Tips, snippets and smug satisfaction for Launchpad's Emacs and XEmacs users.
Sorting the TAGS tables
make TAGS creates a tags table with the canonical package sorted first.
Add bzr-tools.el to your load-path and then use bzr-tools-grep to search all of the versioned files. This can help you catch code in txt or zcml files that an rgrep might not find.
Never have lint again!
This snippet, pinched from http://www.plope.com/Members/chrism/flymake-mode/view, runs pyflakes through flymake. That means unused imports and unrecognized names get highlighted, without you having to explicitly run anything.
Tested with GNU Emacs 22.214.171.124.
;; Run pyflakes with flymake. (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) ;; Work around bug in flymake that causes Emacs to hang when you open a ;; docstring. (delete '(" *\\(\\[javac\\]\\)? *\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[ \t\n]*\\(.+\\)" 2 4 nil 5) flymake-err-line-patterns) ;; And the same for the emacs-snapshot in Hardy ... spot the difference. (delete '(" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:( \n]+\\):\\([0-9]+\\):[ \n]*\\(.+\\)" 2 4 nil 5) flymake-err-line-patterns) (delete '(" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:( \n]+\\):\\([0-9]+\\):[ \n]*\\(.+\\)" 2 4 nil 5) flymake-err-line-patterns)
Sorting import statements
Chuck this in your .emacs, restart (or eval-region it), put the cursor between the ()s of a big nasty import statement and M-x sort-imports should straighten everything out (MichaelHudson).
BarryWarsaw 22-Oct-2007 -- made this portable between XEmacs and FSFmacs and renamed the command sort-imports
BradCrittenden 22-Oct-2007 -- sort-imports does not work with emacs21. Upgrade to emacs22 and it works just fine.
(defun join-words-wrapping (words separator line-prefix line-length) (let ((lines ()) (current-line line-prefix)) (while words (let* ((word (car words)) (maybe-line (concat current-line word separator))) (if (> (length maybe-line) line-length) (setq lines (cons (substring current-line 0 -1) lines) current-line (concat line-prefix word separator " ")) (setq current-line (concat maybe-line " ")))) (setq words (cdr words))) (setq lines (cons (substring current-line 0 (- 0 (length separator) 1)) lines)) (mapconcat 'identity (nreverse lines) "\n"))) (defun sort-imports () (interactive) (save-excursion (let ((open-paren (save-excursion (progn (up-list -1) (point)))) (close-paren (save-excursion (progn (up-list 1) (point)))) sorted-imports) (goto-char (1+ open-paren)) (skip-chars-forward " \n\t") (setq sorted-imports (sort (delete-dups (split-string (buffer-substring (point) (save-excursion (goto-char (1- close-paren)) (skip-chars-backward " \n\t") (point))) ", *\\(\n *\\)?")) ;; XXX Should this sort case insensitively? 'string<)) ;; Remove empty strings. (delete-region open-paren close-paren) (goto-char open-paren) (insert "(\n") (insert (join-words-wrapping (remove "" sorted-imports) "," " " 78)) (insert ")") )))
Quoting diffs for reviews
Emacs users: here's a little defun that makes the quoting part of the above workflow a little easier. Just mark the region of text you want to quote and do M-x baw-quote-region (or bind to a key of course). (BarryWarsaw)
(defun baw-quote-region (start end) (interactive "_r") (let ((fill-prefix "> ")) (indent-region start end nil)))
Note that this snippet only works with XEmacs. Testing in emacs-snapshot on gutsy gave this error: execute-extended-command: Invalid control letter '_' (137) in interactive calling string.
In XEmacs the underscore will not cause the region to be deactivated when the command completes. The equivalent would be to set zmacs-region-stays at the end of the function (but only if it's bound so that it wouldn't error on FSFmacs). I don't know if FSFmacs has the equivalent functionality. -- BarryWarsaw
And here's a version that works with GNU Emacs:
(defun equote-region () (interactive) (save-excursion (replace-regexp "^" "> " nil (region-beginning) (region-end))))
Spotting style issues while you edit
You can set up Emacs to highlight some common style issues - long lines, trailing whitespace, annoying silent TABs and such.
I used whitespace-mode.el from the GNU Emacs tree. The mode customization is difficult, so I just copied my custom variables here. This gives you long line highlighting, trailing whitespace, extra newlines at the end of the file, and bright red evil TABs:
(custom-set-variables ... '(global-whitespace-mode t) '(whitespace-style (quote (tabs trailing lines empty tab-mark))) ... (custom-set-faces ... '(whitespace-tab ((((class color) (background dark)) (:background "red1" :foreground "yellow")))) ...
For something lighter, you may want to set the show-trailing-whitespace variable - it will show trailing whitespace as bright red.
Get Emacs to clean up your whitespace
(defun baw-whitespace-normalization () "Like untabify, but also cleans up lines with trailing whitespace." (interactive) (save-excursion (save-restriction (untabify (point-min) (point-max)) (goto-char (point-min)) (while (re-search-forward "[ \t]+$" nil t) (let ((bol (save-excursion (beginning-of-line) (point))) (eol (save-excursion (end-of-line) (point)))) (goto-char (match-beginning 0)) (if (and (bolp) (eq (char-after) ?\)) (forward-char 1)) (skip-chars-backward " \t" bol) (delete-region (point) eol) )) ;; Now clean up any trailing blank lines (goto-char (point-max)) (skip-chars-backward " \t\n") (if (not (bolp)) (forward-char 1)) (delete-region (point) (point-max)) ;; But make sure the files ends in a newline (if (not (bolp)) (newline)) )))
Bugify and mail standup notes
Joey has asked that standup notes include the bug number and description. Kiko has contributed a script (lp-bug-ifier.py) to fetch the bug description for all bugs found in STDIN and spit it out on STDOUT.
The following script will copy the current buffer into a compose-mail buffer and bugify it. The launchpad list address is filled in as is most of the subject. It'll need to be customized for other teams than Foundations.
(defun bugify () (interactive) (mark-whole-buffer) (kill-ring-save (region-beginning) (region-end)) (beginning-of-buffer) (set-mark-command nil) (compose-mail) (end-of-buffer) (yank) (mark-whole-buffer) (shell-command-on-region (region-beginning) (region-end) "lp-bug-ifier.py" t) (beginning-of-buffer) (end-of-line) (insert "email@example.com") (next-line) (end-of-line) (insert "Foundations standup: 2008-") (delete-other-windows) )
Work with large files
Sometimes you may need to work with large files in Launchpad. To avoid Emacs prompting you about whether you really mean to bring that large file into a buffer, use this:
(setq large-file-warning-threshold nil)