In typst
I can use column
to split content/text into columns on the page, is there a way for me to control the spreading/splitting of content into different boxes in a more granular fashion?
For example, say I have a rudimentary dictionary that looks like this
Items:
-
Section: Foo
Details:
ABCD: EFGH
HIJK: KLMN
-
Section: Bar
Details:
OPQR: STUV
WXYZ: 1234
-
Section: Tres
Details:
Random: Thought
Test: Value
And I am calling it using code that looks like this:-
#let content = yaml("dictionary.yaml") // Get the content file
#let test_item(test_item) = {
[
*#underline[#test_item.Section]* \
#for (hit, details) in test_item.Details [
*#hit* : #details \
] #v(-0.25em) // Add some space for the next section
]
}
#box(height: 75pt,
columns(2, gutter: 11pt)[
#set par(justify: true)
#for entry in content.Items {
test_item(entry)
}
]
)
Is there a way I can direct content to specific boxes in the column. What function/utility of script should I be reading into?
Right now the compiler decides on its own - but is there a way I can control it so I can tell the compiler to send a item to a very specific column.
This does not have to be done with `columns` if there is some other way to script what specific section of the page content ends up in.
My goal was to create a dictionary with the following structure:
information.yaml
Items:
-
Section: Foo
Details:
ABCD: EFGH
HIJK: KLMN
-
Section: Bar
Details:
OPQR: STUV
WXYZ: 1234
-
Section: Tres
Details:
Random: Thought
Test: Value
I hoped to generate a document that resembles this:-
(Note: I created this manually, but it's not scalable or easy to automate.)
Following up on the suggestion that grid
might be better suited for this than column
I tried the following code:
#let content = yaml("information.yaml") // Load the content file
#let test_item(test_item) = {
[
*#underline[#test_item.Section]* \\
#for (hit, details) in test_item.Details [
*#hit* : #details \\
] #v(-0.25em) // Add space before the next section
]
}
#grid(
columns: 2,
column-gutter: 1em,
let column_value = 1,
for entry in content.Items {
grid.cell(
x: column_value,
skills_entry(entry)
)
grid.cell(x: column_value, test_item(entry))
if (column_value == 1) {
column_value = 0
} else if (column_value == 0) {
column_value = 1
}
}
)
My intention with the if and else if syntax was to alternate between the first and second columns, cycling between 0 and 1. However, this approach didn't work, and all dictionary items ended up in the first column.
The code produced this document:-
As I'm only somewhat familiar with variable scoping, I tried using printf-style debugging to see if column_value was being updated:
#let tri(c, val) = {
polygon.regular(
fill: c,
size: 5mm,
vertices: 3,
)
[The value is #val]
}
#grid(
columns: 2,
stroke: blue,
inset: 1mm,
let col_val = 1,
for i in range(4) {
grid.cell(x: col_val, tri(green, col_val))
if (col_val == 1) {
col_val = 0
} else if (col_val == 0) {
col_val = 1
}
}
)
This produced
The outcome has me completely confused: the value of col_val is updated, but it doesn't affect the actual grid.cell
- is this where I should start reading into state.
I suspect I might be going about this the wrong way and there is probably a more elegant and less hacky solution - if so could someone help me out?
Turns out I can just do this
#let content = yaml("information.yaml") // Load the content file
#let test_item(test_item) = [
*#underline[#test_item.Section]* \
#for (hit, details) in test_item.Details [
*#hit*: #details \
]
#v(-0.25em) // Add space before the next section
]
#grid(
columns: (1fr, 1fr),
column-gutter: 1em,
row-gutter: 1em,
..content.Items.map(entry => test_item(entry))
)
The crucial part was ..{<dictionary>}.map(item => function)
Which makes
i.e. automatically distributing the items across the columns one at a time.