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 (get-buffer 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)))))
(default (message "This buffer has no file name."))))


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:

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 RET /search/in/here/*.cxx 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.

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)

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.

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)

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.