Emacs Megathread:

I've been wanting to write down everything I love about emacs. Over the past five years I've picked up a lot of neat tricks. Individually each one is cool, but together they're even cooler, and I want to write them all down in the same place.
It would take a book to really do justice to what I have in mind. And I think I'll write that book eventually. This isn't that book, but it is my first attempt at dumping these ideas out on paper with a minimal amount of organization.

Without further ado...
*Org Mode*

This was the killer app that made me stick with emacs. I actually can't imagine working on stuff w/out using org mode. It's the only project management tool that will work out long term for me, since it lives in the same place as my code.
Some things about org mode:

- Doesn't impose structure. You shape it to your workflow
- Built-in time tracking, spreadsheets, executable code blocks, tags, task scheduler
- It's only text. No proprietary file format, just text. Timeless
- Built-in export to markdown, latex, html
Some examples of how I use org-mode for managing projects:
I typically make an org file per project. So for my Staq.js project I have a file called staq.org. The top-level bullet is the name of the project, then I have two sub-bullets called "Notes" and "Build".
Notes I usually use for thinking through some problem by writing about it. Build I use for task logistics. I sub-bullet a header for the active sprint and one to archive old sprints.
That clocktable line up top expands to a table that reports how much time I've spent on things. Within each task I record time log statements (made easy by org-mode), and the clock table aggregates and formats them.
How do those TODO items end up under the right sprint header? Sometimes I'm in the org file when I come up with the task, but if I'm not, I use org-capture. org-capture lets you record a quick task description, and then files the item away for you in a pre-determined location.
It's helpful to have org-capture bound to a convenient global key chord. Mine is "SPC a o c". And my refile location is an org file called inbox.org.
When I press "SPC a o c" anywhere in emacs, a capture buffer pops up where I record the name and any pertinent details about the task. When I'm done, pressing ", ," refiles the new item to inbox.org.
Ok cool so now there's a task in inbox.org. How do I get it into my sprint bullet?

This is where org-agenda comes in.
org-agenda is a little application that shows you what's on your agenda. It's heavily customizable, just like everything else in Emacs. You can treat it kind of like a command center for your todos.
I have mine set up with three sections. Top: what's on the agenda for today?; Middle: what's in the inbox and needs to be refiled? Bottom: what are all the pending tasks for different side projects I have going on?
To refile a task from the inbox, I move to the task row, type "r", and then pick a header to refile it under. The headers are generated from the files under the org-refile-targets variable.
There are lots of other cool things you can do in org mode, but these are the features I use all the time. I'll probably do other threads about other org mode things at some point. For now, let's move on.
The next killer app (there are many!) I discovered in emacs was magit, the best git client in the Milky Way🌌 After getting used to the basic git workflow in magit, there's really no question of ever going back to a command line git client, or anything else.
In magit you don't have to type out git commands, or point and click. You just hit brief key chords to cast powerful git spells. Some examples:
Bring up a colorized network graph of commit history with "l -c l".
View file level diffs by hovering over a file and typing "TAB".
Stage a change with "s".
Unstage with "u"
Commit currently staged changes with "c c".
- Push to remote with "p p"
- Fetch from origin with "f u"
- Checkout file from another branch with "O f"
- Stash on current branch with "z z"
- Pop current stash with "z p"
There is no better way to use git that I know of.
What's next?? If I'm going by level of impact on my workflow, it's a tough choice between helm and projectile. But since I'll get to both eventually, it doesn't make much difference and so I'll go alphabetically.
*Helm* is billed as "a framework for incremental completions and narrowing selections." It's a package that you use for finding things. Need to run a function? Helm. Need to find a file? Helm. Need to open a project? Helm. It's awesome. Let's see it in action.
First the basics. The default way to open a file in Emacs is with "C-x C-f". The interface for that command is... not great. You pretty much have to type in the exact file name, and in order to bring up a list of available files in the current directory, you need to TAB twice...
And even then, it just shows you what's available and you have to type it in.
Alright, so what's so much better about helm? The function `helm-find-files` brings up a buffer that lists files in the current directory. You can either navigate to the file you want with arrow keys (or better, "C-j" and "C-k"), or type in a fuzzy pattern to narrow the search.
What else can helm do? We can run functions with `helm-M-x`. Again, the default UX Emacs provides here has zero discoverability. With helm, we get a buffer showing commands that match the current fuzzy search. In this clip I run a function to format the current json buffer.
Now, there's more helm stuff I want to talk about, but these parts of my workflow sort of blur the line between helm and the next package, projectile. So I'll just introduce projectile now and show some examples of how I use the two packages together.
projectile.el is for project interaction. Mostly I use it for moving around inside a project, or moving between projects. projectile lets you jump to another file or directory inside the current project or a different one with just a few keystrokes.
projectile uses the presence of certain files to define the root of a project. Most version control repos are supported out of the box, so for example a directory with a .git folder is considered to be the root of a project, and everything underneath it is inside the project.
I don't think I've ever used projectile on its own. I've always used it in combination with helm, through the package helm-projectile, which provides helm integration for projectile. These next examples use commands from the helm-projectile package.
We can switch into a project from anywhere with `helm-projectile-switch-project`. This command brings up a buffer where we can use a fuzzy search to select from a list of projects. Once a project is selected, helm lets us use another fuzzy search to open a file from the project.
Here's another mega-useful combo of helm and projectile: `helm-projectile-rg` uses the ripgrep tool to search for strings inside a project. This package runs a string search on the current project, and then displays the results in a helm buffer for selection.
In this clip I use `helm-projectile-rg` to search my project for all occurrences of "auth". I preview a couple results by moving to them and hitting TAB. Then I hit "Alt-g" to provide a glob pattern that narrows the search to only .js files.
There are other options for doing string search with helm and projectile. I've used helm-grep and helm-ag (which use grep and ag, respectively), but in my experience ripgrep performs better than both.
Just like with string search, helm and projectile can be combined to search for files inside a project. I use `helm-projectile-find-file` to open files from a helm completion buffer. Just typing a small portion of the file name is usually enough to narrow down the selection.
The next topic I want to touch on is not a package, but imo is a skill that is crucial to effective use of emacs. Window management. Emacs windows are what is known in other tools as panes. Basically horizontal or vertical splits of the same desktop window.
Keeping multiple files and buffers open simultaneously was a major paradigm shift that I quickly grew to enjoy when I switched from vim to emacs. Editing an html template file and the corresponding JS controller? Pop them open side by side with a couple keystrokes.
Here are what I consider the fundamental window management operations, and the keybindings I have them bound to for convenience.
Open a window below the current one: `split-window-below` - "SPC w s"
Open a window to the right of the current one: `split-window-right` - "SPC w v"
Close the current window: `delete-window` - "SPC w d"
Make the current window the only window: `delete-other-window` - "SPC w m"
Being able to quickly move between open windows is important. Whatever your bindings are, you should be able to run them without leaving the home row. Here are mine:

