When I sit in front of an old school, regular computer1, writing happens in Vim. Mails, code, blogposts, my diploma thesis, ToDo-lists, comments on random web pages2 - everything.
And I love Markdown. And footnotes3. So the usage of MultiMarkdown-footnotes is a natural fit.
There is no real standard for the notation, but most people tend to use numbers
or words or a combination of these two. As long as the footnote marker is
preceded by a caret (^
) and enclosed by square brackets ([]
) and the
matching footnote reference starts at the beginning of a line and is followed
by a colon (:
), MultiMarkdown is a happy camper. The resulting
Markdown-source is easy to read and really flexible:
1 2 3 4 5 6 7 8 9 10 |
|
Trouble is, all these brackets and carets for the footnote links are kind of hard to type. The best practice for the footnote references is to keep them at the end of the file, so additional cursor movement is necessary. If you just want to insert a footnote as fast as possible and keep your writing flow, all this key pressing gets boring really soon.
vim-markdownfootnotes
to the rescue
Luckily, I use Vim. Vim loves text automation. And Vim is used by lots of smart people like David Sanson who forked the venerable vimfootnotes, named it vim-markdownfootnotes and tweaked it for use with the extended Markdown markup as shown above.
The vim-markdownfootnotes
plugin can easily be installed with Pathogen and defines
two mappings:
1 2 |
|
From now on, you just type <Leader>f
whenever you want to insert a footnote
marker. The mapping works in normal and in insert mode which results in
almost no friction while writing. This simple command inserts a footnote marker
like [^1]
after the cursor and a matching footnote reference like [^1]:
gets inserted all the way down at the end of the file. Impressive, but the
wonder does not stop here:
Vim opens a new buffer in a split window at the bottom of the current window
and places your cursor right behind the empty space after the colon. This way
you can just keep on typing your footnote and hit <Leader>r
to close the
split and return to the place in the main text where you left off. And you
just keep on typing, leaving behind only a beautifully formatted MultiMarkdown
footnote and no wasted thoughts.
It looks a lot like this:
The plugin also keeps track of the number of footnotes it inserted so the
second footnote marker gets inserted as [^2]
, the third as [^3]
and so
on…
It’s a really good solution and includes some nice bells and whistles. If, for
example, you don’t like the use of the default arabic numerals you are free to
change the format by setting the variable vimfootnotetype
to one of the
following:
arabic
: 1, 2, 3…alpha
: a, b, c, aa, bb…, zz, a…Alpha
: A, B, C, AA, BB…, ZZ, A…roman
: i, ii, iii… (displayed properly up to 89)Roman
: I, II, III…star
: *, **, ***…
Because we can. Crazy stuff. Totally cool if you think about it.
My footnote counter pet peeve
I installed the plugin in spring 2012 and slightly changed the sourcecode to
use [^fn23]
as footnote markup4 to make it more distinguishable from
regular numbered Markdown reference style links. I kept on using it ever
since, despite one minor gripe which kept on itching me:
The footnote counter only works for one session. Whenever I opened a file which
already contained some footnotes, I had to check5 for the number of the
last added footnote and use the FootnoteNumber
command to set the counter to
the correct starting point.
I usually write my blogposts in small chunks, so typing :FootnoteNumber 5
after finding out that the last footnote was [^fn4]
was also kinda boring.
And of course I always inserted a [^fn1]
when footnotes were already
present in the file before remembering I had to adjust the counter. So I had to
undo the last footnote, close the split by hand, reset the counter and start
again…
I don’t want to do this little footnote-counter-adjusting-dance every time I open a file. My computer should do this for me. I mean, seriously how hard can it be?
Luckily, another smart Vim-user named Nick Coleman, solved the problem for the automatic insertion of HTML-footnotes which are magnitudes harder to type than their Markdown counterparts. He wrote his own footnote.vim script which6 does not include fancy stuff like key mappings or splits but had a working footnote counter implemented in VimL.
So I did what every self respecting geek would do:
I ripped the code apart and changed the regular expression to match against my
style of Markdown footnotes. The result worked fine on it’s own but I missed
the easy writing flow of <Leader>f
and <Leader>r
.
Naturally, I forked vim-markdownfootnotes
on Github and cobbled the
counter code directly into the function s:VimFootnotes(appendcmd)
. Now,
whenever I hit <Leader>f
the script counts the occurences of the footnote
references, adds 1 and sets the global variable g:vimfootnotenumber
to the result.
The FootnoteNumber
, FootnoteNumberRestore
and FootnoteUndo
functions are
still present in the code, but whatever they set the variable to gets
overridden by the automatic counter which, by the way, even works with non
arabic numerals. So people who prefer their footnotes numbered with roman
numerals or stars can also use this.
No more thinking about the current footnote counter, more thinking about my words. Excellent.
Sorting Markdown footnotes
Now, because I tend to edit my posts in small chunks it is not uncommon at all, that I insert a footnote somewhere in the text. Maybe even at the very beginning. This can lead to a situation like this7:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
The second footnote is added to the beginning of the text, 2 appears before 1. The footnote references are numbered 1, 2, 3 but the footnote markers are 2, 1, 3.
This is, and I may overreact here, totally wrong…
Markdown does not care a bit about the order in which the footnotes appear in the text. The text above and the following, nicely tidied up text render to the exact same HTML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
So nobody but me would notice any difference. But really, this bothered me. So again, I turned to the Internet to see if I could find a solution for my problem. And sure enough, in a thread on the MultiMarkdown Google group I found a hint8 that the document converter Pandoc could do this by converting from Markdown to Markdown like this:
1
|
|
Indeed, this works fine but strips my beloved fn
-addition from each and every
footnote… And I’m so used to my beloved fn
-additions…
I considered diving into the source of Pandoc to fix this behaviour and learn some Haskell along the way but decided against it. I thought of formd, which I use to convert Markdown links from inline to reference style9 and wondered, why this fine software does not work with footnotes. After all, they are not that different from regular reference links, aren’t they?
Soon I found out that Seth Brown aka Dr. Bunsen altered the code of
formd
to ignore footnotes. As requested by Martin Kopischke and,
ahem, me…
I tried to find out if I could alter the behaviour of formd
to sort footnotes
as effortless into a nice order as links. But my Python-fu was too weak.
With some more looking at the Internet I found a promising looking post by yet another Dr., Dr. Drang. He wrote a Python-script to tidy up Markdown reference links.
More importantly, he explained the inner workings of the script in great
detail, so even I could figure out10 how this was supposed to work. Just
like formd
, the script made sure to exclude footnotes. I changed the two
regular expressions to match against footnote markers and references and ignore
regular markdown links. The inner logic remained the same and some more
adjustments to the string replacement parts later the new sort_footnotes
script worked surprisingly well. It looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
The script is also available in it’s own Github repository.
Like the original by Dr. Drang, sort_footnotes
is by no means foolproof. In
fact, it does not work with footnote links at the start of a line and fails
horrible if one is found in a file. The alternate way to differentiate between
footnote links and footnote references would have been the colon. I figured it
is much more probable that a footnote link appears right before a colon, than
it’s appearance at the start of a line. After all, footnotes should appear
after words or, even better, sentences and not before them11. Even
stranger things might occur if two footnotes have the same number or if one
marker misses it’s reference or vice versa. This kind of stuff should of course
never happen if you use the automatic insertion of footnotes as described above
but YMMV…
This script also does not work with roman numerals or stars so fans of these footnote markers will have to port the numeral converter from VimL to Python and insert it into my script12…
Because the script was designed to work via standard input it is easy to create
a small Vim macro, assign a mapping like <Leader>fs
and pipe the content of the
current buffer through it. For good measure I also defined a <Leader>fx
mapping to use formd
and sort_footnotes
in one fell swoop on the current
buffer.
The mappings are defined in my .vimrc
as follows:
1 2 3 4 5 6 7 8 9 10 |
|
And this is pretty much it.
Without worrying about cursor movement, bracket typing and keeping footnote counters up to date it is much easier to type at the speed of thought. It is one mental barrier less when I jump into a draft for a 20 minute editing session after a long day. And the nicely ordered lists of links and footnotes at the end of my markdown source files make me feel all warm and cozy inside.
-
As in, not an iOS device… ↩
-
Thanks to the wonderful QuickCursor… ↩
-
Oh boy, do I love me some footnotes… ↩
-
This is just my personal preference, you can use just about anything or leave it as is… ↩
-
as in manually… ↩
-
on purpose… ↩
-
Sample text produced by the awesome Samuel L. Ipsum… ↩
-
From the already mentioned David Sanson… ↩
-
formd
sorts the reference style links exactly like I want my footnotes sorted… ↩ -
After poking around in the code with a long stick and some
print
statements… ↩ -
Well, maybe, one of those days… ↩