(or emacs irrelevant)

Please consider supporting me on Patreon

In light of the recent success of the Magit Kickstarter (congratulations to @tarsius, by the way), I got a lot more optimistic about Free Software crowdfunding.

So I opened a Patreon account where you can support my work: https://www.patreon.com/abo_abo. The goal I set there is both optimistic and (hopefully) realistic: I'd like to hack on Free Software 1 day per week indefinitely, reducing my real world job days to 4 per week.

Ideally, I'd like to work on Free Software full time (one can dream), but it doesn't look like that level of donations is attainable right now. But I think I could accomplish a lot working a full day per week:

  • improve the level of maintenance of my current projects
  • polish and release a few projects I have in a semi-complete unreleased state
  • produce more content on my YouTube channel
  • maybe start working on an Emacs book

Here's a list of popular repositories I've made over the last 5 years in my free time (all Free Software under GPL):

If you are a user of my work, don't feel any pressure to donate. We are all here voluntarily: I publish because I enjoy it, you use the software because you find it useful. But out there is the real world, and, although I like my real world job enough, I can't say that would I do it voluntarily if I had enough money to meet my needs.

If you do what you love, you'll never work a day in your life

I'd like to do what I love, and I wish you all the same. Happy hacking!

Extending completion-at-point for Org-mode

Intro

When creating documents, context aware completion is a powerful mechanism that can help you improve the speed, correctness and discoverability.

Emacs provides context aware completion via the complete-symbol command, bound to C-M-i by default. In order for it to do something useful, completion-at-point-functions has to be set up.

Documentation:

Special hook to find the completion table for the thing at point.
Each function on this hook is called in turn without any argument and should
return either nil to mean that it is not applicable at point,
or a list of the form (START END COLLECTION) where
START and END delimit the entity to complete and should include
point, COLLECTION is the completion table to use to complete it.

For each major-mode, a different value of completion-at-point-functions can (and probably should) apply. One of the modes that's set up nicely by default is emacs-lisp-mode: press C-M-i to get completion for Elisp variable and function names. Org-mode, on the other hand, is quite lacking in this regard: nothing useful happens with C-M-i.

Here's my current setting for Org-mode:

(setq completion-at-point-functions
      '(org-completion-symbols
        ora-cap-filesystem
        org-completion-refs))

org-completion-symbols

When I write about code in Org-mode, I quote items like this:

=/home/oleh/=, =HammerFactoryFactory=, etc.

Quoting has several advantages:

  • It looks nice, since it's in a different face,
  • flyspell doesn't need to check it, which makes sense since it would fail on most variable and class names,
  • Prevents Org from confusing directory names for italics mark up.

Completion has one more advantage on top of that: if I refer to a symbol name multiple times within a document, completion helps me to enter it quickly and correctly. Here's the corresponding completion source:

