Monthly Archives: June 2016

Find and open files from anywhere with helm-for-files

Helm is an extremely powerful package that provides a search interface that narrows the matches as you type. What makes it powerful is the range of back-ends that you can access through helm. I don’t use it for a lot of things (I slightly prefer ivy in general), but one of my favourites is helm-for-files. This gives you a search interface where you start typing the name of a file and it narrows a list of files from multiple useful sources: currently opened files; recent files; bookmarked files; files in the current directory; and files anywhere on your system using your system’s locate command. Basically, it find any file anywhere on your system, showing you the most likely matches first. Hitting RET to select a file opens it in Emacs as usual.

Here is how I install and configure helm for this purpose

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; helm                                                                   ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(use-package helm
  :ensure t
  :init
  (progn
    (require 'helm-config)
    ;; limit max number of matches displayed for speed
    (setq helm-candidate-number-limit 100)
    ;; ignore boring files like .o and .a
    (setq helm-ff-skip-boring-files t)
    ;; replace locate with spotlight on Mac
    (setq helm-locate-command "mdfind -name %s %s"))
  :bind (("C-x f" . helm-for-files)))

Since I use a Mac, I tell helm to use mdfind which is the command line interface to the spotlight indexer in place of the normal locate command. Finally, I bind the command to C-x f to serve as a memorable alternative for C-x C-f (the default interface for opening files).

Cycle through windows across all frames

There are lots of ways to switch between windows in Emacs. I recently discovered that s-' (i.e. super and ' where super is the command key on a Mac) runs the command next-multiframe-window which cycles you through all the current windows regardless of which frame they are in. This is a nice quick way to switch to another window.

Aside: in Emacs terminology a frame is what most programmes call a window – the floating box containing the programme. In Emacs a frame can be split into several windows such as when you have several buffers open at the same time.

Macro Counters

I’ve posted about using keyboard macros to record and play back repetitive tasks. Macros include a counter which lets you insert numerical values that increment each time the macro is called.

For example, go to a new line and start a macro with C-x ( and then hit C-a to move to the start of the line, C-x C-k C-i to insert the macro counter (initially zero) and then RET to go to a new line and C-x ) to stop the recording. Run the macro a few times with C-x e and then just e to repeat the macro and you’ll get something like this:

0
1
2
3
4

The counter starts at zero every time you define a new macro. To set it to another value, use C-x C-k C-c before defining or invoking a macro.

Insert file name

Here is a simple function from the emacs wiki to insert the name of a file into the current buffer. The convenient thing is that it uses the normal find-file prompt with whatever your completion setting is, so it works very easily. I bind it to C-c b i and as the documentation says, by default it inserts a relative path but called with a prefix (C-u C-c b i) it inserts the full path.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; insert file name at point                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; https://www.emacswiki.org/emacs/InsertFileName
(defun bjm/insert-file-name (filename &optional args)
  "Insert name of file FILENAME into buffer after point.

  Prefixed with \\[universal-argument], expand the file name to
  its fully canocalized path.  See `expand-file-name'.

  Prefixed with \\[negative-argument], use relative path to file
  name from current directory, `default-directory'.  See
  `file-relative-name'.

  The default with no prefix is to insert the file name exactly as
  it appears in the minibuffer prompt."
  ;; Based on insert-file in Emacs -- ashawley 20080926
  (interactive "*fInsert file name: \nP")
  (cond ((eq '- args)
         (insert (expand-file-name filename)))
        ((not (null args))
         (insert filename))
        (t
         (insert (file-relative-name filename)))))

;; bind it
(global-set-key (kbd "C-c b i") 'bjm/insert-file-name)