I like the rendering of curved quotes using [[help:text-quoting-style][text-quoting-style]], because it improves the readability of documentation strings in the =∗Help∗= buffer and whatnot.
When typing prose in Org documents, I need to [[file:ha-org-word-processor.org::*Typographic Quotes][do something else]] for rounded quotes and ellipsis.
After reading [[https://irreal.org/blog/?p=12139][Jon Sander’s essay]] as well as [[https://mbork.pl/2024-04-27_Emacs_everywhere][Marcin Borkowski's essay]], I decided to try out Tecosaur’s [[https://github.com/tecosaur/emacs-everywhere][Emacs Everywhere]] approach:
This package is /called outside of Emacs/, so I bound a keybinding to iCanHazShortcut:
#+begin_src sh
emacsclient --socket-name personal --eval "(emacs-everywhere)"
#+end_src
When you type ~C-c C-c~ to close a window, it /doesn’t always/ paste back into the original window, but the text is saved to the clipboard, a quick paste works. And now, I don’t scream when I need to use those Electron apps, like Slack and Discord.
Always spaces and never tabs. Note that we use =setq-default= since [[elisp:(describe-variable 'indent-tabs-mode)][indent-tabs-mode]] is a /buffer-local/ variable, meaning using =setq=, sets it for /that buffer file/. We want this globally the default:
When I push changes to my files to Gerrit and other code review, I don’t want trailing spaces or any tabs to appear, so let’s fix all files when I [[elisp:(describe-variable 'before-save-hook)][save them]]:
The [[https://www.emacswiki.org/emacs/RecentFiles][recentf]] feature has been in Emacs for a long time, but it has a problem with Tramp, as we need to turn off the cleanup feature that attempts to =stat= all the files and remove them from the =recent= accessed list if they are readable. The requires recentf to open up a remote files which blocks Emacs at the most inopportune times… like when trying to reboot the machine.
#+begin_src emacs-lisp
(use-package recentf
:straight (:type built-in)
:config
(setq recentf-auto-cleanup 'never) ;; disable before we start recentf!
(recentf-mode 1))
#+end_src
*** File Backups
While I use git as much as I can, sometimes Emacs’ built-in file backup and versioning feature has saved me for files that aren’t.
As [[https://philjackson.github.io//emacs/backups/2022/01/31/keeping-backups-of-every-edited-file/][Phil Jackson]] mentioned, Emacs has a lot of variations to its file backup strategy, and either change the [[help:backup-directory-alist][backup-directory-alist]] to put individual file backups elsewhere, e.g.
Might be nice to have a =url-download= function that just grabs a file from a website without fuss (or other dependencies). Easy enough to prototype, but dealing with errors are another thing …
#+begin_src emacs-lisp
(defun url-download (url dest)
"Download the file as URL and save in file, DEST.
Note that this doesn't do any error checking ATM."
(interactive "sURL: \nDDestination: ")
(let* ((url-parts (url-generic-parse-url url))
(url-path (url-filename url-parts))
(filename (file-name-nondirectory url-path))
(target (if (file-directory-p dest)
(file-name-concat dest filename)
dest))
(callback (lambda (status destination)
(unwind-protect
(pcase status
(`(:error . ,_)
(message "Error downloading %s: %s" url (plist-get status :error)))
This function can be called interactively with a URL and a directory (and it attempts to create the name of the destination file based on the latter-part of the URL), or called programmatically, like:
After using Ivy, I am going the route of a =completing-read= interface that extends the original Emacs API, as opposed to implementing backend-engines or complete replacements.
The [[https://github.com/minad/vertico][vertico]] package puts the completing read in a vertical format, and like [[https://github.com/raxod502/selectrum#vertico][Selectrum]], it extends Emacs’ built-in functionality, instead of adding a new process. This means all these projects work together.
My issue with Vertico is when calling =find-file=, the Return key opens =dired=, instead of inserting the directory at point. This package addresses this:
This fuzzy completion style is like the built-in =flex= style, but has a better scoring algorithm, non-greedy and ranks completions that match at word; path component; or camelCase boundaries higher.
While flexible at matching, you have to get the /order/ correct. For instance, ~alireg~ matches with [[help:align-regexp][align-regexp]], but ~regali~ does not, so we will use =hotfuzz= for scoring, and not use this as a completion-project (see the =fussy= project below).
While the space can be use to separate words (acting a bit like a =.*= regular expression), the [[https://github.com/oantolin/orderless][orderless]] project allows those words to be in any order.
The [[https://github.com/jojojames/fussy][fussy]] project is a fuzzy pattern matching extension for the normal [[help:completing-read][completing-read]] interface. By default, it uses [[https://github.com/lewang/flx][flx]], but we can specify other sorting and filtering algorithms.
How does it compare? Once upon a time, I enjoyed typing ~plp~ for =package-list-packages=, and when I switched to [[https://github.com/oantolin/orderless][orderless]], I would need to put a space between the words. While I will continue to play with the different mechanism, I’ll combine =hotfuzz= and =orderless=.
Persist history over Emacs restarts using the built-in [[https://www.emacswiki.org/emacs/SaveHist][savehist]] project. Since both Vertico and Selectrum sorts by history position, this should make the choice /smarter/ with time.
The [[https://github.com/minad/marginalia][marginalia]] package gives a preview of =M-x= functions with a one line description, extra information when selecting files, etc. Nice enhancement without learning any new keybindings.
The [[https://github.com/justbur/emacs-which-key][which-key]] project shows a menu of available key-bindings based on what you have already typed. For instance, if you remember that Org Goto function (like most Org-related functions) began with ~C-c~, after typing that sequence, all possible keybindings and their functions are shown. Useful for discovering new features.
The [[https://gitlab.com/ideasman42/emacs-undo-fu][undo-fu]] isn’t much to the project (that’s a good thing), but It doesn’t /cycle/ around the redo ring, which can be annoying.
This extends the =use-package= to include a =:general= keybinding section.
Since I seldom remember keybindings, or even function names, for major-modes, I pull them all together into a nice table using the [[https://github.com/jerrypnz/major-mode-hydra.el][Major Mode Hydra]] project:
In =org-mode=, ~TAB~ calls [[help:org-cycle][org-cycle]], which, in the context of typing text, calls the binding for ~TAB~, which is the [[help:indent-for-tab-command][indent-for-tab-command]]. If the line is /indented/, I can complete the word:
This calls [[help:completion-at-point][completion-at-point]]. This code (from mini-buffer) doubles with the other [[Vertico][completing processes]] (like [[help:completing-read][completing-read]]) and presents choices based on a series of functions (see [[https://with-emacs.com/posts/tutorials/customize-completion-at-point/][this essay]] for details). This will call into the CAPF function list (see the variable, =completion-at-point-functions= and the [[file:ha-programming.org::*Cape][Cape]] section for details).
*** Hippie Expand
The venerable [[help:hippie-expand][hippie-expand]] function does a better job than the default, [[help:dabbrev-expand][dabbrev-expand]], so let’s swap it out (see this [[https://www.masteringemacs.org/article/text-expansion-hippie-expand][essay]] by Mickey Petersen) with its default key of ~M-/~ (easy to type on the laptop) as well as ~C-Tab~ (easier on mechanical keyboards):
Details on its job? We need to update its [[help:hippie-expand-try-functions-list][list of expanders]]. I don’t care much for [[help:try-expand-line][try-expand-line]], so that is not on the list.
#+begin_src emacs-lisp
(setq hippie-expand-try-functions-list
'(try-complete-file-name-partially ; complete filenames, start with /
In the shell, IDEs and other systems, the key binding is typically ~TAB~. In modes other than =org-mode=, ~TAB~ re-indents the line with [[help:indent-for-tab-command][indent-for-tab-command]], but I find that I want that feature when I’m in Evil’s =normal state= and hit the ~=~ key, so changing this sounds good. But why not /have both/?
The default completion system either inserts the first option directly in the text (without cycling, so let’s hope it gets it right the first time), or presents choices in another buffer (who wants to hop to it to select an expansion).
After using [[http://company-mode.github.io/][company]] for my completion back-end, I switch to [[https://github.com/minad/corfu][corfu]] as it works with the variable-spaced font of my org files (also see [[https://takeonrules.com/2022/01/17/switching-from-company-to-corfu-for-emacs-completion/][this essay]] for my initial motivation).
Since I have troubles installing Doom’s [[https://github.com/hlissner/doom-snippets][collection of snippets]], lets use the [[http://github.com/AndreaCrotti/yasnippet-snippets][yasnippet-snippets]] package:
The [[https://www.emacswiki.org/emacs/AutoInsertMode][auto-insert]] feature is a wee bit complicated. All I want is to associate a filename regular expression with a YASnippet template. I'm stealing some ideas from Henrik Lissner's [[https://github.com/hlissner/doom-emacs/blob/develop/modules/editor/file-templates/autoload.el][set-file-template!]] macro, but simpler?
For all other functions that use regular expressions, many call the function, =read-regexp=, and thought it would be helpful if I could type =rx:…= and allow me to take advantage of the =rx= macro.
#+begin_src emacs-lisp
(defun read-regexp-with-rx (input)
"Advice for `read-regexp' to allow specifying `rx' expressions.
If INPUT starts with rx: then the rest of the input is given to
the `rx' macro, and function returns that regular expression.
While I grew up on =Control S=, I am liking the /mental model/ associated with the [[https://github.com/abo-abo/avy][avy project]] that allows a /jump/ among matches across all visible windows. I use the ~F18~ key on my keyboard that should be easy to use, but ~g o~ seems obvious.
If you hit the following keys /before/ you select a target, you get special actions (check out this [[https://karthinks.com/software/avy-can-do-anything/][great essay]] about this understated feature):
- ~n~ :: copies the matching target word, well, from the target to the end of the word, so match at the beginning.
- ~x~ ::=kill-word= … which puts it in the kill-ring to be pasted later.
- ~X~ ::=kill-stay= … kills the target, but leaves the cursor in the current place.
- ~t~ ::=teleport= … bring the word at the target to the current point … great in the shell.
- ~m~ ::=mark= … select the word at target
- ~y~ ::=yank= … puts any word on the screen on the clipbard.
- ~Y~ ::=yank-line= … puts the entire target line on the clipboard.
- ~i~ ::=ispell= … fix spelling from a distance.
- ~z~ ::=zap-to-char= … kill from current point to the target
I’m not thinking of ideas of what would be useful, e.g. ~v~ to highlight from cursor to target, etc.
The [[info:emacs#Goto Address mode][Goto Address]] mode (see this [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Goto-Address-mode.html][online link]]) turns URLs into clickable links. Nice feature and built into Emacs, but it requires using the mouse or moving to the URL and hitting ~Return~ (if you like this idea, check out [[https://xenodium.com/actionable-urls-in-emacs-buffers/][Álvaro Ramírez's configuration]] for this).
I appreciated [[https://github.com/abo-abo/ace-link][ace-link]]’s idea for hyperlinks on Org, EWW and Info pages, as it allowed you to jump to a URL from any location on the screen. The [[https://github.com/noctuid/link-hint.el][link-hint]] project does this, but works with more types of files and links:
Can I open a link in another window? The idea with this is that I can select a link, and with multiple windows open, I can specify where the =*eww*= window should show the link. If only two windows, then the new EWW buffer shows in the /other/ one.
Magnar Sveen's [[https://github.com/magnars/expand-region.el][expand-region]] project allows me to hit ~v~ in =visual= mode, and have the selection grow by syntactical units.
The built-in =isearch= is fantastically simple and useful, but the [[https://github.com/kickingvegas/cc-isearch-menu][cc-isearch-menu]] helps expose some /buried/ features.
The idea, is that you can start a search with ~C-s~ (or even ~s-f~ … er, ~Command-f~ on the Mac), and type some letters. Hitting ~C-s~ goes to the next occurrence of what you’ve typed, but if you hit ~Command-g~, a menu appears allowing you to pull in the rest of the word or symbol you are looking at, or edit it completely.
While editing any file on disk is easy enough, I like the mental context switch associated with a full-screen window frame showing all the buffers of a /project task/ (often a direct link to a repository project, but not always).
Since I wasn’t using all the features that [[https://github.com/bbatsov/projectile][projectile]] provides, I have switched to the built-in =project= functions.
A /workspace/ (at least to me) requires a quick jump to a collection of buffer windows organized around a project or task. For this, I'm basing my work on the [[https://github.com/nex3/perspective-el][perspective.el]] project.
Let's describe a list of startup project workspaces. This way, I don't need the clutter of the recent state, but also get back to a state of mental normality.
Granted, this list is essentially a list of projects that I'm currently developing, so I expect this to change often.
For details on using GnuPG in Emacs, see Mickey Petersen’s [[https://www.masteringemacs.org/article/keeping-secrets-in-emacs-gnupg-auth-sources][GnuPG Essay]].
Also, as [[https://www.bytedude.com/gpg-in-emacs/][bytedude]] mentions, I need to use the =epa-pineentry-mode= to =loopback= to actually get a prompt for the password, instead of an error. Also let's cache as much as possible, as my home machine is pretty safe, and my laptop is shutdown a lot.