Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[add] show rule on raw for examples #35

Merged
merged 9 commits into from
Nov 21, 2024
6 changes: 3 additions & 3 deletions docs/tidy-guide.typ
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ We can now parse the module and pass the module `wiggly` through the `scope` par
read("wiggly.typ"),
name: "wiggly",
scope: (wiggly: wiggly),
preamble: "import wiggly: *;"
preamble: "#import wiggly: *\n"
)
```
Expand All @@ -152,7 +152,7 @@ In the output, the preview of the code examples is shown next to it.
read("/examples/wiggly.typ"),
name: "wiggly",
scope: (wiggly: wiggly),
preamble: "import wiggly: draw-sine;",
preamble: "#import wiggly: *\n",
old-parser: false
)
tidy-output-figure(tidy.show-module(module, show-outline: false))
Expand Down Expand Up @@ -255,7 +255,7 @@ Currently, the two predefined styles `tidy.styles.default` and `tidy-styles.mini
read("/examples/wiggly.typ"),
name: "wiggly",
scope: (wiggly: wiggly),
preamble: "import wiggly: *;",
preamble: "#import wiggly: *\n",
old-parser: false
)
tidy-output-figure(tidy.show-module(module, show-outline: false, style: tidy.styles.minimal))
Expand Down
12 changes: 9 additions & 3 deletions examples/wiggly.typ
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/// Draw a sine function with $n$ periods into a rectangle of given size.
///
/// *Example:*
/// #example(`draw-sine(1cm, 0.5cm, 2)`)
///
/// ```example
/// #draw-sine(1cm, 0.5cm, 2)
/// ```
///
/// -> content
#let draw-sine(
Expand All @@ -13,8 +16,11 @@
height,

/// Number of periods to draw.
/// Example with many periods:
/// #example(`draw-sine(4cm, 1.3cm, 10)`)
///
/// Example with many periods:
/// ```example
/// #draw-sine(4cm, 1.3cm, 10)
/// ```
/// -> int | float
periods
) = box(width: width, height: height, {
Expand Down
189 changes: 148 additions & 41 deletions src/show-example.typ
Original file line number Diff line number Diff line change
@@ -1,51 +1,38 @@



/// Takes given code and both shows it and previews the result of its evaluation.
///
/// The code is by default shown in the language mode `lang: typc` (typst code)
/// if no language has been specified. Code in typst markup lanugage (`lang: typ`)
/// is automatically evaluated in markup mode.
///
/// - code (raw): Raw object holding the example code.
/// - scope (dictionary): Additional definitions to make available for the evaluated
/// example code.
/// - dir (direction): Direction for laying out the code and preview boxes.
/// - preamble (str): Code to prepend to the snippet. This can for example be used to configure imports.
/// - ratio (int): Configures the ratio of the widths of the code and preview boxes.
/// - scale-preview (auto, ratio): How much to rescale the preview. If set to auto, the the preview is scaled to fit the box.
/// - inherited-scope (dictionary): Definitions that are made available to the entire parsed
/// module. This parameter is only used internally.
/// - code-block (function): The code is passed to this function. Use this to customize how the code is shown.
/// - preview-block (function): The preview is passed to this function. Use this to customize how the preview is shown.
/// - col-spacing (length): Spacing between the code and preview boxes.
#let show-example(
/// Default example layouter used with @show-example.
#let default-layout-example(
/// Code `raw` element to display.
/// -> raw
code,
scope: (:),

/// Rendered preview.
/// -> content
preview,

/// Direction for laying out the code and preview boxes.
/// -> direction
dir: ltr,
preamble: "",

/// Configures the ratio of the widths of the code and preview boxes.
/// -> int
ratio: 1,

/// How much to rescale the preview. If set to auto, the the preview is scaled to fit the box.
/// -> auto | ratio
scale-preview: auto,
mode: auto,
inherited-scope: (:),

/// The code is passed to this function. Use this to customize how the code is shown.
/// -> function
code-block: block,

/// The preview is passed to this function. Use this to customize how the preview is shown.
/// -> function
preview-block: block,
col-spacing: 5pt,
..options

/// Spacing between the code and preview boxes.
/// -> length
col-spacing: 5pt
) = {
let lang = if code.has("lang") { code.lang } else { "typc" }
if mode == auto {
if lang == "typ" { mode = "markup" }
else { mode = "code" }
}
if mode == "markup" and not code.has("lang") {
lang = "typ"
}
if code.has("block") and code.block == false {
code = raw(code.text, lang: lang, block: true)
}

let preview = [#eval(preamble + code.text, mode: mode, scope: scope + inherited-scope)]

let preview-outer-padding = 5pt
let preview-inner-padding = 5pt
Expand Down Expand Up @@ -118,4 +105,124 @@
else { measure(arrangement(width: size.width)).height }
arrangement(height: height)
})
}
}



/// Takes a `raw` elements and both displays the code and previews the result of
/// its evaluation.
///
/// The code is by default shown in the language mode `lang: typc` (typst code)
/// if no language has been specified. Code in typst markup lanugage (`lang: typ`)
/// is automatically evaluated in markup mode.
///
/// Lines in the raw code that start with `>>>` are removed from the outputted code
/// but evaluated in the preview.
#let show-example(

/// Raw object holding the example code.
/// -> raw
code,

/// Additional definitions to make available in the evaluation of the preview.
/// -> dictionary
scope: (:),

/// Code to prepend to the snippet. This can for example be used to configure imports.
/// This is currently only supported in `markup` mode, see @show-example.mode.
/// -> str
preamble: "",

/// Language mode. Can be `auto`, `"markup"`, or `"code"`.
/// -> auto | str
mode: auto,

/// This parameter is only used internally. Definitions that are made available to the
/// entire parsed module.
/// -> dictionary
inherited-scope: (:),

/// Layout function which is passed to code, the preview and all other options,
/// see @show-example.options.
/// -> function
layout: default-layout-example,

/// Additional options to pass to the layout function.
/// -> any
..options

) = {
let displayed-code = code.text
.split("\n")
.filter(x => not x.starts-with(">>>"))
.join("\n")
let executed-code = code.text
.split("\n")
.map(x => x.trim(">>>", at: start))
.join("\n")

let lang = if code.has("lang") { code.lang } else { auto }
if mode == auto {
if lang == "typ" { mode = "markup" }
else if lang == "typc" { mode = "code" }
else if lang == "typm" { mode = "math" }
else if lang == auto { mode = "markup" }
}
if lang == auto {
if mode == "markup" { lang = "typ" }
if mode == "code" { lang = "typc" }
if mode == "math" { lang = "typm" }
}
if mode == "code" {
preamble = ""
}
assert(lang in ("typ", "typc", "typm"), message: "Previewing code only supports the languages \"typ\", \"typc\", and \"typm\"")

layout(
raw(displayed-code, lang: lang, block: true),
[#eval(preamble + executed-code, mode: mode, scope: scope + inherited-scope)],
..options
)
}



/// Adds the two languages `example` and `examplec` to `raw` that can be used
/// to render code examples side-by-side with an automatic preview.
#let render-examples(
/// Body to apply the show rule to.
/// -> any
body,

/// Scope
/// -> dictionary
scope: (:),

/// Layout function which is passed to code, the preview and all other options,
/// see @show-example.options.
/// -> function
layout: default-layout-example
) = {
show raw.where(lang: "example"): it => {
set text(4em / 3)

show-example(
raw(it.text, block: true, lang: "typ"),
mode: "markup",
scope: scope,
layout: layout,
)
}
show raw.where(lang: "examplec"): it => {
set text(4em / 3)

show-example(
raw(it.text, block: true, lang: "typc"),
mode: "code",
scope: scope,
layout: layout,
..args
)
}
body
}
16 changes: 16 additions & 0 deletions src/show-module.typ
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,22 @@
(eval-scope.tidy.show-reference)(label(label-prefix + target), target)
}

show raw.where(lang: "example"): it => {
set text(4em / 3)

(eval-scope.example)(
raw(it.text, block: true, lang: "typ"),
mode: "markup"
)
}
show raw.where(lang: "examplec"): it => {
set text(4em / 3)

(eval-scope.example)(
raw(it.text, block: true, lang: "typc"),
mode: "code"
)
}

// Show the docs

Expand Down
12 changes: 7 additions & 5 deletions src/styles/default.typ
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,18 @@
}


#import "../show-example.typ": show-example as show-ex
#import "../show-example.typ" as example

#let show-example(
..args
) = {

show-ex(
example.show-example(
..args,
code-block: block.with(radius: 3pt, stroke: .5pt + luma(200)),
preview-block: block.with(radius: 3pt, fill: rgb("#e4e5ea")),
col-spacing: 5pt
layout: example.default-layout-example.with(
code-block: block.with(radius: 3pt, stroke: .5pt + luma(200)),
preview-block: block.with(radius: 3pt, fill: rgb("#e4e5ea")),
col-spacing: 5pt
),
)
}
13 changes: 8 additions & 5 deletions src/styles/help.typ
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,18 @@
link(label, raw(name, lang: none))
}

#import "../show-example.typ": show-example as show-ex
#import "../show-example.typ" as example

#let show-example(
..args
) = {
show-ex(

example.show-example(
..args,
code-block: block.with(stroke: .5pt + fn-color),
preview-block: block.with(stroke: .5pt + fn-color),
col-spacing: 0pt
layout: example.default-layout-example.with(
code-block: block.with(radius: 3pt, stroke: .5pt + luma(200)),
preview-block: block.with(radius: 3pt, fill: rgb("#e4e5ea")),
col-spacing: 5pt
),
)
}
7 changes: 5 additions & 2 deletions src/styles/minimal.typ
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,18 @@
link(label, raw(name, lang: none))
}

#import "../show-example.typ": show-example as show-ex
#import "../show-example.typ" as example

#let show-example(
..args
) = {
show-ex(

example.show-example(
..args,
layout: example.default-layout-example.with(
code-block: block.with(stroke: .5pt + fn-color),
preview-block: block.with(stroke: .5pt + fn-color),
col-spacing: 0pt
),
)
}
2 changes: 1 addition & 1 deletion src/tidy.typ
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#import "old-parser.typ" as tidy-parse
#import "utilities.typ"
#import "testing.typ"
#import "show-example.typ"
#import "show-example.typ" as show-example: render-examples
#import "parse-module.typ": parse-module
#import "show-module.typ": show-module
#import "helping.typ" as helping: generate-help
Expand Down