Cheat productively in Emacs 0

Posted by sjs
on Tuesday, August 21

By now you may have heard about cheat, the command line cheat sheet collection that’s completely open to editing, wiki style. A couple of weeks ago I posted cheat.el which allows one to cheat from within Emacs. There’s an update. However, before I get to cheat.el there’s a small detour.

Cheat is not just about Ruby! A few examples of cheats available are:

  • bash and zsh
  • $EDITOR (if you happen to like e, TextMate, vi, emacs, RadRails, ...)
  • GNU screen
  • Version control (darcs, svn, git)
  • Firebug
  • Markdown and Textile
  • Oracle and MySQL
  • Regular expressions
  • and of course Ruby, Rails, Capistrano, etc.

As of today, Aug-21 2007, the count is at 166 cheat sheets so there’s probably something there that you’ll want to look up from the command line or Emacs sometime. That’s enough stroking cheat’s ego, but there seems to be a notion that cheat is only for Ruby stuff and that’s really not the case.

So what’s new in this version of cheat.el? Completion! The only thing that bothered me about cheating in Emacs was the lack of completion. It now has completion, thus it is now perfect. :) In all likeliness this won’t be the last release, but I can’t really foresee adding anything else to it in the near future. Enjoy!

Download it now: cheat.el

For any newcomers, just drop this into ~/.emacs.d, ~/.elisp, or any directory in your load-path and then (require 'cheat). For more info check the original article for a rundown on the cheat commands.

Cheat from Emacs 5

Posted by sjs
on Friday, August 10

Update: I had inadvertently used string-join, a function provided by something in my ~/.emacs.d. The script has been updated to work with a vanilla Emacs (23, but should work with 22 as well).

Update #2 [2007.08.10]: Editing cheats and diffs have been implemented.

Update #3 [2007.08.21]: I added completion to cheat.el. The file linked on this page is still the latest version.

We all know and love cheat. Now you can cheat without leaving Emacs (and without using a shell in Emacs).

Just save cheat.el in ~/.emacs.d and then (require 'cheat) in your ~/.emacs. I also bind C-z C-c to cheat, you may want to do something similar.

You can’t do everything you can do with cheat on the command line yet, and for most of the commands the cheat command itself is used. Now you can do everything the command line client does from within Emacs, though you may need to revert to using cheat-command (described below).

Here’s the rundown:

Any time you enter a cheat name there are both completion and a cheat-specific history available. Unless you are adding a new cheat. In that case you should use a new, unique name (duh).

  • cheat – Lookup a cheat sheet interactively (cheat <name>)
  • cheat-sheets – List all cheat sheets (cheat sheets)
  • cheat-recent – List recently added cheat sheets (cheat recent)
  • cheat-versions – List versions of a cheat sheet interactively (cheat <name> --versions)
  • cheat-clear-cache – Clear all cached sheets.
  • cheat-add-current-buffer – Add a new cheat using the specified name and the contents of the current buffer as the body. (cheat <name> --add)
  • cheat-edit – Retrieve a fresh copy of the named cheat and display the body in a buffer for editing.
  • cheat-save-current-buffer – Save the current cheat buffer, which should be named *cheat-<name>*.
  • cheat-diff – Show the diff between the current version and the given version of the named cheat. If the version given is of the form m:n then show the diff between versions m and n. (cheat <name> --diff <version>)
  • cheat-command – Pass any arguments you want to cheat interactively.

(Added) I may add support for --diff and --edit in the future.

Please do send me your patches so everyone can benefit from them.

Emacs tips 0

Posted by sjs
on Thursday, August 09

This is my collection of Emacs tips or commands that I keep around for quick reference. Perhaps someone else will find something they like here.

Download the text (2007.08.18): ↓ emacs-tips.txt

Emacs tips
==========

Time-stamp: <2007-08-18 17:40:08 sjs>

Inside an incremental search:
  * C-w pulls in the word under point
  * C-y pulls in the rest of the line from point
  * M-y yanks the last text from the kill ring

Keybinding   Function                                Description
----------   --------                                -----------

==Help
C-h c        describe-key-briefly                    Display the name of the function bound to the given key sequence.
C-h k        describe-key                            Display documentation for the function bound to the given key sequence.
C-h w        where-is                                Display key sequences bound to the given command name.
C-h l        view-lossage                            Display the last 100 keystrokes.
C-h m        describe-mode                           Display documentation on the current major mode.

** C-h after any prefix key will display all available shortcuts under that prefix. **

==General
             word-search-{forward,backward}          Search for sequences of words across newlines & puncuation.
C-x $        set-selective-display                   Hide lines indented greater than ARG levels (folding).
             follow-mode                             Scroll windows of the same buffer in harmony.
C-x =        what-cursor-position                    Display details about what's under the cursor.
C-x z        repeat                                  Repeat the most recently executed command.
C-x ESC ESC  repeat-complex-command                  Edit and re-evaluate the last complex command (or ARGth command).
             list-history-command                    List commands available for repitition (via repeat-complex-command).

==Mark and point
M-r          move-to-window-line                     nil ARG: Move to the middle of the window.
                                                     ARG > 0: Move point to the ARGth line.
                                                     ARG < 0: Move point to the |ARG|th line from the bottom.
C-x h        mark-whole-buffer                       Mark the entire buffer.
C-x C-x      exchange-mark-and-point                 Exchange mark and point, reactivating mark if required.
C-SPC        set-mark-command                        Set and activate the mark, C-u C-SPC pops the mark ring.
C-x C-SPC    pop-global-mark

A prefix of 0 (C-u 0) has a special meaning for the transpose family of functions. Since it would otherwise be meaningless
it transposes the chars/words/sexps/lines around the region specified by point and mark. It's best to try this one out to
see exactly how it works!

C-t          transpose-chars
M-t          transpose-words
C-M-t        transpose-sexps
C-x C-t      transpose-lines

** Mark and point can be treated as a rectangle, and are by certain functions. (see next section) **

==Rectangles
C-x r c      clear-rectangle                         Replace text in the rectangle with spaces, blanking out the region destructively.
C-x r d      delete-rectangle                        Delete text in the rectangle described by mark and point.
C-x r o      open-rectangle                          Shift text in the rectangle right, blanking out the region non-destructively.
C-x r t      string-rectangle                        Replace rectangle contents with the given string.
C-x r y      yank-rectangle                          Yank back the last killed rectangle contents, top-left at point.

==Whitespace / cleaning up
C-x C-o      delete-blank-lines                      Delete all but one of many consecutive blank lines.
             fixup-whitespace                        Clean up space between objects around point.
M-\          delete-horizontal-space                 Delete all spaces & tabs around point.
M-SPC        just-one-space                          Delete all spaces & tabs around point except for one (or N).
             canonically-space-region                Remove extra spaces between words in region.
             delete-trailing-whitespace              Delete all trailing whitespace in the current buffer.

==Shell mode
C-c C-n      comint-next-prompt                      Move point to the next prompt.
C-c C-p      comint-previous-prompt                  Move point to the previous prompt.
C-c RET      comint-copy-old-input                   Copy the command input at point to the end of the buffer.

Variable           Description
--------           -----------

track-eol          If set next-line and previous-line will move to EOL if moving from EOL.

Slime mode
==========

Keybinding   Function                                Description
----------   --------                                -----------

==Compilation
C-c C-k      slime-compile-and-load-file             Compile and load the current buffer.
C-c M-k      slime-compile-file                      Compile (but don't load) the current buffer.
C-c C-c      slime-compile-defun                     Compile the top-level form at or around point.
M-n          slime-next-note                         Move to the next compiler note.
M-p          slime-previous-note                     Move to the previous compiler note.
C-c M-c      slime-remove-notes                      Remove all annotations from the buffer.

==REPL
C-Return     slime-repl-closing-return               Close all open parentheses and evaluate the current line.

==Navigation
M-.          slime-edit-definition                   Go to the definition of the symbol at point.
M-,          slime-pop-find-definition-stack         Go back from the definition found with slime-edit-definition.

==Evaluation
C-M-x        slime-eval-defun                        Evaluate the top-level form.
                                                         (ARG inserts result into buffer)
C-x C-e      slime-eval-last-expression              Evaluate the last expression before point.
                                                         (ARG inserts result info buffer)
C-c C-p      slime-pprint-eval-last-expression       Evaluate the expression before point and pretty-print the result.
C-c C-r      slime-eval-region                       Evaluate the region.
C-c :        slime-interactive-eval                  Evaluate an expression read from the minibuffer.

             slime-scratch                           Create a buffer like Emacs' *scratch*, eval expressions with C-j.

==Programming
C-c M-i      slime-fuzzy-complete-symbol             Presents a list of likely completions to choose from for an abbreviation
                                                     at point.
C-c C-s      slime-insert-arglist                    Look up and insert the arg list for the function at point.
C-c C-m      slime-macroexpand-1                     Macroexpand the expression at point once. Use a prefix to call macroexpand
                                                     instead of macroexpand-1.
C-c C-t      slime-toggle-trace-fdefinition          Toggle tracing of the function at point.
C-c M-d      slime-disassemble-symbol                Dissassemble the function definition of the symbol at point.

==Debugging

[TODO clean this up, this is copied from the Emacs wiki]

The following commands invoke restarts:

    * 0 .. 9 - Invoke a restart by number.
    * q - Throw to the top-level.
    * a - Invoke the ABORT restart.
    * c - Invoke the CONTINUE restart.

There are also commands for poking around in the frame at point:

    * v - Show the current frame's source expression in a buffer.
    * t - Toggle verbose display of the frame at point. The verbose version includes all local variables and CATCH tags.
    * l - Show local variables.
    * e - Evaluate an expression from inside a frame.
    * d - Evaluate an expression and display the result in an extra buffer.
    * i - Evaluate an expression and inspect the result.
    * : - Evaluate an expression (in the global environment).
    * D - Disassemble the code of the current frame.
    * r - Restart execution of the frame with the same arguments as it was called originally. (Not supported by all backends.)
    * R - Return a value from the current frame. (Not supported by all backends.)

Motion between frames:

    * n - Move to the next frame.
    * p - Move to the previous frame.
    * M-n - Detail-move to the next frame. This switches the current frame to a one-line summary, then moves to the next frame, displays it verbosely in the backtrace (as with t), and shows the corresponding source expression (as with v).
    * M-p - Detail-move to the previous frame.

==Reference
C-c <        slime-who-calls                         Reveal callers of the function at or around point.
C-c >        slime-who-references                    Reveal references to the global variable at or around point.

C-c C-d is the prefix for the following help commands:
    d        slime-describe-symbol                    Describe the symbol at point.
    a        slime-apropos
    z        slime-apropos-all                        Includes internal symbols.
    p        slime-apropos-package
    h        slime-hyperspec-lookup                   Customize with common-lisp-hyperspec-root browse-url-browser-function.
    ~        common-lisp-hyperspec-format

See your regular expressions in Emacs 0

Posted by sjs
on Friday, July 06

First, if you are an Emacs newbie then be sure to read (at least) the introduction of Being Productive with Emacs. For some reason the PDF and HTML versions are slightly similar.

Anyway, it mentions re-builder which is an awesome little gem if you use regular expressions at all1. What this baby does is open a small window at the bottom of your screen in which you can type a regex. It is parsed as you type it and matches are highlighted in the other window. Genius.

[1] If you don’t use them I encourage you to “learn them”http://regex.info/. Don’t pay any attention to Jamie Zawinsky and his lack of appreciation for a fantastic tool.

A TextMate tip for Emacs users 1

Posted by sjs
on Tuesday, July 03

Update: The only place I’ve seen this mentioned is in a comment on the MacroMates blog.

My Linux box is down due to a hardware failure; a cheap SATA controller to be specific. Perhaps that will be a story for another day. As a result I’ve been working on my MacBook and back in TextMate. Old habits. And I haven’t gotten comfortable in any of the OS X Emacsen yet.

This gave me an opportunity to accidentally discover some shortcuts in TextMate. A result of the Emacs shortcuts that my fingers are already wired to, here are some TextMate keyboard shortcuts that may or may not be documented (I need to RTFM some day).

  • As in most Cocoa text areas, C-f, C-b, C-n, C-p, C-a, C-e, and C-t work as expected (and others I’m sure).
  • C-k: behaves as a vanilla Emacs, killing till a newline or killing a bare newline. I use the word killing specifically because you can yank it back with…
  • C-y: yanks back the last thing on the kill ring (paste history). You still have to use C-S-v to yank previous items.

I think TextMate may have helped ease me into Emacs without me even knowing. I had my suspicions that Allan was an Emacs fan and now I’m certain of it. I keep finding things in one that the other has, which makes switching between them easy. Well done Allan.

Emacs: tagify-region-or-insert-tag 0

Posted by sjs
on Monday, June 25

After axing half of wrap-region.el I renamed it to tagify.el and improved it ever so slightly. It’s leaner, and does more!

tagify-region-or-insert-tag does the same thing as wrap-region-with-tag except if there is no region it now inserts the opening and closing tags and sets point in between them. I have this bound to C-z t, as I use C-z as my personal command prefix.

< is bound to tagify-region-or-insert-self which really doesn’t warrant an explanation.

RTFM! 0

Posted by sjs
on Monday, June 25

I should read the Emacs manual sometime, especially since I have it in dead-tree form. Check out skeleton pairs in the Emacs manual, or better yet C-h f skeleton-pair-insert-maybe. skeleton-pair has already been massaged to do what you most likely want if you set the correct options. Cool. I like Emacs more every day.

This renders wrap-region useless, which is great! I like a trim .emacs and .emacs.d.

Emacs for TextMate junkies

Posted by sjs
on Saturday, June 23

Update #1: What I first posted will take out your < key by mistake (it’s available via C-q <), it has since been revised to Do The Right Thing.

Update #2: Thanks to an anonymouse[sic] commenter this code is a little cleaner.

Update #3: I should read the Emacs manual sometime, especially since I have it in dead-tree form. Check out skeleton pairs in the Emacs manual.

Despite my current infatuation with Emacs there are many reasons I started using TextMate, especially little time-savers that are very addictive. I’ll talk about one of those features tonight. When you have text selected in TextMate and you hit say the ' (single quote) then TextMate will surround the selected text with single quotes. The same goes for double quotes, parentheses, brackets, and braces. This little trick is one of my favourites so I had to come up with something similar in Emacs. It was easy since a mailing list post has a solution for surrounding the current region with tags, which served as a great starting point.

1
2
3
4
5
6
7
(defun surround-region-with-tag (tag-name beg end)
      (interactive "sTag name: \nr")
      (save-excursion
        (goto-char beg)
        (insert "<" tag-name ">")
        (goto-char (+ end 2 (length tag-name)))
        (insert "</" tag-name ">")))

With a little modification I now have the following in my ~/.emacs file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
;; help out a TextMate junkie

(defun wrap-region (left right beg end)
  "Wrap the region in arbitrary text, LEFT goes to the left and RIGHT goes to the right."
  (interactive)
  (save-excursion
    (goto-char beg)
    (insert left)
    (goto-char (+ end (length left)))
    (insert right)))

(defmacro wrap-region-with-function (left right)
  "Returns a function which, when called, will interactively `wrap-region-or-insert' using LEFT and RIGHT."
  `(lambda () (interactive)
     (wrap-region-or-insert ,left ,right)))

(defun wrap-region-with-tag-or-insert ()
  (interactive)
  (if (and mark-active transient-mark-mode)
      (call-interactively 'wrap-region-with-tag)
    (insert "<")))

(defun wrap-region-with-tag (tag beg end)
  "Wrap the region in the given HTML/XML tag using `wrap-region'. If any
attributes are specified then they are only included in the opening tag."
  (interactive "*sTag (including attributes): \nr")
  (let* ((elems    (split-string tag " "))
         (tag-name (car elems))
         (right    (concat "</" tag-name ">")))
    (if (= 1 (length elems))
        (wrap-region (concat "<" tag-name ">") right beg end)
      (wrap-region (concat "<" tag ">") right beg end))))

(defun wrap-region-or-insert (left right)
  "Wrap the region with `wrap-region' if an active region is marked, otherwise insert LEFT at point."
  (interactive)
  (if (and mark-active transient-mark-mode)
      (wrap-region left right (region-beginning) (region-end))
    (insert left)))

(global-set-key "'"  (wrap-region-with-function "'" "'"))
(global-set-key "\"" (wrap-region-with-function "\"" "\""))
(global-set-key "`"  (wrap-region-with-function "`" "`"))
(global-set-key "("  (wrap-region-with-function "(" ")"))
(global-set-key "["  (wrap-region-with-function "[" "]"))
(global-set-key "{"  (wrap-region-with-function "{" "}"))
(global-set-key "<"  'wrap-region-with-tag-or-insert) ;; I opted not to have a wrap-with-angle-brackets

Download wrap-region.el

That more or less sums up why I like Emacs so much. I wanted that functionality so I implemented it (barely! It was basically done for me), debugged it by immediately evaluating sexps and then trying it out, and then once it worked I reloaded my config and used the wanted feature. That’s just awesome, and shows one strength of open source.

Reinventing the wheel 0

Posted by sjs
on Wednesday, June 20

Emacs is very impressive. I only felt lost and unproductive for minutes and now it seems natural to use and get around in. I’ve got ElSchemo set as the default scheme, and running inferior processes interactively is an absolute dream. My scheme doesn’t have readline support (which bothers me to the point where I’ve thought about adding it just so I can use the thing) but when running it under Emacs there’s absoutely no need for anything like that since I have the power of my editor when interacting with any program.

There has been a considerable amount of work done to aide in Rails development which makes Emacs especially comfortable for me. I now know why people have Emacs windows maximized on their screens. Because of its age Emacs is a handy window manager that basically eliminates the need for anything like GNU screen or a window manager such as Rat poison (which is great if you like screen), just maximize that Emacs “frame” or open one for each display and get to it. If you need a shell you just split the window and run your shell, when you’re done you can easily switch back to your editing and your shell will wait in the background until you need it again. With rails-mode on I can run script/console (or switch back to it) with C-c C-c s c. My zsh alias for script/console is sc and I have other similarly succint ones for other stuff, so I took right to the shortcuts for all the handy things that I no longer have to switch applications to do:

  • C-c C-c . – Run the tests for this file. If I’m in a unit test it runs it, if I’m in the model it runs the corresponding unit tests.
  • C-c C-c w s – Run the web server (script/server).
  • C-c C-c t – Run tests. The last value entered is the default choice, and the options are analogous to the rake test:* tasks.
  • and so on…

The Rails integration is simply stunning and I could go on all day about the mature indentation support, the Speedbar and what not, but I won’t. I’m fairly sure that Emacs has taken the place of TextMate as my weapon of choice now, on all platforms. And after only 2 days!

Anyway, the point of all this was to mention the one thing that’s missing: support for intelligent snippets which insert text at more than one point in the document (well, they appear to do so). I don’t have any E-Lisp-fu to break out and solve the deficiency but if it ever bugs me enough I might try implementing it for Emacs one day. If they were useful to me outside of writing migrations I might have more incentive to do so, but I guess they aren’t useful in normal editing situations (maybe I just haven’t recognised the need).

Back on Gentoo, trying new things 0

Posted by sjs
on Tuesday, June 19

I started using my Gentoo box for development again and there are a few things about Linux I didn’t realize I had been missing.

Shell completion is awesome out of the box

zsh has an impressive completion system but I just don’t feel the urge to ever customize it extensively. I just use the basic completion stuff on OS X because it’s easy. On Gentoo I have rake tasks and all sorts of other crap completed for me by including a few lines in my .zshrc (iirc a script does this automatically anyway). Generally Linux distros try to knit everything together nicely so you never even think about things like whether or not a package will have readline support, and default configs will be tweaked and enhanced beyond the official zsh package.

Linux is stable. Really stable.

While people bash Microsoft daily for tying the GUI layer to the kernel, Apple seems to get away with it scot-free. I don’t know if it’s caused by my external display hooked up to the dock, or the Prolific Firewire chip in my external disk enclosure but something causes the mysterious “music plays till the end of the song, mouse can be moved, but nothing works” bug now and then and all I can do is a hard reset.

On Linux I currently use Fluxbox so everything is rock solid and fast (except Firefox! ;-), but in the extremely rare event that shit does hit the fan usually only a single app will crash, though sometimes X (and hence many others) go with it. A sudo /etc/init.d/gdm restart fixes that. The only times I’ve had to hard reset Linux was because of a random bug (strangely similar to my MacBook bug) with Nvidia’s driver with dual head setups. All this is pretty moot since Linux is generally just stable.

Those are 2 relatively small things but the added comfort they provide is very nice.

In the spirit of switching things up I’m going to forgo my usual routine of using gvim on Linux and try out emacs. I’ve been frustrated with vim’s lack of a decent file browser and I’ve never much liked the tree plugin. Vim is a fantastic editor when it comes to navigating, slicing, and dicing text. After that it sort of falls flat though. After getting hooked on TextMate I have come to love integration with all sorts of external apps such as Subversion, rake, and the shell because it makes my work easier. Emacs seems to embrace that sort of philosophy and I’m more impressed with the efforts to integrate Rails development into Emacs than vim. I’m typing this post using the Textile mode for Emacs and the markup is rendered giving me a live preview of my post. It’s not WYSIWYG like Typo’s preview but it’s still pretty damn cool. I think can get used to emacs.

I’m just waiting for a bunch of crap to compile – because I use Gentoo – and soon I’ll have a Gtk-enabled Emacs to work in. If I can paste to and from Firefox then I’ll be happy. I’ll have to open this in vim or gedit to paste it into Firefox, funny!

I’m also going to try replacing a couple of desktop apps with web alternatives. I’m starting with 2 no-brainers: mail and feeds with Gmail and Google Reader. I never got into the Gmail craze and never really even used Gmail very much. After looking at the shortcuts I think I can get used to it. Seeing j/k for up/down is always nice. Thunderbird is ok but there isn’t a mail client on Linux that I really like, except mutt. That played a part in my Gmail choice. I hadn’t used G-Reader before either and it seems alright, but it’ll be hard to beat NetNewsWire.