Your eyes don't deceive you, that is a 5 1/4 inch drive - the processor direct slot has an Apple // card in it (which was designed for the LC, which my parents bought it with, but it works great in the Colour Classic).
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:
"Logs your mood"
(interactive "sHow are you feeling? ")
But the string form of argument to interactive is just a shortcut. You can easily supply some code instead, with a static completion list:
"Logs your mood"
(interactive (list (completing-read "How are you feeling? " '("happy""sad")))
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
((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)))
((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"
(let ((completion-ignore-case 't))
(concat "Enter subdir of " cdsrc-completions-prefix ": ")
(let ((path2 (concat cdsrc-completions-prefix path)))
(if (string-match mode-name "Shell")
(comint-send-string (current-buffer) (concat "cd " path2))
Comments are broken
Update: Comments are now fixed, both for registered and anonymous persons.
BTW, as well as the same hardware running for over 10 years, the same Linux installation (with security patches which eventually had to be backported after it stopped being supported) has been running that whole time. If I remember right, the maximum uptime was around 700 days - just short of two years. Unfortunately it had to be shut down then to move it to another power rail.
I felt a certain nostalgia poking around it's directory structure looking for anything I wanted to keep. It's probably the last server I've had with /usr/local/playground in a nod to russm. And certainly the last server I will ever run qmail on - it was so awesome, but the massively scalable queue based mail handling just doesn't work with today's spam probes.
Blog Categoriessoftware (41)
..heads up 'tunes (5)
..black and white (6)
..A day in Sydney (18)
..The Daily Shoot (6)
Book Review (2)