mirror of
https://github.com/typst/typst
synced 2025-05-22 04:55:29 +08:00
Revised context.md according to github discussion
This commit is contained in:
parent
c472ee382e
commit
a9a8426d2d
@ -28,25 +28,25 @@ outline, for instance, also provide the proper context to resolve counters.
|
|||||||
## Behavior of the context keyword
|
## Behavior of the context keyword
|
||||||
Style properties frequently change within a document, for example by applying set
|
Style properties frequently change within a document, for example by applying set
|
||||||
rules. To retrieve such poperties in a consistent way, one must first specify
|
rules. To retrieve such poperties in a consistent way, one must first specify
|
||||||
the context where the query is to be executed. This is the purpose of the
|
the precise context where the property should be retrieved. This can be achieved
|
||||||
`context` keyword. Once the context has been fixed, the property information
|
with the `context` keyword. Once the context has been fixed, the property
|
||||||
is available through a simple field access syntax. For example, `text.lang`
|
information is available through standard field access syntax. For example,
|
||||||
asks for the current language setting. In its simplest form, the `context`
|
`text.lang` asks for the current language setting. In its simplest form, the
|
||||||
keyword refers to "right here":
|
`context` keyword refers to "right here":
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#set text(lang: "de")
|
#set text(lang: "de")
|
||||||
// query the language setting "here"
|
// read the language setting "here"
|
||||||
#context text.lang
|
#context text.lang
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that calling `#text.lang` directly would be an error, because the request
|
Note that any attempt to access `#text.lang` directly, i.e. outside of a context,
|
||||||
cannot be answered without knowledge of the context. The field names supported
|
will cause the compiler to issue an error message. The field names supported
|
||||||
by a given element function always correspond to the named parameters documented
|
by a given element function always correspond to the named parameters documented
|
||||||
on each element's page.
|
on each element's page.
|
||||||
|
|
||||||
Moreover, some functions, such as [`to-absolute`]($length.to-absolute)
|
Moreover, some functions, such as [`to-absolute`]($length.to-absolute)
|
||||||
and [`counter.display`]($counter.display) are only applicable in a context,
|
and [`counter.display`]($counter.display), are only applicable in a context,
|
||||||
because their results depend on the current settings of style properties.
|
because their results depend on the current settings of style properties.
|
||||||
When another function `foo()` calls a context-dependent function, it becomes
|
When another function `foo()` calls a context-dependent function, it becomes
|
||||||
itself context-dependent:
|
itself context-dependent:
|
||||||
@ -54,12 +54,14 @@ itself context-dependent:
|
|||||||
```example
|
```example
|
||||||
#let foo() = 1em.to-absolute()
|
#let foo() = 1em.to-absolute()
|
||||||
#context {
|
#context {
|
||||||
// foo() cannot be called outside of a context
|
// foo() cannot be called
|
||||||
|
// outside of a context
|
||||||
foo() == text.size
|
foo() == text.size
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When a property is changed, the response to the query changes accordingly:
|
When a property is changed, the response to the property access
|
||||||
|
changes accordingly:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#set text(lang: "en")
|
#set text(lang: "en")
|
||||||
@ -69,61 +71,68 @@ When a property is changed, the response to the query changes accordingly:
|
|||||||
#context text.lang
|
#context text.lang
|
||||||
```
|
```
|
||||||
|
|
||||||
The output of a `#context ...` call is static in the form of opaque
|
As you see, the result of a `#context ...` expression can
|
||||||
[`content`]. Write access to context output is prohibited, as it would
|
be inserted into the document as `content`. Context blocks can
|
||||||
often result in invalid code: If the context changes between read and
|
contain arbitrary code beyond the field access. However,
|
||||||
write, overwriting a property would cause an inconsistent system state.
|
and this is often surprisingly for newcomers, context-dependent
|
||||||
In fact, context-dependent property fields are immutable constants even
|
property fields remain _constant_ throughout the context's scope.
|
||||||
within the context itself:
|
This has two important consequences: First, direct property
|
||||||
|
assignments like `text.lang = "de"` are _not_ allowed –
|
||||||
|
always use `set` or `show` rules. Second, changes to a
|
||||||
|
property value within a context (e.g. by a `set` rule) are not
|
||||||
|
observable by field access within that same context:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#set text(lang: "en")
|
#set text(lang: "en")
|
||||||
#context [
|
#context [
|
||||||
call 1: #text.lang \
|
Read 1: #text.lang
|
||||||
|
|
||||||
#set text(lang: "fr")
|
#set text(lang: "fr")
|
||||||
call 2: #text.lang
|
Read 2: #text.lang
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Both calls have the same output 'en', because `text.lang` is assigned
|
Both reads have the same output `"en"`, because `text.lang` is assigned
|
||||||
upon entry in the context and remains constant until the end of its scope
|
upon entry in the context and remains constant until the end of its scope
|
||||||
(the closing `]`). It does not "see" the `#set text(lang: "fr")` before
|
(the closing `]`). Thus, the `text.lang` field cannot "see" the effect
|
||||||
call 2. Compare this to the previous example: there we got two different
|
of `#set text(lang: "fr")`, although Read 2 occurs afterwards. Compare
|
||||||
results because we created two different contexts.
|
this to the previous example: There we got two different results because
|
||||||
|
we created two different contexts.
|
||||||
|
|
||||||
However, immutability only applies to the property fields themselves.
|
However, immutability only applies to the property fields themselves.
|
||||||
Content creation instructions within a context _do_ see the effect of
|
The appearance of content within a context _can_ be changed in the
|
||||||
the set rule. Consider the same example with font size:
|
usual manner. e.g. by set rules. Consider the same example with font size:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#set text(size: 50pt)
|
#set text(size: 40pt)
|
||||||
#context [
|
#context [
|
||||||
call 1: #text.size \
|
Read 1: #text.size \
|
||||||
|
|
||||||
#set text(size: 25pt)
|
#set text(size: 25pt)
|
||||||
call 2: #text.size
|
Read 2: #text.size
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Call 2 still outputs '50pt', because `text.size` is a constant.
|
Read 2 still outputs `40pt`, because `text.size` is a constant.
|
||||||
However, this output is printed in '25pt' font, as specified by the set
|
However, this output is printed in 25pt font, as specified by the set
|
||||||
rule before the call. This illustrates the importance of picking the
|
rule before the read. This illustrates the importance of picking the
|
||||||
right insertion point for a context to get access to precisely the right
|
right insertion point for a context to get access to precisely the right
|
||||||
styles. If you need access to updated property fields after a set rule,
|
styles. If you need access to updated property fields after a set rule,
|
||||||
you can use nested contexts:
|
you can use _nested contexts_:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#set text(lang: "en")
|
#set text(lang: "en")
|
||||||
#context [
|
#context [
|
||||||
call 1: #text.lang \
|
Read 1: #text.lang \
|
||||||
|
|
||||||
#set text(lang: "fr")
|
#set text(lang: "fr")
|
||||||
call 2: #context text.lang
|
Read 2: #context text.lang
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
All of the above applies to `show` rules analogously, for example:
|
All of the above applies to `show` rules analogously. To demonstrate this,
|
||||||
|
we define a function `template` which is activated by an "everything" set
|
||||||
|
rule in a context:
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#let template(body) = {
|
#let template(body) = {
|
||||||
@ -131,73 +140,85 @@ All of the above applies to `show` rules analogously, for example:
|
|||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
|
||||||
#set text(size: 50pt)
|
#set text(size: 40pt)
|
||||||
#context [
|
#context [
|
||||||
call 1: #text.size \
|
Read 1: #text.size
|
||||||
|
|
||||||
#show: template
|
#show: template
|
||||||
call 2: #text.size \
|
Read 2: #text.size \
|
||||||
call 3: #context text.size
|
Read 3: #context text.size
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
Reads 1 and 2 print the original text size upon entry in the first
|
||||||
|
context (since `text.size` remains constant there), but Read 3 is
|
||||||
|
located in a nested context and reflects the new font size set by
|
||||||
|
the `show` rule via the `template` function.
|
||||||
|
|
||||||
## Controlling content creation within a context
|
## Using context-dependent property fields to control content appearance
|
||||||
|
An important purpose of reading the current value of properties is,
|
||||||
The main purpose of retrieving the current values of properties is,
|
of course, to use this information in the calculation of derived
|
||||||
of course, to use them in the calculation of derived properties,
|
properties, instead of setting those properties manually. For example,
|
||||||
instead of setting those properties manually. For example, you can
|
you can double the font size like this:
|
||||||
double the font size like this:
|
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#context {
|
#context [
|
||||||
// the context allows you to
|
// the context allows you to
|
||||||
// retrieve the current text.size
|
// retrieve the current text.size
|
||||||
set text(size: text.size * 200%)
|
#set text(size: text.size * 200%)
|
||||||
[large text \ ]
|
Large text \
|
||||||
}
|
]
|
||||||
original size
|
Original size
|
||||||
```
|
```
|
||||||
|
|
||||||
Since set rules are only active until the end of the enclosing scope,
|
Since set rules are only active until the end of the enclosing scope,
|
||||||
'original size' is printed with the original font size.
|
"Original size" is printed with the original font size.
|
||||||
The above example is equivalent to
|
The above example is equivalent to
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#{
|
#[
|
||||||
set text(size: 2em)
|
#set text(size: 2em)
|
||||||
[large text \ ]
|
Large text \
|
||||||
}
|
]
|
||||||
original size
|
Original size
|
||||||
```
|
```
|
||||||
|
|
||||||
but convenient alternatives like this do not exist for most properties.
|
but convenient alternatives like this are unavailable for most properties.
|
||||||
This makes contexts a powerful and versatile concept. For example,
|
This makes contexts a powerful and versatile concept. For example,
|
||||||
to double the spacing between the lines of an equation block, you can
|
you can use a similar resizing technique to increase the spacing
|
||||||
use the same resizing technique in a show rule. In this case, explicitly
|
between the lines of a specific equation block (or any other content):
|
||||||
adding the `context` keyword is not necessary, because a show rule
|
|
||||||
establishes a context automatically:
|
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#let spaced-eq(spacing: 100%, body) = {
|
#let spaced(spacing: 100%, body) = context {
|
||||||
show math.equation.where(block: true): it => {
|
// access current par.leading in a context
|
||||||
// access current par.leading in the
|
set par(leading: par.leading * spacing)
|
||||||
// context of the show rule
|
|
||||||
set par(leading: par.leading * spacing)
|
|
||||||
it
|
|
||||||
}
|
|
||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
|
||||||
normal spacing:
|
Normal spacing:
|
||||||
$
|
$ x \ x $
|
||||||
x \
|
Doubled spacing:
|
||||||
x
|
#spaced(spacing: 200%)[$ z \ z $]
|
||||||
$
|
```
|
||||||
doubled spacing:
|
|
||||||
#spaced-eq(spacing: 200%)[$
|
The advantage of this technique is that the user does not have to know the
|
||||||
z \
|
original spacing in order to double it. To double the spacing of all
|
||||||
z
|
equations, you can put the same calculations in a `show` rule. Note that
|
||||||
$]
|
it is not necessary to add the `context` keyword on the right-hand side
|
||||||
|
of a `show` rule, because show rules establish a context automatically:
|
||||||
|
|
||||||
|
```example
|
||||||
|
Normal spacing:
|
||||||
|
$ x \ x $
|
||||||
|
|
||||||
|
#show math.equation.where(block: true): it => {
|
||||||
|
// access current par.leading in a context,
|
||||||
|
// established automatically by the show rule
|
||||||
|
set par(leading: par.leading * 200%)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
Doubled spacing:
|
||||||
|
$ z \ z $
|
||||||
```
|
```
|
||||||
|
|
||||||
## Location context
|
## Location context
|
||||||
@ -262,9 +283,9 @@ demonstrates this:
|
|||||||
|
|
||||||
The rule that context-dependent variables and functions remain constant
|
The rule that context-dependent variables and functions remain constant
|
||||||
within a given `context` also applies to location context. The function
|
within a given `context` also applies to location context. The function
|
||||||
`counter.display()` is an example for this behavior. Below, call A will
|
`counter.display()` is an example for this behavior. Below, read A will
|
||||||
access the counter's value upon _entry_ into the context, i.e. '1' - it
|
access the counter's value upon _entry_ into the context, i.e. `1` - it
|
||||||
cannot see the effect of `{c.update(2)}`. In contrast, call B accesses
|
cannot see the effect of `{c.update(2)}`. In contrast, read B accesses
|
||||||
the counter in a nested context and will thus see the updated value.
|
the counter in a nested context and will thus see the updated value.
|
||||||
|
|
||||||
```example
|
```example
|
||||||
@ -272,8 +293,8 @@ the counter in a nested context and will thus see the updated value.
|
|||||||
#c.update(1)
|
#c.update(1)
|
||||||
#context [
|
#context [
|
||||||
#c.update(2)
|
#c.update(2)
|
||||||
call A: #c.display() \
|
Read A: #c.display() \
|
||||||
call B: #context c.display()
|
Read B: #context c.display()
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user