From bad60817f3a05f15d3baf3a79e22af7dad13e144 Mon Sep 17 00:00:00 2001 From: tingerrr Date: Fri, 24 Nov 2023 12:53:50 +0100 Subject: [PATCH] Feat: book aware redundancy check --- README.md | 30 ++++++++++++++++++------------ src/core.typ | 17 +++++++++++++---- src/lib.typ | 23 +++++++++++++++-------- 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 0b1de88..5d83ede 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,15 @@ headings is added. Changing the default behavior can be done using the vairous named parameters: ```typst #let hydra( - sel: heading, // the elements to consider - prev-filter: (_, _, _) => true, // check if the last element is eligible - next-filter: (_, _, _) => true, // check if the next element is eligible - display: core.display, // displays the eligible element - paper: "a4", // the paper size to use - page-size: auto, // the smaller page size if set - top-margin: auto, // the top margin is set - loc: none, // a location from which to search + sel: heading, // the elements to consider + prev-filter: (ctx, p, n) => true, // check if the last element is eligible + next-filter: (ctx, p, n) => true, // check if the next element is eligible + display: core.display, // displays the eligible element + is-book: false, // whether the redundancy check should be book aware + paper: "a4", // the paper size to use + page-size: auto, // the smaller page size if set + top-margin: auto, // the top margin is set + loc: none, // a location from which to search ) = { ... } @@ -61,10 +62,15 @@ a complicated selector `(heading, h => h.level in (1, 2, 3))`. This function is matching element in your document. `loc` can be used in contexts where location is already known, this avoids a call to `locate`, -allowing you to inspect the result of `display` directly. `prev-filter` and `next-filter` are used -to check if an element is eligible for being displayed. They receive the `context`, the previous and -next element relative to the given `loc`, the element thast is checked for is not `none`, but the -other may be. +allowing you to inspect the result of `display` directly. + +`prev-filter` and `next-filter` are used to check if an element is eligible for being displayed. +They receive the `context`, the previous and next element relative to the given `loc`, the element +that is checked for is not `none`, but the other may be. These fucntions are executed at most once. + +If `is-book` is set to `true`, it will not display the element if it is visible on the previous +open page. This means for a book with `left` binding, if hydra is used on the right page while the +previous section is visible on the left page, it will display nothing. Of `paper`, `page-size` and `top-margin` exactly one must be given. `paper` and `page-size` are for convenience aand will be used to calculate the `top-margin` for you. Use them as follows: diff --git a/src/core.typ b/src/core.typ index 4664c4d..c0452af 100644 --- a/src/core.typ +++ b/src/core.typ @@ -20,10 +20,19 @@ (prev, next, ctx.loc) } -// check if the next heading is on the curent page -#let is-redundant(ctx, element) = { - (element.location().page() == ctx.loc.page() - and element.location().position().y <= ctx.top-margin) +// check if the next heading is on the current page +#let is-redundant(ctx, prev, next) = { + let is-next-on-top = ( + next.location().page() == ctx.loc.page() + and next.location().position().y <= ctx.top-margin + ) + + let is-prev-visible = ( + ctx.is-book + and calc.odd(ctx.loc.page()) and prev.location().page() == ctx.loc.page() - 1 + ) + + is-next-on-top or is-prev-visible } // display the heading as closely as it occured at the given loc diff --git a/src/lib.typ b/src/lib.typ index 24e7996..9475493 100644 --- a/src/lib.typ +++ b/src/lib.typ @@ -5,10 +5,11 @@ #let hydra( sel: heading, - prev-filter: (_, _, _) => true, - next-filter: (_, _, _) => true, + prev-filter: (ctx, p, n) => true, + next-filter: (ctx, p, n) => true, display: core.display, fallback-next: false, + is-book: false, paper: "a4", page-size: auto, top-margin: auto, @@ -32,19 +33,25 @@ let func = loc => { let ctx = ( + is-book: is-book, top-margin: top-margin, loc: loc, ) - let (last, next, loc) = core.get-adjacent-from(ctx, sel, filter) + let (prev, next, loc) = core.get-adjacent-from(ctx, sel, filter) ctx.loc = loc - let last-eligible = last != none and prev-filter(ctx, last, next) - let next-eligible = next != none and next-filter(ctx, last, next) - let last-redundant = next-eligible and ctx.top-margin != none and core.is-redundant(ctx, next) + let prev-eligible = prev != none and prev-filter(ctx, prev, next) + let next-eligible = next != none and next-filter(ctx, prev, next) + let prev-redundant = ( + prev-eligible + and next-eligible + and ctx.top-margin != none + and core.is-redundant(ctx, prev, next) + ) - if last-eligible and not last-redundant { - display(ctx, last) + if prev-eligible and not prev-redundant { + display(ctx, prev) } else if fallback-next and next-eligible { display(ctx, next) }