IDO - Emacs

emacs

Table of Contents

  1. Minibuffer Completion
  2. Use SPACES in the minibuffer
  3. Vertical candidates
  4. Move to most used folders
  5. Ignore some buffers
  6. Open dired immediately in current directory at find-file

Minibuffer Completion

Emacs-land is gifted with many options for Minibuffer completion e.g. ivy, helm, icomplete, selectrum, and ido. But when I started , (ido-mode t) was the first line of Elisp code that I wrote, therefore I have a special care about it.

I tried almost all third-party packages for minibuffer completions, but I always go back to IDO after a while. Probably I am not a power user for the kind of functionality these frameworks provide.

This is my current setup for ido:


    (defun ido-choose-from-recentf ()
      "Use ido to select recently visited files."
      (interactive)
      (find-file (ido-completing-read "Open file: " recentf-list nil t)))

    (defun bk/go-straight-home ()
      (interactive)
      (cond
       ((looking-back "~/") (insert "projects/"))
       ((looking-back "/") (insert "~/"))
       (:else (call-interactively 'self-insert-command))))

    (defun ido-disable-line-truncation ()
      (set (make-local-variable 'truncate-lines) nil))

    (defun ido-define-keys ()
      (define-key ido-completion-map (kbd "C-n") 'ido-next-match)
      (define-key ido-completion-map (kbd "C-p") 'ido-prev-match))

    (use-package ido
      :ensure nil
      :init
      (setq ido-enable-flex-matching t
            ido-use-filename-at-point nil
            ido-create-new-buffer 'always
            confirm-nonexistent-file-or-buffer nil
            completion-ignored-extensions (cons "*.aux" completion-ignored-extensions)
            max-mini-window-height 0.5
            ido-enable-tramp-completion t
            ido-auto-merge-work-directories-length -1
            ido-confirm-unique-completion t
            ido-default-file-method 'selected-window
            ido-case-fold t
            ido-show-dot-for-dired t
            ido-everywhere t
            ido-ignore-buffers (list (rx (or (and bos  " ")
                                             (and bos
                                                  (or "*Completions*"
                                                      "*Compile-Log*"
                                                      "*Ido Completions*"
                                                      "*Shell Command Output*"
                                                      "*vc-diff*")
                                                  eos))))
            ido-decorations (quote ("\n-> " "" "\n " "\n ..." "[" "]" "
      [No match]" " [Matched]" " [Not readable]" " [Too big]" "
      [Confirm]")))

      :config
      (define-key ido-common-completion-map (kbd "M-SPC") 'just-one-space)
      (define-key ido-common-completion-map (kbd "SPC") 'self-insert-command)
      (define-key ido-file-completion-map (kbd "~") 'bk/go-straight-home)

      (add-hook 'ido-setup-hook 'ido-define-keys)

      (add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-truncation)

      (set-default 'imenu-auto-rescan t)

      (add-to-list 'ido-ignore-directories "target")
      (add-to-list 'ido-ignore-directories "node_modules")

      (add-hook 'after-init-hook 'ido-mode))

This might be a bit lengthy, but I want to explain some of the highlights.

Use SPACES in the minibuffer

Yes, I really like how Ivy let us use the spaces to add more tokens to our searches. That is nice. I didn’t go that deep to reproduce such functionality in IDO, but I use org-roam a lot and several of my notes have spaces in their names.

Thus, the idea was to be able to add SPACES in the minibuffer to filter candidates from Org-Roam.

Turns out you can type M-q SPC to add a space symbol in the minibuffer. But we can do better, right?

    (define-key minibuffer-local-completion-map (kbd "SPC") 'self-insert-command)

The code above let us type SPC in the minibuffer, however, IDO also uses the SPC keyword for ido-complete-space function, therefore we need to remap it too:

    (define-key ido-common-completion-map (kbd "SPC") 'self-insert-command)

Vertical candidates

I tried to get used to the horizontal display, but even not being so bad, I find the benefits for vertical mode very appealing and the necessary tweaks are simple to do:

    (setq ido-decorations (quote "\n-> " "" "\n " "\n ..." "[" "]" "
        [No match]" " [Matched]" " [Not readable]" " [Too big]" "
        [Confirm]"))

I also like to adjust the height of the candidate list to be a little bit taller than usual to fit more candidates before typing anything.

    (setq max-mini-window-height 0.5)

Also need to adjust the navigation keys to use standard C-n and C-p to move up and down the list.


      (defun ido-define-keys ()
        (define-key ido-completion-map (kbd "C-n") 'ido-next-match)
        (define-key ido-completion-map (kbd "C-p") 'ido-prev-match))

    (add-hook 'ido-setup-hook 'ido-define-keys)

Move to most used folders

I like to type ~ twice and be taken to my “projects” folder. This is a nice recipe for you to change as you like.


      (defun bk/go-straight-home ()
        (interactive)
        (cond
         ((looking-back "~/") (insert "projects/"))
         ((looking-back "/") (insert "~/"))
         (:else (call-interactively 'self-insert-command))))

    (define-key ido-file-completion-map (kbd "~") 'bk/go-straight-home)

Ignore some buffers

I really don’t like to see some buffers like *Completions*, *Compile-Log*, etc. If I want to look at them, I will go to M-x ibuffer or M-x buffer-list explicitly.


    (setq ido-ignore-buffers (list (rx (or (and bos  " ")
                                           (and bos
                                                (or "*Completions*"
                                                    "*Compile-Log*"
                                                    "*Ido Completions*"
                                                    "*Shell Command Output*"
                                                    "*vc-diff*")
                                                eos)))))

As soon as I find a new buffer bothering me, I add the name to my blocklist.

Similar situation for some file extensions like the auxiliary files created by LaTeX compilation process.

    (setq  completion-ignored-extensions (cons "*.aux" completion-ignored-extensions))

Open dired immediately in current directory at find-file

This simple setup is very handy. it will add a dot as the first item of your candidates when you fire find-file. You can open dired immediately using RET on the dot.

    (setq ido-show-dot-for-dired t)

Conclusion

I keep learning something new in IDO everytime. Up to now I manage to survive without flx-ido or even ido-completing-read+. I might give then another chance in the near future.

If you have more tweaks to IDO, I would love to know about.

Happy New Year, keep hacking!