2010-01-21

duplicating lines and commenting them

Someone on the Emacs Help mailing list asked for an easy way to duplicate a line
and, optionally, comment-out the first one.

Let's first look at simple duplication of a line. This is a common operation,
and vi-users might use something like Yp for that. In emacs, one way to do
this is by typing C-a C-k C-k C-y C-y, which is actually not as bizarre as
it looks if you try it. When using slick copy, as explained in another post,
it's as easy as M-w C-n C-y; and of course it's easy to define a shorter key
binding.

repeat after me
repeat after me

However, neither of these methods works correctly when you're on the last line
of the buffer (by default at least). Also, it puts the point (cursor) below
the duplicated line, while I'd like to put it at the start of it. It seems we
need something a little smarter.

While we're at it, let's also consider the second question: commenting-out the
first line of the duplicates. This is a quite common thing to do when writing
programs or configuration files; you want to try the effect of a small
variation of a line, but want to keep the original so it can be restored when
the variation turns out not to be as good as expected.

/* for (;;) fork (); */
for (;;) fork ();

I hacked up something quickly to solve both questions, and it has evolved a
little bit since – to answer both of the questions. The bit of weirdness in
the end is because of the special case of the last line in a buffer. It
defines key bindings C-c y for duplicating a line, and C-c c for
duplicating + commenting – but of course you can change those.

(defun djcb-duplicate-line (&optional commentfirst)
  "comment line at point; if COMMENTFIRST is non-nil, comment the original" 
  (interactive)
  (beginning-of-line)
  (push-mark)
  (end-of-line)
  (let ((str (buffer-substring (region-beginning) (region-end))))
    (when commentfirst
    (comment-region (region-beginning) (region-end)))
    (insert-string
      (concat (if (= 0 (forward-line 1)) "" "\n") str "\n"))
    (forward-line -1)))

;; or choose some better bindings....

