PeMt

Emacs Escapade

Just a place for me to pour my thoughts about Emacs editor, about which I have been on the fence for quite some time now.

Why use Emacs?

One config to rule them all

The ability to have one configuration file for every little "subprogram" or "mode" is certainly a huge advantage. Why use a dozen of different programs when Emacs can do the job just fine. (Not to mention I am really fond of configuring various pieces of software)

Unified interface

Emacs fundamental keybindings and way to interact with text mostly stay the same throughout different modes. Fundamental movement keys work exactly the same way, no matter whether you are in interactive shell mode, directory listing, programming language mode or even a browser. Only thing that may change are semantics and how Emacs understands different pieces of text that are inside a given "buffer".

Cool stuff

Eshell

The ability to edit the command output directly, as if it were a normal text file is really darn neat. Being able to easily copy and edit command output without the use of something like Tmux means you can clean up or parse your command backlog really quickly. I gotta add something along the lines of `[Alt-s]` keybind you can find in Fish shell, where it appends `sudo` or `doas` to the beginning of the command. Update from 26/06/2025: here we are!
(defun eshell-sudo-toggle ()
  (interactive)
  (save-excursion
    (move-beginning-of-line 1)
    (let '(prefix (buffer-substring-no-properties (point) (+ 5 (point))))
      (if (string= "sudo " prefix)
	  (delete-char 5)
	(insert "sudo ")))))

Language and project support

Emacs supports a couple of LSP implementations. The one I am currently using is called `eglot` and it worked pretty much perfectly with Deno LSP for JavaScript/TypeScript files. I haven't been able to use it with SQL LSP, however I found out that built-in tools that simply allow you to connect to your database and execute SQL statements in a REPL-like environment work quite well! I found that Markdown and Gemini language support is quite excellent, with a bunch of useful functions and things bundled into respectively `markdown-mode` and `gemini-mode`. Built-in Emacs project management tool also works just fine, though I haven't gotten too deep into it. I've used it mostly as a way to quickly switch between project files. Docker support via `docker` package also works really well. Being able to spin up containers quickly with nice integration with `docker compose` is soooo good. The commands can be interactively customized with neatly documented prompts and simple keybindings that toggle and change each option. Also, **magit rules**. I really enjoy how intuitive and pleasant to use it is.

Customization

I have a tendency to customize my tools and programs a lot and then end up not using them as much, so I am thankful to say that I have been rather conservative with the way I extend Emacs. I recall once using Org mode to make a massive config file, but now I am quite happy with plain old `init.el` file. Albeit, some sort of working outline mode would be helpful~ I miss Vim's feature to incremement number near point so I guess it is high time to implement it myself!~
(defun number-at-point-modify (&optional arg)
  "Increment a number at point.
With prefix argument ARG, increment/decrement it by that number"
  (interactive "p")
  (if (not (thing-at-point 'number))
      (message "Not a number")
    (let* ((num-thing (bounds-of-thing-at-point 'number))
           (num-start (car num-thing))
           (num-end (cdr num-thing))
           (num (string-to-number (buffer-substring-no-properties num-start num-end))))
      (replace-region-contents
       num-start num-end
       (lambda ()
         (number-to-string
          (+ num arg)))))))
I liked the idea of switching between Dired buffers via [Tab] key, just like in other two-pane file managers. Here's really crude function to do just that!
(defun dired-switch-to-other-window ()
  "Switch to other window if it is also in `dired-mode'"
  (interactive)
  (let* ((other-w (cadr (window-list-1)))
         (mode (buffer-local-value 'major-mode (window-buffer other-w))))
    (if (eq mode 'dired-mode)
        (select-window other-w))))