How to use the plain `raw` function?

I try to figure out how to use the plain raw function.

The following works fine:

```
fn main() {
    println!("Hello World!");
}
```

But this version doesn’t:

#raw(block: true, [
  fn main() {
      println!("Hello World!");
  }
])

What’s wrong there?

Note that the text parameter is a string, not a content. It says str (in green), not content (in a different, more blueish shade of green…).

1 Like

Ah, now I see, thanks! The following works fine:

#raw(block: true,
"fn main() {
    println!(\"Hello World!\");
}"
)

But what if I prefer to indent the string? I tried

#raw(block: true,
  "fn main() {
      println!(\"Hello World!\");
  }"
)

but then the output is indented wrongly:

fn main() {
      println!("Hello World!");
  }

This is expected. If you look again at the definition of raw() you’ll see it says

Displays the text verbatim and in a monospace font.

So when you indent your string you add tabs/spaces, which are treated verbatim and shown in the output.

1 Like

And there is no way to tell the compiler something like “ignore the first two spaces”, so that

#raw(block: true,
  "fn main() {
      println!(\"Hello World!\");
  }"
)
```

will give the output shown below?

fn main() {
    println!("Hello World!");
}

As far as I know there is not a way to do it built in, but you can create a helper function that does it for you:

#let rawSkipChars(rawTxt, numCharsToSkip: 2) = raw(
  block: true,
  
  rawTxt
  .split("\n")
  .map(l => l.slice(numCharsToSkip))
  .join("\n")
)

#let func = "  void print(x)
  {
    //something goes here
  }"

#rect(raw(func))
#rect(rawSkipChars(func))
Output

image

The rawSkipChars function splits the text given to it, removes the first two characters from each line, then joins all lines back together.

Note that this won’t work with the exact string you have in your last post because the very first line does not have any spaces before fn.

1 Like

Here are some alternatives you can try:

// keep string indented by making it into seperate strings inside a list, that will be joines with linebreaks
#raw(block: true, (
  "fn main() {",
  "  println!(\"Hello World!\");",
  "}").join("\n")
)

//keep string indented by manually appending linebreaks and joining strings with + operator
#raw(block: true,
  "fn main() {\n" +
  "  println!(\"Hello World!\");\n" +
  "}"
)


//use a custom show rule, that trims the first two leading spaces of each line of any raw block
#show raw: it => it.text.split("\n").map(line => line.trim("  ", at: start, repeat: false)).join("\n")

#raw(block: true,
  "fn main() {
    println!(\"Hello World!\");
  }"
)

The last solution is similar to the proposed solution of @gezepi

EDIT: actually, my last proposal is somewhat flawed, because inside the show rule only the text ist returned and syntax styling gets lost.
A custom function applied to the string before handing it to a raw block would work better here.

1 Like

Another solution is to actually use the raw ``` syntax to make the string :slight_smile:

#raw(block: true,
  ```
  fn main() {
    println!("Hello World!");
  }
  ```.text
)

All spaces before the indent level of the ``` are trimmed (this feature seems to be undocumented).

Of course this is going a bit in circles so I wonder why you want to avoid the ``` syntax for literal raw blocks? Is it to use escape sequences in the string?

2 Likes

Well, currently I simply try to improve my understanding how the plain Typst functions work, because they provide more options to customize the output and thus are very useful. E.g., using plain ‘raw’, I can change the color theme of a specific code block, or maybe to highlight a line there. As far as I know, these things are not possible if I simply use something like

```
// fenced code block
```

I didn’t try your solution yet, because I’m currently not near my laptop.

I can’t try it either right now but if all you want to do is change some options on raw for a single code block you could enclose a set or show rule and the literal raw block in a content block. Like

[
  #set raw(..set some option)
  // Or
  #show raw: set some styling
  ```
    //Some code
  ```
]
2 Likes

The ``` notation is just syntactic sugar for raw(); see the first design principle of Typst, simplicity through consistency.

1 Like

This is an interesting suggestion. Could you show a working example?

#[
  #show raw: set text(weight: "bold")
  ```rust
  fn main() {
    println!("Hello World!");
  }
  ```
]

```rust
fn main() {
  println!("Hello World!");
}
```

2 Likes