It's been a while since I read RMS's paper on Emacs. Back in 1981, I still had another 2 years before I even saw my first computer. Reading the paper gives some insight into some of the issues they were trying to solve (real time display, extensibility, portability).
The first thing that came to mind when I first read this paper was that (to an outsider at least) Emacs really hasn't changed fundamentally since 1981 - the basic structures have held up well. I don't see any mention of subprocesses in the original paper, so that's something pretty fundamental that is new (since 1981). Of course the other obvious additions are MULE, image support, fonts, and the graphical interface.
Amusingly, vi was not mentioned in the Other Interesting Editors section. From reading the wikipedia article on vi, it certainly was available (it's a part of the Unix standard).
But what really struck me as interesting and powerful was the decision to use dynamic binding. I'd remembered playing with the differences between dynamic and lexical scoping in my SICP class in college, but never saw a reason to use it. Well, it totally fits when you want to customize Emacs' behavior.
The paper is certainly worth the 10 minutes it takes to read.
Wednesday, December 23, 2009
Emacs Paper from 1981
Wednesday, September 30, 2009
Emacs Tip #33: paredit
I recently found paredit. It is a mode which allows you to edit s-expressions (sexps) in a structured way.
Essentially it forces you to maintain balanced parentheses by always inserting/deleting matched pairs. It is very easy to modify the current sexp to: enclose (wrap) the next element, to merge it up one level (aka splice, i.e. remove a set of parentheses), to split the current sexp, etc.
It works with round parens ()
, square brackets []
, curly braces {}
, and angle braces <>
. It also handles string quotes "
the same way.
Deleting and killing of text also works nicely. For example, C-k
is bound to 'paredit-kill
which has the following behavior (note: |
represents the cursor position):
(foo bar)| ; Useless comment!It's taking a little getting used to, but I'm finding myself thinking less about where the current block of code ends than I used to. The parentheses just take care of themselves...
->
(foo bar)|
(|foo bar) ; Useful comment!
->
(|) ; Useful comment!
|(foo bar) ; Useless line!
->
|
(foo "|bar baz"
quux)
->
(foo "|"
quux)
This is how I enabled it:
(defun turn-on-paredit-mode ()
(paredit-mode +1))
;; I didn't like C-j being overridden, I want it to still work the old way in lisp-interaction
(eval-after-load "paredit"
'(progn
(define-key paredit-mode-map (read-kbd-macro "C-j") nil)))
(add-hook 'emacs-lisp-mode-hook 'turn-on-paredit-mode)
The cheat sheet is probably the best way to get an idea of what is possible. Check it out here. Also, the command documentation is very complete (see the above which was grabbed right from the
C-k
documentation, so it's easy to remind yourself what is possible.About the only problem I've had is when I've yanked code that has unbalanced parens. So I wrote a little advice which at least warns you and allows you to abort if the yanked text is unbalanced. It's not perfect, but it is a reasonable first implementation:
(defun paredit-check-region-for-yank ()
"run after yank and yank-pop to verify balanced parens"
(when paredit-mode
(save-excursion
(save-restriction
(narrow-to-region (point) (mark))
(condition-case nil
(check-parens)
(error
(if (not (y-or-n-p "The text inserted has unbalanced parentheses, continue? "))
(delete-region (point-min) (point-max)))))))))
(defadvice yank (after yank-check-parens activate)
(paredit-check-region-for-yank))
(defadvice yank-pop (after yank-pop-check-parens activate)
(paredit-check-region-for-yank))
Posted by a at 8:57 PM 5 comments
Labels: emacs-advanced, emacs-tip, lisp
Somewhat meta: blogs on reddit
Recently, doing a vanity search, I saw a link to this blog from reddit. I'm not a reddit user, but found it interesting that some of my posts had made it on there (as you can see here: trey-jackson.blogspot.com on reddit.com).
What I find curious about reddit as it applies to blogs is that it ends up taking the conversation away from the blog. This works well for reddit users, but ends up fracturing the audience. I don't get many comments (I have very few readers) and would have appreciated the reading the comments made on reddit.
For what it's worth, I did update a post to fix a coding bug noticed by someone on reddit (ironically, their fix had syntax problems at the same spot as well).
Posted by a at 10:43 AM 2 comments
Labels: meta
Tuesday, August 4, 2009
Emacs Tip #32: completion-ignore-case and Emacs 23
Everyone is all a-buzz over the new release of Emacs. I've started using it, and I do like the font support.
There was one surprise. I had the old setting(setq completion-ignore-case t)
because I hate typing capital letters when I can avoid it. Enter Emacs 23.1, and I now have to type capital letters for buffer names and file names (which is 90% of what I use minibuffer completion for). It turns out, there are two new variables, one for each of the types of completion:(setq read-buffer-completion-ignore-case t)
(setq read-file-name-completion-ignore-case t)
Everything else in the upgrade has been smooth.
Posted by a at 3:06 PM 1 comments
Wednesday, June 24, 2009
Emacs Tip #31: kill-other-buffers-of-this-file-name
A friend mentioned he wanted a way to get rid of all the other buffers visiting files that of the same file name. I instantly realized this was something I'd wanted for a long time without knowing it.
My usage is that I'm often viewing different versions of the same file, usually in different sandboxes. And, I might also have older versions checked out, whose file names are the same, but end with ".~1.12~" (or whatever version number was checked out).
I'm still old-school and don't use anything fancy for my buffer switching like `ido` or `icicles` or `iswitchb` or any of the other myriad of choices. And, as a result, it's a pain to switch because I have to now discern between the variants. Well, do that once, type `C-x K`, and that'll be the only buffer left for that file name.
(global-set-key (kbd "C-x K") 'kill-other-buffers-of-this-file-name)
(defun kill-other-buffers-of-this-file-name (&optional buffer)
"Kill all other buffers visiting files of the same base name."
(interactive "bBuffer to make unique: ")
(setq buffer (if buffer (get-buffer buffer) (current-buffer)))
(cond ((buffer-file-name buffer)
(let ((name (file-name-nondirectory (buffer-file-name buffer))))
(loop for ob in (buffer-list)
do (if (and (not (eq ob buffer))
(buffer-file-name ob)
(let ((ob-file-name (file-name-nondirectory (buffer-file-name ob))))
(or (equal ob-file-name name)
(string-match (concat name "\\(\\.~.*\\)?~$") ob-file-name))) )
(kill-buffer ob)))))
((message "This buffer has no file name."))))
Edited Sept. 30, 2009 to fix coding error.
Posted by a at 10:25 AM 2 comments
Friday, June 19, 2009
Searching GNU From Firefox
When writing up answers for Emacs related questions on stackoverflow.com, I like to include links to the info pages. I got tired of having to go to the gnu site and then do a google site-specific search. I tried looking for a Firefox search plugin that already did that (or something similar), but to no avail.
However, it's pretty easy to write the search plugin yourself. The main page for creating search plugins on mozilla's developer site gives you pretty much all you need to know, except for where to put the xml file. This page shows you that the installation dir is very likely C:\Program Files\Mozilla Firefox\searchplugins
.
You can read the documentation yourself, or just check out the snippet of XML I wrote.
Probably the "hardest" part was finding an icon, and the all-knowing google led me to the www.favicon.cc web page, where someone had drawn the standard GNU icon and made it available under a Creative Commons license:
Posted by a at 11:03 PM 3 comments
Labels: emacs, html, link, stackoverflow
Friday, June 12, 2009
Emacs Tip #30: igrep
Finding text in files is an everyday (every hour) occurrence for most programmers. And in Unix-land, people generally use grep
to do the searching.
Of course Emacs has an interface to grep, which now (as of Emacs 22) even has interfaces for using both find and grep together to search through directory structures (grep-find
, rgrep
).
But, before those existed, someone wrote a nice package igrep.el, which has a very intuitive (IMO) interface.M-x igrep-find RET
which will search for regexp
in all the files with the extension .cxx
underneath the /search/in/here/
directory.
As you'd expect, the results of the search show up in a buffer, and clicking on any one of them jumps you to that spot in the file. And the standard M-x next-error
(aka C-x `
) will jump you to the next match.
About the only thing I don't like is that the paths returned in the results are the fully expanded path. In other words, when the paths to the files are really long, most of the result buffer is taken up with just the pathname. So I wrote this little snippet of code which post-processes the buffer to trim the names relative to the search path entered (in the example above, all the /search/in/here/
would be removed from the file names.
(defun my-shorten-filenames-in-compilation (buffer &optional stat)
"remove the absolute filenames if they match the default-directory"
(interactive "b")
(save-excursion
(set-buffer buffer)
(goto-char (point-min))
(let ((buffer-read-only nil)
(base-dir (if (re-search-forward "find \\([^ ]+\\) " nil t)
(if (string-match "/$" (match-string 1))
(match-string 1)
(concat (match-string 1) "/"))
default-directory)))
(setq default-directory base-dir)
(while (re-search-forward (concat "^" default-directory) nil t)
(replace-match "")))))
(add-hook 'compilation-finish-functions 'my-shorten-filenames-in-compilation)
I do realize that the built-in
M-x rgrep
does this automatically, I just prefer the igrep
interface.Posted by a at 1:53 PM 1 comments
Labels: emacs, emacs-basic, emacs-tip, lisp
Tuesday, May 19, 2009
Emacs Tip #29: customizing hippe-expand
I read A Curious Progammer's post on customizing dabbrev - specifically to skip certain regular expressions at the front of words.
I remember customizing it for Tcl to avoid looking at the $ used to dereference variables. But, I no longer use dabbrev, I use the slightly more general hippie-expand. However, hippie-expand doesn't use the dabbrev settings.
So, the question is, can you get hippie-expand to do the same thing? The answer is, "yes" of course.
hippie-expand does things slightly differently - a little cleaner IMO. It uses syntax tables to determine what to skip. And, since syntax tables are set up appropriately for every mode, the skipping does what you want w/out having to potentially customize a regexp for each mode.
Syntax tables are Emacs' way of encoding the syntactic use of each character in a buffer, and this knowledge is used for motion and regular expressions. That's how forward-word has reasonable meaning in the various programming modes, text mode, shell mode, etc. Similarly, the syntax tables define list motion.
The syntax table has the basic character types: whitespace, punctuation, word, symbol, open/close parenthesis, string, comment start/end, etc. For example, the alpha-numeric characters are generally word constituents. In html-mode the <> symbols are matching parentheses, but in most other programming modes they are punctuation characters.
The variable you set is hippie-expand-dabbrev-as-symbol
, which defaults to t
. Basically, if non-nil, hippie-expand will try to expand the word under the point including symbol characters, which is not what I personally want. I want to only expand the word characters under my point, so I've set it to nil
.(setq hippie-expand-dabbrev-as-symbol nil)
Posted by a at 11:12 AM 1 comments
Labels: emacs, emacs-intermediate, emacs-tip, link
Friday, May 15, 2009
Stupid VNC Trick
At my office I have a dual monitor setup, and at home I have two monitors as well, so most of my VNC sessions are wide (3280 pixels).
Which presents a problem on the occasions I decide to work from a coffee shop or some other place where I only have my laptop's screen. How do you effectively interact with a VNC session where the session is twice the size of the physical screen?
Clearly scrolling the screen with the mouse is a lose.
My solution is to have two VNC viewers running simultaneously. One shows the right half of the session, and the other shows the left half. That way I can easily CTRL-TAB from one side to the other.
Simple, but pretty effective.
Posted by a at 12:09 PM 1 comments
Labels: vnc
Monday, April 27, 2009
dot-emacs trickery (emacs-fu)
It's been a while, and to be honest, emacs-fu has been doing such a great job putting up useful snippets of Emacs information...
He just put up a question asking for folk's favorite dot-emacs tricks. I added my two cents with:
(defun tj-find-file-check-make-large-file-read-only-hook ()
"If a file is over a given size, make the buffer read only."
(when (> (buffer-size) (* 1024 1024))
(setq buffer-read-only t)
(buffer-disable-undo)
(message "Buffer is set to read-only because it is large. Undo also disabled.")))
(add-hook 'find-file-hooks 'tj-find-file-check-make-large-file-read-only-hook)
Posted by a at 2:46 PM 0 comments
Labels: emacs, emacs-basic, link
Friday, March 27, 2009
Don't Like It? Code it Yourself!
Jeff Atwood writes on a topic that's interested me for quite a while:
Coding Horror: Don't Like It? Code it Yourself!
To me, at least, sponsorship seems like a constructive way for people who are unable or unwilling to write code to affect the direction of a project. For example, I've sponsored several bugfixes in a key .NET open source library that we use for Stack Overflow. These are bugfixes they considered low priority, but were serious issues for our site. I was happy to give back to the project, and it was certainly a more realistic option than us carving out a chunk of our own development time to contribute the bugfixes ourselves.
That said, I am concerned that this sort of aggregated sponsorship system hasn't naturally evolved on its own by now. Is it not sustainible, or incompatible with the kind of intrinsic motivations that drive most open source development?
In my previous job, we wrote software that heavily relied upon open source and GPL'ed software. The entire department developed and deployed software (primarily) for Linux systems, used gcc, Tcl/Tk, and a bunch of smaller open source tools. When compared to the more proprietary systems used (AIX, HP-UX), the savings were huge - both in software, hardware, and overall productivity.
At one point, the department decided to look into providing a "better"(?) debugging experience. After some research, they settled on a proprietary debugger. A year passed, licenses were finally purchased, and ... it was quietly released into the department, with very little fanfare.
I eventually found out about it, tried it out, and found the experience to be underwhelming to say the least. Several of the touted "features" were still in development (visualization of STL containers) and not to be delivered for another year, and the rest of the "features" had been in DDD/GDB for years. As an added hassle, it required the object files to be post-processed to obtain debugging symbols in their proprietary format.
To make a long story short(er), I found out we had paid many times my annual salary for a set of licenses for software that didn't have the features found in open-source software, and we had to pay this amount annually.
I fed this information up the chain of command, which just got the manager of software-development-environment angry at me. I proposed we use the money to instead hire a contractor to work on any bugs/enhancements for GDB/DDD, using the logic that not only would it be cheaper, it'd provide a return on investment faster, as well as be available to the entire department/company/world from here on out - at no extra cost. At the very least, it seemed to me, it was a tiny price to pay for the company's ability to use the open source Linux systems for development.
Management wasn't interested, not in the slightest. About the only argument they'd give me for keeping the status quo was that companies preferred working with other companies, and not contractors.
This always seemed to be more of a duck than a real argument.
I figured, if the software was good enough to use, it should be good enough to pay to improve.
Posted by a at 12:18 PM 2 comments
Labels: meta, opensource
Tuesday, March 3, 2009
More Advice
Way back when I wrote a tip about Emacs Lisp's advice.
How I wish other languages had this capability. A couple of questions came up recently on stackoverflow.com that were (imo) best answered using advice. So, if you're struggling to see when to use advice, I think they're pretty good examples.
"Diff, save or kill" when killing buffers in emacs
Can I change emacs find-file history?
Posted by a at 12:04 PM 0 comments
Labels: emacs, emacs-advanced, emacs-lisp, stackoverflow
Tuesday, February 17, 2009
Dynamic Modal Bindings (auto prefixing)
A guy posted an interesting question on stackoverflow:
Most emacs modes include some sort of prefix to activate their features. For example, when using GUD "next" is "C-c C-n". Of these modes, many provide special buffers where one can use a single key to activate some functionality (just 'n' or 'p' to read next/previous mail in GNUS for example).
Not all modes provide such a buffer, however, and repeatedly typing the prefix can be tiresome. Is there a well-known bit of elisp that will allow for ad-hoc specification of prefix keys to be perpended to all input for some time? (Until hitting ESC or some other sanctioned key, for example)
I don't think you want that (in general) because many of the prefix commands contain an extensive set bindings which clobber too many useful keys. That being said, I'm sure there are places this could come in handy.
I wrote up a solution that prompts you for a key sequence, and it promotes the prefix command keymap to the toplevel (associated with this particular minor mode). The minor mode is buffer specific, and it only allows one prefix command to be promoted at a time.
Check out my answer (won't put the code here in case I need to make an update).
Posted by a at 3:02 PM 0 comments
Labels: emacs, emacs-lisp, stackoverflow
Tuesday, January 13, 2009
Emacs Tip #28: e-blog
There are a number of different packages purporting to enable blogging from Emacs, but most people (including myself) have failed to get any of them to work.
I recently heard about: http://code.google.com/p/e-blog/, as a simple blogging package specifically for blogger.
This is my first post.
Note: It does depend on curl.