Home page of Eric Pement | Home > emacs_tabs.htm |
|
Understanding GNU Emacs and TabsBy Eric Pement I love Emacs, but getting my head around how it handled TABs and how to make it do what I wanted it to do, was a major source of frustration. I spent several hours trying to figure it out, reading, searching and even grepping info pages. This summary is intended to be understandable by novices to Emacs. If you find mistakes or things I left out, or if it helps you, write me and let me know. This document is always subject to change, so please let me know if you find sections that are inaccurate or incomplete. My most recent change to this file was to update the URL to whitespace-mode. To truly understand GNU Emacs and TAB behavior, you must bear three things in mind at once. I've written them as questions to ask yourself, but you should also think of them as options that you have the power to re-define. The possible options below are in square boxes.
The following section contains the longer, detailed explanations of how GNU Emacs handles this or that aspects of TAB settings. Its sections are linked to the questions above. Use file variables to override defaultsAlthough Emacs normally looks at the filetype or file extension (such as *.txt, *.php, *.pl, *.html) to determine what editing mode and variable settings to use when editing a file, you can override this for individual files. If you embed a string of special commands at either the beginning or the end of a file, Emacs will automatically change certain settings such as tab-width, using tabs or spaces, margins, or even editing mode each time it opens that file. For details, see the section on setting file variables. Convert Tabs to Spaces, and vice-versaEmacs is also able to change tabs to spaces or to change spaces to tabs in a document or in part of a document. This is useful if you need to modify things wholesale. How many things should be inserted by the TAB key?Insert one thing onlyNobody wants to insert just one space when they press a TAB key. If they wanted to insert just one space, they'd press the spacebar. Here's how to insert just one TAB when you press the TAB key (because quite often, Emacs will insert several TABs or combinations of TABs and spaces): Just this once time, insert just one TAB: Ctrl-q <TAB> You can do this anytime while typing, and it doesn't change modes or reset
anything. Ctrl-q followed by any (nearly) any other character on the
keyboard inserts that literal character into the file. Associate Ctrl-q
with the word "quote" to memorize it. But pressing three keys
For this session, force just one TAB: M-x local-set-key<RET> <TAB> self-insert-command M-x means the Meta-character followed by x. This
can be be ESC followed by x, or M-x global-set-key<RET> <TAB> self-insert-command Permanently, force TAB to insert just one TAB: (global-set-key (kbd "TAB") 'self-insert-command); # in every mode OR (define-key text-mode-map (kbd "TAB") 'self-insert-command); # only in text-mode Edit your .emacs startup file (I assume you know where to find it) and insert only one of the lines on the previous paragraph. Of course, "permanently" means only so long as you have your .emacs file set this way. The global-set-key line will affect every editing mode; the define-key line shows how to change one mode at a time. It doesn't have to be text-mode necessarily; you should be able to use multiple lines to redefine several editing modes. Either one or many thingsThe default (normal) behavior of Emacs is to insert one or more TABs or spaces when the TAB key is pressed, depending on (a) which editing mode is active, (b) what the character position is on the line, and in particular, (c) what variables have been set. Mostly, the TAB key is bound to indent-relative or indent-relative-maybe, which means that Emacs looks up to the previous printed line, splits it into words, and each press of the TAB key will move the cursor (the "point") to the next nonblank position on the line. For example: A Blue Cow Doesn't Exist, Fred. Greg If the cursor is currently located directly after the word "Greg", then pressing TAB would move it so that it lines up below the "C" in "Cow". Pressing it once more would move it to line up below the "D", and then below the "E" and so on. The indent-relative function is what will move the cursor to the next word. Emacs will insert a combination of TABs and spaces, or else just spaces, depending on another setting. If the TAB key isn't bound to indent-relative or
indent-relative-maybe, it might (and can be) bound to
If the tab-to-tab-stop function is invoked, then Emacs will enter however many TABs and spaces are needed to reach the next position on that list. The number of TABs it will enter with each keypress depends on the value of the tab-width variable. For this session, change the list of tab stops: M-x edit-tab-stops For more info on the tab stop list: M-x describe-variable<RET> tab-stop-list Just remember that you can edit the tab-stop-list all you want, but if the TAB key is bound to indent-relative or to indent-relative-maybe, editing that list probably won't do what you want. You may prefer to disable indent-relative and enable the tab-to-tab-stop function instead, which will insert TABs or spaces (or both) to a predefined list of places to stop at. For this session, use tab-to-tab-stop to control TAB behavior: M-x local-set-key<RET> <TAB> tab-to-tab-stop Permanently use tab-to-tab-stop to control TAB behavior: (global-set-key (kbd "TAB") 'tab-to-tab-stop); # in every mode OR (define-key text-mode-map (kbd "TAB") 'tab-to-tab-stop); # only in text-mode As in the section above, you can modify the "text-mode-map" to be some other mode instead. Emacs isn't inserting anything!!If you feel like I do, you probably are considering this a fault. You keep pressing the TAB key, but nothing happens. In programming modes, such as when you're editing C or Perl or Lisp source code, the TAB key is bound to special indentation rules. That is, instead of being bound to indent-relative as in text-mode, the TAB key is pre-bound to cc-indent-line or lisp-indent-line (if editing your .emacs file), and so on. In c-mode, pressing the TAB key will move the cursor to the first indentation level, and then may not move the cursor forward after that, no matter how many times you press it. If this behavior isn't what you want, you can do one of these things:
What should be inserted when I press TAB?True tab characters onlyTo insert only one TAB when the TAB key is pressed: Back up to read Inserting one thing only To insert one or more TABS (but never spaces!) when the TAB key is pressed:
Spaces onlyFor this session, force Emacs to indent with spaces, never with TABs: M-x set-variable<RET> indent-tabs-mode<RET> nil Permanently force Emacs to indent with spaces, never with TABs: (setq-default indent-tabs-mode nil); # put this in your .emacs file For this file, force Emacs to indent with spaces, never with TABs:
Setting file-specific variables for EmacsEmacs is designed so that individual preferences can be customized on a per-file
basis, even superseding customizations based on filetype or file extensions.
To accomplish this, the customizations must be inserted either in line #1 of
the file, or else at the very bottom of the file (less than 3000 characters from the
end). These customizations are called "File variables", and you can read much more
about them by running the Emacs command: I like to put the variables on the top line of the file, but you can put them at the end of the file if you prefer. On the top line of the file, you put the variables between two -*- symbols, like this: -*- variable:value; variable:value; ... -*- You may separate multiple variables with semicolons (;). If you are using a programming language, you may prefix a comment string to the start, like so: <?php // -*- mode:php; tab-width:3; intent-tabs-mode:nil; -*- // // Double-slashes begin comments in PHP Insert a combination of TABs and spacesFor this session, allow Emacs to use both TABs and spaces to indent: M-x set-variable<RET> indent-tabs-mode<RET> t ; You only need this if the default has been turned off Permanently set Emacs to use both TABs and spaces to indent: (setq-default indent-tabs-mode t); # put this in your .emacs file ; Since this is the default, you shouldn't need to add this command. For this file, use both TABs and spaces to indent: -*- indent-tabs-mode:t; -*- # put this on line #1 of the fiile # more about using File Variables The default behavior of Emacs is to use both TABs and spaces to reach
the next stop position. This is controlled by a Boolean variable,
The indent-tabs-mode variable answers a what question, namely, What can I use to indent? But along with this, Emacs also answers a when question, When does pressing the TAB key do something unusual?, and also a how far question, which is How far ahead should the next stop position be? The when question is controlled by the editing modes (e.g., Lisp-mode), which have different settings for each mode. The how far? question is addressed by indent-relative or by indent-relative-maybe or by tab-to-tab-stop. These are three variables (or rules, if you like), and Emacs uses these rules to figure out how far to move the cursor forward, using the smallest number of TABs and spaces needed to reach that next position. If you don't like this behavior and want to change it, look at one of the tabs only or spaces only options just above. If you used to have this behavior and want to get it back, then
you're probably in a special editing mode like Lisp-mode, outline-mode,
or something else. Try typing How wide should TAB spacing display?Every 8 charactersWhat is a TAB? A tab is an invisible one-byte character that tells the screen to display the next character a certain number of characters to the right. It doesn't have to be capitalized, so "tab" is an acceptable spelling. A TAB can also represent the plastic "TAB key" on the computer keyboard, which often does not insert a literal TAB character into the file or the command line. For the rest of this essay, when I refer to the TAB, I mean the invisible one-byte character that controls the placement of characters sent to the screen or the printer. If I put a space (which incidentally is also an invisible one-byte character) between the letters A and B, I expect to see something like this: 0123456789X12 A B ------------- But if I put a TAB between the letters C and D, then I should expect to see the letter D shifted to the right several characters more, which is what normally happens. In particular, note that in the example below, there is only one TAB character between C and D and between E and F, even though the spacing is visually different to us: 0123456789X12 C D E F ------------- The default TAB display is every eight characters. This means that when you have a TAB character somewhere in a line, the character following that character will appear in a mathematically predictable position on the line. If the first character on your line is position 0 (zero), like in Emacs, then the next character after a TAB will either be on 8, 16, 24, 32, 40, or in some other number which is a multiple of 8. Looking at a line with true TABs in it, it may appear as if there are multiple spaces present on the line, but in fact there are not. The tab-width variable expands the TAB characters on the line to stop at the next unit of i × 8, where i is a positive integer. So therefore, the TAB "stops" occur at positions 8, 16, 24, 32, 40, and so forth. Some people may find it helpful to use whitespace-mode, an Emacs minor mode designed to display TABs and/or spaces in a different highlighted color. whitespace-mode has been part of Emacs since version 23. See a sample use on this page. If your version of Emacs is prior to version 23, get the Emacs Lisp source here for Version 21 or 22: http://www.emacswiki.org/emacs/WhiteSpace After installation, type M-x whitespace-mode to toggle the display of TABS and spaces on and off. You can also control the background color and other features. Every N charactersThis is done by changing the value of the tab-width variable. Note that this has the effect not only of altering how lines with TABs are displayed on the console, but also of altering how many TAB characters are inserted by the tab-to-tab-stop and the indent-relative commands (that is, if you permit TABs to be inserted by the two previous commands. You can enable those commands and permit only spaces to be inserted by them, you know . . .). For this session, set the tab-width to 7 characters M-x set-variable<RET> tab-width<RET> 7 Permanently set the default tab-width to 7 characters (setq default-tab-width 7); # add this to your .emacs file For this file, set the tab-width to 7 characters -*- tab-width:7 -*- # put this on line #1 of the fiile # more about using File Variables Display a certain number of inches or cm. from the leftEmacs isn't Microsoft Word, and therefore it doesn't permit you to set things like font-size, point-size, page layout, and other things that word-processing programs may permit you to do. Emacs is a text editor, and therefore it counts things in characters, not inches or centimeters. In short, you can't tell Emacs to "indent the first line of each paragraph one-half inch," like you can in Microsoft Word. You can tell Emacs what fonts and what font-size you want to see on your computer screen. But this doesn't affect how those fonts are printed on paper. Further, you may be thinking of a TAB as a series of (say) half-inch indentations. Emacs doesn't think that way. It thinks of TAB as a thing which is N-characters wide, and exactly how wide the N will display is up to you. If you want N to display at every 5 characters, you can do that. If you want N to be shown every 13 characters, you can do that, too. The notion of Display-This-On-The-Screen is not the same as
how many characters to insert when the TAB key is pressed. Pressing
the TAB key inserts a certain number of
Tabify: Change spaces to TABsThe Emacs command M-x tabify will remove space characters and insert TABs, effectively making the file smaller. Tabify only works on a marked region, not on the whole buffer. (A "region" is the area or block of text between the "point" and the "mark" in Emacs.) tabify uses the current tab-width variable to calculate how many tabs to insert on the line. For example, if you have 5 spaces at the beginning of the line and the tab-width variable is set to '2', tabify will change those 5 spaces to 2 TABs and one space. If the tab-width variable is set to '4', tabify will change those 5 spaces to one TAB and one space. Note in particular that tabify will insert TABs throughout the entire line, not just in the spaces at the beginning of the line. If for some reason you only want TABs inserted at the beginning of a line, but no TABs inserted in the spaces after the line starts, use the Emacs command M-x shell-command-on-region, invoking the external GNU utility called "unexpand", which by default only converts spaces to TABs at the beginning of a line, but not within the line. The "unexpand" utility also supports a switch to alter the length of a TAB character. Untabify: Change TABs to spacesThe Emacs command M-x untabify will change all the TABs in the current region to spaces. This means you must have marked the region first. A "region" is the area between the "point" (cursor) and the "mark", considered as a stream-block rather than a vertical or columnar block. How many spaces are inserted for each TAB depends on the current tab-width setting, so if the code doesn't seem to be lining up properly, change the tab-width setting to different values until you find one that looks the most nearly correct, and then invoke untabify to convert all the TABs in the marked region to space characters. Incidentally, the external GNU utility "expand" also converts TABs to spaces, and it has switches to alter the tab-width value, plus a switch to convert TABs to spaces only at the beginning of the line, but not to touch TAB characters in the middle of a line. This is a very useful utility in some circumstances, such as in editing TAB-delimited data files. |
These pages created with
GNU Emacs,
xhtmlpp,
Take Command, and
Altap Salamander. Icons courtesy of
Qbullets
|
|