Skip to content
Colin Moldenhauer edited this page Oct 14, 2026 · 4 revisions

Lisp keywords and operators of Hy: fn, defn, the comprehension forms (lfor, dfor, gfor, sfor), ->, in, comparisons and some Greek letters. Requires an extension that provides the language id hy-lang; the pattern **/*.hy makes the rules apply to every .hy file regardless.

Where to put it

The block below is a complete entry for the prettifySymbols.substitutions array. Paste it into your settings.json (command palette Ctrl+Shift+P, then Preferences: Open User Settings (JSON) for all projects, or .vscode/settings.json for one workspace); if you already have that setting, add the { ... } object to the existing array:

"prettifySymbols.substitutions": [
    // the entry below goes here
]

Changes take effect as soon as you save settings.json. The extension is enabled by default; the animation at the bottom starts with it switched off only to show the difference.

Settings

{
  "language"            : ["hy-lang", {"pattern": "**/*.{hy}"}],
  "revealOn"            : "active-line",
  "adjustCursorMovement": true,
  "substitutions"       : [
    { "ugly": "defn",         "pretty": "ƒ", "pre": "\\b", "post": "\\b"},
    { "ugly": "fn/a",         "pretty": "λa", "pre": "\\b", "post": "\\b" },
    { "ugly": "fn",           "pretty": "λ", "pre": "\\b", "post": "\\b"},
    { "ugly": "sfor",         "pretty": "s∀", "pre": "\\b", "post": "\\b"},
    { "ugly": "\\*",          "pretty": "·", "pre": "[^\\*]|^", "post": "\\s|$"},
    { "ugly": "math.sqrt",    "pretty": "√", "pre": "\\(", "post": "\\b"},
    { "ugly": "sum",          "pretty": "∑", "pre": "\\(", "post": "\\b"},
    { "ugly": "in",           "pretty": "∈", "pre": "\\b", "post": "\\b"},
    { "ugly": "not-in",       "pretty": "∉", "pre": "\\b", "post": "\\b" },
    { "ugly": "epsilon",      "pretty": "ε", "pre": "\\b", "post": "\\b" },
    { "ugly": "and",          "pretty": "∧", "pre": "\\(|\\s|^", "post": "\\s|$"},
    { "ugly": "or",           "pretty": "∨", "pre": "\\(|\\s|^", "post": "\\s|$"},
    { "ugly": "not",          "pretty": "¬", "pre": "\\(|\\s|^", "post": "\\s|$"},
    { "ugly": "dfor",         "pretty": "d∀", "pre": "\\b", "post": "\\b" },
    { "ugly": "for",          "pretty": "∀", "pre": "\\(|\\s|^", "post": "\\s|$"},
    { "ugly": "->",           "pretty": "⊳", "pre": "[^->]", "post": "[^->]"},
    { "ugly": "->>",          "pretty": "‣", "pre": "[^->]", "post": "[^->]"},
    { "ugly": "alpha",        "pretty": "α", "pre": "\\b", "post": "\\b"},
    { "ugly": "beta",         "pretty": "β", "pre": "\\b", "post": "\\b"},
    { "ugly": "xi",           "pretty": "ξ", "pre": "\\b", "post": "\\b" },
    { "ugly": ">=",           "pretty": "≥", "pre": "[^=\\-<>]|^", "post": "[^=\\-<>]|$"},
    { "ugly": "<=",           "pretty": "≤", "pre": "[^=\\-<>]|^", "post": "[^=\\-<>]|$"},
    { "ugly": "!=",           "pretty": "≠", "pre": "[^<>=!]|^", "post": "[^<>=]|$"},
    { "ugly": "lfor",         "pretty": "l∀", "pre": "\\b", "post": "\\b"},
    { "ugly": "gfor",         "pretty": "g∀", "pre": "\\b", "post": "\\b"},
    { "ugly": "None",         "pretty": "∅", "pre": "\\b", "post": "\\b"},
    { "ugly": "math.pi",      "pretty": "π", "pre": "\\b", "post": "\\b"},
    { "ugly": "some",         "pretty": "∃", "pre": "\\b", "post": "\\b"},
    { "ugly": "gamma",        "pretty": "γ", "pre": "\\b", "post": "\\b"},
    { "ugly": "delta",        "pretty": "δ", "pre": "\\b", "post": "\\b"},
    { "ugly": "#%",           "pretty": "ξ"},
    { "ugly": "True",         "pretty": "⊤", "pre": "\\b", "post": "\\b"},
    { "ugly": "False",        "pretty": "⊥", "pre": "\\b", "post": "\\b"}
]}

What is what

  • language: which files the entry applies to (a language id plus a file pattern).
  • revealOn: "active-line": all original text on the line of the cursor is revealed, not only the symbol under the cursor. This suits Lisp, where a line is a unit of editing.
  • adjustCursorMovement: true: the arrow keys step over a symbol as if it were one character.
  • substitutions: the rules. Each rule is one line: ugly is a regular expression for the text to hide, pretty is what is shown instead, and the optional pre and post are regular expressions that must match the text just before and after, without being replaced themselves. Backslashes are written twice because the value is parsed by JSON and then as a regular expression.
  • and, or, not, for: match after whitespace, a ( or the start of the line, because in Lisp they usually directly follow an opening parenthesis.
  • fn, fn/a, defn: λ, λa, ƒ; the comprehensions lfor (list), dfor (dict), gfor (generator) and sfor (set) become l∀, d∀, g∀ and s∀.
  • -> and ->> (threading macros): ⊳ and ‣.
  • math.sqrt and sum: √ and ∑, only directly after a (.

In action

Hy example: plain code, extension enabled, clicking a symbol reveals the original

The animation is rendered from the rules on this page. The code is never modified: clicking into a symbol (or moving the cursor onto it) shows the original text again, and the symbol returns when the cursor leaves.

Clone this wiki locally