Whenever someone sees my editor, this is always the first thing they ask about.
Vim (and Emacs) have features that let you conceal text with other text. The actual source text is not modified. If you put your cursor on the concealed line, the conceal goes away.
This is best illustrated by example. Here’s what the Python code normally looks like:
identity = lambda x: x
But here’s what I see:
identity = λ x: x
It’s really easy to abuse since no one has to view it but you, unlike code formatting. I ended up creating an entire mini-language, consistent across multiple programming languages.
The running examples throughout this blog post will be Python and Rust, because I’ve used those recently. Haskell is another language that benefits a lot from this.
By relieving the brain of all unnecessary work, a good notation sets it free to concentrate on more advanced problems, and in effect increases the mental power of the race.
So we start by unifying the building blocks of every language with prettier Unicode versions.
== | ≝ != | ≠ <= | ≤ >= | ≥ and, && | ∧ or, || | ∨ not, ! | ¬ None | ∅ true, false | ⊤, ⊥ (top and bottom from logic) for | ∀ in | ∈ not in | ∉ = | ← (to remind me that equality is really assignment) -> | → (that's an arrow replaced by a better arrow) assert | ‼
Types are concealed with their math symbols
bool | 𝔹 char | ∁ string, str | 𝐒 unsigned | ℕ int | ℤ float | ℝ complex | ℂ vector | V tensor | 𝕋
This is nice because it makes reading code uniform across languages.
Basic constructs like
for .. in .. read like math.
Most of this category is for making ugly syntax bearable.
I read a lot of scientific code and Greek letters as variable names abound.
So I concealed the entire Greek alphabet, lower and uppercase.
I also don’t like looking at
:: in C++ and Rust. Conceptually, it’s
like a dot operator for the purposes of reading code, so I conceal it
I also don’t like looking at semicolons, and my linter will tell me if I
missed them, so they get concealed with
𐤟 (which is apparently a
Phoenician word separator. It should look like a very faint dot, but may
not render correctly in the browser. You can see I’ve scoured a lot of
glyphs for this).
I hate the use of
self in Python, so I concealed it with
female sign emoji. It looks like a little person (a little self), and
is a single character.
If I’m going to see a word a lot in a lot of contexts, it’s probably going to end up concealed.
Grammar of control flow
I have a system for conditionals and looping.
loop | ∞ (`loop` is just `while True`) while | ⥁ continue | ↻ match, if | ▸ elif | ▹ else | ▪ break | ◁ return | ◀ def, fn, function | ※ (Japanese typography reference marker) class | §
The infinity and ouroboros symbols for
The rest, not so much. I worked up this system late at night.
continue is a loop because it doesn’t break out of the loop (that’s
why it loops clockwise since I always imagine looping going clockwise).
It’s a broken ouroboros because it cuts off the current iteration.
The conditionals always start with an
if, which is filled in, and just
gets a pointer to indicate, “hey look at this condition”. Conditions
have to end with an
if or an
else, but not an
an empty pointer.
else is indicated by the mathematical “end of proof”
symbol, since the
else ends the conditional. In this way, a
conditional is only valid if it begins and ends with solid markers.
return takes you out of a function’s scope, and I think of going in
scope as going rightwards, so
return points left. Plus the right
pointer was taken by
break is similar but may not take you out
of all scopes, just the innermost loop enclosing it.
I think the
function conceal is pretty clear. The
class conceal is
because I think of classes like I think of sections in an essay, so they
get a section marker.
range | ι unsafe | ☡ struct | ∏ enum | ∐
The iota is because that’s the one bit of APL I know.
unsafe comes from the “dangerous bend” symbol that Bourbaki used to
indicate a tricky section in their books. That concession to
user-friendliness ironically concealed a dangerous bend. Which was the
fact that Bourbaki books don’t care about anyone being able to read
enum are product and sum (AKA coproduct) types, so they
get the corresponding symbols from category theory.
It lets me feel my code rather than read it. It makes seeing the shape of code easier at first pass, and I can see the forest for the trees somewhat better. But then I have to hunker down and edit it.
function! ToggleConcealLevel() if &conceallevel == 0 setlocal conceallevel=2 else setlocal conceallevel=0 endif endfunction nnoremap <silent> <C-c><C-y> :call ToggleConcealLevel()<CR>
That toggles the conceal. Now other people can read over your shoulder.
It’ll also spare you explanations of how you got the
for to look like
it does in math.
(Since so many of you asked)