Cocoa development in Emacs
In this article
Presented here for your amusement are some directions on how I use Emacs, rather than Project Builder, as the primary focus for my Cocoa development time. These may be of interest to folks who like to use Emacs for everything, or for those folks coming from other Unix platforms and don’t like using Project Builder to edit source code.
The instructions presented here match my particular development style. I don’t mind my build environment having some rough edges. I don’t mind having to expend a little extra mental energy when doing my work. I also want to minimize keystrokes when it makes sense. I do want my compile and running and debugging turnarounds to be as fast as possible. (“Make Mistakes Faster” was the advertising tag line for a classic Mac C compiler.) Once my Emacs buffers get warmed up, I’ve gotten my compiling and running down to two keystrokes each. (Well, three if you count the Return key. From here on I’m not counting the Return key – nyah.) With everything running in one Emacs process, I never have to touch the mouse (or the annoying TiBook trackpad) while I’m reading or editing source code or browsing the system header files. (I do use Mail.app for mail reading and iCab to read the Cocoa documentation, so I’m not a complete GUI luddite.)
With that said, I presume you’re somewhat familiar with Emacs, the .emacs startup initialization file and how to add stuff to it, how to open files, how to move around and how keystrokes are described. For example, M-x goto-line [ret] 321 [ret] is typed as meta/Escape, then x, type goto-line (with tab completion if you so desire), Return, 321, Return). If you don’t know Emacs, you might want to run the built-in tutorial. (Start Emacs. Press Escape, then ‘x’, then type ‘help’, press Return, press ‘t’, then follow along.) O’Reilly (of course) has a book on Emacs.
Want to dig even deeper? Post to the new MacEdition Forums (beta)!
The shell inside Emacs
The Unix shell is a wonderful thing. You can batch process files
(line count of your source files:
wc -l *.[hm]) and
have pipelines of commands (find the pid of a program you want to kill:
ps auxw | grep myRunawayApp).
Using CVS, you can also do all of your revision control at the command
One (sometimes) overlooked Emacs feature is running a shell inside
an Emacs buffer. You do this with
M-x shell. *poof*.
You now have a
shell that will accept shell commands.
M-n keystrokes cycle you through
commands you’ve previously entered during that shell session. One
(frequently) overlooked Emacs feature relating to shells is you can rename
the buffer. I know – who doesn’t just love
the buffer name
I name my shell buffer “qwe” via
M-x rename-buffer [ret] qwe [ret]. (which
is even faster if you do
M-x ren [tab] b [tab] qwe [ret]
and have Emacs do its command completion) Why such a weird name like
“qwe”? On the US keyboard (which I’m using), “qwe” is
really fast to type. To bounce to my main shell, I just do
C-x b qwe [ret] (5 keystrokes). Notice I said
mainshell. After you rename your shell, you can create another one with
M-x shell. (That one I name “asd”.) That’s
very handy if you frequently run commands out of two different working
directories. In my
qwe buffer, I
cd /some/directory and in the
cd /some/other/directory/baby. I find bouncing
between Emacs shell buffers much faster than repeatedly changing
directories in a single shell. Another advantage is that each shell will
have its own command history, allowing for some handy shell shortcuts. One
downer is that some shell built-in control keys (like
C-n to cycle through the history) don’t work in Emacs.
As a wise muppet might have once said, “To you this command history useful to you what is, hrrrrmmmm?” (Or something like that.) So what is this shell command history, and why is it useful for me in freeing myself from the shackles of Project Builder? I’m glad you asked, hrrrrrmmm?
The shell maintains a history of the last hundred or so commands that
you have done. You can use some keystrokes to cycle through these
commands or to search backwards for an interesting command. That’s
all well and good, but I never use those features. Instead, I use
!x . No, that’s not cursing at you.
!! (I pronounce
bang-bang) says, “Paste in the complete previous command,” while
(which I pronounce as bang-string – yeah, I learned to program using
BASIC, and I’m proud) says, “Paste in the last word of the previous
command,” where word is the last blob of characters with a space
!x executes the most recent command that starts
So What. Big Deal.
Here’s where things get fun. Say you have a complex command:
% find / -name "flargle.[mh]" -print
(on your file system, print out the full path of any file named
... that you had to interrupt and want to re-run. You can just redo the
command by doing
Or, if you decided you wanted to re-run the command, but direct output to
a different file:
% !! > /tmp/oopack
... or if you wanted to put all of those files into a tarfile for
% tar cf ~/flarglefiles.tar `!!`
(The backticks execute the
find command in a subshell, then
contents into the
tar command, which then gets executed.)
Now, say you’ve done a bunch of other commands, but now want to run
find command again. You can use the shell or
Emacs command history keys to laboriously cycle through commands, or you
to execute the most recent command that starts with ’
f’, which hopefully will be your
find’ command. As you get accustomed to living
on the command line and using the
of commands, you’ll develop an awareness of commands in your history.
Now what about the
!$ combination which pulls off the last word
of the previous command? Here are some quick examples:
% ls -l some-file-name-blah.h
(To see the file size, permissions, etc. Presumably you used tab completion for the file, or you typed the whole thing just for fun.)
% wc -l !$
(You’ve just now computed the line count without retyping any of the file name again.)
% cvs diff !$
(Use CVS to show the differences in this file from what’s in the source code management repository.)
% cvs commit -m "twiddled the blargleflah" !$
(And now you’ve checked in your changes.)
That’s four different commands working on the same file, and you only really had to specify the file name once.
Of course, the nitpickers in the audience will say, “Yo! That
!$ paradigm thingie will break if you deal with more than one
file name at a time.” And to those nitpickers I say, “Well, yeah.”
Like I said In The Beginning, I don’t mind some rough edges. If I
need to work with multiple file names in one line, I’ll use the shell
or Emacs commands to cycle through the history and edit the command.
For a great majority of the time I’m dealing with one file
some operations, so
!$ works perfectly well.