Showing posts with label elisp. Show all posts
Showing posts with label elisp. Show all posts

Wednesday, February 24, 2010

Tab completion for meta-bang shell commands (Wednesday Emacs blogging)

You probably use M-! to run a quick shell command now and then, when you don't want to be bothered with a full M-x shell. But if, like me, you're a former XEmacs user, then you probably find FSF Emacs' default lack of tab-completion for files in the minibuffer rather annoying. Well, your pain ends here:

(if (not (string-match "XEmacs" emacs-version))
    (progn
      (defadvice read-from-minibuffer
        (around tab-is-pcomplete-in-minibuffer activate)
        "Bind TAB to pcomplete in minibuffer reads."
        (let ((keymap minibuffer-local-map))
          (define-key keymap "\t" 'pcomplete)
          (ad-set-arg 2 keymap)
          ad-do-it))))

Ta-da. Now when you M-! mv LongAnnoyingFileName.java LongAnnoyingFileNameFactory.java, you'll be able to tab-complete the filename.

Incidentally, who knew that elisp supported aspect-oriented programming? Apparently it does. Astonishing. I owe this tip to a co-worker, who I'd name except that I doubt he'd want to be associated with the other content on this blog. (p.s. AF, if you ever run across this post and don't mind being credited, I'll happily add your name.)

Wednesday, June 04, 2008

Soft word wrap for long lines (Wednesday Emacs blogging)

The short story: Use M-x longlines-mode.

The long story: longlines-mode is a minor mode that enables "soft wrap" for Emacs text. In longlines, lines will be displayed wrapped on word boundaries, as under most word processors (but not most text editors). This is useful for editing certain textual formats like HTML or wiki markup.

longlines comes bundled in FSF Emacs 22, but for earlier versions (or XEmacs) do the following:

  1. Get longlines.el, from the longlines Emacs Wiki page.
  2. Copy longlines.el somewhere on your load path. (To add a directory to your load path, add a line (add-to-list 'load-path "/path/to/directory/") to your .emacs)
  3. Add (require 'longlines) to your .emacs.

longlines-mode is a minor mode, and does not automatically hook itself into any major modes. You can hook longlines automatically in the standard fashion:

(add-hook 'html-mode-hook
          '(lambda () (longlines-mode)))

Alternatively, you can simply do M-x longlines-mode to toggle the minor mode manually, as I suggest above.

Once you get started with longlines, you'll probably want to customize its settings to taste. For example, by default the word wrap width won't automatically adjust to the window size. To see all relevant customizable settings, use M-x customize-group [enter] longlines [enter].

Incidentally, this feature is astonishingly obscure and late to arrive to Emacs, given that it's been a standard menu item in crippled brain-dead text editors like Windows Notepad for over a decade. Yet another example of how open source software development is not rationally optimized to serve the needs of the user.

Wednesday, November 08, 2006

Unix man page lookup (Wednesday Emacs blogging)

Today's a quick one:

; man page lookup (by default, f1 is help, but I
; already know how to bring that up using C-h)
(define-key global-map [f1]
  (lambda () (interactive)
    (manual-entry (current-word))))

As the comment implies, by default f1's bound to Emacs help. But of course, longtime Emacs users know how to acces the rich interactive help system using C-h; C-h ? ? gives you a list of the main C-h functions, but here are some favorites that I hit reflexively almost once a day:

C-h a
"Apropos" help: looks up anything (including both functions and variables) matching a substring
C-h b
List all key bindings in the current mode
C-h k keystroke
Look up the function bound to this keystroke

So, what do you really need that f1 help for? Looking up a Unix manpage on the current word is much more useful, especially in M-x shell mode or other modes where you're editing shell commands.

Wednesday, November 01, 2006

Fast access to dired file manager (retroactive Wednesday Emacs blogging)

Despite the existence of modern graphical file managers, I still find myself dropping into Emacs dired-mode ("the directory editor") for file management surprisingly often.

I haven't really figured out why. Certain operations just seem easier or faster in dired. Maybe it's because I can use Emacs idioms like incremental search (C-s) for moving to files and directories, and dired-advertised-find-file (f) to open things, which makes navigation speedier than scrolling and mousing inside a folder window. Maybe it's because (unlike graphical file managers) you can mark files (m) for an operation without fear of losing that selection on an errant mouse-click or keystroke. Or maybe it's because of little things like tilde (~), which marks all files in the current dired buffer that match the glob *~ for deletion.

Anyway, calling dired on the current directory when you're editing a file is extremely useful. Accordingly I've bound a keystroke to this function:

; F4 for dired buffer of the current directory in the other window
(define-key global-map [f4] (lambda () (interactive)
    (dired-other-window default-directory)))

The above Elisp binds F4 to open dired on the current directory. If you're a Unix user, then some directories have dotfiles (files whose names begin with .) that you'd rather ignore sometimes. Accordingly, I've also got a binding that uses a regexp to filter out all dotfiles from the view:

; F8 to open dired buffer of the current directory without dotfiles
; in other window
(define-key global-map [f8] (lambda () (interactive)
    (dired-other-window (concat default-directory "[^.]*"))))

Wednesday, October 25, 2006

Scroll bindings (Wednesday Emacs blogging)

Part of the Zen of Emacs is the fact that --- in contrast to merely mortal text editors or word processors --- you need not move your hands from the default typing position for common navigation tasks, like moving to the beginning of a line (C-a) or word (M-b).

Clearly, therefore, it is uncivilized to use arrow keys, or to move your hand to the mouse and hunt for that little arrow on your scroll bar, when you merely want to scroll up or down a couple of lines. Accordingly, the following elisp binds downwards and upwards scrolling to the M-n and M-p keystrokes respectively.

; Handy incremental scrolling keys
(define-key global-map "\M-n" (lambda () (interactive) (scroll-up 1)))
(define-key global-map "\M-p" (lambda () (interactive) (scroll-down 1)))

I chose M-n and M-p to be mnemonic "cognates" with C-n and C-p. Note that scroll-up is so named because it moves the document up, which makes the viewport appear to scroll down, and vice versa for scroll-down.

Nevertheless, it is sometimes convenient to do scrolling with your mouse --- e.g., if your hand's already there because you're switching focus among open windows. Recent Emacsen understand the scroll wheel, but some older versions do not. Fortunately, they can be taught, using the following recipe suitable for either (FSF) .emacs or (XEmacs) .xemacs/init.el:

; Mouse wheel: scroll up/down; control-wheel for pgup/pgdn.
(defun wheel-scroll-up   ()   (lambda () (interactive) (scroll-up 2)))
(defun wheel-scroll-down ()   (lambda () (interactive) (scroll-down 2)))
(defun wheel-scroll-pgup ()   (lambda () (interactive) (scroll-up 20)))
(defun wheel-scroll-pgdown () (lambda () (interactive) (scroll-down 20)))
(cond
 ((string-match "XEmacs" emacs-version)
  (progn
    (define-key global-map 'button5 (wheel-scroll-up))
    (define-key global-map 'button4 (wheel-scroll-down))
    (define-key global-map '(control button5) (wheel-scroll-pgup))
    (define-key global-map '(control button4) (wheel-scroll-pgdown))))
 (t ; FSF Emacs uses weird [bracket] keymap specifiers.
  (progn
    (define-key global-map [mouse-5] (wheel-scroll-up))
    (define-key global-map [mouse-4] (wheel-scroll-down))
    (define-key global-map [C-mouse-5] (wheel-scroll-pgup))
    (define-key global-map [C-mouse-4] (wheel-scroll-pgdown)))))

This recipe also binds C-mouse-4 and C-mouse-5 to page-down and page-up, for handy fast scrolling, which does not come standard even on recent Emacsen. It should be pretty obvious how to customize it to scroll more or fewer lines at a time.

Wednesday, October 18, 2006

Rotating background colors (Wednesday Emacs blogging)

Like every veteran Emacs user, I've long used multiple buffers, multiple windows in a buffer (C-x 2) and multiple frames (C-x 5 2) to edit multiple files simultaneously during heavy sessions of programming or writing. Lately I've been working on a monitor so vast, and reading so many different files simultaneously, that I've found it useful to run multiple instances of Emacs as well. (Among other things, this speeds up tab-completion when switching buffers with C-x b, because each instance has shorter buffer list.).

When running multiple Emacs instances, it gets hard to tell which frame corresponds to which running instance of Emacs. The following Elisp code enables rotation among a set of background colors on a keystroke:

(defvar background-color-rotation
  '("aliceblue" "thistle" "lemonchiffon" "khaki" "papayawhip"
    "honeydew" "mistyrose" "paleturquoise")
  "List of background color names to rotate")
(defun next-background-color ()
  "Rotates among colors in background-color-rotation."
  (set-variable 'background-color-rotation
                (append (cdr background-color-rotation)
                        (list (car background-color-rotation))))
  (car background-color-rotation))
(define-key global-map [f10]
  (lambda ()
    (interactive)
    (set-face-background 'default (next-background-color))))

Paste this into your startup file for recent FSF Emacs (.emacs) or XEmacs (.xemacs/init.el). As always you can also try it out quickly by pasting into your *scratch* buffer and using C-j to evaluate the defvar, the defun, and define-key expressions in turn. Once the above has been evaluated, hit F10 to rotate among the named background colors.

The code's pretty trivial, so if you know Elisp --- or even if you don't --- it should be relatively straightforward to customize it for different colors, or a different keystroke. To list all the color names your display supports, use M-x list-colors-display.

I considered making the macro save the background color rotation between Emacs invocations, so that each new instance would automatically come up with a different background color. It wouldn't be too hard to do this, but I decided it didn't fit the way I work. I like to have a particular color correspond to a particular task --- "aliceblue" for general hacking (the first Emacs I open when I login), "thistle" for writing notes to myself, etc. --- so I prefer to do the rotation manually.

Incidentally, note the use of string arguments to defvar and defun to document the function and variable. Some Python advocates tout Python's "innovative" and "unique" use of string literals in class and function bodies for documentation comments. I agree that it's a clever idea, but it predates Python by several decades. There's a reason that Emacs is called the "extensible, self-documenting display editor".

P.S. The title of this post declares my intention to post a random section from my Emacs init.el files every week until I run out of things to describe. My startup Elisp has been on the web for ages, but I think that having a well-titled blog post for individual tweaks will make better Google-food, and will therefore be more useful to the world.