This is more or less my vanilla-ish Emacs playground. I start from nano-emacs. It’s pretty and pretty useful. But expect it to veer pretty far from that base over time.
NOTE
There’s bound to be a lot of things that make you, the Emacs veteran, wonder “why didn’t he just do X?” The likeliest options:
I didn’t know X was an option
I saw X but wanted to wait until I understood it
That last is particularly likely. I keep getting reminded that outsmarting yourself is a major hazard of Emacs configuration.
I’ll add org-pymacs-nodejs-todoist-roam-lsp-mode later. Maybe. I may not even need it.
Foundations
Give Emacs some breathing room
max-specpdl-size sets the upper limit for how many variable bindings and unwind-protect Emacs allows. max-lisp-eval-depth says how deep we can get into a recursive function call.
I got the RAM so let’s go past the respective defaults of 1600 and 800.
And of course I’m sure to screw something up so let’s make sure the debugger is enabled for when I do.
Enable local lisp
Simplify reloading my config
I putter with this config marginally less than I did initially - progress! - but enough that restarting Emacs for every config tweak gets tedious.
One of the ideas I grabbed from Vianney Lebouteiller’s Emacs config.
But if I’m using straight.el I better disable package.el during the early init
stage.
Bootstrap straight.el
Boilerplate from the straight.el documentation.
Integrate with use-package
I tried to avoid use-package here for a more “minimal” setup. That did not work. Since straight.el plays nice with use-package, let’s let it do that.
General Usability
General guidelines for text handling
Where to put the fill column marker for line wraps, how many pixels to put between lines, stuff like that.
invoke M-x without Alt
I read Steve Yegge’s effective-emacs a long time ago — back when it was an internal Amazon blog. Applied his suggestion to invoke X-m with C-x C-m and that’s been part of my Emacs muscle memory ever since.
Make a few adjustments for running on macOS
Make sure the macOS Emacs GUI app picks up environment variables.
macOS doesn’t use GNU Coreutils and of course its ls isn’t what
dired expects. Adjust for that.
visual-fill-column for a nice soft wrap
Aesthetics
Fonts
The Roboto Mono font that NANO wants is not part of any *roboto* package I
found in Pop! OS repositories. Ended up going to Font Library for a direct
download.
Because I’m the kind of person I am: setting the nano theme colors to match my
own tacky tastes. Maybe not tacky but certainly not as refined as the author of
nano.
This particular set of colors comes from the Spaceduck theme.
Set up font faces
I feel comfortable loading nano-faces for font rules now that I’ve defined my colors.
Will need to fuss a bit more in a second though.
Want to overload some of the defaults, though. nano-emacs does not
like to show bold text when using Fantasque Sans Mono.
Let nano theme everything
nano-theme maps those custom faces to pretty much everything everywhere.
Pretty nice.
Except for this little thing where it disables bold for graphical displays? I think? I’m still learning how all this works.
I know I like bold, though. And italics, now that you mention it.
Once I have my base established, I should be able to load the nano theme.
Load nano defaults
Enable nano session handling
Enable the nano modeline
One of my favorite bits really.
Enable nano key bindings
C-x k
kill current buffer without asking
M-n
open a new frame
M-`
switch to other frame
C-x C-c
delete the current frame; exit if no frames remain
C-c r
interactive select from recent files
<M-return>
toggle maximization of current frame’ not sure if I like this one; it confuses org muscle memory, and if I want “maximized” I usually toggle tiling in the window manager
nano Counsel integration
nano-counsel.el is small. I’ll just map its logic directly to some use-package magic.
I need to give myself a little context here.
Ivy, Counsel, and Swiper
flexible, simple tools for minibuffer completion in Emacs
These are technically separate packages developed together in the swiper repo.
Ivy
an alternative completion framework for Emacs
Counsel
Ivy-enhanced alternatives to common Emacs commands
Swiper
Ivy-enhanced alternative to Isearch
Loading nano-counsel failed with complaints about missing smex.
Smex provides enhancements to M-x behavior, such as an interface to recent and commonly used commands.
Since I want my foundation to be a clean Nano experience, I install smex as well.
nano splash
Life management with Org
Okay here we go. Building up my org-roam experience while keeping Deft handy for the longer, more intentional notes.
File locations
I work this out piecemeal, as some of the files and folders build on
what’s been defined before.
First: what’s the top level of everything? That depends on whether I’m
in a UNIX-like system or playing with the native Windows version of
Emacs.
Trying an experiment where first we look for a local ~org/ folder and
use that if found, otherwise going with my actual default of
~/Dropbox/org. Trying to shift over to git-synchronized Org files
instead of Dropbox-synchronized, but that change will take a bit to
percolate through all my systems.
That’s enough to define most of the files I need.
Oh, one more thing. I want to include org-roam files in my Org
agenda. I found helpful instructions, but I’m not adding that code to
my config until I understand it. Maybe if I follow the link to the
beginning of the post series and start there.
What a novel idea.
But today? With my small collection of org-roam notes, I can get away
with directly including them in my agenda searches.
Tumblelogging with ox-hugo
I started an experiment with using Org to drive a tumblelog at Random Geekery Life. Tumblelog is an older term for a blog that mainly consists of dumping whatever thoughts, links, or just whatever. Sort of like Twitter or Tumblr, but on my own site and less constrained than a tweet-length microblog. Someday I may put more words elsewhere and replace this all this explanatory text with a link.
For now I build the visible tumblelog as a static site with Hugo. It’s quick and it’s familiar.
Org enters the scene with a single file within my Hugo site.
That file contains all the content for the tumblelog, but the important part here is a function to dynamically generate a filename for ox-hugo based on the current time.
Hugo configuration determines permalinks from post dates, which ox-hugo derives from task completion timestamps. If I want to keep all the times for an entry in sync I manually edit, but it’s not a big deal yet. C-t d muscle memory so far is quicker than figuring out how to automate that process.
The actual filename gets ignored, but the epoch timestamp keeps each output file unique at my normal human rate of adding entries.
This also squeaks me past the fact that I came up with this version of the template after I already had a few entries.
Then when I’m building org-capture-templates I create a datetree entry for tumblelogging.
Custom keywords
A process vagiuely similar to GTD but my brain insists on its own task
classifications.
LATER
I need to do it, but it can wait (or it’s waiting on something)
NOW
I got everything I need to do this
MAYBE
An idea, suggestion, or action that I may or may not want to to
More to keep my org-roam-ui graph in order than for publishing, but
hopefully it’ll come in handy there too.
Putting it all together
Additional Org tools
Deft
The perfect solution for knowledge management varies by context. But the core thing really needed: someplace to drop my notes where I can find them when I need them.
Deft provides exactly that. And since Org mode is the main reason I load Emacs, my ~/org folder is where Deft will look for notes.
I don’t want org-roam notes obscuring the more persistent notes in my Org folder. Better ignore them. Also the org-brain stuff until I have a good handle on that.
Helpful hint when enabling deft-recursive: =../ is one of the entries in your directory listing, and Deft will do its darndest to follow it if you forget to include it in deft-recursive-ignore-dir-regexp (set to "\\(?:\\.\\|\\.\\.\\)" by default).
This can lead to all sorts of recursive headaches, so don’t forget!
Of course I’ll end up tweaking it. But to get me started?
“Ask deft about my notes” is more than sufficient.
I like to always see backlinks as a side-window of my current view.
Something is off with my :bind and :bind-keymap settings for org-roam.
Until I learn enough to fix that, I’ll make a global binding for the
one I care about: going to today’s daily note.
org-roam-ui
For the pretty. Sometimes I enable org-roam-ui-mode on load.
ox-hugo
Although ox-hugo isn’t required to use Hugo with Emacs, it sure does simplify things.
Project management with Projectile and friends
Projectile plus a .dir-locals.el file seems like the right way to
handle development projects without bumping into everything else.
lsp-mode and related for an IDE experience
lsp-mode adds support for Microsoft’s Language Server Protocol. Hypothetically that means easier setup of commonly desired
features like linting and autocompletion.
lsp-mode uses YASnippet for abbreviation and expansion.
nano-modeline and lsp-mode’s breadcrumb trail wrestle with each other
for space on that top line. Maybe someday I can figure out how to
stack them. Until then, I like the modeline and its placement more
than I like the breadcrumb.
Programming Languages
Python
Pyenv for Python versions.
I manage my projects with Poetry. poetry.el offers a nice Magit-like
interface to managing and maintaining Poetry projects.
In particular, it might simplify venv handling when I get to linting
tools and language server providers.
Which Key?
which-key adds a completion panel for commands. That helps me learn
the many Emacs key maps.
Treemacs
Treemacs is a file explorer sidebar. That part is kind of “meh” for
me. The outliner provided by lsp-treemacs interests me much more.
To get Treemacs and nano playing nice I had to comment out line 515 of
nano-modeline.el in my local copy of nano.