diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8348a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +layout.html +.DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a10494c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "haml"] + path = haml + url = git://github.com/drothlis/haml.git diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b280e7c --- /dev/null +++ b/LICENSE @@ -0,0 +1,12 @@ +Copyright © 2012 David Röthlisberger. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +A copy of the license is available at http://www.gnu.org/copyleft/fdl.html + +The scripts in the bin/ directory, and the makefile in the same directory as +this LICENSE file, are released to the public domain. If you live somewhere +with totally braindead Copyright laws, you can use them (the scripts and the +makefile) under the ISC or CC0 licenses, both of which are as close to the +public domain as possible. diff --git a/README b/README new file mode 100644 index 0000000..a547f26 --- /dev/null +++ b/README @@ -0,0 +1,60 @@ +"How to learn Emacs" +is a guide aimed at computer programmers who want to master the GNU Emacs +text editor. + + +Generating HTML from the source HAML files +========================================== + +The document source is in Haml + Markdown format: Haml for HTML block +structure, and Markdown for paragraphs and formatting. + +Haml uses significant indentation: + + HAML HTML + #about
+ *Hello* there *Hello* there +
+ +See for details. + +I use a custom fork† of Haml that automatically formats plain-text content +through Markdown‡, so the above Haml example actually converts to: + +
+

+ Hello there +

+
+ +† +‡ + +To install all the necessary tools: (on a Unixy system: Linux, OS X, etc.) + +1. Install ruby and rubygems (the ruby package manager) with your system's +package manager (macports or homebrew on OS X, apt-get or yum on some Linux +distributions, etc.). You may already have these installed (try `ruby` and +`gem` at the terminal). On some systems the `rubygems` package is called +`rb-rubygems`. + +2. Use `gem` to install the rdiscount package (a Markdown implementation): +`gem install rdiscount` + +3. Clone this repository: +`git clone git://github.com/drothlis/how-to-learn-emacs.git` + +4. Fetch the haml submodule of this repository: +`cd how-to-learn-emacs` +`git submodule init` +`git submodule update` + +5. Build the HTML from the Haml sources: +`make` + + +Why are the generated HTML files tracked in the git repository? +=============================================================== + +So that I can easily see the effects of changes to the scripts that generate +the HTML. diff --git a/basic_c.haml b/basic_c.haml new file mode 100644 index 0000000..954db0b --- /dev/null +++ b/basic_c.haml @@ -0,0 +1,711 @@ +%h1 Basic Unix/C workflow + +This chapter uses the source code of the GNU Readline library as an example. +You can grab it (by `cd`ing to a directory of your choice and then issuing the +shell command `git clone git://git.savannah.gnu.org/readline.git`[[1]]) or +follow along using your own C or C++ code. + + +%h2#c c-mode + +.do + Start Emacs and open (`C-x C-f`) the file `readline/examples/rl.c`. + +.figure#minibuffer + .window< +   + .modeline< + :preserve + -U:--- *scratch* All L1 (Lisp Interaction)---------------------------------------- + .echoarea< + Find file: \.../readline/examples/rl.c + %p The minibuffer + +If you accidentally invoke `C-x C-f` again, or any other command that is +expecting some kind of input from you, remember you can cancel by making sure +the minibuffer has focus and pressing `C-g`. + +Because this is a C source file, Emacs has automatically activated an editing +mode called "c-mode", which provides some custom keybindings and knowledge of C +indentation rules and syntax highlighting. We will study c-mode in depth [later +on]( customize_c.html). + + +%h2#shell shell + +.do + Run the `shell` command (that is, `M-x shell RET`). + +This creates a new buffer running the shell specified by environment variable +SHELL.[[2]] The buffer is called `*shell*` (the asterisks are part of the name, +so you have to type them when switching to this buffer with `C-x b`). + +.do + `cd` to the `readline` directory and run the following shell commands: + -# + `./configure` + `make` + +The `*shell*` buffer's editing mode is `shell-mode`. You can run almost any +shell command inside shell-mode; the exceptions are anything that requires real +terminal support, like pagers (`less`) and curses-based programs. You lose +bash's readline completion and any custom bash-completion scripts, or the +equivalent in your shell of choice (though Emacs provides its own command +history and tab-completion). For these reasons, I tend to have a real terminal +running (outside of Emacs) for some tasks, as well as a shell in Emacs. (Trying +to do *everything* in Emacs reaches a point of diminishing returns.) + +The big advantage of `shell-mode` is that all output is available for you to +search through, copy, paste, and otherwise act upon, all with the standard +Emacs commands; you don't have to move your hand to the mouse just to select +some text. + +Shell-mode adds a number of keybindings: + +.figure + .titlebar< + \\.../examples/rl.c + .window.default< + :preserve + gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00) + /usr/llvm-gcc-4.2/bin/../libexec/gcc/i686-apple-darwin11/4.2.1/collect2 -dynamic -dylib -dylib_compatibility_version 6 + -dylib_current_version 6.2 -arch x86_64 -dylib_install_name /usr/local/lib/libhistory.6.2.dylib + -dynamic -macosx_version_min 10.3 -undefined dynamic_lookup -weak_referen + ce_mismatches non-weak -undefined dynamic_lookup -o libhistory.6.2.dylib -ldylib1.o -L/us + r/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/x86_64 -L/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/x86_64 + + readline$ +   + .modeline< + :preserve + --:--- *shell* Bot L404 (Shell:run)------------------------------ + .window.default< + :preserve + Shell mode: + Major mode for interacting with an inferior shell. + RET after the end of the process' output sends the text from + the end of process to the end of the current line. + RET before end of process output copies the current line minus the prompt to + the end of the buffer and sends it (C-c RET just copies the current line). + M-x send-invisible reads a line of text without echoing it, and sends it to + the shell. This is useful for entering passwords. Or, add the function + `comint-watch-for-password-prompt' to `comint-output-filter-functions'. + .modeline< + :preserve + -U:%%- *Help* Top L1 (Help View)------------------------------ + .echoarea< + Type C-x 1 to delete the help window, C-M-v to scroll help. + %p The Help window + +.do + Type `C-h m` and read the documentation on shell-mode and its keybindings. + +(For now, don't bother reading the help text about customization—the variables +and hooks shell-mode provides to modify its behavior. After shell-mode comes +documentation for all the active minor modes; you don't need to read that +either.) + +Of particular interest are pressing `RET` or `C-c RET` on a previous input +line; `C-` and `C-` (or `M-p` and `M-n`) to cycle through previous +commands; and `M-x dirs`. + +.do + Figure out how to send signals (e.g. C-c) to the shell. (Hint: search the + help buffer for "interrupt" and "stop".) +.do + Figure out what `C-M-l` (that's the letter ell) and `C-c C-s` do (these are + both useful after running a shell command that produces a lot of + output).[[3]] + + +%h2#eshell eshell + +If you're not particularly wedded to bash or any other shell, instead of +`shell` you might consider using `eshell`, a shell totally implemented in Emacs +lisp. Among other advantages, running eshell on Windows doesn't require Cygwin; +you can enter lisp code or any Emacs command by name directly at the shell +prompt; and you can redirect command output to the Emacs clipboard or to any +open Emacs buffer. + +I don't use eshell myself, but many do. For now it might be simplest to stick +with the shell you know (running inside Emacs). + + +%h2#term ansi-term + +The final option for running a shell under Emacs is `ansi-term`. This is a full +terminal emulator, and it will pass most key presses directly to the program +running in the terminal. This includes `TAB`, so it will be the shell, not +Emacs, performing tab-completion for you. + +`C-x` and `C-c` are still processed by Emacs; for `M-x` you'll have to type +`C-x M-x`. You _can_ switch from "raw" character mode to "line" mode to get +normal Emacs behavior back (e.g. for moving the cursor around so you can copy +some previous output); nothing will be sent to the terminal until you press +return. + +To find out how, you can't use `C-h m` because `C-h` is passed to the shell +(where it probably means backspace). Instead of `C-h` use ``, or invoke +`describe-mode` by name. + + +%h2#shell-command shell-command + +To run a one-off shell command without opening a full shell buffer, use +`shell-command` (`M-!`). + +.do + `M-! date RET` + +`shell-command-on-region` (`M-|`) is similar but sends the current region to +the shell command's standard input. Let's use it to calculate the line count +of `rl.c`'s `main` function: + +.do + Switch to buffer `rl.c` (with `C-x b`). + -# + Move the point to the `main` function (by searching with `C-s`). + + Now move the point so that it is directly on the `main` function's opening + `{` bracket. + + Press `C-SPC` to set the mark. + + Press `C-M-f` to move point forward to the matching `}` bracket. The region + (the area between the mark and the point) now covers the full body of `main`. + + `M-| wc -l RET` + +.window.default< + :preserve +
printf ("%s\n", temp); + exit (0); + }
+ +.modeline< + :preserve + --:--- rl.c Bot L158 Git-master (C/l Abbrev)----------------------------------- +.echoarea< + Shell command on region: wc -l + +If you forget the names of these commands, type `M-x shell TAB TAB`. + +.do + Read the help for `shell-command-on-region`. You can look it up by keybinding + (`C-h k`) or by function name (`C-h f`). + +The help for this one is pretty long, but the important information is near the +top. Ignore the paragraph on coding systems, and everything about +noninteractive arguments (which are for calling this function from lisp +scripts, as opposed to interactively like we have been doing). + +The sentence "Prefix arg means replace the region with [the output of the shell +command]" refers to providing a numeric argument to the command. You'll +remember numeric arguments from the tutorial. In this case the value of the +argument doesn't matter, so `M-2 C-M-|` or `C-u C-M-|` will do. + +.do + Try it! + +.figure + .window< +   + .modeline< + :preserve + --:**- rl.c Bot L158 Git-master (C/l Abbrev)----------------------------------- + .echoarea< + %p Unsaved modifications indicator + +.do + And now undo (`C-/`) what you've done to the buffer. Note the modeline + indicator when the buffer has unsaved modifications. + + +%h2#sh sh-mode + +.do + Open the file `readline/configure`. + +If you are not particularly comfortable with shell scripting, I apologize for +dumping you into a 12,000-line programmatically-generated script, but it's the +closest one I had for an example. + +The mode for editing shell scripts is `sh-mode` (as opposed to `shell-mode` for +running an interactive shell session, which we've seen already). If Emacs +didn't figure out that the file is a shell script (perhaps it's missing the +hash-bang interpreter directive on the first line) you can enter `sh-mode` +with, you guessed it, `M-x sh-mode`. + +I don't really have much to say about `sh-mode`. It will do syntax highlighting +and indentation for a variety of shells; and it provides keybindings to run the +script, and to insert certain shell constructs (`case` statements, `for` loops, +etc.) with the correct syntax for the current shell. If Emacs gets it wrong +(again with the missing hash-bang!) you can tell Emacs which shell to use. + +By now you know where to find out how. + + +%h2#infodoc Info documentation + +.do + Back in the `configure` script, invoke `info-lookup-symbol` and when prompted + enter `test`. + +Assuming that the Info documentation for the `bash` shell is correctly +installed on your system (which should be the case for any Linux or OS X +system, at least) you will see an Info window showing the `bash` manual at +the very line for the `test` command. + +.do + Follow the link to "Bash Conditional Expressions". If you don't want to use + the mouse, `TAB` moves the point to the next link and `RET` does the obvious + thing. + +As usual, `C-h m` will show all the keybindings for `info` mode. For once, +though, don't bother remembering all the keybindings, nor reading through the +rather tedious Info tutorial. All you need to know is: + +* `SPC` and `DEL` for scrolling; when you get to the end of a "node" (a page or +section), pressing `SPC` again goes to the next node in the sequence. I must +warn you, `DEL` is sometimes buggy when you reach the first node in a chapter. +* `l` (the letter ell) moves back in history. +* `u` or `^` moves up to the nearest enclosing table of contents. Pressing `u` +repeatedly will get you to the main Info directory containing all the Info +manuals found on your system. (The Emacs-related manuals are also available [on +the web]( http://www.gnu.org/software/emacs/manual/).) +* Use the usual mechanisms for searching (`C-s` and `C-r`); when you reach the +end of a node, pressing `C-s` again will continue searching through the rest of +the manual. + +As you can see from the Info directory, there are many Info manuals, including +manuals for Emacs itself, an Emacs Lisp reference and intro, and manuals for +the more complex Emacs editing modes like `cc-mode`. + +I can't overstate how useful the Info documentation is. If you're maintaining a +Makefile you can look up the meaning of esoteric symbols like `$@`. Need to do +some socket programming? In a [later chapter](info.html) we will install the +Info manuals for glibc (the GNU implementation of the Unix standard library). + +`info-lookup-symbol` uses the mode of the current buffer to determine which +manual to look in. Sometimes it can't tell, so it will prompt you: Enter +`sh-mode` or `makefile-mode` or `c-mode` or whatever (`TAB` to show all +possible options). With a `C-u` prefix, `info-lookup-symbol` will always ask. + + +%h2#compile compile + +.do + Switch to buffer `rl.c` (with `C-x b`) if necessary. + -# + Move the point to the `main` function (by searching with `C-s`). + + Introduce a deliberate compilation error just after `main`'s opening `{` + bracket, as in the example below, and save your change. + + `M-x compile` (and accept the default shell command of `make -k`). + +.titlebar< + rl.c +.window.default< + :preserve + int + main (argc, argv) + int argc; + char **argv; + { + failhere  + char *temp, *prompt; + struct stat sb; + int opt, fd, nch; + FILE *ifp; +.modeline< + :preserve + --:--- rl.c 59% L84 Git-master (C/l Abbrev)----------------------------------- +.window.default< + :preserve + make -k + rm -f rl.o + gcc -DHAVE_CONFIG_H -DREADLINE_LIBRARY -DRL_LIBRARY_VERSION='"6.2"' -I. -I.. -I.. -g -O -c rl.c + rl.c: In function ‘main’: + rl.c:84: error: ‘failhere’ undeclared (first use in this function) + rl.c:84: error: (Each undeclared identifier is reported only once + rl.c:84: error: for each function it appears in.) + rl.c:85: error: expected ‘;’ before ‘char’ + rl.c:97: error: ‘prompt’ undeclared (first use in this function) + rl.c:150: error: ‘temp’ undeclared (first use in this function) +.modeline< + :preserve + -U:%*- *compilation* Top L1 (Compilation:exit [2])----------------------------------- +.echoarea< + Compilation exited abnormally with code 2 + +.do + With the active cursor still in the `rl.c` window, type `C-x 0` (zero) to + maximize the `*compilation*` window. + +(`C-x 1`, which you learned in the tutorial, hides all windows except the +currently selected one; `C-x 0` does the opposite.) + +.do + While you're at it, try out `C-x 2` and `C-x 3`. `C-x o` (the letter oh) + cycles between windows. + +Anyway, back to the `*compilation*` window. Compilation-mode has its own +special keybindings, of course: + +.do + Get help on compilation-mode and its keybindings (`C-h m`). Good news: the + help for this mode is quite short. Again, don't bother reading the help for + all the active minor modes, unless you want to. + +.do + Try out the keybindings for `compilation-next-error` and + `compilation-previous-error`. If `next-error-follow-minor-mode` sounded + intriguing, try that out too. + +The compilation command is run from the buffer's associated directory; normally +this is the directory containing the buffer's file. To run `make` on a +different Makefile, you could specify the `-C` (`--directory`) or `-f` +(`--makefile`) `make` options; or you can change the buffer's default directory +with `M-x cd` before `M-x compile`. + + +%h2#rgrep rgrep + +To search for all occurrences of a string (or regular expression) in a project, +use `rgrep`.[[4]] This puts the matches in a new buffer, which you can navigate +just like the compilation buffer (in fact, grep-mode inherits its functionality +and keybindings from compilation-mode). + +.do + Use `rgrep` to search the `readline` source (`*.[ch]` files) for + "rl_insert_comment" (make sure you search in the `readline` directory, not in + `readline/examples`). + +You can control the exact grep command line used: Read the documentation for +`rgrep` to find out how, or use `grep` or `grep-find` instead. The `C-h f` +documentation is an adequate reference, but the Info manual (`C-h S rgrep`) +provides a better introduction. + + +%h2#vc vc + +Emacs has a set of commands, all starting with "`vc-`", that provide a +consistent interface to various version control systems. The `readline` files +we are using in this tutorial are in a git repository, but the basic commands +are the same for subversion or cvs. More advanced commands (such as altering +repository settings, or pushing and pulling to remote repositories in git and +other distributed vc systems) you will still have to do outside of Emacs. + +.do + Switch to buffer `rl.c` (with `C-x b`) if necessary. + +(If you find yourself missing clickable tabs for switching between buffers, +remember that `C-x b` is more scalable—it works better when you have hundreds +of buffers open. [Later on](customize_general.html#ido) we will see how to save +a lot of typing under `C-x b`.) + +.do + `rl.c` probably has changes from when we were messing with it earlier. Invoke + `vc-revert` to, well, revert it to the latest version in the repository. + +Now for argument's sake, let's say we find `rl.c`'s documentation for the "-u" +command-line flag somewhat confusing: + +.do + Find (with `C-s`) both instances of the documentation for "-u" and replace + the word "unit" with "fd". Save your changes. + +.figure + .titlebar< + \\*vc-diff* + .window< + :preserve + diff --git a/examples/rl.c b/examples/rl.c + index 845a4b1..7bfb932 100644 + --- a/examples/rl.c + +++ b/examples/rl.c + @@ -2,7 +2,7 @@ + * rl - command-line interface to read a line from the standard input + * (or another fd) using readline. + * + - * usage: rl [-p prompt] [-u unit] [-d default] [-n nchars] + + * usage: rl [-p prompt] [-u fd] [-d default] [-n nchars] + */ + + /* Copyright (C) 1987-2009 Free Software Foundation, Inc. + @@ -72,7 +72,7 @@ set_deftext () + static void + usage() + { + .modeline< + :preserve + --:%*- *vc-diff* Top L1 (Diff from rl.c)----------------------------------- + .echoarea< + You can run the command \`vc-diff' with C-x v = + +.do + Ask Emacs to show you a diff of this file. (If you need a hint, it's in the + first sentence of this section.) + +The diff will be shown in diff-mode, which is also used for viewing patch +files. diff-mode has some useful tricks—read its documentation when you have a +spare minute. + +All the vc commands are bound to key sequences starting with `C-x v`. If you +were paying attention when you invoked the diff command by its full name, you +may have noticed that Emacs told you the corresponding keybinding. + +.do + Press `C-x v C-h` to see all keybindings starting with `C-x v`. + -# + This also works with any other prefix. Try it with `C-x 4`—you might notice + some parallels with keybindings you already know. + +To commit the file, look into `C-x v v` (`vc-next-action`). Or enter +`vc-dir-mode` with `C-x v d` and find out how to mark files, for performing +`vc-` actions on multiple files at once. + +`vc` has a (long!) [section in the Emacs manual]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Version-Control.html). + +Personally, I prefer to use the `gitk` and `git gui` tools, or git's +command-line interface directly, for adding, staging, committing, reverting, +merging, branching. But I *do* use the Emacs `vc-diff` and `vc-print-log` (and +`vc-annotate`!) extensively. + +Because `vc` is limited to the common denominator of the backend systems it +supports, people have written custom modes for specific version control +systems. `Magit` is one such mode for git; but as we haven't yet learned how to +install extensions, we'll stick with `vc`. Anyway, `vc` can do a thing or two +even `magit` doesn't do—have I mentioned `vc-annotate`? + + +%h2#annotate vc-annotate + +A couple of sections ago, I asked you to grep the readline sources for +"rl_insert_comment". + +.do + Switch to the `*grep*` buffer if you still have it around, or do a new + search. + +Remember, when switching buffers with `C-x b` you have to enter the asterisks +as part of the buffer name. (Incidentally, the asterisks are for buffers not +associated with a file on disk. This is just a convention; you could always +rename the `*grep*` buffer to something without asterisks —see +`rename-buffer`— or save it to disk if you wanted to.) + +.do + The first hit should have been in `emacs_keymap.c`. Jump to that match. + +Let's find out which release of readline added the Meta-# keybinding: + +.do + .figure.wide + .titlebar< + \\*Annotate emacs_keymap.c (rev master)* + .window< + :preserve + ^06cd36c emacs_keymap.c /* The start of printing characters. */ + f8d82ba2 emacs_keymap.c { ISFUNC, rl_set_mark }, /* Meta-SPACE */ + f8d82ba2 emacs_keymap.c { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-! */ + f8d82ba2 emacs_keymap.c { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-" */ + f8d82ba2 emacs_keymap.c { ISFUNC, rl_insert_comment }, /* Meta-# */ + + + `M-x vc-annotate` + -# + Delete all Emacs windows other than the annotate window (you might also want + to resize the frame so that it is large enough). + + With point on the "Meta-#" line, press `d` to view the diff of the revision + where this line was last changed. + + Now we're in diff-mode. It seems that this revision consisted mostly of + whitespace changes. Find the exact change to "Meta-#". You can press `C-c + C-w` to hide whitespace-only changes in the hunk surrounding point, and `n` + to jump to the next hunk. + + Nope, this revision wasn't it. Press `q` to exit the diff buffer, then `a` to + run annotate again, starting from the revision before this line's revision. + + .figure.wide + .titlebar< + \\*vc-diff* + .window< + :preserve + { ISFUNC, (Function *)0x0 }, /* Meta-! */ + { ISFUNC, (Function *)0x0 }, /* Meta-" */ + - { ISFUNC, (Function *)0x0 }, /* Meta-# */ + + { ISFUNC, rl_insert_comment },/* Meta-# */ + { ISFUNC, (Function *)0x0 }, /* Meta-$ */ + { ISFUNC, (Function *)0x0 }, /* Meta-% */ + + Now make sure your point is on the right line (if the new revision is + different enough from the newer one, the line we're interested in may have + moved around). Then press `d` again, and in diff-mode `n` until you find the + right hunk. Yes, this is the change we're looking for! + + Go back to the annotate buffer (`q`). Press `l` to view the log message for + this revision. See, readline's "Meta-#" binding dates back to version 2.1! If + you want some context you can press `D` (that's *shift*-d) to view the diff + of *all* files changed in this revision. + +Of course, annotate is more useful when the commits are more granular and the +commit messages are more descriptive, with links to bug tracker entries and so +on. But you get the idea. + +Right now I don't expect you to remember all these keybindings, but I do expect +you to know how to find them when you need them. + + +%h2#ediff ediff + +`ediff` is a more powerful mode for viewing differences between files or +revisions. + +.do + Switch to buffer rl.c if necessary. + -# + `M-x ediff-revision`. Accept the default values of rl.c, its latest revision, + and its current state. + +This opens a new frame from which you control `ediff`; always make sure the +`ediff` frame has focus when you're giving it a command. + +.do + Press `?` for help. Figure out how to step through each diff. Figure out how + to show the files side-by-side. `q` when you're done. + +When invoking `ediff-revision` you can supply any two revisions, not just the +latest revision and the current working copy. You can also diff any 2 buffers +(`ediff-buffers`) or files (`ediff-files`). + +I suggest you stay away from `ediff-directories` (if you want to know why, try +using it). + + +%h2#etags etags + +`etags` is a program that indexes source files and creates a `TAGS` file that +Emacs can use to find definitions of variables, functions and types. + +.do + Run the shell command `make TAGS` in the `readline` directory (either from a + `shell` buffer, or with `M-x compile`). + +The Makefiles of most open-source projects include the `TAGS` target. For those +that don't, you can use a combination of `find`, `xargs` and `etags` from the +shell to generate the `TAGS` file manually (read the man pages for those tools +if you need to). + +The `etags` you just ran was probably the one that shipped with Emacs. There's +an alternate implementation called ["Exuberant ctags"]( +http://ctags.sourceforge.net/) that supports more languages. Install it with +your package manager (e.g. `port` or `yum install ctags`) and call it with +`ctags -e`. + +.do + Back in Emacs, invoke `find-tag` (`M-.`). Enter `rl_insert_comment` as the + tag to find, and then the location of the `TAGS` file you just generated. + +.do + From the help for `find-tag`, figure out how to jump back to the location you + were at before invoking the command, and how to find the next match if there + is more than one. (You might find the documentation from `C-h S find-tag` + clearer than that from `C-h f`.) + +To use a different `TAGS` file `visit-tags-table`. + +If you're a C++ programmer, you'll soon find that `ctags`/`etags` is not +perfect when it comes to classes and namespaces. As a 90% solution, it's good +enough, most of the time. Hopefully someone will come up with a [clang]( +http://clang.llvm.org/)-based indexer sometime soon. + + +%h2#gdb gdb + +We're going to run the `rl` program under the GNU debugger, gdb. + +.do + First run `compile` in `readline` and then in `readline/examples`. + +The compilation should succeed,[[5]] as long as you haven't introduced any errors +in any of the source files. If you have, you know how to view and back out your +changes. + +.do + `M-x gdb`. When prompted for the command-line to use, specify the program + `examples/rl` as an argument to `gdb`: if you're in the `readline/examples` + directory, the command-line will look like `gdb ‑‑annotate=3 ./rl`. + +You are now running `gdb` inside Emacs, so the standard `gdb` commands apply. +Let's set a breakpoint in the `readline` function, start the `rl` program, and +when we reach the breakpoint step through a few lines. + +.do + Type the following commands at the `gdb` prompt: + -# + `break readline` + `run` + `print rl_pending_input` + `next` + `step` + `backtrace` + `frame 1` + +Note how Emacs displays the corresponding source file and line in a separate +window. + +The above commands are all interpreted directly by the `gdb` program. `gdb` +allows you to abbreviate them to `r`, `p`, `n`, `s`, `bt`, and `f`, +respectively. Pressing return on an empty line repeats the previous +command—useful for multiple `next` commands. `help` displays `gdb`'s built-in +help. + +For serious debugging, Emacs can open additional windows showing the current +stack frames, breakpoints, local variables and registers. See the Emacs manual +for details: `C-h r` opens the Emacs manual in the Info browser, then search +for the chapter titled "GDB Graphical Interface". + + +%h2#homework Homework + +You may be feeling somewhat overwhelmed at this point. Spend a few days using +Emacs as your main editor, painful though it may be, before moving on to the +next chapter of this guide. If you've forgotten a command I've taught you, try +to figure it out yourself (use `C-h m`, `C-h a`, `C-h f`, `C-h k` and `C-h S`) +before looking it up here. + +As part of your commitment to learning Emacs, try to run your shell within +Emacs as much as possible. (If you need help configuring your shell to work +well within Emacs, or configuring Emacs to work well with your shell, we will +revisit shell-mode in the ["General customization" chapter]( +customize_general.html#shell) of this guide.) + + +#footnotes + [[1]]: + You will need `git`, a source control system; the Git Book has [installation + instructions]( http://book.git-scm.com/2_installing_git.html). + + [[2]]: + On Windows you will need a shell provided by Cygwin or similar. + + [[3]]: + These keybindings aren't arbitrary. `C-c C-s` mirrors `C-x C-s`, which you + already know for saving the entire buffer to a file ("global" keybindings + tend to start with `C-x`, whereas `C-c` is a prefix for mode-specific + bindings). And `C-M-l` performs a similar function in other editing modes—in + c-mode it tries to bring into view the whole function surrounding the point. + If you're feeling overwhelmed by the number of keybindings to memorize, don't + worry; you can always find them again with `C-h m`. + + [[4]]: + On Windows you will need `find` and `grep` commands provided by Cygwin or + similar. + + [[5]]: + I haven't tested this on Windows, but I'm assuming that Cygwin installs the + necessary compiler, headers and libraries. diff --git a/basic_c.html b/basic_c.html new file mode 100644 index 0000000..5242f0a --- /dev/null +++ b/basic_c.html @@ -0,0 +1,606 @@ + + + + + + How to learn Emacs :: Basic Unix/C workflow + + + + + +
+ +

Basic Unix/C workflow

+

This chapter uses the source code of the GNU Readline library as an example. +You can grab it (by cding to a directory of your choice and then issuing the +shell command git clone git://git.savannah.gnu.org/readline.git[1]) or +follow along using your own C or C++ code.

+

c-mode

+ +
+

Start Emacs and open (C-x C-f) the file readline/examples/rl.c.

+
+
+

 

+
-U:--- *scratch* All L1 (Lisp Interaction)----------------------------------------
+

Find file: .../readline/examples/rl.c

+

The minibuffer

+ +
+

If you accidentally invoke C-x C-f again, or any other command that is +expecting some kind of input from you, remember you can cancel by making sure +the minibuffer has focus and pressing C-g.

+ +

Because this is a C source file, Emacs has automatically activated an editing +mode called “c-mode”, which provides some custom keybindings and knowledge of C +indentation rules and syntax highlighting. We will study c-mode in depth later +on.

+

shell

+ +
+

Run the shell command (that is, M-x shell RET).

+
+

This creates a new buffer running the shell specified by environment variable +SHELL.[2] The buffer is called *shell* (the asterisks are part of the name, +so you have to type them when switching to this buffer with C-x b).

+
+

cd to the readline directory and run the following shell commands:

+

./configure
+ make

+
+

The *shell* buffer’s editing mode is shell-mode. You can run almost any +shell command inside shell-mode; the exceptions are anything that requires real +terminal support, like pagers (less) and curses-based programs. You lose +bash’s readline completion and any custom bash-completion scripts, or the +equivalent in your shell of choice (though Emacs provides its own command +history and tab-completion). For these reasons, I tend to have a real terminal +running (outside of Emacs) for some tasks, as well as a shell in Emacs. (Trying +to do everything in Emacs reaches a point of diminishing returns.)

+ +

The big advantage of shell-mode is that all output is available for you to +search through, copy, paste, and otherwise act upon, all with the standard +Emacs commands; you don’t have to move your hand to the mouse just to select +some text.

+ +

Shell-mode adds a number of keybindings:

+
+

.../examples/rl.c

+
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00) /usr/llvm-gcc-4.2/bin/../libexec/gcc/i686-apple-darwin11/4.2.1/collect2 -dynamic -dylib -dylib_compatibility_version 6 -dylib_current_version 6.2 -arch x86_64 -dylib_install_name /usr/local/lib/libhistory.6.2.dylib -dynamic -macosx_version_min 10.3 -undefined dynamic_lookup -weak_referen ce_mismatches non-weak -undefined dynamic_lookup -o libhistory.6.2.dylib -ldylib1.o -L/us r/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/x86_64 -L/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/x86_64 readline$  
+
--:--- *shell* Bot L404 (Shell:run)------------------------------
+
Shell mode: Major mode for interacting with an inferior shell. RET after the end of the process' output sends the text from the end of process to the end of the current line. RET before end of process output copies the current line minus the prompt to the end of the buffer and sends it (C-c RET just copies the current line). M-x send-invisible reads a line of text without echoing it, and sends it to the shell. This is useful for entering passwords. Or, add the function `comint-watch-for-password-prompt' to `comint-output-filter-functions'.
+
-U:%%- *Help* Top L1 (Help View)------------------------------
+

Type C-x 1 to delete the help window, C-M-v to scroll help.

+

The Help window

+ +
+
+

Type C-h m and read the documentation on shell-mode and its keybindings.

+
+

(For now, don’t bother reading the help text about customization—the variables +and hooks shell-mode provides to modify its behavior. After shell-mode comes +documentation for all the active minor modes; you don’t need to read that +either.)

+ +

Of particular interest are pressing RET or C-c RET on a previous input +line; C-<up> and C-<down> (or M-p and M-n) to cycle through previous +commands; and M-x dirs.

+
+

Figure out how to send signals (e.g. C-c) to the shell. (Hint: search the + help buffer for “interrupt” and “stop”.)

+
+
+

Figure out what C-M-l (that’s the letter ell) and C-c C-s do (these are + both useful after running a shell command that produces a lot of + output).[3]

+
+

eshell

+

If you’re not particularly wedded to bash or any other shell, instead of +shell you might consider using eshell, a shell totally implemented in Emacs +lisp. Among other advantages, running eshell on Windows doesn’t require Cygwin; +you can enter lisp code or any Emacs command by name directly at the shell +prompt; and you can redirect command output to the Emacs clipboard or to any +open Emacs buffer.

+ +

I don’t use eshell myself, but many do. For now it might be simplest to stick +with the shell you know (running inside Emacs).

+

ansi-term

+

The final option for running a shell under Emacs is ansi-term. This is a full +terminal emulator, and it will pass most key presses directly to the program +running in the terminal. This includes TAB, so it will be the shell, not +Emacs, performing tab-completion for you.

+ +

C-x and C-c are still processed by Emacs; for M-x you’ll have to type +C-x M-x. You can switch from “raw” character mode to “line” mode to get +normal Emacs behavior back (e.g. for moving the cursor around so you can copy +some previous output); nothing will be sent to the terminal until you press +return.

+ +

To find out how, you can’t use C-h m because C-h is passed to the shell +(where it probably means backspace). Instead of C-h use <f1>, or invoke +describe-mode by name.

+

shell-command

+

To run a one-off shell command without opening a full shell buffer, use +shell-command (M-!).

+
+

M-! date RET

+
+

shell-command-on-region (M-|) is similar but sends the current region to +the shell command’s standard input. Let’s use it to calculate the line count +of rl.c’s main function:

+
+

Switch to buffer rl.c (with C-x b).

+

Move the point to the main function (by searching with C-s). + Now move the point so that it is directly on the main function’s opening + { bracket.

+ +

Press C-SPC to set the mark.

+ +

Press C-M-f to move point forward to the matching } bracket. The region + (the area between the mark and the point) now covers the full body of main.

+ +

M-| wc -l RET

+
+
printf ("%s\n", temp); exit (0); }
+
--:--- rl.c Bot L158 Git-master (C/l Abbrev)-----------------------------------
+