- windmove-left: "SPC w h"
- windmove-right: "SPC w l"
- windmove-down: "SPC w j"
- windmove-up: "SPC w k"
In my opinion, that covers window management. These motions will eventually become second nature, and you'll feel one big step closer to emacs being the ideal command center.
Alright, now the thing that I spend the most time in emacs doing is writing code. I write code for the web, which usually means running a local frontend server, possibly some backend server like a python process, and maybe even a database in a docker container.
These next few packages all tie together to support my code writing workflow. They make it possible for emacs to support most features that you would expect from a typical IDE, including code completion, type checking, linting, auto-formatting, building, and testing.
We'll start with flycheck. flycheck is the emacs package for syntax checking. It uses external tools to support more than 40 different languages out of the box.
Running flycheck in a buffer will underline syntax issues, and put markers in the fringe. Moving point to the underline will cause the specific error to show up in the mini buffer. You can also open a dedicated flycheck buffer that lists all the errors in the file.
Flycheck will automatically pick up on the file type and use the associated syntax checker. Some languages support multiple syntax checker options. For example, flycheck can use ESLint, JSHint, or Standard to check JavaScript files.
Not only does flycheck work with linters, it works with language servers that offer more sophisticated checking features. To integrate one of those, like TypeScript Language Server, we need to introduce another emacs package called lsp, which stands for "language server protocol"
lsp is not the only popular language server package, there is also eglot, which markets itself as a lightweight alternative to lsp. I use lsp, however, so that's what we'll see here.
lsp can be a little tricky to get working, since there is an external dependency in the language server. I primarily use lsp with JavaScript, and so I use the typescript-language-server available from npm.

Install globally w/: npm install -g typescript-language-server
In order to get the lsp package running for a particular file type, add a mode hook that runs (lsp) when loading the mode for that file type.

ex.
(add-hook 'rjsx-mode-hook 'lsp)
Once you get lsp up and running, what can you do with it? For one thing, it augments flycheck to show issues beyond just syntax. A language server can tell when a variable is defined but never used, and when a variable in use has not been defined.
A language server can also provide language-specific completions, like builtin functions, and methods and fields on objects. This feature requires another package, called company, which provides a generalized auto-completion interface for emacs.
When company-mode and lsp-mode are enabled in the same buffer, company will automatically detect the completions provided by lsp. In this clip we see the ability to autocomplete a builtin JS function, and autocomplete a method on an object.
The next one is more of a language-specific thing, but the point is packages like this can be written for any language. I'm talking about auto-formatting packages, specifically prettier-js for formatting JavaScript code.
Just like how flycheck uses external linting tools, and lsp uses external language servers, prettier-js uses the prettier tool available from npm.

