diff options
author | mms <michal@sapka.me> | 2024-07-28 20:57:11 +0200 |
---|---|---|
committer | mms <michal@sapka.me> | 2024-07-28 20:57:11 +0200 |
commit | f864511fe699fec99da4c45b37f17600f3516e71 (patch) | |
tree | 285db42dd824d9b3093c24d3eebb4219ae11e478 /content/emacs | |
parent | f7f9b4b4670881fe3e51f1b1e55603df5ce21133 (diff) |
feat: Unify emacs with cool emacs
Diffstat (limited to 'content/emacs')
-rw-r--r-- | content/emacs/input-completition-in-emacs.md | 120 | ||||
-rw-r--r-- | content/emacs/literate-programing-in-emacs.md | 117 | ||||
-rw-r--r-- | content/emacs/org-babel.md | 175 | ||||
-rw-r--r-- | content/emacs/whys-of-emacs.md | 180 |
4 files changed, 0 insertions, 592 deletions
diff --git a/content/emacs/input-completition-in-emacs.md b/content/emacs/input-completition-in-emacs.md deleted file mode 100644 index f7747a1..0000000 --- a/content/emacs/input-completition-in-emacs.md +++ /dev/null @@ -1,120 +0,0 @@ -+++ -title = "Emacs: Input Completiton in Emacs" -author = ["Michał Sapka"] -date = 2023-05-26T23:00:00+02:00 -categories = ["emacs"] -draft = false -weight = 2001 -abstract = "Icomplete, IDO and FIDO" -aliases = ["/2023/input-completition-in-emacs/"] -[menu] - [menu.emacs] - weight = 2001 - identifier = "emacs-input-completiton-in-emacs" - parent = "guides" - name = "Input completition (Icomplete, IDO, and FIDO)" -+++ - -Emacs consists of a massive set of tools with a long history. -Therefore, whatever the problem is, someone likely has already created a package for it. -In many cases, this package is already baked in Emacs. -This is great for veterans but very confusing to newcomers - like me. - - -## The three modes {#the-three-modes} - -Emacs comes with three modes for input completion: Icomplete, IDO, and FIDO. -Input completion works with whatever you select in the Minibuffer section. -For text competition, you must use a different solution, like Company mode[^fn:1]. - -The oldest one of those is _icomplete_[^fn:2] mode. -It allows you to select from a list of choices incrementally[^fn:3], so you need to type the beginning, and icomplete will narrow the list of propositions. -For example, when searching for "magit", the user needs to type "m" first as omitting it and starting with "i" will instead narrow to options beginning with "i". -Similarly, "mgt" will not limit to "magit" as we're missing"a". -Newer Emacs versions allowallow us to use "flex" matching with icomplete, but more on this later. -Incomplete work for all lists using a mini buffer, like filenames or imenu. - -Then _IDO_[^fn:4] mode (Interactively Do) came in. -It uses the aforementioned "flex" matching, where you can search for any part of the word. -"Magit" would be found with "agit", "mgt" or just "git". -IDO, however, works only with files and buffers, so \`M-x\` would still fall back to icomplete. - -Starting with Emacs 27, we've got _fido_ mode (Fake Ido). -It combines the best things about icomplete (works anywhere) with flex matching. -In fact, all Fido does under the hood is to enable Icomplete with flex matching. - -There are also other solutions for competition, not baked into emacs, with the most popular being Helm[^fn:5] and Ivy[^fn:6]. -Personally, I always try the default option, and only if their limits become annoying do I look at the alternatives. -So, I am now a happy FIDO mode user. - - -## Using FIDO {#using-fido} - -To start FIDO mode run - -```emacs-lisp -fido-mode -``` - -or, if you find a vertical list to be more readable, use - -```emacs-lisp -fido-veritcal-mode -``` - -You can also customize variables to have it auto-load in your \`init.el\`: - -```emacs-lisp -(fido-mode t) -;; or -(fido-vertical-mode t) -``` - -As I've stated above, FIDO is nothing more than flex-enabled Icomplete, so all keybindings work the same. -For vertical mode: - -- Typing a string will narrow the selection -- \`C-n\` and \`C-p\` will select the next/prev element on the list -- \`Tab\` will display a buffer with a list of narrowed elements -- \`enter\` or \`C-j\` will select the option - -One cool thing you can do with FIDO is file deletion (when selecting files) or closing buffers (when selecting buffers) using \`C-k\`. - - -## Customizing the Minibuffer {#customizing-the-minibuffer} - -We can, of course, customize how Icomplete looks works[^savanah]. - -- _icompleteatches-format_ (default "%s/%s") - how the number of filtered and total options is presented -- _complete-first-match_ (default (t :weight bold)) - how the first filtered option is presented -- _icomplete-selected-match_ (default (t :inherit highlight)) - the same as above, but for vertical mode -- _icomplete-section_ (default (t :inherit shadow :slant italic)) - how the section title for vertical mode is presented -- _icomplete-compute-delay_ (default .15) - how fast the filtering will start after a keypress when a larger number of options is presented -- _icomplete-delay-completions-threshold_ (default 400) - defines the "large number" for icomplete-compute-delay -- _icomplete-max-delay-chars_ (default 2) - maximum number of initial characters before applying _icomplete-compute-delay_. I have no idea what it means, nor have I the knowledge of Elisp to dig into it. -- _icomplete-in-buffer_ (default nil) - enables usage of Icomplete outside of the Minibuffer. I have not tested it. - -We can also use _icomplete-minibuffer-setup-hook_ hook if needed. -[^savanah]: list based on [Icomplete source code](https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/icomplete.el) - - -## Using Completions from Elisp {#using-completions-from-elisp} - -The great thing about FIDO is that it, like Icomplete, uses Minibuffer API[^fn:7], so you can simply: - -```emacs-lisp -(completing-read - "prompt: " - '(("option1" 1) ("option" 2)) - nil t "default query") -``` - -[^fn:1]: [Company-mode website](https://company-mode.github.io/) -[^fn:2]: [Icomplete documentation](https://www.gnu.org/software/emacs/manual/html_node/emacs/Icomplete.html) -[^fn:3]: According to a [Reddit comment](https://www.reddit.com/r/emacs/comments/13szol7/comment/jltmaud/?utm_source=reddit&utm_medium=web2x&context=3) this behavior is relatively new. - Until recently, Icompelete only showed the narrowed selection in a dedicated buffer, similar to using \`Tab-Tab\` now. - The actual input was still up to the user to type in. Thanks for the tidbit -[^fn:4]: [IDO documentation](https://www.gnu.org/software/emacs/manual/html_mono/ido.html) -[^fn:5]: [Helm website](https://emacs-helm.github.io/helm/) -[^fn:6]: [Ivy website](https://oremacs.com/swiper/) -[^fn:7]: [Guide on Minibuffer completition](https://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffer-Completion.html) diff --git a/content/emacs/literate-programing-in-emacs.md b/content/emacs/literate-programing-in-emacs.md deleted file mode 100644 index 258a96d..0000000 --- a/content/emacs/literate-programing-in-emacs.md +++ /dev/null @@ -1,117 +0,0 @@ -+++ -title = "Emacs: Introduction to Literate programming" -author = ["Michał Sapka"] -date = 2024-01-30T19:10:00+01:00 -categories = ["emacs"] -draft = false -weight = 2002 -abstract = "A short introduction into the idea of literate programming" -[menu] - [menu.emacs] - weight = 2002 - parent = "guides" - identifier = "litprog" - name = "Literate programming" -+++ - -## Abstract {#abstract} - -In this article I give a short, theoretical introduction to the idea of Literate programming - - -## Introduction {#introduction} - -Literate programming is not a subject that comes out often, except if you are talking with an Emacs enthusiast. -There is a significant chance that most programmers don't even know the term. -Let's fix that with a quote: - -> Literate programming is an approach to programming which emphasises that programs should be written to be read by people as well as compilers. -> From a purist standpoint, a program could be considered a publishable-quality document that argues mathematically for its own correctness. -> A different approach is that a program could be a document that teaches programming to the reader through its own example. -> A more casual approach to literate programming would be that a program should be documented at least well enough that someone could maintain the code properly and make informed changes in a reasonable amount of time without direct help from the author. -> At the most casual level, a literate program should at least make its own workings plain to the author of the program so that at least the author can easily maintain the code over its lifetime. -> -> -- Christopher Lee[^fn:1] - -The idea is therefore a conversion of an entity out of which one can extract code or documentation. -A semi-abstract in-between called "web[^fn:2]". -The process of creating code is called "tangling", and generation of document is a "weave". - - -## An example {#an-example} - -Let's say we want to show the reader how to install DWM. -We can create a document in a style: - -> DWM is a window manager that can be changed only via source code modification. -> Here, we will fetch and compile it. -> First, we need to download the tarball: -> -> ```shell -> wget https://dl.suckless.org/dwm/dwm-6.4.tar.gz -> ``` -> -> then, simply extract it -> -> ````shell -> tar - xvzf dwm-6.4.tar.gz -> ```` -> -> And then we compile it -> -> `````shell -> cd dwm-6.4 -> doas make clean install -> ````` -> -> After the compilation finishes, add executable to your .xinit -> -> ``````shell -> echo "exec dwm" >> ~/.xinit -> `````` - -So yeah, it's a blog post. -A blog post which one can execute. -The example assumes shell, but the actual language can be anything. -We can _tangle_ C code without any problems. - - -## Literate programming {#literate-programming} - -This is **not** the way we do programming. -We smack spaghetti code together, add a random sentence here and there, commit is as "bug fix" and voilà! -In a few months no one knows what's going on. -Success, up to the next JIRA task. - -Very often code comments are treated as an harmful or (at best) a necessary evil. -We think that code should be self-documenting. -And this is completely valid. -A developer needs to understand what given code does, just by reading it. -If your function is so convoluted, nested and complicated that it's impossible to comprehend without a descriptive comment. - -But this is not the whole story. -A function may be very simple, but there is always _context_ in which it is used. - -Literate Programming promotes telling story to the reader. -You are free to do narration giving all extra info in one place. -Since the code coexists with documentation, the reader gets the whole picture. - - -## Conclusion {#conclusion} - -Now, this is not a generic fix for all programs. -We work on massive systems with hundreds of intertwined, moving parts. -It is impossible to create a cohesive narrative when the program jumps all over the place. - -Literate programing, however, found a different home. -It is loved by scientists (just look at Jupyter Notebooks[^fn:3]) who use it for reproducible resarch. -We, amongts Emacs crowed, use it extensively for literate configuration of our environments. -It could be used for scripts, runbooks, debugging logs and so on. -Wherever one can see a logical A, B and C points, we can explain the interconnections. - -You can learn more (including much better example) by reading the [original Knuth's paper](https://michal.sapka.me/papers/literate_programming_knuth_1984.pdf). - -[^fn:1]: ["Literate Programming -- Propaganda and Tools", Christopher Lee, 1997](https://web.archive.org/web/20170603045917/http://vasc.ri.cmu.edu:80/old_help/Programming/Literate/literate.html) -[^fn:2]: this name was choosen, because at the time it was not in use related to computing. - We're dealing with history here! -[^fn:3]: I know that Jupyter is not strictly a literate program, but it's close enough. diff --git a/content/emacs/org-babel.md b/content/emacs/org-babel.md deleted file mode 100644 index 691f6c7..0000000 --- a/content/emacs/org-babel.md +++ /dev/null @@ -1,175 +0,0 @@ -+++ -title = "Emacs: Executing code in Org files with Babel" -author = ["Michał Sapka"] -date = 2024-02-07T21:23:00+01:00 -categories = ["emacs"] -draft = false -weight = 2003 -abstract = "A short introduction into the world if Org Babel" -[menu] - [menu.emacs] - weight = 2003 - identifier = "emacs-executing-code-in-org-files-with-babel" - parent = "litprog" - name = "Literate programing in Org with Babel" -+++ - -**Abstract**: a very short introduction into the word of Org Babel. - -No other package seems to have had such huge impact on Emacs community as the introduction of Org Babel[^fn:1]. -It made folks not only love their Org Mode, but _live_ in it. - -In short: Babel allows for [literate programming](/emacs/literate-programing-in-emacs/) form within an Org document. - - -## Source code basics {#source-code-basics} - -Babel comes baked into any modern version of `Emacs`, so you've already got everything you need. -Open any `org` document, add the code to the document within source code blocks: - -```emacs-lisp -regular text - -#+BEGIN_SRC emacs-lisp -(+ 1 1) -#+END_SRC - -and more regular text -``` - -Now, move the pointer to with the blocks, tap `C-c C-c` and the code is evaluated. -The result will be appended just below the source code, in a `RESULT` block. - -You now know how to do literate programming in Emacs. -Create an Org document, add your narrative, add your source code and execute. -Simple, isn't it? - -By default, `Babel` allows only for execution of `emacs-lisp` mode, but it supports many more. -You can enable all supported via: - -```emacs-lisp -(org-babel-do-load-languages 'org-babel-load-languages - '((shell . t) - (js . t) - (emacs-lisp . t) - (clojure . t) - (python . t) - (ruby . t) - (dot . t) - (css . t) - (plantuml . t))) -``` - -There are even more provided as dedicated packages. - - -## Being faster {#being-faster} - -Typing `#+BEGIN_SRC` can become tedious pretty quick. -We can use the `org-tempo` package to make it much faster. - -```emacs-lisp -(require 'org-tempo) -(setq org-structure-template-alist - '(("s" . "src"))) -``` - -Now, we can create new block simply by taping `<s` and pressing tab. - -Org tempo supports many more blocks, you can refer to [the official manual](https://orgmode.org/manual/Structure-Templates.html). - - -## Joining the blocks together {#joining-the-blocks-together} - -In _strict_ Literate Programming sense, your _web/_ should not be where you execute code. -Instead, you should extract programmatic parts and run it separately - the process is called _tangling_. - -Babel bypasses this limitation with `noweb` mode, in which code blocks can reference each other. -First, you need to name your code blocks: - -```emacs-lisp -#+NAME: two -#+BEGIN_SRC emacs-lisp -(+ 1 1) -#+END_SRC -``` - -Then we can use it the result other code blocks - -```emacs-lisp -#+NAME: three -#+BEGIN_SRC emacs-lisp :noweb yes -(+ <<two>> 1) -#+END_SRC -``` - -Here, the `<<two>>` will be replaced with the result of block named `two`. -This makes the block `three` return the number `3`. - -This mode gives quite a lot more option. -You can read about them inside [manual](https://orgmode.org/manual/Noweb-Reference-Syntax.html). - - -## Running on remote machines {#running-on-remote-machines} - -To make it even _cooler_, Babel integrates with `Tramp` mode which allows for execution over ssh! -You can add a tramp-style header argument as `:dir` and the code will be executed over the established connection. - -```emacs-lisp -#+BEGIN_SRC shell :dir /user@host:~/ -rm -rf / -#+END_SRC -``` - -And boom - we've got a bomb. - - -## Babel as source for Emacs configuration {#babel-as-source-for-emacs-configuration} - -The most popular use case of Babel however is Emacs configuration. -You can have as many org files as you want, have the configuration inside `emacs-lisp` code blocks and use that as config. - - -### Loading files directly {#loading-files-directly} - -If your config isn't _very_ complicated, you can force Emacs to parse the files on boot. -To achieve that, add - -```emacs-lisp -(org-babel-load-file "~/.emacs.d/config.org") -``` - -To your `init.el`. - -What happens is, that Emacs will create a corresponding `config.el` (_tangle_) file and load it as a elisp file. -Just remember not to name your config as `init.org` as there will be naming conflict with `init.el`. - - -### Pre-tangling {#pre-tangling} - -If you don't want _tangling_ on boot time, but rather want to have it ready you can manually _org-babel-tangle_. -To achieve it, add a `tangle` header argument to all you code blocks: - -```emacs-lisp -#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/init.el -(+ 1 1) -#+END_SRC -``` - -And then, after any changes of the file run `org-babel-tangle` and your `init.el` will be up-to-date. -This is the approach [Prot](https://protesilaos.com/codelog/2023-12-18-emacs-org-advanced-literate-conf/) uses, but his config consists of over _17_000_ [sic!] lines of org file, so your mileage may vary. - - -## Links {#links} - -If you are interested in the subject, you can look at much more details sources: - -- [Official website](https://orgmode.org/worg/org-contrib/babel/intro.html) -- [Literate devops](https://howardism.org/Technical/Emacs/literate-devops.html) on Howardism -- [Advanced literate configuration](https://protesilaos.com/codelog/2023-12-18-emacs-org-advanced-literate-conf/) on Prot's website. -- [Cheat sheet](https://org-babel.readthedocs.io/en/latest/) - -[^fn:1]: you may argue and say that `magit` had bigger impact. - I disagree. - Magit made using git nicer and easier, but it is still the old, old git. - Babel changed the way we use the edit code, the way we think and how we work. diff --git a/content/emacs/whys-of-emacs.md b/content/emacs/whys-of-emacs.md deleted file mode 100644 index 2c62ee1..0000000 --- a/content/emacs/whys-of-emacs.md +++ /dev/null @@ -1,180 +0,0 @@ -+++ -title = """ - My "whys" for Emacs - """ -author = ["Michał Sapka"] -date = 2023-12-26T22:12:00+01:00 -categories = ["emacs"] -draft = false -weight = 2002 -abstract = "My reasons for using Emacs" -[menu] - [menu.emacs] - weight = 2002 - identifier = "my-whys-for-emacs" - parent = "varia" -+++ - -I have used many editors over the years. -I've started with Notepad, then moved to Notepad++, Sublime Text, IntelliJ, and VS Code. -Heck, I even Nova at some point. -But only two really stayed with me for longer - the first being Vim, the second Emacs. -Choosing Vim[^fn:1] seems like the logical option[^fn:2]. -It's an extremely popular editor with a huge community. - -But first: I **strongly** believe, that everyone working with computer, owe to themselves to spend some quality time with both, Vim, and Emacs. -Vim is amazing. -Modal editing is second to none when it comes to natural text processing. -They keybindings are close to perfect. -It requires some time to get used to, but let's not overstate that. -You can get semi-fluent in Vim in 2 weeks. - -And then there's Emacs. -I've tried it for a year. -I like it, but something felt off[^fn:3]. -Then, for a few months I have returned to using Neovim. -But here I am. -Using Emacs once again. -Why is that? - - -## License {#license} - -VSCode is released under non-free license[^fn:4], and therefore the code you can see is not necessary what you run. -In fact we know this, as VSCode spies on users[^fn:5], so it's an instant No for me. - -[Codium](https://vscodium.com/) exists as _libre_ version of VSCode, so it's an option. -However, it is not the same program as VSCode as incompatibilities exist, and the presence of plugins is limited[^fn:6]. -Any advancement of Codium is to the benefit of VSCode, and I hove problems with this. - -IntelliJ is completely closed-source, so it's also a no-go for me. - -Emacs[^fn:7] is released on GPL[^fn:8] -Vim is released under custom _libre_ license[^fn:9]. -Neovim is released under Apache license[^fn:10] -This means that the software is truly free. -I can see the entirety of codebase, not just the Lite version (like with VSCode). -I can redistribute it, I can copy, and share it without any limitations. -I can fork it, I can change it. -I can do almost whatever the hell I want it - as this was the basis of FSF. -This may be not important to you, but it is for me. - -I believe _libre_ software is a necessity. -Some people prefer _proprietary_ programs - some even don't see problems with _software as a service_. -But only _libre_ software allows for betterment of our _craft_. -Only by being able to freely modify and share software are we able to make the _craft_ better for future generations[^fn:11]. -I am paying for free software without any second thoughts by donating to some foundations. -Yes, I make my living creating _properties_ software, but I try to give back. -I refuse to _choose_ non-free software. -I am forced to use some, but whenever there is a choice, I will choose _free_. - -This leaves Vim and Emacs as two the two _important_ and _libre_ editors. -And with this, I have quickly removed almost all competition. -Now, how did I choose between those two? - - -## Different visions of computing {#different-visions-of-computing} - -Vim and Emacs represent two, vastly different visions of computing. - -Vim is a precompiled program with plugin capabilities. -This is the vision of computing that has won. -You get a binary (or, worse, a webpage) which makes your program do its thing. -You can _expand_ it using different plugins and configuration, but the _program_ is an unmovable object[^fn:12] - -Emacs is different. -We've got a very small _core_ written in C. -It handles basic functionalities, but by itself is close to useless. -But then we've got Lisp. -Almost all user-facing functionalities are written in Emacs specific dialect Lisp. - -And Lisp is the keyword here. -All of the codebase is exposed to the user, ready to be not only read (as with Vim) but also modified during runtime. -You can _change_ Emacs at a whim. - -VSCode tries the same, as it's a JavaScript-backed browser dressed as an editor. -Emacs therefore can be though as a Lisp-backed virtual machine dressed as an editor. -But the former was already rejected on the basis of being non-free (and I don't to run more Chromes that it's absolutely necessary), so it leaves me with Emacs. - -I am not a Lisp programmer, but I started learning it. -For now I like it more than JavaScript. - - -## Community {#community} - -I am not a people person, but people are what drive me. - -And this another aspect which drives me to Emacs. -There are folks who are happy with all-batteries-included distributions, like Doom Emacs. - -But there's a huge community of personalization maniacs. -People change every possible aspect of Emacs, because the program allows it. -Lisp is right there, and Emacs seems to be the last standing in the good fight to preserve _Literate Coding_ with _Literate Configuration_ people share. -To name just a few, who are my personal inspiration: - -- [Alex Maestas](https://se30.xyz/conf.html) -- [Pavel Korytov](https://sqrtminusone.xyz/configs/readme/) -- [Protesilaos Stavrou](https://protesilaos.com/emacs/dotemacs) -- [Derek Taylor](https://gitlab.com/dwt1/dotfiles/-/blob/master/.config/emacs/config.org?ref_type=heads) -- [Sacha Chua](https://sachachua.com/dotemacs/index.html) - -But at the same time the community is _small_ and I have a thing for smaller communities. -There are Vim users everywhere, but it's not that easy to find an Emacsian[^fn:13]. -But when you do, there are huge chances you've met someone at least interesting. -All Emacs users who I've ever meet in real life became my mentors to some degree. - -Also, what is **very** important to mention: despite popular joke, there is very little hate in the Emacs community. -People into Vim tend to tell mean joke about Emacs users[^fn:14] - and part of this joke is that the feeling is mutual. -It couldn't be further from the truth. -We all have great respect for other _libre_ editors and their users. -In fact, a lot of us move between Emacs and Vim on a daily basis. - -Maybe this is partly due to age[^fn:15]? -Emacs users tend to be, well, older. -Some have their configs evolving since the 90s! -They've already got a lot to show, so they don't need to be mean spirited? -I have no idea, but what I know is that they are a lovely bunch! - - -## Stability {#stability} - -Lastly, stability. -I use [BSD](/bsd/) because it doesn't change for the sake of change. -No SystemD will ruin a perfectly good workflow. - -Emacs is the same. -It's badge of honor - very rarely were there any bigger breaking changes. -When I used NeoVim, every few weeks something broke due to unfortunate update. -In Emacs on the other hand? -Not even once has something broke not from my own volition. - -Emacs comes with multiple competing solutions for the same problem, as people may rely on one of those. -If a new one comes along, the old ones are not replaced. -This increases the confusion of a new user, but it's very much appreciated. - - -## Summary {#summary} - -Emacs is the only empowering, libre and limitless editor I know. -It has an amazing community which values I share, and I want to participate in. -Also, it does not require constant maintenance because someone changed something. - -Using Emacs _sparks joy_. - -[^fn:1]: I don't distinguish between Vim and Neovim here. -[^fn:2]: amongst specific crowd at least. - But since you are here, it's quite possible that you are one of us. -[^fn:3]: mostly keybindings. I am now armed with Evil mode, the best replication of Vim in any editor. -[^fn:4]: <https://code.visualstudio.com/license> -[^fn:5]: "The software may collect information about you and your use of the software, and send that to Microsoft"[^fn:4] -[^fn:6]: <https://ruky.me/2022/06/11/im-switching-form-vs-code-to-vs-codium/> -[^fn:7]: I refer to "GNU Emacs" as "Emacs". -[^fn:8]: <https://www.gnu.org/philosophy/free-sw.html> -[^fn:9]: <https://github.com/vim/vim/blob/master/LICENSE> -[^fn:10]: <https://github.com/neovim/neovim/blob/master/LICENSE.txt> -[^fn:11]: I will need to write a dedicated article about it at some point, as all that would only mud this one. -[^fn:12]: I know you can modify the source code, but then you are running a fork and not the original program. -[^fn:13]: this also applies my other love, [BSD](/bsd/) -[^fn:14]: sadly, this was one of the biggest reasons I stopped following certain hyperactive Vim evangelist. - Let him become nameless. -[^fn:15]: there is a very funny movie about this <https://www.youtube.com/watch?v=urcL86UpqZc> |