#+TITLE: Emacs @ mms site #+AUTHOR: Michał Sapka #+URL: https://michal.sapka.me #+STARTUP: show2levels indent logdone #+HUGO_BASE_DIR: ~/ghq/vcs.sapka.me/michal-sapka-me/ #+HUGO_WEIGHT: auto #+HUGO_SECTION: emacs * Guides :@emacs: :PROPERTIES: :EXPORT_HUGO_MENU: :menu emacs :parent guides :END: ** DONE Emacs: Input Completiton in Emacs CLOSED: [2023-05-26 Wed 23:00] :PROPERTIES: :EXPORT_FILE_NAME: input-completition-in-emacs :EXPORT_HUGO_CUSTOM_FRONT_MATTER: :abstract Icomplete, IDO and FIDO :EXPORT_HUGO_MENU_OVERRIDE: :name "Input completition (Icomplete, IDO, and FIDO)" :EXPORT_HUGO_CUSTOM_FRONT_MATTER+: :aliases '(/2023/input-completition-in-emacs/) :END: 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 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:company]. The oldest one of those is /icomplete/[fn:icomplete] mode. It allows you to select from a list of choices incrementally[fn:hist], 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:ido] 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:helm] and Ivy[fn:ivy]. 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. [fn:company] [[https://company-mode.github.io/][Company-mode website]] [fn:hist] According to a [[https://www.reddit.com/r/emacs/comments/13szol7/comment/jltmaud/?utm_source=reddit&utm_medium=web2x&context=3][Reddit comment]] 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:icomplete] [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Icomplete.html][Icomplete documentation]] [fn:ido] [[https://www.gnu.org/software/emacs/manual/html_mono/ido.html][IDO documentation]] [fn:helm] [[https://emacs-helm.github.io/helm/][Helm website]] [fn:ivy] [[https://oremacs.com/swiper/][Ivy website]] *** Using FIDO To start FIDO mode run #+BEGIN_SRC emacs-lisp fido-mode #+END_SRC or, if you find a vertical list to be more readable, use #+BEGIN_SRC emacs-lisp fido-veritcal-mode #+END_SRC You can also customize variables to have it auto-load in your `init.el`: #+BEGIN_SRC emacs-lisp (fido-mode t) ;; or (fido-vertical-mode t) #+END_SRC 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 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 [[https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/icomplete.el][Icomplete source code]] *** Using Completions from Elisp The great thing about FIDO is that it, like Icomplete, uses Minibuffer API[fn:minibuffer], so you can simply: #+BEGIN_SRC emacs-lisp (completing-read "prompt: " '(("option1" 1) ("option" 2)) nil t "default query") #+END_SRC [fn:minibuffer] [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffer-Completion.html][Guide on Minibuffer completition]] ** DONE Emacs: Introduction to Literate programming CLOSED: [2024-01-30 Tue 19:10] :PROPERTIES: :EXPORT_FILE_NAME: literate-programing-in-emacs :EXPORT_HUGO_CUSTOM_FRONT_MATTER: abstract A short introduction into the idea of literate programming :EXPORT_HUGO_MENU_OVERRIDE: :identifier "litprog" :name "Literate programming" :END: *** Abstract In this article I give a short, theoretical introduction to the idea of Literate programming *** 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: #+begin_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:lee] #+end_quote 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:web]". The process of creating code is called "tangling", and generation of document is a "weave". *** An example Let's say we want to show the reader how to install DWM. We can create a document in a style: #+begin_quote 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: #+begin_src shell wget https://dl.suckless.org/dwm/dwm-6.4.tar.gz #+end_src then, simply extract it #+begin_src shell tar - xvzf dwm-6.4.tar.gz #+end_src And then we compile it #+begin_src shell cd dwm-6.4 doas make clean install #+end_src After the compilation finishes, add executable to your .xinit #+begin_src shell echo "exec dwm" >> ~/.xinit #+end_src #+end_quote 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 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. [fn:lee] [[https://web.archive.org/web/20170603045917/http://vasc.ri.cmu.edu:80/old_help/Programming/Literate/literate.html]["Literate Programming -- Propaganda and Tools", Christopher Lee, 1997]] [fn:babel] [[https://orgmode.org/worg/org-contrib/babel/intro.html][Org Babel]] [fn:jupyter] I know that Jupyter is not strictly a literate program, but it's close enough. [fn:web] this name was choosen, because at the time it was not in use related to computing. We're dealing with history here! *** 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:jupyter]) 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 [[https://michal.sapka.me/papers/literate_programming_knuth_1984.pdf][original Knuth's paper]]. ** DONE Emacs: Executing code in Org files with Babel CLOSED: [2024-02-07 Wed 21:23] :PROPERTIES: :EXPORT_FILE_NAME: org-babel :EXPORT_HUGO_CUSTOM_FRONT_MATTER: abstract A short introduction into the world if Org Babel :EXPORT_HUGO_MENU_OVERRIDE: :parent "litprog" :name "Literate programing in Org with Babel" :END: *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:magit]. It made folks not only love their Org Mode, but /live/ in it. In short: Babel allows for [[/emacs/literate-programing-in-emacs/][literate programming]] form within an Org document. [fn:magit] 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. *** 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: #+BEGIN_SRC emacs-lisp regular text ,#+BEGIN_SRC emacs-lisp (+ 1 1) ,#+END_SRC and more regular text #+END_SRC 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: #+begin_src 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))) #+end_src There are even more provided as dedicated packages. *** Being faster Typing =#+BEGIN_SRC= can become tedious pretty quick. We can use the =org-tempo= package to make it much faster. #+begin_src emacs-lisp (require 'org-tempo) (setq org-structure-template-alist '(("s" . "src"))) #+end_src Now, we can create new block simply by taping => 1) ,#+END_SRC #+end_src Here, the =<>= 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 [[https://orgmode.org/manual/Noweb-Reference-Syntax.html][manual]]. *** 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. #+begin_src emacs-lisp ,#+BEGIN_SRC shell :dir /user@host:~/ rm -rf / ,#+END_SRC #+END_SRC And boom - we've got a bomb. *** 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 If your config isn't /very/ complicated, you can force Emacs to parse the files on boot. To achieve that, add #+begin_src emacs-lisp (org-babel-load-file "~/.emacs.d/config.org") #+END_SRC 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 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: #+begin_src emacs-lisp ,#+BEGIN_SRC emacs-lisp :tangle ~/.emacs.d/init.el (+ 1 1) ,#+END_SRC #+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 [[https://protesilaos.com/codelog/2023-12-18-emacs-org-advanced-literate-conf/][Prot]] uses, but his config consists of over /17_000/ [sic!] lines of org file, so your mileage may vary. *** Links If you are interested in the subject, you can look at much more details sources: - [[https://orgmode.org/worg/org-contrib/babel/intro.html][Official website]] - [[https://howardism.org/Technical/Emacs/literate-devops.html][Literate devops]] on Howardism - [[https://protesilaos.com/codelog/2023-12-18-emacs-org-advanced-literate-conf/][Advanced literate configuration]] on Prot's website. - [[https://org-babel.readthedocs.io/en/latest/][Cheat sheet]] * Varia :@emacs: :PROPERTIES: :EXPORT_HUGO_MENU: :menu emacs :parent varia :END: ** DONE My "whys" for Emacs CLOSED: [2023-12-26 Tue 22:12] :PROPERTIES: :EXPORT_FILE_NAME: whys-of-emacs :EXPORT_HUGO_CUSTOM_FRONT_MATTER: :abstract My reasons for using Emacs :END: 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:nvim] seems like the logical option[fn:popular]. 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:off]. Then, for a few months I have returned to using Neovim. But here I am. Using Emacs once again. Why is that? [fn:popular] amongst specific crowd at least. But since you are here, it's quite possible that you are one of us. [fn:nvim] I don't distinguish between Vim and Neovim here. [fn:off] mostly keybindings. I am now armed with Evil mode, the best replication of Vim in any editor. *** License VSCode is released under non-free license[fn:vsclicense], and therefore the code you can see is not necessary what you run. In fact we know this, as VSCode spies on users[fn:vsctelemetry], so it's an instant No for me. [[https://vscodium.com/][Codium]] 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:codium]. 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:gnu] is released on GPL[fn:emacsgpl] Vim is released under custom /libre/ license[fn:vimlicense]. Neovim is released under Apache license[fn:nvimlicense] 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:libre]. 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? [fn:gnu] I refer to "GNU Emacs" as "Emacs". [fn:vsclicense] https://code.visualstudio.com/license [fn:vsctelemetry] "The software may collect information about you and your use of the software, and send that to Microsoft"[fn:vsclicense] [fn:codium] https://ruky.me/2022/06/11/im-switching-form-vs-code-to-vs-codium/ [fn:emacsgpl] https://www.gnu.org/philosophy/free-sw.html [fn:vimlicense] https://github.com/vim/vim/blob/master/LICENSE [fn:nvimlicense] https://github.com/neovim/neovim/blob/master/LICENSE.txt [fn:libre] I will need to write a dedicated article about it at some point, as all that would only mud this one. *** 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:os] 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. [fn:os] I know you can modify the source code, but then you are running a fork and not the original program. *** 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: - [[https://se30.xyz/conf.html][Alex Maestas]] - [[https://sqrtminusone.xyz/configs/readme/][Pavel Korytov]] - [[https://protesilaos.com/emacs/dotemacs][Protesilaos Stavrou]] - [[https://gitlab.com/dwt1/dotfiles/-/blob/master/.config/emacs/config.org?ref_type=heads][Derek Taylor]] - [[https://sachachua.com/dotemacs/index.html][Sacha Chua]] 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:bsd]. 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:vimjoke] - 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:paah]? 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! [fn:bsd] this also applies my other love, [[/bsd/][BSD]] [fn:vimjoke] sadly, this was one of the biggest reasons I stopped following certain hyperactive Vim evangelist. Let him become nameless. [fn:paah] there is a very funny movie about this https://www.youtube.com/watch?v=urcL86UpqZc *** 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 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/. * Local vars # Local Variables: # org-num-skip-tags: ("UNNUMBERED") # End: