breathing code

crib notes on technology

Cocoa Emacs 23 as a Python IDE on MacOS 10.6 Snow Leopard: Part Two

leave a comment »

Background

I was introduced to Emacs early on in my career, and had familiarized myself with enough of its commands that I could perform basic editing tasks, but never learned to truly appreciate its power until a few years ago, when a pair programming session with Malthe Borch opened my eyes to how learning a single text editor well can significantly enhance productivity and make programming more enjoyable. Malthe’s workflow incorporated Emacs in a way that made programming seem effortless and fun, at least compared to my programming workflow when using Eclipse PyDev or TextMate. I was a TextMate user at the time, and I found myself feeling clumsy and slow when using the mouse as part of my TextMate workflow. During our pair programming session Malthe challenged me to use my editor without using the mouse. I was surprised at how much I actually depended on the mouse and how much that dependency was slowing me down. I then resolved to learn the keybindings for TextMate, and that definitely helped speed up my workflow when using that particular editor. I still found myself using the mouse for some things in TextMate such as navigating the project tree and open file buffers. I also missed several features of Emacs that Malthe had turned me on to such as multiple ‘windows’ per ‘frame’ and running shells inside buffers. I decided to give Emacs another try and really learn how to use a larger portion of its features. I am still learning, and it seems the learning won’t end, which I don’t mind. In fact, I enjoy learning, and with Emacs, there is always a new feature or mode to explore. There are limitless possibilities for configuration as well. Needless to say, many yaks (or gnus) have been shaved in preparation for this tutorial.

General Configuration

Like many Emacs enthusiasts, I have spent a good deal of time hacking a configuration to my liking. I have crafted my configuration files over several years, starting from the sections of .emacs files of colleagues such as Malthe that I have cargo-culted. Some of the core bits of functionality that I rely on every day come from that pair programming session at a sprint in the Austrian Alps, back in 2008.

I have checked my Emacs configuration into bitbucket, feel free to check it out. It should run out of the box with Emacs 23 on a Mac, with the caveat that you need all of the third party libraries installed that I’ve got installed. We’ll get to that part. For now, you should be safe just loading the dbrenneman-init.el file with the lines loading other dbrenneman-*.el files commented out with semicolons.

There are many options for configuring Emacs, and for this section of the tutorial, I’m going to stick to what I consider my base configuration.

I won’t be going over my emacs configuration line by line, but most of my config is fairly well commented. Cargo-cult to your liking.

Your Emacs configuration lives in ~/.emacs by default. You can edit your ~/.emacs configuration file in place. When you are ready to test your changes, simply save the file:

C-x C-s

Then enter the command:

M-x eval-buffer

This will reload your configuration without restarting Emacs.

I have opted for the ‘write your own config’ method of configuring Emacs, for the most part, rather than using the customize function from within Emacs.

One of the first options I configure in my .emacs file is the load path for my custom configuration files:

(add-to-list 'load-path "~/.emacs.d")

This allows me to put any Emacs elisp libraries in ~/.emacs.d/ and easily load them into Emacs.

I also start Emacs in server mode with the following directive:

(server-start)

With an Emacs running in server mode, you can use emacsclient to open files in your running emacs, you can even set emacsclient as your default EDITOR and use it for commit messages, etc. I have created a shell script that I use to call emacsclient with the proper flags for the given editing situation.

Here’s my ~/bin/emacsclient.sh:

#!/bin/bash
/Applications/Emacs.app/Contents/MacOS/bin/emacsclient -c

I have added the directory ~/bin/ to my PATH, and have made the ~/bin/emacsclient.sh file executable.

I have aliased the executable to ec in my shell initialization file, so I can then run ‘ec filename.py’ and have the specified file open in a new buffer in my running Emacs, and have the focus switch to the new buffer in Emacs as well.

I run midnight mode in the default configuration, which will run a command at midnight to clean up old and unused buffers.

I also load a library called lorem-ipsum, which allows one to easily generate as much lorem ipsum dummy text as one needs with a few keystrokes.

I have split my configuration into multiple files, which can help make a long configuration easier to deal with. I load each of these config files explicitly in my main .emacs file. In my bitbucket repository, the dbrenneman-init.el file is what I use as my ~/.emacs file. You can symlink it in if you like.

I turn tempbuf on for dired buffers, so that I don’t have to kill a bunch of dired buffers all the time.

;; turn on tempbuf mode for dired buffers
(require 'tempbuf)
(add-hook 'dired-mode-hook 'turn-on-tempbuf-mode)

I also run a nifty little function called uniquify that makes buffer names unique.

;; Unique Buffer Names - makes navigation of open buffers easier
(require 'uniquify)
(setq uniquify-buffer-name-style 'reverse)
(setq uniquify-separator "/")
(setq uniquify-after-kill-buffer-p t) ; rename after killing uniquified
(setq uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers)

I like TRAMP, it allows you to edit files on remote machines via ssh in a local Emacs buffer. Here, I set TRAMP to default to using ssh to connect to remote hosts.

;;TRAMP should default to ssh
(setq tramp-default-method "ssh")

Another function I find useful is the desktop. This function can be configured to save the buffers one has open in an Emacs session upon exiting the editor, and then reload the saved buffers when Emacs is started again.

;; load saved desktop on startup and save buffers to desktop on exit
(load "desktop")
(desktop-save-mode 1)
(desktop-read)
(setq desktop-load-locked-desktop t)

;; save a bunch of variables to the desktop file
;; for lists specify the len of the maximal saved data also
(setq desktop-globals-to-save
      (append '((extended-command-history . 30)
                (file-name-history        . 100)
                (grep-history             . 30)
                (compile-history          . 30)
                (minibuffer-history       . 50)
                (query-replace-history    . 60)
                (read-expression-history  . 60)
                (regexp-history           . 60)
                (regexp-search-ring       . 20)
                (search-ring              . 20)
                (shell-command-history    . 50)
                tags-file-name
                register-alist)))

A similar function is saveplace; when you enable it, it saves your place in each file you open when you close the editing buffer. When you re-open the same file in a new buffer, the cursor is placed in the same position it was in when the last buffer associated with that particular file was closed.

;; save our place when closing a file
(require 'saveplace)
(setq-default save-place t)

I also set global-auto-revert mode to true, so that any time a file connected to an open Emacs buffer changes on disk, the editor will attempt to reload the contents of the file from disk.

;; always revert buffers if their files change on disk to reflect new changes
(global-auto-revert-mode 1)

Next time I will discuss the configuration of modes such as ido and org modes. We’ll get to Python specific configuration in a future installment.

Advertisement

Written by David Brenneman

April 26, 2010 at 19:38

Posted in hacking, software

Tagged with , , ,

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.