In the office I have to use Windows instead of my preferred OS X - no wonder, since we're developing a Windows application using .NET and IronPython.

I was quite used to TextMate by now (a very nice and powerful editor), but it has no Windows version, and it's alleged replacement, e isn't polished enough for my tastes.

After a bit of research, it seems that Emacs could suit my needs very well, since it's infinitely customizable, support python out of the box, and can be extended by either elisp or Python. It also helps that TextMate was based on Emacs, so there isn't going to be much weirdness.

This is a work in progress, so I'll state my goals below, in order of precedence.

  • Make it behave like a normal Windows application. The goal is to have someone used to TextPad sit on my desk and being able to do most tasks without cursing and swearing. Mostly Done using EmacsW32
  • Make it run a bunch of Python scripts related to our dev environment, like "Run Test suite", "Run single Test", etc. The output should go to an emacs buffer and be clickable. Also, have it jump from a module to its test and back. Mostly Done using PyMacs and a bunch of python scripts. Some nastiness there - will post further details. No clicky yet - will research that.
  • Have a TextMate like Python mode, with auto-indenting, snippets etc.
  • Have a symbol browser that will allow me to jump to a function/method in the current buffer.
  • Have a "Go to definition" function Mostly Done using ctags. I have to run ctags manually, but I'm sure I can automate this.

