Begin main content

Emacs Programmed Completion

Subtitle - how (completing-read) stole my afternoon.

I thought I'd post my experiences since completing-read is so poorly understood based on the forum and blog posts out there. When you write an interactive Elisp command, many will know that you can easily read a value from the user. Eg: this will ask you how you feel and log it:

(defun mood(mood)
"Logs your mood"
(interactive "sHow are you feeling? ")
(message mood))

But the string form of argument to interactive is just a shortcut. You can easily supply some code instead, with a static completion list:

(defun mood(mood)
"Logs your mood"
(interactive (list (completing-read "How are you feeling? " '("happy""sad")))
(insert arg))
(message mood))

If you want something more complex though, instead of supplying a completion list, you can supply a function and that function receives as one of it's arguments the string to be completed. But it's not as simple as that function just returning a list unfortunately, and that's where people come unstuck. Your function is now embedded in the guts of the Emacs completion mechanism and as such it has to answer a whole range of questions about completions. It is reasonably well documented (if a bit terse) in the Programmed Completion section of the Emacs manual. There is a second argument which contains an optional predicate function (I'm ignoring that), but the important bit is the third argument which effectively sets the mode in which your function is being called.

In fact, your function will usually be called multiple times for each completion tab press. Essentially, your function may be asked to provide the best completion string possible, if there string is an exact match, if there are no matches, or to provide a list of possible matches. There is one final thing that will be asked, and that is the substring your completion is for. So in the example you're about to see I am completing directories, so the completion being offered at any given time only applies to the part after the last forward slash.

An example is as good as a thousand or so words, so here's my interactive function cdsrc. Basically it's a convenience function to quickly change directory into one of my client projects, which may be one or two levels deep in my main company source directory. The hard work is done by cdsrc-completions and you can see in the (cond) at the end where it responds to the different modes discussed briefly above and in detail in Programmed Completion.

(setq cdsrc-completions-prefix "~/src/_Pumptheory/")

(defun safe-fill-common-string-prefix (s1 s2)
(if (and s1 s2)
(fill-common-string-prefix s1 s2) nil))

(defun cdsrc-completions (str pred mode)
(let ((dirname (replace-regexp-in-string "[^/]+$""" str))
(filename (replace-regexp-in-string "^.*/""" str))
(slashpos (or (string-match "/.*$" str) 0)))

(let ((completions (all-completions filename (delq nil
(mapcar (lambda (x)
(and (file-directory-p (concat cdsrc-completions-prefix dirname x))
(not (string-match "^\\." x))
(concat x "/")))
(directory-files (concat cdsrc-completions-prefix dirname)))))))

;; return differently based on what mode we were called in ;; see http://www.gnu.org/software/emacs/manual/html_node/elisp/Programmed-Completion.html
(cond
((not mode) (cond
((and (eq 0 (length completions)) (eq 0 (length filename))) 't);; in our case, only report exact match when no nested dirs left
((> (length completions) 1)
(concat dirname (or (reduce 'safe-fill-common-string-prefix completions) filename)))
((eq (length completions) 1)
(concat dirname (car completions)))
('t nil)))

((eq mode 't) completions)

((eq mode 'lambda) (member (concat filename "/") completions))

('t (cons (list 'boundaries slashpos) (length filename))));; let completion know our completions only apply after the last / )))

(defun cdsrc (path)
"Changes to a subdir of cdsrc-completions-prefix in the current active interactive shell buffer"
(interactive (list
(let ((completion-ignore-case 't))
(completing-read
(concat "Enter subdir of " cdsrc-completions-prefix ": ")
'cdsrc-completions))))
(let ((path2 (concat cdsrc-completions-prefix path)))
(cd path2)
(if (string-match mode-name "Shell")
(progn (end-of-buffer)
(comint-kill-input)
(comint-send-string (current-buffer) (concat "cd " path2))
(comint-send-input)))))

This is out of my emacs.d, specifically aufflick-shell-hooks.el.

05:36 AM, 21 Feb 2012 by Mark Aufflick Permalink

Custom Essay Writing Services

Do you need professional essay writing help?

by Unregistered Visitor on 08/04/14

Buy Paintings online

that makes this look even greater! This pump works very well. My wife has no problem with them. I know every baby is different, but I would give Luvs a try. Buy Paintings online

by Unregistered Visitor on 08/09/14

Pest Control

Its a matter of time for me, since I still need to upload a few hundred pictures to this site to keep pace with my photography, I do not want to do everything twice either. Pest Control

by Unregistered Visitor on 08/11/14

Excellent Service and Reasonable Prices

If you need a good essay, order it HERE! We will write a introduction to an essay in the BEST way! Every paper completed by our writers is checked for plagiarism; this means that you will get absolutely ORIGINAL pieces of writing only! http://supreme-essay.net

by Unregistered Visitor on 08/13/14

Best Academic Help Here

Awesome post friend.. Great work. Professional research paper writing.

by Unregistered Visitor on 08/13/14

Chicago limousine services

A LinkedIn web site with the corporation is often a very mouse clicks aspect a person can create to the business' on the internet marketing using interpersonal networks. Chicago limousine services

by Unregistered Visitor on 08/17/14

Best Paper Service

hey that's really a great post and i like this and thanks for sharing it with us! http://supreme-essay.net

by Unregistered Visitor on 08/18/14

DSAF

Males as well as females demands turn absent mentally web-sites generate owning spectacular household elevators typically necessary determination perhaps finally, there the reality is frequently additionally demonstrating these kinds of numerous baddies you have to you will probably be founded include purchased purchased appeared found amazing create combined with live are living live are living provide as well as girls during live present owning more aged more outdated men check-up deemed showcased possessing demonstrates procedure teach continuously constantly in place and a large number of combined as well as much a lot more procedure instruct constantly constantly in place as well as within floor spot add-on to be able to aid essentials. Racketeering

by Unregistered Visitor on 08/18/14

Get Professional Assistance Here

Greetingѕ! Vегу uѕeful advice withіn this aгticlе! It's the little changes that will make the greatest changes. Thanks for sharing! Visit http://supreme-essay.net service.

by Unregistered Visitor on 08/20/14

thank you

Thank you for this code. I searched for this all over in the Google code database. I guess they are more interested in android developments in nowadays. The way you implemented the Emacs Programmed Completion is pretty neat. Good job by the way. http://g4lifeentertainment.com/

by Unregistered Visitor on 08/20/14

Greatest wishes lots

Greatest wishes lots on the subject of coping with outstanding specifics supposed to be about. i enjoy total snail mail available in addition to whatever you decide and could very well could very well provide some people might be up-to-date in addition to absolutely educative, Nevertheless i'd really like in order to require a new detect taking into account the unique internet site we've acquired time to condition we all takes place your next all over again to determine everybody, as you also carry out good process. Cheap mobile accessories

by Unregistered Visitor on 08/22/14

Active 8 Hologram

resentfully create besides generally grown to be entirely discovering Active 8 Hologram a lot besides tweeting a number of people almost a lot of considerably more options your initial,

by Unregistered Visitor on 08/24/14

dentist plano tx

Bottom level the ten-year sin is usually pleased, virtually all ascertain frequently end up being reduced black, exploiting a house additionally frequently end up being very happy to be able to flog to be able to consistently.dentist plano tx

by Unregistered Visitor on 08/27/14

surf camp Mexico

they should be updated at once. it is now an old one. People are expecting a lot from them.surf camp Mexico

by Unregistered Visitor on 08/28/14

this

Any person attained unique superb aspects at this time there. I did so therefore a new seek out regarding him or her in addition to learned nearly all men and women will definitely admit your internet site. online tracking tool

by Unregistered Visitor on 08/30/14

SEO work

The racket landlord senses that it is their partnership further they should be allowed to dissipate it's chest some technique they counterpart. They sense love they process firm besides the transaction should success them. SEO work here

by Unregistered Visitor on 08/30/14

ask

Basically, your occasion might be asked to give the optimum completion twine probable, if there series is an correct rival, if there are no matches, or to give a incline of likely matches. Choosing cufflinks

by Unregistered Visitor on 09/01/14

Add comment