The following notes were taken while discussing Chapter 5 of the book Mastering Emacs by Mickey Petersen (2022 edition) in book discussion group meetings.
An index of notes for all chapters are available at notes.html.
{{ toc }}Killing text is equivalent to what we call as cutting text in other editors. Killing some text removes the text from the buffer and adds it to the kill ring. The kill ring is the clipboard of Emacs.
To discover kill commands using the apropos functionality,
type C-h a ^kill-.
Here is a list of commands introduced in the first section of this chapter:
C-d: Delete the next character.
<backspace>: Delete the previous character.
M-d: Kill until the end of a word.
C-<backspace>: Kill backward until the
beginning of a word.
C-k: Kill the rest of the current line.
M-k: Kill until the end of sentence.
C-M-k: Kill expression following point.
C-S-<backspace>: Kill current line. Does not
work in terminal Emacs. Use C-a C-k as alternative.
C-w: Kill text between point and mark.
M-w: Copy text between point and mark to kill ring.
C-M-w: Cause the following command, if it kills, to
append to the last stretch of text in the kill ring.
C-y: Yank (paste) the last stretch of text in the
kill ring to the buffer.
M-y: Cycle through kill ring.
I have observed that some Emacs users do not bother
using M-w to copy to kill ring. Instead they
type C-w C-/ to cut the text and immediately undo the
cut which effectively leaves the buffer unchanged but inserts a copy
of the text that was cut into the kill ring. For example,
while C-a C-SPC C-n C-n M-w copies two lines into the
kill ring, so does C-a C-SPC C-n C-n C-w C-/. The
latter key sequence avoids having to use M-w but it is
worth noting that this key sequence does not work in a readonly
buffer while the former does. To quickly see the difference,
open /etc/hosts as a non-root and non-privileged user
and try both the key sequences. The former key sequence does not
modify the buffer, so it works perfectly in a readonly buffer. The
latter key sequence modifies the buffer when we
type C-w, so it does not work in a readonly buffer.
I have also observed that many Emacs users do not bother
learning C-S-<backspace> because they can achieve
the same results using C-a C-k.
Further, C-S-<backspace> does not work in
terminal Emacs due to terminal limitations. The key
sequence C-a moves the cursor to the beginning of the
line and C-k kills everything until the end of the
line.
There is a difference between deleting and
killing. The first two commands C-d
and <backspace> delete characters but the deleted
characters are not added to the kill ring. The remaining commands
in the list above kill text, i.e. remove the text from the buffer
and add it to the kill ring. The killed text can be pasted into the
buffer using C-y. For example, M-d M-d M-d C-p
C-p C-y kills the next three words and pastes them two lines
above.
The key sequence C-M-w is used to ensure that if the
next command happens to be a kill command, then the killed text is
appended to the last stretch of text in the kill ring.
To understand what this command does we must first understand that
after a kill command adds a new stretch of text to the kill ring,
subsequent consecutive kills append to the same stretch of text in
the kill ring, i.e. consecutive kills form a single large stretch of
text in the kill ring. This can be tested by performing consecutive
kills and then pasting with C-y. For example,
M-d M-d M-d C-p C-p C-y kills 3 words, creates a single
stretch of text consisting of those 3 words in the kill ring and
pastes that text two lines above.
However, the moment a non-kill command is used, it seals the stretch
of text in the kill ring. Any subsequent kill command begins a new
stretch of text. For example, M-d M-d M-d C-p M-d M-d C-p
C-y kills 3 words at first but then it moves to the previous
line sealing that kill text consisting of 3 words. Then it kills 2
words and creates a new stretch of text in the kill ring.
Therefore, the final yank command pastes only those 2 words from the
kill ring.
This can be a problem if we want to kill text from various parts of
the buffer and yet create a single stretch of text that we want to
paste somewhere. That's when C-M-w comes useful. For
example, M-d M-d M-d C-p C-M-w M-d M-d C-p C-y kills 3
words and creates a single stretch of text in the kill ring
consisting of those 3 words. Then it moves one line up and kills 2
more words but this time it appends those 2 words to the existing
stretch of text in the kill ring. Finally, it moves two lines up
and pastes the entire stretch of text consisting of 5 words into the
buffer.
Here are some complete key sequences that demonstrate digit and negative arguments:
M-3 M-d: Kill the next 3 words.
M- M-d : Kill the previous word.
M-- M-3 M-d : Kill the previous 3 words.
C-M-3 C-M-k: Kill the next 3 expressions.
C-M-- C-M-k: Kill the previous expression.
C-M-- C-M-3 C-M-k: Kill the previous 3 expressions.
There are two key bindings to learn here. The key
sequence C-y executes the yank command
which yanks the last stretch of text from the kill ring.
In the apropos system, paste is a synonym
of yank. Type C-h v apropos-synonyms RET
to see all the synonyms define for the apropos system.
Thus C-h a paste RET includes the results
for yank too.
The key sequence M-y executes the yank-pop
command which replaces a just-yanked kill with an older kill. This
key sequence helps us to cycle through the kill ring and fetch older
and older kills to be pasted into the buffer.
Here is an experiment to see how we can use C-y
and M-y can be used together:
foo bar baz qux quux.
C-a M-d C-g M-d C-g M-d. At this point
three stretches of text have been inserted into the kill ring.
The C-g between every M-d is there to
avoid appending kills to the existing stretch of text in the kill
ring. This ensures that we have three separate stretches of text
in the kill ring.
C-y. The last stretched of kill text, i.e.
baz is now pasted into the buffer.
M-y.
The earlier pasted text baz is now replaced with an
older stretch of text from the kill ring. Thus baz
is replaced with bar.
M-y. The earlier pasted
text bar is now replaced with a further older stretch
of text from the kill ring. Thus bar is replaced
with foo.
Note in the previous steps how we are not supposed to type any other
key between the first C-y and M-y.
Similarly, while cycling through the kill ring, we must not type any
other key between the consecutive M-y key sequences.
While cycling through the kill ring, when we reach the oldest kill,
the next M-y wraps around and brings back the newest
kill.
Since Emacs 28, the key sequence M-y also supports
browsing the kill ring and yanking any arbitrary entry from the kill
ring. For example, after trying the above experiment,
type C-g just to make sure that we are breaking any
existing C-y or M-y cycle. Then
type M-y and a minibuffer prompt appears to yank an
arbitrary kill from the kill ring. If we remember the previous
kill, we can type it out partially and type TAB to
autocomplete it. Alternatively, we could also type TAB
initially itself to browse all the kills in the kill ring.
Type C-h v kill-ring-max RET to see the maximum length
of the kill ring. It is 60 by default.
Since C-S-<backspace> works only in GUI Emacs and
not in terminal Emacs due to terminal limitations, in the
section Killing Lines the author recommends installing the
package whole-line-or-region which modifies the
behaviour of C-w to kill the current line if there is
no active region.
This package can be installed with the following command:
M-x package-install whole-line-or-region RET
Then a mode offered by this package can be enabled by adding this line to the Emacs initialisation file:
(whole-line-or-region-global-mode)
After Emacs is started with the updated initialisation file,
typing C-w kills the current line if there is no active
region. However, if there is an active region then C-w
retains the default behaviour of killing the region.
Although the author recommends this package, I do not use this
package. I have found C-a C-k to be very effective for
killing the current line. However, it is worth noting that for
non-empty lines, C-k does not include the newline in
the kill by default. If we want to remove the newline too, we must
type C-k another time. Therefore, to faithfully
reproduce the behaviour of C-w
(of whole-line-or-region) or that
of C-S-<backspace>, we need to type C-a C-k
C-k.
It is possible to change the default behaviour of C-k
such that when we type it at the beginning of a line, the trailing
newline is included in the kill. To do so, add this to the Emacs
initialisation file:
(setq kill-whole-line t)
After Emacs is started with this initialisation
file, C-k kills a whole line along with the trailing
newline only if cursor is at the start of a line. In other words,
with this setting, C-a C-k always kills a whole line
along with the trailing newline.
Here are some transpose commands:
C-t: Interchange characters around point.
M-t: Interchange words around point.
C-M-t: Interchange expressions around point.
C-x C-t: Exchange current line and previous line.
M-x transpose-paragraphs RET: Interchange current
paragraph with next one.
M-x transpose-sentences RET: Interchange the current
sentence with the next one.
While using C-t remember that the point is the logical
place between two characters. For example if the cursor blinking on
the letter e of the word hello, then the
point is between the letters h and e.
When we type a new character, the new character is inserted where
the point is. The key sequence C-t interchanges the
characters on both sides of the point, i.e. it exchanges the
character the cursor is blinking on with the character just before
it.
There is a subtle difference between the way C-x C-t
works and the way the other commands work. The other commands
exchange the current or previous object with the next one.
However, C-x C-t exchanges the current line with the
previous one.
Note that the cursor moves to the end of the next object after
performing an exchange. This allows the object that moved forward
to be dragged further forward by repeated application of the same
command. Note again that while the other commands drag the thing at
point forward, C-x C-t drags the previous line forward.
If the cursor is on a space between "foo" :: "bar",
note that M-t will transpose it to "bar" ::
"foo" because it ignores symbols.
Here are some complete key sequences that perform paragraph filling:
M-q: Refill paragraph.
C-u M-q: Refill paragraph and justify text too.
C-x f 40 RET: Set fill-column to 40.
C-x .: Set the fill prefix to the current line up to
point. On performing a fill operation, the fill prefix is
inserted at the beginning of every new line created.
C-a C-x .: To cancel the fill prefix, type C-x
. at the beginning of a line. Thus C-a C-x .
cancels the fill prefix.
M-x auto-fill-mode RET: Toggle auto-filling.
Here are some key bindings to add comments to code in various ways:
M-;: Insert or remove comment in a do what I
mean (DWIM) fashion. If the line is empty, a comment is
inserted at the beginning of the line. If the line is not empty,
a comment is inserted at the end of the line and then indented to
the column numbered comment-column if it can. If a
region is selected, it comments or uncomments that region.
C-x C-;: Comment out or uncomment the current line.
M-x comment-box RET: Comment a region by drawing a
box made of comment characters around the selected region.
Running this command repeatedly on the same region creates
multiple nested comment boxes.
M-j: Insert a new line and continue with the comment
if the current line has an open comment. If there is no open
comment in the current line, then create a new line and indent.
C-M-j: Same as above.
Here are some variables that control the behaviour of comment-related commands:
comment-style: The default is indent
which ensures that new comments created with the comment commands
are correctly indented.
comment-styles: An association list with all the
available comment styles.
comment-start: String to insert to start a new
comment.
comment-end: String to insert to end a new comment.
comment-padding: Extra spacing between the comment
characters and the comment text. This is the minimum number of
spaces (only if the value of this variable is made of spaces) that
Emacs tries to keep between the comment characters and comment
text. No spaces are inserted if comment-start
and comment-end already
provide comment-padding number of spaces or more to
separate the comment text.
To demonstrate how changing comment-style changes the
commenting behaviour try M-x (setq comment-style 'indent)
RET, then select a region and type M-;. The
selected region will be commented out with a comment box.
However running M-x (setq comment-style 'aligned) RET,
selecting a region in a C buffer and typing M-; does
not seem to do anything interesting.
Here are some complete key sequences that demonstrate search and replace commands:
M-% foo RET bar RET: Replace the
string foo with bar while prompting for
instruction at every match.
C-M-% f.. RET bar RET: Replace matches for regular
expression f.. with bar while prompting
for instruction at every match.
M-x query-replace RET foo RET bar RET: Same
as M-% foo RET bar RET.
M-x query-replace-regexp RET f.. RET bar RET: Same
as C-M-% f.. RET bar RET.
M-x replace-string RET foo RET bar RET: Replace the
string foo with bar but do not prompt
for instruction at every match.
M-x replace-string RET f.. RET bar RET: Replace
matches for regular expression f..
with bar but do not prompt for instruction at every
match.
The following key bindings work while a query replace operation is in progress:
y: Replace one match and continue.
SPC: Same as y.
n: Skip to next match.
DEL: Same as n.
q: Exit query replace.
RET: Same as q.
.: Replace one match and exit.
,: Replace and stay at current match.
!: Replace all remaining matches in the buffer with
no more questions.
^: Move point back to the previous match.
u: Undo previous replacement.
U: Undo all replacements.
E: Edit replacement string and replace next match.
Just like incremental search (C-s or
C-M-s), search and replace performs case folding,
i.e. performs case-insensitive match if the search string is a
lowercase string. However, the moment we include an uppercase
character in the search string, search and replace performs
case-sensitive search and replace.
This section presents some examples of regular-expression-based search as well as search-and-replace. Here is a simple text buffer where the commands to be presented later can be tried out.
foo-bar-baz
foo-baar-baz
foo-baaar-baz
foo-baaaar-baz
foo-baaaaar-baz
foo-baaaaaar-baz
web
server
webserver
web server
web_server
web->server
web::server
web.server
securewebserver
secure web server
web server port 80
web-server
web-api-server
secure-web-server
web-server-port-80
web-server-port-http
web-server-port-HTTP-80
(1, 2, 3)
[4, 5, 6]
{7, 8, 9}
((10 + 20) * 30)
<40, 50, 60>
"hello, world"
'hello, world'
; comment
# comment
// comment
/* comment */
Here are some complete key sequences that demonstrate regular expressions in search operations:
C-M-s f..: Search for the letter f
followed by two characters.
C-M-s foo\|bar: Search for the
string foo or bar.
C-M-s ba\{3\}r: Search for the letter b
followed by the string aaa and the
letter r.
C-M-s ba\{3,5\}r: Search for the
letter b followed by 3 to 5 repetitions of the
letter a followed by the letter r.
C-M-s port-[0-9]+: Search for the
string port- followed by one or more digits.
C-M-s port-[[:digit:]]+: Same as above.
C-M-s port-[[:alnum:]]+: Search for the
string port- followed by one or more alphanumeric
characters.
C-M-s port-[[:upper:][:digit:]-]+: Search for the
string port- followed by consecutive sequence of one
or more upper-case letters, digits or hyphen.
C-M-s \<web: Search for the
string web at the beginning of a word.
C-M-s web\>: Search for the
string web at the end of a word.
C-M-s \<web.+server\>: Search for the
string web at the beginning of a word followed by one
or more characters and the string server at the end
of a word.
C-M-s \_<web.+server\_>: Search for the
string web at the beginning of a symbol followed by
one or more characters and the string server at the
end of a symbol.
C-M-s web\s server: Search for the
string web followed by one whitespace character and
the string server.
C-M-s web\s-server: Same as above.
C-M-s \s : Search for whitespace character.
C-M-s \s-: Same as above.
C-M-s \sw: Search for word constituent character.
Typically uppercase letters, lowercase letters and digits are
considered word constituents.
C-M-s \s_: Search for a symbol character that is used
in variable names or command names.
C-M-s \s.: Search for punctuation character.
C-M-s \s(: Search for opening pair of a grouping
character, e.g. (, [, {.
C-M-s \s): Search for closing pair of a grouping
character, e.g. ), ], },
etc.
C-M-s \s": Search for string delimiter. This does
not work in text mode but does work in programming modes.
C-M-s \s<: Search for opening comment delimiter.
This too does not work in text mode but does work in programming
modes.
C-M-s \s>: Search for closing comment delimiter.
This too does not work in text mode but does work in programming
modes.
C-M-s \Sw: Search for character that is not a word
constituent. The pattern \S matches any character
whose syntax code is not the given syntax code (w in
this example).
All examples above that contain the regular
expression \s followed by a character matches a
character that belongs to a specific syntax class. For
example \s. matches characters that belong to the
punctuation syntax class. The syntax class for each character is
decided by the current major mode. Thus the same character may
belong to different syntax classes in different modes. For example,
while the character # belongs to the punctuation syntax
class in text mode, it belongs to the comment syntax class in Python
mode.
To find out which syntax class a particular character belongs to,
place the cursor on the character and type C-u C-x =.
The syntax field in the output buffer shows the syntax
class of the character.
Here are some complete key sequences that demonstrate various search-and-replace features:
C-M-% \(web\)\(\s-\)\(server\) RET \3\2\1 RET: Search
for the string web followed by a whitespace and the
string server and swap web
with server.
C-M-% \(foo-\)\sw+\(-baz\) RET \1\?\2 RET: Search for
the string foo- followed by a word and the
string baz and replace the middle word with text
input provided by the user. Before each replace operation, Emacs
will prompt the user to edit the replacement pattern by putting
the point where \? was in the original replacement
string.
C-M-% foo RET \# RET: Search for the
string foo and replace each match with an
autoincrementing number. The first match is replaced
with 0, the second one with 1, the third
one with 2 and so on. Precisely speaking, the
backreference \# refers to the count of the
replacements already made in the current search and replace
operation.
C-M-% foo RET \&\& RET: Search for the
string foo and duplicate it. The replacement
pattern \& stands for the whole match.
C-M-% f.. RET \,(upcase \&) RET: Search for the
letter f followed by two characters and replace the
match with an uppercase form of the match. The
syntax \,(form) is used to evaluate an Elisp
form and use its result in the replacement string. The
backreference \& refers to the whole match as a
string in the Elisp expression.
C-M-% [0-9]+ RET \,(+ 1000 \#&): Search for
numbers and add 1000 to each match. The
backreference \#& refers to the whole match as a
number within the Elisp expression.
C-M-% \(\sw+\)-\(\sw+\) RET \,(upcase \2)-\1 RET:
Search for two words separated by a hyphen and then swap them but
convert the second word in each match to uppercase. The
backreference \2 refers to the string matched by the
second capturing group as a string within the Elisp expression.
C-M-% port-\([0-9]+\) RET port-\,(+ 1000 \#1) RET:
Search for the string port- followed by a number and
add 1000 to the number. The backreference \#1 refers
to the string matched by the first capturing group as a string
within the Elisp expression.
Here are some commands to change case of text:
M-l: Convert string from point to the end of word to
lowercase.
M-u: Convert string from point to the end of word to
uppercase.
M-c: Capitalise string from point to the end of word.
C-x C-l: Convert region to lower case.
C-x C-u: Convert region to upper case.
M-x upcase-initials-region RET: Capitalise region.
Note that the commands C-x C-l
(downcase-region) and C-x C-u
(upcase-region) are disabled by default. Follow the
prompts to try it or enable it. A quick way to try it is to
type SPC. Also, adding the following to the Emacs
initialisation file permanently enables it.
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
Here are some commands to count lines, words, characters, patterns, etc:
M-=: Count lines, words and characters in region.
M-x count-words-region RET: Same as above.
M-x count-words RET: Similar to above. If no region
is selected, then counts in the entire buffer.
M-x how-many RET f.. RET: Show the number of matches
for the regular expression f.. following point. If
region is selected, then show the number of matches in the region.
M-x count-matches RET f.. RET: Same as above.
The commands that are presented in this section can be tested with a buffer like this:
foo
bar
foo
bar
foo
foo
bar
foo
baz
baz
baz
Here are the commands:
M-x delete-duplicate-lines RET: Delete all but one
copy of duplicate lines in region. When executed on the whole of
the example buffer presented above, it leaves us with three
non-empty lines and one blank line. When duplicate lines are
encountered, the first instance of each line is kept intact and
the others are deleted.
C-u M-x delete-duplicate-lines RET: Like the previous
command but search backwards. Thus effectively, the last instance
of each repeated line is left intact while the other duplicates
are deleted.
C-u C-u M-x delete-duplicate-lines RET: Delete only
those duplicate lines that are adjacent to each other. In every
contiguous group of duplicate lines, the first one is left intact
and the rest are deleted.
C-u C-u C-u M-x delete-duplicate-lines RET: Like the
first command in this list but repeated blank lines are left
intact. When executed on the whole of the example buffer
presented above, it leaves us with three non-empty lines and six
blank lines.
M-x flush-lines RET b.. RET: Delete lines in region
that match the regular expression b... If no region
is active, then delete matching lines between the point and end of
buffer. The deleted lines are not copied to kill ring.
M-x keep-lines RET b.. RET: Keep lines in region that
match the regular expression b.. and delete the rest.
If no region is active, then keep matching lines between the point
and end of buffer and delete the rest. The deleted lines are not
copied to kill ring.
M-x copy-matching-lines RET b.. RET: Copy lines in
region that match the regular expression b.. to the
kill ring. If no region is active, then copy matching lines
between the point and end of buffer. (Available since Emacs 28.1)
M-x kill-matching-lines RET b.. RET: Kill lines in
region that match the regular expression b.. to the
kill ring. If no region is active, then kill matching lines
between the point and end of buffer. (Available since Emacs 28.1)
To try each command on the entire buffer, first type C-x
h to select the entire buffer as the region and then type a
command mentioned above.
Here is a list of commands that help with splitting and joining lines:
C-o: Insert a newline after the point but do not move
the point.
C-x C-o: On blank line, delete all surrounding blank
lines, leaving just one. On isolated blank line, delete the blank
line. On non-blank line, delete all consecutive blank lines that
follow the non-blank lines. While deleting blank lines it also
deletes lines that consist only of whitespaces.
C-M-o: Split current line at the next non-whitespace
character after the point while maintaining its indentation.
Everything from the next non-whitespace character after the point
to the end of the line moves down by one line but the new line is
indented so that the column numbers of all the characters that
moved down remain the same. If a fill-prefix has been set, say
with C-x ., then the fill-prefix is inserted in the
new line.
M-^: Join current line with previous line and leave
exactly one space between the joined lines. If a fill-prefix is
set, say with C-x ., then the fill-prefix is removed
while joining lines.
The key sequence C-x C-o is very useful for removing
spurious blank lines between paragraphs.
Note that M-^ also works on a region. When a region is
active, it joins all lines in the region.
Here is a list of commands that are useful in examining whitespace in the current buffer:
M-x whitespace-mode RET: Toggle visualisation of
spaces, tabs, newlines and lines longer
than whitespace-line-column number of columns (80 by
default) with special glyphs and colour.
M-x whitespace-newline-mode RET: Toggle visualisation
of newlines.
M-x whitespace-toggle-options RET: Toggle local
options for whitespace-mode.
After typing M-x whitespace-toggle-options RET, type a
key to tell it what to do. For example, type N and it
will start or restart whitespace-mode with the
visualisation of newline toggled. Type ? to see the
list of all key inputs it supports.
The key sequence M-x whitespace-toggle-options RET may
be typed anytime regardless of whether whitespace-mode
is currently enabled or not. If whitespace-mode is not
enabled, running whitespace-toggle-options
automatically enables it. If whitespace-mode is
already enabled, then running whitespace-toggle-options
and toggling an option, restarts local whitespace-mode
with the updated option setting.
Here are some commands to report and clean up whitespace issues:
M-x whitespace-report RET: Shows a report of
whitespace issues. The "Current setting" column on left shows the
current settings found in the
variable whitespace-style. The "Whitespace Problem"
column on the right shows the whitespace problems found in the
buffer.
M-x whitespace-report-region RET: Like the previous
command but reports problems in a region.
M-x whitespace-cleanup RET: Cleans up whitespace
issues in the buffer. This command checks
the whitespace-style variable to decide which issues
to fix. See C-h f whitespace-cleanup RET for
complete details.
M-x whitespace-cleanup-region RET: Cleans up
whitespace issues in a region. Unlike the previous command, this
command does not fix empty lines at the beginning or end of
buffer. See C-h f whitespace-cleanup-region RET for
complete details.
As mentioned in the list above, the whitespace cleanup functions
read the variable whitespace-style to decide which
whitespace issues to fix. Say, we do not want to fix trailing
whitespace issue but do want to fix other whitespace issues selected
by default (e.g. empty lines at the beginning or end of buffer,
spaces before tab, etc.), then we need to update
the whitespace-style variable as follows:
(setq whitespace-style (delete 'trailing whitespace-style))
Now running whitespace-cleanup
or whitespace-cleanup-region is going to skip fixing
trailing spaces but it will perform the other cleanups determined by
the value of whitespace-style.
The behaviour of keyboard macro key sequences depend on the current context. So they are presented as table below.
| Key | Command | While not recording | While recording |
|---|---|---|---|
F3
|
kmacro-start-macro-or-insert-counter
|
Start recording | Insert counter |
F4
|
kmacro-end-or-call-macro
|
Call macro | End recording |
C-x (
|
kmacro-start-macro
|
Start recording | Do nothing |
C-x )
|
kmacro-end-macro
|
End recording | Do nothing |
C-x e
|
kmacro-end-and-call-macro
|
Call macro | End recording and call macro |
The key sequences in the table above can be divided into three groups:
C-x ( and C-x ): These invoke simple
commands that start and stop macro recording.
F3 and F3: These are wrappers around the
simple commands.
C-x e: This is a slightly high level command too that
wraps around simpler macro commands and functions that end
recording and calls a macro.
Given these details, there are broadly two ways these macro key sequences can be used. They are shown in the table below.
| Operation | Using Function Keys | Using Control Keys |
|---|---|---|
| Start recording | F3 |
C-x ( |
| Stop recording | F4 |
C-x ) |
| Call macro | F4 |
C-x e |
| Stop recording and call macro | F4 F4 |
C-x e |
| Repeat call macro | F4 |
e |
If you are comfortable using function keys, you might want to follow the second column in the table above. Otherwise, you might want to follow the third column in the table above.
The last row is not mentioned in the book but the fact
that e may be used to repeat a macro call performed
with C-x e is documented in the Emacs
manual: Keyboard
Macros: Basic Use.
Note that F3 inserts a counter value and increments the
counter value by 1 or by the number specified via a digit argument.
Here is an example key sequence that may be typed in a buffer with
multiple lines to demonstrate this:
C-x ( to start macro recording.
C-a F3 . SPC M-c C-n to insert macro counter
which 0 by default, followed by dot and space at the
beginning of the line, capitalise the first word and move to the
next line.
C-x e to stop macro recording and call the
recorded macro. Now 1, dot and space is inserted at
the beginning of the line. The first word of the current line is
capitalised and the cursor moves to the next line.
e to repeat the macro call. Keep
typing e to repeat the macro call.
The behaviour of the the macro commands change with universal arguments and digit arguments as follows:
C-u F3: Execute the last macro, then record new macro
and append it to the last macro. Set
kmacro-execute-before-append to nil
(it is t by default) to prevent executing the last
macro before appending a new macro to the last macro.
C-u C-x (: Same as above.
C-5 F3: Start recording but set counter to 5, i.e.
while a macro is being recorded, typing F3 inserts 5
the first time, 6 the second time and so on. The numeric prefix
argument sets the counter value.
C-5 C-x (: Same as above.
C-u F4: Execute the second macro in the ring.
C-7 F4: Repeat the last macro 7 times.
C-7 C-x e: Repeat the last macro 7 times.
C-0 F3: Repeat macro until there is an error (e.g.
reaching the end of a buffer).
C-0 C-x e: Same as above.
Type C-x C-k C-h to discover keyboard macro commands
and their key bindings. The list below shows some of the
interesting ones mentioned in the book. In the list below, complete
key sequences are used, so that they serve as a demonstration of the
macro commands.
C-x C-k C-a 20 RET: Add 20 value to the counter.
C-x C-k TAB: Insert counter. Note that we saw earlier
that this can also be done with F3.
C-x C-k C-c: Set counter.
C-x C-k C-f %02x: Set macro counter format to
zero-padded two-digit hexadecimal numbers with a minimum width of
2.
Note that all of the above commands work fine even when no macro
recording is in progress. For example, earlier we saw
that F3 inserts the macro counter value only when a
macro recording is in progress. However, C-x C-k TAB
inserts the macro counter value even when a macro recording is not
in progress.
Another interesting feature mentioned in the book is querying for
user input while recording a keyboard macro. The key sequence to
query the user is C-x C-k q or C-x q.
Here are a few complete key sequences that may be used to
demonstrate this feature:
F3 C-n C-a foo: C-x q C-e :bar F4: This defines a
macro such that when we execute the macro by
typing F4 one more time, the macro first
inserts foo at the beginning of the next line, then
it prompts us to decide if we want to continue with macro
execution. If we type type y, then it continues with
the remainder of the macro execution. If we type n,
it skips the rest of the macro iteration and continue with the
next iteration of the macro (such as when we are replaying the
macro multiple times with a digit argument). If we
type RET, it skips the rest of the macro execution as
well as skip any further iterations of the macro (in case we are
replaying the macro multiple times).
F3 C-a foo: C-x C-k q C-e :bar F4: Same as above but
slightly longer key sequence. The key sequence in the previous
point is easier to remember and type.
In the above examples, when the macro playback prompts queries for
user input, we can also type C-l to recentre the
screen, C-r to enter recursive edit or
C-M-c to exit recursive edit.
Note that the key sequence C-l behaves a little
differently from the regular C-l. Unlike the
regular C-l, successive invocations of this key
sequence during macro query does not cause the window to reposition
at various places (centre, top and bottom by default) in a cyclical
order. Successive invocations of C-l during macro
query, leaves the screen centred.
Here are some key sequences to save and recall macros:
C-x C-k C-p: Move to the previous keyboard macro in
the keyboard macro ring.
C-x C-k C-n: Move to the next keyboard macro in the
keyboard macro ring.
C-x C-k n foo RET: Assign the name foo
to the current keyboard macro in the keyboard macro ring. Now the
macro can be executed by simply typing M-x foo RET.
M-x insert-kbd-macro foo RET: Insert the definition
of the named keyboard macro foo as Elisp code into
the current buffer.
C-x C-k b C-c 1: Assign the key sequence C-c
1 to the current keyboard macro in the keyboard macro ring.
Now the macro can be executed by simply typing C-c 1.
Finally, here are some commands to edit keyboard macros:
C-x C-k e C-x e: Edit the current keyboard macro.
C-x C-k e M-x foo RET: Edit the keyboard macro
named foo.
C-x C-k e C-c 1: Edit the keyboard macro
bound to C-c 1.
C-x C-k l: View the most recent 300 keystrokes and
edit it to create a new keyboard macro.
M-x kmacro-edit-lossage RET: Same as above.
A few additional commands:
C-h l: See the last 300 characters typed (lossage).
M-x open-dribble-file foo.txt RET: Write input events
to a dribble file named foo.txt.
M-: (open-dribble-file nil) RET: Close the dribble file.
Here are some Abbrev commands:
C-x a l: Take the word before the cursor and define a
mode-specific abbreviation for it.
C-x a g: Take the word before the cursor and define a
global abbreviation for it.
C-x a i l: Take the abbreviated word before the
cursor and define a mode-specific expansion for it.
C-x a i l: Take the abbreviated word before the
cursor and define a global expansion for it.
Note that for the expansions to work Abbrev mode should be enabled,
say with M-x abbrev-mode RET.
Here are some complete key sequences that demonstrate how we can use Abbrev to define an abbreviation, i.e. text that automatically gets replaced by another text:
Use SPC Debian C-x a l deb RET: Define a
mode-specific abbreviation deb such that whenever we
type deb, it automatically expands
to Debian.
Use SPC Linux C-x a g lnx RET: Define a global
abbreviation lnx such that whenever we
type lin, it automatically expands
to Linux.
Hello SPC wld C-x a i l World RET: Define a
mode-specific abbreviation wld such that whenever we
type wld, it automatically expands
to World.
Hello SPC evry C-x a i g Everyone RET: Define a
global abbreviation evry such that whenever we
type evry, it automatically expands
to Everyone.
Although not mentioned in the book, these commands can be used with a numeric prefix argument to specify the number of words before the cursor to be picked for expansion for the abbreviation we are about to define. Here are some complete key sequences that demonstrate this:
I use Debian GNU/Linux C-3 C-x a l dgl: Define a
mode-specific abbreviation dgl such that whenever we
type dgl, it automatically expands to Debian
GNU/Linux.
I use Debian GNU/Linux C-3 C-x a g dgl: Similar to
above but define a global abbreviation.
There are two key bindings discussed in the book:
M-/: Expand the word just before the cursor to the
nearest preceding word for which the current word is a prefix. If
no suitable preceding word is found, expand it to the nearest
succeeding word for which the current word is a prefix. Repeating
this command cycles between the other matches found.
C-M-/: Find all words in the buffer that has the
current word before the cursor as the prefix and expand the
current word to the longest common prefix of all these matching
words. However, if the longest common prefix of the matching
words is same as the word before the cursor, then present them as
suggestions for completion. If there is exactly one matching
word, expand the word before the cursor to that word.
The last command above takes a little while to get used to it. The following steps demonstrate how it works.
Create a text buffer with the following line:
abacus apple appliance application
ap followed by C-M-/, the word
expands to appl since that is the longest common
prefix among the matching words.
C-M-/ again. The matching
words apple, appliance
and application are presented as possible completions
in a temporary buffer named *Completions*.
ic, so that the word before the cursor
becomes applic and type C-M-/ again.
Now the word before the cursor expands to application
because that is the only possible completion now.
Note that by default DAbbrev looks for matching words in other open buffers too and offers them as completions.
Unlike DAbbrev, Hippie Expand goes beyond open buffers to look for
expansions. The variable
hippie-expand-try-functions-list contains a list of
expansion functions that hippie-expand uses to look for
completions. The book suggests remapping M-/ to
invoke hippie-expand with this Elisp code:
(global-set-key [remap dabbrev-expand] 'hippie-expand)
By default, Hippie Expand can complete file names, complete lines, etc. For example, if there is a line for which the current line is a prefix (leading whitespace is ignored while checking for matches), then the current line is expanded to the other matchine line.
Repeated invocations of this command cycles between the matches.
As mentioned earlier, the
variable hippie-expand-try-functions-list determines
which expansion algorithms are used. Here is an example that
demonstrates how we can alter this variable:
(setq hippie-expand-try-functions-list '(try-complete-lisp-symbol))
The above rather unrealistic example severely restricts the
expansions Hippie Expand can perform. With the above example, word
expansion, line expansion, file name completion, etc. are disabled.
Only Elisp symbols are expanded. For example,
typing white followed by M-/ first expands
the word to whitespace because all matching Elisp
symbols have that as the longest common prefix.
Typing M-/ over and over again, completes the expansion
further with various Elisp symbols.
As mentioned before, the above example is highly atypical. The above example is only meant for demonstrating how this variable can be set. Typically, users add more functions to this variable to add more expansion capabilities.
Emacs automatically indents code as we type. The major mode decides
the automatic indentation behaviour. The automatic identation is
provided by a global minor mode named
electric-indent-mode which is enabled by default.
Typing TAB indents the current line. In many modes
like emacs-lisp-mode, python-mode,
text-mode, etc. the command
indent-for-tab-command is bound to it. But there are
modes that bind another command to TAB. For example,
in c-mode, the command
c-indent-line-or-region is bound to TAB.
The behaviour of indent-for-tab-command is determined
by the variables tab-always-indent. It
is t by default which causes TAB to just
indent the current line. If set to nil,
hitting TAB indents the current line only if the point
is before the first non-whitespace character of the line. Otherwise
it inserts tabs or spaces to move the point to the next tab stop
column. If set to 'complete, typing TAB
first tries to indent the current line but if the line is already
correctly indented, then it tries to complete the thing at point.
When indent-for-tab-command is bound
to TAB and when indent-for-tab-command
decides to indent the current line, it calls the function in the
variable indent-line-function to perform the
indentation. Here is a table that shows
what indent-line-function contains in a few major modes
where indent-for-tab-command command is bound
to TAB:
major-mode |
indent-line-function |
|---|---|
emacs-lisp-mode |
lisp-indent-line |
python-mode |
python-indent-line-function |
text-mode |
indent-relative |
While lisp-indent-line and
python-indent-line attempt to indent the current line
according to the syntax of the language,
indent-relative inserts tabs and spaces to move the
point to the next indentation point where the indentation point is
defined as the next non-whitespace character following whitespace.
This can be useful in aligning the point with words in the previous
line. If the previous line has no indentation point (e.g. the
previous line is an empty line or does not have whitespace),
then tab-to-tab-stop is invoked which inserts tabs or
spaces to move the point to the next tab stop column.
The command tab-to-tab-stop command introduced in the
previous paragraph can also be invoked with M-i.
By default, Emacs uses a mix of tabs and spaces for indentation and alignment. When it needs to align the first non-whitespace character of a line with a certain token in the previous line, it would insert as many tabs as it can followed by a few spaces if necessary to attain the desired alignment. To force Emacs to always use spaces for indentation and alignment, add the following Elisp code to the Emacs initialisation file:
(setq-default indent-tabs-mode nil)
The variable tab-width is used in various contexts
while performing indentation and alignment. For example,
when indent-tabs-mode is enabled, for
every tab-width columns of indentation required, Emacs
inserts a tab to indent the code.
Also, when indent-tabs-mode is set to nil,
typing M-i inserts as many spaces as necessary to move
the point to the next tab stop column where the distance between two
tab stops is assumed to be tab-width.
The behaviour of M-i can be customised further by
manually defining tab stop columns. Type M-x edit-tab-stops
RET first. A buffer named *Tab Stops* appears.
The second and third line of this buffer contains a ruler to
indicate the column numbers. Type : (i.e. colon) in
the first line whereever you want to define tab stops. Then
type C-c C-c to install the changes. Now
when M-i is typed in a text buffer, each time it
inserts as many tabs (if indent-tabs-mode
is t) or spaces as necessary to move the point to the
next tab stop column as defined earlier in the *Tab
Stops* buffer.
Typing TAB when a region is active indents the region
according to the major mode's indentation rules. It invokes the
same command as the one invoked when we type TAB to
indent a line. The command bound to it takes care of indenting
region. For example, if TAB is bound
to indent-for-tab-command, the latter checks if a
region is active and if it is, then it simply
calls indent-region.
The indent-region command can be invoked explicitly
using C-M-\. If fill-prefix has been set,
say with C-x ., then it is added to every line in the
region being indented. With a numeric prefix argument, each line in
the region is indented to the column indicated by the argument. For
example, C-M-1 C-M-0 C-M-\ indents each line of the
region to column 10.
When we want to rigidly control how a region must be indented, we
can type C-x TAB to perform rigid indentation. Doing
so allows us to bypass the indentation rules of the major mode.
Instead we control exactly how the indentation must be done. The
following complete key sequences demonstrates a few examples of
rigid indentation:
C-x TAB: Interactively indent region.
Type <right> or <left> to
increase or decrease indentation by one space respectively.
Type <right> or <left> to
increase or decrease indentation by one tab stop respectively.
C-6 C-x TAB: Indent region by 6 spaces. Appropriate
number of tabs and spaces are inserted to achieve an apparent 6
spaces of indentation. Whether tabs are inserted or not and how
many tabs are inserted depend on the values
of indent-tabs-mode and tab-width as
explained in the previous sections.
C-- C-6 C-x TAB: Reduce indentation of region by 6
spaces.
Assuming a region is active, here are some complete key sequences for various sorting commands:
M-x sort-lines RET: Sort lines alphabetically.
C-u M-x sort-lines RET: Reverse sort lines
alphabetically.
M-x sort-fields RET: Sort lines alphabetically by the
first field alphabetically. Fields are separated by whitespace.
M-2 M-x sort-fields RET: Sort lines alphabetically
by the second field.
M-2 M-x sort-numeric-fields RET: Sort lines
numerically by the second field.
M-x sort-columns RET: Sort columns between the column
position of mark and column position of point.
M-x sort-regexp-fields RET [A-Z]*->\(.*\) RET \1 RET:
Sort the strings in each line matched by the given regular
expression by the field matched by the first (and the only)
capturing group in the regular expression. The part of each line
that is not matched by the regular expression remains intact.
They never move. Only the part of each line that is matched by
the regular expression moves around during the sorting operation.
M-x sort-regexp-fields RET: Sort paragraphs
alphabetically.
The two simple commands for aligning text introduced first in the book are:
M-x align RET: Aligns current region.
M-x align-current RET: Aligns current section. A
section is a group of consecutive lines both below, above and
including the current line for which the first alignment rule
(according to the major mode) applies.
Consider the following Elisp buffer:
(defvar person '(("name" . "Alice")
("city" . "London")
("country" . "UK")))
If we type C-x h followed by M-x align RET
or if we put the cursor on any line of the above code and
type M-x align-current RET, we get the following
result:
(defvar alice '(("name" . "Alice")
("city" . "London")
("country" . "UK")))
There is also an align-regexp command that allows us to
parts of lines by regular expressions. The following experiments
demonstrate this command.
Alice:London:UK
Bob:Paris:France
Carol:Tokyo:Japan
Type C-x h followed by C-u M-x align-regexp
\(\s-*\): RET 1 RET 1 RET y RET. The result looks like
this:
Alice :London :UK
Bob :Paris :France
Carol :Tokyo :Japan
Note that the regular expression capturing
group \(\s-*\) appears as the default in the
minibuffer. We only add : to it. Similarly the
two occurrences of 1 appear as default values. The
first 1 is the default for determining which
parenthesis group to modify. The second 1 is the
default for amount of spacing to be used during alignment.
The y in the end specifies that we want to repeat
the alignment throughout the line.
C-/ to undo the changes done in the last step.
Then type C-x h followed by M-x align-regexp
: RET. This is a shorter equivalent to the previous
command. The output is same as before.
Type C-/ to undo the changes done in the last step.
Then type C-x h followed by C-u M-x
align-regexp :\(\s-*\) RET 1 RET 1 y RET. Note that the
only difference this time is that we place the colon before the
parenthesis group. The result looks like this:
Alice: London: UK
Bob: Paris: France
Carol: Tokyo: Japan
Type C-/ to undo the changes done in the last step.
Then type C-x h followed by C-u M-x
align-regexp \(\s-*\): RET 1 RET 0 y RET. Note that the
only difference this time is that we place the colon before the
parenthesis group. We specify 0 as the amount of
spacing this time, so a minimum of zero spacing is used for
alignment when possible. The result looks like the following.
Notice the lack of space after Alice
and Carol.
Alice:London:UK
Bob :Paris :France
Carol:Tokyo :Japan
Type C-/ to undo the changes done in the last step.
Then type C-x h followed by C-u M-x
align-regexp \(\s-*\): RET 1 RET 5 y RET. Note that the
only difference this time is that we place the colon before the
parenthesis group. We specify 5 as the amount of
spacing this time, so a minimum of 5 spaces are used for
alignment.
Alice :London :UK
Bob :Paris :France
Carol :Tokyo :Japan
The steps below demonstrate the zap-to-char command
that is bound to the key sequence M-z. This command
kills up to and including the given character.
Create a buffer with the following text:
foo bar baz qux quux
Type M-< to go to the beginning of the buffer
and then type M-z r to kill text up to and
including the first occurrence of the letter r.
The buffer now looks like this:
baz qux quux
Type M-< to go to the beginning of the buffer
and then type M-z x to kill text up to and
including the first occurrence of the letter x.
The buffer now looks like this:
quux
Now type C-e SPC C-y to reinsert the killed text at
the end of the line. The buffer now looks like this:
quux foo bar baz qux
Note that the last step yanks both chunks of text that were killed in the previous two steps. This is due to the fact that consecutive kills append to the same stretch of text in the kill ring. This fact was discussed earlier in section Append Kill
Now type M-< to go back to the beginning of the
buffer again. Then type M-2 M-z a. The numeric
argument 2 specifies that we want to zap up to the
second occurrence of the letter a. The buffer
looks like this:
z qux
Type C-e SPC C-y to reinsert the text killed in the
previous step at the end of the line. The buffer looks like
this now:
z qux quux foo bar ba
Type M-- M-2 M-z x to zap backward up to the second
occurrence of the letter x. The buffer looks like
this now:
z qu
Here are some steps that demonstrate the zap-up-to-char
command. This command kills text up to, but not including, the
given character.
Create a buffer with the following text:
foo bar baz qux quux
Type M-< to go to the beginning of the buffer.
Then type M-x zap-up-to-char RET b. The result now
looks like this:
bar baz qux quux
Type M-2 M-x zap-up-to-char RET q. The result now
looks like this:
quux
Type C-e SPC C-y to reinsert the killed text at the end
of the buffer:
quux foo bar baz qux
Type M-- M-2 M-x zap-up-to-char RET b. The buffer
now looks like this:
quux foo b
The author of the book suggests binding this command
to M-S-z with the following Elisp code:
(global-set-key (kbd "M-S-z") 'zap-up-to-char)
The above code, however, does not create the binding successfully. Therefore, use the following Elisp code instead:
(global-set-key (kbd "M-Z") 'zap-up-to-char)
Now the commands presented in this section above can be typed as follows:
M-Z bM-2 M-Z qM-- M-Z b
The spell checking commands of Emacs require a spell checking
program to be installed on the system. Emacs supports the spell
checking programs aspell, ispell,
hunspell and enchant-2. If multiple
programs are present, it looks for them one by one in the order
specified in the previous sentence and picks the first one that is
found. The following spell checking commands are introduced in the
book:
M-$: Check spelling of word under or before the
cursor. Possible corrections are offered in a new window. If the
word under or before the cursor is already correct, a message
like APPLE is correct appears in the echo area. When
corrections are offered, each correction is numbered.
Type SPC to leave the word unchanged or type a number
to choose a numbered correction. Type x to exit the
the spelling buffer (the one that shows corrections).
Type q to quit the spelling session (kills the
spelling program process). To see the list of all key bindings
supported, type C-h f ispell-help RET.
M-x flyspell-mode RET: Toggle on-the-fly spell
checking. Misspelled words are underlined with squiggly lines.
Type C-M-i or C-. to correct a
misspelled word under or before the cursor. All possible
corrections appear in the echo area. Repeat C-M-i
or C-. to cycle through the possible corrections.
M-x flyspell-prog-mode RET: Turns
on flyspell-mode for comments and strings only. This
is useful while working in a buffer with a programming mode
enabled.
M-x ispell-buffer RET: Check the current buffer for
spelling errors interactively. Each misspelled word is
highlighted and corrections are offered in a new window. The
interface and key sequences for making corrections are the same as
the ones for M-$ introduced above.
M-x ispell-region RET: Like the previous command but
checks the current region for spelling errors.
The following complete key sequences demonstrate some of the dictionary commands introduced in the book:
M-x dictionary-lookup-definition RET: Look up
definitions of the word at or before the cursor.
M-x dictionary-search RET programming RET: Search
definitions of the word programming.
M-x dictionary-select-dictionary RET: This command
presents a list of available dictionaries in a new buffer.
Navigate the buffer and click on a dictionary or
type RET while the cursor is on a dictionary entry to
select it. For example, move the cursor down to the entry that
begins with the text jargon: and
type RET and then type M-x dictionary-search
RET programming RET to see the definition of the
word programming from the Jargon File only.
The dictionary commands first attempt to connect to a locally
running dictionary server. If the connection does not succeed, it
prompts for consent to connect to
dict.org. Typing y at
the prompt allows the command to proceed and complete the command.
Here are some complete key sequences that demonstrate quoted insert:
C-q C-l: Insert form feed character. This is
displayed as ^L in Emacs using the face
named escape-glyph. Emacs treats each form feed
character as a page break and we can navigate back and forth
between pages with C-x [ and C-x ]
respectively.
C-q (: Insert a literal open parenthesis. Useful
in paredit-mode where the key sequence (
is bound to paredit-open-round which inserts a
balanced pair of parentheses. To insert a single parenthesis
instead, we can perform a quoted insert with C-q (.
C-q TAB: Insert a literal tab character.
C-q C-j: Insert a literal line feed character, i.e.
a newline character.
C-q RET: Insert a literal carriage return. This is
displayed as ^M in Emacs.
C-q ESC: Insert a literal escape character. This is
displayed as ^[ in Emacs.
C-q C-[: Same as above.
The following list includes some links that were discussed during the book discussion group meetings: