Skip to content

Commit b46c985

Browse files
authored
Add use-last parameter (#19)
Closes #13. This allows hydra to alternatively display the last instead of the first candidate on a page, mimicking the behavior of LaTeX.
1 parent 0c6205c commit b46c985

File tree

19 files changed

+93
-18
lines changed

19 files changed

+93
-18
lines changed

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# [unreleased](https://github.com/tingerrr/hydra/releases/tags/)
22
## Added
3+
- `use-last` parameter on `hydra` for a more LaTeX style heading look up, thanks @freundTech!
4+
- `hydra` now has a new `use-last` parameter
5+
- `context` now has a new `use-last` field
6+
- **BREAKING CHANGE** `candidates` now has a new `last` field containiing a suitable match for the last primary candidate on this page
37

48
## Removed
59

Diff for: doc/chapters/3-reference.typ

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Defines the candidates that have been found in a specific context.
4646

4747
```typc
4848
(
49-
primary: (prev: content | none, next: content | none),
49+
primary: (prev: content | none, next: content | none, last: content | none),
5050
ancestor: (prev: content | none, next: content | none),
5151
)
5252
```
@@ -61,6 +61,7 @@ displaying.
6161
next-filter: (context, candidates) => bool,
6262
display: (context, content) => content,
6363
skip-starting: bool,
64+
use-last: bool,
6465
book: bool,
6566
anchor: label | none,
6667
anchor-loc: location,

Diff for: doc/manual.pdf

-2.99 KB
Binary file not shown.

Diff for: src/core.typ

+29-17
Original file line numberDiff line numberDiff line change
@@ -84,43 +84,48 @@
8484
#let get-candidates(ctx, scope-prev: true, scope-next: true) = {
8585
let look-prev = selector(ctx.primary.target).before(ctx.anchor-loc)
8686
let look-next = selector(ctx.primary.target).after(ctx.anchor-loc)
87+
let look-last = look-next
8788

8889
let prev-ancestor = none
8990
let next-ancestor = none
9091

9192
if ctx.ancestors != none {
92-
let prev = query(selector(ctx.ancestors.target).before(ctx.anchor-loc))
93-
let next = query(selector(ctx.ancestors.target).after(ctx.anchor-loc))
93+
let prev-ancestors = query(selector(ctx.ancestors.target).before(ctx.anchor-loc))
94+
let next-ancestors = query(selector(ctx.ancestors.target).after(ctx.anchor-loc))
9495

9596
if ctx.ancestors.filter != none {
96-
prev = prev.filter(x => (ctx.ancestors.filter)(ctx, x))
97-
next = next.filter(x => (ctx.ancestors.filter)(ctx, x))
97+
prev-ancestors = prev-ancestors.filter(x => (ctx.ancestors.filter)(ctx, x))
98+
next-ancestors = next-ancestors.filter(x => (ctx.ancestors.filter)(ctx, x))
9899
}
99100

100-
if scope-prev and prev != () {
101-
prev-ancestor = prev.last()
101+
if scope-prev and prev-ancestors != () {
102+
prev-ancestor = prev-ancestors.last()
102103
look-prev = look-prev.after(prev-ancestor.location())
103104
}
104105

105-
if scope-next and next != () {
106-
next-ancestor = next.first()
106+
if scope-next and next-ancestors != () {
107+
next-ancestor = next-ancestors.first()
107108
look-next = look-next.before(next-ancestor.location())
108109
}
109110
}
110111

111-
let prev = query(look-prev)
112-
let next = query(look-next)
112+
let prev-targets = query(look-prev)
113+
let next-targets = query(look-next)
114+
let last-targets = query(look-last)
113115

114116
if ctx.primary.filter != none {
115-
prev = prev.filter(x => (ctx.primary.filter)(ctx, x))
116-
next = next.filter(x => (ctx.primary.filter)(ctx, x))
117+
prev-targets = prev-targets.filter(x => (ctx.primary.filter)(ctx, x))
118+
next-targets = next-targets.filter(x => (ctx.primary.filter)(ctx, x))
119+
last-targets = last-targets.filter(x => (ctx.primary.filter)(ctx, x))
117120
}
121+
last-targets = last-targets.filter(x => x.location().page() == ctx.anchor-loc.page())
118122

119-
let prev = if prev != () { prev.last() }
120-
let next = if next != () { next.first() }
123+
let prev = if prev-targets != () { prev-targets.last() }
124+
let next = if next-targets != () { next-targets.first() }
125+
let last = if last-targets != () { last-targets.last() }
121126

122127
(
123-
primary: (prev: prev, next: next),
128+
primary: (prev: prev, next: next, last: last),
124129
ancestor: (prev: prev-ancestor, next: next-ancestor),
125130
)
126131
}
@@ -231,11 +236,18 @@
231236
let candidates = get-candidates(ctx)
232237
let prev-eligible = candidates.primary.prev != none and (ctx.prev-filter)(ctx, candidates)
233238
let next-eligible = candidates.primary.next != none and (ctx.next-filter)(ctx, candidates)
239+
let last-eligible = candidates.primary.last != none and (ctx.next-filter)(ctx, candidates)
234240
let active-redundant = is-active-redundant(ctx, candidates)
235241

236-
if prev-eligible and not active-redundant {
242+
if active-redundant and ctx.skip-starting {
243+
return
244+
}
245+
246+
if ctx.use-last and last-eligible {
247+
(ctx.display)(ctx, candidates.primary.last)
248+
} else if prev-eligible and not active-redundant {
237249
(ctx.display)(ctx, candidates.primary.prev)
238-
} else if next-eligible and not ctx.skip-starting {
250+
} else if next-eligible {
239251
(ctx.display)(ctx, candidates.primary.next)
240252
}
241253
}

Diff for: src/lib.typ

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
/// display. If this is `auto`, the default implementaion will be used.
2929
/// - skip-starting (bool): Whether `hydra` should show the current candidate even if it's on top of
3030
/// the current page.
31+
/// - use-last (bool): If hydra should show the name of the first or last candidate on the page.
32+
// Defaults to false.
3133
/// - dir (direction, auto): The reading direction of the document. If this is `auto`, the text
3234
/// direction is used. Be cautious about leaving this option on `auto` if you switch text
3335
/// direction mid-page and use hydra outside of footers or headers.
@@ -47,6 +49,7 @@
4749
next-filter: auto,
4850
display: auto,
4951
skip-starting: true,
52+
use-last: false,
5053
dir: auto,
5154
binding: auto,
5255
book: false,
@@ -57,6 +60,7 @@
5760
util.assert.types("next-filter", next-filter, function, auto)
5861
util.assert.types("display", display, function, auto)
5962
util.assert.types("skip-starting", skip-starting, bool)
63+
util.assert.types("use-last", use-last, bool)
6064
util.assert.enum("dir", dir, ltr, rtl, auto)
6165
util.assert.enum("binding", binding, left, right, auto)
6266
util.assert.types("book", book, bool)
@@ -78,6 +82,7 @@
7882
next-filter: util.auto-or(next-filter, () => default-filter),
7983
display: util.auto-or(display, () => core.display),
8084
skip-starting: skip-starting,
85+
use-last: use-last,
8186
dir: dir,
8287
binding: binding,
8388
book: book,

Diff for: tests/features/use-last/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# added by typst-test

Diff for: tests/features/use-last/basic/ref/1.png

36.4 KB
Loading

Diff for: tests/features/use-last/basic/ref/2.png

36.8 KB
Loading

Diff for: tests/features/use-last/basic/ref/3.png

17.7 KB
Loading

Diff for: tests/features/use-last/basic/ref/4.png

25.8 KB
Loading

Diff for: tests/features/use-last/basic/ref/5.png

36.8 KB
Loading

Diff for: tests/features/use-last/basic/ref/6.png

171 KB
Loading

Diff for: tests/features/use-last/basic/ref/7.png

25 KB
Loading

Diff for: tests/features/use-last/basic/test.typ

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Synopsis:
2+
// - Setting use-last to true makes hydra use show the last candidate on a page instead of the first
3+
4+
#import "/src/lib.typ": hydra
5+
6+
#set page(
7+
paper: "a7",
8+
header: context hydra(use-last: true),
9+
)
10+
#set heading(numbering: "1.1")
11+
#show heading.where(level: 1): it => pagebreak(weak: true) + it
12+
#set par(justify: true)
13+
14+
= Introduction
15+
#lorem(200)
16+
17+
= Content
18+
== First Section
19+
#lorem(50)
20+
== Second Section
21+
#lorem(100)
22+
== Third section
23+
#lorem(100)

Diff for: tests/features/use-last/multiple-ancestors/ref/1.png

26 KB
Loading

Diff for: tests/features/use-last/multiple-ancestors/ref/2.png

37 KB
Loading

Diff for: tests/features/use-last/multiple-ancestors/ref/3.png

32.5 KB
Loading

Diff for: tests/features/use-last/multiple-ancestors/ref/4.png

22.9 KB
Loading

Diff for: tests/features/use-last/multiple-ancestors/test.typ

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Synopsis:
2+
// - When there are multiple ancestors on one page hydra should still show the last heading
3+
4+
#import "/src/lib.typ": hydra
5+
6+
#set page(
7+
paper: "a7",
8+
header: context hydra(2, use-last: true),
9+
)
10+
#set heading(numbering: "1.1")
11+
#set par(justify: true)
12+
13+
14+
= Introduction
15+
== First Section
16+
#lorem(50)
17+
== Second Section
18+
#lorem(100)
19+
== Third section
20+
#lorem(50)
21+
22+
= Other
23+
#lorem(10)
24+
== test
25+
#lorem(10)
26+
= More
27+
#lorem(5)
28+
== more tests
29+
#lorem(10)

0 commit comments

Comments
 (0)