npm install --save-dev --save-exact prettier
prettier-js runs prettier when you save a file to format your JavaScript code according to rules you can configure in a .prettierrc
lsp-mode and company-mode are useful for autocompleting single atoms of code, like methods or object properties. There's another package specifically for expanding longer code snippets, like the boilerplate for functions, classes, or conditional expressions. This is YASnippet.
YASnippet, which stands for Yet Another Snippet Extension, uses predefined templates to help you write boilerplate code. Typing TAB in insert mode will bring up a helm selection buffer of snippets that are available for the current mode.
Hitting RET over an option will insert the template associated with the option. Typing TAB will cycle through the template's dynamic fields, letting you customize the template to your code.
Those packages - flycheck, lsp, prettier, company, yasnippet - are all for writing code; literally putting code into files. But software development involves more than writing code. Running code is also a big part of it. Let's talk about how to do that from emacs.
prodigy.el is a package for running external programs from emacs. When you're writing code for a web app, you need local servers for your client and your server. You could run these by typing commands into a terminal emulator, or you could type a couple keys into emacs.
prodigy provides an interface for registering services with enough info to run the program, whatever it is. These services become available in a prodigy service management menu.
Start and stop them from this menu with a single key press. Hop to a buffer showing a service's output with another keypress. Here's an example of running a React app server from prodigy. We start it, open the output buffer, then shut it down after it finishes loading.
You can use prodigy with any program you have an executable for.
When running a service or services in Emacs with prodigy, it's nice to be able to conveniently switch to the output buffers to check out what's going on.
You could do this with the generic `switch-to-buffer` behavior, or likely something a little more sophisticated like `helm-buffers`. But even that requires a bunch of keystrokes to type out enough of the buffer's name to properly select it from all the buffers you have open.
This is a perfect use case for a layout package like eyebrowse. There are other packages you could use for this, like persp-mode. Or you could use built in configuration registers. But I find eyebrowse to be the simplest method for managing workspaces like this.
eyebrowse lets you create separate workspaces, each with their own window configuration. You can name them, and switch between them with lightning fast keystrokes. The prodigy use case is to open a workspace to hold the output buffers of your running processes.
I have eyebrowse workspaces bound to "SPC w <digit>" where <digit> can be 0-9. So there are 10 workspaces. Naming the current workspace is done with "SPC w ,". You can see the name (or the digit if there is no name) of the current workspace in the bottom left.
In this clip I create a new workspace called "prodigy-output" to hold the prodigy menu and the output buffer from a python process running a simple web server. The "main" workspace remains available for coding or whatever.
The stdout of services isn't the only output you care about, and typically it's not the most important. What you really want are the log files. You can also use eyebrowse for this. Just pop to a higher numbered workspace and open the logfiles that your services are writing to.
The important thing here is to enable auto-revert-tail-mode in these buffers so they keep spitting out logs.
This is a bit manual and tedious for a professional emacs setup, admittedly. I'm working on a package, or at least a few convenience functions, to help define and open logfile layouts easily. I'll thread that later when I finish it. It uses the window-layout package.
Just a couple more ideas I want to touch on before we can wrap up this thread.

1) evil mode
2) keybindings
evil-mode is a package that brings vim's modal editing to emacs. Now, if vim already has modal editing, why not just use that?
A good question, honestly. vim and emacs are frequently grouped into the same bucket because of their status as legacy editors, and so their differences are not well-known.
In my opinion, emacs has a serious advantage over vim because its customization language is lisp. Lisp is a serious and enjoyable programming language, vimscript is not (relax, these are my opinions).
At the same time, modal editing is a better paradigm than non-modal editing (also my opinions). And since it's harder to bring lisp to vim than it is to bring modal editing to emacs, evil mode is the winning solution.
Now for keybindings. Starting to understand emacs keybindings was a huge leap in my ability to shape the editor to my workflow. The central thing to understand is: if you want to be able to run a certain function from a certain keychord in a certain mode, you can.
This is a special case of the general idea of emacs which is: if you want to make the editor do a certain thing, you can. But it's especially helpful to grasp this idea in relation to keybindings because they are the primary way you interact with the editor.
This is by no means a comprehensive guide to emacs keybindings. Heck, maybe I'll do one of those one day. These are just the core ideas that I use to make granular keymap customizations.
First thing is this: figure out what mode you're in. Most of the time you'll want to override a keybinding just for a certain mode. Like for example you want to bind a convenient keychord in org mode for toggling TODO state.
To find the major mode of the current buffer, run the function `describe-mode`. This is bound to "C-h m" by default, which is useful to keep around to use in insert mode. I also have it bound to "SPC h m" in normal mode.
When you've found the name of the major mode, you'll be able to write an `evil-define-key` command to set your desired keybinding.

(evil-define-key 'normal <major-mode-map> '<desired-command>)
The 'normal symbol in that command can be any one of the modes that evil provides: 'normal, 'visual, 'insert, 'replace, 'operator-pending, 'motion.
Mostly you'll want 'normal or 'insert, but if you're getting real crazy with it, check out the docs

evil.readthedocs.io/en/latest/over…
This concludes my Emacs Megathread.
Appendix A: Links to packages mentioned in this thread

* org-mode orgmode.org
* magit magit.vc
* helm emacs-helm.github.io/helm/
* projectile projectile.mx
* helm-projectile github.com/bbatsov/helm-p…
...
This tweet makes this thread 99 tweets long. I didn’t know about the awesome @threadapalooza account last night when I posted, otherwise I would have found a way to make it 100! Hoping @visakanv let’s that slide 🙂 I’ll make the next one 101

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with matt (6/100 posts)

matt (6/100 posts) Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!