Shell command on region: wc -l

+

If you forget the names of these commands, type M-x shell TAB TAB.

+
+

Read the help for shell-command-on-region. You can look it up by keybinding + (C-h k) or by function name (C-h f).

+
+

The help for this one is pretty long, but the important information is near the +top. Ignore the paragraph on coding systems, and everything about +noninteractive arguments (which are for calling this function from lisp +scripts, as opposed to interactively like we have been doing).

+ +

The sentence “Prefix arg means replace the region with [the output of the shell +command]” refers to providing a numeric argument to the command. You’ll +remember numeric arguments from the tutorial. In this case the value of the +argument doesn’t matter, so M-2 C-M-| or C-u C-M-| will do.

+
+

Try it!

+
+
+

 

+
--:**- rl.c Bot L158 Git-master (C/l Abbrev)-----------------------------------
+
+

Unsaved modifications indicator

+
+
+

And now undo (C-/) what you’ve done to the buffer. Note the modeline + indicator when the buffer has unsaved modifications.

+
+

sh-mode

+ +
+

Open the file readline/configure.

+
+

If you are not particularly comfortable with shell scripting, I apologize for +dumping you into a 12,000-line programmatically-generated script, but it’s the +closest one I had for an example.

+ +

The mode for editing shell scripts is sh-mode (as opposed to shell-mode for +running an interactive shell session, which we’ve seen already). If Emacs +didn’t figure out that the file is a shell script (perhaps it’s missing the +hash-bang interpreter directive on the first line) you can enter sh-mode +with, you guessed it, M-x sh-mode.

+ +

I don’t really have much to say about sh-mode. It will do syntax highlighting +and indentation for a variety of shells; and it provides keybindings to run the +script, and to insert certain shell constructs (case statements, for loops, +etc.) with the correct syntax for the current shell. If Emacs gets it wrong +(again with the missing hash-bang!) you can tell Emacs which shell to use.

+ +

By now you know where to find out how.

+

Info documentation

+ +
+

Back in the configure script, invoke info-lookup-symbol and when prompted + enter test.

+
+

Assuming that the Info documentation for the bash shell is correctly +installed on your system (which should be the case for any Linux or OS X +system, at least) you will see an Info window showing the bash manual at +the very line for the test command.

+
+

Follow the link to “Bash Conditional Expressions”. If you don’t want to use + the mouse, TAB moves the point to the next link and RET does the obvious + thing.

+
+

As usual, C-h m will show all the keybindings for info mode. For once, +though, don’t bother remembering all the keybindings, nor reading through the +rather tedious Info tutorial. All you need to know is:

+ +
    +
  • SPC and DEL for scrolling; when you get to the end of a “node” (a page or +section), pressing SPC again goes to the next node in the sequence. I must +warn you, DEL is sometimes buggy when you reach the first node in a chapter.
  • +
  • l (the letter ell) moves back in history.
  • +
  • u or ^ moves up to the nearest enclosing table of contents. Pressing u +repeatedly will get you to the main Info directory containing all the Info +manuals found on your system. (The Emacs-related manuals are also available on +the web.)
  • +
  • Use the usual mechanisms for searching (C-s and C-r); when you reach the +end of a node, pressing C-s again will continue searching through the rest of +the manual.
  • +
+ + +

As you can see from the Info directory, there are many Info manuals, including +manuals for Emacs itself, an Emacs Lisp reference and intro, and manuals for +the more complex Emacs editing modes like cc-mode.

+ +

I can’t overstate how useful the Info documentation is. If you’re maintaining a +Makefile you can look up the meaning of esoteric symbols like $@. Need to do +some socket programming? In a later chapter we will install the +Info manuals for glibc (the GNU implementation of the Unix standard library).

+ +

info-lookup-symbol uses the mode of the current buffer to determine which +manual to look in. Sometimes it can’t tell, so it will prompt you: Enter +sh-mode or makefile-mode or c-mode or whatever (TAB to show all +possible options). With a C-u prefix, info-lookup-symbol will always ask.

+

compile

+ +
+

Switch to buffer rl.c (with C-x b) if necessary.

+