(defun org-completion-symbols ()
  (when (looking-back "=[a-zA-Z]+")
    (let (cands)
      (save-match-data
        (save-excursion
          (goto-char (point-min))
          (while (re-search-forward "=\\([a-zA-Z]+\\)=" nil t)
            (cl-pushnew
             (match-string-no-properties 0) cands :test 'equal))
          cands))
      (when cands
        (list (match-beginning 0) (match-end 0) cands)))))
  1. First of all, it checks if the point is e.g. after =A, i.e. we are in fact entering a new quoted symbol. If that's not the case, return nil and let the other completion sources have a go.

  2. Next, it looks through the current buffer for each =foo= and =bar=, accumulating them into a list.

  3. Finally, it returns the bounds of what we've got so far, plus the found candidates. It's important that the bounds are passed to the completion engine, so that it can delete everything inside the bounds before inserting the whole selected symbol.

org-cap-filesystem

This source is for completing file names:

(defun ora-cap-filesystem ()
  (let (path)
    (when (setq path (ffap-string-at-point))
      (let ((compl
             (all-completions path #'read-file-name-internal)))
        (when compl
          (let ((offset (ivy-completion-common-length (car compl))))
            (list (- (point) offset) (point) compl)))))))

I usually enter ~, so that ffap-string-at-point recognizes it as a path. Then complete each part of the path with C-M-i. It's very similar to counsel-find-file. In fact, I could just use counsel-find-file for this, with M-o i to insert the file name instead of opening the selected file.

org-completion-refs

org-completion-refs is very similar to org-completion-symbols: it will collect all instances of e.g. \label{foo}, and offer them for completion when you enter \ref{. If you want to look at the code, it's available in my config.

Outro

I hope I convinced you about the usefulness of completion at point. It's especially cool since it's a universal interface for major-mode-specific completion. So any IDE-like package for any language could provide its own completion using the familiar interface. That could go a long way towards providing a "just works" experience, particularly when dealing with a new language.

Ripgrep

counsel-rg

Lately, due to working with a large code base, I've grown more and more fond of counsel-rg. It's an Elisp wrapper around ripgrep - a relatively new recursive grep tool that aims to be faster than the competition (ag, git grep, pt, ack etc).

Besides being really fast, rg also has some really nice command switches. One such switch is especially useful for Emacs:

-M, --max-columns NUM : Don't print lines longer than this limit in bytes. Longer lines are omitted, and only the number of matches in that line is printed.

The -M switch is useful twofold:

  • Emacs is slow when dealing with long lines (by long I mean thousands of chars per line)
  • Emacs is slow at accepting a huge amount of output from a process

For each character you add to your input, counsel-rg starts a new shell command to recalculate the matches with the new input. This means that in order to avoid keyboard lag there's only about 0.1 seconds available for both:

  1. Running the shell command.
  2. Accepting output from the shell command.

So I'm quite happy that rg speeds up both steps. Less time spent on these steps provides for much smoother searching.

counsel-grep-or-swiper

I also work with large log files, one file at a time. For a long time, I've used counsel-grep-or-swiper as my main search command:

(global-set-key (kbd "C-s") 'counsel-grep-or-swiper)

But for a 40Mb log file with really long lines counsel-grep-or-swiper started to lag a bit. I tried counsel-rg, and it was actually faster than grep, although it was searching the whole directory. So I thought, why not use rg instead of grep? The switch is actually really easy and required only a simple user customization:

(setq counsel-grep-base-command
 "rg -i -M 120 --no-heading --line-number --color never '%s' %s")

Outro

If you haven't tried ripgrep so far, I suggest you give it a go. Happy hacking!

And if you're a C hacker and have some free time on your hands, why not look at the long lines and the process output issues in Emacs? I'd be very grateful:)

hydra.el talk @ london.el

Today I gave a talk on hydra at the London Emacs meet up - london.el. My screen capture is available on youtube, and the slides are here.

Thanks to @dotemacs for organizing the event and inviting me.

Ivy 0.9.0 is out

Intro

Ivy is a completion method that's similar to Ido, but with emphasis on simplicity and customizability.

Overview

The current release constitutes of 339 commits and almost a full year of progress since 0.8.0. Many issues ranging from #493 to #946 were fixed. The number of people who contributed code as grown to 63; thanks, everyone!

Details on changes

Changelog.org has been a part of the repository since 0.6.0, you can get the details of the current and past changes:

Highlights

Many improvements are incremental and don't require any extra code to enable. I'll go over a few selected features that require a bit of information to make a good use of them.

A better action choice interface

For all ivy completions, pressing M-o allows to execute one of the custom actions for the current command. Now you have an option to use hydra for selecting an action. Use this code to turn on the feature:

(require 'ivy-hydra)

One big advantage of the new interface is that you can peak at the action list with M-o without dismissing the candidate list. Press M-o again to go back to candidate selection without selecting an action.

Here's some code from my config that ensures that I always have some extra actions to choose from:

(defun ora-insert (x)
  (insert
   (if (stringp x)
       x
     (car x))))

(defun ora-kill-new (x)
  (kill-new
   (if (stringp x)
       x
     (car x))))

(ivy-set-actions
 t
 '(("i" ora-insert "insert")
   ("w" ora-kill-new "copy")))

Grepping

The new counsel-rg joins the group of grepping commands in counsel (counsel-ag, counsel-git-grep, counsel-grep, counsel-pt). It wraps around the newly popular and very fast ripgrep shell tool.

A nice improvement to the grepping commands is the ability to specify extra flags when you press C-u (universal-argument) before the command. See this gif for an example of excluding *.el from the files searched by ag.

counsel-find-file

  • Press M-o b to change the current directory to one of the virtual buffers' directories. You continue to select a file from that directory.

  • Press M-o r to find the current file as root.

counsel-git-log

You can now customize counsel-git-log-cmd. See #652 for using this to make counsel-git-log work on Windows.

counsel-mode

  • counsel-info-lookup-symbol now substitutes the built in info-lookup-symbol.
  • Pressing C-r while in the minibuffer of eval-expression or shell-command now gives you completion of your previous history.

counsel-yank-pop

Use the new counsel-yank-pop-separator variable to make counsel-yank-pop look like this.

ivy

There was breaking change for alist type collections some months ago. Right now the action functions receive an item from the collection, instead of (cdr item) like before. If anything breaks, the easy fix is to add an extra cdr to the action function.

Unique index for alist completion was added. The uniqueness assumption is that the completion system is passed a list of unique strings, of which one (or more) are selected. Unlike plain string completion, alists may require violating the uniqueness assumption: there may be two elements with the same car but different cdr. Example: C function declaration and definition for tag completion. Until now, whenever two equal strings were sent to ivy-read, only the first one could be selected. Now, each alist car gets an integer index assigned to it as a text property 'idx. So it's possible to differentiate two alist items with the same key.

Action functions don't require using with-ivy-window anymore. This allows for a lot of simplification, e.g. use insert instead of (lambda (x) (with-ivy-window (insert x))).

ivy-switch-buffer

You can now customize faces in ivy-switch-buffer by the mode of each buffer. Here's a snippet from my config:

(setq ivy-switch-buffer-faces-alist
      '((emacs-lisp-mode . swiper-match-face-1)
        (dired-mode . ivy-subdir)
        (org-mode . org-level-4)))

Looks neat, I think:

ivy-switch-buffer-faces-alist

swiper

Customize swiper-include-line-number-in-search if you'd like to match line numbers while using swiper.

New Commands

counsel-bookmark

Offers completion for bookmark-jump. Press M-o d to delete a bookmark and M-o e to edit it.

A custom option counsel-bookmark-avoid-dired, which is off by default, allows to continue completion for bookmarked directories. Turn it on with:

(setq counsel-bookmark-avoid-dired t)

and when you choose a bookmarked directory, the choice will be forwarded to counsel-find-file instead of opening a dired-mode buffer.

counsel-colors-emacs and counsel-colors-web

Completion for colors by name:

  • the default action inserts the color name.
  • M-o h inserts the color hex name.
  • M-o N copies the color name to the kill ring.
  • M-o H copies the color hex name to the kill ring.

The colors are displayed in the minibuffer, it looks really cool:

counsel-colors-emacs

You also get 108 shades of grey to choose from, for some reason.

counsel-faces

Completion for faces by name:

counsel-faces

counsel-command-history

Shows the history of the Emacs commands executed and lets you select and eval one again. See #826 for a nice screenshot.

counsel-company

Picks up company's candidates and inserts the result into the buffer.

counsel-dired-jump and counsel-file-jump

Jump to a directory or a file in the current directory.

counsel-dpkg and counsel-rpm

Wrap around the popular system package managers.

counsel-package

Install or uninstall Emacs packages with completion.

counsel-mark-ring

Navigate the current buffer's mark ring.

counsel-semantic

Navigate the current buffer's tags.

counsel-outline

Navigate the current buffer's outlines.

counsel-recentf

Completion for recentf.

counsel-find-library

Completion for find-library.

counsel-hydra-heads

Completion for the last hydra's heads.

counsel-org-agenda-headlines

Completion for headlines of files in your org-agenda-files.

Outro

Again, thanks to all the contributors. Happy hacking!