From 6dcb65e3a30c59f4a99cd1a985075b1d0adc385f Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 11 Apr 2023 21:41:27 +0200 Subject: [PATCH] Improve documentation --- docs/src/reference/scripting.md | 17 +++--- docs/src/reference/types.md | 14 +++-- library/src/meta/context.rs | 92 +++++++++++++++++---------------- library/src/meta/document.rs | 26 +++++++--- tests/typ/meta/document.typ | 4 ++ 5 files changed, 90 insertions(+), 63 deletions(-) diff --git a/docs/src/reference/scripting.md b/docs/src/reference/scripting.md index 7d40f256a..d125bf5b5 100644 --- a/docs/src/reference/scripting.md +++ b/docs/src/reference/scripting.md @@ -81,7 +81,8 @@ It explains #name. Sum is #add(2, 3). ``` -Let bindings can be used to destructure arrays and dictionaries. +Let bindings can also be used to destructure [arrays]($type/array) and +[dictionaries]($type/dictionary). ```example #let (x, y) = (1, 2) @@ -92,10 +93,11 @@ The first element is #a. The last element is #b. #let books = ( - "Shakespeare": "Hamlet", - "Homer": "The Odyssey", - "Austen": "Persuasion", + Shakespeare: "Hamlet", + Homer: "The Odyssey", + Austen: "Persuasion", ) + #let (Austen,) = books Austen wrote #Austen. @@ -104,14 +106,13 @@ Homer wrote #h. #let (Homer, ..other) = books #for (author, title) in other [ - #author wrote #title, + #author wrote #title. ] ``` -Note that the underscore `_` is the only identifier that can -be used multiple times in the same assignment. +You can use the underscore to discard elements in a destructuring pattern: -``` +```example #let (_, y, _) = (1, 2, 3) The y coordinate is #y. ``` diff --git a/docs/src/reference/types.md b/docs/src/reference/types.md index 816cc3911..184da1377 100644 --- a/docs/src/reference/types.md +++ b/docs/src/reference/types.md @@ -526,11 +526,6 @@ Fails with an error if the index is out of bounds. The index at which to retrieve the item. - returns: any -### enumerate() -Returns an array of the values along with their indices. - -- returns: array - ### push() Add a value to the end of the array. @@ -616,6 +611,15 @@ transformed with the given function. The function to apply to each item. - returns: array +### enumerate() +Returns a new array with the values alongside their indices. + +The returned array consists of `(index, value)` pairs in the form of length-2 +arrays. These can be [destructured]($scripting/#bindings) with a let binding or +for loop. + +- returns: array + ### fold() Folds all items into a single value using an accumulator function. diff --git a/library/src/meta/context.rs b/library/src/meta/context.rs index 3902f47aa..710347f4f 100644 --- a/library/src/meta/context.rs +++ b/library/src/meta/context.rs @@ -89,6 +89,16 @@ impl Show for LocateElem { /// In the future, the provided styles might also be directly accessed to look /// up styles defined by [set rules]($styling/#set-rules). /// +/// ```example +/// #let thing(body) = style(styles => { +/// let size = measure(body, styles) +/// [Width of "#body" is #size.width] +/// }) +/// +/// #thing[Hey] \ +/// #thing[Welcome] +/// ``` +/// /// Display: Style /// Category: meta /// Returns: content @@ -122,67 +132,61 @@ impl Show for StyleElem { } } -/// Provides access to the current outer container's (or page's, if none) size (width and height). +/// Provides access to the current outer container's (or page's, if none) size +/// (width and height). /// -/// The given function must accept a single parameter, `size`, which is a dictionary with keys -/// `width` and `height`, both having the type [`length`]($type/length). +/// The given function must accept a single parameter, `size`, which is a +/// dictionary with keys `width` and `height`, both of type +/// [`length`]($type/length). /// -/// That is, if this `layout` call is done inside (for example) a box of size 800pt (width) -/// by 400pt (height), then the specified function will be given the parameter -/// `(width: 800pt, height: 400pt)`. + +/// ```example +/// #let text = lorem(30) +/// #layout(size => style(styles => [ +/// #let (height,) = measure( +/// block(width: size.width, text), +/// styles, +/// ) +/// This text is #height high with +/// the current page width: \ +/// #text +/// ])) +/// ``` /// -/// If, however, this `layout` call is placed directly on the page, not inside any container, -/// then the function will be given `(width: page_width, height: page_height)`, where `page_width` -/// and `page_height` correspond to the current page's respective dimensions, minus its margins. +/// If the `layout` call is placed inside of a box width a width of `{800pt}` +/// and a height of `{400pt}`, then the specified function will be given the +/// parameter `{(width: 800pt, height: 400pt)}`. If it placed directly into the +/// page it receives the page's dimensions minus its margins. This is mostly +/// useful in combination with [measurement]($func/measure). /// -/// This is useful, for example, to convert a [`ratio`]($type/ratio) value (such as `5%`, `100%` -/// etc.), which are usually based upon the outer container's dimensions (precisely what this -/// function gives), to a fixed length (in `pt`). -/// -/// This is also useful if you're trying to make content fit a certain box, and doing certain -/// arithmetic using `pt` (for example, comparing different lengths) is required. -/// -/// Please note: This function may provide a width or height of `infpt` if one of the page -/// dimensions is `auto`, under certain circumstances. This should not normally occur for -/// usual page sizes, however. +/// You can also use this function to resolve [`ratio`]($type/ratio) to fixed +/// lengths. This might come in handy if you're building your own layout +/// abstractions. /// /// ```example -/// layout(size => { -/// // work with the width and height of the container we're in -/// // using size.width and size.height +/// #layout(size => { +/// let half = 50% * size.width +/// [Half a page is #half wide.] /// }) -/// -/// layout(size => { -/// // convert 49% (of page width) to 'pt' -/// // note that "ratio" values are always relative to a certain, possibly arbitrary length, -/// // but it's usually the current container's width or height (e.g., for table columns, -/// // 15% would be relative to the width, but, for rows, it would be relative to the height). -/// let percentage_of_width = (49% / 1%) * 0.01 * size.width -/// // ... use the converted value ... -/// }) -/// -/// // The following two boxes are equivalent, and will have rectangles sized 200pt and 40pt: -/// -/// #box(width: 200pt, height: 40pt, { -/// rect(width: 100%, height: 100%) -/// }) -/// -/// #box(width: 200pt, height: 40pt, layout(size => { -/// rect(width: size.width, height: size.height) -/// })) /// ``` /// +/// Note that this function will provide an infinite width or height if one of +/// the page width or height is `auto`, respectively. +/// /// Display: Layout /// Category: meta /// Returns: content #[func] pub fn layout( - /// A function to call with the outer container's size. Its return value is displayed - /// in the document. + /// A function to call with the outer container's size. Its return value is + /// displayed in the document. + /// + /// The container's size is given as a [dictionary]($type/dictionary) with + /// the keys `width` and `height`. /// /// This function is called once for each time the content returned by /// `layout` appears in the document. That makes it possible to generate - /// content that depends on the size of the container it is inside. + /// content that depends on the size of the container it is inside of. func: Func, ) -> Value { LayoutElem::new(func).pack().into() diff --git a/library/src/meta/document.rs b/library/src/meta/document.rs index 99e5c6b60..bb42faaf5 100644 --- a/library/src/meta/document.rs +++ b/library/src/meta/document.rs @@ -3,16 +3,24 @@ use crate::prelude::*; /// The root element of a document and its metadata. /// -/// All documents are automatically wrapped in a `document` element. The main -/// use of this element is to use it in `set` rules to specify document -/// metadata. +/// All documents are automatically wrapped in a `document` element. You cannot +/// create a document element yourself. This function is only used with +/// [set rules]($styling/#set-rules) to specify document metadata. Such a set +/// rule must appear before any of the document's contents. /// -/// The metadata set with this function is not rendered within the document. -/// Instead, it is embedded in the compiled PDF file. +/// ```example +/// #set document(title: "Hello") +/// +/// This has no visible output, but +/// embeds metadata into the PDF! +/// ``` +/// +/// Note that metadata set with this function is not rendered within the +/// document. Instead, it is embedded in the compiled PDF file. /// /// Display: Document /// Category: meta -#[element(LayoutRoot)] +#[element(Construct, LayoutRoot)] pub struct DocumentElem { /// The document's title. This is often rendered as the title of the /// PDF viewer window. @@ -27,6 +35,12 @@ pub struct DocumentElem { pub children: Vec, } +impl Construct for DocumentElem { + fn construct(_: &mut Vm, args: &mut Args) -> SourceResult { + bail!(args.span, "can only be used in set rules") + } +} + impl LayoutRoot for DocumentElem { /// Layout the document into a sequence of frames, one per page. fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult { diff --git a/tests/typ/meta/document.typ b/tests/typ/meta/document.typ index bc9d4908a..f4676f3cc 100644 --- a/tests/typ/meta/document.typ +++ b/tests/typ/meta/document.typ @@ -22,6 +22,10 @@ Hello // Error: 2-30 document set rules must appear before any content #set document(title: "Hello") +--- +// Error: 10-12 can only be used in set rules +#document() + --- #box[ // Error: 4-32 document set rules are not allowed inside of containers