;; duplicate a line
(global-set-key (kbd "C-c y") 'djcb-duplicate-line)

;; duplicate a line and comment the first
(global-set-key (kbd "C-c c") (lambda()(interactive)(djcb-duplicate-line t)))

2010-01-16

rectangles and cua

CUA-mode is a minor-mode that enables the use of Ctrl-X/C/V for cut/copy/paste, as is customary in many computer programs. Of course, it's a bit different in emacs, as it predates CUA and all of those programs. With esp. Ctrl-X (C-x) being in heavy use as a prefix-key already, it's unlikely to change.

CUA-mode has a clever trick to solve that problem – C-x for cut only works when a selection is active, and when no other key is pressed shortly. Otherwise, C-x behaves as usual. This works quite nicely, but personally, I don't use it, as I already have the Emacs key bindings in my muscle memory. Still, it can be useful for people migrating from other CUA-based editors. See e.g. CuaMode for more information.

However, apart from the C-x-trick, CUA also has some nice functionality for rectangular selections. These are sometimes quite useful, and during emacs-fu's prehistory there was already an article about it. The method there works, but with CUA, it is much easier.

So, let's turn it on; put the following in your .emacs:

(setq cua-enable-cua-keys nil) ;; only for rectangles
(cua-mode t)

Now, just put your cursor anywhere, and press C-RET (Ctrl + Enter). You have now started a rectangular selection! There rest is pretty straightforward, you can cut, copy and paste with the normal Emacs key bindings..

I could go into more detail, but the best way is to see it in action in this wonderful screen cast by Mark Mansour. I especially like the way you can add numbered lists.

2009-12-30

automatically checking your spelling

When I'm typing fast, it's easy to make spelling mistakes (as you may have noticed reading Emacs-Fu). It's not so much that I don't know how to write things, but sometimes there seems to be a bit of a disconnect between brain and fingers.

One tool that helps me to make fewer mistakes is automatic spelling checking, and in particular on-the-fly spelling checking. Spell-checking in emacs is taken care of by the ispell-package. Traditionally, this was a way to interface emacs with the ispell-program on Unix, but nowadays it's often used with other programs, such as aspell.

aspell is GNU's intended replacement for ispell, and has been for a long time. In the meantime, other spelling checkers have come up; in the Free Software world, the most prominent one is probably hunspell, which is used by e.g. Mozilla and OpenOffice. As I said, Emacs supports all of those; I'm using aspell, which works well for me. To use aspell for spelling-checking, I have the following in my .emacs:

(setq ispell-program-name "aspell"
  ispell-extra-args '("--sug-mode=ultra"))

Please consult the aspell documentation for the details.

You can spell-check your text with ispell-buffer and friends, which are also available through the menu (Tools/Spell Checking/...). This works fine, but it makes spelling checking a separate step you have to go through and you may forget. So, I like to do the spelling-checking on-the-fly, that is, while I am typing. This can be done using flyspell-mode (you can also use flyspell-prog-mode, to do spell checking inside comments in computer programs, but I find that a bit over the top).

When flyspell-mode is enabled, it will mark misspelt eh misspelled words by painting them in a different color while you are typing -- the common way many word processing programs do it. A common way to enable flyspell-mode is to put it the the mode-hook for the modes where you want to use it. For example, to enable flyspell-mode for all your org-mode buffers, you can add something like the following to your .emacs:

(add-hook 'org-mode-hook
  (lambda()
    (flyspell-mode 1)))

Note, you can use the middle mouse button to get alternatives for a misspelled word.

By default, it uses the English dictionary, but it's easy to switch to another using M-x ispell-change-dictionary. To make it easier, I have defined the C-c N key binding to activate Dutch-language ("nederlands") spelling checking, and update the buffer.

(global-set-key (kbd "C-c N") 
  (lambda()(interactive)
    (ispell-change-dictionary "nederlands")
    (flyspell-buffer))) 

Now, there's another category of mistakes – their-they're-there, its-it's or to-too-two that require a spelling checker that's a bit smarter. There are some free implementations in OpenOffice and Abiword; it'd be interesting to see if those could be integrated with emacs as well.

Now, laugh about the sweet irony of the spelling errors that I failed to notice :)

2009-12-13

scrolling

Scrolling It's an integral part of just about any graphical user interface, including emacs. However, I always found that the default way scrolling works in emacs left something to be desired. It puts the scroll bar on the left (!), and when scrolling around, it does not scroll smoothly, but instead it seem to do so in bursts. But, this being emacs, we can change it!

First, the position of the scroll bar. Presumably for historical reasons, emacs puts the scroll bar on the left of the window, unlike most other programs. We can easily change that, by putting the following in .emacs (or ~/.emacs.d/init.el):

(set-scroll-bar-mode 'right)

Instead of right, you can also use left, or nil to hide the scroll bar completely. You can also do this through the menu (Options / Show/Hide / Scroll bar). Note that on X, when the cursor (point) reaches the end of the document, the slider on the scroll bar may not be at the bottom; I understand this is because of some disagreement between Emacs and the toolkit (GTK+ in this case).

Now, what about the other issue, the non-smoothness when scrolling with the cursor-keys or with C-n, C-p? Below are my settings for making scrolling a bit smoother, and the explanation. Of course, these are just my personal preferences.

(setq
  scroll-margin 0                  
  scroll-conservatively 100000
  scroll-preserve-screen-position 1)
  • The scroll-margin. This determines when scrolling should start; by setting it to 0, emacs will start to scroll whenever you are entering the top or bottom line of the window. You can also this to, say, 5 to let scrolling start whenever you're getting closer than 5 lines from top or bottom
  • Then, scroll-conservatively determines how far the cursor is allowed to be distanced from the center of the screen when scrolling start. The default sets this to 0, which means that whenever you start scrolling, the cursor jumps to the center of the screen. I find that quite annoying, so I set it to some big number (the 'effective maximum' for that is lines-in-window / 2, but you can put any bigger number there to avoid the jumpiness)
  • scroll-preserve-screen-position tries to maintain the current screen position when you scroll using Page-Up/Page-Down. I like that.

There are also the variables scroll-up-aggressively and scroll-down-aggressively. Normally, they determine how far emacs will scroll (up and down, respectively) when it does so. However, they don't make any difference with a big scroll-conservatively like I am using. Still, if you want to play with it, their values are fractions between 0.0 and 1.0 (inclusive); a value of 1 means that it will move a full screen when scrolling starts, a value of 0.0 causes a move of only one single line.

2009-12-06

changing the cursor color and shape dynamically

When typing some text, it's often useful to know what mode we're in – are we in overwrite-mode, in read-only-mode, or in normal insert-mode. The information is available in the mode-line – but wouldn't it be nicer to get some small visual cue, for example by changing the cursor color or style?

That indeed is possible. There are some existing ways to do this, described in EmacsWiki. However, I want to be able to control both the cursor color and cursor shape, and also distinguish between overwrite, read-only and 'normal' mode. Below is my attempt.

By putting the following snippet in your .emacs, the cursor becomes a yellow vertical bar during normal mode, it becomes a red block when you're in overwrite-mode and it becomes a gray vertical bar when you're in read-only mode.

;; Change cursor color according to mode; inspired by
;; http://www.emacswiki.org/emacs/ChangingCursorDynamically
(setq djcb-read-only-color       "gray")
;; valid values are t, nil, box, hollow, bar, (bar . WIDTH), hbar,
;; (hbar. HEIGHT); see the docs for set-cursor-type

(setq djcb-read-only-cursor-type 'hbar)
(setq djcb-overwrite-color       "red")
(setq djcb-overwrite-cursor-type 'box)
(setq djcb-normal-color          "yellow")
(setq djcb-normal-cursor-type    'bar)

(defun djcb-set-cursor-according-to-mode ()
  "change cursor color and type according to some minor modes."

  (cond
    (buffer-read-only
      (set-cursor-color djcb-read-only-color)
      (setq cursor-type djcb-read-only-cursor-type))
    (overwrite-mode
      (set-cursor-color djcb-overwrite-color)
      (setq cursor-type djcb-overwrite-cursor-type))
    (t 
      (set-cursor-color djcb-normal-color)
      (setq cursor-type djcb-normal-cursor-type))))

(add-hook 'post-command-hook 'djcb-set-cursor-according-to-mode)

You can change the colors and cursor types by modifying the various variables.

I should probably turn this into a proper minor mode, but for now this seems to work well.

2009-11-29

making buffer names unique

When you open a file in emacs, the buffer gets the name of that file. That's all fine, but what if you open multiple files with the same name? At least for me, it's a fairly common to have a number of different Makefile.am buffers Makefile.am<3> etc., but that does really help to find the right one at the same time. Emacs does make those names unique – Makefile.am<2>, quickly.

To do that, emacs provides uniquify – it makes buffer names unique. In your .emacs:

(require 'uniquify) 
(setq 
  uniquify-buffer-name-style 'post-forward
  uniquify-separator ":")

This is emacs, so you can influence the way in which the names are made unique. I prefer post-forward, and as separator I use a : rather than the default |. Note, instead of post-forward there are other bizarre styles, please see the documentation.

Anyway, now, when opening ('visiting') files test/a/foo and test/b/foo, their buffers get the names foo:a and foo:b. In other words, the name followed by a colon and part of the path. I think it's much clearer than the default names foo and foo<2>. One could ask why emacs should not use uniquify as its default behavior; it seems a clear improvement.

Uniquify is a small convenience that's been a documented part of emacs for 20 years. Still, somehow I missed it until this year. I suspect I am not the only one - which is why I write this.

2009-11-19

showing pop-ups

Updated: yes, it's %s, not %d Sometimes, it's nice when emacs can warn you when something is happening or should happen. For example, when a new e-mail has arrived, or when there's a meeting in 15 minutes you should attend.

As always, there are different way to do this, but here's what I've been using for while. Various versions of this have been circulating around mailing lists, so I don't know whom to credit with the original idea – anyway, this is the (modified) version that I'm using.

(defun djcb-popup (title msg &optional icon sound)
  "Show a popup if we're on X, or echo it otherwise; TITLE is the title
of the message, MSG is the context. Optionally, you can provide an ICON and
a sound to be played"

  (interactive)
  (when sound (shell-command
                (concat "mplayer -really-quiet " sound " 2> /dev/null")))
  (if (eq window-system 'x)
    (shell-command (concat "notify-send "

                     (if icon (concat "-i " icon) "")
                     " '" title "' '" msg "'"))
    ;; text only version

    (message (concat title ": " msg))))

A couple of notes:

  • I'm using notify-send for sending notifications; this assumes you are using that system (it's part of the libnotify-bin package in Debian/Ubuntu). You can of course replace it with whatever is available on your system. Alternatives are zenity or kdialog or xmessage (for old-timers) and their equivalents (?) on Windows, MacOS.
  • I'm now using mplayer for playing sounds. This is a bit heavy, but at least plays all kinds of audio files. If you only care about .wav-files, you could replace it with e.g. aplay;
  • as always, please ignore my ego-centric function names :-)

Now, we can use this function by evaluation e.g.

(djcb-popup "Warning" "The end is near"
   "/usr/share/icons/test.png" "/usr/share/sounds/beep.ogg")

showing pop-ups from org-mode appointments

The above popup function is most useful when it's does its work based on some event. To be notified of appointments and the like, there is the emacs appt facility. Here, we set up this appt, and then hook it up with org-mode, so appt can warn us when there's something happening soon…

;; the appointment notification facility
(setq
  appt-message-warning-time 15 ;; warn 15 min in advance

  appt-display-mode-line t     ;; show in the modeline
  appt-display-format 'window) ;; use our func
(appt-activate 1)              ;; active appt (appointment notification)
(display-time)                 ;; time display is required for this...

 ;; update appt each time agenda opened

(add-hook 'org-finalize-agenda-hook 'org-agenda-to-appt)

;; our little façade-function for djcb-popup
 (defun djcb-appt-display (min-to-app new-time msg)
    (djcb-popup (format "Appointment in %s minute(s)" min-to-app) msg 
      "/usr/share/icons/gnome/32x32/status/appointment-soon.png"

      "/usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg"))
  (setq appt-disp-window-function (function djcb-appt-display))

Of course, you can freely choose a icon / sound to your liking.

showing pop-ups for new mail

Another event you might want to be warned about is new mail. There is something to be set for not letting yourself be disturbed for new mail, but if you sufficiently filter your mails before they enter your inbox, it can be a good way to periodically bring you back from your deep sl ^H^H thinking. For Wanderlust, I use something like this:

(add-hook 'wl-biff-notify-hook
    (lambda()
      (djcb-popup "Wanderlust" "You have new mail!"
        "/usr/share/icons/gnome/32x32/status/mail-unread.png"
        "/usr/share/sounds/ubuntu/stereo/phone-incoming-call.ogg")))

Exercise for the reader: adapt this for your chosen mail client.