The following notes were taken while discussing Chapter 6 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 }}The book suggests the following techniques to explore Emacs:
Reading the manual. For example, type M-x info RET
or C-h i, then navigate to the Emacs
hyperlink, then type C-s version control RET and
then navigate to the node named Version Control to
read the corresponding manual.
Note that the section named The Info Manual in Chapter
3 offers more alternatives to reach a specific node in a more
straightforward manner. For example, C-h i m emacs RET m
Version Control RET accomplishes the same result.
Alternatively, C-h R emacs RET m Version Control
RET also accomplishes the same result. Yet another way
to accomplish the same result is to evaluate the Elisp
expression (info "(emacs)Version Control"). See
section Info in chapter 3 notes for
more details.
Yet another way to explore the manual is to use
the info-apropos command. For example,
type M-x info-apropos RET version control RET to
find manuals which have the string "version control" in them.
Using apropos. For example, type C-h d version control
RET to search for all symbols whose documentation string
contains the specified pattern. Then type C-h a ^vc-
RET to search for all commands that match this pattern.
This is a convenient way to list the vc commands. Also, see
section Apropos in chapter 3
notes for more details.
Exploring prefix keys. For example, type C-x v C-h
to list all key sequences bound to the prefix key C-x
v. This is in fact a convenient way to list all the vc
key bindings. Also, see section
Discovering
and Remembering Keys in chapter 3 notes for more details.
Describe what a key does. For example, type C-h k
followed by C-x v v to see the command that is
bound to the latter key sequence as well as its documentation
string along with other details like the keymap where the key
binding is found, the file where the command is defined, other
key bindings for the same command, etc. See
section Describe in chapter 3
notes for some more details.
Describe commands. For example, type C-h f vc-dir
RET to see information about the vc-dir
command. See section Describe
in chapter 3 notes for some more details.
Find mode commands. Type C-h m to see the
documentation strings of the current major mode and minor modes.
A brief summary of the minor modes is shown first, followed by
the major mode description. This is followed by documentation
strings of the minor modes separated by page breaks (the form
feed character that is rendered as ^L in Emacs).
See section Describe in chapter
3 notes for some more details.
Type M-X to run
execute-extended-command-for-buffer which executes
commands that are relevant to the current buffer. While
offering completions, it limits the completions to commands
relevant to the current buffer. See
section M-X:
Execute Extended Command for Buffer of chapter 3 notes for
more details.
Emacs comes with a project management package
named project.el which offers commands to operate on
projects. When we use a project management command like C-x p
f to visit a file in the current project, this package
automatically detects the top-level directory of the project by
checking parent directories for version control system artifacts
(e.g. .git directory) and presents files within that
top-level directory as autocomplete options.
The following complete key sequences demonstrate the package management commands mentioned in the book:
C-x p p ... TAB RET ~/git/foo/ RET f README.md:
This awkward key sequence discovers a new project directory
at ~/git/foo/ and then finds the file
named README.md in it. As soon as the key
sequence f is typed above, the new project
directory is discovered and added
to ~/.emacs.d/projects which is where the list of
known projects is saved.
C-x p p bar TAB RET f Makefile: Assuming there is
already a known project with bar in its name
(say, ~/git/bar/) that was discovered earlier, this
key sequence switches to that project and finds the file named
in Makefile in it.
C-x p f dev/build.sh RET: Find file
named dev/build.sh in the current project.
C-x p f build TAB RET: Same as above
if dev/build.sh is the only match
for build. Otherwise, it presents all files in the
current project containing build anywhere in its
path name as autocomplete options.
C-x p f bar TAB RET build TAB RET: When we
type C-x p f while visiting a file that does not
belong to any project, then its prompts for a project name. In
this example, we type bar TAB RET to automatically
expand it to a known project name such
as ~/git/bar/ and enter it. Then we
type build TAB RET to automatically expand it to a
file name such as dev/build.sh and enter it.
It is worth noting a general point that whenever we invoke a project command while visiting a file that does not belong to a project, the project command prompts for the project name. After we enter the project name, the project command runs on our chosen project. This general point applies to other project commands that come later in this list.
C-x p b Makefile RET: Switch to a buffer
named Makefile in the current project. While
entering the buffer name when TAB is typed,
completion options present buffer names from the current project
only.
C-x p k yes RET: Kill all buffers belonging to the
current project.
C-x p g ^key\> RET: Find all matches for the
regular expression ^key\> in the current
project. The matches are found in all files in the project
regardless of whether they are currently open in Emacs or not.
The matches are displayed in a buffer named *xref*.
We can navigate this buffer using key sequences
like n, p, etc. Type
C-h m in this buffer to see a list of key sequences
supported in this buffer. As we navigate this buffer and go
from one match to another using n, p,
etc. the files containing the match are loaded in a split window
automatically with the matching lines automatically centred in
that window.
C-x p r ^key\> RET =key= RET: Find all matches
for the regular expression pattern ^key\> in the
current project and replace them with =key=. The
modified files are not automatically saved though. They needed
to be saved later explicitly.
C-x p c RET: Compiles the current project. By
default, it offers as make -f as the command to be
run in the project root. If a specific make target
needs to be executed or if another command needs to be executed,
then the default command offered may be edited before
typing RET.
C-x p v: Runs VC-Dir in the current project's root
which in turn shows version control status for the project root.
C-x p s: Start shell in the current project's root
directory.
C-x p d RET: Start Dired in the current project's
root directory.
C-x p D: Same as above.
C-x p d doc/tutorial/ RET: Start Dired in
the doc/tutorial/ subdirectory in the current
project.
There are several more project management key bindings.
Type C-x p C-h to see a complete list of them.
Xref provides a generic framework to support commands for cross-referencing in Emacs. While there are several ways to set it up and configure it, the book mentions a particular way to set it up using a couple of external tools. The next two subsections discuss the setup work involved before we can use Xref in a modern way. The remaining subsections discuss how to use Xref.
By default when we try to look up a definition of an identifier in,
say, a C file or Python file, by typing M-., it
presents a minibuffer for us to select a tags table file (typically
named TAGS). This requires setting up
a TAGS file with a tool like ctags. The
book, however, does not explore this method for good reason.
Typically the TAGS file needs to be created with a tool
like ctags or etags for every project we
work on. This file contains an index of names found in source code
files. We need to periodically update it as the code of our
projects evolve, so that this index remains up-to-date. For a long
time, this was the only way to maintain an index of the names found
in a source code, so that we could perform cross-referencing in
editors like Vim and Emacs. Relying on a tool
like grep to search the code on the fly was deemed to
be quite slow. However, with modern, fast hardware we do not have
to work like this anymore. Further, there are search tools
like ag and rg which are extremely fast.
Given these modern developments, there are simpler ways to set up
cross-referencing in Emacs.
The book suggets installing an external package
named dumb-jump. It can be installed from MELPA with
the key sequence M-x package-install dumb-jump RET.
See github.com/jacktasia/dumb-jump
for more details about this package. After installing this package,
add the following code to the Emacs initialisation file:
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
Here is a minimal Elisp code that sets up dumb-jump
from scratch and configures it as mentioned above:
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(dolist (package '(dumb-jump))
(unless (package-installed-p package)
(package-install package)))
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
The above code configures Emacs to use MELPA, retrieve the latest
list of packages available there, install dumb-jump
from it, as well as set up a hook to activate it automatically when
we use certain Xref commands.
Once Xref is set up with dumb-jump as explained in the
previous section, open a source code file (say, a C file or a Python
file), move the cursor over to some identifier and
type M-. to search that identifier in your environment.
By default, it searches for the identifier in files of the same type
found under the home directory with a tool like ag,
rg or grep (the first one it finds).
There is an exception to this rule though. If
neither ag nor rg is found and only GNU
grep is found, then typing M-. on an indentifier
searches the identifier in all files in the home directory (as
opposed to searching for files of a specific type). If BSD grep is
found instead, then this is not a problem and only files of the
current type is searched for the identifier.
Further, while looking up definitions within a Git repository, this
package invokes the git grep command to restrict
searches to the repository directory.
Let us now look at a few examples of the actual search commands that
are executed under the hood when we type M-..
If neither ag nor rg is installed and we
only have grep on our system, typing M-.
while the cursor is on an identifier named foo in a
Python file leads to the execution of a command like this when BSD
grep is found:
grep -REn --include '*.py' -e '\s*\bfoo\s*=[^=\n]+' -e 'def\s*foo\b\s*\(' -e 'class\s*foo\b\s*\(?' /Users/susam
If GNU grep is found instead, then all files (not
just *.py files) are searched with a command like this:
grep -rEn -e '[[:space:]]*\bfoo[[:space:]]*=[^=\n]+' -e 'def[[:space:]]*foo\b[[:space:]]*\(' -e 'class[[:space:]]*foo\b[[:space:]]*\(?' /home/susam
If rg is the only additional search tool installed,
then the following command is executed:
rg --color never --no-heading --line-number -U --pcre2 --type py '\s*\bfoo\s*=[^=\n]+|def\s*foo\b\s*\(|class\s*foo\b\s*\(?' /home/susam
If ag is installed, then the following command is
executed:
ag --nocolor --nogroup --python '\s*\bfoo\s*=[^=\n]+|def\s*foo\b\s*\(|class\s*foo\b\s*\(?' /home/susam
When we type M-. in a file that belongs to a Git
repository, only the repository directory is searched with a command
like this:
git grep --color=never --line-number --untracked -E '\s*\bfoo\s*=[^=\n]+|def\s*foo\b\s*\(|class\s*foo\b\s*\(?' -- /home/susam/repo/*.py
The book makes a mention of rg and remarks about the
impressive speed with which it searches the file system. I
recommend it too. Since the M-. command may search the
whole home directory, if the home directory is very large, having a
fast search tool like rg or ag makes a
significant difference. For example what could normally take 10 to
20 seconds to search using grep might only take a
second or two with rg or ag. I
use M-. with rg.
The book mentions the following commands as the four most common commands we should know about:
M-.: Find definitions of the identifier at point.
If a unique definition is found, then the file containing the
definition is automatically opened and the definition is centred
in the window. If multiple possible candidates are found, then
they are displayed in an Xref buffer that we can navigate using
key sequences like n or p. As we
navigate the Xref buffer, the source of each match is
automatically opened in a split window and the matching line is
centred.
M-,: Go back to where M-. was last
invoked.
M-? foo RET ~/git/foo/ RET: Find all occurrences of
the word foo in files of the same type as the
current file in the project directory ~/git/foo/.
It does not restrict the search to definitions only. If the
current file belongs to a project already, then we could simply
type M-? foo RET. In fact, since the input to the
minibuffer prompt is the identifier at the point by default, we
could simply type M-? RET to search for the current
identifier in the current project.
C-M-. foo RET: Find symbols matching the given
pattern. Although the documentation mentions that this supports
regular expressions, it seemed to treat the given pattern as an
identifier and searched for that identifier literally. In fact,
the rg commands that were executed under the hood
were exactly the same as the ones executed by M-..
Thus with dumb-jump enabled, both M-.
and C-M-. behave similarly. The only difference is
that M-. searches for the identifier at the point
whereas C-M-. searches for the identifier we enter
at the minibuffer as input.
When multiple cross-references are displayed in the Xref buffer, we can use the following key sequences to work with the Xref buffer.
n: Move to the next cross-reference. The source of
the cross-reference is automatically displayed in another
window.
n: Move to the previous cross-reference. The source
of the cross-reference is automatically displayed in another
window.
.: Same as n.
,: Same as p.
RET: Jump to the source of the current
cross-reference.
TAB: Hide Xref buffer and jump to the source.
C-o: Show the source of the cross-reference at
point in a separate window but keep the point in the Xref
window. This is useful when we navigate the Xref buffer using
normal Emacs commands like C-p, C-n,
C-s, etc. While navigating the Xref buffer with
these normal Emacs commands, the source of the cross-references at
the point is not automatically displayed. The key
sequence C-o helps us to display the cross-reference
at the point in this case.
r: Perform search and replace in the names of the
references displayed in the Xref buffer. However, I did not
find this to be working successfully
with dumb-jump. Any attempt to use this command
with dumb-jump always led me to the following
error: No suitable matches here. This key sequence
does work as expected when Xref is invoked from Dired as going
to be explained in the next section.
Here are some key sequences that demonstrate how we can use Xref with Dired.
C-x d RET: Edit current directory using Dired.
n: Move to the next line. C-n also
works.
p: Move to the previous line. C-p also
works.
m: Mark the file or subdirectory at the point.
u: Unmark the file or subdirectory at the point.
A f.. RET: Find all matches for the regular
expression f.. in the marked files and
subdirectories. The matches are always displayed in an Xref
buffer, even when a single match is found.
Q f.. RET bar RET: Find all matches for the regular
expression f.. in the marked files and subdirectories
and replace them with bar.
In this section of the book, it discusses a set of commands that are useful for working with log files. Note that some of these commands have been already introduced in the previous chapters. The following list presents the commands discussed in this section of the book:
C-x C-f: Find a file.
C-x C-r: Find file and open in read-only mode.
C-x C-q: Toggle read-only mode.
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. See
section Deleting
and Keeping Lines of chapter 5 notes for more details.
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. See section
Deleting and
Keeping Lines of chapter 5 notes for more details.
M-s o b.. RET: Show all lines in the current buffer
matching the regular expression b... If the region
is active, then show matching lines from the region only. The
matches are shown in a new Occur mode buffer. The book makes a
special mention that we can run M-s o on an Occur
mode buffer to filter it further and get the results in another
Occur mode buffer. See section
Occur Mode in chapter 4 notes
for more details.
Section Working with Log Files of Chapter 6 of the book also introduces highlighting commands that can be very useful for highlighting certain strings in the log file. The highlighting commands are demonstrated below with an example.
First create a buffer with the following content.
foo bar baz
Foo Bar Baz
FOO BAR BAZ
foo bar baz
Foo Bar Baz
FOO BAR BAZ
Now type M-s h p f.. SPC b.. RET RET to highlight
the phrases matching the regular expression f.. b..
in a case-insensitive and whitespace-insensitive manner. A
total of six matches will be highlighted because the first two
words and the whitespace between them in all lines match this
phrase pattern when we ignore the case of the words and the
amount of whitespace. The second RET is meant to
accept the default face offered to us for highlighting.
Now type M-s h p b.z RET RET to highlight the
phrases matching the regular expression b.z. Again
we select the default face offered to us for highlighting. At
this point, we should see two sets of highlighting in two
different faces.
Now move the cursor to one of the first set of highlights and
type M-s h u RET. Those highlights will be
unhighlighted. The RET key accepts the default
unhighlighting pattern offered to us. It happens to be the
pattern with which the highlight under the cursor was
highlighted. That is why this key sequence ends up
unhighlighting the highlight under the cursor.
If the cursor were not over a highlgiht, then the default
unhighlighting pattern offered to us would have been the pattern
we used for the last highlight. In that case, we could
type M-s h u f.. b.. RET to explicitly specify the
unhighlighting pattern.
Now type M-s h u RET again to remove the second set
of highlights too.
Type M-s h p F.. SPC B.. RET RET to perform a
case-sensitive but whitespace-insensitive highlighting. When
there is an uppercase letter in the pattern, the highlighting
becomes case-sensitive.
Type M-s h u RET to remove the previous
highlighting.
Type M-s h r f.. SPC b.. RET RET to perform a
case-insensitive but whitespace-sensitive highlighting. This
time, there are only three matches from the first three lines.
Type M-s h u RET to remove the previous
highlighting.
Type M-s h r F.. SPC B.. RET RET to perform a
case-sensitive and whitespace-sensitive highlighting. The
matching strings are found in the second and third lines.
Move the cursor to lowercase bar and type M-s
h . to highlight symbol at point. All six occurrences of
this symbol are highlighted in a case-insensitive manner because
the symbol at point is written in all lowercase.
Move the cursor to Baz and type M-s h
. to highlight symbol at point. Only two occurrences of
this symbol get highlighted. The highlighted symbols match the
symbol Baz exactly (case-sensitive match). The
highlighting is done in case-sensitive manner because the symbol
at point has at least one uppercase letter.
The following steps demonstrate how to use
the revert-buffer command and then how to
use auto-revert-mode.
In a terminal, run the following command:
: > /tmp/log.txt && while true; do date >> /tmp/log.txt; sleep 1; done
You could use ansi-term within Emacs too as the
terminal if you are familiar with it.
Now within Emacs, type C-x C-f /tmp/log.txt RET.
Wait for a few seconds and type M-x revert-buffer RET yes
RET to update the buffer with the latest content of the
file from the file system.
Type M-x auto-revert-mode RET to enable automatic
update of the buffer as the file changes on the file system.
Note that this reloads the entire file whenever a change is
detected, so this could be inefficient while working with very
large files.
Type M-> to go to the end of the buffer. This
moves the cursor to the end of the buffer. Doing this ensures
that as the buffer is automatically updated, the cursor
automatically keeps moving to the end of the file.
Terminate the command of step 1 and run this command in a terminal:
echo hello > /tmp/log.txt
The content of the buffer should now automatically truncate and
update to just the text hello.
Run the command in step 1 again and confirm that the content of the buffer in Emacs gets updated automatically.
Type M-x auto-revert-mode RET to disable automatic
update of the buffer.
The mode named auto-revert-tail-mode is similar
to auto-revert-mode. However,
unlike auto-revert-mode which reloads the entire file
on every update, the auto-revert-tail-mode only follows
the tail of the buffer and appends any new text found to the buffer.
The following steps demonstrate this:
Like in the previous section, run the following command:
: > /tmp/log.txt && while true; do date >> /tmp/log.txt; sleep 1; done
Type M-x auto-revert-tail-mode RET. Note that this
command follows the tail of the file only. It does not reload
the entire file. This can be confirmed with the next step.
Terminate the command of step 1 and run this command in a terminal:
echo hello > /tmp/log.txt
The buffer for this file in Emacs should automatically update to
show the text hello at the bottom. But notice all
the earlier text remains intact. The earlier text does not
disappear from the buffer because Emacs does not reload the
entire file when auto-revert-tail-mode is enabled.
Run the command in step 1 again and confirm that the content of the buffer begins to get updated automatically again.
As of Emacs 28.2, unfortunately running M-x
auto-revert-tail-mode RET is not sufficient to disable
automatic updates in the buffer. This command does disable the
mode but the buffer continues to be updated everytime the file
changes. This is very likely a bug in this mode.
As a workaround, disabling auto-revert-mode ends up
stopping the auto-update behaviour. There are two ways to do
this. You could type M-x auto-revert-mode RET
twice: once to enable it and a second time to disable it.
Alternatively, just simply type C-0 M-x auto-revert-mode
RET which invokes the mode with a prefix argument of zero
which ends up disabling the mode.
The following steps demonstrate how we can not only browse a tarball but also edit files in it and save them back to the tarball.
First, create a directory of text files with the following shell commands:
mkdir -p foo/bar/baz/
echo hello foo > foo/foo.txt
echo hello bar > foo/bar/bar.txt
echo hello baz > foo/bar/baz/baz.txt
tar -caf /tmp/foo.tgz foo/
Confirm that the tarball looks good with these shell commands:
tar -tf /tmp/foo.tgz
tar -xOf /tmp/foo.tgz
Within Emacs, type C-x C-f /tmp/foo.tgz RET to open
the tarball. A list of all entries in the tarball is displayed
in a Tar buffer.
Type n and p to navigate the Tar
buffer down and up respectively.
With the cursor on the line
containing foo/bar/baz/baz.txt,
type RET. The content of this entry is now
displayed in a new buffer.
Now in the buffer that displays the content
of baz.txt, edit its content. Say, type C-a
! to append an exclamation point to this buffer.
Type C-x C-s to save this buffer. This updates the
entry of foo/bar/baz/baz.txt within the buffer
for foo.tgz. However, the updated tarball is not
written to the file system yet.
Type C-x b foo.tgz RET to go back to the buffer
with the tarball entry listing.
Finally, type C-x C-s to save the tarball to the
file system.
Now repeat step 2. The updated content
of foo/bar/baz/baz.txt should now appear in the
output.
Assuming there is a directory ~/foo/ that contains
several image files as well as files of other types, the
command M-x image-dired RET ~/foo/ RET creates a
preview buffer of all images in the directory and displays it along
with a normal dired buffer showing the directory listing. Both
buffers are displayed in two separate windows.
When the preview buffer is first launched, all image files found in
the directory are automatically marked. This can be seen
in the Dired buffer. However the preview buffer does not reflect
this immediately. Type m in the preview buffer to
force it to pick the current list of marked images and highlight
them.
As a best practice, remember to type m soon after
launching image-dired so that the marked images are
accurately displayed in the preview buffer.
Within the preview buffer, the following key sequences are supported:
C-f: Move to next image.
C-b: Move to the previous image.
C-n: Move to next row of images.
C-p: Move to previous row of images.
RET: Display the original image in a display buffer.
m: Mark an image file.
u: Unmark an image file.
d: Flag an image file for deletion.
t t: Tag marked thumbnails. If no thumbnails are
marked, tag the current thumbnail.
t r: Remove tag from marked thumbnails. If no
thumbnails are marked, remove tag from the current thumbnail.
l: Rotate thumbnail left.
r: Rotate thumbnail right.
The m, u or d commands in the
preview buffer are actually meant to mark, unmark or flag the
corresponding files in the Dired buffer. The highlighting or
unhighlighting that occurs in the preview buffer is merely a
convenience feature. The preview buffer may not always accurately
reflect the most recent list of all marked and flagged files.
Always keep an eye on the Dired buffer to check the most recent
state of the files.
Especially, if we go back to the Dired buffer and mark, unmark or
flag files, the preview buffer does not reflect it automatically.
We need to go to the preview buffer again and perform at least one
similar operation (m, u or
d) in the preview buffer for it to be updated again.
This is why it is important to keep an eye on the Dired buffer to
get an accurate account of which files are marked or flagged.
Say we have marked some image files using the key
sequence m in the preview buffer. Now we can perform
various operations on these marked files. For example, to copy the
marked files to /tmp/ directory, in a Dired buffer,
type C /tmp/ RET. To move them instead, type R
/tmp/.
When we flag thumbnails by typing d in the preview
buffer, the corresponding files are flagged for deletion in the
Dired buffer. The first column of the flagged file entries contain
the letter D in the Dired buffer. Type x
in the Dired buffer to permanently delete (expunge) the flagged
files.
If there are marked images, then the tagging and untagging commands executed in the preview buffer work on those marked images. Otherwise, they work on image corresponding to the current thumbnail. We will refer to these images that the tagging or untagging commands work on as target images in the next few paragraphs..
The key sequence t t trip;oxford;uk RET tags the target
images with the tags trip, oxford
and uk. The tags must be separated by semicolon as
shown in the preceding example. The tags are saved in a path set in
the image-dired-db-file variable. Type C-h v
image-dired-db-file to read this path. Typically, it is
something like ~/.emacs.d/image-dired/.image-dired_db.
We will call this the DB file. This file may be manually inspected
to see how this command and the next command affect the tags for
each thumbnail. Alternatively, type C-t e in a Dired
buffer to view and edit the tags of the target files.
The key sequence t r trip RET removes the
tag trip from the target images. By virtue of how this
functionality is implemented, a key sequence like t r
t.*d removes the tags trip;oxford
and trip;salford (if present) from the DB file but it
does not remove a tag like trip;cambridge (if present).
Tagging thumbnails could be useful if we want to later mark files by
tags. In a Dired buffer, the key sequence C-t f t.*d
will mark all files whose thumbnails have tags (as they appear in
the tags file) matching the regular expression t.*d.
For example, images that have with tags trip;oxford;uk
as well as trip;london;uk will be marked but images
with tags trip;bath;uk
and trip;liverpool;uk will not be marked.
When we type RET in the preview buffer, the original
image is displayed in a display buffer. The following key sequences
are supported in the display buffer:
s: Resize image to fit window.
f: Display current image in full size.
q: Quit window.
The book makes a note that when we open an image file directly from
a Dired buffer, the image is opened in image-mode which
is more powerful than the display buffer we get when we open an
image from the thumbnail preview window.
When a PDF or another document of a supported format is opened in
Emacs, they are converted to images on the fly and displayed in
Emacs. In this section, we will discuss working with PDFs only.
The converted images are cached at the directory set in
the doc-view-cache-directory variable.
Type C-h v auto-mode-alist RET and search
for doc-view in the help buffer to see the list of file
formats that Emacs tries to open in DocView.
Ghostscript needs to be installed so that DocView can convert the
PDF into images. Further, for some commands where we perform
text-based operations on the PDF, we need the pdftotext
command so that DocView can extract text from the PDF.
Type C-h v doc-view-ghostscript-program RET
and C-h v doc-view-pdftotext-program RET to see the
external programs that DocView depends on. These programs can be
installed with the following command on a Debian or Debian-based
Linux distribution:
apt-get install ghostscript poppler-utils
On a macOS system, run the following command instead:
brew install ghostscript poppler
The following list presents some of the key bindings supported by DocView:
n: Go to next page.
p: Go to previous page.
C-x ]: Same as n.
C-x [: Same as p.
SPC: Scroll up if possible or go to next page.
DEL: Scroll down if possible or go to the previous page.
S-SPC: Same as above.
M-<: View the first page.
M->: View the last page.
+: Enlarge the document.
-: Shrink the document.
0: Reset the document size to the initial one.
W: Fit the image width to the window width.
H: Fit the image height to the window height.
P: Fit the image to the window such that neither the
document width nor the document height exceed the window width or
height respectively.
F: Resize the window so it just fits the page. When
there is only window in the frame, the window cannot be resized
independently of the frame, so the frame is resized instead.
M-x doc-view-presentation RET: Display document in
presentation mode, i.e. as a full screen slide show.
Although not mentioned in the book, here are some commands that show
how to perform text-based operations on the PDF. These commands
need pdftotext to be installed.
C-s ^f..\> RET: Initiate a new search for lines
that begin with a three-lettered word beginning with the
letter f. The cursor does not move to the first
match automatically. To make the cursor move to the first match,
type C-s. This is also explained in the next point.
C-s: When a search has been initiated, jump to the
next match for the last search that was initiated.
C-u C-s ^b..\> RET: Initiate a new search. This
is useful when a search was already initiated and we want to
abandon that search and start another new search.
C-r: Similar to C-s but works in reverse
direction. All three commands mentioned above work
with C-r too.
C-t: Show tooltip for the current location.
Normally, this shows a tooltip like "Page 100 of 314" to describe
the current page. When a search is in progress, the tooltip
includes all the matches from the current page too.
C-c C-t: Show the current document's content as text.
Then type the key sequence C-c C-c to switch to
editing the document and C-c C-c again to switch to
viewing the document. The key sequence C-c C-c is
elaborated a little more in the next point.
C-c C-c: Toggle between editing or viewing the
document. In case of PDF, switching to editing the document may
not be very helpful because the binary code of the document is
opened for editing in this mode which is quite non-trivial to edit
directly.
If the text in the document looks pixelated in Emacs, set
the doc-view-resolution variable to 300 as follows:
(setq doc-view-resolution 300)
This sets the dots per inch resolution used to render the documents to 300. This offers a good trade-off between high quality rendering and fast rendering. After setting this variable, type the following key sequences:
M-x doc-view-clear-cache RET to delete the cache
directory.
C-x k to kill the existing DocView buffer (if any).
C-x C-f document.pdf RET to open the document
(say document.pdf) again!
Clearing the cache directory and reopening the document in this manner regenerates the images from the documents with the updated resolution.
TRAMP stands for Transparent Remote Access, Multiple Protocol. The general syntax of paths supported by TRAMP is:
/method:[user@][hostname[#port]]:[path]
Here are some complete key sequences that demonstrate various ways to open a remote file using TRAMP:
C-x C-f /ssh:alice@box:~/foo.txt RET: Edit file in a
remote host via SSH.
C-x C-f /ssh:susam@box#22:~/foo.txt RET: Same as
above. However the port is explicitly specified this time.
C-x C-f /scp:alice@box:~/foo.txt RET: Edit file in a
remote host via SCP.
C-x C-f /ssh:box:~/foo.txt RET: Edit file in a
remote host via SSH after logging into it with the username of the
current user in the current shell.
C-x C-f /ssh:alice@:~/foo.txt RET: Edit file in
localhost via SSH after logging into it as a specific user.
C-x C-f /ssh::~/foo.txt RET: Edit file in localhost
via SSH after logging into it with the username of the current
user in current shell.
C-x C-f /sudo::/etc/hosts: Edit file as superuser.
C-x c-f /sudo:alice@:~/foo.txt RET: Edit file as
a specific user.
C-x C-f /sudoedit::/etc/hosts: Edit file as superuser
but do not keep an open session running in the background for
security reasons. This method has worse performance than
the sudo method.
C-x C-f /su::/etc/hosts: Edit file as
the root user.
/su:alice@:~/foo.txt: Edit file as a specific user.
/su:alice@localhost:~/foo.txt: Same as above.
C-x C-f /sudo:: RET: Browse the root
user's home directory as superuser.
C-x C-f /su:: RET: Browse the root
user's home directory with Dired.
C-x C-f /-:: RET:
Use tramp-default-method (scp by
default) to connect to tramp-default-host
(current hostname by default). With the default
values of these variables, this leads to connecting to the local
system as the current user via SCP and browsing the current user's
home directory in Dired.
This chapter recommends looking up the info manual
page (tramp) Internal methods but this is very likely
an error. For example, evaluating (info "(tramp)Internal
methods") leads to the following error:
user-error: No such node or anchor: Internal methods
Instead evaluate (info "(tramp)Inline methods") to
reach the correct node that describes the various connection
methods.
The variable default-directory is buffer local.
Typically, this is automatically set to the directory where Emacs
was launched or to the directory of the currently visited file.
Commands like C-x C-f defaults to looking up files in
this directory.
While editing a remote file via TRAMP, the value for this variable
may look something like /ssh:alice@box:/home/alice/.
The @ character is displayed in the mode line while
editng a remote file.
The chapter presents the following examples of commands that work seamlessly on a remote machine:
C-x d: Manage remote files and directories. We can
even copy files (using the key sequence C) between
remote and local dired sessions.
M-x compile RET RET: Run make -k (the
default) or an arbitrary command remotely. The result is shown in
the *compilation* buffer.
M-x rgrep RET f.. RET *.txt RET RET:
Use find and grep together to search for
the pattern f.. in files matching the
pattern *.txt in the current remote directory.
M-x shell RET: Open shell on the remote system in the
current remote directory.
M-x eshell RET: Open Eshell on the remote system in
the current remote directory.
With Eshell we can go directly into remote directories seamlessly. The following Eshell session illustrates this:
Welcome to the Emacs shell ~ $ uname Darwin ~ $ cd /ssh:alice@box:~/foo/ /ssh:alice@box:/home/alice/foo $ hostname debian /ssh:alice@box:/home/alice/foo $
Here are some commands that illustrate how multi-hops work:
C-x C-f /ssh:alice@box|ssh:bob@localhost:~/foo.txt
RET: First log in as alice
into box and then from there log in
as bob into the same system.
C-x C-f /ssh:alice@box|sudo:box:/etc/hosts RET: First
log in as alice into box and then edit
file as superuser.
C-x C-f /ssh:alice@box|sudo::/etc/hosts RET: Same as
above.
C-x C-f /ssh:alice@box|sudo:bob@box:~/bar.txt RET:
First log in as alice into box and then
use sudo to edit file as bob in the
latter user's home directory.
C-x C-f /ssh:alice@box|su::/etc/hosts RET: First log
in as alice into box and then edit file
as root.
C-x C-f /ssh:alice@box|su:bob@:~/bar.txt RET: First log
in as alice into box and then edit file
as bob.
C-x C-f /ssh:alice@box|su:bob@box:~/bar.txt RET: Same
as above.
C-x C-f /ssh:alice@box1|ssh:bob@box2|ssh:carol@box3:~/foo.txt:
An example of two hops.
Bookmarks with key sequences like C-x r m
(bookmark-set), C-x r l
(bookmark-bmenu-list) and C-x r b
(bookmark-jump) work seamlessly for remote files
(including multi-hops).
Eshell works seamlessy too across multi-hops. Here is an Eshell session that illustrates it:
~ $ uname Darwin ~ $ cd '/ssh:alice@box1|ssh:bob@box2|ssh:carol@box3:/home/carol/foo/bar/' /ssh:alice@box1|ssh:bob@box2|ssh:carol@box3:/home/carol/foo/bar $ uname Linux /ssh:alice@box1|ssh:bob@box2|ssh:carol@box3:/home/carol/foo/bar $
The following commands are useful to get started with EWW.
M-x eww RET hello RET: Search for the word "hello"
with DuckDuckGo. If the buffer *eww* already exists,
then reuse that buffer, otherwise create such a buffer. The
search engine can be customised by setting the
variable eww-search-prefix (it
is "https://duckduckgo.com/html/?q=" by default).
C-u M-x eww RET hello RET: Like previous command
except that it creates a new EWW buffer.
M-x eww RET example.net RET: Visit the
URL http://example.net. Reuses
the *eww* buffer if it exists.
M-x eww RET http://example.net/ RET: Same as above.
C-u M-x eww RET example.net RET: Like before but
creates a new EWW buffer.
In the EWW buffer, the following navigation keys work:
TAB: Skip to the next link.
S-TAB or C-M-i: Skip to the previous link.
RET: Browse the URL under point.
C-u RET: Browse the URL under point using an external
browser. This is especially useful when we know that the URL we
want to open does not render well in EWW.
&: Open the current page in an external browser.
Note that unlike the previous command, this command opens
the current page. The previous command opens the URL
under point instead.
q: Quit EWW.
l: Go to the previously displayed page.
r: Go to the next displayed page.
b: Bookmark the current page.
B: Show bookmarks.
H: Show history of the current EWW buffer. The most
recently visited URLs are displayed on top and the oldest ones are
shown at the bottom. The current URL is not displayed in the
history. Only the older URLs are shown in the history.
R: View the main "readable" parts of the current
page. This command uses heuristics to find the parts of the web
page that contains the main content and omits the non-content part
like navigation menus etc.
M-s M-w: Search the web for the text in the region.
If there is no region, then prompt for a search string.
M-RET: Open link in a new EWW buffer.
s: Prompt for an EWW buffer to display and switch to
the selected buffer. This is similar to changing to tabs in a
desktop web browser.
w: If the point is on a URL or just after a URL, then
copy that URL to the kill ring. If the point is at any other
place, copy the URL of the current page.
Further, EWW supports a few semantic browsing methods. The pertaining commands are presented below. However note that whether these commands would work on a page or not depends on whether the page provides the relevant navigation aids required by these commands. Here are the key sequences for such commands:
p: Go to the page marked previous. A page
is marked previous if there is
a <link> tag or an <a> tag
for it with the attribute rel="prev" (a standard
value for the attribute) or rel="previous"
(non-standard value supported by EWW).
n: Go to the page marked next. A page is
marked next if there is a <link> tag
or an <a> tag for it with the
attribute rel="next".
u: Go to the page marked up. A page is
marked up if there is a <link>
or an <a> tag for it with the
attribute rel="up".
t: Go to the page marked top. A page is
marked top if there is a <link> tag or
an <a> tag for it with the
attribute rel="start" or rel="home"
or rel="contents".
If we would rather open a URL using our desktop web browser, then we
can use the browse-url command like this: M-x
browse-url RET http://example.net/ RET.
This command very conveniently picks up the word or domain name at
the point or just before the point and uses that as the default
value for the URL input. Therefore if the cursor is already on a
URL, then we can simply type M-x browse-url RET RET to
visit it.
There are several ways to start Dired. Some examples are presented below:
C-x C-f ~/foo/bar/ C-d: If IDO or FIDO mode is
enabled, then this key sequence automatically opens Dired in the
given directory path. Essentially, while using C-x
C-f with IDO/FIDO mode, we can type C-d
anytime and Dired is opened in the path entered so far.
M-x dired RET ~/foo/bar/ RET: Opens Dired in the
given directory path.
M-x dired RET RET: In the previous command, the
default input is the path of the current directory
(default-directory), so this key sequence
conveniently opens Dired in the current directory.
C-x d: Same as above.
C-x 4 d: Like before but open Dired in another
window.
The following keys work in a Dired buffer:
RET: Visit the file or directory on the current line.
^: Go up by one directory. If the parent directory
is found in an existing buffer, then switch to that buffer.
Otherwise create a new buffer to show the parent directory in
Dired.
q: Quit Dired window. The buffer remains intact,
i.e. the buffer is only buried, not killed.
C-u q: Quit Dired window and kill the buffer.
p or C-p: Move to the previous line and
position the point on the filename.
n or C-n: Move to the next line and
position the point on the filename.
Note that when we go from one Dired buffer to another (say, by
typing RET to enter a subdirectory from a parent
directory), then typing q or C-u q buries
or kills (respectively) the current buffer and takes us back to the
last Dired buffer.
The following list describes marking and unmarking commands of Dired:
m: Mark the file or directory at point. If the
region is active, mark all files or directories in the region.
Note that at least one character of the filename or directory name
must lie within the region for a file to be marked.
u: Unmark the file or directory at point. If the
region is active, unmark all files or directories in the region.
Note that this also removes the flag for deletion (introduced
later in this list).
U: Unmark everything. Note that this also removes
flags for deletion.
d: Flag the file or directory for deletion. If the
region is active, flag all files or directories in the region for
deletion.
The following key sequences describe the effects of prefix arguments with marking, unmarking and flagging commands:
C-5 m: Mark 5 files from the current line to 4 more
lines below.
C-5 u: Unmark 5 files from the current line for
deletion..
C-5 d: Flag 5 files from the current line for deletion.
C-- C-1 m: Mark the file on the previous line.
C-- C-1 u: Unmark the file on the previous line.
C-- C-1 d: Flag the file on the previous line for deletion.
C-- C-5 m: Mark files in the 5 previous lines.
C-- C-5 u: Unmark files in the 5 previous lines.
C-- C-5 d: Flag files in the 5 previous lines for
deletion.
Additionally, the chapter mentions the following commands in a separate table but on Emacs 28.2, they seem to have the same effect as one of the commands discussed earlier:
* m: Behaves the same as m and marks
files.
* u: Behaves the same as u and unmarks
files.
However the following commands (also introduced briefly in the same table but illustrated with complete key sequences below) provide additional marking and unmarking facilities:
* % f.. RET: Mark files with names that match the
regular expression f... If the region is active,
then only the files in the region that match the pattern are
marked. The directories . and .. are
never marked.
% m f.. RET: Same as above.
C-u * % f.. RET: Unmark files with names that match
the regular expression f... If the region is active,
then only the files in the region that match the pattern are
unmarked. The directories . and .. are
never unmarked.
C-u % m f.. RET: Same as above.
t or * t: Toggle marks. The marked
files become unmarked and vice versa. If the region is active,
toggle the marks of only the files in the region. The
directories . and .. are never toggled.
Flagged files are not toggled.
* c * D: Change all files marked with *
to be now marked with D (i.e. flagged for deletion).
Note that unlike the other commands, this command ignores the
active region. It performs the change in the whole buffer.
* c D SPC: Change all files marked
with D to be now unmarked.
The chapter also mentions a key sequence * . to mark
files by extension but this requires dired-x, so this
is discussed in a later section of this page.
This section explains some operations we can perform in Dired. If there are one or more items marked in the Dired buffer, then the operations work on the marked items. Otherwise, the operations work on the item under the cursor.
C: Copy marked files or copy the current file. If
one file is being copied, this command prompts for the target file
path. If multiple files are being copied, this command prompts
for the target directory path.
R: Rename marked files or the current file. If one
file is being renamed, this command prompts for the target file
path. If multiple file are being renamed, this command prompts
for the target directory path.
O: Change owner of the marked files or the current
file. A complete key sequence may look like O root
RET.
G: Change group of the marked files or the current
file. A complete sequence may look like G wheel RET.
M: Change the mode of the marked files or the current
file. A complete key sequence may look like M u+x
RET or M 600 RET. Both symbolic modes
like u+x and numeric modes like 600 are
supported.
D: Delete marked files, i.e. the files that are
marked with * on the leftmost column of the Dired
buffer.
x: Delete the files flagged for deletion, i.e. the
files that are marked with D on the leftmost column
of the Dired buffer.
c: Compress marked files or current file into an
archive. The archive file name is prompted. The format of the
archive is automatically deduced from the extension of the file
name entered at the prompt. A complete key sequence may look
like c foo.tar.gz RET or c foo.zip RET.
Note the difference between D and x. The
key D deletes marked files but the key x
deletes flagged files. Therefore there are two ways of deleting
files:
m and delete them with D.
d and delete them with x.
I normally prefer the second way of deleting files. Since deleting
file is a destructive operation which is possibly risky, I like to
flag them first with d before deleting them
with x. In other words, I flag files for deletions and
mark files for everything else. Since I do not use
the D key, I can be confident that my marked files are
always safe and there is no risk of inadvertently deleting them.
The following steps explain how we can copy or move files from one Dired buffer to another. First we will see the default behaviour and then we will customise Dired to copy or move files to a particular Dired directory.
C-x d /usr/ RET.
C-x 2.
C-x d /tmp/ RET.
C-x 2 agian.
C-x d /etc/ RET.
/etc/ and then
type C or R and we will see that the
default directory to copy/move the file to is /etc/.
(setq dired-dwim-target t).
C or R again while the cursor
is on some file in /etc/. We will see that the
default directory to copy/move the file to is /tmp/
now. Since dired-dwim-target is set to non-nil,
Dired picks the directory from the next window with a Dired buffer
and uses that as the target buffer.
Here are some examples of Dired keys that do not act on marked files but does other interesting work:
g: Refresh the Dired buffer.
+: Create directory. A complete key sequence may
look like + bar RET.
s: Toggle sorting by date. By default, the items in
the Dired buffer are sorted by file/directory names.
<: Jump to the next directory.
>: Jump to the previous directory.
j: Jump to a file by name. A complete sequence may
look like j hosts RET. Note that this only moves the
cursor to the line in Dired buffer with the provided filename. It
does not visit the file.
M-s a C-s: Perform multi-file incremental search
through all marked files or the current file. Marked directories
are ignored. Action region is also ignored. It performs the
search across all marked files. A complete key sequence may look
like M-s a C-s foo and then repeat C-s
over and over again to jump through all the matches. When the
search reaches the end of one file, the next C-s
automatically jumps to the match in the next file.
Q: Perform multi-file regex-based search-and-replace
operation through all marked files or the current file. For any
marked directories, the search-and-replace operation is performed
in all its files recursively. The active region is ignored. A
complete key sequence may look like Q f.. RET \&\&
RET which searches for strings matching the
pattern f.. and duplicates that string. The key
sequences supported by C-M-%
(query-replace-regexp)
like y, n, etc. work here. See
section Search and
Replace for an account of the supported key sequences. The
search results are also displayed in a
separate *xref*
A: Find matches for a regular expression pattern in
all marked files or the current file. For any marked directories,
all its files are searched recursively. The active region is
ignored. A complete key sequence may look like A
f.. RET. Note that this does not perform incremental
search. Instead the search results are displayed in
*xref* buffer.
!: Run a shell command on each marked file or
directory (or the current file or directory if nothing is marked).
The command is executed synchronously. The active region is
ignored or the current file or directory. The command works on
all marked files and directories. The output is displayed in a
separate buffer. If * is present in the command,
then each * is replaced with the entire file list and
the command runs only once (not multiple times, once for each
file). If ? is present in the command, then the
command runs multiple times, once for each marked file, with
each ? replaced with the name of the file being
operated on. It is an error to specify both *
and ?. If neither is present, then the command runs
multiple times, once for each marked file.
&: Like the previous command but runs the command
asynchronously.
To understand the usefulness of g, while Dired is open
create a new file in the current directory with, say, C-x C-f
foo.txt RET and save it with C-x s. Then kill
the buffer for the file with C-x k and return to the
Dired buffer. The Dired buffer does not show the new
file foo.txt. Now type g to refresh the
Dired buffer. As soon as g is typed, the buffer gets
updated to display the new file.
To understand the difference between ! and
& mark five files and then type the key
sequence ! sleep 1; echo. Emacs blocks (i.e. does not
react to our keystrokes) for 5 seconds while it runs the given
command for each file. When the echo output for all
files is obtained after 5 seconds, the output appears and Emacs
unblocks again. Now type & sleep 1; echo. Now
Emacs remains unblocked while the output of each echo
command appears at one second intervals in the output buffer.
Dired-X provides extra Dired functionality. It is not enabled by default. To enable it, add the following line to the Emacs initialisation file:
(require 'dired-x)
The following key sequences are supported by Dired-X:
F: Visit the marked files or the current file. When
multiple files are visited, they are opened in split windows
distributed as evenly as possible.
C-u F: Visit the marked files or the current file but
open them in background, i.e. do not show them on any window.
* .: Mark files with a certain extension. If the
region is active, then mark only the files in the region that have
the given extension. A complete key sequence may look
like * . txt.
! and &: These commands still work
the way they were described in the previous section. However with
Dired-X enabled, when ! or & is
invoked on a single file (either a single marked file or no marked
file in which case it operates on the current file), it
automatically determines the command to execute for the current
file type and offers that as the default input.
The following key sequences offer some support for working across multiple directories in the same Dired buffer:
i: While the cursor is on a line for a directory, it
expands the directory listing for that directory in the same Dired
buffer. Now we could use the mark, unmark, etc. commands to
select files that belong to multiple directories and operate on
them from the same Dired buffer.
$: Collapse or expand the current directory listing.
If there are multiple directory listings (such as the ones created
with i), then move to the next directory listing
after collapsing or expanding the current one.
Using i to insert the directory listing of a
subdirectory into the current Dired buffer could feel tedious if we
want to recursively work on multiple directories. The commands
(illustrated with complete key sequences below) may be more suitable
for such operations:
M-x find-dired RET RET -name SPC "f*.txt" RET: Find
all files and directories in the current directory and its
subdirectories recursively with name matching the
pattern f*.txt and show the results in the buffer
named *Find* with Dired mode enabled in it. Emacs
runs the following command to get the results:
find . \( -name "f*.txt" \) -ls
M-x find-name-dired RET RET f*.txt RET: Same as
above. Emacs runs the following command to get the results:
find . \( -name f\*.txt \) -l
Further on a system with case-insensitive filenames, Emacs is
clever enough to use the -iname argument instead
of -name so that case-insensitive search is
performed.
M-x find-grep-dired RET RET f.. RET: Find all files
in the current directory and its subdirectories recursively and
list the files where lines matching the regular
expression .. is found. The result is shown in a
the buffer named *Find with Dired mode enabled in
it. Emacs runs the following command to get the results:
find . \( -type f -exec grep -q -e f.. \{\} \; \) -ls
M-x find-lisp-find-dired RET RET f.. RET: Find all
files in the current directory and subdirectories recursively
and list the files with names that match the regular expression
pattern ... Note that this is different from
both find-name-dired
and find-grep-dired. The former relies on the
Unix find command to match filenames using glob
patterns. The latter uses both find
and grep to list files that contain a line with a
matching regular expression pattern. However this command lists
files with names that match a regular expression pattern (not
glob pattern). Further this command is implemented purely in
Elisp and does not have any external dependencies on tools
like find and grep.
The following complete key sequences demonstrate how we can invoke shell commands from Emacs.
M-! uname RET: Execute shell command and show output.
C-u M-! uname RET: Like above but insert the output
into the buffer wherever the cursor is. The cursor remains at the
same place. The mark is set to the character just after the last
character of the output. Therefore, typing C-x C-x
(exchange-point-and-mark) is a quick way to highlight
the output just inserted as an active region.
M-! ping SPC -c SPC 4 SPC localhost RET: Execute a
slightly long running shell command that takes about 4 seconds to
complete. Emacs blocks while the command is running because the
command is executed synchronously.
C-u M-! ping SPC -c SPC 4 SPC localhost RET: Like
before but the output is inserted into the buffer. Again, Emacs
blocks while the command is executed. The output appears in the
buffer only after the command completes execution.
M-& ping SPC -c SPC 4 SPC localhost RET:
Like M-! but execute shell command asynchronously.
Emacs remains unblocked and the output appears in the output
buffer as soon as the output is printed by the command.
M-| wc RET: Pipe region to shell command and show
output.
C-u M-| wc RET: Pipe region to shell command and
replace the region with the output.
The book also mentions that C-u M-& is supposed to
work like C-u M-! but asynchronously but I did not find
this to be true. For example, C-u M-& uname RET
led to the following error Wrong type argument: stringp,
(4). This may be a bug in Emacs 28.2.
The following complete key sequences demonstrate this feature:
M-x compile RET: Runs make -f by
default. The default command is offered as a minibuffer input
before we type RET. Therefore we can edit the
command to any arbitrary command before typing RET.
M-x recompile RET: Runs the last compile command
again.
C-x p c: Compile in the current project. See
section Project Management for
more details.
The compile commands display the output in
the *compilation* buffer where the following key
sequences work:
M-g M-n: Jump to the next error. The cursor jumps to
the next error line in the *compilation* and the
source of the matching error line is opened in a separated window.
M-g M-p: Jump to the previous error.
g: Recompile, i.e. run the last compile command
again.
The key sequence M-x shell RET starts a shell with
input/output done via a buffer. Some important points to keep in
mind while using this:
TAB invokes
Emacs's own completion mechanism.
top and man that need to
control the terminal do not work. Only programs that perform
input/output via standard input, standard output and standard
error, etc. work well.
RET to execute whatever is on that line as a
shell command. Shell prompt on the line is automatically excluded
from the command to be executed.
Here are some key bindings that work in the shell buffer:
M-p: Cycle backwards through input history.
M-n: Cycle forwards through input history.
C-<up>: Same as M-p. May not work
if the desktop environment gobbles up this keystroke.
C-<down>: Same as M-n. May not
work if the desktop environment gobbles up this keystroke.
M-r f..: Search history backwards for all commands
that match the pattern f... Within the search, we
can use incremental search key bindings
like C-r, C-s, etc. to search backward,
forward, etc. respectively.
C-c C-p: Move to the previous prompt. The cursor
moves to the place just after the prompt.
C-c C-n: Move to the next prompt.
C-c C-s out.txt RET: Write output since the last
input to a file. Any prompt at the end of the output is not
written. Note that by default the output on shell contains the
input command as well. The input command is echoed back, so our
input command appears twice in the buffer: once where we typed it
and once more echoed just before the beginning of the output.
This echoed input command is also saved to the file.
C-c C-o: Delete all output since the last input. Any
prompt is of course left intact.
C-u C-c C-o: Delete all output since the last input
and save it to the kill ring.
C-c C-l: Show the list of recent inputs in
the *Input History* buffer.
C-d: If the cursor is at the end of the buffer and
there is no input, send EOF. Otherwise delete a character forward.
C-c C-z: Suspend the current job. This performs the
same function as C-z in the underlying shell. We can
then use job control commands like bg
or fg to resume the job as a background process or
foreground process.
TAB: Perform completion at point.
The key sequence M-x ansi-term RET RET launches an
ANSI-capable terminal emulator. It can run sophisticated programs
like top, man, etc. that require terminal
capabilities fine. The following key sequences are useful in this
terminal emulator:
C-c C-j: Switch to line ("cooked") sub-mode. Emacs
editing key sequences work normally in this mode,
except RET which sends the current line as a command
to the underlying shell.
C-c C-k: Switch to char ("raw") sub-mode. By
default, the terminal starts in this mode. Each character we type
in this sub-mode is sent directly to the shell, except for the
escape character C-c which is used as the prefix keys
for the key sequences described in this list.
C-c C-c: Interrupt the current subjob.
The key sequence M-x eshell RET creates an interactive
Eshell buffer if none exists or switches to an existing one. Eshell
is implemented in Elisp. It provides Elisp implementation of Unix
commands like ls, cp, etc.
The list below provides examples of some commands we can enter directly into Eshell:
which ls: The output should show that ls
is an Elisp function.
which which: The output should show
that which itself is an Elisp function.
which top: The output should show the file path of
the external program top.
ls -l: Run Eshell's implementation of ls
written in Elisp.
find-file /etc/hosts: Run the Elisp function
named find-file with the
argument /etc/hosts thus opening the file in a
buffer.
/bin/ls -l: Run the external command ls
available provided by the operating system utilities.
python3 --version: Run the external
program python3.
top: Start the program top in a separate
buffer with term-mode as the major mode.
In the last point we see that for programs like top
which need terminal capabilities to show output in a visual fashion
(as opposed to just printing output to standard output or standard
error), Eshell automatically runs the program in
a term-mode buffer, so that the output of the visual
program can be handled and displayed correctly. Eshell looks at the
list in the variable eshell-visual-commands to
determine if a command needs terminal support or not. By default,
commands like vi, screen,
tmux, top, etc. belong to this list.