How can I include user privilege indicators in shell prompts while keeping syntax highlighting enabled in codeblocks?

If you want to use it for only oneliners:

#show raw: set text(font: "Fira Mono")

#let user(command) = emph(raw("$ ")) + raw(command, lang: "sh")
#let root(command) = emph(raw("# ")) + raw(command, lang: "sh")

Example snippet, to be run by a regular user:

`$ ````sh chmod test.sh```

#user("chmod test.sh")

Example snippet, to be run by with root privileges:

`# ````sh chown user test.sh```

#root("chown user test.sh")

image

For multi-line stuff you can do something like this:

#show raw: set text(font: "Fira Mono")

#let user(command) = {
  show raw.line: it => emph(text(font: "Fira Mono", "$ ")) + it
  command
}
#let root(command) = {
  show raw.line: it => emph(text(font: "Fira Mono", "# ")) + it
  command
}

Example snippet, to be run by a regular user:

#user(```sh
chmod this
chmod that
```)

Example snippet, to be run by with root privileges:

#root(```sh
chown user this
chown user that
```)

image

Or if you want to write the appropriate prefix yourself, here is a little trick (note that you need to specify an absolute font size):

#show raw: set text(font: "Fira Mono", size: 10pt)

#show raw.where(lang: "console"): it => {
  let user = emph(raw("$ "))
  let root = emph(raw("# "))
  it
    .text
    .split("\n")
    .map(line => {
      let starts(pattern) = line.starts-with(pattern)
      let prefix = if starts("$ ") { user } else if starts("# ") { root }
      let text = line.replace(regex("^[$#] "), "")
      prefix + raw(text, lang: "sh")
    })
    .join("\n")
}

```console
$ chmod this
$ chmod that
# chown user this
# chown user that
```

image

I tried using show raw.line inside show raw.where(lang: "console"), but I hit infinite show rule recursion and I don’t know if it is fixable. So this approach is the second one, and it actually works. But multi-line commands probably will not be highlighted properly. Maybe with enough dedication a more resilient solution can be found.

1 Like