The vi/ex Editor, Part 5: Take Control of Your Editing Environment
       
         The set Command
         set Command Variables that Control How to Paint the Screen
         Playing "tag"
         Making Your Environment Setup Automatic
         The Next Installment
       
       
       Besides all the power in the Vi/Ex editor, there's a lot of
       flexibility in it, too.  You've already met some of this
       adaptability when I pointed out various ways to perform many
       editing functions.  Now it's time to meet phase two of editor
       flexibility -- the myriad ways to modify the editor's internal
       operations.
       
       There's no "setup mode" for changing these parameters.  Instead,
       all the changes are made with line-mode commands, which can be
       interspersed with ordinary editing commands.  That is, you give
       the commands from the prompt, as usual, if you are editing in line
       mode.  When you are editing in visual (or screen) mode, precede
       these environment-modifying commands with a colon, as you would
       with any other line-mode commands you specify in visual mode.
       
       These modifications take effect as soon as you give the commands.
       They stay in effect as long as you run the editor program.  You
       can switch from editing one file to another -- as with any of the
       edit, next, rewind commands -- without affecting the editing
       environment you've set up.  And, you can revoke or further modify
       any environmental changes you've made at any time, by using the
       same commands or variant forms of them.
       
       Your environment setup does go away when you quit the editor
       altogether.  The next time you invoke the editor you'll find that
       all the environment parameters have returned to their default
       values. (This can be a blessing in disguise, because there is no
       direct way to tell the editor to restore all parameters to default
       settings.)
       
       When you've found a combination of settings you'd like to use
       again, there are ways to have these settings established
       automatically (or semi-automatically) whenever you invoke the
       editor.  You can even have several of these preset environments --
       which one is used will depend on the circumstances in which you
       invoke the editor.  I'll explain how to automate the settings at
       the end of this tutorial.
       
       
       The set Command
       
       Most of your setup will be accomplished by a single command that
       controls around fifty editor variables that affect the editing
       environment.  The set command, for which se is the shortest
       abbreviation, sets variables having three different types of
       values: string, numeric, and boolean.  Consider the examples here:
       
         set report=7
         set term=vt100
         set terse
         set nomagic
       
       Because the first two examples are assignments, they must specify
       either string or numeric values.  The first is numeric; here,
       report=7 tells the editor to give you a report (warning message)
       whenever a command changes seven or more lines -- the default is
       five or more lines.
       
       The second example assigns a string value; the numerals in it are
       regarded as merely characters by the editor.  The term=vt100
       directive tells the editor to address your terminal as though it
       were a DEC model VT100.  (You specify one of the listed short
       names for the terminal -- obtained from the Termcap or Terminfo
       terminal-description systems -- as its string value.)  The default
       for this variable is to use the terminal type from your log-in
       shell environment (the value assigned to your TERM variable), if
       available -- and if not available, then address your terminal as
       though it were a "dumb" terminal.
       
       The last two examples (without equal signs) illustrate boolean
       variables, which can be either on (enabled) or off (disabled). You
       turn a boolean variable on just by giving its name after the set
       command.  The first of these two boolean examples tells the editor
       to make any error messages very brief: cryptic to inexperienced
       users, but convenient for people who are quite familiar with the
       editor.  The default for this variable is "off" or "disabled",
       which provides longer, more explanatory error messages.
       
       To turn a boolean variable off, just give its name prefixed by the
       string "no" without any intervening space characters.  The last of
       these examples turns off the special ("magic") interpretation of
       several metacharacters, as discussed in an earlier part of this
       tutorial dealing with search patterns. The usual default for this
       variable's value is "magic", which means all metacharacters have
       their special interpretation -- but if you invoke the editor by
       the name edit or vedit, then "nomagic" is the default value (no
       special interpretation of these particular metacharacters).
       
       There's no need to use several distinct set commands when you want
       to change a number of these variables.  A single command can have
       almost any number of arguments.  So all four of the example
       commands above could be replaced by this single command:
       
         set report=7 term=vt100 terse nomagic
       
       Variant forms of this command will tell you the present status of
       individual variables, all that have been changed, or all the
       variables. For instance, type "set" without any arguments to tell
       the editor to display a list of all the variables that have been
       changed from their default values, along with their current
       values.
       
       Type "set all" to display all the variables and their values,
       whether changed from default or not.  This is a good way to check
       which variables your version of the editor recognizes, and what
       their default values actually are -- some proprietary versions of
       the editor have played with both these factors.
       
       If you want to check the values of only one or a few variables,
       you don't have to scan through a long list -- you can run a set
       command that will report the settings of only the variables you
       specify.  For a boolean variable, just give the name of the
       variable, immediately followed by a question mark, as an argument
       to the command.  For a string- or numeric-valued variable, you
       only need to specify the name itself, without the equal sign.
       Thus, typing:
       
         set report magic?
       
       will produce a response like this:
       
         report=7 nomagic
       
       If the details of checking individual variables seem too arcane to
       remember, the editor will cut you some slack: You may specify the
       name of a boolean variable in its "no" form, and you may give a
       non-boolean variable with an unneeded question mark at the end of
       it, and your query will still work.  So typing:
       
         set report? nomagic?
       
       will produce the same result as the previous query did.
       
       You can even mix option settings with inquiries in the same set
       command, in any order.  For example, if you want to turn on number
       and set report to warn you whenever even three lines are changed,
       and also want to know what terminal type the editor thinks you are
       using and whether terse is on or off, any one of the following
       command lines will take care of it all:
       
         set number report=3 term terse?
         set term terse? number report=3
         set term number terse? report=3
       
       Below, I've listed some important editor variables that modify the
       visual display, with an explanation of each.  If two names are
       specified, the first is the full name and the other is the
       shortest recognized abbreviation.  The full name will appear in
       the lists displayed when you type "set" by itself or type "set
       all".
       
       
       set Command Variables that Control How to Paint the Screen
       
         number nu
       
       You already know that the editor assigns a number to every line in
       your file, and changes line numbers every time you add or delete
       lines, in order to keep the numbers consecutive.  The number
       boolean variable tells the editor to display those line numbers
       next to every file line that appears on the screen, in both screen
       and line-editing modes. You just have to turn it on; it's off by
       default.  If you have a window that looks like this:
       
         COLOR CODING FOR POWER WIRES
         green     ground
         white     neutral
         black     hot
         red       hot
       
       turning on this variable will make it look something like this:
       
         158  COLOR CODING FOR POWER WIRES
         159  green     ground
         160  white     neutral
         161  black     hot
         162  red       hot
       
       The displayed numbers do not become part of the file, and nothing
       you can do, deliberate or accidental, will cause your editing to
       interact with the line numbers.
       
         list
       
       Turning on this off-by-default variable makes two changes in the
       way file lines are displayed on the screen, whether in line- or
       screen-editing mode:
       
       The end of each line is marked by a dollar sign.  (This applies to
       actual line ends, not to places where the editor wraps a long line
       so it can all be displayed on the screen.)
       
       Every tab character is replaced by a circumflex-capital-I ("^I")
       character sequence.  (This means that columns that were kept in
       alignment by preceding tabs will not be displayed aligned with
       this variable enabled.)
       
       Taking the same sample screen as in the previous example, when the
       list variable is on, the screen would look like this:
       
         COLOR CODING FOR POWER WIRES$
         green^Iground$
         white^Ineutral$
         black^Ihot$
         red^Ihot$
       
       This variable affects display only, the contents of the file are
       not changed in any way.  The list and number variables are
       compatible. Enabling them both would produce a display like this:
       
         158  COLOR CODING FOR POWER WIRES$
         159  green^Iground$
         160  white^Ineutral$
         161  black^Ihot$
         162  red^Ihot$
       
         window=
       
       The numeric value of this variable tells the editor how many
       screen lines should be in the editing window (in screen-editing
       mode). The default is one less than the size of your screen or
       window. This variable's value cannot be changed while you are in
       screen-editing mode.
       
         scroll
       
       A numeric variable that sets the number of lines to be scrolled
       down by a control-D or up by a control-U command.  The z command
       uses twice this count as the number of lines to display.  Default
       value is half the size of the screen or window.
       
       You can give a count prior to one of those scrolling commands,
       which will override the value of the scroll variable.  For
       example, typing "3control-D" will scroll forward just three lines.
       
       Caution:  The editor will remember any count you give, and use
       that count -- instead of the value assigned to scroll -- with any
       future command you give without specifying a new count. Because
       the value of the scroll variable remains unchanged, even though it
       is no longer being used, the set command has no way to undo this
       new behavior.  The only way to go back to using the value set for
       scroll is to look up that value -- type "set scroll" -- then use
       this value as a count preceding another of the commands that
       normally use the scroll variable.
       
       
       Playing " tag"
       
       If your editing work requires jumping from place to place in
       numerous files, it would be convenient to index the places you
       visit most. The editor has a system for handling this.  It's
       pretty simple, too; you set up one or more reference lists, then
       you can go to the place within the file that you want just by
       typing a few characters.
       
       Caution:  the "tags" system described below does not simply switch
       focus briefly to another file.  It ends your editing of the
       current file, then loads the new file into the editor with the
       standard context changes, just as if you had given an edit
       command.  As a consequence of this, the editor will normally
       refuse to execute a tag command when the file you are presently
       editing has changes which you have not yet written to permanent
       storage.  If you choose to override this protection, give the
       command as tag! or ta!.
       
       To use this system, you need to set up at least one "tags" file
       containing references to your file destinations.  If programming
       is your work and you use C, C++, Pascal, FORTRAN, lex or yacc, the
       Unix <a href="/unixworld/man/ctags.1">ctags utility can set up a
       suitable "tags" file for you.  If not, it isn't all that difficult
       to build such a file yourself.
       
       Each line in a "tags" file is a complete reference to a place you
       might want to go.  The line has five parts, which (reading from
       left to right) are:
       
       The short name you will use to refer to the particular file and
       the place in it.  Don't start choosing names, though, until you've
       read the third way to invoke a tag, below.
       
       One tab character, as a separator.  A space character will not do
       here.
       
       The name of the destination file.  This can be a simple name, if
       the file is in your current directory, or a path name, if not.
       
       Another tab character.  Again, a space character won't do.
       
       A line-mode search command that will find the place you want
       within the file.  As you may have cleverly deduced, you can string
       multiple commands together here with the vertical-bar ("|")
       character, and can use editing commands if you want the file
       pre-edited.  Spaces and even tabs may appear in this string if
       needed; only the first two tabs in a line are interpreted as field
       separators.
       
       If this file structure sounds a little complex, look at this short
       example of a "tags" file to see how things actually work out:
       
         difid   ../math/calc    /^APPENDIX/;/^C. Differen
         integ   ../math/calc    /^APPENDIX/;/^D. Integrals
         log     /adm/err-log    1;?Err-7$
         rvlog   /adm/err-log    g/^/m0|0;/Err-7$
         vocab   %      /^GLOSSARY
         words   %      /^GLOSSARY
       
       The first line in the example above provides that using "difid" as
       a tag will take the user to edit a file named "calc", in a
       directory with relative path name "../math". (Note: that using
       this tag will not change the current directory of the user's
       shell; only the file being edited is changed.)  Once that file has
       been loaded, the editor will seek out the first line that starts
       with "APPENDIX", and go from there to the next line that begins
       with "C. Differen".
       
       Yes, you can specify different tags to enter the same file at
       different points.  My second example line contains a tag that
       leads to a different place in the same file.  After the editor has
       searched out the first line beginning "APPENDIX", as before, it
       goes on to a different section of the appendix.
       
       You can even use multiple tags to enter the file at the same
       point, but with different preliminary editing.  My "log" and
       "rvlog" tags go to the same file and the same line -- the most
       recently appended line that ends with "Err-7".  The difference is
       that the "rvlog" tag first reverses the order of lines in the
       file.  (Note that the search command for the two tags is
       different, because in the second case the line being sought has
       been moved to a different position in the file.)
       
       And you can use a tag to move to a place in the file you are
       already editing.  In the last two example lines I have used the
       percent sign (%) to indicate "current file"; the pound-sign (#)
       for "alternate file" is also acceptable.  These tags move the user
       to the glossary section of the document currently being edited,
       whatever that document may be.  If I were to invoke a tag with an
       actual file name in it, and that file happened to be the file I
       was presently editing, the effect would be the same.
       
       Finally, you undoubtedly saw that the last two entries in my tags
       file are identical except for the tag names.  Either tag will take
       you to the same place in the same file with no preliminary
       editing. This is legitimate, and often useful.  You may be
       building a tag file for multiple users -- some of these users are
       accustomed to a certain tag name for a given file and location,
       some to another tag name. The tags system allows you to
       accommodate both groups.
       
       You may have noticed that the lines in my example file are
       arranged in ASCII-sort order.  This is necessary to keep the
       tag-search mechanism from missing the tag you specify.  If you
       don't trust your own ability to sort the lines, the Unix sort
       utility can do it for you.
       
       When you've built your "tags" file, you need a place to put it.
       Ordinarily, when you invoke a tag name, the editor first tries to
       look it up in a file named "tags" in your current directory. If it
       fails to find such a file, it then looks for /usr/lib/tags .  But
       you can override these defaults by setting a different value for
       the "tags" file in your editing environment.  For instance, if you
       include this command in your setup file:
       
         set tags=moretags
       
       then tag searches will take place in a file named "moretags" in
       your current directory.
       
       With everything set up, you only need to know how to invoke a tag
       as needed.  There are three or four ways to do it, all enumerated
       below:
       
       When you invoke the editor from your shell's command line you can
       use the "-t" command-line option flag to specify a tagged item
       instead of naming a file to edit.  For example, typing the line
       (from your shell prompt):
       
         vi -t chap3
       
       tells the editor to look up the "chap3" tag to find the
       destination file and location in that file.  Oddly enough, you can
       list some file names to edit as well as a tag (with "-t") on the
       editor-invocation command line.  The rule is that the first string
       of non-whitespace characters immediately following the "-t" flag
       is regarded by the editor as a tag name; any other such strings
       that don't begin with a "-" character are taken as actual names of
       files.  However, the tagged and the named files aren't remembered
       the same way in this case.
       
       For instance, if you specify a tag, then two file names, the
       editor will initially place you in the tagged file and when you
       type :next you will move to the first named file, and another :n
       (the shortest abbreviation) takes you to the second named file.
       But, the tagged file does not appear on the argument list --
       viewed with the args command -- so when you enter a :rewind
       command you return to the first named file, not the tagged file,
       even though it was specified first on the command line.
       
       While you are editing a file, you can invoke a tag with the
       line-mode command tag (shortest abbreviation, ta) followed by a
       space and the tag name.  This command can be given from screen
       mode as :tag, of course.
       
       While you are in screen mode, you can put the cursor on either the
       first letter of a word or the space immediately preceding it and
       then type a "control-]" character.  This has the same effect as if
       you'd typed the word the cursor is at as the argument to a :tag
       command.
       
       Caution:  A "control-]" is the default Telnet "escape" character.
       So if you are editing on a remote system during a Telnet session
       and enter a "control-]", control will return to Telnet, which will
       interpret what you type next as a Telnet command.  You could
       change the Telnet escape character when you start your remote
       terminal session in order to use "control-]" with the editor.
       
       Some newer versions of the editor maintain a stack of tags.  If
       so, you can repeat the last :tag command you gave in screen mode
       by typing "control-T". This can take a count, so that typing a "2"
       and then a "control-T" repeats the :tag command preceding the last
       one you gave, etcetera.
       
       
       Making Your Environment Setup Automatic
       
       When you've worked out an editing environment setup that you will
       want to use frequently, or even occasionally, there is no need to
       type in all the changes from default every time you start up the
       editor. Because these are all line-mode editor commands, there are
       several ways to define them automatically, all or some of the
       time.
       
       If there is an editor start-up file (which must be named .exrc) in
       your home directory (the dot at the start of the name is essential
       and the "rc" abbreviation means "run command"), the editor will
       interpret it every time you invoke the editor and execute (or at
       least attempt to execute) the lines in the file as line-mode
       commands before it turns editing control over to you.  This
       applies to environment-setting commands as well as others, so
       placing your set-up commands somewhere in this file will cause the
       setup to happen every time you invoke the editor.
       
       There are drawbacks to this approach, though.  You can only have
       one environment preset this way: the editor will use that same
       environment every time you invoke the editor.  One way to provide
       more flexibility is to maintain several files with various setups
       in them, and before you enter the editor, rename the appropriate
       one of those start-up files to .exrc and when you leave the
       editor, restore its original name.  But you shouldn't have to deal
       with anything this cumbersome just to control your editing
       environment.
       
       The creators of the editor have provided a much better solution.
       Before the editor looks in your home directory for a start-up
       file, it first looks in the directory from which you invoked the
       editor. If it finds a file named .exrc there, it interprets that
       as the start-up file instead of the .exrc file in your home
       directory.
       
       That behavior lets you have a special setup for each directory in
       which you might want to do some editing.  For instance, let's say
       you have a directory of shell scripts, another containing chapters
       from a book you're writing, still another you use for writing
       e-mail, plus one where you store and edit error logs -- you can
       have a separate editing environment for each of these purposes.
       And if you invoke the editor from a directory where you don't
       maintain a separate start-up file, the one in your home directory
       will be used.  Just remember to change to the directory where the
       target file(s) are located before invoking the editor.
       
       Caution:  If you invoke the editor from a directory different from
       the one containing the file you're editing, the editor will
       interpret the start-up file from your start-up directory, and not
       use the intended environment (defined by the .exrc file in the
       directory where the target file resides).
       
       One caveat about multiple .exrc files, though.  In Unix System V
       and its successors, a security feature restricts the editor's
       access to .exrc files that are not in your home directory. The
       editor will not interpret a .exrc file that's not in your home
       directory, unless you also have a .exrc file that does live in
       your home directory, and that file contains a line that sets the
       exrc boolean variable.
       
       The security hazard that this complex proviso guards against is a
       real one.  Let's say you need to edit several files that are in a
       directory like /tmp, /var/tmp or some other directory that is
       writable by all users.  To save the trouble of providing a full
       path name every time you want want to switch from one file to
       another, you could easily change directories (that is, "cd" to the
       directory where these files are located). But when you want to
       start editing a file, the Vi/Ex editor may find a Trojan horse
       file named .exrc placed in your current directory by a cracker to
       await victims.  Of course, the commands in this false editor
       start-up file will be run with your account ownership.  These
       commands aren't limited to editor set-up commands, but may be any
       shell command that you're allowed to run, including ones to wipe
       out your files, reset file permissions to allow public access to
       confidential data, send indelicate comments to your boss using
       utilities like write combined with banner, and so forth.
       
       Now, perhaps you work on files that have different kinds of
       material in different sections, and you want to be able to make a
       complete change of editing environment whenever you move from one
       section to another. In this case, use the source command, with so
       as its shortest abbreviation.
       
       The source line-mode command can be given at any time, although
       you may have to give it from line-editing mode, not from screen
       mode with a preceding colon.  It takes one argument, a file name
       or path name, and its function is to read the named set-up file
       and attempt to execute the lines in it as a series of line-mode
       commands.
       
       Whether or not you can specify this command successfully in screen
       mode depends on the editor version you are using.  Some early
       versions were quite serious about prohibiting multiple-line
       line-mode commands while in screen mode.  So serious that these
       versions will execute only the first line of a script that has
       been sourced in while the user is in screen mode.  If you don't
       encounter this behavior, you can ignore this warning.  If you do,
       you at least know where the problem lies.
       
       Now that you understand editor start-up files, I can acknowledge
       that the one you put in you home directory is not strictly
       necessary. The editor will accept the value of a shell environment
       variable named EXINIT as the string of line-mode commands to be
       run whenever the editor starts up.  But I don't recommend going
       this route, for several reasons:
       
       Usually the shell has a strict limit on the number of characters
       for the value of an environment variable, whereas the size of a
       .exrc file is practically unlimited.  As you get better at using
       the editor, you can easily develop a home-directory start-up file
       that is too large for EXINIT.
       
       A start-up file can be changed by simple editing, but you have to
       redefine the EXINIT variable from scratch.
       
       A change in your start-up file takes effect the next time you
       invoke the editor, whereas if your EXINIT variable is defined in a
       shell start-up file, it's new definition won't take effect until
       you log-in again or explicitly "source" the shell start-up file
       from the shell's command line.
       
       When you want to restore the editor's environment variables to
       their beginning state, you can simply source in the editor
       start-up file. There's no way to do this with the EXINIT shell
       variable.
       
       You can use source to execute an editor set-up file from anywhere
       in your file space.  It will also execute any file of line-mode
       commands, no matter what the file name.  For example, let's say
       you have a special environment setup that you never use at the
       beginning of an editing job, but you do need it to edit tables.
       You invoke the editor as always, but when you're ready to edit
       your tables, you run a command like:
       
         :so table-defs
       
       where the table-defs file contains line-mode commands that set up
       the editor for table editing.
       
       When you specify a file of line-mode editing commands with source
       to perform, say, a frequently used edit automatically, it's
       probably a good idea to have commands in that file to return the
       editing environment to what it was before the editing commands
       were run, assuming the environment was changed for the editing
       task.
       
       Caution:  If you decide to use environment set-up files that you
       specify while you are editing -- you can't always depend on
       default values.  For example, the autoindent variable is disabled
       ("off") by default.  So if you are setting up a start-up file that
       will only be used at the beginning of editor sessions, and you
       don't want to use autoindenting, you don't need to do anything to
       leave it turned off.  But if you plan to occasionally use that
       set-up file in the middle of a session, you have to ask yourself,
       "Will I ever use this setup in a case where I previously had
       autoindenting turned on, either by another set-up file or because
       I manually turned it on?" If the answer that question is "Yes",
       then the set-up file you're writing must contain a set noai
       command to be sure that autoindentation is definitely disabled.
       
       And, what if the source command is broken in your version of the
       editor?  There is still a way to make semiautomatic environment
       changes.  You have to use the line-mode read command plus a
       little-known feature of letter-named storage buffers.
       
       You're probably accustomed to using the "a" through "z" named
       buffers for storing pieces of text, and returning these pieces to
       the main document with commands like "jp, which returns the
       contents of the "j" buffer right after the cursor position in
       visual mode.  Well, you can also use a visual-mode command of the
       form @j, which takes the text from the "j" buffer and executes it
       as a visual-mode command string. For instance, if buffer "j"
       contains "257G3dd" as its text, then typing @j will move the
       cursor to line 257 and delete that line and the two that follow
       it.
       
       The text in the buffer must be commands you could give from visual
       mode for this feature to work, but that includes line-mode
       commands that are preceded by a colon and terminated with a
       carriage-return character. So if buffer "h" contains the lines:
       
         :se nomesg terse list
         :map v :!wc -w %^M
         1G
       
       then typing "@h" will reset three variables, map a command string,
       and move the cursor to the first line in the file.
       
       There are a few points you should keep well in mind when you are
       placing line-mode commands into a letter-named buffer for future
       execution.  All of them revolve around the fact that the editor is
       expecting screen-mode commands from this source.
       
       A line-mode command must begin with a colon character.
       
       A line-mode command may begin at the start of a line of text or in
       the middle of it, but it must end at the end of the line.  At
       execution time, the newline character at the end of the text line
       is what tells the editor that this particular command is ended and
       a new command (either line- or screen-mode) will follow.
       
       Never put a line break in buffer text you will execute as a
       command string unless a carriage return is part of the command
       string at that point.
       
       To import this set-up command list from an outside file to the "h"
       buffer, use the read command.  For example, if your three-line
       set-up file is named set.5, then type:
       
         :r set.5
         "h3dd@h
       
       to read the file into your editing buffer, then the "h3dd@h
       command will delete those three lines -- which came from the
       external file -- into the "h" named buffer, then execute the same
       lines as set-up commands.
       
       The Next Installment
       
       You asked for it, and it's here! Most of the e-mail I receive
       about this tutorial asks me how to do some specific kind of
       editing with Vi.  The most popular request so far has been for
       techniques to edit material in columns, and that's what I explain
       in the next installment. Then it's on to the treacherous, albeit
       important, topic of addresses for screen-mode commands.
       
 (DIR) Part 6: Addresses and Columns
 (DIR) Back to the index