That's well enough for an Emacs newb. I'll post my findings and .emacs file as I work on it. A lot of this may already be built-in (I know there's a fairly comprehensive Python mode).

Some resources I've found, in no particular order

UPDATE: It seems that my emacs file is mature enough now. I'll copy it here for future reference. Please comment if you see anything stupid:

(setq load-path (cons (expand-file-name "C:\\elisp") load-path))

(require 'python)

(require 'linum)
(require 'highlight-symbol)
(require 'highline)

(ido-mode 1)

(defun my-python-hooks ()
  (linum-mode 1)
  (highlight-symbol-mode 1)
  )

(add-hook 'python-mode-hook 'my-python-hooks)

(global-set-key (kbd "C-S-h") 'highlight-symbol-at-point)

;; move cursor one line when going past end of page
(setq scroll-step 1)

;; jump to definition
(defun find-tag-noconfirm ()
(interactive)
(find-tag (find-tag-default)))
;; TODO: if no tags are found, try and run ctags -Rn in the source root
(define-key global-map  [f3] 'find-tag-noconfirm)
(define-key global-map  (kbd "S-") 'pop-tag-mark)

;; Camel case
(c-subword-mode 1)
(setq cua-keep-region-after-copy t)

;; no big prompts
(fset 'yes-or-no-p 'y-or-n-p)
;; no startup message
(setq inhibit-startup-message t)

(when (load "flymake" t) 
  (defun flymake-pyflakes-init () 
    (let* ((temp-file (flymake-init-create-temp-buffer-copy 
               'flymake-create-temp-inplace)) 
       (local-file (file-relative-name 
            temp-file 
            (file-name-directory buffer-file-name)))) 
      (list "pyflakes" (list local-file))))

(add-to-list 'flymake-allowed-file-name-masks 
           '("\\.py\\'" flymake-pyflakes-init)))

(add-hook 'find-file-hook 'flymake-find-file-hook)

;;;
;; Smart Tab

(defvar smart-tab-using-hippie-expand nil
  "turn this on if you want to use hippie-expand completion.")

(global-set-key [(tab)] 'smart-tab)
(defun smart-tab (prefix)
  "Needs `transient-mark-mode' to be on. This smart tab is
minibuffer compliant: it acts as usual in the minibuffer.

In all other buffers: if PREFIX is \\[universal-argument], calls
`smart-indent'. Else if point is at the end of a symbol,
expands it. Else calls `smart-indent'."
  (interactive "P")
  (if (minibufferp)
      (minibuffer-complete)
    (if (smart-tab-must-expand prefix)
        (if smart-tab-using-hippie-expand
            (hippie-expand nil)
          (dabbrev-expand nil))
      (smart-indent))))

(defun smart-indent ()
  "Indents region if mark is active, or current line otherwise."
  (interactive)
  (if mark-active
      (indent-region (region-beginning)
                     (region-end))
    (indent-for-tab-command)))

(defun smart-tab-must-expand (&optional prefix)
  "If PREFIX is \\[universal-argument], answers no.
Otherwise, analyses point position and answers."
  (unless (or (consp prefix)
              mark-active)
    (looking-at "\\_>")))

;; Use external python programs, using pymacs
(setenv "PYMACS_PYTHON" "C:\\Python25\\python.exe") 
(load "C:\\elisp\\pymacs.el")
(autoload 'pymacs-apply "pymacs")
(autoload 'pymacs-call "pymacs")
(autoload 'pymacs-eval "pymacs" nil t)
(autoload 'pymacs-exec "pymacs" nil t)
(autoload 'pymacs-load "pymacs" nil t)

;;(eval-after-load "pymacs"
;;'(add-to-list 'pymacs-load-path "C:/elisp/python"))
;; The above doesn't work, so I hack around.
(pymacs-load "PYMACSPATH")
(if (pymacs-load "rsl-util")
    (define-key global-map "\M-r" 'rsl-util-run-resolver)
  (define-key global-map  [f5] 'rsl-util-run-ironpython-file)
  (define-key global-map  [f6] 'rsl-util-run-single-test)
  (define-key global-map  [f4] 'rsl-util-jump-to-test)
  )

(python-setup-brm)

(defun close-window-and-buffer()
  (interactive)
  (kill-this-buffer)
  (delete-window)
  )

(setq skeleton-pair t)
(global-set-key "[" 'skeleton-pair-insert-maybe)
(global-set-key "(" 'skeleton-pair-insert-maybe)
(global-set-key "{" 'skeleton-pair-insert-maybe)
(global-set-key "\"" 'skeleton-pair-insert-maybe)
(global-set-key "'" 'skeleton-pair-insert-maybe)

;; Define some additional "native-Windows" keystrokes (^tab, Alt/F4, ^A, ^F, ^O,
;; ^S, ^W) and redefine (some of) the overridden Emacs functions.
(global-set-key [C-tab] 'other-window)
(global-set-key [M-f4] 'save-buffers-kill-emacs)
(global-set-key "\C-a" 'mark-whole-buffer)
(global-set-key "\C-f" 'isearch-forward)
(global-set-key "\C-z" 'undo)                   
(global-set-key "\C-o" 'find-file)
(global-set-key "\C-s" 'save-buffer)
(global-set-key "\C-n" 'make-frame)
(global-set-key "\C-w" 'close-window-and-buffer)
(global-set-key (kbd "C-S-o") 'open-line)
(global-set-key (kbd "C-S-w") 'kill-region)
(define-key global-map (kbd "RET") 'newline-and-indent) ; For programming language modes
(define-key isearch-mode-map "\C-f" 'isearch-repeat-forward)

(custom-set-variables
  ;; custom-set-variables was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 '(column-number-mode t)
 '(cua-mode t nil (cua-base))
 '(emacsw32-max-frames nil)
 '(emacsw32-mode t)
 '(emacsw32-style-frame-title t)
 '(global-highline-mode t)
 '(highline-priority 1000000)
 '(htmlize-view-print-visible t t)
 '(ido-default-file-method (quote other-frame))
 '(ido-enable-flex-matching t)
 '(ido-ignore-directories (quote ("\\`CVS/" "\\`\\.\\./" "\\`\\./" "\\`SVN/")))
 '(make-backup-files nil)
 '(menuacc-active t nil (menuacc))
 '(recentf-mode t)
 '(show-paren-mode t)
 '(speedbar-directory-button-trim-method (quote trim))
 '(speedbar-track-mouse-flag t)
 '(speedbar-use-imenu-flag nil)
 '(swbuff-y-mode t)
 '(transient-mark-mode t)
 '(w32-meta-style (quote emacs))
 '(w32-print-menu-show-print nil)
 '(w32-print-menu-show-ps-print nil)
 '(w32shell-shell (quote cmd)))
(custom-set-faces
  ;; custom-set-faces was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 '(highline-face ((t (:inherit highlight :background "#EEEFEF"))))
 '(linum ((t (:inherit shadow :background "#EEEFEF" :slant italic :weight extra-light)))))

In my elisp file, I have:

  • linum.el
  • python.el
  • sym-comp.el
  • pymacs.el
  • highlight-symbol.el
  • highline.el

and in elisp/python I have my rsl-util.py scripts that are project specific.

Please share!

February 28, 2008, 8:37 a.m. More (1003 words) 7 comments Feed
Previous entry: Porting to numpy
Next entry: On extreme programming

Comments

1

Comment by Alexander Solovyov , 4 years, 2 months ago :

Hehe, emacs is great. :-)

Few notes: try bs-show for C-x C-b, it is very useful for buffer switching (I've used ibuffer and tabbar earlier, bs-show is better) and iswitchb-buffer for C-x b (it powerful enough).

Look at winner-mode (undo and redo for window configurations).

And I'm sure you'll love those all mail, irc, jabber clients and other org-modes. ;-)

P.S. Here is my config: http://hg.piranha.org.ua/conf/file/ti...

2

Comment by Orestis Markou , 4 years, 2 months ago :

Made some nice progress, trying to understand how things work as I go along.

I'm >-< this close on being able to launch an external process and have it pipe stuff back into an emacs buffer. I'll have to find out how to make the output clickable.

Elisp seems easy enough, at least for normal things.

Should post some samples tomorrow evening.

3

Comment by Kamil , 4 years, 2 months ago :

You could just copy my vim setup, it does most of what you list plus more. :)

For example, I can run gvim with all my settings and plugins on any machine in our network off the shared drive. When I am pairing with someone on foreign machine I can still use my customized editor.

4

Comment by Orestis Markou , 4 years, 2 months ago :

I could, but I hate vim's modes! I could install viper mode on emacs just for you, though :)

I think I can also run emacs from the network, I'll have to look into it.

5

Comment by Orestis Markou , 4 years, 2 months ago :

This blog post: http://pigpog.com/node/2875 describes how to run emacs from a usb stick, I suppose I can change it around to run from the network...

6

Comment by Orestis Markou , 4 years, 2 months ago :

Also, for having tabs: http://amitp.blogspot.com/2007/04/ema...

7

Comment by Kamil , 4 years, 2 months ago :

My respnose to 'I hate vim's modes!': http://blog.kamil.dworakowski.name/20...


This post is older than 30 days and comments have been turned off.