Posts

  • Super Keybindings for Magit

    This short article will present one simple, but unconventional idea - super-powered keybindings for Magit.1

    I hope by now most of you know (and use) the 3 default global Magit keybindings:

    • C-x g (magit-status)
    • C-x M-g (magit-dispatch)
    • C-c M-g (magit-file-dispatch)

    Typically you’d add to them C-c g, as a more convenient alternative of C-c M-g.2

    So far, so good. Now you can invoke a lot of commands with keybindings like C-x g l l or C-c g b, which is not bad as far as Emacs keybindings go. Remembering when to use C-x g, C-x M-g and C-c g takes a bit of practice, but it’s not very hard.

    But what if you wanted to have a lot of Magit commands under a single two-key (super convenient) prefix? Such prefixes are tight in Emacs these days, but only if we’re talking about the commonly used prefixes based on Control (e.g. C-c and C-x). If you’re not a traditionalist you can try something different - use a prefix based on the rarely utilized in Emacs Super key.3 Here’s one such idea using the Super-m prefix (the m, of course, stands for Magit4):

    ;; essentials
    (global-set-key (kbd "s-m m") 'magit-status)
    (global-set-key (kbd "s-m j") 'magit-dispatch)
    (global-set-key (kbd "s-m k") 'magit-file-dispatch)
    ;; a faster way to invoke very common commands
    (global-set-key (kbd "s-m l") 'magit-log-buffer-file)
    (global-set-key (kbd "s-m b") 'magit-blame)
    
    ;; or alternatively
    (use-package magit
      :ensure t
      :bind (("s-m m" . magit-status)
             ("s-m j" . magit-dispatch)
             ("s-m k" . magit-file-dispatch)
             ("s-m l" . magit-log-buffer-file)
             ("s-m b" . magit-blame)))
    

    Not only are all essential Magit commands under a single mnemonic (s-m) right now, but you can also bind some “internal” commands that you’d normally invoke via magit-dispatch or magit-file-dispatch directly under this prefix. This makes it slightly more efficient to invoke frequently used commands.

    The suggested keys m, j and k are clustered together on a typical QWERTY keyboard which makes it super easy to press them in sequence. Of course, you can find many other comfortable options.

    One thing that you should keep in mind is that your mileage with Super keybindings will vary based on your operating system/desktop environment. Windows, for instance, uses Win + letter keybindings a lot, so s-m is not an option there (it minimizes the current window). Frankly, I’m not sure if any Win + letter keybindings are available there at all.5 On macOS and Linux, however, such keybindings work fairly well, unless you happen to be using a window manager that’s fond of them (e.g. exwm).

    I first adopted the use of Super several years ago, but I never promoted it enough, apart from including a few such keybindings in Emacs Prelude. While the examples I gave today are with Magit, you can leverage the super keybindings with any package - e.g. I’ve long favored the use of s-p for Projectile and bindings like s-. for avy.

    That’s all I have for you today. Super-X forever!

    1. In the sense of using the Super key. Although I guess one can argue that they are also super convenient. 

    2. This article discusses the topic of the essential Magit commands in a bit more detail. 

    3. Typically this is the Windows key on PC keyboards and the Command key on Mac keyboards. 

    4. I sometimes wonder how the default keybindings for Magit ended up the letter “g” instead of “m”. It’s either a reference to Git, or that “g” happens to be on the home row. Or both. 

    5. In theory it should be possible to tell Emacs to intercept the Win key before Windows for (at least) some commands, but the suggested solution never worked for me. 

  • Essential Magit File Commands

    Everyone knows Magit and everyone knows it’s one of my favorite Emacs packages.

    One thing that probably fewer people know is that once Magit is installed, it establishes automatically several keybindings in the global keymap1 that allow you to interact with Magit from any Emacs buffer in 3 different ways:

    • C-x g (magit-status) - that’s the way in which most people use Magit.2 You get a dedicated Magit buffer where you can invoke all sorts of commands for everything that you can imagine (e.g. pulling, pushing, staging, committing, branching). Generally this seems to be the best way to work with multiple files. I’m pretty sure all of you are familiar with this way to use Magit, as it dates back to the earliest days of the project.
    • C-x M-g (magit-dispatch) - that’s pretty much the same as magit-status, but you get the opportunity to trigger a Magit command directly from the minibuffer. One can argue that’s a (slightly) more effective way to work if you know it advance what you want to do (e.g. pressing C-x M-g l l will display the git log).
    • C-c M-g (magit-file-dispatch) - that’s the way to invoke Magit commands on the current file (e.g. blame) and that’s the hero of today’s article.

    I’ve noticed that for some reason many people don’t use magit-file-dispatch much, which seems like a wasted opportunity as it provides the fastest way to do common things like:

    • magit-blame (C-c M-g b)
    • stage the current file (C-c M-g s)
    • commit the current file (C-c M-g c)
    • show the git log for the current file (C-c M-g l)
    • show the diff for the current file (C-c M-g d)

    I hope you’ll agree those are pretty handy commands. magit-file-dispatch offers other commands as well, but let’s stick to the essential ones today. One small improvement that you can do in terms of ergonomics is to map magit-file-dispatch to C-c g instead:

    (global-set-key (kbd "C-c g") 'magit-file-dispatch)
    

    The reasoning for this is pretty simple - it’s much easier to use C-c g than C-c M-g. Unfortunately, there’s a strong Emacs tradition forbidding packages to utilize directly such keybindings (they are reserved for user keybindings), so Magit settles for the next best thing by default. You, however, have the power to do anything you want with your keybindings.

    As a side note - if you’re manually configuring Magit’s keybindings you can stop doing this:

    ;; commonly found in the wild
    (use-package magit
      :ensure t
      :bind (("C-x g" . magit-status)
             ("C-x M-g" . magit-dispatch)
             ("C-c M-g" . magit-file-dispatch))
    
    ;; should be just
    (use-package magit
      :ensure t
      :bind ((("C-c g" . magit-file-dispatch))
    

    If for some reason you don’t like the default Magit keybindings, you can disable them via magit-define-global-keybindings.

    I have to admit that for a very long time I’d use only magit-status (C-x g) and I’d go for the file commands from Emacs’s built-in vc package like vc-annotate (C-x v g, a command similar to magit-blame), just because I’ve been using Emacs since before the creation of Git (and respectively Magit). While the built-in vc package is nice (and VCS-agnostic), Magit is way nicer when it comes to Git support, so I’m glad I eventually managed to shed my old habits.

    Magit probably has the best documentation of any Emacs package, but the problem with having a great documentation and lots of features is that someone has to do a lot of reading. Consider this article a cheatsheet of sorts. That’s all I have for you today. I hope you’ve learned something useful! Feel free to share in the comments how/when do you use Magit’s 3 modes of operations.

    1. That’s a recent change from November 2020. Before it there was global-magit-file-mode that was serving the same purpose. 

    2. Based on my subjective observations. 

  • Favorite Emacs Packages

    People often ask me which are my favorite Emacs packages, so I’ve decided to write a short article on the subject. I’ll limit my myself to only 5 packages and I’ll exclude:

    • built-in packages (e.g. dired, erc)
    • color themes
    • everything that’s specific to a particular programming language (e.g. SLIME, CIDER)

    In other words, I’ll focus on (more or less) “universal” packages.

    Projectile

    Projectile is a project interaction library, written by your truly. I’m obviously biased here, but that’s also the package I use the most in my day to day interactions with Emacs.

    Projectile is a massive package with numerous commands, but I mostly limit myself to the ones outlined here.

    Funny enough, I think I never wrote any articles on Projectile here. I guess I should change this.

    Magit

    Magit is the best way to interact with Git from Emacs. Period. It has probably converted more people to Emacs than any other Emacs package.

    I’ll have to admit that at this point I’m not sure whether I can still use Git from the command-line.

    Selectrum/Ivy

    Selectrum and Ivy are minibuffer completion/filtering/sorting frameworks. I’m cheating a bit here by listing both of them, but they are pretty similar and equally awesome.

    Ivy has more bells and whistles (more features and a fancier UI) and selectrum has a simpler design. I used to use ivy for quite a while, but recently I’ve switched to selectrum, as I realized I rarely used ivy’s famous add-ons swiper and counsel.

    Anyways, both packages are great and you can’t go wrong choosing any them.

    Note: Regardless of which one of them you’re using, you definitely want to combine them with the awesome prescient package that supercharges the sorting and filtering algorithm.

    crux

    crux is a collection of ridiculously useful Emacs commands. Like the Matrix it cannot be explained, you have to experience it for yourselves.

    Note: The package started life as an Emacs Prelude module, but was eventually extracted, so those commands could be used by anyone. A lot of the articles I wrote early on at Emacs Redux were dedicated to commands that are part of crux.

    avy

    avy allows you to quickly (with only a couple of keystrokes) jump to a specific place in your visible Emacs windows. I can’t imagine going back to Emacs’s standard commands for those tasks, after spending so much time with avy.

    Honorary Mentions

    I promised I’ll limit myself to only 5 packages, but I cannot omit the following awesome packages as well:

    • company-mode (a great completion framework)
    • diff-hl (shows you VC diffs in the gutter)
    • which-key (helps you navigate the numerous Emacs keybindings with helpful hints in the minibuffer)
    • smartparens (smart handling of paired delimiters; its smartparens-strict-mode is a decent paredit alternative)
    • paredit (like smartparens, but geared towards Lisp programming)
    • easy-kill (saving/killing made easy and fast; I wrote about it in the past)
    • expand-region (expand the selected region incrementally by semantic units)
    • undo-tree (my favourite way to deal with undo in Emacs; undo-tree-visualize is pure gold)
    • flycheck (lint tool integration)
    • lsp-mode (trying to give VS Code a run for its money)

    I’ll stop here, as I realized I use quite a few packages all the time.

    Closing Words

    In my book, my favorite packages are ones that I’m using the most. They keep changing with time, but I doubt I’ll stop using any of the packages that I mentioned in this article any time soon.

    That being said, I’ve been using Emacs for over 15 years and looking back at my list it seems to me that the only packages that I used back then (circa 2005) where probably paredit and undo-tree. The Emacs landscape has been very dynamic in recent years and everything has changed (for the better). I can only imagine what amazing packages will get created and become prominent in the next 15 years.

    I didn’t really cover any niche/obscure packages today, but I hope that some of you will learn about a new package that they can experiment with. Playing with different packages and approaches to solving the same problem has always been a defining trait of the Emacs experience for me.

    That’s all I have for you today. Down the road I plan to expand on some the packages I’ve mentioned in passing today. So, what are your favorite Emacs packages?

  • Switching to a New Comments Service

    Just wanted to let you know that for various reasons I’ve migrated the comments of Emacs Redux from Disqus to Hyvor Talk. I’ve described the process in a dedicated article.

    The migration process converted all Disqus comments to guest comments in Hyvor, which is a bit unfortunate, but unavoidable. Still, I think that’s a small price to pay for a privacy-focused (and more developer-friendly) solution with better usability. I hope that this transition will result in more interesting discussions taking place here and more Emacs Lisp snippets shared via the comments! Meta-X forever!

  • Maximize the Emacs Frame on Startup

    I don’t know about you, but I always use Emacs maximized.1 It’s my most important tool2 and I want to dedicate to it as much screen real estate as possible. As Emacs doesn’t start in maximized mode by default you have to do one of the following:

    • Maximize it manually (e.g. by clicking the maximize icon)
    • Figure out how to maximize it automatically

    I guess by now it should be clear we’ll be going for the second option. As usual with Emacs there are multiple ways to achieve what we want. If you’re the type of person who starts Emacs from the command-line you might try the -mm option:

    $ emacs -mm
    

    Furthermore, you can just alias emacs to emacs -mm. Put something like this in your shell configuration:

    alias emacs="emacs -mm"
    

    Tip: There’s also emacs -fs that will start Emacs in full-screen mode.

    Another simple option would be to add something like this to your Emacs config:

    ;; the t parameter apends to the hook, instead of prepending
    ;; this means it'd be run after other hooks that might fiddle
    ;; with the frame size
    (add-hook 'window-setup-hook 'toggle-frame-maximized t)
    

    Here’s the description of windows-setup-hook:

    Normal hook run after loading init files and handling the command line. This is very similar to ‘emacs-startup-hook’. The only difference is that this hook runs after frame parameters have been set up in response to any settings from your init file. Unless this matters to you, use ‘emacs-startup-hook’ instead.

    By the way, toggle-frame-maximized is an interactive Emacs command that you can use with M-x. There’s also a similar toggle-frame-fullscreen command that does exactly what you’d expect it to do.

    Finally, the most granular and slightly more involved solution would be to leverage a couple of frame setup options - namely default-frame-alist and initial-frame-alist. The two accept exactly the same configuration values, but differ in their scope:

    • default-frame-alist is applied to every Emacs frame that you create
    • initial-frame-alist is applied only to the initial (startup) Emacs frame

    I prefer the use of initial-frame-alist, as I rarely work with multiple frames anyways:

    ;; start the initial frame maximized
    (add-to-list 'initial-frame-alist '(fullscreen . maximized))
    
    ;; start every frame maximized
    (add-to-list 'default-frame-alist '(fullscreen . maximized))
    

    For the completely list of frame size options, see this section of the Emacs manual for details. The short version is that you can set the fullscreen3 parameter to one of the following:

    • fullwidth (make the frame as wide as possible, don’t touch the vertical)
    • fullheight (make the frame as tall as possible, don’t touch the horizontal)
    • fullboth (set height and width to to size of the screen)
    • maximized (self-explanatory)

    The difference between fullboth and maximized is that you can resize the former with the mouse, while with the latter you cannot.

    That’s all I have for you today. I hope you learned something useful. Meta-X forever!

    1. From time to time I even use it in full-screen mode, depending on how deep in the zone I am. 

    2. Not to mention it’s a pretty decent window manager as well. 

    3. I find the name very confusing, but it is how it is. 

Subscribe via RSS | View Older Posts