Thursday, May 16, 2013

Emacs Word Commands in C and Java Modes


The Problem
You use the Emacs commands:

CommandAction
M-fMove forward by one word
M-bMove backward by one word
M-dDelete word ahead of the cursor
M-DELDelete word behind cursor
M-tTranspose words
M-@Mark word
M-uUpcase word
M-lDowncase word
M-cCapitalize word

They work beautifully with ordinary text but not so great in C or Java modes. For example, the arrows in the image below show where the cursor will skip to if you use M-f to skip forward starting at the first arrow.




The problem here is that C-mode doesn't recognize "_" as part of a "word".

The Solution
There is an easy fix for this: simply add the following lines to your .emacs file:
01 (add-hook 'c-mode-common-hook
02        (lambda ()
03          (modify-syntax-entry ?_ "w" c-mode-syntax-table)))
04 (add-hook 'java-mode-hook
05        (lambda ()
06          (modify-syntax-entry ?_ "w" java-mode-syntax-table)))
The image below shows where the cursor will skip to after the hook is installed.




All word-related commands will recognize "_" as part of a "word" in C and Java modes.

Problem solved.

Wednesday, May 15, 2013

Using Emacs for Fun and Profit. Part 2: Copying random text from random places.





The Problem

In this post we will address the problem of collecting text from scattered locations in one or more buffers and placing it in a specific location. For example: suppose that you want to copy some C function prototypes from a .c file into a header file as illustrated below.


What is an efficient way to accomplish this? There are two solutions that come to mind right away.

Solution 1: Use Text Registers
  1. Mark text in the source buffer.
  2. Append text to some register (we'll use "A" here).
  3. Repeat steps 1 and 2 until you have collected all of the text that you need to move.
  4. Switch to the destination buffer.
  5. Move to the target location.
  6. Copy register "A" to destination buffer with C-x r i A
Let's walk through this. In the screenshots below, the source buffer is on the left and the destination buffer is on the right. 

Steps 1 and 2: Mark text in the source buffer, append with M-x append-to-register 


 
Steps 4, 5, and 6: Switch to the destination buffer, move to the target location and insert register "A".




Unfortunately append-to-register places all of the copied text onto a single line so some editing must be done.



Solution 2: Use the Global Mark
Emacs' CUA mode provides a global mark which offers a more efficient solution than text registers. When the global mark is enabled, any keystrokes that you type will be sent to the target location and any text that you place in the kill ring will also be sent to the target location. So the sequence of steps is now:
  1. Move to target location and enable the global mark S-C-SPC.
  2. Copy the text you wish to send to the target location to the kill ring.
  3. Press ";" then RET to place a semicolon at the the end of the target text. Pressing RET causes any other text copied to the kill ring to be placed on a separate line. This saves us the editing step required when we use append-to-register.
To use the global mark, place the following in your .emacs file:
(setq-default cua-enable-cua-keys nil)
(cua-mode t)
This will enable CUA features such as global mark/copy and enhanced rectangle editing but not enable CUA keys such as C-c for copy, C-v for paste etc.

Let's illustrate the above steps with some screenshots.

Step 1: Move to target location and enable the global mark S-C-SPC.



Step 2: Copy the text you wish to send to the target location to the kill ring.   The text will instantly appear at the target location.



Step 3: Press ";" then RET to place a semicolon at the the end of the target text. Pressing RET causes any other text copied to the kill ring to be placed on a separate line. This saves us the editing step required when we use append-to-register.


  Repeat steps 2 and 3 to copy more text