pub struct Counter(/* private fields */);
Expand description
Counts through pages, elements, and more.
With the counter function, you can access and modify counters for pages, headings, figures, and more. Moreover, you can define custom counters for other things you want to count.
Since counters change throughout the course of the document, their current value is contextual. It is recommended to read the chapter on [context] before continuing here.
§Accessing a counter { #accessing }
To access the raw value of a counter, we can use the get
function. This function returns an array: Counters can have multiple
levels (in the case of headings for sections, subsections, and so on), and
each item in the array corresponds to one level.
#set heading(numbering: "1.")
= Introduction
Raw value of heading counter is
#context counter(heading).get()
§Displaying a counter { #displaying }
Often, we want to display the value of a counter in a more human-readable
way. To do that, we can call the display
function on
the counter. This function retrieves the current counter value and formats
it either with a provided or with an automatically inferred [numbering].
#set heading(numbering: "1.")
= Introduction
Some text here.
= Background
The current value is: #context {
counter(heading).display()
}
Or in roman numerals: #context {
counter(heading).display("I")
}
§Modifying a counter { #modifying }
To modify a counter, you can use the step
and update
methods:
-
The
step
method increases the value of the counter by one. Because counters can have multiple levels , it optionally takes alevel
argument. If given, the counter steps at the given depth. -
The
update
method allows you to arbitrarily modify the counter. In its basic form, you give it an integer (or an array for multiple levels). For more flexibility, you can instead also give it a function that receives the current value and returns a new value.
The heading counter is stepped before the heading is displayed, so
Analysis
gets the number seven even though the counter is at six after the
second update.
#set heading(numbering: "1.")
= Introduction
#counter(heading).step()
= Background
#counter(heading).update(3)
#counter(heading).update(n => n * 2)
= Analysis
Let's skip 7.1.
#counter(heading).step(level: 2)
== Analysis
Still at #context {
counter(heading).display()
}
§Page counter
The page counter is special. It is automatically stepped at each pagebreak. But like other counters, you can also step it manually. For example, you could have Roman page numbers for your preface, then switch to Arabic page numbers for your main content and reset the page counter to one.
>>> #set page(
>>> height: 100pt,
>>> margin: (bottom: 24pt, rest: 16pt),
>>> )
#set page(numbering: "(i)")
= Preface
The preface is numbered with
roman numerals.
#set page(numbering: "1 / 1")
#counter(page).update(1)
= Main text
Here, the counter is reset to one.
We also display both the current
page and total number of pages in
Arabic numbers.
§Custom counters
To define your own counter, call the counter
function with a string as a
key. This key identifies the counter globally.
#let mine = counter("mycounter")
#context mine.display() \
#mine.step()
#context mine.display() \
#mine.update(c => c * 3)
#context mine.display()
§How to step
When you define and use a custom counter, in general, you should first step the counter and then display it. This way, the stepping behaviour of a counter can depend on the element it is stepped for. If you were writing a counter for, let’s say, theorems, your theorem’s definition would thus first include the counter step and only then display the counter and the theorem’s contents.
#let c = counter("theorem")
#let theorem(it) = block[
#c.step()
*Theorem #context c.display():*
#it
]
#theorem[$1 = 1$]
#theorem[$2 < 3$]
The rationale behind this is best explained on the example of the heading
counter: An update to the heading counter depends on the heading’s level. By
stepping directly before the heading, we can correctly step from 1
to
1.1
when encountering a level 2 heading. If we were to step after the
heading, we wouldn’t know what to step to.
Because counters should always be stepped before the elements they count, they always start at zero. This way, they are at one for the first display (which happens after the first step).
§Time travel
Counters can travel through time! You can find out the final value of the counter before it is reached and even determine what the value was at any particular location in the document.
#let mine = counter("mycounter")
= Values
#context [
Value here: #mine.get() \
At intro: #mine.at(<intro>) \
Final value: #mine.final()
]
#mine.update(n => n + 3)
= Introduction <intro>
#lorem(10)
#mine.step()
#mine.step()
§Other kinds of state { #other-state }
The counter
type is closely related to [state] type. Read its
documentation for more details on state management in Typst and why it
doesn’t just use normal variables for counters.
Implementations§
Source§impl Counter
impl Counter
Sourcepub fn new(key: CounterKey) -> Counter
pub fn new(key: CounterKey) -> Counter
Create a new counter identified by a key.
Sourcepub fn both(
&self,
engine: &mut Engine<'_>,
location: Location,
) -> SourceResult<CounterState>
pub fn both( &self, engine: &mut Engine<'_>, location: Location, ) -> SourceResult<CounterState>
Gets the current and final value of the state combined in one state.
Sourcepub fn at_loc(
&self,
engine: &mut Engine<'_>,
location: Location,
) -> SourceResult<CounterState>
pub fn at_loc( &self, engine: &mut Engine<'_>, location: Location, ) -> SourceResult<CounterState>
Gets the value of the counter at the given location. Always returns an array of integers, even if the counter has just one number.
Sourcepub fn display_at_loc(
&self,
engine: &mut Engine<'_>,
loc: Location,
styles: StyleChain<'_>,
numbering: &Numbering,
) -> SourceResult<Content>
pub fn display_at_loc( &self, engine: &mut Engine<'_>, loc: Location, styles: StyleChain<'_>, numbering: &Numbering, ) -> SourceResult<Content>
Displays the value of the counter at the given location.
Sourcepub fn select_any() -> Selector
pub fn select_any() -> Selector
Selects all state updates.
Source§impl Counter
impl Counter
Sourcepub fn construct(key: CounterKey) -> Counter
pub fn construct(key: CounterKey) -> Counter
Create a new counter identified by a key.
Sourcepub fn get(
&self,
engine: &mut Engine<'_>,
context: Tracked<'_, Context<'_>>,
span: Span,
) -> SourceResult<CounterState>
pub fn get( &self, engine: &mut Engine<'_>, context: Tracked<'_, Context<'_>>, span: Span, ) -> SourceResult<CounterState>
Retrieves the value of the counter at the current location. Always returns an array of integers, even if the counter has just one number.
This is equivalent to {counter.at(here())}
.
Sourcepub fn display(
self,
engine: &mut Engine<'_>,
context: Tracked<'_, Context<'_>>,
span: Span,
numbering: Smart<Numbering>,
both: bool,
) -> SourceResult<Value>
pub fn display( self, engine: &mut Engine<'_>, context: Tracked<'_, Context<'_>>, span: Span, numbering: Smart<Numbering>, both: bool, ) -> SourceResult<Value>
Displays the current value of the counter with a numbering and returns the formatted output.
Sourcepub fn at(
&self,
engine: &mut Engine<'_>,
context: Tracked<'_, Context<'_>>,
span: Span,
selector: LocatableSelector,
) -> SourceResult<CounterState>
pub fn at( &self, engine: &mut Engine<'_>, context: Tracked<'_, Context<'_>>, span: Span, selector: LocatableSelector, ) -> SourceResult<CounterState>
Sourcepub fn final_(
&self,
engine: &mut Engine<'_>,
context: Tracked<'_, Context<'_>>,
span: Span,
) -> SourceResult<CounterState>
pub fn final_( &self, engine: &mut Engine<'_>, context: Tracked<'_, Context<'_>>, span: Span, ) -> SourceResult<CounterState>
Retrieves the value of the counter at the end of the document. Always returns an array of integers, even if the counter has just one number.
Sourcepub fn step(self, span: Span, level: NonZeroUsize) -> Content
pub fn step(self, span: Span, level: NonZeroUsize) -> Content
Increases the value of the counter by one.
The update will be in effect at the position where the returned content
is inserted into the document. If you don’t put the output into the
document, nothing happens! This would be the case, for example, if you
write {let _ = counter(page).step()}
. Counter updates are always
applied in layout order and in that case, Typst wouldn’t know when to
step the counter.
Sourcepub fn update(self, span: Span, update: CounterUpdate) -> Content
pub fn update(self, span: Span, update: CounterUpdate) -> Content
Updates the value of the counter.
Just like with step
, the update only occurs if you put the resulting
content into the document.
Trait Implementations§
Source§impl FromValue for Counter
impl FromValue for Counter
Source§fn from_value(value: Value) -> HintedStrResult<Self>
fn from_value(value: Value) -> HintedStrResult<Self>
Self
.Source§impl NativeScope for Counter
impl NativeScope for Counter
Source§fn constructor() -> Option<&'static NativeFuncData>
fn constructor() -> Option<&'static NativeFuncData>
Source§impl NativeType for Counter
impl NativeType for Counter
impl StructuralPartialEq for Counter
Auto Trait Implementations§
impl Freeze for Counter
impl !RefUnwindSafe for Counter
impl Send for Counter
impl Sync for Counter
impl Unpin for Counter
impl !UnwindSafe for Counter
Blanket Implementations§
Source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
Source§fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
Source§fn adapt_into(self) -> D
fn adapt_into(self) -> D
Source§impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Source§fn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Source§impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Source§fn arrays_into(self) -> C
fn arrays_into(self) -> C
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Source§type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T> CheckedAs for T
impl<T> CheckedAs for T
Source§fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
Source§impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
Source§fn checked_cast_from(src: Src) -> Option<Dst>
fn checked_cast_from(src: Src) -> Option<Dst>
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Source§fn components_from(colors: C) -> T
fn components_from(colors: C) -> T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Source§fn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle
.Source§impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Source§fn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other
into Self
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T> FromValue<Spanned<Value>> for Twhere
T: FromValue,
impl<T> FromValue<Spanned<Value>> for Twhere
T: FromValue,
Source§fn from_value(value: Spanned<Value>) -> Result<T, HintedString>
fn from_value(value: Spanned<Value>) -> Result<T, HintedString>
Self
.Source§impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Source§fn into_angle(self) -> U
fn into_angle(self) -> U
T
.Source§impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Source§type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Source§fn into_color(self) -> U
fn into_color(self) -> U
Source§impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Source§fn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoResult for Twhere
T: IntoValue,
impl<T> IntoResult for Twhere
T: IntoValue,
Source§fn into_result(self, _: Span) -> Result<Value, EcoVec<SourceDiagnostic>>
fn into_result(self, _: Span) -> Result<Value, EcoVec<SourceDiagnostic>>
Source§impl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Source§fn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self
into T
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T> OverflowingAs for T
impl<T> OverflowingAs for T
Source§fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
Source§impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
Source§fn overflowing_cast_from(src: Src) -> (Dst, bool)
fn overflowing_cast_from(src: Src) -> (Dst, bool)
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> SaturatingAs for T
impl<T> SaturatingAs for T
Source§fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
Source§impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
Source§fn saturating_cast_from(src: Src) -> Dst
fn saturating_cast_from(src: Src) -> Dst
Source§impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Source§type Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors
fails to cast.Source§fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Source§impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Source§fn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds
error is returned which contains
the unclamped color. Read more