Python-mode Customizations

I do some Python coding on my own, and so I have a few python customizations. Python-mode now comes with GNU Emacs, and so these work pretty much out-of-the-box. However, this does not get autoloaded, so you have to put the following before modifying python-mode-map or python-mode-hook.

(require 'python)

Before you start modifying python-mode-hook or python-mode-map or you get void-variable errors. Python-mode-hook is a collection of functions that gets run whenever python is entered, and python-mode-map is the list of keybindings that python-mode provides. Anyway, on to the customizations:

(add-hook 'python-mode-hook
          '(lambda () (eldoc-mode 1)) t)

I’ve talked about eldoc-mode before here. It is still one of my favourite minor modes, and I am greatly saddened whenever I realize a programming mode doesn’t have it. Fortunately, Python does, so I always know the arguments to my functions.

(defun my-insert-self ()
  "Insert self. at the beginning of the current expression."
  (interactive)
  (save-excursion
    (search-backward-regexp "[ \n\t,(-]\\|^")
    (if (not (looking-at "^"))
        (forward-char))
    (insert "self.")))
(define-key	python-mode-map	(kbd "C-;")	'my-insert-self)

I forget to type ’self.’ in front of my variables a lot. If this happens, I can use this function to insert it at the beginning of the variable name I’m currently typing. This ends up saving me a ton of keypresses; I no longer have to navigate to the start of the name and back. This is even more efficient then typing ’self.’ in front of variable names; Two key presses instead of five, if you include the Control.

(defun python-self-insert-command ()
  "appends __ to the string if it should"
  (interactive)
  (save-excursion
    (let ((cur (point)))
      (search-backward-regexp "[\n\t .(-]\\|^" 0 t)
      (if (not (looking-at "^"))
          (forward-char 1))
      (if (looking-at "\\s\__")
          (setq my-temp-var t)
        (setq my-temp-var nil))))
  (save-excursion
    (when (> (point) 2 )
      (backward-char 2)
      (if (looking-at "__")
          (setq my-temp-var nil))))
  (if my-temp-var (insert "__"))
  (self-insert-command 1))
(define-key	python-mode-map (kbd ".")	'python-self-insert-command)
(define-key	python-mode-map " "	        'python-self-insert-command)
(define-key	python-mode-map (kbd "(")	'python-self-insert-command)

This function similarly helps when I forget to append ‘__’ to private variables. I usually remember to put them at the beginning of a variable or function name, but often forgot the end. This function will check to see if the current function/variable starts with __, and if so append __ to it. This only occurs, of course, if __ is not already appended to the variable. I bind this function to space, period, and paren, so that I don’t have to actively think about this for it to happen. This function is more complicated than it seems it should be, but I haven’t quite figured out how to simplify it.

I haven’t investigated python-mode very much, since I’ve recently been using Python only lightly. Looking over it’s documentation, it looks like there are a few commands that could be quite useful, and the next time I write a significant project in Python I’ll definitely look through the manual, but these functions should tide me over until then. If you know of any cool commands in python-mode, don’t hesitate to let me know.

One final thing I was playing with that sounded very useful was ropemacs, an emacs integration of a python refactoring library. This provides refactoring and intellisense, but I could never get it to work. Ropemacs requires pymacs in order to run. Pymacs is a package for Emacs that attempts to enable you to use Python to modify Emacs instead of elisp, which I’d certainly be on board with. However, loading it into my emacs ended up installing a lot of hooks that didn’t work, making it difficult to even quit. I tried getting it to work, but never managed to. I also had a few philosophical problems with it, in that it used python’s egg system and did not allow me to specify where I wanted everything installed; this makes it hard to keep under version control so all of my computers can easily obtain it. If you know an easy way of getting it configured and working, please let me know; I’d love to be able to play around with it.

Tags: ,

4 Responses to “Python-mode Customizations”

  1. Basu says:

    I never got ropemacs to work right either. I think that this is one of the biggest weakpoints of the Python community: state-of-the-art tool support. I think someone really should sit down and crank out a full blown python mode with all the bells and whistles (completion, source code browsing etc). Might be a good GSoC project for someone interested enough.

  2. ralf says:

    I use the following to install rope:

    #! /bin/sh

    hg clone http://bitbucket.org/agr/rope
    hg clone http://bitbucket.org/agr/ropemacs
    hg clone http://bitbucket.org/agr/ropemode
    ln -s ../ropemode/ropemode ropemacs/

    easy_install rope
    easy_install ropemacs

    wget http://pymacs.progiciels-bpi.ca/archives/Pymacs-0.23.tar.gz
    tar xfv Pymacs-0.23.tar.gz
    cd Pymacs-0.23
    make
    easy_install .

    easy_install pysmell

  3. Luke says:

    What exactly does eldoc mode do? The only functions that it helps me with are built-ins (xrange, set, len, etc.) which isn’t all that impressive. Can you make it display documentation for methods as well?

  4. nflath says:

    Luke: I haven’t used Eldoc too much in python, but my testing shows it also works for standard library functions, such as random.randint(). The documentation for the function says that it does not work with methods, currently. While this isn’t as good as working for arbitrary methods, I find it’s a great deal better than nothing.

Leave a Reply