Intermediate Emacs
==================
Now that you've had a little introduction to Emacs and some of its
keystrokes, you may be able to appreciate this comic.
.. image:: imgs/real_programmers.jpg
:align: center
You haven't gotten much chance to experience the true power of emacs
yet, though.
Unfortunately we won't really be firing up the warp engines; there's
plenty online if you want to delve deeper. Please have a look at this
page:
`A Tour of Emacs `_
You'll notice that we've talked about several of the commands you see there.
But there is MUCH more. Emacs has a built-in programming language which
let's you write functions and programs which you can bind to keystrokes.
Let's look at just a few more features before we leave our introduction to
Emacs.
Customization: The ``.emacs`` Startup File
------------------------------------------
When Emacs starts, it looks for a file in your home directory called
*hidden* file called: ``.emacs``. This file contains commands written
in the Emacs programming language called `*Lisp*
`_ (more
specifically it is *Emacs Lisp* --a variation of *Lisp*).
You can customize Emacs to alter its behavior to your liking. For
example, when Emacs started up before, we clicked on the line that said
``Dismiss this startup screen``
Actually that text was linked to a Lisp function which wrote the following
text in your ``.emacs`` file.
::
'(inhibit-startup-message t)
Open a shell window (if you don't have one open). Type **ls -a** (or better
you *alias* **la**) for a listing of *all files. You should see ``.emacs``
in the list.
Have a look at it with **less**. You should see something like this:
::
;; .emacs
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(diff-switches "-u")
'(inhibit-startup-screen t))
This may look a bit terrifying, but here's a quick example of the kind of
thing you can do.
Try this: Edit your ``.emacs`` file in Emacs (type: **emacs .emacs**),
and add the following line to the bottom
::
(display-time)
Then save the ``.emacs`` config file, the next time you start emacs, you
will see something like this:
.. image:: imgs/emacsDisplayTime.jpg
The time is now displayed in the *mode-line*. Not going to change your life,
but at least you see how the customizations work. Consult the web for more
customization ideas.
|
Find and Replace
----------------
Let's do a simple task which might come up while you are editing. It
might seem stupid, but it will lead us into a more advanced topic.
Open Emacs by typing: **emacs** at the prompt.
|
With no filename (new or existing) give, Emacs start on a buffer called
``*scratch*`` that looks like this:
::
;; This buffer is for notes you don't want to save, and for Lisp evaluation.
;; If you want to create a file, visit that file with C-x C-f,
;; then enter the text in that file's own buffer.
-UUU:----F1 *scratch* All L5 (Lisp Interaction)----10:32AM 0.51--------
For information about GNU Emacs and the GNU system, type C-a.
If you want a clean new file in which to put text, you either need to supply
a *filename* on the command line when you start emacs, or "*visit*" the file
by asking emacs to *open a file* with **C-x C-f**, and giving it a name.
So, let's call this file, ``cat.txt``. Copy the text fragment below into the buffer
::
The brown cat is fat
The fat cat is old
Therefore, the brown cat is old.
Let's substitute "``dog``" for "``cat``" in this file. Easy enough.
Make sure the cursor is at the beginning of the file (on the first
character of the first line). You do this so that everything below
will be subject to the Search/Replace.
Click on " **Edit->Replace->Replace String** in the *Toolbar*.
.. image:: imgs/emacsReplace.jpg
This will make Emacs prompt you in the mini-buffer with the words:
``Query replace: ``.
.. image:: imgs/emacsReplaceModeline.jpg
In the mini-buffer type: **cat** then **RETURN**.
.. image:: imgs/emacsReplaceCat.jpg
(Remember if anything goes wrong--you can always "Abort" with **C-g**
or the Toolbar->Red (X), and then start over).
The mini-buffer responds with: ``Query replace cat with: ``
.. image:: imgs/emacsReplaceCatWith.jpg
Type: **dog** then **RETURN**
.. image:: imgs/emacsReplaceCatWithDog.jpg
Emacs highlights the next instance of ``cat``, and waits for your
input.
.. image:: imgs/emacsReplaceBuffer.jpg
Also the mini-buffer has changed to: ``Query replacing cat with dog:
(? for help)``
.. image:: imgs/emacsReplaceMiniBuffer.jpg
To *accept* this Replacement (i.e. *cat->dog*), just hit the **Spacebar** .
Emacs *replaces* ``cat`` with ``dog``, jumps to the next ``cat``
and waits for your choice on the next occurance of ``cat``:
.. image:: imgs/emacsReplaceCat2Dog.jpg
This time, hit the "**n**" key (for *No*, do not replace this occurance)
instead of *Spacebar*. Emacs will skip that replacement and
jump to the next ``cat``.
Hit the **Spacebar** on this next one.
Emacs says: "``Replaced 2 occurances``", which is what it did.
Now you should have the following text in your emacs buffer:
::
The brown dog is fat
The fat cat is old
Therefore, the brown dog is old.
|
**The Text-mode way**
Let's change these "dogs" back to "cats". But this time we'll do it the Text-mode way.
Put the cursor at the beginning of the file.
You may have noticed when you clicked
*Edit-Replace-Replace String* in the Toolbar, that to the right of the menu item was the
character string: *M-%*. This is the *Text-mode key binding* for the *Query/Replace*
command (``query-replace``).
Type: **M-%** (Yeah: **ESC** followed by "**%**". Understand the XKCD comic better
now?)
This initiates a "Query/Replace" command, just like you did above with your mouse
in the GUI Toolbar.
This time, since you just previously did a *Query/Replace*, Emacs offers the same replacement
strings as the "*Default*".
.. image:: imgs/emacsReplaceDefaultPrev.jpg
If you just hit **RETURN**, you will accept the *Default*: replacing ``cat`` with ``dog`` again.
Since we skipped one ``cat`` (the "fat cat") in the previous execise, there should be one ``cat``
left to transform to a ``dog``.
Go ahead and hit **RETURN**. Emacs will jump to that occurance of ``cat`` and wait for you
to hit **Spacebar** to *accept* the swap.
Now, the text should be all about *dogs*.
|
Let's practice one more time, and change all the *dogs* back to *cats*.
Put the cursor at the beginning of the text.
Type: **M-%**
In the mini-buffer, after "``Query replace (Default: cat - >dog): ``", type **dog**
Then after "``with:``", type **cat**
Emacs jumps to the first instance of "``dog``".
|
This time, let's just do them all at once--we don't want to go through each
instance of "``dog``" and answer with "**Spacebar**" or "**n**".
Simply type **!** (an exclaimation symbol).
Emacs will change all occurances of "``dog``" to "``cat``" throughout the file.
|
Let's summarize Query/Replace:
|
================================= ====================================================
**Query (Search) / Replace** (``query-replace``)
----------------------------------------------------------------------------------------
GUI (menu/mouse) Mode *Edit->Replace->Replace String*
Text Mode type: **M-%**
================================= ====================================================
|
=============== ===========================
*Replacement Choices*
---------------------------------------------
**Spacebar** to accept replacement
**n** to regect the change
**!** to accept all replacements
**?** for help
=============== ===========================
|
Regular Expression Matching
---------------------------
Try this; in Emacs, open a new file ``regexp.txt`` and copy the following text into it.
::
zzz1234
zyx2345
zzz5555
uuu9845
u6638v
v3948w
w8395x
x7730y
y2349z
Let's suppose this is data from some log file, and you need to extract the
numbers from each line.
You *could* do it *by hand*, i.e. move around and use *Backspace* and *Delete*.
Yuk.
You *could* do *six Query/Replace* operations: replacing the characters ``u,v,w,x,y,z``
with empty replacement strings (""), i.e. just hit RETURN when asked for the
Replace string:
::
"u" -> ""
"v" -> ""
...
"y" -> ""
"z" -> ""
That would do it, but it's a lot of different Query/Replace operations. Yuk, again.
----------------------
|
There's a really cool way to do it using *Regular Expressions*: a match *pattern*
rather than an *exact* match, like ``cat``.
What we want to do is to remove all the alphabet characters (a-z) and leave the
numbers (0-9). So we need a pattern that will only match alphabet characters.
|
*Make sure your cursor is at the top of the text window*. Emacs will (for now) only
search *Forward* for matches. So, if you start the Query/Replace with the cursor at the
end of the text, it will not find anything.
You can quickly move the cursor to the beginning of the buffer by typing: **C-HOME** (Ctrl-HOME).
Similarly, **C-END** takes you to the end of the buffer.
|
To invoke a **Query/Replace using a Regular Expression** (``query-replace-regexp``),
we can either use
+ the GUI method: *Edit->Replace-Replace Regexp...*
+ or the Text-mode keyboard sequence: **M-C-%**
Yup: that's **ESC** followed by **Ctrl-%**, including the *SHIFT* key
needed to get the *%*. Unless you're pretty dextrous, just use the GUI way:
.. image:: imgs/emacsQueryRegexpGUI.jpg
:align: center
|
In the *mini-buffer* you see the prompt for the ``regexp``, the *Regular Expression* (and
because I didn't close my Emacs window since the last Query/Replace, you see the
``default: cat -> dog`` from before).
Emacs is now asking for a ``regexp``--a *PATTERN* to use for matching.
Type: **[a-z]+** then **RETURN**
.. image:: imgs/emacsQueryRegexpString.jpg
The *pattern* is ``[a-z]+``. Here's what the parts mean:
+ ``[ ]`` says to match *any* of the character inside the brackets
+ ``a-z`` means any letter between ``a`` and ``z`` (if you wanted ANY letter, including CAPs you would do ``[A-Za-z]``)
+ ``+`` means match *one or more* of "these"
When you hit *RETURN* above, Emacs is now waiting for you to supply the text to
replace the thing matched (zzz, zxy, etc.)
.. image:: imgs/emacsQueryRegexpString2.jpg
If you simply hit **RETURN** again, meaning replace with *nothing* (the empty string), Emacs
highlights *everything* that matches the *regular expression pattern* ``[a-z]+``.
.. image:: imgs/emacsQueryRegexpHighlight.jpg
Hit the **!** key, and *voila!*, all the letter characters are removed and your data is
scrubbed clean.
.. image:: imgs/emacsQueryRegexpClean.jpg
|
Like many topics in this course, this example is just to let you know that *Regular Expression Substitution*
can be very useful. In addition to match a *pattern*, you can also *save* the *match data* and put it in
the substituion string. For example, with one Query/Replace/Regexp command you could make the following
substitution:
::
zzz\ **1**\ abc -> filename\ **1**\ .dat
zyx\ **2**\ cba -> filename\ **2**\ .dat
qxz\ **3**\ bac -> filename\ **3**\ .dat
There are many online resources to learn about *Emacs Regular Expressions*. Try:
+ `http://www.emacswiki.org/emacs/RegularExpression `_
+ `http://www.gnu.org/software/emacs/tour/ `_
|
*Regular Expressions* are used in most advanced programming languages, Python, PERL, Java, Javascript, PHP, etc.
If you continue to develop your scientific programming skills, you will encounter them again.
|
-------------------------------------------
|
In the above discussion, I have tried to always include the *emacs command* for each action. If you look back
at the summaries, you see things like:
================= ==================== ====================
Action Emacs Command Keybinding
----------------- -------------------- --------------------
To open a file ``(find-file)`` **C-x C-f**
To kill a buffer ``(kill-buffer)`` **C-x C-k**
Paste Text ``(yank)`` **C-y**
...hundreds more
================= ==================== ====================
Here's a small sample of some of the Emacs
`commands `_
|
**Emacs: execute-extended-command (M-x)**
If you happen to know the *Emacs command* for an *action*, you can have Emacs initiate
that action by typing **M-x**, then typing the command in the mini-buffer.
|
Let's try it.
If you don't have an open Emacs window running, start Emacs.
Now *visit* a file ("visit" is the Emacs lingo for openning a file in a buffer),
using the usual keyboard way: type **C-x C-f**
Emacs responds with
::
Find file: ~/
in the mini-buffer. You could continue by typing the name of a file to edit, like ``stairway.txt``.
However, we don't need to edit the file. So, *abort* the action by typing **C-g** (or clicking the Red (X)
in the toolbar.
|
Once you see ``Quit``, indicating that the action was aborted, type:
**M-x** (ESC-x)
The mini-buffer shows simply
::
M-x
Emacs is waiting for you to type a command.
Type
**find-file** and hit **RETURN**
Emacs response with:
::
Find file: ~/
the same as it did above, when you typed **C-x C-f**. You've just learned *yet another way* to make
Emacs do things, by using the ``(execute-extended-command)`` command, which is bound to the keystrokes **M-x**.
|
A command I use often is the ``(goto-line)`` command. Suppose you programming and the compiler
says you have a bug in your code at line 972.
You can open the program file in Emacs and type **M-x**. Emacs responds with ``M-x`` in the mini-buffer.
To this you type **goto-line** and **RETURN**.
Emacs responds with: ``Goto line: ``
You type: **972 RETURN**
and Emacs jumps to line 972 in your program file so that you can edit out your syntax error.
|
This would be written in "Emacs lingo" as **M-x goto-line**.
Of course there is a keyboard shortcut way to do this too: **M-g g** (ESC g g), but I find it easier
to remember **M-x goto-line**.
|
Emacs Windows and Buffers
-------------------------
Like most windowed (GUI) applications, you can resize the Emacs window
by dragging the corner to make it bigger. You can also open several
files/buffers in one emacs session. This is useful when you want to
cut and paste across buffers, compare them, or use a host of other
|
**Emacs "modes"**
|
Here's an example of a useful mode, do this:
**M-x calendar**
This should pop up a second buffer in a smaller window at the bottom
of your emacs window. This buffer will be in "Calendar mode" and thus
responds to various keystrokes differently than a normal buffer. For
example, if you click on a date that is not today's, the cursor moves
there. Typing a period "**.**" takes the cursor back to today's date.
Just a very small example of the behavior of Emacs modes.
Now how do you get rid of the calendar?
Well, you know how to kill a buffer: **C-x k**
If your cursor is in the calendar window and you type the above
keystroke **C-x k**, you will delete the calendar buffer. Go ahead and
try it .
You may see another buffer in it's place, like ***messages***
or another emacs' "operating buffers". You can kill that one too with
**C-x k**.
But what about the *Window*?
Even though you killed the buffer the window is still there.
|
**To manipulate windows:**
If your cursor is in the window you want to keep , you type
**C-x 1** (think "*keep this ONE*").
If you want to delete the window your cursor
is in , you type
**C-x 0** (think "*this buffer is a ZERO*").
If you have two windows open, you can jump to the other window, by
typing
**C-x o** (*that's an "oh" for "other"*).
Or you can just click in it, which will take your cursor there as
well. If you have only one window and want to split your screen, type
**C-x 2**.
Note that in each window you can type **C-x C-f** to open a separate
file in each. Of course you can also use the Toolbar. Finally, you can
drag the *mode-line* (the info-bar between buffers) up or down to make
the windows bigger/smaller.
|
Let's practice:
In Emacs, type **C-x 2** to split the screen into two windows.
Drag the mode-line in the middle of the screen to resize the windows.
Type **C-x C-f** to visit a file. Any file will do. In fact, when you
get ``Find File: ``, hit the **TAB** key, *twice*.
This will list all the files in the current directory. You can click
on one with the mouse. Hitting **TAB** again will scroll to the next
page if there are more files than fit on one screen.
|
**Window control summary**:
================================ =======================
Action Keystrokes
-------------------------------- -----------------------
Close this window **C-x 0**
Close *all but* this window **C-x 1**
Split current window into two **C-x 2**
Split window *horizontally* **C-x 3**
Jump to other window **C-x o**
Compare text in two windows **M-x compare-windows**
================================ =======================
|
Dired
-----
One last useful trick. You can open a **directory** in Emacs:
In an shell terminal, type **emacs .** (i.e. open "the current directory").
This will open Emacs with a long listing of your files.
.. image:: imgs/emacsDired.jpg
For more info on dired mode see:
`GNU Emacs Manual/Dired `_
This is ``dired mode`` (*DIR*\ ectory *ED*\ it). There are many handy things
you can do in dired mode.
For example, you can **mark files for deletion** by typing **d** with
the cursor on the line for a each file. After marking a number of files,
typing **x** will "*expunge*" (delete) all marked files. Similarly,
you can mark files to be *moved, copied*, etc. in bulk.
This is handy if you need to do operations on a large number of files.
Sure, you can do this easily by *Ctrl-Clicking* to mark a number of files in the
GUI File Explorer, but if you are logged into a machine on the other side of the world
through a terminal window (i.e. you DON'T have GUI access), this can be a very powerful
way to do things that you take for granted in your desktop environment.
Some Emacs Fun
--------------
People with too much time on their hands have written some pretty
silly Emacs modes.
Open Emacs and try these (remember **C-x k** will kill the buffer):
**M-x tetris** (do you guys know this ancient game?)
**M-x doctor**
Read: `Conway's Game of Life `_. Then do
**M-x life**
|
This has given you a little taste of what Emacs can do.
Homework
========
Homework 4 is `here `_