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.
Basics
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.
Idiosyncratic
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
with .
.
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 ♀
, the
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 loop
and while
feel
intuitive.
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 elif
, so elif
gets
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 if
. 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.
Really Idiosyncratic
AKA mathy.
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
them.
struct
and enum
are product and sum (AKA coproduct) types, so they
get the corresponding symbols from category theory.
Why?
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.
Important
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.
Screenshot
(Since so many of you asked)