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 }}

## Exploring Emacs

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.

## Project Management

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

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.

### Xref Setup

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.

### Search Tools for Xref

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`.

### Four Most Common Xref Commands

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.

### Xref and Dired

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`.

## Working with Log Files

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.

## Highlighting

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.

1. 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

2. 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.

3. 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.

4. 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.

5. Now type `M-s h u RET` again to remove the second set of highlights too.

6. 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.

7. Type `M-s h u RET` to remove the previous highlighting.

8. 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.

9. Type `M-s h u RET` to remove the previous highlighting.

10. 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.

11. 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.

12. 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.

## Auto-Revert Mode

The following steps demonstrate how to use the `revert-buffer` command and then how to use `auto-revert-mode`.

1. 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.

2. Now within Emacs, type `C-x C-f /tmp/log.txt RET`.

3. 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.

4. 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.

5. 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.

6. 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`.

7. Run the command in step 1 again and confirm that the content of the buffer in Emacs gets updated automatically.

8. Type `M-x auto-revert-mode RET` to disable automatic update of the buffer.

## Auto Revert Tail Mode

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:

1. Like in the previous section, run the following command:

       : > /tmp/log.txt && while true; do date >> /tmp/log.txt; sleep 1; done

2. 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.

3. 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.

4. Run the command in step 1 again and confirm that the content of the buffer begins to get updated automatically again.

5. 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.

## Browsing Tarballs

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.

1. 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/

2. Confirm that the tarball looks good with these shell commands:

       tar -tf /tmp/foo.tgz
       tar -xOf /tmp/foo.tgz

3. 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.

4. Type `n` and `p` to navigate the Tar buffer down and up respectively.

5. 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.

6. 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.

7. 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.

8. Type `C-x b foo.tgz RET` to go back to the buffer with the tarball entry listing.

9. Finally, type `C-x C-s` to save the tarball to the file system.

10. Now repeat step 2. The updated content of `foo/bar/baz/baz.txt` should now appear in the output.

## Dired: Thumbnail Image Browser

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.

### Preview Buffer Quirks

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.

### Working on Marked Files

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/`.

### Deleting Images

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.

### Tagging and Untagging

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).

### Using Tags

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.

### Display Buffer

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.

## DocView

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.

### DocView Resolution

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

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.

### Default Directory

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 $

### Multi-Hops

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 $

## EWW: Emacs Web Wowser

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"`.

## Invoking External Browser

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.

## Dired

### Dired: Getting Started

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.

### Dired: Navigation

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.

### Dired: Marking and Unmarking

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.

### Dired: Operations

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:

- Mark files with `m` and delete them with `D`.
- Flag files with `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.

### Dired: Copying or Renaming Between Buffers

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.

1. Type `C-x d /usr/ RET`.
2. Type `C-x 2`.
3. Type `C-x d /tmp/ RET`.
4. Type `C-x 2` agian.
5. Type `C-x d /etc/ RET`.
6. Move the cursor on some file in `/etc/` and then type `C` or `R` and we will see that the default directory to copy/move the file to is `/etc/`.
7. Now type `(setq dired-dwim-target t)`.
8. Now type `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.

### Dired: More Keys

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

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.

### Dired: Working Across Directories

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`.

## Shell Commands

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.

## Compiling in Emacs

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.

## Shells in Emacs

### M-x shell

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:

- The TAB-completion mechanism of the underlying shell (e.g. Bash, Zsh, etc.) does not work. In fact, `TAB` invokes Emacs's own completion mechanism.
- Programs like `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.
- Since the shell buffer is made completely of text, all text editing commands of Emacs work seamlessly on the buffer.
- We can take the cursor to absolutely anywhere in the buffer and type `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.

### M-x ansi-term

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.

### M-x eshell

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.