Move the point to the main function (by searching with C-s). + Introduce a deliberate compilation error just after main’s opening { + bracket, as in the example below, and save your change.

+ +

M-x compile (and accept the default shell command of make -k).

+
+

rl.c

+
int main (argc, argv) int argc; char **argv; { failhere  char *temp, *prompt; struct stat sb; int opt, fd, nch; FILE *ifp;
+
--:--- rl.c 59% L84 Git-master (C/l Abbrev)-----------------------------------
+
make -k rm -f rl.o gcc -DHAVE_CONFIG_H -DREADLINE_LIBRARY -DRL_LIBRARY_VERSION='"6.2"' -I. -I.. -I.. -g -O -c rl.c rl.c: In function ‘main’: rl.c:84: error: ‘failhere’ undeclared (first use in this function) rl.c:84: error: (Each undeclared identifier is reported only once rl.c:84: error: for each function it appears in.) rl.c:85: error: expected ‘;’ before ‘char’ rl.c:97: error: ‘prompt’ undeclared (first use in this function) rl.c:150: error: ‘temp’ undeclared (first use in this function)
+
-U:%*- *compilation* Top L1 (Compilation:exit [2])-----------------------------------
+

Compilation exited abnormally with code 2

+
+

With the active cursor still in the rl.c window, type C-x 0 (zero) to + maximize the *compilation* window.

+
+

(C-x 1, which you learned in the tutorial, hides all windows except the +currently selected one; C-x 0 does the opposite.)

+
+

While you’re at it, try out C-x 2 and C-x 3. C-x o (the letter oh) + cycles between windows.

+
+

Anyway, back to the *compilation* window. Compilation-mode has its own +special keybindings, of course:

+
+

Get help on compilation-mode and its keybindings (C-h m). Good news: the + help for this mode is quite short. Again, don’t bother reading the help for + all the active minor modes, unless you want to.

+
+
+

Try out the keybindings for compilation-next-error and + compilation-previous-error. If next-error-follow-minor-mode sounded + intriguing, try that out too.

+
+

The compilation command is run from the buffer’s associated directory; normally +this is the directory containing the buffer’s file. To run make on a +different Makefile, you could specify the -C (--directory) or -f +(--makefile) make options; or you can change the buffer’s default directory +with M-x cd before M-x compile.

+

rgrep

+

To search for all occurrences of a string (or regular expression) in a project, +use rgrep.[4] This puts the matches in a new buffer, which you can navigate +just like the compilation buffer (in fact, grep-mode inherits its functionality +and keybindings from compilation-mode).

+
+

Use rgrep to search the readline source (*.[ch] files) for + “rl_insert_comment” (make sure you search in the readline directory, not in + readline/examples).

+
+

You can control the exact grep command line used: Read the documentation for +rgrep to find out how, or use grep or grep-find instead. The C-h f +documentation is an adequate reference, but the Info manual (C-h S rgrep) +provides a better introduction.

+

vc

+

Emacs has a set of commands, all starting with “vc-”, that provide a +consistent interface to various version control systems. The readline files +we are using in this tutorial are in a git repository, but the basic commands +are the same for subversion or cvs. More advanced commands (such as altering +repository settings, or pushing and pulling to remote repositories in git and +other distributed vc systems) you will still have to do outside of Emacs.

+
+

Switch to buffer rl.c (with C-x b) if necessary.

+
+

(If you find yourself missing clickable tabs for switching between buffers, +remember that C-x b is more scalable—it works better when you have hundreds +of buffers open. Later on we will see how to save +a lot of typing under C-x b.)

+
+

rl.c probably has changes from when we were messing with it earlier. Invoke + vc-revert to, well, revert it to the latest version in the repository.

+
+

Now for argument’s sake, let’s say we find rl.c’s documentation for the “-u” +command-line flag somewhat confusing:

+
+

Find (with C-s) both instances of the documentation for “-u” and replace + the word “unit” with “fd”. Save your changes.

+
+
+

*vc-diff*

+
diff --git a/examples/rl.c b/examples/rl.c index 845a4b1..7bfb932 100644 --- a/examples/rl.c +++ b/examples/rl.c @@ -2,7 +2,7 @@ * rl - command-line interface to read a line from the standard input * (or another fd) using readline. * - * usage: rl [-p prompt] [-u unit] [-d default] [-n nchars] + * usage: rl [-p prompt] [-u fd] [-d default] [-n nchars] */ /* Copyright (C) 1987-2009 Free Software Foundation, Inc. @@ -72,7 +72,7 @@ set_deftext () static void usage() {
+
--:%*- *vc-diff* Top L1 (Diff from rl.c)-----------------------------------
+

You can run the command `vc-diff' with C-x v =

+
+
+

Ask Emacs to show you a diff of this file. (If you need a hint, it’s in the + first sentence of this section.)

+
+

The diff will be shown in diff-mode, which is also used for viewing patch +files. diff-mode has some useful tricks—read its documentation when you have a +spare minute.

+ +

All the vc commands are bound to key sequences starting with C-x v. If you +were paying attention when you invoked the diff command by its full name, you +may have noticed that Emacs told you the corresponding keybinding.

+
+

Press C-x v C-h to see all keybindings starting with C-x v.

+

This also works with any other prefix. Try it with C-x 4—you might notice + some parallels with keybindings you already know.

+
+

To commit the file, look into C-x v v (vc-next-action). Or enter +vc-dir-mode with C-x v d and find out how to mark files, for performing +vc- actions on multiple files at once.

+ +

vc has a (long!) section in the Emacs manual.

+ +

Personally, I prefer to use the gitk and git gui tools, or git’s +command-line interface directly, for adding, staging, committing, reverting, +merging, branching. But I do use the Emacs vc-diff and vc-print-log (and +vc-annotate!) extensively.

+ +

Because vc is limited to the common denominator of the backend systems it +supports, people have written custom modes for specific version control +systems. Magit is one such mode for git; but as we haven’t yet learned how to +install extensions, we’ll stick with vc. Anyway, vc can do a thing or two +even magit doesn’t do—have I mentioned vc-annotate?

+

vc-annotate

+

A couple of sections ago, I asked you to grep the readline sources for +“rl_insert_comment”.

+
+

Switch to the *grep* buffer if you still have it around, or do a new + search.

+
+

Remember, when switching buffers with C-x b you have to enter the asterisks +as part of the buffer name. (Incidentally, the asterisks are for buffers not +associated with a file on disk. This is just a convention; you could always +rename the *grep* buffer to something without asterisks —see +rename-buffer— or save it to disk if you wanted to.)

+
+

The first hit should have been in emacs_keymap.c. Jump to that match.

+
+

Let’s find out which release of readline added the Meta-# keybinding:

+
+
+

*Annotate emacs_keymap.c (rev master)*

+
^06cd36c emacs_keymap.c /* The start of printing characters. */ f8d82ba2 emacs_keymap.c { ISFUNC, rl_set_mark }, /* Meta-SPACE */ f8d82ba2 emacs_keymap.c { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-! */ f8d82ba2 emacs_keymap.c { ISFUNC, (rl_command_func_t *)0x0 }, /* Meta-" */ f8d82ba2 emacs_keymap.c { ISFUNC, rl_insert_comment }, /* Meta-# */
+
+

M-x vc-annotate

+

Delete all Emacs windows other than the annotate window (you might also want + to resize the frame so that it is large enough).

+ +

With point on the “Meta-#” line, press d to view the diff of the revision + where this line was last changed.

+ +

Now we’re in diff-mode. It seems that this revision consisted mostly of + whitespace changes. Find the exact change to “Meta-#”. You can press C-c C-w to hide whitespace-only changes in the hunk surrounding point, and n + to jump to the next hunk.

+ +

Nope, this revision wasn’t it. Press q to exit the diff buffer, then a to + run annotate again, starting from the revision before this line’s revision.

+
+

*vc-diff*

+
{ ISFUNC, (Function *)0x0 }, /* Meta-! */ { ISFUNC, (Function *)0x0 }, /* Meta-" */ - { ISFUNC, (Function *)0x0 }, /* Meta-# */ + { ISFUNC, rl_insert_comment },/* Meta-# */ { ISFUNC, (Function *)0x0 }, /* Meta-$ */ { ISFUNC, (Function *)0x0 }, /* Meta-% */
+
+

Now make sure your point is on the right line (if the new revision is + different enough from the newer one, the line we’re interested in may have + moved around). Then press d again, and in diff-mode n until you find the + right hunk. Yes, this is the change we’re looking for!

+ +

Go back to the annotate buffer (q). Press l to view the log message for + this revision. See, readline’s “Meta-#” binding dates back to version 2.1! If + you want some context you can press D (that’s shift-d) to view the diff + of all files changed in this revision.

+
+

Of course, annotate is more useful when the commits are more granular and the +commit messages are more descriptive, with links to bug tracker entries and so +on. But you get the idea.

+ +

Right now I don’t expect you to remember all these keybindings, but I do expect +you to know how to find them when you need them.

+

ediff

+

ediff is a more powerful mode for viewing differences between files or +revisions.

+
+

Switch to buffer rl.c if necessary.

+

M-x ediff-revision. Accept the default values of rl.c, its latest revision, + and its current state.

+
+

This opens a new frame from which you control ediff; always make sure the +ediff frame has focus when you’re giving it a command.

+
+

Press ? for help. Figure out how to step through each diff. Figure out how + to show the files side-by-side. q when you’re done.

+
+

When invoking ediff-revision you can supply any two revisions, not just the +latest revision and the current working copy. You can also diff any 2 buffers +(ediff-buffers) or files (ediff-files).

+ +

I suggest you stay away from ediff-directories (if you want to know why, try +using it).

+

etags

+

etags is a program that indexes source files and creates a TAGS file that +Emacs can use to find definitions of variables, functions and types.

+
+

Run the shell command make TAGS in the readline directory (either from a + shell buffer, or with M-x compile).

+
+

The Makefiles of most open-source projects include the TAGS target. For those +that don’t, you can use a combination of find, xargs and etags from the +shell to generate the TAGS file manually (read the man pages for those tools +if you need to).

+ +

The etags you just ran was probably the one that shipped with Emacs. There’s +an alternate implementation called “Exuberant ctags” that supports more languages. Install it with +your package manager (e.g. port or yum install ctags) and call it with +ctags -e.

+
+

Back in Emacs, invoke find-tag (M-.). Enter rl_insert_comment as the + tag to find, and then the location of the TAGS file you just generated.

+
+
+

From the help for find-tag, figure out how to jump back to the location you + were at before invoking the command, and how to find the next match if there + is more than one. (You might find the documentation from C-h S find-tag + clearer than that from C-h f.)

+
+

To use a different TAGS file visit-tags-table.

+ +

If you’re a C++ programmer, you’ll soon find that ctags/etags is not +perfect when it comes to classes and namespaces. As a 90% solution, it’s good +enough, most of the time. Hopefully someone will come up with a clang-based indexer sometime soon.

+

gdb

+

We’re going to run the rl program under the GNU debugger, gdb.

+
+

First run compile in readline and then in readline/examples.

+
+

The compilation should succeed,[5] as long as you haven’t introduced any errors +in any of the source files. If you have, you know how to view and back out your +changes.

+
+

M-x gdb. When prompted for the command-line to use, specify the program + examples/rl as an argument to gdb: if you’re in the readline/examples + directory, the command-line will look like gdb ‑‑annotate=3 ./rl.

+
+

You are now running gdb inside Emacs, so the standard gdb commands apply. +Let’s set a breakpoint in the readline function, start the rl program, and +when we reach the breakpoint step through a few lines.

+
+

Type the following commands at the gdb prompt:

+

break readline
+ run
+ print rl_pending_input
+ next
+ step
+ backtrace
+ frame 1

+
+

Note how Emacs displays the corresponding source file and line in a separate +window.

+ +

The above commands are all interpreted directly by the gdb program. gdb +allows you to abbreviate them to r, p, n, s, bt, and f, +respectively. Pressing return on an empty line repeats the previous +command—useful for multiple next commands. help displays gdb’s built-in +help.

+ +

For serious debugging, Emacs can open additional windows showing the current +stack frames, breakpoints, local variables and registers. See the Emacs manual +for details: C-h r opens the Emacs manual in the Info browser, then search +for the chapter titled “GDB Graphical Interface”.

+

Homework

+

You may be feeling somewhat overwhelmed at this point. Spend a few days using +Emacs as your main editor, painful though it may be, before moving on to the +next chapter of this guide. If you’ve forgotten a command I’ve taught you, try +to figure it out yourself (use C-h m, C-h a, C-h f, C-h k and C-h S) +before looking it up here.

+ +

As part of your commitment to learning Emacs, try to run your shell within +Emacs as much as possible. (If you need help configuring your shell to work +well within Emacs, or configuring Emacs to work well with your shell, we will +revisit shell-mode in the “General customization” chapter of this guide.)

+
+

[1]: + You will need git, a source control system; the Git Book has installation + instructions.

+ +

[2]: + On Windows you will need a shell provided by Cygwin or similar.

+ +

[3]: + These keybindings aren’t arbitrary. C-c C-s mirrors C-x C-s, which you + already know for saving the entire buffer to a file (“global” keybindings + tend to start with C-x, whereas C-c is a prefix for mode-specific + bindings). And C-M-l performs a similar function in other editing modes—in + c-mode it tries to bring into view the whole function surrounding the point. + If you’re feeling overwhelmed by the number of keybindings to memorize, don’t + worry; you can always find them again with C-h m.

+ +

[4]: + On Windows you will need find and grep commands provided by Cygwin or + similar.

+ +

[5]: + I haven’t tested this on Windows, but I’m assuming that Cygwin installs the + necessary compiler, headers and libraries.

+
+ +

+
+ + diff --git a/bin/footnotes b/bin/footnotes new file mode 100755 index 0000000..92db136 --- /dev/null +++ b/bin/footnotes @@ -0,0 +1,15 @@ +#!/bin/sh + +# Replaces "[1]" on stdin with an html link to #fn1 on stdout; +# similarly, replaces "[1]:" with an html anchor for #fn1. + +# GNU sed uses "-r" for extended regexps; BSD sed uses "-E". +if $(echo test | sed -r >/dev/null 2>&1); then + sed="sed -r" +else + sed="sed -E" +fi + +fn='\[\[([0-9]+)\]\]' +$sed -e "/$fn/ s,$fn([^:]|\$),[\1]\2,g" \ + -e "s,$fn:,[\1]:," diff --git a/bin/glossarylinks b/bin/glossarylinks new file mode 100755 index 0000000..f1b44f9 --- /dev/null +++ b/bin/glossarylinks @@ -0,0 +1,22 @@ +#!/usr/bin/env perl + +# Replaces words on stdin with html links to their entry in the glossary. +# Presence of any command-line argument inhibits all replacements (we don't want to +# add links on the glossary html page itself, for example). + +while () { + if (!@ARGV[0] && !/frame 1|tcpip-parser|Notepad|Making Buffer Names Unique/) { + s,((C-M-|C-|M-|s-)([a-zA-Z0-9 /|-])+),$1,g; + s,(?-])\b(frame)\b(?![/<]),$&,gi; + s,(?-])\b(windows?)\b(?![/<]),$&,g; + s,(?-])\b(buffers?)\b(?![/<-]),$&,gi; + s,(?-])\b(modeline)\b(?![/<]),$&,gi; + s,(?-])\b(echo area)\b(?![/<]),$&,gi; + s,(?-])\b(minibuffer)\b(?![/<]),$&,gi; + s,(?-])\b(the (point|mark|region))\b,$&,gi; + s,(?-])\b(kill|yank)(ing)?\b,$&,gi; + s,(?-])\b(editing modes?|major modes?)\b,$&,gi; + s,(?-])\b(minor modes?)\b,$&,gi; + } + print; +} diff --git a/bin/layout b/bin/layout new file mode 100755 index 0000000..2dfe742 --- /dev/null +++ b/bin/layout @@ -0,0 +1,8 @@ +#!/bin/sh + +# Prints a complete html page to stdout from the layout filename in $1 and the +# content on stdin. + +sed -e '/-- Contents --/ q' $1 +cat +sed -n -e '/-- Contents --/,$ p' $1 diff --git a/bin/next b/bin/next new file mode 100755 index 0000000..74af984 --- /dev/null +++ b/bin/next @@ -0,0 +1,18 @@ +#!/bin/sh + +# Inserts, at the appropriate position on stdout, an html link to the next +# chapter. + +plain_toc=$1 +chapter=$2 +next_chapter=$(awk "\$2 == \"$chapter\" { PRINT=1; next; } + /^[0-9A-Z]+\. / && PRINT==1 { print \$2; exit; }" \ + < $plain_toc) + +if [ -n "$next_chapter" ]; then + next_title=$(sed -n 's,%h1 \(.*\),\1,p' $next_chapter.haml) + next_link="" + sed -e "s,,

$next_link

," +else + cat +fi diff --git a/bin/tables b/bin/tables new file mode 100755 index 0000000..d7f57c9 --- /dev/null +++ b/bin/tables @@ -0,0 +1,37 @@ +#!/usr/bin/env perl + +while (<>) { + if (s,^( *)\| *,,) { + $indentation = $1; + print $indentation; + if (! $intable) { + $intable = 1; + print "\n$indentation"; + } + if (! $inrow) { + $inrow = 1; + print ",; + } + markdown(); + } + elsif ($intable) { + $intable = 0; + print "$indentation
" + } + s, \| ,,g; + if (/\|$/) { + $inrow = 0; + s,\|$,
\n"; + } + s,^( *)\\\|,$1|,; + + print; +} + +# My own limited markdown implementation, because the markdown invoked by my +# toolchain ("haml --autofilter markdown" ...) doesn't touch content inside +# .... +sub markdown { + s,`([^`]+)`,$1,g; + s, $,
,; +} diff --git a/bin/title b/bin/title new file mode 100755 index 0000000..051d5b7 --- /dev/null +++ b/bin/title @@ -0,0 +1,7 @@ +#!/bin/sh + +# Replaces "" on stdin with the actual title on stdout; +# takes the actual title from the

...

contents of the filename in $1. + +title=$(sed -n 's,%h1 \(.*\),\1,p' $1) +sed -e "s,,How to learn Emacs :: $title," diff --git a/bin/toc b/bin/toc new file mode 100755 index 0000000..ed003df --- /dev/null +++ b/bin/toc @@ -0,0 +1,13 @@ +#!/bin/sh + +# Replaces "" on stdin with html, generated by +# toc.awk, on stdout. + +plain_toc=$1 +chapter=$2 # toc.awk highlights this chapter. + +html_toc=/tmp/toc.html.$$ +trap "rm -f $html_toc" EXIT + +$(dirname $0)/toc.awk current=$chapter < $plain_toc > $html_toc +sed -e "/-- Table of Contents --/ r $html_toc" diff --git a/bin/toc.awk b/bin/toc.awk new file mode 100755 index 0000000..b060614 --- /dev/null +++ b/bin/toc.awk @@ -0,0 +1,25 @@ +#!/usr/bin/env awk -f + +BEGIN { printf "
    \n" } +/^[0-9A-Z]+\. / { li($1, $2, $3) } +/^[—A-Za-z ]{2,}/ { printf "
\n

" $0 "

\n
    \n" } +END { printf "
\n" } + +function li(number, file, subs) { + if (file == current) printf "
  • " + else printf "
  • " + printf number " " + system("sed -n 's,%h1 ,,p' " file ".haml | tr -d '\n'") + if (file != current) printf "" + if (file == current && subs == "+subsections") { + printf "\n
      \n" + subsections(file) + printf "
    \n " + } + printf "
  • \n" +} +function subsections(file) { + system("sed -En 's,%h2#([a-z0-9-]*) (.*)" \ + ",
  • \\2
  • " \ + ",p' " file ".haml") +} diff --git a/bin/updated b/bin/updated new file mode 100755 index 0000000..38f764f --- /dev/null +++ b/bin/updated @@ -0,0 +1,6 @@ +#!/bin/sh + +# Replaces "" on stdin with the date of the latest commit. + +updated=$(git log -n1 --format=format:%cD "$@" | awk '{print $2, $3, $4 "."}') +sed -e "s,,$updated," diff --git a/contribute_emacs.haml b/contribute_emacs.haml new file mode 100644 index 0000000..ce010ba --- /dev/null +++ b/contribute_emacs.haml @@ -0,0 +1,185 @@ +%h1 Contributing to Emacs + +Please consider contributing patches to Emacs, even if you're an Emacs novice. +*Especially* if you're an Emacs novice--no-one is better qualified to judge the +introductory documentation. Contribute *now*, before Stockholm syndrome sets +in! + + +%h2 Reporting a bug + +`M-x report-emacs-bug` will open a mail buffer with a template ready for you to +fill with information. You probably haven't configured Emacs to be able to send +email, but you can copy from this buffer and paste into your favorite email +client. + +Do follow the instructions in that buffer. In particular, make sure you can +reproduce the bug having run Emacs with `emacs -Q` (to confirm that it is a bug +in Emacs itself and not in your customizations or in a third-party package). + + +%h2 A simple documentation change + +The documentation for `ido-find-file` says: + +.titlebar< + \\*Help* +.window< + :preserve + C-j Select the current prompt as the buffer or file. + If no buffer or file is found, prompt for a new one. +   +.modeline< + :preserve + -U:%%- *Help* 32% L22 (Help View)----------------------------------------------- +.echoarea< +   + +After reading that I still didn't know what `C-j` (at the `ido-find-file` +prompt) actually does. It turns out to mean "use whatever you've typed +verbatim" instead of using `ido`'s fuzzy matching. I'll submit a patch to the +documentation string. + + +%h2 Making a patch, the 1980s way + +.do + `M-x find-function ido-find-file`. + +.do + Save a copy of this buffer (with `C-x C-w`) to `~/.emacs.d/ido.el` and + another copy to `~/.emacs.d/ido.el.orig`. + +.do + Modify `~/.emacs.d/ido.el`. To test the change, evaluate (`C-M-x`) the + `defun` form you changed. + +.do + Generate a patch with `diff -cp ido.el.orig ido.el`.[[1]] + +.titlebar< + ido.el.patch +.window< + :preserve + *** ido.el.orig 2012-04-07 10:20:31.000000000 +0100 + --- ido.el 2012-04-07 10:28:59.000000000 +0100 + *************** (defun ido-switch-buffer () + *** 4041,4048 **** + RET Select the buffer at the front of the list of matches. If the + list is empty, possibly prompt to create new buffer. + + ! \\[ido-select-text] Select the current prompt as the buffer. + ! If no buffer is found, prompt for a new one. + + \\[ido-next-match] Put the first element at the end of the list. + \\[ido-prev-match] Put the last element at the start of the list. + --- 4041,4047 ---- + RET Select the buffer at the front of the list of matches. If the + list is empty, possibly prompt to create new buffer. + + ! \\[ido-select-text] Use the current input string verbatim. + + \\[ido-next-match] Put the first element at the end of the list. + \\[ido-prev-match] Put the last element at the start of the list. + *************** (defun ido-find-file () + *** 4128,4135 **** + RET Select the file at the front of the list of matches. If the + list is empty, possibly prompt to create new file. + + ! \\[ido-select-text] Select the current prompt as the buffer or file. + ! If no buffer or file is found, prompt for a new one. + + \\[ido-next-match] Put the first element at the end of the list. + \\[ido-prev-match] Put the last element at the start of the list. + --- 4127,4133 ---- + RET Select the file at the front of the list of matches. If the + list is empty, possibly prompt to create new file. + + ! \\[ido-select-text] Use the current input string verbatim. + + \\[ido-next-match] Put the first element at the end of the list. + \\[ido-prev-match] Put the last element at the start of the list. + +.modeline< + :preserve + -U:--- ido.el.patch Top L1 (Diff)----------------------------------------------- +.echoarea< +   + + +%h2 Making a patch in the 21st century[[2]] + +Ideally you'd make the patch against the latest (unreleased) version of the +Emacs source code, instead of version 23.3. Someone else might even have fixed +your problem already! The Emacs source code is hosted at [savannah.gnu.org]( +http://savannah.gnu.org/projects/emacs) and you can grab the source code from +the official Bazaar repository: + +.do + `bzr branch bzr://bzr.savannah.gnu.org/emacs/trunk` + +Or, if you prefer git, from the git mirror (which can [allegedly]( +http://emacswiki.org/emacs/EmacsFromGit) be up to one day behind the Bazaar +repo): + +.do + `git clone git://git.savannah.gnu.org/emacs.git` + +Note that either one of the above commands will take quite a while, but you'll +only do it once. I'll use git in the following instructions. + +.do + Create a private (local) branch for your changes: + `git checkout -b ido-el-documentation --track master` + +.do + Make the change on the source files directly. Test. + +.do + `git commit -am "* ido.el: Documentation for C-j in ido-find-file and ido-switch-buffer."` + +.do + `git format-patch master` + +In future, before starting on another change you'll want to pull the latest +changes from upstream: + +.do + `git checkout master` + `git pull --rebase`[[3]] + + +%h2 Send the patch + +Send the patch to the same email address as `M-x report-emacs-bug`. But first +read the [instructions for contributing to Emacs]( +http://git.savannah.gnu.org/cgit/emacs.git/plain/etc/CONTRIBUTE) and the [Emacs +Lisp tips and conventions]( +http://www.gnu.org/software/emacs/manual/html_node/elisp/Tips.html). + + +%h2 Contributing to third-party packages + +Try to find contribution guidelines on the package's website: Where to email +your patch, the preferred formatting of the patch and its changelog message, +etc. + +If the package is hosted on github, the package maintainers may be open to pull +requests via github's interface. + + +#footnotes + [[1]]: + Don't ask me why the Emacs maintainers don't like unified diffs (`diff -u`). + They [specifically ask]( + http://git.savannah.gnu.org/cgit/emacs.git/tree/etc/CONTRIBUTE?id=9771cd41#n103) + for `diff -c`. + + [[2]]: + The 21st century requires half a gig of disk space and a 30-minute download. + + [[3]]: + The `--rebase` is to avoid complicated merges in the history if you have + local un-pushed commits on the master branch. Though if you've followed these + instructions, your local changes should only ever be on private branches, not + on master. diff --git a/contribute_emacs.html b/contribute_emacs.html new file mode 100644 index 0000000..88c13d6 --- /dev/null +++ b/contribute_emacs.html @@ -0,0 +1,164 @@ + + + + + + How to learn Emacs :: Contributing to Emacs + + + + + +
    + +

    Contributing to Emacs

    +

    Please consider contributing patches to Emacs, even if you’re an Emacs novice. +Especially if you’re an Emacs novice—no-one is better qualified to judge the +introductory documentation. Contribute now, before Stockholm syndrome sets +in!

    +

    Reporting a bug

    +

    M-x report-emacs-bug will open a mail buffer with a template ready for you to +fill with information. You probably haven’t configured Emacs to be able to send +email, but you can copy from this buffer and paste into your favorite email +client.

    + +

    Do follow the instructions in that buffer. In particular, make sure you can +reproduce the bug having run Emacs with emacs -Q (to confirm that it is a bug +in Emacs itself and not in your customizations or in a third-party package).

    +

    A simple documentation change

    +

    The documentation for ido-find-file says:

    +

    *Help*

    +
    C-j Select the current prompt as the buffer or file. If no buffer or file is found, prompt for a new one.  
    +
    -U:%%- *Help* 32% L22 (Help View)-----------------------------------------------
    +

     

    +

    After reading that I still didn’t know what C-j (at the ido-find-file +prompt) actually does. It turns out to mean “use whatever you’ve typed +verbatim” instead of using ido’s fuzzy matching. I’ll submit a patch to the +documentation string.

    +

    Making a patch, the 1980s way

    + + +
    +

    Save a copy of this buffer (with C-x C-w) to ~/.emacs.d/ido.el and + another copy to ~/.emacs.d/ido.el.orig.

    +
    +
    +

    Modify ~/.emacs.d/ido.el. To test the change, evaluate (C-M-x) the + defun form you changed.

    +
    +
    +

    Generate a patch with diff -cp ido.el.orig ido.el.[1]

    +
    +

    ido.el.patch

    +
    *** ido.el.orig 2012-04-07 10:20:31.000000000 +0100 --- ido.el 2012-04-07 10:28:59.000000000 +0100 *************** (defun ido-switch-buffer () *** 4041,4048 **** RET Select the buffer at the front of the list of matches. If the list is empty, possibly prompt to create new buffer. ! \\[ido-select-text] Select the current prompt as the buffer. ! If no buffer is found, prompt for a new one. \\[ido-next-match] Put the first element at the end of the list. \\[ido-prev-match] Put the last element at the start of the list. --- 4041,4047 ---- RET Select the buffer at the front of the list of matches. If the list is empty, possibly prompt to create new buffer. ! \\[ido-select-text] Use the current input string verbatim. \\[ido-next-match] Put the first element at the end of the list. \\[ido-prev-match] Put the last element at the start of the list. *************** (defun ido-find-file () *** 4128,4135 **** RET Select the file at the front of the list of matches. If the list is empty, possibly prompt to create new file. ! \\[ido-select-text] Select the current prompt as the buffer or file. ! If no buffer or file is found, prompt for a new one. \\[ido-next-match] Put the first element at the end of the list. \\[ido-prev-match] Put the last element at the start of the list. --- 4127,4133 ---- RET Select the file at the front of the list of matches. If the list is empty, possibly prompt to create new file. ! \\[ido-select-text] Use the current input string verbatim. \\[ido-next-match] Put the first element at the end of the list. \\[ido-prev-match] Put the last element at the start of the list.
    +
    -U:--- ido.el.patch Top L1 (Diff)-----------------------------------------------
    +

     

    +

    Making a patch in the 21st century[2]

    +

    Ideally you’d make the patch against the latest (unreleased) version of the +Emacs source code, instead of version 23.3. Someone else might even have fixed +your problem already! The Emacs source code is hosted at savannah.gnu.org and you can grab the source code from +the official Bazaar repository:

    +
    +

    bzr branch bzr://bzr.savannah.gnu.org/emacs/trunk

    +
    +

    Or, if you prefer git, from the git mirror (which can allegedly be up to one day behind the Bazaar +repo):

    +
    +

    git clone git://git.savannah.gnu.org/emacs.git

    +
    +

    Note that either one of the above commands will take quite a while, but you’ll +only do it once. I’ll use git in the following instructions.

    +
    +

    Create a private (local) branch for your changes:
    + git checkout -b ido-el-documentation --track master

    +
    +
    +

    Make the change on the source files directly. Test.

    +
    +
    +

    git commit -am "* ido.el: Documentation for C-j in ido-find-file and ido-switch-buffer."

    +
    +
    +

    git format-patch master

    +
    +

    In future, before starting on another change you’ll want to pull the latest +changes from upstream:

    +
    +

    git checkout master
    + git pull --rebase[3]

    +
    +

    Send the patch

    +

    Send the patch to the same email address as M-x report-emacs-bug. But first +read the instructions for contributing to Emacs and the Emacs +Lisp tips and conventions.

    +

    Contributing to third-party packages

    +

    Try to find contribution guidelines on the package’s website: Where to email +your patch, the preferred formatting of the patch and its changelog message, +etc.

    + +

    If the package is hosted on github, the package maintainers may be open to pull +requests via github’s interface.

    +
    +

    [1]: + Don’t ask me why the Emacs maintainers don’t like unified diffs (diff -u). + They specifically ask + for diff -c.

    + +

    [2]: + The 21st century requires half a gig of disk space and a 30-minute download.

    + +

    [3]: + The --rebase is to avoid complicated merges in the history if you have + local un-pushed commits on the master branch. Though if you’ve followed these + instructions, your local changes should only ever be on private branches, not + on master.

    +
    + +

    +
    + + diff --git a/contribute_guide.haml b/contribute_guide.haml new file mode 100644 index 0000000..aaca730 --- /dev/null +++ b/contribute_guide.haml @@ -0,0 +1,35 @@ +%h1 Contributing to this guide + +This guide is released under the [GNU Free Documentation License]( +http://www.gnu.org/copyleft/fdl.html). The source documents are available on +[github]( https://github.com/drothlis/how-to-learn-emacs). Please contribute +patches, no matter how small, to correct errors or omissions. It's very easy! + +I initially intended to write multiple variants of the introductory chapter +["Basic Unix/C workflow"]( basic_c.html): One targeting Ruby/Rails developers, +etc. I gave up due to a lack of time, but if you'd like to contribute such a +chapter, please do. It could be tricky because I introduce concepts in a +particular order, and an introductory chapter for (say) Rails development would +require installing third-party packages, something I don't touch on until much +later. + + +%h2 Super-easy way to contribute small patches + +If you have a small correction to wording or spelling, you can browse to the +source file on [github](https://github.com/drothlis/how-to-learn-emacs), click +the button that says "Fork and edit this file", make your change, and submit a +"pull request". This will require you to create a (free) account on github, but +you don't even need to checkout the source files onto your computer. + +Or just [email me]( mailto:david@rothlis.net?subject=How%20to%20learn%20Emacs) +the correction. Unless you ask me otherwise, I will use your name and email +address in the change logs, which will be visible to anyone who downloads the +source repository from github. + + +%h2 More complex changes + +See the [README]( +https://github.com/drothlis/how-to-learn-emacs/blob/master/README) for +instructions on generating the html from the source haml files. diff --git a/contribute_guide.html b/contribute_guide.html new file mode 100644 index 0000000..dea9daf --- /dev/null +++ b/contribute_guide.html @@ -0,0 +1,86 @@ + + + + + + How to learn Emacs :: Contributing to this guide + + + + + +
    + +

    Contributing to this guide

    +

    This guide is released under the GNU Free Documentation License. The source documents are available on +github. Please contribute +patches, no matter how small, to correct errors or omissions. It’s very easy!

    + +

    I initially intended to write multiple variants of the introductory chapter +“Basic Unix/C workflow”: One targeting Ruby/Rails developers, +etc. I gave up due to a lack of time, but if you’d like to contribute such a +chapter, please do. It could be tricky because I introduce concepts in a +particular order, and an introductory chapter for (say) Rails development would +require installing third-party packages, something I don’t touch on until much +later.

    +

    Super-easy way to contribute small patches

    +

    If you have a small correction to wording or spelling, you can browse to the +source file on github, click +the button that says “Fork and edit this file”, make your change, and submit a +“pull request”. This will require you to create a (free) account on github, but +you don’t even need to checkout the source files onto your computer.

    + +

    Or just email me +the correction. Unless you ask me otherwise, I will use your name and email +address in the change logs, which will be visible to anyone who downloads the +source repository from github.

    +

    More complex changes

    +

    See the README for +instructions on generating the html from the source haml files.

    + +

    +
    + + diff --git a/customize_c.haml b/customize_c.haml new file mode 100644 index 0000000..26f8515 --- /dev/null +++ b/customize_c.haml @@ -0,0 +1,593 @@ +%h1 cc-mode customization + +I should probably lead you through the relevant parts of the [Emacs]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/index.html), [Emacs +Lisp]( http://www.gnu.org/software/emacs/manual/html_node/elisp/index.html), +and [CC Mode]( +http://www.gnu.org/software/emacs/manual/html_node/ccmode/index.html) manuals, +but they're just. so. *long*! The mere table of contents for the Emacs manual +is longer than our previous "Unix/C workflow" chapter.[[1]] + +Instead I'll show you how I try to find the information I need from the Emacs +source code (most of which, thankfully, is in Lisp rather than C). The manuals +I dissed a moment ago *are* incredibly useful. It is cause for wonder that an +open-source project has produced such comprehensive documentation! But it is +*impossible* to read those manuals cover-to-cover; you must learn how to +efficiently find the right information. We've already covered the basic tools +for that, and now we will exercise them a lot more. + +By the way, `c-mode`, `c++-mode`, `objc-mode`, `java-mode`, and a few others +are all aliases for `cc-mode`, but with slight configuration changes to support +the respective languages. From here on I'll use the name `cc-mode`. + + +%h2#style House coding style + +Are you supposed to indent with 2, 3, 4 or 8 spaces, or with tabs? How big is +a tab? Whatever you want, I'm going to assume it's *not* the indentation that +cc-mode provides by default, so that we can walk through the procedure for +changing it. + +.do + Visit (open) a C or C++ file (you can use `readline/examples/rl.c` from the + previous chapter). + +Pressing `TAB` anywhere on a line indents it to the appropriate position +according to the current indentation rules (to insert a literal tab, use +`C-q`, a.k.a. `quoted-insert`). + +Let's find out what Emacs does behind the scenes when we press `TAB`: + +.do + `C-h k TAB` + +.window< + :preserve + TAB runs the command c-indent-line-or-region, + which is an interactive compiled Lisp function in `cc-cmds.el'. +   +.modeline< + :preserve + -U:%%- *Help* Top L1 (Help View)----------------------------------------------- +.echoarea< + Type C-x 1 to delete the help window. + +If you don't see the link to `cc-cmds.el`, then you don't have the elisp +sources installed. Use your system's package manager to install the `emacs-el` +package and try again. + +.do + Follow the link to `cc-cmds.el`. This will position you right where + `c-indent-line-or-region` is defined. Bring the whole definition into view + (`C-M-l`) if necessary. + +.window.default< + :preserve + (defun c-indent-line-or-region (&optional arg region) + "Indent active region, current line, or block starting on this line. + In Transient Mark mode, when the region is active, reindent the region. + Otherwise, with a prefix argument, rigidly reindent the expression + starting on the current line. + Otherwise reindent just the current line." + (interactive + (list current-prefix-arg (use-region-p))) + (if region + (c-indent-region (region-beginning) (region-end)) + (c-indent-command arg))) + + +%h2#elisp Emergency elisp + +A brief parenthesis is needed to explain the above code. Let's start with the +`if` statement at the end: + +.window.default< + :preserve + (if region + (c-indent-region (region-beginning) (region-end)) + (c-indent-command arg))) + +For clarity, let's simplify it to: + +.window.default< + :preserve + (if region + a + b) + +If you still don't understand what that means, pretend that `if` is actually a +function, and that it looks like this: + +.window.default< + :preserve + if(region, a, b) + +(Moving that parenthesis to the *left* of the function is probably the largest +single barrier to Lisp's adoption by the rest of the world.)[[2]] + +.do + What do the three arguments `region`, `a` and `b` mean? Make a guess, and + then check the answer at `C-h f if`. + +The definitions of *`COND`*, *`THEN`* and *`ELSE`* should be pretty clear. But +what does it mean by "`if` is a special form"? + +It turns out that `if` isn't a regular function. The elisp rule for evaluation +of "normal" forms—where "form" means a parenthesized "shape" like `(a b c)` or +`(a b (c d))`—is to evaluate each argument, and then pass the resulting values +to the function. + +Let's consider the function `+` (elisp doesn't have special infix operators, so +`+` is just a function). If `x` is a variable containing the value `5`, and `y` +is a variable containing the value `2`, then the following two expressions are +identical: + +.window.default< + :preserve + (+ x y) + (+ 5 2) + +The function `+` never sees `x`; it only sees `5`. + +.do + Evaluate the form `(+ 5 2)`: Switch to the `*scratch*` buffer, type `(+ 5 2)` + on a line of its own, and press `C-M-x` to evaluate the form and display the + result in the echo area. + +The very first element in the form (`+`, in this case) gets evaluated too. `+` +is actually a variable[[3]] whose value is the function that adds numbers. + +Anyway, back to `if`. `if` is a "special" form, which means that the elisp +interpreter treats `if` as a special case. Upon reflection, it is obvious that +the normal function evaluation rules are not suitable for `if`: We wouldn't +want to evaluate *`ELSE`*, with its possible side-effects, when *`COND`* is +"true" (non-nil). + +All this is explained in the Emacs Lisp manual: + +.do + `C-h S if` + -# + In the `*info*` buffer press `i` (for `i`ndex) and enter `special forms`. + +.do + Go back to the `cc-cmds.el.gz` buffer. + -# + Enable the `eldoc` minor mode (`M-x eldoc-mode`). Now positioning the point + over the `if` statement will show some brief documentation in the echo area. + -# + Enable `show-paren-mode` too. This should help clarify where the *`THEN`* and + *`ELSE`* clauses begin and end. + +Now, back up to the `defun`: + +.window.default< + :preserve + (defun c-indent-line-or-region (&optional arg region) + "Indent active region, current line, or block starting on this line. + In Transient Mark mode, when the region is active, reindent the region. + Otherwise, with a prefix argument, rigidly reindent the expression + starting on the current line. + Otherwise reindent just the current line." + (interactive + (list current-prefix-arg (use-region-p))) + (if region + (c-indent-region (region-beginning) (region-end)) + (c-indent-command arg))) + +.do + You now have three ways to get help on `defun`: `eldoc`'s summary in the echo + area, the reference provided by `C-h f`, and the more comprehensive Info + manual at `C-h S`. Take your pick. + +If you run across the word "lambda", it's the same as the "function" keyword +in javascript for an anonymous function. + +To reiterate: + +* `defun` defines a function named *`NAME`*. +* *`ARGLIST`* is a list of arguments for the function. In elisp, a list is +enclosed in parens: `(a b c)`. In this case it isn't evaluated as a function +call, because `defun` is a special form that treats this particular list in a +special way. When `defun`ing a function that takes no arguments, *`ARGLIST`* +would be the empty list `()`. +* The optional *`DOCSTRING`* is used by the `C-h f` help system (yes, even for +functions you define yourself!). +* *`BODY`* is one or more lists that are evaluated when you *call* the +function. +* ...except for the `(interactive ...)` form. + +.do + `C-h S interactive` + +Don't get too bogged-down by the explanation; reading the first two paragrahs +is enough. Learn to find *just* the information you need, or you will be easily +overwhelmed. Right now we don't need to know how to *use* `interactive`, only +what it *means*. + + +%h2#indentation Configuring indentation + +So. `c-indent-line-or-region` is a function that optionally takes arguments +`arg` and `region`, which, when the function is called interactively (for +example by pressing `TAB`), are set to the prefix argument (if specified with +`C-u` or similar) and "true" if the region is active. + +Right now we care about indentation when operating not on the region but on a +single line (i.e. `region` is `nil`), so let's look at the *`ELSE`* clause: + +.window.default< + :preserve + (if region + (c-indent-region (region-beginning) (region-end)) + (c-indent-command arg)) + +.do + Use `find-function` to jump to the definition of `c-indent-command`. + +This is a long and scary function, but luckily it has a good documentation +string. Now that we know the name of this function, we can view the same +documentation in a help buffer, with `C-h f c-indent-command`. + +The documentation mentions a couple of interesting variables: `c-basic-offset` +and `indent-tabs-mode`. + +.do + `C-h v c-basic-offset` + +That talks about "buffer-local" and "file local" variables. What? + +.do + `C-h S buffer-local` + +.do + From the elisp Info node for Buffer-Local Variables, search for "file local" + (you can use `C-s` or the index `i`). + +As you can see you sometimes have to try different searches to find the right +information. "Buffer-local" happened to be in the index, so the symbol search +(`C-h S`) found it; "File local" has a space, but the symbol search doesn't +allow spaces, so you had to search from within the Info buffer itself. You +could also have gone up (`u`) from the "Buffer-Local Variables" Info node and +scanned the "Variables" table of contents. + +Let's check the current value of `c-basic-offset`: + +.do + Switch to buffer `rl.c` (`c-basic-offset` is buffer-local, so it matters + which buffer we're in). + + `M-x eval-expression RET c-basic-offset RET` + +Now change it to 4: + +.do + `M-x set-variable c-basic-offset 4` + -# + Find a line to re-indent and press `TAB`. + +.do + Repeat the same investigation with variable `indent-tabs-mode`. + + +%h2#setq Setting variables from elisp code + +.do + Switch to the `*scratch*` buffer. + +Anything starting with a `;` is a comment. + +.do + Type in this form and evaluate it with `C-M-x`: + -# + `(set indent-tabs-mode nil)` + +You triggered an error, and Emacs brings up the backtrace in an elisp debugger. +You tried to set a constant to `nil`, which is clearly an error. + +.do + Explain why this happened, with your knowledge of the previous value of + `indent-tabs-mode` and of the elisp rules for evaluating functions. + +We can *quote* the name of the variable so that it doesn't get evaluated: + +.do + `(set 'indent-tabs-mode nil)` + +Read more about quoting: + +.do + `C-h S quote` + -# + `C-h S setq` + +The following forms do exactly the same; the preferred form is `setq`. +-# +.window.default< + :preserve + (set 'indent-tabs-mode nil) + (set (quote indent-tabs-mode) nil) + (setq indent-tabs-mode nil) + +One last thing: `indent-tabs-mode` is buffer-local, so setting it here only +affects the `*scratch*` buffer. To make the change global, you must use +`setq-default`. + + +%h2#init Init file + +Your changes to these variables will be lost when you restart Emacs. You need +to put your settings into an initialization file that Emacs will load each time +it starts. + +.do + In the Emacs manual (`C-h r`) table of contents, search for "init file" and + read the first paragraph. + +There are several places you can put your init file; I suggest the one that +goes inside the `~/.emacs.d` directory, so you can organize your customizations +by keeping multiple elisp files in the same directory, and loading them from +the main init file. Put this directory under version control. + +.do + Visit (open) the init file you've chosen (if the file doesn't exist, Emacs + will create it when you save the buffer). + +.do + Add the following lines: + -# + `(setq-default c-basic-offset 4)` + `(setq-default indent-tabs-mode nil)` + +(or whatever values you have chosen). + +.do + Restart Emacs, visit `rl.c`, and verify that your settings are in effect. + + +%h2#hooks Hooks + +By default, `cc-mode` automatically re-indents the line whenever you type a +character like `;` or `}`. These are called ["electric characters"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Electric-C.html) and +you can disable this behavior in a particular buffer with +`c-toggle-electric-state` (`C-c C-l`). + +To always disable electric characters we can have Emacs call +`c-toggle-electric-state` each time it loads `cc-mode`. + +.do + `C-h m` (from the `rl.c` buffer, or any other `cc-mode` buffer) to find out + the names of the hooks provided by `cc-mode`. + +A [hook]( http://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html) +is a variable containing a list of functions to be run, usually upon entry to a +particular editing mode. For C code we have two hooks: One for all of +`cc-mode`'s supported languages, and one just for C. We'll use the first one, +`c-mode-common-hook`. + +.do + Add the following to your init file: + -# + .window.default< + :preserve + (defun my-disable-electric-indentation () + "Stop ';', '}', etc. from re-indenting the current line." + (c-toggle-electric-state -1)) + (add-hook 'c-mode-common-hook 'my-disable-electric-indentation) + +First we defined a function that takes no arguments and calls +`(c-toggle-electric-state -1)`. Then we added the function to the +`c-mode-common-hook`. + +The `-1` argument tells `c-toggle-electric-state` to disable, rather than +toggle, the electric behavior (I learned this from `C-h f +c-toggle-electric-state`; some functions might want `nil`, but this one wanted +a negative number). + +You could add an anonymous function to a hook directly: + +.window.default< + :preserve + (add-hook 'c-mode-common-hook + (lambda () (c-toggle-electric-state -1))) + +but then you have no way of referring to the function by name, so you can't +remove it from the hook with `remove-hook`. + + +%h2#style-system The cc-mode style system + +There is more to coding style than the size of indentation. Where should +opening braces go? Should they be indented too? + +The `C-h v` documentation for `c-basic-offset` mentioned a "style system", and +referred us to `c-default-style`. + +.do + `C-h v c-default-style` + +.window.default< + :preserve + c-default-style is a variable defined in `cc-vars.el'. + Its value is ((java-mode . "java") + (awk-mode . "awk") + (other . "gnu")) + +Elisp syntax for a list is `(a b c)`, and for a pair is `(a . b)`. Pairs are +called "cons cells" in lisp terminology, and you access the first element with +the function `car`, the second with the function `cdr` (pronounced +"could-er"). + +So the value of `c-default-style` is a list containing 3 pairs; it's used as a +lookup dictionary where `java-mode`, `awk-mode` and `other` are the keys, and +`"java"`, `"awk"` and `"gnu"` are the values (in this case, names of styles to +use for each of the editing modes represented by the keys). These lookup +dictionaries are called "alists". + +.do + `C-h S alist` + +In your init file you could set `c-default-style` so that the default style for +`other`[[4]] is something other than `"gnu"`. + +If you need to customize anything (including `c-basic-offset` and +`indent-tabs-mode`) to something different than any of the built-in styles, I +recommend you define your own style: Thus if you work on different projects +with different styles, you will be able to switch easily (with `c-set-style`). +The way we set `c-basic-offset` earlier will [automatically create a style +called "user"]( +http://www.gnu.org/software/emacs/manual/html_node/ccmode/Built_002din-Styles.html#index-User-style-294). + +For help see ["Configuration basics"]( +http://www.gnu.org/software/emacs/manual/html_node/ccmode/Config-Basics.html), +["Customizing indentation"]( +http://www.gnu.org/software/emacs/manual/html_node/ccmode/Customizing-Indentation.html), +and ["Sample .emacs file"]( +http://www.gnu.org/software/emacs/manual/html_node/ccmode/Sample-_002eemacs-File.html) +in the CC Mode Manual. + + +%h2#keys Binding keys + +I often come across source code where one file expects tabs to equal 8 spaces, +and another file in the same directory—or even other lines within the same +file—want a tab to be 4 spaces. Let's create a function that cycles +`tab-width` between 2, 4 and 8 spaces. + +(I found the variable `tab-width` by using `apropos-variable` to search for +"tab".) + +.do + .window.default< + :preserve + (defun my-tab-width () + "Cycle tab-width between values 2, 4, and 8." + (interactive) + (setq tab-width + (cond ((eq tab-width 8) 2) + ((eq tab-width 2) 4) + (t 8))) + (redraw-display)) + +The `cond` expression evaluates to 2 if `tab-width` equals 8; to 4 if +`tab-width` equals 2; and to 8 otherwise. Look up `cond` and `eq` in the Info +manuals if you like. + +I've been naming all my functions "*my*-something" because elisp doesn't have +separate namespaces for each mode or package; this way I can be sure my +functions won't accidentally re-define an existing function that some editing +mode relies on. + +Now let's bind our new function to a key sequence, so we can invoke it +conveniently. `C-c` followed by a letter is [reserved for users to define]( +http://www.gnu.org/software/emacs/manual/html_node/elisp/Key-Binding-Conventions.html), +so we'll use `C-c t`: + +.do + .window.default< + :preserve + (global-set-key (kbd "C-c t") 'my-tab-width) + + +The meaning of "global" in `global-set-key` should be obvious. If you'd like a +keybinding just for `cc-mode`, use `define-key` to add the binding to the +mode's keymap: + +.window.default< + :preserve + (define-key c-mode-base-map (kbd "C-c t") 'my-tab-width) + +I discovered `c-mode-base-map` with `C-h v c-mode- TAB TAB`. There is also a +`c-mode-map` which is just for the C language, rather than all languages +supported by `cc-mode`. + + +%h2#auto-mode Associating file extensions with an editing mode + +Say you want `.h` files to open in `c++-mode` rather than `c-mode`: + +.do + `C-h v auto-mode-alist` + -# + `C-h f add-to-list` + +.figure + .window.default< + :preserve + (add-to-list 'auto-mode-alist + '("\\.h$" . c++-mode)) + .modeline< + :preserve + -U:--- *scratch* All L6 (Lisp Interaction)---------------------------------------- + .echoarea< + Regexp I-search: \\.h$ + +The trickiest part will be getting the regular expression right—elisp doesn't +have syntax for a regexp literal, so you have to put it inside a string, and +then the string backslash-escaping makes the regexp rather awful. See +["Regexps"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html) in the +Emacs manual. + + +%h2#homework Homework + +If you have a spare 30 minutes read Steve Yegge's [Emergency Elisp]( +http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html). + +If you have a spare 6 months work through [Structure and Interpretation of +Computer Programs]( http://mitpress.mit.edu/sicp/), a famous textbook from MIT +that teaches important (and some quite advanced) programming concepts and +techniques using a simple dialect of Lisp called Scheme. If you like "mathy" +things like the [Sieve of Eratosthenes]( +http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) for finding prime numbers, +[Heron's method]( +http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) +for calculating square roots, or estimating the value of pi using [Monte Carlo +simulation]( http://en.wikipedia.org/wiki/Monte_Carlo_method), then you'll love +this book. + +If you had a collection of `.emacs` customizations collected from the web +before you started this guide to Emacs, go over them now and try to understand +them thoroughly. + +In future, when you need a particular customization try to find the solution +from the manuals or the elisp sources before reaching for Google. + +Don't try to modify the elisp files that are part of the Emacs distribution. +For one, it won't be easy to merge your changes when you update Emacs to a +newer version. Second, the files are byte-compiled so you'd have to recompile +them. Third, even if you did it still wouldn't help because the core elisp +functions are [built into the Emacs image]( +http://www.gnu.org/software/emacs/manual/html_node/elisp/Building-Emacs.html), +so you'd have to recompile the whole program. Instead, use the variables and +hooks provided for customization. + +Don't pay attention to the Emacs manual whenever it tells you to use the ["Easy +customization"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Easy-Customization.html) +facility (in some help buffers it will say "you can customize this variable"). +It's referring to a really awkward semi-graphical interface for setting Emacs +variables. Best to keep all your customizations in your own init file. + + +#footnotes + [[1]]: + Try this: + `lynx --dump http://www.gnu.org/software/emacs/manual/html_node/emacs/index.html |` + `sed '/^References/,$ d' | wc -w` + + [[2]]: + I *am* joking. Lisp does have plenty of real problems. + + [[3]]: + Actually a "symbol". Curiously, elisp functions and variables live in + separate namespaces, so you can define the variable `+`, set it to `2`, and + still use `+` as a function in nonsensical statements like `(+ 1 +)`. Try it: + `(setq + 2)` + `(+ 1 +)` + + [[4]]: + "Other" here only refers to languages supported by `cc-mode`, not *any* other + language. diff --git a/customize_c.html b/customize_c.html new file mode 100644 index 0000000..c4ba0e0 --- /dev/null +++ b/customize_c.html @@ -0,0 +1,485 @@ + + + + + + How to learn Emacs :: cc-mode customization + + + + + +
    + +

    cc-mode customization

    +

    I should probably lead you through the relevant parts of the Emacs, Emacs +Lisp, +and CC Mode manuals, +but they’re just. so. long! The mere table of contents for the Emacs manual +is longer than our previous “Unix/C workflow” chapter.[1]

    + +

    Instead I’ll show you how I try to find the information I need from the Emacs +source code (most of which, thankfully, is in Lisp rather than C). The manuals +I dissed a moment ago are incredibly useful. It is cause for wonder that an +open-source project has produced such comprehensive documentation! But it is +impossible to read those manuals cover-to-cover; you must learn how to +efficiently find the right information. We’ve already covered the basic tools +for that, and now we will exercise them a lot more.

    + +

    By the way, c-mode, c++-mode, objc-mode, java-mode, and a few others +are all aliases for cc-mode, but with slight configuration changes to support +the respective languages. From here on I’ll use the name cc-mode.

    +

    House coding style

    +

    Are you supposed to indent with 2, 3, 4 or 8 spaces, or with tabs? How big is +a tab? Whatever you want, I’m going to assume it’s not the indentation that +cc-mode provides by default, so that we can walk through the procedure for +changing it.

    +
    +

    Visit (open) a C or C++ file (you can use readline/examples/rl.c from the + previous chapter).

    +
    +

    Pressing TAB anywhere on a line indents it to the appropriate position +according to the current indentation rules (to insert a literal tab, use +C-q, a.k.a. quoted-insert).

    + +

    Let’s find out what Emacs does behind the scenes when we press TAB:

    + +
    TAB runs the command c-indent-line-or-region, which is an interactive compiled Lisp function in `cc-cmds.el'.  
    +
    -U:%%- *Help* Top L1 (Help View)-----------------------------------------------
    +

    Type C-x 1 to delete the help window.

    +

    If you don’t see the link to cc-cmds.el, then you don’t have the elisp +sources installed. Use your system’s package manager to install the emacs-el +package and try again.

    +
    +

    Follow the link to cc-cmds.el. This will position you right where + c-indent-line-or-region is defined. Bring the whole definition into view + (C-M-l) if necessary.

    +
    +
    (defun c-indent-line-or-region (&optional arg region) "Indent active region, current line, or block starting on this line. In Transient Mark mode, when the region is active, reindent the region. Otherwise, with a prefix argument, rigidly reindent the expression starting on the current line. Otherwise reindent just the current line." (interactive (list current-prefix-arg (use-region-p))) (if region (c-indent-region (region-beginning) (region-end)) (c-indent-command arg)))
    +

    Emergency elisp

    +

    A brief parenthesis is needed to explain the above code. Let’s start with the +if statement at the end:

    +
    (if region (c-indent-region (region-beginning) (region-end)) (c-indent-command arg)))
    +

    For clarity, let’s simplify it to:

    +
    (if region a b)
    +

    If you still don’t understand what that means, pretend that if is actually a +function, and that it looks like this:

    +
    if(region, a, b)
    +

    (Moving that parenthesis to the left of the function is probably the largest +single barrier to Lisp’s adoption by the rest of the world.)[2]

    +
    +

    What do the three arguments region, a and b mean? Make a guess, and + then check the answer at C-h f if.

    +
    +

    The definitions of COND, THEN and ELSE should be pretty clear. But +what does it mean by “if is a special form”?

    + +

    It turns out that if isn’t a regular function. The elisp rule for evaluation +of “normal” forms—where “form” means a parenthesized “shape” like (a b c) or +(a b (c d))—is to evaluate each argument, and then pass the resulting values +to the function.

    + +

    Let’s consider the function + (elisp doesn’t have special infix operators, so ++ is just a function). If x is a variable containing the value 5, and y +is a variable containing the value 2, then the following two expressions are +identical:

    +
    (+ x y) (+ 5 2)
    +

    The function + never sees x; it only sees 5.

    +
    +

    Evaluate the form (+ 5 2): Switch to the *scratch* buffer, type (+ 5 2) + on a line of its own, and press C-M-x to evaluate the form and display the + result in the echo area.

    +
    +

    The very first element in the form (+, in this case) gets evaluated too. + +is actually a variable[3] whose value is the function that adds numbers.

    + +

    Anyway, back to if. if is a “special” form, which means that the elisp +interpreter treats if as a special case. Upon reflection, it is obvious that +the normal function evaluation rules are not suitable for if: We wouldn’t +want to evaluate ELSE, with its possible side-effects, when COND is +“true” (non-nil).

    + +

    All this is explained in the Emacs Lisp manual:

    +
    +

    C-h S if

    +

    In the *info* buffer press i (for index) and enter special forms.

    +
    +
    +

    Go back to the cc-cmds.el.gz buffer.

    +

    Enable the eldoc minor mode (M-x eldoc-mode). Now positioning the point + over the if statement will show some brief documentation in the echo area.

    +

    Enable show-paren-mode too. This should help clarify where the THEN and + ELSE clauses begin and end.

    +
    +

    Now, back up to the defun:

    +
    (defun c-indent-line-or-region (&optional arg region) "Indent active region, current line, or block starting on this line. In Transient Mark mode, when the region is active, reindent the region. Otherwise, with a prefix argument, rigidly reindent the expression starting on the current line. Otherwise reindent just the current line." (interactive (list current-prefix-arg (use-region-p))) (if region (c-indent-region (region-beginning) (region-end)) (c-indent-command arg)))
    +
    +

    You now have three ways to get help on defun: eldoc’s summary in the echo + area, the reference provided by C-h f, and the more comprehensive Info + manual at C-h S. Take your pick.

    +
    +

    If you run across the word “lambda”, it’s the same as the “function” keyword +in javascript for an anonymous function.

    + +

    To reiterate:

    + +
      +
    • defun defines a function named NAME.
    • +
    • ARGLIST is a list of arguments for the function. In elisp, a list is +enclosed in parens: (a b c). In this case it isn’t evaluated as a function +call, because defun is a special form that treats this particular list in a +special way. When defuning a function that takes no arguments, ARGLIST +would be the empty list ().
    • +
    • The optional DOCSTRING is used by the C-h f help system (yes, even for +functions you define yourself!).
    • +
    • BODY is one or more lists that are evaluated when you call the +function.
    • +
    • …except for the (interactive ...) form.
    • +
    + +

    Don’t get too bogged-down by the explanation; reading the first two paragrahs +is enough. Learn to find just the information you need, or you will be easily +overwhelmed. Right now we don’t need to know how to use interactive, only +what it means.

    +

    Configuring indentation

    +

    So. c-indent-line-or-region is a function that optionally takes arguments +arg and region, which, when the function is called interactively (for +example by pressing TAB), are set to the prefix argument (if specified with +C-u or similar) and “true” if the region is active.

    + +

    Right now we care about indentation when operating not on the region but on a +single line (i.e. region is nil), so let’s look at the ELSE clause:

    +
    (if region (c-indent-region (region-beginning) (region-end)) (c-indent-command arg))
    +
    +

    Use find-function to jump to the definition of c-indent-command.

    +
    +

    This is a long and scary function, but luckily it has a good documentation +string. Now that we know the name of this function, we can view the same +documentation in a help buffer, with C-h f c-indent-command.

    + +

    The documentation mentions a couple of interesting variables: c-basic-offset +and indent-tabs-mode.

    + +

    That talks about “buffer-local” and “file local” variables. What?

    + +
    +

    From the elisp Info node for Buffer-Local Variables, search for “file local” + (you can use C-s or the index i).

    +
    +

    As you can see you sometimes have to try different searches to find the right +information. “Buffer-local” happened to be in the index, so the symbol search +(C-h S) found it; “File local” has a space, but the symbol search doesn’t +allow spaces, so you had to search from within the Info buffer itself. You +could also have gone up (u) from the “Buffer-Local Variables” Info node and +scanned the “Variables” table of contents.

    + +

    Let’s check the current value of c-basic-offset:

    +
    +

    Switch to buffer rl.c (c-basic-offset is buffer-local, so it matters + which buffer we’re in).

    + +

    M-x eval-expression RET c-basic-offset RET

    +
    +

    Now change it to 4:

    +
    +

    M-x set-variable c-basic-offset 4

    +

    Find a line to re-indent and press TAB.

    +
    +
    +

    Repeat the same investigation with variable indent-tabs-mode.

    +
    +

    Setting variables from elisp code

    + +
    +

    Switch to the *scratch* buffer.

    +
    +

    Anything starting with a ; is a comment.

    +
    +

    Type in this form and evaluate it with C-M-x:

    +

    (set indent-tabs-mode nil)

    +
    +

    You triggered an error, and Emacs brings up the backtrace in an elisp debugger. +You tried to set a constant to nil, which is clearly an error.

    +
    +

    Explain why this happened, with your knowledge of the previous value of + indent-tabs-mode and of the elisp rules for evaluating functions.

    +
    +

    We can quote the name of the variable so that it doesn’t get evaluated:

    +
    +

    (set 'indent-tabs-mode nil)

    +
    +

    Read more about quoting:

    + +

    The following forms do exactly the same; the preferred form is setq.

    +
    (set 'indent-tabs-mode nil) (set (quote indent-tabs-mode) nil) (setq indent-tabs-mode nil)
    +

    One last thing: indent-tabs-mode is buffer-local, so setting it here only +affects the *scratch* buffer. To make the change global, you must use +setq-default.

    +

    Init file

    +

    Your changes to these variables will be lost when you restart Emacs. You need +to put your settings into an initialization file that Emacs will load each time +it starts.

    +
    +

    In the Emacs manual (C-h r) table of contents, search for “init file” and + read the first paragraph.

    +
    +

    There are several places you can put your init file; I suggest the one that +goes inside the ~/.emacs.d directory, so you can organize your customizations +by keeping multiple elisp files in the same directory, and loading them from +the main init file. Put this directory under version control.

    +
    +

    Visit (open) the init file you’ve chosen (if the file doesn’t exist, Emacs + will create it when you save the buffer).

    +
    +
    +

    Add the following lines:

    +

    (setq-default c-basic-offset 4)
    + (setq-default indent-tabs-mode nil)

    +
    +

    (or whatever values you have chosen).

    +
    +

    Restart Emacs, visit rl.c, and verify that your settings are in effect.

    +
    +

    Hooks

    +

    By default, cc-mode automatically re-indents the line whenever you type a +character like ; or }. These are called “electric characters” and +you can disable this behavior in a particular buffer with +c-toggle-electric-state (C-c C-l).

    + +

    To always disable electric characters we can have Emacs call +c-toggle-electric-state each time it loads cc-mode.

    +
    +

    C-h m (from the rl.c buffer, or any other cc-mode buffer) to find out + the names of the hooks provided by cc-mode.

    +
    +

    A hook +is a variable containing a list of functions to be run, usually upon entry to a +particular editing mode. For C code we have two hooks: One for all of +cc-mode’s supported languages, and one just for C. We’ll use the first one, +c-mode-common-hook.

    +
    +

    Add the following to your init file:

    +
    (defun my-disable-electric-indentation () "Stop ';', '}', etc. from re-indenting the current line." (c-toggle-electric-state -1)) (add-hook 'c-mode-common-hook 'my-disable-electric-indentation)
    +
    +

    First we defined a function that takes no arguments and calls +(c-toggle-electric-state -1). Then we added the function to the +c-mode-common-hook.

    + +

    The -1 argument tells c-toggle-electric-state to disable, rather than +toggle, the electric behavior (I learned this from C-h f c-toggle-electric-state; some functions might want nil, but this one wanted +a negative number).

    + +

    You could add an anonymous function to a hook directly:

    +
    (add-hook 'c-mode-common-hook (lambda () (c-toggle-electric-state -1)))
    +

    but then you have no way of referring to the function by name, so you can’t +remove it from the hook with remove-hook.

    +

    The cc-mode style system

    +

    There is more to coding style than the size of indentation. Where should +opening braces go? Should they be indented too?

    + +

    The C-h v documentation for c-basic-offset mentioned a “style system”, and +referred us to c-default-style.

    + +
    c-default-style is a variable defined in `cc-vars.el'. Its value is ((java-mode . "java") (awk-mode . "awk") (other . "gnu"))
    +

    Elisp syntax for a list is (a b c), and for a pair is (a . b). Pairs are +called “cons cells” in lisp terminology, and you access the first element with +the function car, the second with the function cdr (pronounced +“could-er”).

    + +

    So the value of c-default-style is a list containing 3 pairs; it’s used as a +lookup dictionary where java-mode, awk-mode and other are the keys, and +"java", "awk" and "gnu" are the values (in this case, names of styles to +use for each of the editing modes represented by the keys). These lookup +dictionaries are called “alists”.

    + +

    In your init file you could set c-default-style so that the default style for +other[4] is something other than "gnu".

    + +

    If you need to customize anything (including c-basic-offset and +indent-tabs-mode) to something different than any of the built-in styles, I +recommend you define your own style: Thus if you work on different projects +with different styles, you will be able to switch easily (with c-set-style). +The way we set c-basic-offset earlier will automatically create a style +called “user”.

    + +

    For help see “Configuration basics”, +“Customizing indentation”, +and “Sample .emacs file” +in the CC Mode Manual.

    +

    Binding keys

    +

    I often come across source code where one file expects tabs to equal 8 spaces, +and another file in the same directory—or even other lines within the same +file—want a tab to be 4 spaces. Let’s create a function that cycles +tab-width between 2, 4 and 8 spaces.

    + +

    (I found the variable tab-width by using apropos-variable to search for +“tab”.)

    +
    +
    (defun my-tab-width () "Cycle tab-width between values 2, 4, and 8." (interactive) (setq tab-width (cond ((eq tab-width 8) 2) ((eq tab-width 2) 4) (t 8))) (redraw-display))
    +
    +

    The cond expression evaluates to 2 if tab-width equals 8; to 4 if +tab-width equals 2; and to 8 otherwise. Look up cond and eq in the Info +manuals if you like.

    + +

    I’ve been naming all my functions “my-something” because elisp doesn’t have +separate namespaces for each mode or package; this way I can be sure my +functions won’t accidentally re-define an existing function that some editing +mode relies on.

    + +

    Now let’s bind our new function to a key sequence, so we can invoke it +conveniently. C-c followed by a letter is reserved for users to define, +so we’ll use C-c t:

    +
    +
    (global-set-key (kbd "C-c t") 'my-tab-width)
    +
    +

    The meaning of “global” in global-set-key should be obvious. If you’d like a +keybinding just for cc-mode, use define-key to add the binding to the +mode’s keymap:

    +
    (define-key c-mode-base-map (kbd "C-c t") 'my-tab-width)
    +

    I discovered c-mode-base-map with C-h v c-mode- TAB TAB. There is also a +c-mode-map which is just for the C language, rather than all languages +supported by cc-mode.

    +

    Associating file extensions with an editing mode

    +

    Say you want .h files to open in c++-mode rather than c-mode:

    + +
    +
    (add-to-list 'auto-mode-alist '("\\.h$" . c++-mode))
    +
    -U:--- *scratch* All L6 (Lisp Interaction)----------------------------------------
    +

    Regexp I-search: \.h$

    +
    +

    The trickiest part will be getting the regular expression right—elisp doesn’t +have syntax for a regexp literal, so you have to put it inside a string, and +then the string backslash-escaping makes the regexp rather awful. See +“Regexps” in the +Emacs manual.

    +

    Homework

    +

    If you have a spare 30 minutes read Steve Yegge’s Emergency Elisp.

    + +

    If you have a spare 6 months work through Structure and Interpretation of +Computer Programs, a famous textbook from MIT +that teaches important (and some quite advanced) programming concepts and +techniques using a simple dialect of Lisp called Scheme. If you like “mathy” +things like the Sieve of Eratosthenes for finding prime numbers, +Heron’s method +for calculating square roots, or estimating the value of pi using Monte Carlo +simulation, then you’ll love +this book.

    + +

    If you had a collection of .emacs customizations collected from the web +before you started this guide to Emacs, go over them now and try to understand +them thoroughly.

    + +

    In future, when you need a particular customization try to find the solution +from the manuals or the elisp sources before reaching for Google.

    + +

    Don’t try to modify the elisp files that are part of the Emacs distribution. +For one, it won’t be easy to merge your changes when you update Emacs to a +newer version. Second, the files are byte-compiled so you’d have to recompile +them. Third, even if you did it still wouldn’t help because the core elisp +functions are built into the Emacs image, +so you’d have to recompile the whole program. Instead, use the variables and +hooks provided for customization.

    + +

    Don’t pay attention to the Emacs manual whenever it tells you to use the “Easy +customization” +facility (in some help buffers it will say “you can customize this variable”). +It’s referring to a really awkward semi-graphical interface for setting Emacs +variables. Best to keep all your customizations in your own init file.

    +
    +

    [1]: + Try this:
    + lynx --dump http://www.gnu.org/software/emacs/manual/html_node/emacs/index.html |
    + sed '/^References/,$ d' | wc -w

    + +

    [2]: + I am joking. Lisp does have plenty of real problems.

    + +

    [3]: + Actually a “symbol”. Curiously, elisp functions and variables live in + separate namespaces, so you can define the variable +, set it to 2, and + still use + as a function in nonsensical statements like (+ 1 +). Try it:
    + (setq + 2)
    + (+ 1 +)

    + +

    [4]: + “Other” here only refers to languages supported by cc-mode, not any other + language.

    +
    + +

    +
    + + diff --git a/customize_colors.haml b/customize_colors.haml new file mode 100644 index 0000000..5d76818 --- /dev/null +++ b/customize_colors.haml @@ -0,0 +1,294 @@ +%h1 Fix that awful color scheme + +The default Emacs color scheme is affectionately known as "angry fruit salad". + +%h2#default Default font + +["Fonts" in the Emacs manual]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Fonts.html)[[1]] says: + +.do + Click on 'Set Default Font' in the 'Options' menu. To save this for future + sessions, click on 'Save Options' in the 'Options' menu.[[2]] + +"DejaVu Sans Mono" is a good choice (also known as "Bitstream Vera Sans Mono", +or "Menlo" on OS X 10.6+). Do choose a fixed-width font, even if you like +proportional fonts for programming. We'll cover Emacs's handling of +proportional fonts later. + +The "Save Options" menu command automatically modified your init file with the +new settings (and told you so in the echo area, now in the `*Messages*` buffer +if you missed it). + +There is a [known bug]( http://debbugs.gnu.org/cgi/bugreport.cgi?bug=2845) on +OS X that prevents "Save Options" from saving changes to the default font. OS X +users will have to use the `customize-face` mechanism I explain below, +specifying `default` as the face name. + + +%h2#colours Syntax highlighting colours + +[Font Lock mode]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Font-Lock.html) is the +minor mode responsible for syntax highlighting. You can read up on font-lock +mode if you want to figure out how Emacs decides what is a comment or a keyword +or a variable, or how to add your own keywords. + +But to merely change the colours: + +.do + Figure out the name of the face you want to change: `describe-face` (defaults + to the face at point) or `list-faces-display`. + +.do + `modify-face` will prompt you for a face and for each attribute to change. + Leave attributes as "unspecified" (the default) to inherit from the default + face. When it comes to the foreground and background colours, you can use the + predefined colours shown by tab-completion, or you can specify RGB hex values + like `#3f7f5f`. + +.do + `customize-face` brings up the "easy customization" interface I warned you + against in the previous chapter. Click the `State` button and select `Save + for Future Sessions`. (You can make changes here too, but I prefer + `modify-face` because it gives you tab-completion on the possible values for + each attribute.) + +Apart from `describe-face`, which I found in the Help menu, I found all these +in the Emacs manual under ["Faces"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Faces.html), +["Standard Faces"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Standard-Faces.html) +and ["Customizing Faces"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Face-Customization.html). + +Now let's figure out how to bypass the "easy customization" interface: + +.do + Visit your init file to see what "easy customization" added. If you already + had the file open, you may need `revert-buffer` to see the latest changes. + +.titlebar< + init.el +.window.default.new-comment-face< + :preserve + (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. + ) + (custom-set-faces + ;; custom-set-faces 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. + '(default ((t (:height 120 :family "Menlo")))) + '(font-lock-comment-face ((t (:foreground "#3f7f5f"))))) + + +You could configure the remaining font-lock faces by adding arguments to the +`custom-set-faces` form, but they might be overwritten if you use the easy +customization framework in future. Inspired by the name `custom-set-faces`, I +searched for functions beginning with `set-face` and found +`set-face-attribute`: + +.window< + :preserve + (set-face-attribute 'default nil :family "Menlo" :height 120) + (set-face-attribute 'font-lock-comment-face nil :foreground "#3f7f5f") + (set-face-attribute 'font-lock-string-face nil :foreground "#4f004f") + (set-face-attribute 'font-lock-constant-face nil :foreground "#4f004f") + (set-face-attribute 'font-lock-keyword-face nil :foreground "#00003f") + (set-face-attribute 'font-lock-builtin-face nil :foreground "#00003f") + (set-face-attribute 'font-lock-type-face nil :foreground "#000000") + (set-face-attribute 'font-lock-function-name-face nil + :foreground "#000000" :weight 'bold) + (set-face-attribute 'font-lock-variable-name-face nil + :foreground "#000000" :weight 'bold) + +The above settings produce a very conservative dark-on-white color scheme. I +like it because in many languages it highlights variable and function +*definitions* but not their uses. + +For all the face attribute names see ["Face Attributes"]( +http://www.gnu.org/software/emacs/manual/html_node/elisp/Face-Attributes.html) +in the Emacs Lisp manual. As to elisp syntax, [keyword symbols]( +http://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Type.html) like +`:foreground` and `:weight` are constants (that evaluate to themselves so you +don't have to quote them). + + +%h2#diff diff-mode + +While we're on colours, let's add some helpful colouring to `diff-mode` (which +we came across earlier, in the section on the `vc` version control +interface).[[4]] + +.do + .titlebar< + init.el + .window< + :preserve + (eval-after-load 'diff-mode + '(progn + (set-face-foreground 'diff-added "green4") + (set-face-foreground 'diff-removed "red3"))) + +`eval-after-load` does what it says: The first time `diff-mode` is loaded, +evaluate the following form. Emacs tends not to load every elisp package on +startup, but waits until you actually *use* `diff-mode` to load it. + +If you used `(set-face-foreground 'diff-added ...)` directly in your init file, +you would get the error "invalid face diff-added". You could explicitly load +`diff-mode` (using `require`) in your init file, but that would increase +Emacs's startup time—ever so slightly—every time you run Emacs in the +terminal for a quick job that won't even use `diff-mode`. + +`eval-after-load` takes a single form to evaluate, but we want to make two +function calls, so we wrap them in `progn` which merely evaluates a bunch of +forms sequentially. We quote it so that it doesn't get evaluated right now, +before even being passed to `eval-after-load`. + +.figure + .titlebar< + diff-mode.el.gz + .window< + :preserve +   + ;; provide the package + (provide 'diff-mode) + +The first argument to `eval-after-load` has to match the name that the package +`provide`s (this usually matches the name of the command to enable the mode, +but to double-check: `C-h f diff-mode`, follow the link to `diff-mode.el.gz`, +and find the `provide` form near the bottom). + + +%h2#themes Color themes + +Maybe you already have a favourite color theme, like [Zenburn]( +http://slinky.imukuppi.org/zenburnpage/) or [Solarized]( +http://ethanschoonover.com/solarized). There are Emacs implementations +([Zenburn]( https://github.com/bbatsov/zenburn-emacs), [Solarized]( +https://github.com/sellout/emacs-color-theme-solarized)) built on top of the +[`color-theme`]( http://www.nongnu.org/color-theme/) minor mode. `color-theme` +is a third-party package; it doesn't come with Emacs. + +Note that Emacs 24, which hasn't been officially released yet, provides a +built-in mechanism for defining multiple color themes. Nevertheless, I'll walk +you through the process of installing third-party packages using `color-theme` +and the Solarized theme as examples. + +/ TODO: Find a better example once Emacs 24 is released. + +Emacs 24 will also come with a package management system, so--as long as the +package's author has taken advantage of the new mechanism--the manual +installation procedure described below will not be necessary either. + + +%h2#packages Installing third-party elisp packages + +I'll assume that you are keeping your `~/.emacs.d` under version control using +git.[[3]] + +`color-theme`'s [installation instructions]( +http://www.nongnu.org/color-theme/#sec5) recommend using your package manager +(`apt-get install emacs-goodies-el` or `port install color-theme-mode.el`, +etc.) but I prefer to manage all my Emacs extensions in a single place. That +place is my `~/.emacs.d` directory, because I will eventually want an extension +that isn't provided by my system's package manager. + +.do + Download the [color-theme.6.6.0.tar.gz]( + http://download.savannah.nongnu.org/releases/color-theme/) and extract into + `~/.emacs.d`. + + `git add color-theme.6.6.0;` + `git commit -m "color-theme 6.6.0 from http://www.nongnu.org/color-theme/";` + +.do + Add the color-theme directory to your Emacs `load-path`: + -# + .titlebar< + init.el + .window< + :preserve + (add-to-list 'load-path "~/.emacs.d/color-theme-6.6.0") + +.do + And actually load it: + -# + .window< + :preserve + (require 'color-theme) + +Now you can select a theme with `color-theme-select`. + + +%h2#github Installing packages from github + +The Solarized color theme for Emacs is [available on github]( +https://github.com/sellout/emacs-color-theme-solarized). If you are keeping +your `~/.emacs.d` under version control using git, you can use git submodules +to simplify the management of such third-party packages. + +.do + `cd ~/.emacs.d;` + `git submodule add https://github.com/sellout/emacs-color-theme-solarized.git;` + +In future you can use `git pull` from `~/.emacs.d/emacs-color-theme-solarized/` +to get the latest changes. + +.do + Add `~/.emacs.d/emacs-color-theme-solarized/` to your Emacs `load-path`, and + require `'color-theme-solarized`, as you did for the `color-theme` package. + +Now you can activate the theme with `color-theme-solarized-light` (or `-dark`). + + +%h2#size Increasing the font size + +`C-x C-+`, `C-x C--`, and `C-x C-0`. See ["Temporary Face Changes"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Temporary-Face-Changes.html). + + +%h2#variable-pitch variable-pitch-mode + +You can toggle between fixed- and variable-width fonts in a particular buffer +with `variable-pitch-mode`. The face to customize is `variable-pitch`. + +To automatically enable `variable-pitch-mode`, add it to the hooks for all the +major modes where you want it to take effect. For example, to `text-mode-hook` +for editing plain text. + +If you really want it *everywhere*, I suppose there's no harm in setting the +`default` face to a proportional font. The great advantage of +`variable-pitch-mode`, though, is that it is so easy to switch between +proportional- and fixed-width fonts when you come across some ascii art or an +ascii table in a comment. + + +#footnotes + [[1]]: + I found this—after some dead ends—with Info's `i`ndex command, typing + "font", tab-completing, and trying whatever looked promising. I could just + have explored the Options menu instead, but—silly me—I had disabled the + menus because people on the internet said "real Emacs power users disable the + menus." That might make sense on a text terminal, where you can't click the + menu anyway, but on OS X, where there's only one menu bar at the top of the + screen, it's just silly. See the next footnote. + + [[2]]: + If you have disabled the menu, perhaps because you're using an init file + copied from someone else or something like the [Emacs starter kit]( + http://github.com/technomancy/emacs-starter-kit), you can re-enable it just + for this session with `M-x menu-bar-mode`. + + [[3]]: + `cd ~/.emacs.d; git init .; git add init.el; git status; git diff --cached;` + `git commit -m "My emacs init file."` + + [[4]]: + This customization—with several others—is borrowed from the [Emacs + Starter Kit]( https://github.com/technomancy/emacs-starter-kit). diff --git a/customize_colors.html b/customize_colors.html new file mode 100644 index 0000000..b007e00 --- /dev/null +++ b/customize_colors.html @@ -0,0 +1,265 @@ + + + + + + How to learn Emacs :: Fix that awful color scheme + + + + + +
    + +

    Fix that awful color scheme

    +

    The default Emacs color scheme is affectionately known as “angry fruit salad”.

    +

    Default font

    +

    “Fonts” in the Emacs manual[1] says:

    +
    +

    Click on ‘Set Default Font’ in the ‘Options’ menu. To save this for future + sessions, click on ‘Save Options’ in the ‘Options’ menu.[2]

    +
    +

    “DejaVu Sans Mono” is a good choice (also known as “Bitstream Vera Sans Mono”, +or “Menlo” on OS X 10.6+). Do choose a fixed-width font, even if you like +proportional fonts for programming. We’ll cover Emacs’s handling of +proportional fonts later.

    + +

    The “Save Options” menu command automatically modified your init file with the +new settings (and told you so in the echo area, now in the *Messages* buffer +if you missed it).

    + +

    There is a known bug on +OS X that prevents “Save Options” from saving changes to the default font. OS X +users will have to use the customize-face mechanism I explain below, +specifying default as the face name.

    +

    Syntax highlighting colours

    +

    Font Lock mode is the +minor mode responsible for syntax highlighting. You can read up on font-lock +mode if you want to figure out how Emacs decides what is a comment or a keyword +or a variable, or how to add your own keywords.

    + +

    But to merely change the colours:

    +
    +

    Figure out the name of the face you want to change: describe-face (defaults + to the face at point) or list-faces-display.

    +
    +
    +

    modify-face will prompt you for a face and for each attribute to change. + Leave attributes as “unspecified” (the default) to inherit from the default + face. When it comes to the foreground and background colours, you can use the + predefined colours shown by tab-completion, or you can specify RGB hex values + like #3f7f5f.

    +
    +
    +

    customize-face brings up the “easy customization” interface I warned you + against in the previous chapter. Click the State button and select Save for Future Sessions. (You can make changes here too, but I prefer + modify-face because it gives you tab-completion on the possible values for + each attribute.)

    +
    +

    Apart from describe-face, which I found in the Help menu, I found all these +in the Emacs manual under “Faces”, +“Standard Faces” +and “Customizing Faces”.

    + +

    Now let’s figure out how to bypass the “easy customization” interface:

    +
    +

    Visit your init file to see what “easy customization” added. If you already + had the file open, you may need revert-buffer to see the latest changes.

    +
    +

    init.el

    +
    (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. ) (custom-set-faces ;; custom-set-faces 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. '(default ((t (:height 120 :family "Menlo")))) '(font-lock-comment-face ((t (:foreground "#3f7f5f")))))
    +

    You could configure the remaining font-lock faces by adding arguments to the +custom-set-faces form, but they might be overwritten if you use the easy +customization framework in future. Inspired by the name custom-set-faces, I +searched for functions beginning with set-face and found +set-face-attribute:

    +
    (set-face-attribute 'default nil :family "Menlo" :height 120) (set-face-attribute 'font-lock-comment-face nil :foreground "#3f7f5f") (set-face-attribute 'font-lock-string-face nil :foreground "#4f004f") (set-face-attribute 'font-lock-constant-face nil :foreground "#4f004f") (set-face-attribute 'font-lock-keyword-face nil :foreground "#00003f") (set-face-attribute 'font-lock-builtin-face nil :foreground "#00003f") (set-face-attribute 'font-lock-type-face nil :foreground "#000000") (set-face-attribute 'font-lock-function-name-face nil :foreground "#000000" :weight 'bold) (set-face-attribute 'font-lock-variable-name-face nil :foreground "#000000" :weight 'bold)
    +

    The above settings produce a very conservative dark-on-white color scheme. I +like it because in many languages it highlights variable and function +definitions but not their uses.

    + +

    For all the face attribute names see “Face Attributes” +in the Emacs Lisp manual. As to elisp syntax, keyword symbols like +:foreground and :weight are constants (that evaluate to themselves so you +don’t have to quote them).

    +

    diff-mode

    +

    While we’re on colours, let’s add some helpful colouring to diff-mode (which +we came across earlier, in the section on the vc version control +interface).[4]

    +
    +

    init.el

    +
    (eval-after-load 'diff-mode '(progn (set-face-foreground 'diff-added "green4") (set-face-foreground 'diff-removed "red3")))
    +
    +

    eval-after-load does what it says: The first time diff-mode is loaded, +evaluate the following form. Emacs tends not to load every elisp package on +startup, but waits until you actually use diff-mode to load it.

    + +

    If you used (set-face-foreground 'diff-added ...) directly in your init file, +you would get the error “invalid face diff-added”. You could explicitly load +diff-mode (using require) in your init file, but that would increase +Emacs’s startup time—ever so slightly—every time you run Emacs in the +terminal for a quick job that won’t even use diff-mode.

    + +

    eval-after-load takes a single form to evaluate, but we want to make two +function calls, so we wrap them in progn which merely evaluates a bunch of +forms sequentially. We quote it so that it doesn’t get evaluated right now, +before even being passed to eval-after-load.

    +
    +

    diff-mode.el.gz

    +
      ;; provide the package (provide 'diff-mode)
    +
    +

    The first argument to eval-after-load has to match the name that the package +provides (this usually matches the name of the command to enable the mode, +but to double-check: C-h f diff-mode, follow the link to diff-mode.el.gz, +and find the provide form near the bottom).

    +

    Color themes

    +

    Maybe you already have a favourite color theme, like Zenburn or Solarized. There are Emacs implementations +(Zenburn, Solarized) built on top of the +color-theme minor mode. color-theme +is a third-party package; it doesn’t come with Emacs.

    + +

    Note that Emacs 24, which hasn’t been officially released yet, provides a +built-in mechanism for defining multiple color themes. Nevertheless, I’ll walk +you through the process of installing third-party packages using color-theme +and the Solarized theme as examples.

    + +

    Emacs 24 will also come with a package management system, so—as long as the +package’s author has taken advantage of the new mechanism—the manual +installation procedure described below will not be necessary either.

    +

    Installing third-party elisp packages

    +

    I’ll assume that you are keeping your ~/.emacs.d under version control using +git.[3]

    + +

    color-theme’s installation instructions recommend using your package manager +(apt-get install emacs-goodies-el or port install color-theme-mode.el, +etc.) but I prefer to manage all my Emacs extensions in a single place. That +place is my ~/.emacs.d directory, because I will eventually want an extension +that isn’t provided by my system’s package manager.

    +
    +

    Download the color-theme.6.6.0.tar.gz and extract into + ~/.emacs.d.

    + +

    git add color-theme.6.6.0;
    + git commit -m "color-theme 6.6.0 from http://www.nongnu.org/color-theme/";

    +
    +
    +

    Add the color-theme directory to your Emacs load-path:

    +

    init.el

    +
    (add-to-list 'load-path "~/.emacs.d/color-theme-6.6.0")
    +
    +
    +

    And actually load it:

    +
    (require 'color-theme)
    +
    +

    Now you can select a theme with color-theme-select.

    +

    Installing packages from github

    +

    The Solarized color theme for Emacs is available on github. If you are keeping +your ~/.emacs.d under version control using git, you can use git submodules +to simplify the management of such third-party packages.

    +
    +

    cd ~/.emacs.d;
    + git submodule add https://github.com/sellout/emacs-color-theme-solarized.git;

    +
    +

    In future you can use git pull from ~/.emacs.d/emacs-color-theme-solarized/ +to get the latest changes.

    +
    +

    Add ~/.emacs.d/emacs-color-theme-solarized/ to your Emacs load-path, and + require 'color-theme-solarized, as you did for the color-theme package.

    +
    +

    Now you can activate the theme with color-theme-solarized-light (or -dark).

    +

    Increasing the font size

    +

    C-x C-+, C-x C--, and C-x C-0. See “Temporary Face Changes”.

    +

    variable-pitch-mode

    +

    You can toggle between fixed- and variable-width fonts in a particular buffer +with variable-pitch-mode. The face to customize is variable-pitch.

    + +

    To automatically enable variable-pitch-mode, add it to the hooks for all the +major modes where you want it to take effect. For example, to text-mode-hook +for editing plain text.

    + +

    If you really want it everywhere, I suppose there’s no harm in setting the +default face to a proportional font. The great advantage of +variable-pitch-mode, though, is that it is so easy to switch between +proportional- and fixed-width fonts when you come across some ascii art or an +ascii table in a comment.

    +
    +

    [1]: + I found this—after some dead ends—with Info’s index command, typing + “font”, tab-completing, and trying whatever looked promising. I could just + have explored the Options menu instead, but—silly me—I had disabled the + menus because people on the internet said “real Emacs power users disable the + menus.” That might make sense on a text terminal, where you can’t click the + menu anyway, but on OS X, where there’s only one menu bar at the top of the + screen, it’s just silly. See the next footnote.

    + +

    [2]: + If you have disabled the menu, perhaps because you’re using an init file + copied from someone else or something like the Emacs starter kit, you can re-enable it just + for this session with M-x menu-bar-mode.

    + +

    [3]: + cd ~/.emacs.d; git init .; git add init.el; git status; git diff --cached;
    + git commit -m "My emacs init file."

    + +

    [4]: + This customization—with several others—is borrowed from the Emacs + Starter Kit.

    +
    + +

    +
    + + diff --git a/customize_general.haml b/customize_general.haml new file mode 100644 index 0000000..f6fe85c --- /dev/null +++ b/customize_general.haml @@ -0,0 +1,168 @@ +%h1 General customization + +%h2#ido ido-mode + +Other editors and IDEs have nice tree views of directories and files, as well +as tabs for switching between buffers. Emacs does have a rather ugly tree +view—`M-x speedbar` if you want to see *how* ugly—but the real Emacs answer +to navigating large projects is `ido-mode`. + +.figure + .titlebar< + init.el + .window< + :preserve + (ido-mode 1) +   + .modeline< + :preserve + -U:--- init.el All L17 (Emacs-Lisp)---------------------------------------- + .echoarea< + Find file: \.../readline/ex{examples/ | histexpand.c | text.c} + +`ido-mode` remaps the keybindings for `find-file` and `switch-to-buffer` to +more powerful versions of the same. You'll only need to type a few letters of +the file or buffer name (not necessarily matching the beginning of the name, +and not necessarily adjacent letters). A list of matches, in most-recently-used +order, is displayed in the minibuffer; `` and `` (or `C-s` and +`C-r`) navigate amongst the matches. If nothing matches, after a brief +(and configurable) pause `ido` can search previously-used directories. + +Because `RET` opens the first matching file, to actually open a directory +you'll have to use `C-f` (at the `ido-find-file` prompt) to drop back into +normal `find-file`. + +`ido` ships with Emacs but isn't present at all in the manual; read the online +help for the `ido-find-file` command. For more details and configuration +instructions, use `C-h f ido-mode` to find its elisp implementation, and read +the long comment at the top of the elisp file. + +Emacs users tend to leave buffers open when they have finished with them, and +after a while have hundreds of buffers open so `ido-switch-buffer` effectively +becomes "find file in project". + +To save your list of open files between invocations of Emacs, or to manage +separate sets of open files (if you're working on several projects in +parallel), see ["Saving Emacs Sessions"]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Saving-Emacs-Sessions.html) +in the Emacs manual. + + +%h2#minimalism Minimalism + +To make the most of your screen space, consider disabling the toolbar and +scrollbars: + +.titlebar< + init.el +.window< + :preserve + (tool-bar-mode -1) + (scroll-bar-mode -1) + +Similarly, you can disable the menu bar with `(menu-bar-mode -1)`, though I +find the menu bar useful for discovering Emacs features; major and minor modes +often add their own menu to the menu bar. As previously noted, you certainly +shouldn't disable the menu bar on OS X; if you'd like to share your Emacs init +file among several environments you could conditionally disable `menu-bar-mode` +based on the value of variables `system-type` and `window-system`. + +Some commands like `revert-buffer` force you to confirm by typing `yes`; it +would be nice to just type `y`. If you look at the definition of +`revert-buffer` you'll find it calls `yes-or-no-p`, which we can redefine to +call `y-or-n-p` instead: + +.window< + :preserve + (defun yes-or-no-p (prompt) + (y-or-n-p prompt)) + +Or more simply: + +.window< + :preserve + (defalias 'yes-or-no-p 'y-or-n-p) + +Another thing everyone does the second they install Emacs is to prevent the +creation of a "`~`"-suffixed backup file on every save: + +.window< + :preserve + (setq make-backup-files nil) + +Rely on your version control system for backups instead. + + +%h2#elisp Navigating Emacs Lisp + +In the last couple of chapters I have encouraged you to discover Emacs +functionality by studying the elisp code directly. To make the job easier we +already saw `show-paren-mode` and `eldoc-mode`; let's enable them globally +because they're useful in other programming languages too. + +.window< + :preserve + (show-paren-mode 1) + (eldoc-mode 1) + +We'll also re-bind `M-.` from its default `find-tag` to +`find-function-at-point`, but only for elisp files, for which you don't need a +tags table because Emacs already knows all about every elisp function it has +loaded. + +.window< + :preserve + (define-key emacs-lisp-mode-map + (kbd "M-.") 'find-function-at-point) + +If you plan on *writing* a lot of Lisp, `paredit-mode` is great for always +keeping your parentheses balanced, and for moving whole forms around when +refactoring—but it does take some getting used to. + + +%h2#shell shell + +If you ever tried to run a program like git under `M-x shell`, you will have +come across the warning "terminal is not fully functional" followed by unusable +behavior. This is because git sends its output through a pager (probably +`less`), which requires a real terminal emulator. + +Setting the `PAGER` environment variable to `/bin/cat` (but only inside Emacs) +solves this problem: + +.titlebar< + init.el +.window< + :preserve + (setenv "PAGER" "/bin/cat") + +This also allows you to use `git grep` from `M-x grep`. +-# +Make sure you don't override `PAGER` in your `~/.gitconfig` file or the +`GIT_PAGER` environment variable (and `MANPAGER` for the `man` program, etc). + +If you need to make customizations in your `~/.bashrc` file (or the +corresponding file for your shell of choice) you can test for the environment +variable `INSIDE_EMACS`. To configure which shell Emacs uses, see [the manual]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Interactive-Shell.html). + + +%h2#other Other ideas + +Other customizations you might like to make are covered by the Emacs manual: + +* [Minor Modes]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Minor-Modes.html). +* [Making Buffer Names Unique]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Uniquify.html). +* [Displaying The Cursor]( +http://www.gnu.org/software/emacs/manual/html_node/emacs/Cursor-Display.html) +(in particular `global-hl-line-mode`). + +For further inspiration you might want to look at other people's init files, +widely available on the [Emacs wiki]( +http://www.emacswiki.org/emacs/CategoryDotEmacs) and on the [internet at +large]( http://sites.google.com/site/steveyegge2/my-dot-emacs-file). Some of +the customizations I have presented here came from the [Emacs Starter Kit]( +http://github.com/technomancy/emacs-starter-kit), a collection of elisp files +to provide "a more pleasant set of defaults than you get normally with Emacs". diff --git a/customize_general.html b/customize_general.html new file mode 100644 index 0000000..6d9afe5 --- /dev/null +++ b/customize_general.html @@ -0,0 +1,175 @@ + + + + + + How to learn Emacs :: General customization + + + + + +
    + +

    General customization

    +

    ido-mode

    +

    Other editors and IDEs have nice tree views of directories and files, as well +as tabs for switching between buffers. Emacs does have a rather ugly tree +view—M-x speedbar if you want to see how ugly—but the real Emacs answer +to navigating large projects is ido-mode.

    +
    +

    init.el

    +
    (ido-mode 1)  
    +
    -U:--- init.el All L17 (Emacs-Lisp)----------------------------------------
    +

    Find file: .../readline/ex{examples/ | histexpand.c | text.c}

    +
    +

    ido-mode remaps the keybindings for find-file and switch-to-buffer to +more powerful versions of the same. You’ll only need to type a few letters of +the file or buffer name (not necessarily matching the beginning of the name, +and not necessarily adjacent letters). A list of matches, in most-recently-used +order, is displayed in the minibuffer; <right> and <left> (or C-s and +C-r) navigate amongst the matches. If nothing matches, after a brief +(and configurable) pause ido can search previously-used directories.

    + +

    Because RET opens the first matching file, to actually open a directory +you’ll have to use C-f (at the ido-find-file prompt) to drop back into +normal find-file.

    + +

    ido ships with Emacs but isn’t present at all in the manual; read the online +help for the ido-find-file command. For more details and configuration +instructions, use C-h f ido-mode to find its elisp implementation, and read +the long comment at the top of the elisp file.

    + +

    Emacs users tend to leave buffers open when they have finished with them, and +after a while have hundreds of buffers open so ido-switch-buffer effectively +becomes “find file in project”.

    + +

    To save your list of open files between invocations of Emacs, or to manage +separate sets of open files (if you’re working on several projects in +parallel), see “Saving Emacs Sessions” +in the Emacs manual.

    +

    Minimalism

    +

    To make the most of your screen space, consider disabling the toolbar and +scrollbars:

    +

    init.el

    +
    (tool-bar-mode -1) (scroll-bar-mode -1)
    +

    Similarly, you can disable the menu bar with (menu-bar-mode -1), though I +find the menu bar useful for discovering Emacs features; major and minor modes +often add their own menu to the menu bar. As previously noted, you certainly +shouldn’t disable the menu bar on OS X; if you’d like to share your Emacs init +file among several environments you could conditionally disable menu-bar-mode +based on the value of variables system-type and window-system.

    + +

    Some commands like revert-buffer force you to confirm by typing yes; it +would be nice to just type y. If you look at the definition of +revert-buffer you’ll find it calls yes-or-no-p, which we can redefine to +call y-or-n-p instead:

    +
    (defun yes-or-no-p (prompt) (y-or-n-p prompt))
    +

    Or more simply:

    +
    (defalias 'yes-or-no-p 'y-or-n-p)
    +

    Another thing everyone does the second they install Emacs is to prevent the +creation of a “~”-suffixed backup file on every save:

    +
    (setq make-backup-files nil)
    +

    Rely on your version control system for backups instead.

    +

    Navigating Emacs Lisp

    +

    In the last couple of chapters I have encouraged you to discover Emacs +functionality by studying the elisp code directly. To make the job easier we +already saw show-paren-mode and eldoc-mode; let’s enable them globally +because they’re useful in other programming languages too.

    +
    (show-paren-mode 1) (eldoc-mode 1)
    +

    We’ll also re-bind M-. from its default find-tag to +find-function-at-point, but only for elisp files, for which you don’t need a +tags table because Emacs already knows all about every elisp function it has +loaded.

    +
    (define-key emacs-lisp-mode-map (kbd "M-.") 'find-function-at-point)
    +

    If you plan on writing a lot of Lisp, paredit-mode is great for always +keeping your parentheses balanced, and for moving whole forms around when +refactoring—but it does take some getting used to.

    +

    shell

    +

    If you ever tried to run a program like git under M-x shell, you will have +come across the warning “terminal is not fully functional” followed by unusable +behavior. This is because git sends its output through a pager (probably +less), which requires a real terminal emulator.

    + +

    Setting the PAGER environment variable to /bin/cat (but only inside Emacs) +solves this problem:

    +

    init.el

    +
    (setenv "PAGER" "/bin/cat")
    +

    This also allows you to use git grep from M-x grep.

    +

    Make sure you don’t override PAGER in your ~/.gitconfig file or the +GIT_PAGER environment variable (and MANPAGER for the man program, etc).

    + +

    If you need to make customizations in your ~/.bashrc file (or the +corresponding file for your shell of choice) you can test for the environment +variable INSIDE_EMACS. To configure which shell Emacs uses, see the manual.

    +

    Other ideas

    +

    Other customizations you might like to make are covered by the Emacs manual:

    + + + + +

    For further inspiration you might want to look at other people’s init files, +widely available on the Emacs wiki and on the internet at +large. Some of +the customizations I have presented here came from the Emacs Starter Kit, a collection of elisp files +to provide “a more pleasant set of defaults than you get normally with Emacs”.

    + +

    +
    + + diff --git a/emacs.css b/emacs.css new file mode 100644 index 0000000..ced2b05 --- /dev/null +++ b/emacs.css @@ -0,0 +1,186 @@ +/* Start with a blank slate */ +html, body, div, p, ul, ol, h1, h2, h3 { margin: 0; padding: 0; border: 0; } + +/* === Layout === */ + +#content2 { max-width: 700px; margin: 50px 0 0 400px; } +#sidebar { position: absolute; left: 50px; top: 50px; width: 300px; } +.figure { float: right; clear: both; margin: 6px 0 18px 10px; } +.figure.center { float: none; text-align: center; } +.figure.first { margin-top: 18pt; } +#footnotes { margin-top: 3em; } + +/* === Smartphones === */ +/* (only tested on iPhone) */ +@media only screen +and (max-device-width: 480px) { + #content2 { max-width: 100%; margin: 1em; } + #sidebar { position: static; width: 100%; } + #toc li ul { display: none; } +} + +/* === Typography === */ + +body { font-family: verdana, helvetica, sans-serif; + font-size: 12pt; line-height: 1.5; } + +h1, h2, h3 { font-family: georgia, "times new roman", serif; clear: both; } +h1 { font-size: 18pt; line-height: 1; margin-bottom: 1em; } +h2 { font-size: 14pt; line-height: 1.28; margin: 1.28em 0; } +h3 { font-size: 12pt; line-height: 1.5; margin: 1.5em 0; } + +#sidebar, +#sidebar a { color: #888; } +#sidebar { font-size: 10pt; line-height: 1.8; } +#info h1 { font-size: 12pt; line-height: 1.5; } +#info p { margin: 0; } +#toc { margin-top: 1.5em; } +#toc ul { list-style: none; } +#toc p { margin: .5em 0 0 0; font-style: italic; } +#toc li.current { font-weight: bold; } +#toc li.current ul { list-style: disc; font-weight: normal; margin-left: 3em; } + +p { margin: 1.5em 0; } + +a { color: #00007f; text-decoration: none; } +a:hover { text-decoration: underline; } +a.glossary { color: inherit; text-decoration: none; } +a.glossary:hover, +#first-key-sequence a.glossary { border-bottom: 1px dashed #888; } + +li { margin-left: 1.2em; } +#toc li { margin: 0; } + +.figure p { font-size: 8pt; line-height: 1; font-weight: bold; + margin: 0; text-align: center; } + +.footnote { font-size: 10pt; vertical-align: super; line-height: 1; + font-family: verdana, helvetica, sans-serif; font-weight: normal; } +#footnotes { font-size: 10pt; } +#footnotes .footnote { vertical-align: baseline; } + +.next { text-align: right; clear: both; } +.next a { color: #888; } + +/* === Instructions for the reader === */ +.do { margin: 1.5em 0; padding: 0 1ex 0 35px; + background: url("images/do.png") no-repeat 0 8px; } +.do p { margin: .5em 0; } + +/* === Draw an emacs frame === */ +.titlebar, +.window, +.modeline, +.echoarea { position: relative; width: 559px; margin: 0 auto; + background-repeat: no-repeat; overflow: hidden; + font-family: Menlo, "DejaVu Sans Mono", "Bitstream Vera Sans Mono", monospace; + font-size: 12px; line-height: 1.25; white-space: pre; } +.titlebar { height: 23px; margin-top: 18pt; + background-image: url("images/titlebar.png"); + text-align: center; } +.window { width: 535px; padding: 0 12px; + background-image: url("images/window.png"); + background-repeat: repeat-y; } +.modeline { width: 554px; padding-left: 5px; height: 15px; + background-image: url("images/modeline.png"); } +.echoarea { height: 18px; margin-bottom: 18pt; + background-image: url("images/echoarea.png"); } +.titlebar p { margin: 5px 0 0 0; } +.window p { text-align: left; /* Over-rides text-align:center when inside .figure */ + margin: 0; } /* margin is provided by .window's padding, to + support non-

    content generated by haml's + :preserve filter. */ +.modeline { text-align: left; } +.echoarea p { text-align: left; margin: 1px 12px 0; } + +/* === Half-width emacs frame when shown as a floated figure === */ +.figure .window, +.figure .modeline, +.figure .echoarea { text-align: left; } +.figure .titlebar, +.figure .echoarea { width: 260px; } +.figure .window { width: 236px; } +.figure .modeline { width: 255px; } +.figure .titlebar { margin-top: 0; } +.figure .echoarea { margin-bottom: 4pt; } +.figure .titlebar p, +.figure .window p, +.figure .echoarea p { font-weight: normal; line-height: 1.25; } +.figure .titlebar p { margin-left: 150px; } + +/* === Full-width emacs frame when shown as a floated figure === */ +.figure.wide .titlebar, +.figure.wide .echoarea { width: 320px; } +.figure.wide .window { width: 296px; } +.figure.wide .modeline { width: 315px; } + +/* === Font-lock colours === */ +.window.default .comment { color: #b22; } +.window.default .builtin { color: #738; } +.window.default .keyword { color: #707; } +.window.default .type { color: #282; } +.window.default .variable-name { color: #952; } +.window.default .function-name { color: #00f; } +.window.default .string { color: #825; } +.window.default .doc { color: #825; } +.window .comment, +.window.new-comment-face .comment { color: #3f7f5f; } +.window .builtin { color: #004; } +.window .keyword { color: #004; } +.window .type { color: #000; } +.window .variable-name { color: #000; font-weight: bold; } +.window .function-name { color: #000; font-weight: bold; } +.window .string { color: #505; } +.window .doc { color: #505; } +.window .region { background-color: #ed9; } +.window .hl-line { background-color: #beb; } +.window .cursor, +.echoarea .cursor { background-color: #ccc; } +.modeline .error { color: #f00; font-weight: bold; } +.echoarea .prompt { color: #24d; } +.echoarea .ido-first-match { font-weight: bold; } +.window .bold { font-weight: bold; } +.window .button { text-decoration: underline; } +.window .underline { text-decoration: underline; } +.window .comint-highlight-prompt { color: #008; } +.window .compilation-error { color: #f00; font-weight: bold; } +.window .compilation-line-number { color: #952; } +.window .diff-header, +.window .diff-hunk-header, +.window .diff-function { background-color: #ccc; } +.window .diff-file-header { background-color: #bbb; font-weight: bold; } +.window .diff-context { color: #777; } +.window .vc-annotate-face-3f3fff { color: #44f; background-color: #000; } +.window .vc-annotate-face-56ff3f { color: #5f4; background-color: #000; } + +/* === why.html === */ +#vri-examples { float: right; width: 300px; margin: 3pt 0 1em 2em; } +#nile, +#tcpip-parser { white-space: pre; + overflow-x: auto; overflow-y: hidden; + font-family: Menlo, "Bitstream Vera Sans Mono", monospace; + font-size: 10pt; line-height: 1; } +#tcpip-parser { font-size: 9pt; letter-spacing: -1pt; text-align: center; } +#vri-examples p { white-space: normal; font-family: verdana, helvetica, sans-serif; + font-size: 9pt; line-height: 1; font-weight: bold; + text-align: center; margin-top: 0; } + +/* === tutorial.html === */ +.modeline img.mouse { position: absolute; left: 400px; top: 0px; } +td { vertical-align: bottom; padding-right: 1ex; } +td:first-child { vertical-align: top; text-align: right; } +td code { outline: 1px dotted #ccc; } + +/* === basic_c.html === */ +.figure#minibuffer .echoarea, +.notethis { border: #a00 2px solid; } +.modeline .notethis { font-size: 80%; } /* so that top & bottom borders are visible */ + +/* === glossary.html === */ +dt { margin-top: 1.5em; font-weight: bold; } +dd { margin-left: 0; } +dd p { margin-top: 0; } +dl a { color: #888; font-size: 10pt; line-height: 1.8; } +dl td { vertical-align: top; } +dl td:first-child { white-space: nowrap; } +#glossary-frames { margin-top: -18pt; } diff --git a/ergonomics.haml b/ergonomics.haml new file mode 100644 index 0000000..389959e --- /dev/null +++ b/ergonomics.haml @@ -0,0 +1,57 @@ +%h1 Ergonomics + +Most of the following advice relies heavily on the Control key, so bind your +Caps Lock to Control. This is easy to do on [OS X](osx.html) and Linux, and on +Windows involves [changing a registry entry]( +http://sites.google.com/site/steveyegge2/effective-emacs#item1). + +You may choose to swap the left Control key with Caps Lock, or just to make +them both Control keys — in Emacs and bash you can uppercase a word with `M-u` +(upcase-word) and the region with `C-x C-u` (upcase-region). + +Now you will find the navigation keys like `C-f`, `C-b`, `C-n` and `C-p` much +closer to your home row position than the arrow keys. Learn to navigate in +larger jumps with `C-a` and `C-e` (beggining and end of line), `M-f` and `M-b` +(forward and back by one word), `C-M-f` and `C-M-b` (forward and back by one +block of parentheses or braces), and `M-a` and `M-e` (beginning and end of a +sentence or expression). + +If you need to move to a far-away position it is often faster to get there by +searching with `C-s`. + +For fixing typos, `C-t` (transpose-chars) comes in handy. + +Instead of reaching for the backspace key, consider rebinding `C-h` to +backspace (as in most shells), and `C-w` to backward-kill-word (also as in most +shells; in Emacs it is normally bound to `C-backspace`). `C-d` deletes the +*next* character, and you don't even need to bind it yourself. + +Rebinding `C-h` is a bit tricky, because after making your binding you might +activate some major or minor mode that binds a new sequence beginning with +`C-h`, undoing your own binding. You can use `key-translation-map` to make +`C-h` appear to Emacs as the backspace key, ignoring all other `C-h` bindings +now or in future: + +.window< + :preserve + (define-key key-translation-map (kbd "C-h") (kbd "<DEL>")) + +You will still be able to access the help commands with `F1 f`, `F1 v`, `F1 S`, +etc. + +As for `C-w`, you could define your own function that keeps the default +behavior when the region is active, and does `backward-kill-word` when not: + +.window< + :preserve + (defun kill-region-or-backward-kill-word (&optional arg region) + "`kill-region' if the region is active, otherwise `backward-kill-word'" + (interactive + (list (prefix-numeric-value current-prefix-arg) (use-region-p))) + (if region + (kill-region (region-beginning) (region-end)) + (backward-kill-word arg))) + (global-set-key (kbd "C-w") 'kill-region-or-backward-kill-word) + +Some of these tips were inspired by Steve Yegge's [Effective Emacs]( +http://sites.google.com/site/steveyegge2/effective-emacs) article. Read it. diff --git a/ergonomics.html b/ergonomics.html new file mode 100644 index 0000000..88d8107 --- /dev/null +++ b/ergonomics.html @@ -0,0 +1,99 @@ + + + + + + How to learn Emacs :: Ergonomics + + + + +

    +
    + +

    Ergonomics

    +

    Most of the following advice relies heavily on the Control key, so bind your +Caps Lock to Control. This is easy to do on OS X and Linux, and on +Windows involves changing a registry entry.

    + +

    You may choose to swap the left Control key with Caps Lock, or just to make +them both Control keys — in Emacs and bash you can uppercase a word with M-u +(upcase-word) and the region with C-x C-u (upcase-region).

    + +

    Now you will find the navigation keys like C-f, C-b, C-n and C-p much +closer to your home row position than the arrow keys. Learn to navigate in +larger jumps with C-a and C-e (beggining and end of line), M-f and M-b +(forward and back by one word), C-M-f and C-M-b (forward and back by one +block of parentheses or braces), and M-a and M-e (beginning and end of a +sentence or expression).

    + +

    If you need to move to a far-away position it is often faster to get there by +searching with C-s.

    + +

    For fixing typos, C-t (transpose-chars) comes in handy.

    + +

    Instead of reaching for the backspace key, consider rebinding C-h to +backspace (as in most shells), and C-w to backward-kill-word (also as in most +shells; in Emacs it is normally bound to C-backspace). C-d deletes the +next character, and you don’t even need to bind it yourself.

    + +

    Rebinding C-h is a bit tricky, because after making your binding you might +activate some major or minor mode that binds a new sequence beginning with +C-h, undoing your own binding. You can use key-translation-map to make +C-h appear to Emacs as the backspace key, ignoring all other C-h bindings +now or in future:

    +
    (define-key key-translation-map (kbd "C-h") (kbd "<DEL>"))
    +

    You will still be able to access the help commands with F1 f, F1 v, F1 S, +etc.

    + +

    As for C-w, you could define your own function that keeps the default +behavior when the region is active, and does backward-kill-word when not:

    +
    (defun kill-region-or-backward-kill-word (&optional arg region) "`kill-region' if the region is active, otherwise `backward-kill-word'" (interactive (list (prefix-numeric-value current-prefix-arg) (use-region-p))) (if region (kill-region (region-beginning) (region-end)) (backward-kill-word arg))) (global-set-key (kbd "C-w") 'kill-region-or-backward-kill-word)
    +

    Some of these tips were inspired by Steve Yegge’s Effective Emacs article. Read it.

    + +

    +
    + + diff --git a/glossary.haml b/glossary.haml new file mode 100644 index 0000000..6d5318e --- /dev/null +++ b/glossary.haml @@ -0,0 +1,109 @@ +%h1 Glossary + +%dl + %dt#keys Emacs key names: + %dd + | `C-x` | means Control-x. | + | `C-x C-s` | means Control-x, then Control-s. | + | `C-x k` | means Control-x, then k on its own (without Control). | + | `M-x` | means Alt-x (Alt is called Option on some Mac keyboards). + | The `M` stands for “Meta” which is presumably what the Alt + | key was called in the 70s. | + | `M-x help` | means press Alt-x, then type `help`, then press return. | + | `C-M-x` | means Control-Alt-x | + | `S-x` | means Shift-x | + | `s-x` | means Command-x (the ⌘ Command key on Mac keyboards). + | The `s` stands for “Super”, from the days when keyboards + | had Meta, Super, and Hyper keys. | + | `<RET>` | means the Return or Enter key. | + | `<SPC>` | means the Space bar. | + | `<DEL>` | means Backspace + | (not to be confused with the delete-forward key) | + + %dt#frames Frames: + %dd + .figure#glossary-frames + .titlebar< + rl.c + .window.default< + :preserve + int + main (argc, argv) + int argc; + char **argv; + {  + .modeline< + :preserve + --:--- rl.c 59% L83 Git-master (C/l Abbrev)----------------------------------- + .window.default< + :preserve + make -k + rm -f rl.o + gcc -DHAVE_CONFIG_H -DREADLINE_LIBRARY -DRL_LIBRARY_VERSION='"6.2"' -I. -I.. -I.. -g -O -c rl.c + rl.c: In function ‘main’: + .modeline< + :preserve + -U:%*- *compilation* Top L1 (Compilation:exit [2])----------------------------------- + .echoarea< + Compilation exited abnormally with code 2 + %p One frame, two windows
    (each with its own modeline) + + + What Emacs calls your window-manager's windows. [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Frames.html) + + %dt#windows Windows: + %dd + Subdivisions inside a Frame. [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Windows.html) + + %dt#buffers Buffers: + %dd + The text you are editing. The difference between a buffer and a file is + that their contents may differ until you save your changes; and some + buffers aren't backed by files at all (e.g. a `*compilation*` or `*Help*` + buffer). [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Buffers.html) + + %dt#modeline Mode line: + %dd + Describes the buffer in the window above the modeline. Hover your mouse + over each indicator in the modeline for a description. [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Mode-Line.html) + + %dt#echoarea Echo area: + %dd + The line at the very bottom of the frame, used to display small informative + messages. [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Echo-Area.html) + + %dt#minibuffer Minibuffer: + %dd + The echo area when it is prompting for user input. [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer.html) + + %dt#region The point, the mark and the region: + %dd + The point is where the cursor is. Set the mark with `C-`, move the + point, and now the region is the area between point and mark. [[Emacs + manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Mark.html) + + %dt#killing Killing and yanking: + %dd + Killing = cutting. Yanking = pasting (sorry vi users!). [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Killing.html) + + %dt#majormode Major mode or Editing mode: + %dd + A major mode is a customization of Emacs for editing text of a particular + sort (e.g. a particular programming language). A buffer can only have one + major mode active at a time. [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Major-Modes.html) + + %dt#minormode Minor mode: + %dd + Multiple minor modes can be enabled at once; they add functionality ranging + from syntax highlighting to automatic spell-checking to modifying the + behavior of common Emacs commands. [[Emacs manual]]( + http://www.gnu.org/software/emacs/manual/html_node/emacs/Minor-Modes.html) diff --git a/glossary.html b/glossary.html new file mode 100644 index 0000000..1efc229 --- /dev/null +++ b/glossary.html @@ -0,0 +1,145 @@ + + + + + + How to learn Emacs :: Glossary + + + + + +
    + +

    Glossary

    +
    +
    Emacs key names:
    +
    + + + + + + + + + + + + +
    C-x means Control-x.
    C-x C-s means Control-x, then Control-s.
    C-x k means Control-x, then k on its own (without Control).
    M-x means Alt-x (Alt is called Option on some Mac keyboards).
    + The M stands for “Meta” which is presumably what the Alt + key was called in the 70s.
    M-x helpmeans press Alt-x, then type help, then press return.
    C-M-x means Control-Alt-x
    S-x means Shift-x
    s-x means Command-x (the ⌘ Command key on Mac keyboards).
    + The s stands for “Super”, from the days when keyboards + had Meta, Super, and Hyper keys.
    <RET>means the Return or Enter key.
    <SPC>means the Space bar.
    <DEL>means Backspace
    + (not to be confused with the delete-forward key)
    +
    +
    Frames:
    +
    +
    +

    rl.c

    +
    int main (argc, argv) int argc; char **argv; { 
    +
    --:--- rl.c 59% L83 Git-master (C/l Abbrev)-----------------------------------
    +
    make -k rm -f rl.o gcc -DHAVE_CONFIG_H -DREADLINE_LIBRARY -DRL_LIBRARY_VERSION='"6.2"' -I. -I.. -I.. -g -O -c rl.c rl.c: In function ‘main’:
    +
    -U:%*- *compilation* Top L1 (Compilation:exit [2])-----------------------------------
    +

    Compilation exited abnormally with code 2

    +

    One frame, two windows
    (each with its own modeline)

    + +
    +

    What Emacs calls your window-manager’s windows. [Emacs manual]

    +
    +
    Windows:
    +
    +

    Subdivisions inside a Frame. [Emacs manual]

    +
    +
    Buffers:
    +
    +

    The text you are editing. The difference between a buffer and a file is + that their contents may differ until you save your changes; and some + buffers aren’t backed by files at all (e.g. a *compilation* or *Help* + buffer). [Emacs manual]

    +
    +
    Mode line:
    +
    +

    Describes the buffer in the window above the modeline. Hover your mouse + over each indicator in the modeline for a description. [Emacs manual]

    +
    +
    Echo area:
    +
    +

    The line at the very bottom of the frame, used to display small informative + messages. [Emacs manual]

    +
    +
    Minibuffer:
    +
    +

    The echo area when it is prompting for user input. [Emacs manual]

    +
    +
    The point, the mark and the region:
    +
    +

    The point is where the cursor is. Set the mark with C-<SPC>, move the + point, and now the region is the area between point and mark. [Emacs + manual]

    +
    +
    Killing and yanking:
    +
    +

    Killing = cutting. Yanking = pasting (sorry vi users!). [Emacs manual]

    +
    +
    Major mode or Editing mode:
    +
    +

    A major mode is a customization of Emacs for editing text of a particular + sort (e.g. a particular programming language). A buffer can only have one + major mode active at a time. [Emacs manual]

    +
    +
    Minor mode:
    +
    +

    Multiple minor modes can be enabled at once; they add functionality ranging + from syntax highlighting to automatic spell-checking to modifying the + behavior of common Emacs commands. [Emacs manual]

    +
    +
    + + +
    + + diff --git a/haml b/haml new file mode 160000 index 0000000..c91e8be --- /dev/null +++ b/haml @@ -0,0 +1 @@ +Subproject commit c91e8bed4f0fe50f165cbfd986a9aac0fd00e4b5 diff --git a/howtolearn.haml b/howtolearn.haml new file mode 100644 index 0000000..e0d88bc --- /dev/null +++ b/howtolearn.haml @@ -0,0 +1,21 @@ +-# This file will go inside a
    so feel free to use h1 etc. + +%h1 About this guide to Emacs + +This guide is aimed at computer programmers who want to master the GNU Emacs +text editor. + +It has been said that the Emacs learning curve is not so much steep as *long*. +While the initial learning curve is indeed much steeper than other editors, +that is a hump you'll get over fairly soon. This guide does start from the +basics, but its real aim is to help you reach the next level —programming the +behavior of Emacs itself— in months rather than years. The focus is on +self-driven discovery by leveraging the Emacs built-in help, debugging +facilities, and source code. + +What I need from you is commitment (a couple of dedicated hours of study per +week, and to use Emacs as your day-to-day editor) and patience (be willing to +give up your favourite IDE's features, at least for a month or two). + +If you're not sure it's worth the trouble, please read the next section—and +*then* by all means sniff in contempt. diff --git a/howtolearn.html b/howtolearn.html new file mode 100644 index 0000000..9abe417 --- /dev/null +++ b/howtolearn.html @@ -0,0 +1,78 @@ + + + + + + How to learn Emacs :: About this guide to Emacs + + + + + +
    + +

    About this guide to Emacs

    +

    This guide is aimed at computer programmers who want to master the GNU Emacs +text editor.

    + +

    It has been said that the Emacs learning curve is not so much steep as long. +While the initial learning curve is indeed much steeper than other editors, +that is a hump you’ll get over fairly soon. This guide does start from the +basics, but its real aim is to help you reach the next level —programming the +behavior of Emacs itself— in months rather than years. The focus is on +self-driven discovery by leveraging the Emacs built-in help, debugging +facilities, and source code.

    + +

    What I need from you is commitment (a couple of dedicated hours of study per +week, and to use Emacs as your day-to-day editor) and patience (be willing to +give up your favourite IDE’s features, at least for a month or two).

    + +

    If you’re not sure it’s worth the trouble, please read the next section—and +then by all means sniff in contempt.

    + +

    +
    + + diff --git a/images/do.png b/images/do.png new file mode 100644 index 0000000..44a8326 Binary files /dev/null and b/images/do.png differ diff --git a/images/echoarea.png b/images/echoarea.png new file mode 100644 index 0000000..9a693be Binary files /dev/null and b/images/echoarea.png differ diff --git a/images/filemenu.png b/images/filemenu.png new file mode 100644 index 0000000..873d27a Binary files /dev/null and b/images/filemenu.png differ diff --git a/images/modeline.png b/images/modeline.png new file mode 100644 index 0000000..7a7ece1 Binary files /dev/null and b/images/modeline.png differ diff --git a/images/mouse.png b/images/mouse.png new file mode 100644 index 0000000..41a858e Binary files /dev/null and b/images/mouse.png differ diff --git a/images/titlebar.png b/images/titlebar.png new file mode 100644 index 0000000..37998e9 Binary files /dev/null and b/images/titlebar.png differ diff --git a/images/window.png b/images/window.png new file mode 100644 index 0000000..e5e4f57 Binary files /dev/null and b/images/window.png differ diff --git a/info.haml b/info.haml new file mode 100644 index 0000000..e0662cf --- /dev/null +++ b/info.haml @@ -0,0 +1,75 @@ +%h1 Info documentation + +%h2#path Info file search path + +The [Info manual]( +http://www.gnu.org/software/texinfo/manual/info/html_node/Emacs-Info-Variables.html) +tells us about variable `Info-default-directory-list`: + +.do + .window< + :preserve + (eval-after-load 'info + '(progn + (push "/opt/local/share/info" Info-default-directory-list) + (push "~/.emacs.d/info" Info-default-directory-list))) + +The first is the directory for info files installed by my package manager +(macports); modify the path according to your own system. The second directory +is where we'll install info files manually. + + +%h2#glibc glibc + +[`glibc`]( http://www.gnu.org/software/libc/) ("gee lib cee") is the GNU +implementation of `libc`, the Unix standard C library. Don't confuse it with +`glib`, which is a library from the GNOME desktop project. + +If you're not developing for a GNU/Linux system, but you don't find +`info`-format documentation for your system's own `libc`, you might still find +the GNU docs useful. `glibc` follows the ISO C 99 and POSIX standards, and its +documentation is always careful to point out where a feature is non-standard. +Common Unix variations are covered (e.g. the BSD and SysV styles of signal +handling). + +.do + Download "Info document (gzipped tar file)" from [the GNU website]( + http://www.gnu.org/software/libc/manual/). + + Untar into `~/.emacs.d/info/` + + `cd ~/.emacs.d/info` + `install-info libc.info dir` + +`install-info` is provided by the texinfo package, which you can install with +your system's package manager. + +The generated `dir` file contains an entry for every function and constant in +libc. These entries are added to your top-level Info menu. It is easy to remove +these from the top-level menu (you will still be able to find them via Info's +`i`ndex command or by searching): The `dir` file is plain text, so you can edit +it and remove those entries. Leave the single libc entry under "Libraries". + +Now visit a C file and use `info-lookup-symbol` to look up, say, `socket`. Go +`u`p to the main sockets node for introductory material. + + +%h2#python Python + +Install [pydoc-info.el]( +https://bitbucket.org/jonwaltman/pydoc-info/src/default/pydoc-info.el) (we +covered elisp package installation in a [previous chapter]( +customize_colours.html#packages)) and follow the instructions under "Setup and +Install" in [pydoc-info's README]( +https://bitbucket.org/jonwaltman/pydoc-info). + + +%h2#perl Perl + +I've found [info docs for perl 5.6]( +http://www.cpan.org/doc/manual/texinfo/perl5/) (over a decade old now). If you +know of a more recent version, or know how to build info files from the latest +perl docs, please send me detailed instructions. + +And spread the word! It's a shame that such a well-integrated documentation +system hasn't received more support from popular software distributions. diff --git a/info.html b/info.html new file mode 100644 index 0000000..d88fc13 --- /dev/null +++ b/info.html @@ -0,0 +1,118 @@ + + + + + + How to learn Emacs :: Info documentation + + + + + +
    + +

    Info documentation

    +

    Info file search path

    +

    The Info manual +tells us about variable Info-default-directory-list:

    +
    +
    (eval-after-load 'info '(progn (push "/opt/local/share/info" Info-default-directory-list) (push "~/.emacs.d/info" Info-default-directory-list)))
    +
    +

    The first is the directory for info files installed by my package manager +(macports); modify the path according to your own system. The second directory +is where we’ll install info files manually.

    +

    glibc

    +

    glibc (“gee lib cee”) is the GNU +implementation of libc, the Unix standard C library. Don’t confuse it with +glib, which is a library from the GNOME desktop project.

    + +

    If you’re not developing for a GNU/Linux system, but you don’t find +info-format documentation for your system’s own libc, you might still find +the GNU docs useful. glibc follows the ISO C 99 and POSIX standards, and its +documentation is always careful to point out where a feature is non-standard. +Common Unix variations are covered (e.g. the BSD and SysV styles of signal +handling).

    +
    +

    Download “Info document (gzipped tar file)” from the GNU website.

    + +

    Untar into ~/.emacs.d/info/

    + +

    cd ~/.emacs.d/info
    + install-info libc.info dir

    +
    +

    install-info is provided by the texinfo package, which you can install with +your system’s package manager.

    + +

    The generated dir file contains an entry for every function and constant in +libc. These entries are added to your top-level Info menu. It is easy to remove +these from the top-level menu (you will still be able to find them via Info’s +index command or by searching): The dir file is plain text, so you can edit +it and remove those entries. Leave the single libc entry under “Libraries”.

    + +

    Now visit a C file and use info-lookup-symbol to look up, say, socket. Go +up to the main sockets node for introductory material.

    +

    Python

    +

    Install pydoc-info.el (we +covered elisp package installation in a previous chapter) and follow the instructions under “Setup and +Install” in pydoc-info’s README.

    +

    Perl

    +

    I’ve found info docs for perl 5.6 (over a decade old now). If you +know of a more recent version, or know how to build info files from the latest +perl docs, please send me detailed instructions.

    + +

    And spread the word! It’s a shame that such a well-integrated documentation +system hasn’t received more support from popular software distributions.

    + +

    +
    + + diff --git a/install.haml b/install.haml new file mode 100644 index 0000000..e032062 --- /dev/null +++ b/install.haml @@ -0,0 +1,56 @@ +%h1 Install the right Emacs + +Install the latest release of [GNU Emacs]( http://www.gnu.org/s/emacs/) (23.3 +as of this writing). Not XEmacs, not EmacsW32, not AquaMacs, not Carbon Emacs. + +%h2 Linux + +Emacs is probably already installed; if not, use your distro's package manager +(yum, apt-get, etc). + +If your distro only has older Emacs packages, I suggest you [build the latest +version from source]( +http://www.gnu.org/software/emacs/emacs-faq.html#Compiling-and-installing-Emacs), +if you are comfortable doing so. + +%h2 OS X + +If you use [macports]( http://www.macports.org/), install the `emacs-app` port, +which gives you a native OS X application. By default macports will install +Emacs.app into /Applications/MacPorts. If you use a laptop I recommend the +`fullscreen` variant (i.e. `port install emacs-app +fullscreen`) which adds the +command `ns-toggle-fullscreen` to Emacs. + +If you use [homebrew]( http://mxcl.github.com/homebrew/): +`brew install emacs --cocoa`. + +Otherwise, you can use a [pre-built emacs]( http://emacsformacosx.com/), but do +consider installing macports or homebrew so that you can easily install other +Unixy tools as you need them. + +%h2 Windows + +You are mostly on your own as I am not a Windows user; I apologize in advance +if some of the examples in this guide don't work on your system, as I haven't +tested on Windows. + +You'll want to download the latest `emacs-xx.x-bin-i386.zip` from + and unzip it into a directory of +your choice. Then run `addpm.exe` from the `bin` subdirectory, as an +administrator (this adds a start menu shortcut and various registry entries). + +Some Emacs functionality requires Unixy tools like `find` and `grep`, which you +can get by installing a posix emulation environment such as [Cygwin]( +http://www.gnu.org/software/emacs/windows/Other-useful-ports.html). You will +have to ensure that the posix utilities are on the system PATH so that Emacs +can find them. + +For further help refer to the [GNU Emacs FAQ for MS Windows]( +http://www.gnu.org/software/emacs/windows/) and the (often outdated) +[EmacsWiki]( http://www.emacswiki.org/emacs/MsWindowsInstallation). + +%h2 Remove any existing .emacs configuration + +If you have existing Emacs customizations in a `.emacs` file or `.emacs.d` +directory, you should move it out of the way if you want your Emacs behavior to +exactly mirror the examples in this guide. diff --git a/install.html b/install.html new file mode 100644 index 0000000..42747be --- /dev/null +++ b/install.html @@ -0,0 +1,104 @@ + + + + + + How to learn Emacs :: Install the right Emacs + + + + + +
    + +

    Install the right Emacs

    +

    Install the latest release of GNU Emacs (23.3 +as of this writing). Not XEmacs, not EmacsW32, not AquaMacs, not Carbon Emacs.

    +

    Linux

    +

    Emacs is probably already installed; if not, use your distro’s package manager +(yum, apt-get, etc).

    + +

    If your distro only has older Emacs packages, I suggest you build the latest +version from source, +if you are comfortable doing so.

    +

    OS X

    +

    If you use macports, install the emacs-app port, +which gives you a native OS X application. By default macports will install +Emacs.app into /Applications/MacPorts. If you use a laptop I recommend the +fullscreen variant (i.e. port install emacs-app +fullscreen) which adds the +command ns-toggle-fullscreen to Emacs.

    + +

    If you use homebrew: +brew install emacs --cocoa.

    + +

    Otherwise, you can use a pre-built emacs, but do +consider installing macports or homebrew so that you can easily install other +Unixy tools as you need them.

    +

    Windows

    +

    You are mostly on your own as I am not a Windows user; I apologize in advance +if some of the examples in this guide don’t work on your system, as I haven’t +tested on Windows.

    + +

    You’ll want to download the latest emacs-xx.x-bin-i386.zip from +http://ftp.gnu.org/pub/gnu/emacs/windows/ and unzip it into a directory of +your choice. Then run addpm.exe from the bin subdirectory, as an +administrator (this adds a start menu shortcut and various registry entries).

    + +

    Some Emacs functionality requires Unixy tools like find and grep, which you +can get by installing a posix emulation environment such as Cygwin. You will +have to ensure that the posix utilities are on the system PATH so that Emacs +can find them.

    + +

    For further help refer to the GNU Emacs FAQ for MS Windows and the (often outdated) +EmacsWiki.

    +

    Remove any existing .emacs configuration

    +

    If you have existing Emacs customizations in a .emacs file or .emacs.d +directory, you should move it out of the way if you want your Emacs behavior to +exactly mirror the examples in this guide.

    + +

    +
    + + diff --git a/layout.haml b/layout.haml new file mode 100644 index 0000000..565e276 --- /dev/null +++ b/layout.haml @@ -0,0 +1,30 @@ +!!! 5 +%html(lang="en") + %head + %meta(charset="utf-8") + %title + / Title + %link(rel="stylesheet" href="emacs.css" media="all") + + %body + + #sidebar + #info + %h1 How to learn Emacs + + By [David Röthlisberger](http://david.rothlis.net). + Comments welcome at david@rothlis.net. + Last updated + + #toc + / Table of Contents + + Copyright © 2012 [David Röthlisberger](http://david.rothlis.net). + This guide is released under the + GNU + Free Documentation License. + + #content2 + / Contents + + / Next chapter link diff --git a/makefile b/makefile new file mode 100644 index 0000000..f758c68 --- /dev/null +++ b/makefile @@ -0,0 +1,38 @@ +chapters := $(shell awk '/^[0-9A-Z]+\. / {print $$2}' toc) + +chapters_haml := $(chapters:%=%.haml) +chapters_html := $(chapters:%=%.html) + +all: $(chapters_html) + +haml := haml/bin/haml --format html5 --autofilter markdown + +$(chapters_html): %.html: %.haml toc layout.html + @echo $@: $^ + @set -o pipefail; \ + cat $< |\ + bin/footnotes |\ + bin/tables |\ + $(haml) |\ + bin/layout layout.html |\ + bin/title $< |\ + bin/updated $(chapters_haml) |\ + bin/toc toc $(<:%.haml=%) |\ + bin/glossarylinks $(filter glossary.haml,$<) |\ + bin/next toc $(<:%.haml=%) \ + > $@ + +layout.html: layout.haml + @echo $@: $^ + @$(haml) $< > $@ + +clean: + rm -f *.html +.PHONY: clean + +wc: basic_c.haml + sed -Ee '/^ *(\.figure|\.window|\.modeline|\.echoarea)/,/^$$/ d' \ + $^ | wc +.PHONY: wc + +.DELETE_ON_ERROR: diff --git a/osx.haml b/osx.haml new file mode 100644 index 0000000..15fffa2 --- /dev/null +++ b/osx.haml @@ -0,0 +1,89 @@ +%h1 OS X + +%h2 Control and Command keys + +Mac keyboards conveniently have separate Control, Meta (a.k.a. Option or Alt) +and Command (⌘) keys. You have the traditional Emacs bindings on Control and +Meta, and the OS X bindings on Command. + +As recommended previously, you should strongly consider re-binding Caps Lock +to Control, system-wide. Go to System Preferences > Keyboard > Modifier Keys. + +On a laptop's smaller keyboard there is no Control key for the right hand. Good +ergonomic practice is to use a right-hand Control key with a left-hand normal +key, instead of stretching your left hand. You can use the open-source +[KeyRemap4MacBook]( http://pqrs.org/macosx/keyremap4macbook/index.html) to bind +your Return key to an additional Control—but only when held down; hitting it +once still registers as Return. Try it! It's not as crazy as it sounds. +KeyRemap4MacBook, despite its name, works on any recent Mac. + +After you have passed the initial learning curve and are used to the Emacs +bindings for opening, saving, copying, cutting, pasting, and undo, you may want +to re-bind the Command keys to be additional Meta keys, simply to offer a +larger target for your fingers: + +.titlebar< + init.el +.window< + :preserve + (setq mac-command-modifier 'meta) + (global-set-key (kbd "M-`") 'other-frame) + +(The second line keeps the very useful ⌘-\` behavior.) +-# +Rebinding Command in this way won't work when running Emacs inside a terminal, +as the terminal program will intercept the Command keybindings. + +If you choose to leave the Command modifier alone, you might want to rebind +`⌘-q` because it is so close to the frequently-used `M-q`. Or at least make +Emacs prompt before quitting: + +.window< + :preserve + (defun ask-before-closing () + (interactive) + (if (y-or-n-p "Are you sure you want to exit Emacs? ") + (save-buffers-kill-emacs) + (message "Canceled exit"))) + (global-set-key (kbd "s-q") 'ask-before-closing) + + +%h2 System-wide PATH + +When you start Emacs.app from the Finder (or the Dock, or Spotlight) the +environment doesn't contain customizations from your `.bash_profile` or +`.bashrc` files. If you run a shell inside Emacs (`M-x shell`) that shell +*will* load your `.bashrc`, but other Emacs commands like `shell-command`, +`grep` and `compile` won't. + +You can modify Emacs's environment directly in your init file: + +.window< + :preserve + (setenv "PATH" (concat (getenv "HOME") "/bin:" + "/opt/local/bin:" + (getenv "PATH"))) + +You can also set environment variables to apply to any OS X application in your +login session, by creating the file `~/.MacOSX/environment.plist`: + +.titlebar< + \~/.MacOSX/environment.plist +.window< + :preserve + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" + "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>PATH</key> + <string>/usr/bin:/bin:/usr/sbin:/sbin</string> + </dict> + </plist> + + +%h2 Running Emacs from the command line + +If you're using Emacs.app installed by macports, you can find the command-line +version in `/Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs`. (Useful +when you need to run Emacs with certain command-line switches, like `-Q`). diff --git a/osx.html b/osx.html new file mode 100644 index 0000000..f7132d8 --- /dev/null +++ b/osx.html @@ -0,0 +1,108 @@ + + + + + + How to learn Emacs :: OS X + + + + + +
    + +

    OS X

    +

    Control and Command keys

    +

    Mac keyboards conveniently have separate Control, Meta (a.k.a. Option or Alt) +and Command (⌘) keys. You have the traditional Emacs bindings on Control and +Meta, and the OS X bindings on Command.

    + +

    As recommended previously, you should strongly consider re-binding Caps Lock +to Control, system-wide. Go to System Preferences > Keyboard > Modifier Keys.

    + +

    On a laptop’s smaller keyboard there is no Control key for the right hand. Good +ergonomic practice is to use a right-hand Control key with a left-hand normal +key, instead of stretching your left hand. You can use the open-source +KeyRemap4MacBook to bind +your Return key to an additional Control—but only when held down; hitting it +once still registers as Return. Try it! It’s not as crazy as it sounds. +KeyRemap4MacBook, despite its name, works on any recent Mac.

    + +

    After you have passed the initial learning curve and are used to the Emacs +bindings for opening, saving, copying, cutting, pasting, and undo, you may want +to re-bind the Command keys to be additional Meta keys, simply to offer a +larger target for your fingers:

    +

    init.el

    +
    (setq mac-command-modifier 'meta) (global-set-key (kbd "M-`") 'other-frame)
    +

    (The second line keeps the very useful ⌘-` behavior.)

    +

    Rebinding Command in this way won’t work when running Emacs inside a terminal, +as the terminal program will intercept the Command keybindings.

    + +

    If you choose to leave the Command modifier alone, you might want to rebind +⌘-q because it is so close to the frequently-used M-q. Or at least make +Emacs prompt before quitting:

    +
    (defun ask-before-closing () (interactive) (if (y-or-n-p "Are you sure you want to exit Emacs? ") (save-buffers-kill-emacs) (message "Canceled exit"))) (global-set-key (kbd "s-q") 'ask-before-closing)
    +

    System-wide PATH

    +

    When you start Emacs.app from the Finder (or the Dock, or Spotlight) the +environment doesn’t contain customizations from your .bash_profile or +.bashrc files. If you run a shell inside Emacs (M-x shell) that shell +will load your .bashrc, but other Emacs commands like shell-command, +grep and compile won’t.

    + +

    You can modify Emacs’s environment directly in your init file:

    +
    (setenv "PATH" (concat (getenv "HOME") "/bin:" "/opt/local/bin:" (getenv "PATH")))
    +

    You can also set environment variables to apply to any OS X application in your +login session, by creating the file ~/.MacOSX/environment.plist:

    +

    ~/.MacOSX/environment.plist

    +
    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PATH</key> <string>/usr/bin:/bin:/usr/sbin:/sbin</string> </dict> </plist>
    +

    Running Emacs from the command line

    +

    If you’re using Emacs.app installed by macports, you can find the command-line +version in /Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs. (Useful +when you need to run Emacs with certain command-line switches, like -Q).

    + +

    +
    + + diff --git a/toc b/toc new file mode 100644 index 0000000..184ebd9 --- /dev/null +++ b/toc @@ -0,0 +1,22 @@ +1. howtolearn +2. why + +—Basic usage— +3. install +4. tutorial +5. basic_c +subsections + +—Basic customisation— +6. customize_c +subsections +7. customize_colors +subsections +8. customize_general +subsections + +—Miscellaneous— +9. info +subsections +10. contribute_emacs + +—Appendices— +A. ergonomics +B. osx +C. contribute_guide +D. glossary diff --git a/tutorial.haml b/tutorial.haml new file mode 100644 index 0000000..f9aff8a --- /dev/null +++ b/tutorial.haml @@ -0,0 +1,67 @@ +%h1 The very basics + +.do#first-key-sequence + Work through the Emacs tutorial: Start Emacs and press `C-h t`. + +If the tutorial seems a bit tedious, soldier on. It will only take you 30 +minutes, at most; and the material is essential for understanding Emacs. Most +of the cursor movement and text manipulation keybindings you'll learn will also +work in the bash shell (or any program that uses the readline library) and, if +you use OS X, even in the text fields of any native GUI application. + +Do not proceed to the next chapter of this guide until you have read the entire +tutorial, and you are comfortable with: + +| Visiting (opening) and saving files: | `C-x C-f` and `C-x C-s` | +| Switching between buffers: | `C-x b` and `C-x C-b` | +| Using the mark and the point +| to set the region: | `C-SPC` | +| Killing (cutting) and +| yanking (pasting): | `C-w`, `C-k`, `C-y`, `M-y` | +| Searching forwards and backwards: | `C-s`, `C-r` | +| Invoking commands by name: | `M-x` | +| Undo: | `C-/` | +| Cancelling half-entered commands: | `C-g` | +| Getting help on editing modes, +| keybindings and commands: | +| `C-h m`, `C-h k`, `C-h f`, `C-h a` +| (just remember `C-h` and read +| the prompt in the minibuffer) | +| Quitting Emacs: | `C-x C-c` | + +.figure.first + %img(src="images/filemenu.png" width="319" height="172") + +Don't worry if you don't remember *every­thing* from the tutorial. For now +there's no need to remember all the cursor move­ment keybindings; the arrow +keys will do. If you forget the keys for visiting (opening) or saving a file, +the File menu will remind you. Instead of remembering `C-x 1` to remove other +windows from the frame, you can use the mouse (hover over the right-hand side +of the window's modeline and read the help text in the echo area). I will ask +you to re-read the entire tutorial in a month or so, to fill in the gaps; in +the meantime, try to learn the keybindings instead of relying on the menus and +the mouse. + +.window< +   +.modeline< + :preserve + -U:--- *scratch* All L1 (Lisp Interaction)----------------------------------------------- + %img.mouse(src="images/mouse.png") +.echoarea< + mouse-1: Select (drag to resize), mouse-2: Make current window occupy the whole frame, mouse-3: Remove current window from display + +If you're on a Mac running OS X, you're in luck: Since you have separate Meta +(alt/option), Control, and Command (⌘) keys on your keyboard, the latter is +reserved for the standard OS keybindings. You can save with ⌘-s, copy with ⌘-c, +paste with ⌘-v, and search with ⌘-f. Still, you should eventually learn the +Emacs alternatives for all of the above, as they are much more powerful. In +Emacs-speak the ⌘ key is called "super", abbreviated to a lower-case "s", as in +`s-f`. + +If you're not on a Mac, resist the temptation to enable cua-mode. cua-mode +rebinds keys like `C-z`, `C-x`, `C-c`, and `C-v` to their standard Windows +meanings. cua-mode also changes the behavior of the region, so that using +shift-arrow keys highlights text, and typing text replaces the active +selection, as you'd expect in most other text editors. Get used to the Emacs +way of doing these things. diff --git a/tutorial.html b/tutorial.html new file mode 100644 index 0000000..26c50e2 --- /dev/null +++ b/tutorial.html @@ -0,0 +1,121 @@ + + + + + + How to learn Emacs :: The very basics + + + + + +
    + +

    The very basics

    +
    +

    Work through the Emacs tutorial: Start Emacs and press C-h t.

    +
    +

    If the tutorial seems a bit tedious, soldier on. It will only take you 30 +minutes, at most; and the material is essential for understanding Emacs. Most +of the cursor movement and text manipulation keybindings you’ll learn will also +work in the bash shell (or any program that uses the readline library) and, if +you use OS X, even in the text fields of any native GUI application.

    + +

    Do not proceed to the next chapter of this guide until you have read the entire +tutorial, and you are comfortable with:

    + + + + + + + + + + + + +
    Visiting (opening) and saving files:C-x C-f and C-x C-s
    Switching between buffers: C-x b and C-x C-b
    Using the mark and the point
    +to set the region:
    C-SPC
    Killing (cutting) and +yanking (pasting): C-w, C-k, C-y, M-y
    Searching forwards and backwards: C-s, C-r
    Invoking commands by name: M-x
    Undo: C-/
    Cancelling half-entered commands: C-g
    Getting help on editing modes,
    +keybindings and commands:

    +C-h m, C-h k, C-h f, C-h a
    +(just remember C-h and read
    +the prompt in the minibuffer)
    Quitting Emacs: C-x C-c
    +
    + +
    +

    Don’t worry if you don’t remember every­thing from the tutorial. For now +there’s no need to remember all the cursor move­ment keybindings; the arrow +keys will do. If you forget the keys for visiting (opening) or saving a file, +the File menu will remind you. Instead of remembering C-x 1 to remove other +windows from the frame, you can use the mouse (hover over the right-hand side +of the window’s modeline and read the help text in the echo area). I will ask +you to re-read the entire tutorial in a month or so, to fill in the gaps; in +the meantime, try to learn the keybindings instead of relying on the menus and +the mouse.

    +

     

    +
    -U:--- *scratch* All L1 (Lisp Interaction)----------------------------------------------- +
    +

    mouse-1: Select (drag to resize), mouse-2: Make current window occupy the whole frame, mouse-3: Remove current window from display

    +

    If you’re on a Mac running OS X, you’re in luck: Since you have separate Meta +(alt/option), Control, and Command (⌘) keys on your keyboard, the latter is +reserved for the standard OS keybindings. You can save with ⌘-s, copy with ⌘-c, +paste with ⌘-v, and search with ⌘-f. Still, you should eventually learn the +Emacs alternatives for all of the above, as they are much more powerful. In +Emacs-speak the ⌘ key is called “super”, abbreviated to a lower-case “s”, as in +s-f.

    + +

    If you’re not on a Mac, resist the temptation to enable cua-mode. cua-mode +rebinds keys like C-z, C-x, C-c, and C-v to their standard Windows +meanings. cua-mode also changes the behavior of the region, so that using +shift-arrow keys highlights text, and typing text replaces the active +selection, as you’d expect in most other text editors. Get used to the Emacs +way of doing these things.

    + +

    +
    + + diff --git a/why.haml b/why.haml new file mode 100644 index 0000000..d67fca1 --- /dev/null +++ b/why.haml @@ -0,0 +1,115 @@ +%h1 Why Emacs + +I believe that the future of software development, if we are to survive +ever-increasing complexity, lies in domain-specific languages that can express +solutions measured in hundreds of lines of code, not the tens or hundreds of +*thousands* of lines common in today's software systems. + +#vri-examples + #nile< + :preserve + CompositeSoftLight : Compositor + ∀ (A, B) + C = (1 - B / B.a) × (2 × A - A.a) + D = B × (A.a - C) + (A ⊕ B) + E = B × (A.a - C × (3 - 8 × B / B.a)) + (A ⊕ B) + F = B × A.a + (√(B / B.a) × B.a - B) × (2 × A - A.a) + (A ⊕ B) + >> {D if 2 × A < A.a, E if B × 8 ≤ B.a, F} + %p VRI's Nile language for rendering and compositing + #tcpip-parser< + :preserve + { structure-diagram } + +-------------+----------+----------+-------------------+-------------------------------------------------+ + \| 00 01 02 03 | 04 05 06 | 07 08 09 | 10 11 12 13 14 15 | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | + +-------------+----------+----------+-------------------+-------------------------------------------------+ + \| sourcePort | destinationPort | + +-------------------------------------------------------+-------------------------------------------------+ + \| sequenceNumber | + +---------------------------------------------------------------------------------------------------------+ + \| acknowledgementNumber | + +-------------+----------+----------+-------------------+-------------------------------------------------+ + \| offset | reserved | ecn | controlBits | window | + +-------------+----------+----------+-------------------+-------------------------------------------------+ + \| checksum | urgentPointer | + +-------------------------------------------------------+-------------------------------------------------+ + tcp -- Transmission Control Protocol packet header [RFC 793] + %p VRI's language for defining bit field accessors + +On the right are two examples from Alan Kay's Viewpoints Research Institute. +The top one is a snippet of code in the Nile language for rendering and +compositing. Below it, what looks like documentation is a valid program for +encoding and decoding TCP headers: it defines accessors called tcp-sourcePort, +tcp-destinationPort and so on. (The complete parser for this, and other +ascii-art programs, is 77 lines of code.[[1]]) This second example may seem a +bit gimmicky but I've included it to stimulate your imagination and to show +just how different, and data-driven, these languages can be. + +What does this have to do with Emacs? Well, if you are frequently using dozens +of different languages, perhaps even creating your own, you want an editor that +is easily extensible. Programmable. At the core of Emacs is an interpreter for +Emacs Lisp, a full-fledged programming language;[[2]] plus *excellent* integrated +help, code navigation, and a debugger. Because the interpreter is embedded in +Emacs itself, you can write your tools and customizations interactively; your +changes take effect immediately. (If you are familiar with other interpreted +languages you will already know and love the convenience of a Read-Eval-Print +Loop.) The many Emacs libraries and APIs can be overwhelming, but Emacs Lisp +itself is quite simple. + +%h2 Emacs vs. _____ + +“Writing an Eclipse or IntelliJ (or God help you, Visual Studio) plugin is a +monumental effort, so almost nobody does it. This means there's no community of +building and customizing your own tools [...]. Moreover, the effort to create a +plugin is high enough that people only do it for really significant +applications, whereas in Emacs a “plugin” can be any size at all, from a single +line of code up through enormous systems and frameworks.”[[3]] + +Of course, there are many valid, reasonable reasons *not* to learn Emacs. If +you program entirely or mostly in Java, Windows/.NET, or OS X/iOS, there are +compelling reasons to use Eclipse/IntelliJ, Visual Studio, or XCode, +respectively; you will certainly get a better out-of-the-box experience, with +IntelliSense and other IDE features that just work, at the expense of +extensibility. + +Or maybe you just abhor complexity in your tools: One of my early +mentors, who to this day is one of the programmers I most respect, used nothing +but dozens of Notepad and terminal windows open at once and an extra-wide +taskbar along the left edge of the screen to tell them apart. True story. + +%h2 Some thoughts on longevity + +**...of your language:** Even if you don't buy the "dozens of domain-specific +languages" idea, think about where you see yourself in 10 years. Will you still +be writing programs exclusively in Java? In C++? + +**...of your editor:** GNU Emacs has been around for almost 30 years, and +earlier versions for 10 years before that. It is open source (and [free]( +http://www.gnu.org/philosophy/free-sw.html)) software, still under active +development, with a large, talented community writing extensions for every new +language imaginable. Can you expect the same longevity from TextMate or Sublime +Text or whatever the web crowd is using these days? + + +#footnotes + [[1]]: + The Nile code snippet was taken from [Gezira]( + https://github.com/damelang/gezira/blob/master/nl/compositor.nl), a 2D + vector graphics renderer. Nile and Gezira are described in the [Viewpoints + Research Institute 2009 report]( + http://www.vpri.org/pdf/tr2009016_steps09.pdf). + The TCP/IP implementation is described in the [2007 report]( + http://www.vpri.org/pdf/tr2007008_steps.pdf). The source code for [TCP frames + is here]( + http://piumarta.com/svn2/idst/trunk/function/examples/tcp/net-tcp.k) and the + [ascii-art parser is here]( + http://piumarta.com/svn2/idst/trunk/function/examples/tcp/structure.k). + + [[2]]: + For some Lisp evangelism, read [Paul Graham]( + http://www.paulgraham.com/avg.html). + + [[3]]: + Steve Yegge, [*XEmacs is dead. Long live XEmacs!*]( + http://steve-yegge.blogspot.com/2008/04/xemacs-is-dead-long-live-xemacs.html). + Read all of Steve's Emacs articles for some equally conflicted (but much + funnier) Emacs advocacy. diff --git a/why.html b/why.html new file mode 100644 index 0000000..69ea2db --- /dev/null +++ b/why.html @@ -0,0 +1,136 @@ + + + + + + How to learn Emacs :: Why Emacs + + + + + +
    + +

    Why Emacs

    +

    I believe that the future of software development, if we are to survive +ever-increasing complexity, lies in domain-specific languages that can express +solutions measured in hundreds of lines of code, not the tens or hundreds of +thousands of lines common in today’s software systems.

    +
    +
    CompositeSoftLight : Compositor ∀ (A, B) C = (1 - B / B.a) × (2 × A - A.a) D = B × (A.a - C) + (A ⊕ B) E = B × (A.a - C × (3 - 8 × B / B.a)) + (A ⊕ B) F = B × A.a + (√(B / B.a) × B.a - B) × (2 × A - A.a) + (A ⊕ B) >> {D if 2 × A < A.a, E if B × 8 ≤ B.a, F}
    +

    VRI's Nile language for rendering and compositing

    +
    { structure-diagram } +-------------+----------+----------+-------------------+-------------------------------------------------+ | 00 01 02 03 | 04 05 06 | 07 08 09 | 10 11 12 13 14 15 | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | +-------------+----------+----------+-------------------+-------------------------------------------------+ | sourcePort | destinationPort | +-------------------------------------------------------+-------------------------------------------------+ | sequenceNumber | +---------------------------------------------------------------------------------------------------------+ | acknowledgementNumber | +-------------+----------+----------+-------------------+-------------------------------------------------+ | offset | reserved | ecn | controlBits | window | +-------------+----------+----------+-------------------+-------------------------------------------------+ | checksum | urgentPointer | +-------------------------------------------------------+-------------------------------------------------+ tcp -- Transmission Control Protocol packet header [RFC 793]
    +

    VRI's language for defining bit field accessors

    +
    +

    On the right are two examples from Alan Kay’s Viewpoints Research Institute. +The top one is a snippet of code in the Nile language for rendering and +compositing. Below it, what looks like documentation is a valid program for +encoding and decoding TCP headers: it defines accessors called tcp-sourcePort, +tcp-destinationPort and so on. (The complete parser for this, and other +ascii-art programs, is 77 lines of code.[1]) This second example may seem a +bit gimmicky but I’ve included it to stimulate your imagination and to show +just how different, and data-driven, these languages can be.

    + +

    What does this have to do with Emacs? Well, if you are frequently using dozens +of different languages, perhaps even creating your own, you want an editor that +is easily extensible. Programmable. At the core of Emacs is an interpreter for +Emacs Lisp, a full-fledged programming language;[2] plus excellent integrated +help, code navigation, and a debugger. Because the interpreter is embedded in +Emacs itself, you can write your tools and customizations interactively; your +changes take effect immediately. (If you are familiar with other interpreted +languages you will already know and love the convenience of a Read-Eval-Print +Loop.) The many Emacs libraries and APIs can be overwhelming, but Emacs Lisp +itself is quite simple.

    +

    Emacs vs. _____

    +

    “Writing an Eclipse or IntelliJ (or God help you, Visual Studio) plugin is a +monumental effort, so almost nobody does it. This means there’s no community of +building and customizing your own tools […]. Moreover, the effort to create a +plugin is high enough that people only do it for really significant +applications, whereas in Emacs a “plugin” can be any size at all, from a single +line of code up through enormous systems and frameworks.”[3]

    + +

    Of course, there are many valid, reasonable reasons not to learn Emacs. If +you program entirely or mostly in Java, Windows/.NET, or OS X/iOS, there are +compelling reasons to use Eclipse/IntelliJ, Visual Studio, or XCode, +respectively; you will certainly get a better out-of-the-box experience, with +IntelliSense and other IDE features that just work, at the expense of +extensibility.

    + +

    Or maybe you just abhor complexity in your tools: One of my early +mentors, who to this day is one of the programmers I most respect, used nothing +but dozens of Notepad and terminal windows open at once and an extra-wide +taskbar along the left edge of the screen to tell them apart. True story.

    +

    Some thoughts on longevity

    +

    …of your language: Even if you don’t buy the “dozens of domain-specific +languages” idea, think about where you see yourself in 10 years. Will you still +be writing programs exclusively in Java? In C++?

    + +

    …of your editor: GNU Emacs has been around for almost 30 years, and +earlier versions for 10 years before that. It is open source (and free) software, still under active +development, with a large, talented community writing extensions for every new +language imaginable. Can you expect the same longevity from TextMate or Sublime +Text or whatever the web crowd is using these days?

    +
    +

    [1]: + The Nile code snippet was taken from Gezira, a 2D + vector graphics renderer. Nile and Gezira are described in the Viewpoints + Research Institute 2009 report.
    + The TCP/IP implementation is described in the 2007 report. The source code for TCP frames + is here and the + ascii-art parser is here.

    + +

    [2]: + For some Lisp evangelism, read Paul Graham.

    + +

    [3]: + Steve Yegge, XEmacs is dead. Long live XEmacs!. + Read all of Steve’s Emacs articles for some equally conflicted (but much + funnier) Emacs advocacy.

    +
    + +

    +
    + +