diff -urN elvis-2.2_0/Announce-2.2_0 elvis-2.2_1/Announce-2.2_0 --- elvis-2.2_0/Announce-2.2_0 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/Announce-2.2_0 1970-01-01 01:00:00 +0100 @@ -1,39 +0,0 @@ -As of October 20, Elvis 2.2 is officially released. - -To learn about elvis, or download (source, Win32 binaries, or MS-DOS -binaries) go to... - - ftp://ftp.cs.pdx.edu/pub/elvis/README.html - -It's been a full four years since the version 2.1.4 was released so you -should expect a lot of new features. Here's a brief summary: - -* Elvis 2.2 is pretty - o The :color command has been greatly improved. - o Can use Xft for antialiased text (x11 only). - o You can use background images. (x11 and windows only) - o You can load your own elvis icon. (x11 and windows only) - o Themes are supported. ":theme sand" is included. Other themes are - available via ":e theme:". (x11 and windows only) - o Good default colors are provided for all user interfaces. - o The Windows interface can use X11 color names. - -* Elvis 2.2 has many of Vim's feaures - o :autocmd - o Many g commands. - o Name completion. Filenames, commands, options, etc. - o notation in :map commands. - o You can load aliases and maps to emulate vim better with ":ru likevim". - -* Other stuff - o Built-in spell checker. Context sensitive, and can suggest corrections. - o Folding. Lets you hide parts of your text without deleting it. - o Region highlighting. - o User-definable URL protocols. - -* Still has the best features of 2.1 - o "hex" display mode for editing binary files. - o "html", "man", and "tex" display modes, for previewing text. - o Online manual is written in HTML, and viewable with the "html" display - mode. Look nice, and has many convenient links. - diff -urN elvis-2.2_0/Announce-2.2_1 elvis-2.2_1/Announce-2.2_1 --- elvis-2.2_0/Announce-2.2_1 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/Announce-2.2_1 2004-03-26 22:35:30 +0100 @@ -0,0 +1,321 @@ +I almost have version 2.1.1 ready. I'm probably about 4 weekends away. +You can download a copy of the source code from... + + ftp://ftp.cs.pdx.edu/pub/elvis/unreleased/almost-2.2_1.tar.gz + + +The following bugs have been fixed: + + :andale was using Luxi Mono fonts + The :andale alias (used in the "x11" user interface) was + actually using Luxi Mono fonts instead of Andale fonts. + + filenamerules broke newline handling + When I implemented the filenamerules option in 2.2.0, I + accidentally broke the way it parses newlines. This is important + if you remove the spaces keyword from filenamerules, and then do + something like ":n `grep foo *.txt`" to sets the args list to + all files containing "foo". + + HTTP User-agent: header line + When sending HTTP requests, Elvis should send a User-agent: + header line. Some web sites demand this. + + Default button names + In the "html" display mode, the and tags should have the default values "Submit" and + "Reset" respectively. In 2.2.0, they have no default. + +
shows ------------> + The "html" display mode had trouble with tags that end with + "/>". Elvis would display the > on the screen instead of hiding + it. + + + The key should beep when pressed in visual command mode. + + Delayed screen updates in "x11" user interface + When a map times out, Elvis wasn't updating the screens + immediately in the "x11" user interface, which made it hard to + detect that the map had indeed timed out. + + "d)" could crash + In a file full of blank lines, "d)" caused 2.2.0 to dump core. + + :put from a cut buffer + The :put command wasn't accepting a cut buffer name argument. + + :dict didn't handle single words + The :dict alias (after ":load dict") didn't handle single-word + queries correctly. + + The directory editor's links were relative to the wrong directory. + If you used ":e dirname" to edit the directory "dirname", then + the links in the generated HTML weren't interpreted as being + relative to "dirname". They were treated as being relative to + the current directory. + + "x11" converts to ^K0062. + The "x11" user interface is too aggressive when trying to + convert key names from angle-bracket notation to raw characters. + If a map contains an HTML tag such as , and the tag name + happens to match the name of a key such as the "b" key, then + Elvis was trying to convert that keystroke into a raw control + sequence. + + ":normal cwFOO^[" didn't work + The c operator was implemented in a way that didn't work in the + :normal command. + + ".IP \(bu 4" had too large of an indent. + This is apparently due to the fact that "4" has no explicit + scaling suffix, and .IP was using the wrong default scaling + factor. + + Hard to enter ^ in WinElvis on a Norwegian keyboard + WinElvis has always had a hard time with "dead keys", but now + I'm hopeful that it should work. The ^ key works in Norway now, + at least. + + ":e +cmd file" didn't work + For the :e command and a few others, the "+" flag could only + handle a line number parameter, not a full ex command line. + + Typos in manual. + Many found and fixed. Still many more to be found, I'm sure. + + :chregion always changes the comment + The :chregion shouldn't change the comment of an existing region + unless you give a new comment explicitly, or the old comment was + merely the old font name. + + ":set show=spell" doesn't work very well. + You need to load the whole dictionary to get good suggestions + from the spell checker. In 2.2.0 you had to turn on the + "spellautoload" option, but in 2.2.1 that option is on by + default. + + :map doesn't list all user-defined maps. + 2.2.0 assumed that any map tied to a symbolic key was defined by + the system, so it wouldn't list it unless you said ":map all". + This means you couldn't see actions mapped to function keys. + 2.2.1 is smarter about this -- it adds a flag to indicate + whether the map was added by the user or created automatically + by the GUI. + + Command names were truncated in error messages. + When displaying a "bad command name" error message, 2.2.0 would + truncate the name at the first character that prevented it from + being recognized as a command. 2.2.1 displays the full name of + the bad command, exactly as you typed it. + + :man doesn't display backslashes correctly + The :man alias didn't handle backslashes very well, so pages + which use a lot of backslashes such as ":man groff_man" looked + bad. + + :%unr doesn't always remove all regions. + This mostly occured when running autocmds. It also affected the + :chregion command. + + :%j only joined two lines + The command ":1,%j" joins all lines but ":%j" only joined two. + + elvis.ini maps too much + The default "elvis.ini" file contained maps without the nosave + flag, so if you ran :mkexrc in an xterm, your ~/.elvisrc file + would contain maps that are present in all user interfaces and + for all termcap terminal types. + + :mkexrc can lose GUI-specific options + The :mkexrc command only saved GUI-specific options for the + current GUI. This means that running :mkexrc in the "termcap" + interface could clobber your default font for the "x11" + interface. 2.2.1 gets around this by storing all GUI-specific + options, even those for other GUIs or unknown GUIs, just so it + can save them in the ~/.elvisrc file. + +
  • looks ugly + Many HTML documents use this sequence of tags to generate lists + that have a bit of vertical whitespace between items. But 2.2.0 + was drawing the list item marker (bullet or number) on the blank + line, instead of the line where the paragraph's text starts. + 2.2.1 treats this as a special case -- it ignores the

    in + this context. + + security=safer is too strict + The "security=safer" setting didn't allow some command that it + should have allowed. This prevented some harmless and useful + commands such as "elvis -client foo" from working. To get this + working right, I had to overhaul the behavior of + "security=safer". It is no longer a more lenient superset of + "security=restricted". See ":help set security" for details. + + One consequence of this is that the "-S" flag now sets + security=restricted. + + :wq didn't work when security=safer or security=restricted. + The manual said it should. The new version of security=safer + doesn't allow any writing, but you can now :wq when + security=restricted. + + The "ax" text object didn't support tag names with hyphens + I've extended it to allow single hyphens but not double hyphens + (since double hyphens mark comments). It also allows colons, for + namespace control. + + dirperm(".") returns readonly + The dirperm() function didn't recognize directories correctly. + This was a bug in the way the "dir:" pseudo-protocol was + implemented. + + hlobject didn't allow commas + An increasing number of options in elvis store multiple values + in comma-delimited lists. The "hlobject" option can store + multiple values, but required them to be either crammed together + or delimited by spaces. Now it supports commas. + + rcssince didn't work + The rcssince alias (part of ":load since") is supposed to be + executed when a buffer is loaded, but it used some commands + which are illegal during initialization. Most of the commands + that are illegal during initialization are only illegal because + they're useless until the first file is loaded into a buffer. + The rcssince alias was actually running after the file was + loaded, so it should be allowed, but Elvis had a rather weak + idea of when "initialization" ends. + + :suspend didn't work + It wasn't in Elvis' internal command list correctly. The :stop + equivalent has always worked though. + + Backslashes aren't handled right in "simpler syntax" + If a "simpler syntax" expression started with \( or \$ then + Elvis should convert that to a literal ( or $ character. + Instead, 2.2.0 was leaving it as a literal \ followed by an + parenthesized subexpression, or $ variable substitution. (This + arose from trying to make an initial \\ remain unchanged so + Windows users could five UNC names such as \\machine\dir\file.) + + AliasLeave events + At the end of an alias, 2.2.0 generated an AliasEnter event when + it should have generated an AliasLeave event. + + :eval does not compute + The :eval command could get confused if the command that it runs + needs to evaluate an expression. This was because a static + buffer is used to return the results of evaluations, and :eval + didn't copy the result into a local buffer before trying to + execute it. + + Trouble with gzipped files + The ":load gzip" command (formerly ":load augz") sets up elvis + to automatically handle gzipped files. It has some problems, but + the two biggest problems are now fixed. + + One problem was that filtering commands always wrote out the + final newline to gunzip, even though that newline wasn't part of + the gzipped data. This caused gunzip to output an error message. + 2.2.1 doesn't write out the final newline when the + "partiallastline" option is set. + + The other main problem was that the file was initially displayed + in hex mode, even after the file had been gunzipped into text. + To get around this, elvis will now temporarily remove ".gz" from + the end of the file name, then rerun the "elvis.arf" script, and + then slap the ".gz" back on the file name again so the file can + be saved correctly. + + "x11" could generate a BadMatch error while exiting + This would occur if you start Elvis from an xterm, and then + exited the xterm before Elvis. Elvis will now ignore that + particular error. + + + +The following new features have been added: + + :nofold + Wipes out folds. This differs from :unfold in that :unfold + leaves some information behind to allow the region to be easily + refolded. :nofold leaves nothing behind. + + Persistent information + Elvis can store cursor positions and some other things between + invocations. See the "persistfile" and "persist" options. + + %< and #< in filenames + When giving file name arguments, you can use %< and #< to get + the name of the current or alternate file, with its extension + removed. For example, if you're editing "database_interface.c", + then you can get to "database_interface.h" by typing ":e %<.h". + + :phelp command + Like :help except that :phelp doesn't split the screen. Instead, + it saves your old cursor position on the tag stack and then + shows the help page in your current screen. + + X11 buttons can simulate keystrokes + The :gui command accepts a new notation for defining toolbar + buttons that simulate keystrokes instead of invoking an ex + command. This is useful when you want to do something with a + character selection; ex commands treat all selections as line + selections. + + The notation uses square brackets around the name. You can put + the characters to simulate after the closing square bracket. If + you omit those characters, then Elvis will simulate keystrokes + that spell out the button name, with the brackets included. You + can then set up a :map to convert that to something else. That + can be nice because elvis allows maps to be somewhat context + sensitive. + + Computed line addresses + In ex command lines, you can now use =option to pull a line + address from an option, or =(expression) for more complex + expressions. This is often handy in aliases. + + GDB interface + The core of a simple GDB interface is provided, to allow Elvis + and GDB to work together. This depends on Elvis' "x11" user + interface; you can't use it with the termcap interface. It is + implemented partly as a C program that acts as a "wrapper" + around GDB and parses its output for things that Elvis needs to + know, and partly as a set of aliases which receive that + information and act on it (e.g., by moving the cursor, or + changing the highlight of breakpoint lines). + + Generic "state" display + A new "state" option has been created. If the "show" option + contains the keyword "state", then the value of the "state" + option will be displayed at the bottom of the window. This can + be handy in complex alias packages. The GDB interface uses it to + indicate the debugged program's status. + + More function keys + The and function keys are now supported on most + platforms. I also tried to support shift and control function + keys, with some success on Linux. + + :map noselect ... + The :map command now supports a noselect flag. This is short for + "every context except select". + + :load scripts described + I've added a section to the "Tips" chapter describing the + scripts in Elvis' library. (These may be loaded via the :load + alias.) + + :source can read from a program + The :source command has been extended to allow it to read the + output of a program, and interpret that output as a series of ex + commands. For example, you could create a program that scans an + HTML document and outputs a series of :fold commands to allow + you to selective hide sections of it. + + incsearch partially supports history + When using incremental search, the final search expression is + stored in the search history. You can use arrow keys or ^Ok and + ^Oj to retrieve a previous search. Full editing is still only + supported for non-incremental searches, though. + diff -urN elvis-2.2_0/Makefile.in elvis-2.2_1/Makefile.in --- elvis-2.2_0/Makefile.in 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/Makefile.in 2004-03-26 22:35:30 +0100 @@ -1,5 +1,5 @@ # Makefile.in -# $Id: Makefile.in,v 2.121 2003/10/21 02:31:00 steve Exp $ +# $Id: Makefile.in,v 2.124 2004/03/19 23:02:53 steve Exp $ # # Makefile.in should not be modified! The "configure" script reads Makefile.in # and writes a customized Makefile by editing the values of the following @@ -71,7 +71,7 @@ # ctags and elvtags are the same program under different names. The $(EXE) on # the end is just in case this Makefile is reconfigured for an operating # system which requires the EXE macro to be something like ".exe". -ALL=elvis$(EXE) ref$(EXE) elvtags$(EXE) elvfmt$(EXE) +ALL=elvis$(EXE) ref$(EXE) elvtags$(EXE) elvfmt$(EXE) elvgdb$(EXE) ################################################################################ # The installation directories are relative to this @@ -107,7 +107,7 @@ ############################################################################### # Portable compilation rules -VERSION=2.2_0 +VERSION=2.2_1 MISC= BUGS README.html COPYING INSTALL Makefile.in configure instman.sh\ elvis.lsm makwin32.bat makmsdos.bat makos2.cmd e2 \ elvis.spec.in Announce-$(VERSION) @@ -137,12 +137,12 @@ LPSRCS= lpescape.c lpovrtyp.c lpps.c LPOBJS= lpescape$(OBJ) lpovrtyp$(OBJ) lpps$(OBJ) HDRS= $(OSHDRS) $(GUIHDRS) autocmd.h buffer.h buffer2.h calc.h color.h\ - cut.h descr.h digraph.h display.h display2.h draw.h draw2.h elvis.h\ - elvisio.h event.h ex.h gui.h gui2.h input.h lowbuf.h lp.h map.h\ - mark.h message.h message2.h misc.h more.h move.h need.h operator.h\ - opsys.h optglob.h options.h regexp.h region.h safe.h scan.h session.h\ - spell.h state.h state2.h tag.h tagsrch.h tagelvis.h version.h vi.h\ - vicmd.h window.h config.h + cut.h descr.h digraph.h display.h display2.h draw.h draw2.h elvctype.h\ + elvis.h elvisio.h event.h ex.h fold.h gui.h gui2.h input.h lowbuf.h\ + lp.h map.h mark.h message.h message2.h misc.h more.h move.h need.h\ + operator.h opsys.h optglob.h options.h regexp.h region.h safe.h scan.h\ + session.h spell.h state.h state2.h tag.h tagsrch.h tagelvis.h version.h\ + vi.h vicmd.h window.h config.h SRCS= $(OSSRCS) $(GUISRCS) $(LPSRCS) autocmd.c buffer.c calc.c color.c cut.c\ descr.c digraph.c display.c dmhex.c dmmarkup.c dmnormal.c dmsyntax.c\ draw.c event.c ex.c exaction.c exconfig.c exedit.c exmake.c exsubst.c\ @@ -199,6 +199,9 @@ fmt$(EXE): fmt.c os$(OS)$(SLASH)osdir.c $(CC) $(CFLAGS) fmt.c -o fmt$(EXE) +elvgdb$(EXE): elvgdb.c + $(CC) $(CFLAGS) elvgdb.c $(LIBS) -o elvgdb$(EXE) + verify$(EXE): $(HDRS) verify$(OBJ) $(OBJ1) $(OBJ2) $(CC) $(CFLAGS) verify$(OBJ) $(OBJ1) $(OBJ2) -o verify$(EXE) diff -urN elvis-2.2_0/README.html elvis-2.2_1/README.html --- elvis-2.2_0/README.html 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/README.html 2004-03-26 22:35:30 +0100 @@ -1,17 +1,17 @@ -README.html file for elvis 2.2 - +README.html file for Elvis 2.2 +

    -

    Quick intro to elvis 2.2, with links to source code and binaries

    +

    Quick intro to Elvis 2.2, with links to source code and binaries

    CONTENTS
     .---------------------------------------------------------------.
    -| This is not elvis' user manual!  The real documentation for   |
    -| elvis is located in its online help facility.  While running  |
    -| elvis, enter the command ":help" to see the table of contents.|
    +| This is not Elvis' user manual!  The real documentation for   |
    +| Elvis is located in its online help facility.  While running  |
    +| Elvis, enter the command ":help" to see the table of contents.|
     ^---------------------------------------------------------------^

    1. About this file

    This file is written in the HTML markup language. You can view it with any WWW viewer, such as Netscape. -You can also use elvis 2.2 to view it; this version of elvis +You can also use Elvis 2.2 to view it; this version of Elvis has the ability to view HTML documents, and print them. -

    If elvis 2.2 doesn't automatically start up in HTML mode when you +

    If Elvis 2.2 doesn't automatically start up in HTML mode when you view this file, then you'll need to force it into HTML mode by giving the command ":display html". -

    2. Differences between vi and elvis 2.2

    +

    2. Differences between vi and Elvis 2.2

    Elvis is a superset of vi. It runs on more operating systems than vi, it is free, @@ -61,7 +62,7 @@
  • A variety of display modes, including syntax coloring and HTML.
  • Online help, with hypertext links.
  • Enhanced tags, to support overloading in C++. -
  • Network support, so you can load/save files via FTP, or even use elvis as a light-weight Web browser. +
  • Network support, so you can load/save files via FTP, or even use Elvis as a light-weight Web browser.
  • Aliases, which allow you to define new ex commands.
  • Built-in calculator @@ -69,14 +70,14 @@

    For a more complete list, with links to detailed descriptions, check the online manual. -You can bring up the online manual by starting elvis and giving the command +You can bring up the online manual by starting Elvis and giving the command ":help". The list of extensions appears after the table of contents and a brief introduction.

    3. Differences between 2.1 and 2.2

    -The following is a summary of changes made since the release of elvis 2.1. +The following is a summary of changes made since the release of Elvis 2.1. These are in addition to any bug fixes.

    3.1 New EX commands

    @@ -127,7 +128,7 @@
    Closes all windows except this one.
    :preserve -
    Exit elvis, but don't delete the session file. +
    Exit Elvis, but don't delete the session file.
    :push
    This is similar to :e, except that :push @@ -225,7 +226,7 @@
    antialias, aasqueeze
    For "x11" only, the antialias option controls whether -elvis will use the Xft library to draw antialiased text. +Elvis will use the Xft library to draw antialiased text. Antialiased fonts tend to leave a much larger gap between lines, so the aasqueeze option gives you a way to reduce that gap, and get more lines on the screen. @@ -244,8 +245,8 @@ store attributes about the buffer, for use by your own maps and aliases.
    binary -
    This is set to indicate that elvis was invoked with a "-b" flag. -The default elvis.brf uses this to set the readeol +
    This is set to indicate that Elvis was invoked with a "-b" flag. +The default Elvis.brf uses this to set the readeol option to "binary" when appropriate.
    blinktime @@ -253,7 +254,7 @@ Setting it to 0 will disable blinking.
    cleantext -
    Controls when elvis erases old text. +
    Controls when Elvis erases old text. Its value is a comma-delimited set of keywords, which may include "short", "long", "bs", "input", and/or "ex". @@ -265,7 +266,7 @@ It's value is a comma-delimited list of keywords, which may include "dollar", "paren", "space", "special", "tilde", and "wildcard". Windows users may want to remove the "space" keyword, which will prevent -elvis from parsing spaces as name delimiters; this will make it easier to +Elvis from parsing spaces as name delimiters; this will make it easier to enter names with spaces in them.
    folding @@ -319,7 +320,7 @@
    prefersyntax
    You can set the prefersyntax option to one of -"never", "writable", "local", or "always" to control when elvis should +"never", "writable", "local", or "always" to control when Elvis should start displaying a file in the "syntax" display modes rather than one of the markup display modes such as "html". For example, after ":set prefersyntax=writable", whenever you edit @@ -419,7 +420,332 @@
    -

    4. Links to related files

    +

    4. Differences between 2.2.1 and 2.2.0

    +Elvis 2.2.1 is mostly a bug-fix update of 2.2.0. +A few new feature crept in though. + +

    4.1 Fixed bugs

    +
    + +
    :andale was using Luxi Mono fonts +
    The :andale alias (used in the "x11" user interface) +was actually using Luxi Mono fonts instead of Andale fonts. + +
    filenamerules broke newline handling +
    When I implemented the filenamerules option in 2.2.0, I accidentally +broke the way it parses newlines. +This is important if you remove the spaces keyword from +filenamerules, and then do something like +":n `grep foo *.txt`" +to sets the args list to all files containing "foo". + +
    HTTP User-agent: header line +
    When sending HTTP requests, Elvis should send a User-agent: header line. +Some web sites demand this. + +
    Default button names +
    In the "html" display mode, the <input type=submit> and +<input type=reset> tags should have the default values "Submit" and +"Reset" respectively. +In 2.2.0, they have no default. + +
    <hr/> shows ------------> +
    The "html" display mode had trouble with tags that end with "/>". +Elvis would display the > on the screen instead of hiding it. + +
    <Esc> +
    The <Esc> key should beep when pressed in visual command mode. + +
    Delayed screen updates in "x11" user interface +
    When a map times out, Elvis wasn't updating the screens immediately +in the "x11" user interface, which made it hard to detect that the map +had indeed timed out. + +
    "d)" could crash +
    In a file full of blank lines, "d)" caused 2.2.0 to dump core. + +
    :put from a cut buffer +
    The :put command wasn't accepting a cut buffer name argument. + +
    :dict didn't handle single words +
    The :dict alias (after ":load dict") didn't handle single-word +queries correctly. + +
    The directory editor's links were relative to the wrong directory. +
    If you used ":e dirname" to edit the directory "dirname", +then the links in the generated HTML weren't interpreted as being relative +to "dirname". They were treated as being relative to the current directory. + +
    "x11" converts <b> to ^K0062. +
    The "x11" user interface is too aggressive when trying to convert key names +from angle-bracket notation to raw characters. +If a map contains an HTML tag such as <b>, and the tag name happens to match +the name of a key such as the "b" key, then Elvis was trying to convert that +keystroke into a raw control sequence. + +
    ":normal cwFOO^[" didn't work +
    The c operator was implemented in a way that didn't work in the +:normal command. + +
    ".IP \(bu 4" had too large of an indent. +
    This is apparently due to the fact that "4" has no explicit scaling suffix, +and .IP was using the wrong default scaling factor. + +
    Hard to enter ^ in WinElvis on a Norwegian keyboard +
    WinElvis has always had a hard time with "dead keys", but now I'm hopeful +that it should work. The ^ key works in Norway now, at least. + +
    ":e +cmd file" didn't work +
    For the :e command and a few others, the "+" flag could only +handle a line number parameter, not a full ex command line. + +
    Typos in manual. +
    Many found and fixed. +Still many more to be found, I'm sure. + +
    :chregion always changes the comment +
    The :chregion shouldn't change the comment of an existing region unless +you give a new comment explicitly, or the old comment was merely the old +font name. + +
    ":set show=spell" doesn't work very well. +
    You need to load the whole dictionary to get good suggestions from the +spell checker. +In 2.2.0 you had to turn on the "spellautoload" option, but in 2.2.1 that +option is on by default. + +
    :map doesn't list all user-defined maps. +
    2.2.0 assumed that any map tied to a symbolic key was defined by the +system, so it wouldn't list it unless you said ":map all". +This means you couldn't see actions mapped to function keys. +2.2.1 is smarter about this -- it adds a flag to indicate whether the +map was added by the user or created automatically by the GUI. + +
    Command names were truncated in error messages. +
    When displaying a "bad command name" error message, 2.2.0 would truncate +the name at the first character that prevented it from being recognized as +a command. +2.2.1 displays the full name of the bad command, exactly as you typed it. + +
    :man doesn't display backslashes correctly +
    The :man alias didn't handle backslashes very well, +so pages which use a lot of backslashes such as ":man groff_man" looked bad. + +
    :%unr doesn't always remove all regions. +
    This mostly occured when running autocmds. +It also affected the :chregion command. + +
    :%j only joined two lines +
    The command ":1,%j" joins all lines but ":%j" +only joined two. + +
    elvis.ini maps too much +
    The default "elvis.ini" file contained maps without the +nosave flag, so if you ran :mkexrc in an xterm, +your ~/.elvisrc file would contain maps that are present in all user interfaces +and for all termcap terminal types. + +
    :mkexrc can lose GUI-specific options +
    The :mkexrc command only saved GUI-specific options for the +current GUI. +This means that running :mkexrc in the "termcap" interface could +clobber your default font for the "x11" interface. +2.2.1 gets around this by storing all GUI-specific options, even those for +other GUIs or unknown GUIs, just so it can save them in the ~/.elvisrc file. + +
    <li><p> looks ugly +
    Many HTML documents use this sequence of tags to generate lists that have +a bit of vertical whitespace between items. +But 2.2.0 was drawing the list item marker (bullet or number) on the blank +line, instead of the line where the paragraph's text starts. +2.2.1 treats this as a special case -- it ignores the <p> in this context. + +
    security=safer is too strict +
    The "security=safer" setting didn't allow some command that it should +have allowed. +This prevented some harmless and useful commands such as "elvis -client foo" +from working. +To get this working right, I had to overhaul the behavior of "security=safer". +It is no longer a more lenient superset of "security=restricted". +See ":help set security" for details. + +

    One consequence of this is that the "-S" flag now sets security=restricted. + +

    :wq didn't work when security=safer or security=restricted. +
    The manual said it should. +The new version of security=safer doesn't allow any writing, but you can +now :wq when security=restricted. + +
    The "ax" text object didn't support tag names with hyphens +
    I've extended it to allow single hyphens but not double hyphens +(since double hyphens mark comments). +It also allows colons, for namespace control. + +
    dirperm(".") returns readonly +
    The dirperm() function didn't recognize directories +correctly. +This was a bug in the way the "dir:" pseudo-protocol was implemented. + +
    hlobject didn't allow commas +
    An increasing number of options in elvis store multiple values in +comma-delimited lists. +The "hlobject" option can store multiple values, but required them to +be either crammed together or delimited by spaces. +Now it supports commas. + +
    rcssince didn't work +
    The rcssince alias (part of ":load since") is supposed to be executed +when a buffer is loaded, but it used some commands which are illegal during +initialization. +Most of the commands that are illegal during initialization are only +illegal because they're useless until the first file is loaded into a buffer. +The rcssince alias was actually running after the file was loaded, so it +should be allowed, but Elvis had a rather weak idea of when "initialization" +ends. + +
    :suspend didn't work +
    It wasn't in Elvis' internal command list correctly. +The :stop equivalent has always worked though. + +
    Backslashes aren't handled right in "simpler syntax" +
    If a "simpler syntax" expression started with \( or \$ then Elvis +should convert that to a literal ( or $ character. +Instead, 2.2.0 was leaving it as a literal \ followed by an parenthesized +subexpression, or $ variable substitution. +(This arose from trying to make an initial \\ remain unchanged so Windows +users could five UNC names such as \\machine\dir\file.) + +
    AliasLeave events +
    At the end of an alias, 2.2.0 generated an AliasEnter event when it +should have generated an AliasLeave event. + +
    :eval does not compute +
    The :eval command could get confused if the command that it runs +needs to evaluate an expression. +This was because a static buffer is used to return the results of evaluations, +and :eval didn't copy the result into a local buffer before trying to execute +it. + +
    Trouble with gzipped files +
    The ":load gzip" command (formerly ":load augz") +sets up elvis to automatically handle gzipped files. +It has some problems, but the two biggest problems are now fixed. +

    One problem was that filtering commands always wrote out the final newline +to gunzip, even though that newline wasn't part of the gzipped data. +This caused gunzip to output an error message. +2.2.1 doesn't write out the final newline when the "partiallastline" option +is set. +

    The other main problem was that the file was initially displayed in hex +mode, even after the file had been gunzipped into text. +To get around this, elvis will now temporarily remove ".gz" from the end of +the file name, then rerun the "elvis.arf" script, and then slap the ".gz" +back on the file name again so the file can be saved correctly. + +

    "x11" could generate a BadMatch error while exiting +
    This would occur if you start Elvis from an xterm, +and then exited the xterm before Elvis. +Elvis will now ignore that particular error. + +
    + +

    4.2 New features

    +
    + +
    :nofold +
    Wipes out folds. This differs from :unfold in that +:unfold leaves some information behind to allow the region to +be easily refolded. :nofold leaves nothing behind. + +
    Persistent information +
    Elvis can store cursor positions and some other things between invocations. +See the "persistfile" and "persist" options. + +
    %< and #< in filenames +
    When giving file name arguments, you can use %< and #< to get the name of +the current or alternate file, with its extension removed. +For example, if you're editing "database_interface.c", then you can get to +"database_interface.h" by typing ":e %<.h". + +
    :phelp command +
    Like :help except that :phelp doesn't split +the screen. +Instead, it saves your old cursor position on the tag stack and then shows +the help page in your current screen. + +
    X11 buttons can simulate keystrokes +
    The :gui command accepts a new notation for defining toolbar +buttons that simulate keystrokes instead of invoking an ex command. +This is useful when you want to do something with a character selection; +ex commands treat all selections as line selections. + +

    The notation uses square brackets around the name. +You can put the characters to simulate after the closing square bracket. +If you omit those characters, then Elvis will simulate keystrokes that +spell out the button name, with the brackets included. +You can then set up a :map to convert that to something else. +That can be nice because elvis allows maps to be somewhat context sensitive. + +

    Computed line addresses +
    In ex command lines, you can now use +=option to pull a line address from an option, or +=(expression) for more complex expressions. +This is often handy in aliases. + +
    GDB interface +
    The core of a simple GDB interface is provided, +to allow Elvis and GDB to work together. +This depends on Elvis' "x11" user interface; you can't use it with the termcap +interface. +It is implemented partly as a C program that acts as a "wrapper" around GDB +and parses its output for things that Elvis needs to know, and partly as a +set of aliases which receive that information and act on it (e.g., by moving +the cursor, or changing the highlight of breakpoint lines). + +
    Generic "state" display +
    A new "state" option has been created. +If the "show" option contains the keyword "state", then the value of the +"state" option will be displayed at the bottom of the window. +This can be handy in complex alias packages. +The GDB interface uses it to indicate the debugged program's status. + +
    More function keys +
    The <F11> and <F12> function keys are now supported on most +platforms. +I also tried to support shift and control function keys, with some success +on Linux. + +
    :map noselect ... +
    The :map command now supports a noselect flag. +This is short for "every context except select". + +
    :load scripts described +
    I've added a section to the "Tips" chapter describing the scripts +in Elvis' library. +(These may be loaded via the :load alias.) + +
    :source can read from a program +
    The :source command has been extended to allow it to read the output of +a program, and interpret that output as a series of ex commands. +For example, you could create a program that scans an HTML document and +outputs a series of :fold commands to allow you to selective +hide sections of it. + +
    incsearch partially supports history +
    When using incremental search, the final search expression is stored +in the search history. +You can use arrow keys or ^Ok and ^Oj to retrieve a previous search. +Full editing is still only supported for non-incremental searches, though. + +
    herefile script +
    After ":load herefile", Elvis should be able to highlight +"herefiles" in shell scripts. +Herefiles are text files embedded within the script itself, between +<<SYMBOL and a line containing just +SYMBOL. + +
    + +

    5. Links to related files

    The main download site is ftp.cs.pdx.edu. @@ -461,8 +787,8 @@ DOS programs won't be able to find them with their expected names, and vice versa. Consequently, you must use untardos.exe to unpack -elvis-2.2_0-msdos.tar.gz, and untarw32.exe to unpack -elvis-2.2_0-win32.tar.gz. +elvis-2.2_1-msdos.tar.gz, and untarw32.exe to unpack +elvis-2.2_1-win32.tar.gz. (Actually, I recently added a -m flag which forces untarw32.exe to convert long file names to short ones using the MS-DOS method.) @@ -472,21 +798,21 @@ For brief instructions on how to use untaros2, run it with no arguments. -
    elvis-2.2_0.tar.gz +
    elvis-2.2_1.tar.gz
    This is a gzipped tar archive of the source code and documentation for Elvis 2.2 and its related programs. -
    elvis-2.2_0-msdos.tar.gz +
    elvis-2.2_1-msdos.tar.gz
    This archive contains the documentation and MS-DOS executables for Elvis 2.2. -
    elvis-2.2_0-win32.tar.gz +
    elvis-2.2_1-win32.tar.gz
    This archive contains the documentation and Win32 executables for Elvis 2.2. These were compiled and tested under Windows95, but should work under WindowsNT 3.51 (or later) as well. -
    elvis-2.2_0-os2.tar.gz +
    elvis-2.2_1-os2.tar.gz
    This archive contains the documentation and OS/2 executables for Elvis 2.2. If this link is broken then look in Herbert's site, below. @@ -495,7 +821,7 @@ http://www.fh-wedel.de/pub/fh-wedel/staff/di/elvis/00-index.html
    This is where the OS/2 maintainer stores his most up-to-date versions. -It may be better than the elvis-2.2_0-os2.tar.gz file, above. +It may be better than the elvis-2.2_1-os2.tar.gz file, above. diff -urN elvis-2.2_0/autocmd.c elvis-2.2_1/autocmd.c --- elvis-2.2_0/autocmd.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/autocmd.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_autocmd[] = "$Id: autocmd.c,v 1.30 2003/10/19 23:13:33 steve Exp $"; +char id_autocmd[] = "$Id: autocmd.c,v 1.32 2004/03/21 23:24:41 steve Exp $"; #endif #ifdef FEATURE_AUTOCMD @@ -55,7 +55,7 @@ } nametbl[] = { { toCHAR("*"), {0x7fffffff, 0x3fffffff, 0x3fffffff}}, - { toCHAR("*"),/* without OPTBITS */ {0x7fffffff, 0x3ffff9ff, 0x3fffffff}}, + { toCHAR("*"),/* without OPTBITS */ {0x7fffffff, 0x3fff3fff, 0x3fffffff}}, /* file events */ { toCHAR("BufCreate"), {0x00000001, 0x00000000, 0x00000000}}, @@ -147,7 +147,9 @@ { NULL, /* AU_USER29 */ {0x00000000, 0x00000000, 0x10000000}}, { NULL, /* AU_USER30 */ {0x00000000, 0x00000000, 0x20000000}}, }; -#define OPTBITS 0x00003000 +#define OPTBITS 0x0000c000 /* aubits.otherevents, OptSet and OptChanged */ +#define UGLYBIT 0x40000000 /* aubits.otherevents, marks old synonym */ +#define BANGBIT 0x40000000 /* aubits.userevents, marks :auevent! names */ #ifdef USE_PROTOTYPES static ELVBOOL wildmatch(char *fname, char *wildlist); @@ -341,10 +343,10 @@ } /* strip off the "ugly" bit */ - bits.otherevents &= ~0x40000000; + bits.otherevents &= ~UGLYBIT; /* strip off the "internal" bit */ - bits.userevents &= ~0x40000000; + bits.userevents &= ~BANGBIT; /* return the combined bits */ return &bits; @@ -368,7 +370,7 @@ nbits = &nametbl[i].bits; if ((bits.fileevents & nbits->fileevents) != nbits->fileevents || (bits.otherevents & nbits->otherevents) != nbits->otherevents - || (bits.userevents & nbits->userevents) != (nbits->userevents & ~0x40000000)) + || (bits.userevents & nbits->userevents) != (nbits->userevents & ~BANGBIT)) continue; /* add this event to the name */ @@ -437,8 +439,8 @@ continue; /* skip if is/isn't set up using standard scripts */ - if ((nametbl[i].bits.userevents & 0x40000000) != - (long)(xinf->bang ? 0x40000000 : 0x0)) + if ((nametbl[i].bits.userevents & BANGBIT) != + (long)(xinf->bang ? BANGBIT : 0x0)) continue; /* output a space or newline, if necessary */ @@ -490,7 +492,7 @@ /* also mark it as being "internal" if ! flag */ if (xinf->bang) - nametbl[i].bits.userevents |= 0x40000000; + nametbl[i].bits.userevents |= BANGBIT; ContinueContinue: ; } @@ -977,7 +979,7 @@ } /* if requested group not found, fail */ - if (!anygrp) + if (groupname && !anygrp) { msg(MSG_ERROR, "no such augroup"); goto Error; @@ -1044,29 +1046,23 @@ BUFFER custom; /* the buffer to which the :au commands are added */ { ELVBOOL anygrp; /* any groups output yet? */ - MARKBUF end; aug_t *group; au_t *au; CHAR *cmd, *word; int i; - end.buffer = custom; - /* for each event... */ for (i = 2; i < QTY(nametbl) && nametbl[i].name; i++) { /* skip if built-in, or defined in a standard script */ if (nametbl[i].bits.userevents == 0 - || (nametbl[i].bits.userevents & 0x40000000) != 0) + || (nametbl[i].bits.userevents & BANGBIT) != 0) continue; /* output a command to recreate this event type */ - end.offset = o_bufchars(custom); - bufreplace(&end, &end, toCHAR("try aue "), 8L); - end.offset = o_bufchars(custom); - bufreplace(&end, &end, nametbl[i].name, (long)CHARlen(nametbl[i].name)); - end.offset = o_bufchars(custom); - bufreplace(&end, &end, toCHAR("\n"), 1L); + bufappend(custom, toCHAR("try aue "), 8L); + bufappend(custom, nametbl[i].name, 0); + bufappend(custom, toCHAR("\n"), 1L); } /* for each group... */ @@ -1080,12 +1076,9 @@ anygrp = ElvTrue; /* start this group */ - end.offset = o_bufchars(custom); - bufreplace(&end, &end, toCHAR("try aug "), 8L); - end.offset = o_bufchars(custom); - bufreplace(&end, &end, group->group, (long)CHARlen(group->group)); - end.offset = o_bufchars(custom); - bufreplace(&end, &end, toCHAR("\nthen {\n au!\n"), 13L); + bufappend(custom, toCHAR("try aug "), 8L); + bufappend(custom, group->group, 0); + bufappend(custom, toCHAR("\nthen {\n au!\n"), 13L); /* for each au in this group... */ for (au = group->au; au; au = au->next) @@ -1126,8 +1119,7 @@ } /* add the command to the buffer */ - end.offset = o_bufchars(custom); - bufreplace(&end, &end, cmd, CHARlen(cmd)); + bufappend(custom, cmd, CHARlen(cmd)); /* free the string form of the command */ safefree(cmd); @@ -1135,16 +1127,14 @@ } /* for au */ /* mark the end of this group */ - end.offset = o_bufchars(custom); - bufreplace(&end, &end, toCHAR("}\n"), 2); + bufappend(custom, toCHAR("}\n"), 2); } /* for group */ /* if any groups were output, then we need to end "if feature(...)" */ if (anygrp) { - end.offset = o_bufchars(custom); - bufreplace(&end, &end, toCHAR("try aug END\n"), 12L); + bufappend(custom, toCHAR("try aug END\n"), 12L); } } # endif /* FEATURE_MKEXRC */ diff -urN elvis-2.2_0/buffer.c elvis-2.2_1/buffer.c --- elvis-2.2_0/buffer.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/buffer.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_buffer[] = "$Id: buffer.c,v 2.150 2003/10/17 17:41:23 steve Exp $"; +char id_buffer[] = "$Id: buffer.c,v 2.160 2004/03/23 18:23:16 steve Exp $"; #endif #define swaplong(x,y) {long tmp; tmp = (x); (x) = (y); (y) = tmp;} @@ -18,6 +18,14 @@ static void proc(_BLKNO_ bufinfo, long nchars, long nlines, long changes, long prevloc, CHAR *name); # endif +# ifdef FEATURE_PERSIST +static CHAR *persistget(void); +static void persistload(BUFFER buf); +static ELVBOOL persistinternal(BUFFER buf); +static void persisthist(char *field, char *prompt, char *bufname, BUFFER persbuf); +static void persistbuf(BUFFER buf, BUFFER persbuf); +static void persistother(BUFFER buf, BUFFER persbuf); +# endif # ifdef DEBUG_ALLOC static void checkundo(char *where); static void removeundo(struct undo_s *undo); @@ -297,6 +305,812 @@ bufoptions(bufdefopts); } +#ifdef FEATURE_PERSIST +/* Return ElvTrue if a buffer is internal (not persistent) */ +static ELVBOOL persistinternal(buf) + BUFFER buf; /* a buffer to be saved, or NULL for all */ +{ + /* all buffers can't be internal */ + if (!buf) + return ElvFalse; + + if (o_internal(buf) + || !CHARncmp(o_bufname(buf), toCHAR("Elvis untitled"), 14) + || !o_filename(buf)) + return ElvTrue; + + return ElvFalse; +} + + +/* Return the next line, or NULL if there is no next line. The \n is stripped + * off, but there's guaranteed to be room in the buffer for it, so you can + * CHARcat(line, toCHAR("\n")) to put it back. This function assumes you've + * already called ioopen() to start reading the file. + */ +static CHAR *persistget() +{ + static CHAR line[300]; + CHAR *val; + + /* fetch the next line */ + *line = '\0'; + for (val = line; + val < &line[QTY(line) - 1] + && ioread(val, 1) == 1 + && *val != '\n'; + val++) + { + } + + /* if nothing read, then return NULL */ + if (*line == '\0') + return NULL; + + /* return the line */ + *val = '\0'; + return line; +} + +/* Load global persistent information */ +void bufpersistinit() +{ + ELVBOOL doex, dosearch, doargs; + BUFFER exbuf, searchbuf; + CHAR *line; + int i, nargs; + char **newargs; + int gotnext; + ELVBOOL oldhide; + + /* do nothing if persistfile is unset */ + if (!o_persistfile) + return; + + /* figure out what we're supposed to load */ + doex = (ELVBOOL)(calcelement(o_persist,toCHAR("ex")) != NULL); + dosearch = (ELVBOOL)(calcelement(o_persist,toCHAR("search")) != NULL); + doargs = (ELVBOOL)(calcelement(o_persist,toCHAR("args")) != NULL); + if (arglist && *arglist) + doargs = ElvFalse; /* already have args */ + + /* if not supposed to do any globals, then don't */ + if (!doex && !dosearch && !doargs) + return; + + /* try to open the file */ + oldhide = msghide(ElvTrue); + if (!ioopen(iofilename(tochar8(o_persistfile), '\0'), 'r', ElvFalse, ElvFalse, 't')) + { + (void)msghide(oldhide); + return; + } + (void)msghide(oldhide); + + /* locate the history buffers */ + exbuf = bufalloc(toCHAR(EX_BUF), 0, ElvTrue); + searchbuf = bufalloc(toCHAR(REGEXP_BUF), 0, ElvTrue); + + /* for each line up to the first bufname line... */ + nargs = 0; + gotnext = -1; + while ((line = persistget()) != NULL && CHARncmp(line, "bufname ", 8)) + { + /* skip blank lines. */ + if (!*line) + continue; + + /* handle it */ + if (*line == ':') + { + /* skip if not doing ex history */ + if (!doex) + continue; + + /* append to ex history */ + CHARcat(line, toCHAR("\n")); + bufappend(exbuf, line, 0); + } + else if (*line == '/' || *line == '?') + { + /* skip of not doing search history */ + if (!dosearch) + continue; + + /* append to search history */ + CHARcat(line, toCHAR("\n")); + bufappend(searchbuf, line, 0); + } + else if (!CHARncmp(line, "arg ", 4)) + { + /* skip if not doing args */ + if (!doargs) + continue; + + /* append to the args list */ + newargs = safealloc(nargs + 2, sizeof(char *)); + for (i = 0; i < nargs; i++) + newargs[i] = arglist[i]; + newargs[nargs++] = safedup(tochar8(line + 4)); + newargs[nargs] = NULL; + if (arglist) + safefree(arglist); + arglist = newargs; + } + else if (!CHARncmp(line, "argnext ", 8)) + { + /* skip if not doing args */ + if (!doargs) + continue; + + /* remember the "argnext" value for later */ + gotnext = (int)CHAR2long(line + 8); + } + } + + /* maybe restore argnext */ + if (doargs && gotnext > 0 && gotnext <= nargs) + argnext = gotnext - 1; /* so we start on the one before next */ + + /* close the file */ + (void)ioclose(); +} + +/* Load the peristent information about a given buffer */ +static void persistload(buf) + BUFFER buf; +{ + CHAR *line; + char *line8; + long cursor, change; /* found cursor & change */ + int hours; /* age of found timestamp for entry */ + int gotYYYY, gotMM, gotDD, gothh, gotmm; /* parsed timestamp */ + int nowYYYY, nowMM, nowDD, nowhh, nowmm; /* parsed current time */ + ELVBOOL domarks; /* supposed to load marks? */ + ELVBOOL skip; + char markname[2]; + CHAR *phours; + long value; + int i; + ELVBOOL oldhide; + long oldbuflines, oldbufchars; + CHAR *external; +#ifdef FEATURE_REGION + ELVBOOL doregions; /* supposed to load regions? */ + int regions; /* found number of regions */ + _char_ face; + char facename[50]; +#endif +#ifdef FEATURE_FOLD + ELVBOOL dofolds; /* supposed to load folds? */ + int folds; /* found number of folds */ + FOLD newfold; +#endif +#if defined(FEATURE_REGION) || defined(FEATURE_FOLD) + long top, bottom; + MARKBUF marktop, markbottom; + char comment[300]; +#endif + + /* if the persistfile option is unset, then do nothing */ + if (!o_persistfile) + return; + + /* do nothing for internal buffers, buffers without a filename, or + * untitled buffers. + */ + if (persistinternal(buf)) + return; + + /* Try to open the file */ + oldhide = msghide(ElvTrue); + if (!ioopen(iofilename(tochar8(o_persistfile), '\0'), 'r', ElvFalse, ElvFalse, 't')) + { + (void)msghide(oldhide); + return; + } + (void)msghide(oldhide); + + /* detect whether we're supposed to load some specific things */ + domarks = (ELVBOOL)(calcelement(o_persist,toCHAR("marks")) != NULL); +#ifdef FEATURE_REGION + doregions = (ELVBOOL)(calcelement(o_persist,toCHAR("regions")) != NULL); +#endif +#ifdef FEATURE_FOLD + dofolds = (ELVBOOL)(calcelement(o_persist,toCHAR("folds")) != NULL); +#endif + + /* for now, assume buflines and bufchars won't change */ + oldbuflines = o_buflines(buf); + oldbufchars = o_bufchars(buf); + external = calcelement(o_persist, toCHAR("external")); + if (external && *external == ':') + external++; + else + external = toCHAR("b"); + + /* For each line... */ + cursor = change = -1L; + hours = 0; +#ifdef FEATURE_REGION + regions = 0; +#endif +#ifdef FEATURE_FOLD + folds = 0; +#endif + skip = ElvTrue; + while ((line = persistget()) != NULL) + { + /* is it a bufname line? */ + if (!CHARncmp(line, toCHAR("bufname "), 8)) + { + /* is this the end of this buffer's section? */ + if (!skip) + break; + + /* is it the start of this buffer's section */ + skip = (ELVBOOL)(CHARcmp(line+8, o_bufname(buf)) != 0); + } + + /* skip if not for this buffer */ + if (skip) + continue; + + /* is it the entry's timestamp? */ + line8 = tochar8(line); + if (sscanf(line8, "hours %4d%2d%2dT%2d:%2d", + &gotYYYY, &gotMM, &gotDD, &gothh, &gotmm) == 5) + { + /* get the current timestamp */ + sscanf(dirtime(NULL), "%4d%2d%2dT%2d:%2d", + &nowYYYY, &nowMM, &nowDD, &nowhh, &nowmm); + + /* compute the hours between them (sloppily) */ + if (nowYYYY > gotYYYY) + nowMM += 12; + if (nowMM > gotMM) + nowDD += 28;/* best to err on the low side */ + hours = ((nowmm - gotmm) + 60 * (nowhh - gothh) + 1440 * (nowDD - gotDD)) / 60; + continue; + } + + /* is it the number of expected lines or characters? */ + if (sscanf(line8, "bufchars %ld", &value) == 1) + { + oldbufchars = value; + continue; + } + if (sscanf(line8, "buflines %ld", &value) == 1) + { + oldbuflines = value; + continue; + } + + /* is it the cursor? */ + if (sscanf(line8, "cursor %ld", &value) == 1) + { + /* adjust for external changes */ + switch (*external) + { + case 't': + /* adjust relative to bottom */ + value += o_bufchars(buf) - oldbufchars; + break; + + case 's': + /* skip if different */ + if (oldbufchars != o_bufchars(buf)) + continue; + break; + } + + /* store the value as the buffer's "docursor" */ + if (value >= 0 && value < o_bufchars(buf)) + cursor = value; + continue; + } + + /* is it the change position? */ + if (sscanf(line8, "change %ld", &value) == 1) + { + /* adjust for external changes */ + switch (*external) + { + case 't': + /* adjust relative to bottom */ + value += o_bufchars(buf) - oldbufchars; + break; + + case 's': + /* skip if different */ + if (oldbufchars != o_bufchars(buf)) + continue; + break; + } + + /* store the value as the buffer's "last change" */ + if (value >= 0 && value < o_bufchars(buf)) + change = value; + continue; + } + + /* is it a specific mark? and do we care? */ + if (sscanf(line8, "mark %1[a-z] %ld", markname, &value) == 2) + { + /* if not doing marks, then skip it */ + if (!domarks) + continue; + + /* adjust for external changes */ + switch (*external) + { + case 't': + /* adjust relative to bottom */ + value += o_bufchars(buf) - oldbufchars; + break; + + case 's': + /* skip if different */ + if (oldbufchars != o_bufchars(buf)) + continue; + break; + } + + /* if invalid position, then skip it */ + if (value < 0 || value >= o_bufchars(buf)) + continue; + + /* restore the mark */ + i = markname[0] - 'a'; + if (namedmark[i]) + { + marksetbuffer(namedmark[i], buf); + marksetoffset(namedmark[i], value); + } + else + { + namedmark[i] = markalloc(buf, value); + } + continue; + } + +#ifdef FEATURE_REGION + /* is it a region? */ + if (sscanf(line8, "region %ld,%ld %s %[^\n]", &top, &bottom, facename, comment) == 4) + { + /* skip if not doing regions */ + if (!doregions) + continue; + + /* adjust for external changes */ + switch (*external) + { + case 't': + /* adjust relative to bottom */ + top += o_buflines(buf) - oldbuflines; + bottom += o_buflines(buf) - oldbuflines; + break; + + case 's': + /* skip if different */ + if (oldbuflines != o_buflines(buf)) + continue; + break; + } + + /* skip if invalid */ + if (top < 1 || top > bottom || bottom > o_buflines(buf)) + continue; + + /* rebuild the region */ + face = colorfind(toCHAR(facename)); + if (!face) + break; + regionadd(marksetline(marktmp(marktop, buf, 0), top), + marksetline(marktmp(markbottom, buf, 0), bottom+1), + face, toCHAR(comment)); + } +#endif /* FEATURE_REGION */ + +#ifdef FEATURE_FOLD + /* is it a fold or unfold? */ + if (sscanf(line8, " fold %ld,%ld %[^\n]", + &top, &bottom, comment) == 3 + || sscanf(line8, " unfold %ld,%ld %[^\n]", + &top, &bottom, comment) == 3) + { + /* skip if we aren't doing folds */ + if (!dofolds) + continue; + + /* adjust for external changes */ + switch (*external) + { + case 't': + /* adjust relative to bottom */ + top += o_buflines(buf) - oldbuflines; + bottom += o_buflines(buf) - oldbuflines; + break; + + case 's': + /* skip if different */ + if (oldbuflines != o_buflines(buf)) + continue; + break; + } + + /* skip if invalid */ + if (top < 1 || top > bottom || bottom > o_buflines(buf)) + continue; + + /* create the new fold */ + (void)marksetline(marktmp(marktop, buf, 0), top); + (void)marksetline(marktmp(markbottom, buf, 0),bottom+1); + markaddoffset(&markbottom, -1L); + newfold = foldalloc(&marktop, &markbottom, toCHAR(comment)); + + /* there shouldn't be any overlapping folds, + * but just to be safe... + */ + (void)foldbyrange(newfold->from, newfold->to, + ElvTrue, FOLD_NOEXTRA|FOLD_DESTROY); + (void)foldbyrange(newfold->from, newfold->to, + ElvFalse, FOLD_NOEXTRA|FOLD_DESTROY); + + /* add it as a fold or unfold */ + foldadd(newfold, (ELVBOOL)(*line8 == 'f')); + } +#endif /* FEATURE_FOLD */ + } + + /* close the file */ + (void)ioclose(); + + /* get the persist.hours value */ + phours = calcelement(o_persist, toCHAR("hours")); + if (phours) + phours++; + + /* clobber cursor and/or change, if not supposed to load */ + if (!calcelement(o_persist, toCHAR("cursor"))) + cursor = -1L; + if (!calcelement(o_persist, toCHAR("change"))) + change = -1L; + + /* if it hasn't expired then restore cursor */ + if (!phours || hours < atoi(tochar8(phours))) + { + if (cursor >= 0) + { + buf->docursor = cursor; + if (change >= 0) + buf->changepos = change; + } + else if (change >= 0) + buf->docursor = change; + } + else /* maybe still restore '' mark */ + { + if (cursor >= 0) + buf->changepos = cursor; + else if (change >= 0) + buf->changepos = change; + } +} + +/* Append the end of a history buffer to persbuf */ +static void persisthist(field, prompt, bufname, persbuf) + char *field; /* name of field in 'persist' option */ + char *prompt; /* acceptable prompt characters: ":" or "/?" */ + char *bufname; /* name of buffer containing history */ + BUFFER persbuf; /* temp buffer used to construct persistfile */ +{ + long lines; /* number of lines to keep */ + CHAR *scan; + BUFFER histbuf; + MARK mark; + MARKBUF histeol, persend; + + /* locate the history buffer. If not found, there's nothing to save */ + histbuf = buffind(toCHAR(bufname)); + if (!histbuf || o_bufchars(histbuf) == 0L) + return; + + /* get the number of lines to keep. If 0, then save nothing */ + scan = calcelement(o_persist, toCHAR(field)); + if (!scan || *scan++ != ':') + return; + for (lines = 0; elvdigit(*scan); scan++) + lines = lines * 10 + *scan - '0'; + if (lines == 0) + return; + + /* locate the first line to copy */ + mark = markalloc(histbuf, 0L); + if (lines < o_buflines(histbuf)) + marksetline(mark, o_buflines(histbuf) - lines + 1); + + /* for each line in history ... */ + scanalloc(&scan, mark); + for(;;) + { + /* find the end of the line */ + while (scan && *scan != '\n') + scannext(&scan); + if (!scan) + break; + scannext(&scan); + + /* if line starts with prompt char, then copy it */ + if (CHARchr(toCHAR(prompt), scanchar(mark)) != NULL) + { + /* need to stop scanning while changing */ + if (scan) + histeol = *scanmark(&scan); + else + { + histeol.buffer = histbuf; + histeol.offset = o_bufchars(histbuf); + } + + /* copy the history to the end of the persist buffer */ + bufpaste(marktmp(persend, persbuf, o_bufchars(persbuf)), + mark, &histeol); + + /* resume scanning. we changed persbuf, not histbuf, * so the offset of previous scan should be good + */ + if (scan) + scanalloc(&scan, &histeol); + } + + /* move the mark to the start of the next line */ + if (!scan) + break; + marksetoffset(mark, histeol.offset); + } + + markfree(mark); +} + +/* Append information describing one buffer */ +static void persistbuf(buf, persbuf) + BUFFER buf; /* the buffer to be stored */ + BUFFER persbuf;/* temp buffer used to construct new persistfile */ +{ + char line[300]; + int i; +#ifdef FEATURE_REGION + struct region_s *region; +#endif +#ifdef FEATURE_FOLD + FOLD fold; +#endif + + /* always start with a "bufname" line, and timestamp */ + sprintf(line, "bufname %.289s\nhours %s\n", + o_bufname(buf), dirtime(NULL)); + bufappend(persbuf, toCHAR(line), 0); + + /* always store bufchars, buflines, cursor, and change */ + sprintf(line, "bufchars %ld\nbuflines %ld\ncursor %ld\nchange %ld\n", + o_bufchars(buf), o_buflines(buf), buf->docursor,buf->changepos); + bufappend(persbuf, toCHAR(line), 0); + + /* maybe store the named marks */ + if (calcelement(o_persist, toCHAR("marks"))) + { + /* for each mark... */ + for (i = 0; i < QTY(namedmark); i++) + { + /* skip if unset, or in a different buffer */ + if (!namedmark[i] || markbuffer(namedmark[i]) != buf) + continue; + + /* save it */ + sprintf(line, "mark %c %ld\n", + 'a'+i, markoffset(namedmark[i])); + bufappend(persbuf, toCHAR(line), 0); + } + } + +#ifdef FEATURE_REGION + /* maybe save regions */ + if (calcelement(o_persist, toCHAR("regions"))) + { + /* for each region in this buffer... */ + for (region = buf->regions; region; region = region->next) + { + sprintf(line, "region %ld,%ld %s %s\n", + markline(region->from), markline(region->to)-1, + tochar8(colorinfo[(int)region->font].name), + tochar8(region->comment)); + bufappend(persbuf, toCHAR(line), 0); + } + } +#endif + +#ifdef FEATURE_FOLD + /* maybe save folds */ + if (calcelement(o_persist, toCHAR("folds"))) + { + /* save each fold... */ + for (fold = buf->fold; fold; fold = fold->next) + { + sprintf(line, "fold %ld,%ld %s\n", + markline(fold->from), markline(fold->to), + tochar8(fold->name)); + bufappend(persbuf, toCHAR(line), 0); + } + + /* save each unfold... */ + for (fold = buf->unfold; fold; fold = fold->next) + { + sprintf(line, "unfold %ld,%ld %s\n", + markline(fold->from), markline(fold->to), + tochar8(fold->name)); + bufappend(persbuf, toCHAR(line), 0); + } + } +#endif +} + +/* Append file-specific information from the old persistent file onto the + * end of the new persistent buffer. Skip information for buffers that we've + * just explicitly updated via persistbuf(). + */ +static void persistother(buf, persbuf) + BUFFER buf; /* buffer to skip, or NULL to skip all current bufs */ + BUFFER persbuf;/* where to append the file's contents */ +{ + CHAR *line; + ELVBOOL skip; + long max; + + /* try to open the file */ + if (!ioopen(iofilename(tochar8(o_persistfile), '\0'), 'r', ElvFalse, ElvFalse, 't')) + { + return; + } + + /* initially we'll skip. We don't want to copy the global info */ + skip = ElvTrue; + + /* fetch the limit, if any */ + max = -1; + line = calcelement(o_persist, toCHAR("max")); + if (line && *line++ == ':') + { + for (max = 0; elvdigit(*line); line++) + max = max * 10 + *line - '0'; + if (*line == 'k' || *line == 'K') + max <<= 10; + else if (*line == 'm' || *line == 'M') + max <<= 20; + } + + /* for each line of the original persist file... */ + while ((line = persistget()) != NULL) + { + /* is it "bufname" line? */ + if (!CHARncmp(line, toCHAR("bufname "), 8)) + { + /* if the buffer has reached its limit, then break */ + if (max >= 0 && o_bufchars(persbuf) >= max) + break; + + /* is it a buffer we want to skip? */ + if (buf) + skip = (ELVBOOL)(!CHARcmp(line + 8, o_bufname(buf))); + else + { + for (skip = ElvFalse, buf = elvis_buffers; + !skip && buf; + buf = buf->next) + { + skip = (ELVBOOL)(!CHARcmp(line + 8, o_bufname(buf))); + } + buf = NULL; + } + } + + /* MINOR BUG HERE!!! This can eat the blank line before + * "bufname" line. + */ + + /* if we want to skip, then skip */ + if (skip) + continue; + + /* append this line */ + CHARcat(line, toCHAR("\n")); + bufappend(persbuf, line, 0); + } + + /* close the file */ + (void)ioclose(); +} + +/* save persistent information for a given buffer, or for all user buffers if + * buf==NULL. + */ +void bufpersistsave(buf) + BUFFER buf; /* buffer to be saved */ +{ + BUFFER persbuf; + MARKBUF head, tail; + ELVBOOL oldhide; + static ELVBOOL savedall = ElvFalse; + + /* if the persistfile option is unset, then do nothing */ + if (!o_persistfile) + return; + + /* if already saved all buffers, then don't save anything more. The + * "save all buffers" thing is only done during termination, before + * all of the individual buffers are freed. + */ + if (savedall) + return; + + /* if internal bffer, then don't do anything */ + if (persistinternal(buf)) + return; + + /* create a new temporary buffer. We'll use this to construct a new + * version of the persfile. + */ + persbuf = bufalloc(toCHAR(PERSIST_BUF), 0, ElvTrue); + if (o_bufchars(persbuf) > 0L) + { + bufreplace(marktmp(head, persbuf, 0L), + marktmp(tail, persbuf, o_bufchars(persbuf)), + NULL, 0L); + } + + /* save histories */ + persisthist("ex", ":", EX_BUF, persbuf); + persisthist("search", "/?", REGEXP_BUF, persbuf); + + /* maybe save args */ + if (calcelement(o_persist, toCHAR("args"))) + { + char line[300]; + int i; + + for (i = 0; arglist[i]; i++) + { + sprintf(line, "arg %.294s\n", arglist[i]); + bufappend(persbuf, toCHAR(line), 0); + } + sprintf(line, "argnext %d\n", argnext); + bufappend(persbuf, toCHAR(line), 0); + } + + /* save either this buffer, or all buffers */ + if (buf) + persistbuf(buf, persbuf); + else + { + /* scan through the list of buffers, and try to save them all */ + for (buf = elvis_buffers; buf; buf = buf->next) + if (!persistinternal(buf)) + persistbuf(buf, persbuf); + buf = NULL; + savedall = ElvTrue; + } + + /* add any other info from the old persist file */ + persistother(buf, persbuf); + + /* save the persist info */ + oldhide = msghide(ElvTrue); + bufwrite(marktmp(head, persbuf, 0), + marktmp(tail, persbuf, o_bufchars(persbuf)), + iofilename(tochar8(o_persistfile), '\0'), ElvTrue); + (void)msghide(ElvFalse); +} +#endif /* FEATURE_PERSIST */ + /* Create a buffer with a given name. The buffer will initially be empty; * if it is meant to be associated with a particular file, then the file must * be copied into the buffer in a separate operation. If there is already @@ -603,16 +1417,23 @@ * on the last character of the # expression, and the filename is returned. * Otherwise it returns NULL and the scan variable is undefined. * - * This is used for expanding # in filenames. + * This is used for expanding % and # in filenames. */ -CHAR *buffilenumber(refp) - CHAR **refp; +CHAR *buffilenumber(curbuf, refp, endptr) + BUFFER curbuf; /* current buffer, used for % substitution */ + CHAR **refp; /* reference to scanning variable */ + CHAR **endptr; /* if non-NULL, store end pointer here */ { long id; BUFFER buf; MARKBUF tmp; + ELVBOOL trim; + CHAR *name; + + assert(*refp && (**refp == '#' || **refp == '%')); - assert(*refp && **refp == '#'); + /* for now, assume we keep the filename extension */ + trim = ElvFalse; /* remember which buf we're scanning, so we can fix *refp after NULL */ buf = markbuffer(scanmark(refp)); @@ -621,40 +1442,85 @@ /* the scanning context is in a buffer */ /* get the buffer number */ - for (id = 0; scannext(refp) && elvdigit(**refp); ) + if (**refp == '%') { - id = id * 10 + **refp - '0'; + id = -1; + scannext(refp); } + else + for (id = 0; scannext(refp) && elvdigit(**refp); ) + { + id = id * 10 + **refp - '0'; + } - /* move back one character, so *refp points to final char. This - * can be tricky if we bumped into the end of the buffer. - */ - if (*refp) - (void)scanprev(refp); + /* if followed by '<' then we'll want to trim the extension */ + if (*refp && **refp == '<') + trim = ElvTrue; else - (void)scanseek(refp, marktmp(tmp, buf, o_bufchars(buf) - 1)); + { + /* move back one character, so *refp points to final + * char. This can be tricky if we bumped into the + * end of the buffer. + */ + if (*refp) + (void)scanprev(refp); + else + (void)scanseek(refp, marktmp(tmp, buf, o_bufchars(buf) - 1)); + } } else { /* The scanning context is in a string. */ /* get the buffer number */ - for (id = 0; elvdigit(*++*refp); ) + if (**refp == '%') { - id = id * 10 + **refp - '0'; + id = -1; + scannext(refp); } - --*refp; + else + { + for (id = 0; elvdigit(*++*refp); ) + { + id = id * 10 + **refp - '0'; + } + } + if (**refp == '<') + trim = ElvTrue; + else + --*refp; } - /* if 0, then use alternate file */ - if (id == 0) - return o_previousfile; + /* convert id to a name */ + if (id == -1) + /* use the current file */ + name = o_filename(curbuf); + else if (id == 0) + /* use alternate file */ + name = o_previousfile; + else + { + /* try to find a buffer with that value */ + for (buf = elvis_buffers; buf && o_bufid(buf) != id; buf = buf->next) + { + } + name = buf ? o_filename(buf) : NULL; + } + if (!name) + return NULL; - /* try to find a buffer with that value */ - for (buf = elvis_buffers; buf && o_bufid(buf) != id; buf = buf->next) + /* if necessary, trim the extension */ + if (endptr) { + *endptr = name + CHARlen(name); + if (trim) + { + while (*endptr != name && **endptr != '.') + (*endptr)--; + } } - return buf ? o_filename(buf) : NULL; + + return name; } @@ -783,6 +1649,9 @@ void *locals; # endif #endif +#ifdef FEATURE_PERSIST + ELVBOOL nopersist = ElvFalse; /* inhibit loading of persistent info? */ +#endif #ifdef FEATURE_AUTOCMD @@ -822,6 +1691,9 @@ else bufwilldo(marktmp(top, buf, 0), ElvTrue); bufreplace(marktmp(top, buf, 0), marktmp(end, buf, o_bufchars(buf)), (CHAR *)0, 0); +#ifdef FEATURE_PERSIST + nopersist = ElvTrue; +#endif } #ifdef FEATURE_REGION @@ -1044,6 +1916,10 @@ /* set the initial cursor offset to 0 */ buf->docursor = 0L; +#ifdef FEATURE_PERSIST + if (!nopersist) + persistload(buf); +#endif #ifdef FEATURE_AUTOCMD /* done loading. Any later changes may generate Edit events */ @@ -1175,6 +2051,11 @@ } #endif /* FEATURE_AUTOCMD */ +#ifdef FEATURE_PERSIST + /* save the persistent information */ + bufpersistsave(buffer); +#endif + /* transfer any marks to the dummy "bufdefopts" buffer */ while (buffer->marks) { @@ -2224,6 +3105,19 @@ didmodify(markbuffer(from)); } +/* Append text to a buffer. This is useful when constructing a buffer */ +void bufappend(buf, str, len) + BUFFER buf; /* buffer to receive the new text */ + CHAR *str; /* the new text */ + int len; /* length of the text, or 0 to use count it */ +{ + MARKBUF tail; + + if (len == 0) + len = CHARlen(str); + bufreplace(marktmp(tail, buf, o_bufchars(buf)), &tail, str, len); +} + /* Copy part of one buffer into another. "dst" is the destination (where * the pasted text will be inserted), and "from" and "to" describe the * portion of the source buffer to insert. diff -urN elvis-2.2_0/buffer.h elvis-2.2_1/buffer.h --- elvis-2.2_0/buffer.h 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/buffer.h 2004-03-26 22:35:29 +0100 @@ -143,7 +143,7 @@ BEGIN_EXTERNC extern void bufinit P_((void)); extern BUFFER bufalloc P_((CHAR *name, _BLKNO_ bufinfo, ELVBOOL internal)); -extern CHAR *buffilenumber P_((CHAR **refp)); +extern CHAR *buffilenumber P_((BUFFER curbuf, CHAR **refp, CHAR **endptr)); extern BUFFER buffind P_((CHAR *name)); extern BUFFER bufload P_((CHAR *bufname, char *filename, ELVBOOL reload)); extern BUFFER bufpath P_((CHAR *path, char *filename, CHAR *bufname)); @@ -152,4 +152,9 @@ extern void bufoptions P_((BUFFER buffer)); extern void buffree P_((BUFFER buffer)); extern void buftitle P_((BUFFER buffer, CHAR *title)); +extern void bufappend P_((BUFFER buf, CHAR *str, int len)); +#ifdef FEATURE_PERSIST +extern void bufpersistinit P_((void)); +extern void bufpersistsave P_((BUFFER buf)); +#endif END_EXTERNC diff -urN elvis-2.2_0/calc.c elvis-2.2_1/calc.c --- elvis-2.2_0/calc.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/calc.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_calc[] = "$Id: calc.c,v 2.143 2003/10/18 04:47:18 steve Exp $"; +char id_calc[] = "$Id: calc.c,v 2.145 2004/03/14 23:18:52 steve Exp $"; #endif #ifdef TRY @@ -136,6 +136,9 @@ # ifdef FEATURE_NORMAL toCHAR("normal"), # endif +# ifdef FEATURE_PERSIST + toCHAR("persist"), +# endif # ifdef FEATURE_PROTO toCHAR("proto"), # endif @@ -2268,12 +2271,17 @@ case '\\': /* In most contexts, a backslash is treated as a - * literal character. However, it can also be used to - * quote the special characters of a message string: - * dollar sign, parentheses, and the backslash itself. + * literal character; this works best in Windows names. + * However, it can also be used to quote the special + * characters of a message string: dollar sign, + * parentheses, and (except at the beginning of the + * line) the backslash itself. A \\ at the beginning + * of a line could be a Windows \\machine\dir\file name. */ expr++; - if (build == result || !*expr || !strchr("$()\\", *expr)) + if (!*expr + || (build == result && *expr == '\\') + || !strchr("$()", *expr)) { /* at front of expression, or if followed by * normal character - literal */ @@ -2727,7 +2735,7 @@ if (base > 0) { Mismatch: - msg(MSG_ERROR, "(\"()\") mismatch"); + msg(MSG_ERROR, "\\(\\) mismatch"); return (CHAR *)0; } diff -urN elvis-2.2_0/color.c elvis-2.2_1/color.c --- elvis-2.2_0/color.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/color.c 2004-03-26 22:35:29 +0100 @@ -1014,7 +1014,6 @@ { int i; CHAR cmd[200]; - MARKBUF end; guidot_t *scan; /* for each color role... */ @@ -1035,8 +1034,7 @@ CHARcat(cmd, toCHAR("\n")); /* append it to the buffer */ - (void)marktmp(end, buf, o_bufchars(buf)); - bufreplace(&end, &end, cmd, CHARlen(cmd)); + bufappend(buf, cmd, 0); } /* Append the colors for other GUIs too */ @@ -1049,8 +1047,7 @@ CHARcat(cmd, toCHAR("\n")); /* append it to the buffer */ - (void)marktmp(end, buf, o_bufchars(buf)); - bufreplace(&end, &end, cmd, CHARlen(cmd)); + bufappend(buf, cmd, 0); } } #endif /* FEATURE_MKEXRC */ diff -urN elvis-2.2_0/configure elvis-2.2_1/configure --- elvis-2.2_0/configure 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/configure 2004-03-26 22:35:30 +0100 @@ -1020,6 +1020,7 @@ #define FEATURE_TEXTOBJ /* text objects */ #define FEATURE_V /* the v/V/^V marking commands */ #${FEATURE_XFT:-undef} FEATURE_XFT /* support antialiased fonts in "x11" */ +#define FEATURE_PERSIST /* the persistfile option */ /* The FEATURE_CALC option, above, controls whether the calculator and all of * the features that depend on it should be included in elvis. You almost @@ -1215,6 +1216,14 @@ eof-gnome fi +# Remove the elvgdb program if X11 isn't available +if [ "$GUI_X11" != "define" ] +then +cat >> $tmp <Makefile && rm $tmp diff -urN elvis-2.2_0/data/elvgdb.ini elvis-2.2_1/data/elvgdb.ini --- elvis-2.2_0/data/elvgdb.ini 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/elvgdb.ini 2004-03-26 22:35:30 +0100 @@ -0,0 +1,69 @@ +# General pseudo-annotations +elvgdb-default: trace +elvgdb-init: brown fromgdb toelvis +elvgdb-term: fromgdb toelvis +elvgdb-trace: magenta +#elvgdb-trace: fromgdb toelvis table server +#elvgdb-all: trace + +# Prompts +pre-prompt pre-prompt-for-continue pre-query: bold blue +prompt: blue +prompt commands overload-choice query prompt-for-continue: flush server +post-prompt post-prompt-for-continue post-query: + +# Errors +pre-error error-begin: bold red +error: + +# Moving the cursor to the current execution point +source: fromgdb args toelvis + +# Adjusting breakpoints. This is tricky because GDB simply sends us a +# "breakpoints-invalid" message when something changes. To find out what +# changed, we need to force gdb to run an "info breakpoints" command and +# then parse the table that it generates. The result of this parsing will +# be a series of "breakpoints-table" messages, each describing one breakpoint. +# Note that the table may also contain other things like watchpoints. +breakpoints-invalid: fromgdb toelvis limit +breakpoints-table: table +record: record +breakpoints-table-end: toelvis +field0 field1 field3 field5: text bold +breakpoints-headers field2 field4: +field6 field7 field8 field9: red + +# Running state +starting: fromgdb toelvis +stopped: +breakpoint watchpoint: fromgdb args toelvis +signalled signal: fromgdb +signal-name: text +signal-name-end: toelvis +signal-string signal-string-end: +exited: fromgdb args toelvis + +# Listing stack frames +frames-invalid: +frame-begin frame-end: +function-call: +signal-handler-caller: +frame-address frame-address-end: +frame-function-name frame-args arg-end: bold red +frame-source-begin: +frame-source-file frame-source-file-end: +frame-source-line frame-source-end: +frame-where: + +# Displays +display-begin display-number-end display-format: +display-expression display-expression-end display-value: red +display-end: + +# Printed values +value-history-begin value-history-value value-history-end: +value-begin: fromgdb args text +value-end: toelvis +arg-begin arg-name-end arg-value: red +field-begin field-name-end field-value field-end: +array-section-begin elt elt-rep elt-rep-end array-section-end: diff -urN elvis-2.2_0/data/elvis.ali elvis-2.2_1/data/elvis.ali --- elvis-2.2_0/data/elvis.ali 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.ali 2004-03-26 22:35:30 +0100 @@ -25,11 +25,12 @@ (=b) set bd=man (=b)r !!man !* try (=b)1 s/^Reformatting.*ait\.\.\.$// - try (=b)% s/\\/\\\\/g + try (=b)% s/\\//g try (=b)% s/_\(.\)*\(.\)/\\fI\2\\fR/g try (=b)% s/.\(.\)*\(.\)/\\fB\2\\fR/g try (=b)% s/\\fR\\fB//g try (=b)% s/\\fR\\fI//g + try (=b)% s//\\\\/g (=b)1 i .nf (=b) set nomod nospell (=b)split @@ -126,13 +127,26 @@ "Use Andale mono font for the main font, and Courier for italic (X11 only) if !isnumber(!(14)1) then error usage: andale [fontsize] - set font="luxi mono*!(14)1" italicfont="courier*!(14)1i" + set font="andale mono*!(14)1" italicfont="courier*!(14)1i" } alias! fork { "Run a program in the background (X11 only) !! >/dev/null 2>&1 !* & } + + alias! gdb { + " Start gdb in an xterm, connected to elvis + if gui != "x11" + then error The :gdb alias only works with the "x11" user interface + if !alias("fromgdb") + then load gdb + if secret != 0 + then error Already running -- secret!=0 + let secret=rand(1000000000) + eval fork secret=(secret) xterm +ls -xrm "*allowSendEvents:true" -e elvgdb !* + } + } if feature("array") @@ -312,7 +326,7 @@ calc "Network protocols: ";(f ? f : "none") set f="" l="Other features: " - for i in alias array autocmd backtick browse cachedesc calc complete equaltilde fold g hlobject hlsearch image incsearch listchars litre lpr make mapdb misc mkexrc normal proto ram rcsid showtag smartargs spell split tags textobj v xft + for i in alias array autocmd backtick browse cachedesc calc complete equaltilde fold g hlobject hlsearch image incsearch listchars litre lpr make mapdb misc mkexrc normal persist proto ram rcsid showtag smartargs spell split tags textobj v xft do { if feature(i) then { @@ -336,11 +350,18 @@ let o = elvispath(f) if o == "" then error "!^" is not a known configuration file + "Choose a base directory if os=="msdos" || os=="os2" || os == "win32" then let d=$HOME/"dotelvis" else let d=$HOME/".elvis" + "If the directory doesn't exist yet, then create it if dirperm(d) == "new" then eval !mkdir "(d)" + "If we need a subdirectory and it doesn't exist yet, then create it + let n = dirname(d/f) + if dirperm(n) == "new" + then eval !mkdir "(n)" + "If customized file exists, then load it; else start with the default version let n = d / f if exists(n) then e (n) @@ -427,6 +448,9 @@ " until all of the :g commands are finished, and then do :%fold! to " fold them. + " Start by removing any folds already in the file + %nofold + " #if and #else directives g/^\s*#\s*[ie][fl]/ { local t a z diff -urN elvis-2.2_0/data/elvis.arf elvis-2.2_1/data/elvis.arf --- elvis-2.2_0/data/elvis.arf 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.arf 2004-03-26 22:35:30 +0100 @@ -70,7 +70,8 @@ case tex let! mapmode=bufdisplay """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Store the file's timestamp -let timestamp = time(filename) +if security != "restricted" +then let timestamp = time(filename) """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " EXECUTE MODELINES, IF "modeline" OPTION IS SET if modeline && buflines >= 1 && buflines <= modelines * 2 diff -urN elvis-2.2_0/data/elvis.awf elvis-2.2_1/data/elvis.awf --- elvis-2.2_0/data/elvis.awf 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.awf 2004-03-26 22:35:30 +0100 @@ -1,3 +1,4 @@ """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Update the timestamp -let timestamp = time(filename) +if security != "restricted" +then let timestamp = time(filename) diff -urN elvis-2.2_0/data/elvis.brf elvis-2.2_1/data/elvis.brf --- elvis-2.2_0/data/elvis.brf 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.brf 2004-03-26 22:35:30 +0100 @@ -1,4 +1,4 @@ """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " TAKE A GUESS AT THE BUFFER'S TYPE (unless already known) -if readeol == "text" +if readeol == "text" && security != "restricted" then let! readeol=fileeol(filename) diff -urN elvis-2.2_0/data/elvis.bwf elvis-2.2_1/data/elvis.bwf --- elvis-2.2_0/data/elvis.bwf 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.bwf 2004-03-26 22:35:30 +0100 @@ -1,10 +1,13 @@ " Check for changed timestamp (unless it was never set, or forced write) -if !bang && edited && timestamp != "" && time(filename) != timestamp -then error file's timestamp has changed +if security != "restricted" +then { + if !bang && edited && timestamp != "" && time(filename) != timestamp + then error file's timestamp has changed +} " Maybe make a backup -if backup && !newfile +if backup && !newfile && security == "normal" then { - switch os - case unix eval ! cp (filename) (filename).bak - default eval ! copy (filename) (dirname(filename) / basename(filename)).bak >NUL + switch os + case unix eval ! cp (filename) (filename).bak + default eval ! copy (filename) (dirname(filename) / basename(filename)).bak >NUL } diff -urN elvis-2.2_0/data/elvis.clr elvis-2.2_1/data/elvis.clr --- elvis-2.2_0/data/elvis.clr 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.clr 2004-03-26 22:35:30 +0100 @@ -13,7 +13,7 @@ color hlsearch boxed color keyword bold color libt like keyword italic - color linenumber gray + color lnum gray color link like formatted underlined blue or light blue color number Blue4 or light blue color other like keyword @@ -41,7 +41,7 @@ color hlsearch bold color keyword bold white or black color libt like keyword - color linenumber gray + color lnum gray color link underlined blue or light cyan color number light cyan or blue color other like keyword diff -urN elvis-2.2_0/data/elvis.ini elvis-2.2_1/data/elvis.ini --- elvis-2.2_0/data/elvis.ini 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.ini 2004-03-26 22:35:30 +0100 @@ -46,26 +46,26 @@ then set! nottyitalic if term=="xterm" then { - map! Op 0 - map! Oq 1 - map! Or 2 - map! Os 3 - map! Ot 4 - map! Ou 5 - map! Ov 6 - map! Ow 7 - map! Ox 8 - map! Oy 9 - map! On . - map! Ok + - map! Om - - map! Oj * - map! Oo / - map! OM - map! OH visual ^ - map OH ^ - map! OF visual $ - map OF $ + map! nosave Op 0 + map! nosave Oq 1 + map! nosave Or 2 + map! nosave Os 3 + map! nosave Ot 4 + map! nosave Ou 5 + map! nosave Ov 6 + map! nosave Ow 7 + map! nosave Ox 8 + map! nosave Oy 9 + map! nosave On . + map! nosave Ok + + map! nosave Om - + map! nosave Oj * + map! nosave Oo / + map! nosave OM + map! nosave OH visual ^ + map nosave OH ^ + map! nosave OF visual $ + map nosave OF $ } } " diff -urN elvis-2.2_0/data/elvis.syn elvis-2.2_1/data/elvis.syn --- elvis-2.2_0/data/elvis.syn 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/data/elvis.syn 2004-03-26 22:35:30 +0100 @@ -886,15 +886,15 @@ keyword else er err errlist erro error ev eval ex f file fold for foreach keyword g global go goto gu gui h help i if insert j join k l la last le keyword let list lo local lp lpr m ma mak make map mark me message mk -keyword mkexrc move n N new next Next no normal nu number o open p po pop -keyword pre previous print pu push put q qa qall quit r read red redo rew -keyword rewind s sN sNext sa saf safely sall sb sbb sbbrowse sbr sbrowse se -keyword set sh shell sl slast sn sne snew snext so source sp split sre -keyword srew srewind st sta stac stack stag stop subst substitute sus susp -keyword suspend switch t ta tag th then to try u una unab unabbr -keyword unabbreviate unb unbreak undo unfold unm unmap v ve version -keyword vglobal vi visual w wa warning wordf wordfile words wh while wi -keyword window wn wnext wq wquit write x xit y yank z +keyword mkexrc move n N new next Next no nof nofold noh nohlsearch normal nu +keyword number o open p po pop pre previous print pu push put q qa qall quit +keyword r read red redo rew rewind s sN sNext sa saf safely sall sb sbb +keyword sbbrowse sbr sbrowse se set sh shell sl slast sn sne snew snext so +keyword source sp split sre srew srewind st sta stac stack stag stop subst +keyword substitute sus susp suspend switch t ta tag th then to try u una unab +keyword unabbr unabbreviate unalias unb unbreak undo unfold unm unmap v ve +keyword version vglobal vi visual w wa warning wordf wordfile words wh while +keyword wi window wn wnext wq wquit write x xit y yank z anchor ^ " # & < = > @ ~ # note that ! is not listed as a keyword because it interferes with alias args comment " @@ -987,6 +987,38 @@ keyword include lastdrive menucolor menudefault menuitem numlock keyword set shell stacks submenu switches +# The "elvgdb.ini" file +language elvgdb.ini +extension elvgdb.ini +comment # +inword - +font annotation arg-begin arg-end arg-name-end arg-value array-section-begin +font annotation array-section-end breakpoint breakpoints-headers +font annotation breakpoints-invalid breakpoints-table breakpoints-table-end +font annotation commands display-begin display-end display-expression +font annotation display-expression-end display-format display-number-end +font annotation display-value elt elt-rep elt-rep-end elvgdb-default +font annotation elvgdb-init elvgdb-term elvgdb-trace error error-begin +font annotation exited field-begin field-end field-name-end field-value +font annotation field0 field1 field2 field3 field4 field5 field6 field7 +font annotation field8 field9 frame-address frame-address-end frame-args +font annotation frame-begin frame-end frame-function-name frame-source-begin +font annotation frame-source-end frame-source-file frame-source-file-end +font annotation frame-source-line frame-where frames-invalid function-call +font annotation overload-choice post-prompt post-prompt-for-continue +font annotation post-query pre-error pre-prompt pre-prompt-for-continue +font annotation pre-query prompt prompt prompt-for-continue query record +font annotation signal signal-handler-caller signal-name signal-name-end +font annotation signal-string signal-string-end signalled source starting +font annotation stopped value-begin value-end value-history-begin +font annotation value-history-end value-history-value watchpoint +font delimiter : +keyword args black blue bold brown cyan flush fromgdb gray green highlight +keyword limit magenta record red server table text toelvis trace underline +keyword white yellow +color annotation bold blue or light blue +color delimiter bold red + # Windows and LanManager INI files # Original version contributed by Jay Wardle # Modified by SK to take advantage of new Elvis features. diff -urN elvis-2.2_0/data/icons/vi.xpm elvis-2.2_1/data/icons/vi.xpm --- elvis-2.2_0/data/icons/vi.xpm 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/icons/vi.xpm 2004-03-26 22:35:30 +0100 @@ -0,0 +1,38 @@ +/* XPM */ +static char * vi_xpm[] = { +"32 32 3 1", +" c None", +". c white", +"X c black", +" ", +" ", +" ", +"...... ........ ", +"XXXXX. .XXXXXX. ", +".XXX. ..XXXX.. ", +"..XX. .XXX.. ", +" .XX. .XXX. ", +" .XX. ..XX.. ", +" .XX.. .XXX. .... ", +" .XXX. ..XX.. .XX. ", +" ..XX. .XXX. .XX. ", +" .XX. ..XXX. .... ", +" .XX.. .XXX.. ...... ", +" .XXX. .XXX. .XXXX. ", +" ..XX. ..XX.. ..XXX. ", +" .XX. .XXX. ..XX. ", +" .XX.. ..XXX. .XX. ", +" .XXX. .XXX.. .XX. ", +" ..XX. ..XXX. .XX. ", +" .XX. .XXX.. .XX. ", +" .XX....XXX. .XX. ", +" .XXX..XXX.. .XX. ", +" ..XX..XXX. .XX. ", +" .XX.XXXX. .XX. ", +" .XX.XXX.. .XX. ", +" .XXXXXX. ....XX.... ", +" ..XXXX.. ..XXXXXXXX.. ", +" .XXXX. .XXXXXXXXXX. ", +" ...... ............ ", +" ", +" "}; diff -urN elvis-2.2_0/data/scripts/augz.ex elvis-2.2_1/data/scripts/augz.ex --- elvis-2.2_0/data/scripts/augz.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/augz.ex 1970-01-01 01:00:00 +0100 @@ -1,16 +0,0 @@ -" This file contains a set of autocmds which allow elvis to read & write -" files that are compressed via gzip. -augroup gzip - au! - au BufReadPre,FileReadPre *.gz set reol=binary - au BufReadPost *.gz %!gunzip - au FileReadPost *.gz '[,']!gunzip - au BufReadPost,FileReadPost *.gz set reol=text nomodified bufdisplay=normal - au BufReadPost *.gz eval doau BufReadPost (basename(filename)) - au BufWritePost,FileWritePost *.gz eval mv (afile) (basename(afile)) - au BufWritePost,FileWritePost *.gz eval !gzip (basename(afile)) - au FileAppendPre *.gz eval !gunzip (afile) - au FileAppendPre *.gz eval !mv (basename(afile)) (afile) - au FileAppendPost *.gz eval !mv (afile) (basename(afile)) - au FileAppendPost *.gz eval !gzip (basename(afile)) -augroup END diff -urN elvis-2.2_0/data/scripts/dict.ex elvis-2.2_1/data/scripts/dict.ex --- elvis-2.2_0/data/scripts/dict.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/dict.ex 2004-03-26 22:35:30 +0100 @@ -12,6 +12,6 @@ alias dict { " Show the definition of a term in a new window local w="!*" - let w =~ s/ /\\ /g + let w =~ s/ /\\ /ge eval sp dict:(w) } diff -urN elvis-2.2_0/data/scripts/gdb.ex elvis-2.2_1/data/scripts/gdb.ex --- elvis-2.2_0/data/scripts/gdb.ex 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/scripts/gdb.ex 2004-03-26 22:35:30 +0100 @@ -0,0 +1,184 @@ +" Don't load this file yourself -- You should just run ":gdb programname". +" +" This file contains aliases commands that implement the GDB interface. +" The ":gdb" alias (which is defined in elvis.ali) loads this automatically, +" so you should never need to run ":load gdb" although it is harmless to do so. +" All of the aliases defined here are defined via ":alias!" (with a ! suffix) +" so they won't be saved by ":mkexrc" even though they are never unloaded, +" not even when the external gdb process terminates. + +if gui != "x11" +then error The gdb interface only works with elvis' "x11" user interface + +alias! tellgdb { + " Send a command to GDB + !elvgdb -t '!*' +} + +alias! markgdb { + "Set the 'g mark to a given file:line, and also move the cursor there + local f l w + let f="!1"[:1] + let l="!1"[:2] + if !isnumber(l) || !exists(f) + then error Usage: markgdb filename:linenumber + if filename == f + then { + (=f)=l mark g + 'g + } + else { + let w = window(f) + if w + then { + eval window (w) + (=f)=l mark g + eval (w): 'g + } + else { + if !buffer(f) + then { + e (f) + "if bufchars <= 1 + "then e (f) + "else split (f) + } + (=f)=l mark g + 'g + } + } +} + +alias highlightgdb { + "Mark a given line using a region + local f l + let f="!1"[:1] + let l="!1"[:2] + if !isnumber(l) || !exists(f) + then error Usage: highlightgdb filename:linenumber face [comment] + try (=f)=l region !2* + else { + if bufchars <= 1 + then e +"=l region !2*" (f) + else split +"=l region !2*" (f) + } +} + +alias! breakgdb { + " Toggle a breakpoint on the current line + if current("region") == "breakpoint" + then eval tellgdb server delete (current("rcomment")[2]) + else eval tellgdb server break (filename):(current("line")) +} + +alias! initgdb { + " Set up the GUI for GDB + + " Colors. + color! breakpoint on red + + " Buttons. Note that the button that tells gdb to do a "next" command can't + " be named [Next] because there's already a [Next] button. So we use + " MS-style [Step Over] for "next", and [Step In] for "step". + gui gap + gui Step In:tellgdb step + gui Step In"Single-step. For function calls, go into the function + gui Step Over:tellgdb next + gui Step Over"Single-step. Treat function calls as one big step + gui Until:eval tellgdb until (filename):(current("line")) + gui Until"Execute to a point at (or below) the cursor + gui Finish:tellgdb finish + gui Finish"Execute to the end of the current function + gui Continue:tellgdb cont + gui Continue"Execute until the next breakpoint + gui Break Here:breakgdb + gui Break Here=current("region")=="breakpoint" + gui Break Here"Set or clear a breakpoint at the cursor + gui Break At...:eval tellgdb break (a) + gui Break At...;"Where to break" (file)a; ="line or file:line or function" + gui Break At..."Set a breakpoint at a specified address + gui Up:tellgdb up + gui Up"Move up the stack, to the function that called this one + gui Down:tellgdb down + gui Down"Move back down the stack + gui Where:tellgdb where + gui Where"List the whole stack + gui Locals:tellgdb info locals + gui Locals"List values of local variables + gui Whatis:eval tellgdb whatis (current("word")) + gui Whatis?current("word") != "" + gui Whatis"Describe the symbol that the cursor is on + gui Print:eval tellgdb print (current("word")) + gui Print?current("word") != "" + gui Print"Print the value of the variable that the cursor is on + gui Run...:eval tellgdb run (g) + gui Run...;"Command line arguments" (file)g + gui Run...?state=="" || state<<6=="KILLED" || state<<6=="EXITED" + gui Run..."Start execution + gui End GDB:tellgdb quit + gui End GDB"Stop debugging, and exit GDB + + " Shift-K should print value of variable + let k=keywordprg + set keywordprg="tellgdb print $1" + + " The info shown at bottom of screen should include "state" + let s=show + set show="state region tag" + + " Discourage users from running :mkexrc while in GDB mode + alias mkexrc error You probably don't want to save settings while in GDB mode. +} + +alias! termgdb { + " Clean up after GDB terminates + all %unregion breakpoint + gui ~Step In + gui ~Step Over + gui ~Until + gui ~Finish + gui ~Continue + gui ~Break Here + gui ~Break At... + gui ~Up + gui ~Down + gui ~Where + gui ~Locals + gui ~Whatis + gui ~Print + gui ~Run... + gui ~End GDB + let keywordprg=k + let show=s + set secret=0 state="" + unalias mkexrc +} + +alias! fromgdb { + " Receive information from gdb + switch "!1" + case elvgdb-init initgdb + case elvgdb-term termgdb + case source markgdb !2 + case breakpoints-invalid { + all %unregion breakpoint + tellgdb server info breakpoints + } + case breakpoints-table { + if "!3" == "breakpoint" && "!4" == "y" + then highlightgdb !8 breakpoint Breakpoint !2 + } + case starting set state=RUNNING + case breakpoint set state="BREAKPOINT=!2" + case watchpoint set state="WATCHPOINT=!2" + case signal set state="CAUGHT=!2" + case signalled set state="KILLED=!2" + case exited set state="EXITED=!2" + case value-begin echo !3* + default echo fromgdb !* +} + +alias! print { + "Use gdb to print the value of an expression. (Doesn't affect :p) + tellgdb output !* +} diff -urN elvis-2.2_0/data/scripts/gzip.ex elvis-2.2_1/data/scripts/gzip.ex --- elvis-2.2_0/data/scripts/gzip.ex 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/scripts/gzip.ex 2004-03-26 22:35:30 +0100 @@ -0,0 +1,22 @@ +" This file contains a set of autocmds which allow elvis to read & write +" files that are compressed via gzip. +augroup gzip + au! + au BufReadPre,FileReadPre *.gz set reol=binary + au BufReadPost *.gz %!gunzip + au FileReadPost *.gz '[,']!gunzip 2>/dev/null + au BufReadPost,FileReadPost *.gz { + set reol=text nomodified + file! (basename(filename)) + source! (elvispath("elvis.arf")) + file! (filename).gz + set edited + } + au BufReadPost *.gz eval doau BufReadPost (basename(filename)) + au BufWritePost,FileWritePost *.gz eval mv (afile) (basename(afile)) + au BufWritePost,FileWritePost *.gz eval !gzip (basename(afile)) + au FileAppendPre *.gz eval !gunzip (afile) + au FileAppendPre *.gz eval !mv (basename(afile)) (afile) + au FileAppendPost *.gz eval !mv (afile) (basename(afile)) + au FileAppendPost *.gz eval !gzip (basename(afile)) +augroup END diff -urN elvis-2.2_0/data/scripts/herefile.ex elvis-2.2_1/data/scripts/herefile.ex --- elvis-2.2_0/data/scripts/herefile.ex 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/scripts/herefile.ex 2004-03-26 22:35:30 +0100 @@ -0,0 +1,9 @@ +"For shell scripts, use a region to highlight herefiles. +color herefile like comment black or white +aug herefile +au OptChanged bufdisplay { + if bufdisplay == "syntax sh" || knownsyntax(filename) == "sh" + then try %s#<<\\\?\(\S\+\)#+,/^\\s*\1$/-region herefile \1#x +} +au BufDelete all try %unr herefile +aug END diff -urN elvis-2.2_0/data/scripts/html.ex elvis-2.2_1/data/scripts/html.ex --- elvis-2.2_0/data/scripts/html.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/html.ex 2004-03-26 22:35:30 +0100 @@ -1,80 +1,105 @@ "This file contains some maps that are useful when editing XML or HTML code. -" When a > is input at the end of a tag, automatically add the closing tag -map input > noremap >mmFbi/`mli +alias htmlmap { + " Load maps for "html" display mode -" Make the % command match XML tags. This doesn't work as the destination of -" operator commands or during visual selections, though, so we only map it for -" commands. -map command % noremap :xmlmatch - -" Add <> to matchchar -set matchchar="{}()[]<>" - -alias xmlmatch { - "Move the cursor to the matching HTML or XML tag name - - "If not on tag name, then do the normal % character match - if current(/\i/) == "" - then normal % - else { - " d is the direction to search - " i counts nested tag pairs - " n is the tag name without any punctuation - " t is origin tag name without args or > - local d i n t - - "Configure search parameters to be "normal" - local nowrapscan magic magicchar=^$.[* magicname noincsearch ignorecase nosmartcase - - "HTML ignores case, but XML is case sensitive - if (tolower(dirext(filename)) << 4) == ".htm" - then set ignorecase - else set noignorecase - - "This particular alias doesn't really change the file, but it uses - "the :normal command which *can* change the file and hence is not - "allowed on locked buffers. Temporarily turn off locking. - local nolocked - - "Get the current tag name - let t=current(/<\/\i\+/) - if t - then { - let d="backward" - let n=t[,3...] - } - else { - let t=current(/<\i\+/) - if t - then { - let d="forward" - let n=t[,2...] - } - else error cursor isn't on a tag name - } - - " move to the start of this tag, so we don't immediately find it in - " the following search loop and mistake it for a nested tag. - normal F< - - "search for the tag, for nested tags. Stop on the matching one - normal mx - try { - set i=1 - while i > 0 - do { - "find the next opening or closing tag, in the proper direction - switch d - case forward normal /<\/\?\=$n\> - case backward normal ? - - "count nested tag levels - if current(/<\/\?$n/) == t - then let i = i + 1 - else let i = i - 1 - } - } - else normal `x + " Remove the special handing for > + unmap input mode=html > + + " Protect some characters when inserting in html display mode + map input mode=html noremap & & + map input mode=html noremap < < + map input mode=html noremap > > + + " No tag highlighting -- let tags do their own highlighting + set hlobject="" +} +alias htmlunmap { + " Load maps for "syntax html" display mode + + " Remove maps that protect some special HTML characters + unmap input mode=html & + unmap input mode=html < + unmap input mode=html > + + " When a > is input at the end of a tag, automatically add the closing tag + map input mode=html > noremap >Fpa>bi/hi + + " Highlight the innermost tag */ + set hlobject="ix,ax" +} +aug edithtml +au DispMapEnter html htmlmap +au DispMapLeave html htmlunmap +aug END +if display == "html" +then htmlmap +else htmlunmap + +" Add ax to matchchar -- lets you use % to find matching tag pairs +set matchchar="{}()[]ax" + +" Arrange for innermost tag to be highlighted later, when hlobject is set */ +if hllayers == 0 +then { + set hllayers=2 + if color("hlobject1") == "" + then color hlobject1 boxed + if color("hlobject2") == "" + then color hlobject2 bold +} + +" For X11, set up some buttons +if gui == "x11" +then { + gui gap + gui Heading: htmlblock pair h1 + gui Heading?current("selection")=="line" + gui Subheading: htmlblock pair h2 + gui Subheading?current("selection")=="line" + gui Left: htmlblock div left + gui Left?current("selection")=="line" + gui Right: htmlblock div right + gui Right?current("selection")=="line" + gui Center: htmlblock div center + gui Center?current("selection")=="line" + gui Bullet: htmlblock list ul + gui Bullet?current("selection")=="line" + gui Number: htmlblock list ol + gui Number?current("selection")=="line" + gui Preformat: htmlblock pair pre + gui Preformat?current("selection")=="line" + gui Other: eval htmlblock pair (t) + gui Other?current("selection")=="line" + gui Other;"HTML tag to add" t + gui gap + gui [Bold] + gui Bold?current("selection")=="line" || current("selection")=="character" + gui [Italic] + gui Italic?current("selection")=="line" || current("selection")=="character" + gui [Code] + gui Code?current("selection")=="line" || current("selection")=="character" + gui gap + gui Undo: u + alias htmlblock { + switch "!1" + case pair { + !> a + !< i + } + case div { + !> a + !< i
    + if "!2" != "left" + then warning Elvis doesn't display text aligned to the !2 + } + case list { + !% s/^/
  • / + !> a + !< i } + } + map select mode=html noremap [Bold] c>> + map select mode=html noremap [Italic] c>> + map select mode=html noremap [Code] c>> } diff -urN elvis-2.2_0/data/scripts/life.ex elvis-2.2_1/data/scripts/life.ex --- elvis-2.2_0/data/scripts/life.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/life.ex 2004-03-26 22:35:30 +0100 @@ -6,4 +6,253 @@ then set notoolbar nostatusbar noscrollbar if feature("incsearch") then set nois -so macros/life1.5.mac +" Macros to play Conway's Game of Life in vi +" Version 1.5 (aka 1.0m): edges wrap, critters age +" by Eli-the-Bearded (eli@netusa.net), Sept 1996 +" This file may be free distributed so long as these credits remain unchanged. +" +" Modified by Bram Moolenaar (mool@oce.nl), 1996 Sept 10 +" - Made it quite a bit faster, but now needs search patterns in the text +" - Changed the order of mappings to top-down. +" - Made "g" run the whole thing, "C" run one generation. +" - Added support for any uppercase character instead of 'X' +" +" Rules: +" If a germ has 0 or 1 live neighbors it dies of loneliness +" If a germ has 2 or 3 live neighbors it survives +" If a germ has 4 to 8 live neighbors it dies of starvation +" If an empty box has 3 live neighbors a new germ is born +" +" A new born germ is an "A". Every generation it gets older: B, C, etc. +" A germ dies of old age when it reaches "Z". +" +" Notice the rules do not mention edges. This version has the edges wrap +" around. I have an earlier version that offers the option of live edges or +" dead edges. Email me if you are interested. -Eli- +" +" Note: This is slow! One generation may take up to ten minutes (depends on +" your computer and the vi version). +" +" Quite a lot of the messy stuff is to work around the vi error "Can't yank +" inside global/macro". Still doesn't work for all versions of vi. +" +" To use these macros: +" +" vi start vi/vim +" +" :so life.mac Source this file +" +" g 'g'o! runs everything until interrupted: "IR". +" +" I Initialize everything. A board will be drawn at the end +" of the current buffer. All line references in these macros +" are relative to the end of the file and playing the game +" can be done safely with any file as the current buffer. +" +" Change the left field with spaces and uppercase letters to suit +" your taste. +" +" C 'C'ompute one generation. +" + idem, time running one generation. +" R 'R'un 'C'ompute until interrupted. +" 1Giz Make a number the only thing on the first line and use +" 'z' to time that many generations. +" +" Time to run ten generations on my 100Mhz 486 (FreeBSD): +" vi 3.7 3 min 54 sec +" vim 4.5 1 min 45 sec +" nvi 1.78 1 min 02 sec +" Elvis 1.8pl4 failed +" Elvis 2.0 failed +" +" +" And now the macros, more or less in top-down order. +" +" ----- macros that can be used by the human ----- +" +" 'g'o: 'I'nitialize and then 'R'un 'C'ompute recursively (used by the human) +map g IR +" +" +" 'R'un 'C'ompute recursively (used by the human and 'g'o) +map R CV +" work around "tail recursion" problem in vi, "V" == "R". +map V R +" +" +" 'I'nitialize the board (used by the human and 'g'o) +map I G)0)0)0)0)1)0)0)2)0)0)0)0,ok,-11k,-,R,IIN +" +" +" 'C'ompute next generation (used by the human and others) +map C T>>>>>>>>B& +" +" +" Time running one generation (used by the human) +map + <1C<2 +" +" +" Time running N generations, where N is the number on the current line. +" (used by the human) +map z ,^,&,*,&<1,*<2 +" +" ----- END of macros that can be used by the human ----- +" +" ----- Initialisation ----- +" +map ,- :s/./-/g +map ,o oPut 'X's in the left box, then hit 'C' or 'R' +map ,R 03stop +" +" Write a new line (used by 'I'nitialize board) +map )0 o- --....................--....................- +map )1 o- VIM --....................--....................- +map )2 o- LIVES --....................--....................- +" +" +" Initialisation of the pattern/command to execute for working out a square. +" Pattern is: "#" +" where is " " if the current germ is dead, "X" when living. +" is the number of living neighbours (including current germ) +" expressed in X's +" +map ,Il8 O#XXXXXXXXXX .`a22lr  +map ,Id8 o# XXXXXXXX .`a22lr  +map ,Il7 o#XXXXXXXXX .`a22lr  +map ,Id7 o# XXXXXXX .`a22lr  +map ,Il6 o#XXXXXXXX .`a22lr  +map ,Id6 o# XXXXXX .`a22lr  +map ,Il5 o#XXXXXXX .`a22lr  +map ,Id5 o# XXXXX .`a22lr  +map ,Il4 o#XXXXXX .`a22lr  +map ,Id4 o# XXXX .`a22lr  +map ,Il3 o#XXXXX .,a +map ,Id3 o# XXX .`a22lrA +map ,Il2 o#XXXX .,a +map ,Id2 o# XX .`a22lr  +map ,Il1 o#XXX .`a22lr  +map ,Id1 o# X .`a22lr  +map ,Il0 o#XX .`a22lr  +map ,Id0 o# .`a22lr  +" +" Patterns used to replace a germ with it's next generation +map ,Iaa o=AB =BC =CD =DE =EF =FG =GH =HI =IJ =JK =KL =LM =MN =NO =OP =PQ =QR +map ,Iab o=RS =ST =TU =UV =VW =WX =XY =YZ =Z  +" +" Insert the searched patterns above the board +map ,IIN G?^top ,Il8,Id8,Il7,Id7,Il6,Id6,Il5,Id5,Il4,Id4,Il3,Id3,Il2,Id2,Il1,Id1,Il0,Id0,Iaa,Iab +" +" ----- END of Initialisation ----- +" +" ----- Work out one line ----- +" +" Work out 'T'op line (used by show next) +map T G,c2k,!9k,@,#j>2k,$j +" +" Work out 'B'ottom line (used by show next) +map B ,%k>,$ +" +" Work out a line (used by show next, work out top and bottom lines) +map > 0 LWWWWWWWWWWWWWWWWWW,rj +" +" Refresh board (used by show next) +map & :%s/^\(-[ A-Z]*-\)\(-[ A-Z]*-\)\(-[.]*-\)$/\2\3\3/ +" +" +" Work around vi multiple yank/put in a single macro limitation +" (used by work out top and/or bottom line) +map ,$ dd +map ,% "cp +map ,! "byy +map ,@ "cyy +map ,# "bP +map ,c c$ +" +" ----- END of Work out one line ----- +" +" ----- Work out one square ----- +" +" The next three work out a square: put all nine chars around the current +" character on the bottom line (the bottom line must be empty when starting). +" +" 'W'ork out a center square (used by work out line) +map W makh,3`ah,3`ajh,3( +" +" +" Work out a 'L'eft square (used by work out line) +map L makf-h,1`ak,2`af-h,1`a,2`ajf-h,1`aj,2( +" +" +" Work out a 'R'ight square (used by work out line) +map ,r makh,2`akF-l,1`ah,2`aF-l,1`ajh,2`ajF-l,1( +" +" 'M'ove a character to the end of the file (used by all work out square +" macros) +" +map ,1 y G$p +map ,2 2y G$p +map ,3 3y G$p +" +" +" ----- END of Work out one square ----- +" +" ----- Work out one germ ----- +" +" Generate an edit command that depends on the number of living in the last +" line, and then run the edit command. (used by work out square). +" Leaves the cursor on the next character to be processed. +" +map ( ,s,i,X0i?^#A  0,df.l,Y21h +" +" Delete 's'paces (deads); +" The number of remaining characters is the number of living neighbours. +map ,s :.g/ /s///g +" +" Insert current character in the last line +map ,i `ay GP +" +" Replace any uppercase letter with 'X'; +map ,X :.g/[A-Z]/s//X/g +" +" Delete and execute the rest of the line +map ,d "qd$@q +" +" Yank and execute the rest of the line +map ,Y "qy$@q +" +" Yank the character under the cursor +map ,j y +" +" Put the current cut buffer after the cursor +map ,m p +" +" Delete the character under the cursor +map ,n x +" +" Replace a character by it's next, A --> B, B --> C, etc. +map ,a `a,jGi?=,ma 0,dll,j`a21l,ml,nh +" +" ----- END of Work out one germ ----- +" +" ----- timing macros ----- +" +" Get current date (used by time a generation) +map << :r!date +map <1 G?^top O<< +map <2 G?^top k<< +" +" +" Turn number on current line into edit command (used by time N generations) +map ,^ AiC +" +" +" Delete current line and save current line (used by time N generations) +map ,& 0"gd$ +" +" +" Run saved line (used by time N generations) +map ,* @g +" +" ----- END of timing macros ----- +" +" End of the macros. diff -urN elvis-2.2_0/data/scripts/likevim.ex elvis-2.2_1/data/scripts/likevim.ex --- elvis-2.2_0/data/scripts/likevim.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/likevim.ex 2004-03-26 22:35:30 +0100 @@ -39,6 +39,7 @@ map noremap select u noremap gu map noremap select ~ noremap g~ map noremap select J :j +map noremap select gJ :j! map noremap select  y:ta  map noremap select o g% map noremap select O g diff -urN elvis-2.2_0/data/scripts/mail.ex elvis-2.2_1/data/scripts/mail.ex --- elvis-2.2_0/data/scripts/mail.ex 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/scripts/mail.ex 2004-03-26 22:35:30 +0100 @@ -0,0 +1,11 @@ +"This defines a :Mail alias. This is intended mostly to be used when elvis +"is invoked as an external editor by a mail program such as Kmail or Sylpheed. +"The idea is that you'd configure the mail editor to run "elvis -cMail" as the +"external editor. To make that work, you'd need to run ":load mail" and +" ":mkexrc" first though. +alias Mail { + set bufdisplay="syntax email" equalprg="elvfmt -M" + display syntax email + color signature italic red on gray + try $;?^-- *$?,$ region signature +} diff -urN elvis-2.2_0/data/scripts/mailto.ex elvis-2.2_1/data/scripts/mailto.ex --- elvis-2.2_0/data/scripts/mailto.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/mailto.ex 2004-03-26 22:35:30 +0100 @@ -23,18 +23,3 @@ w !!mail -s"!(no subject)subject=" !2 >/dev/null 2>&1 se nomod } - -alias readMAN { - local report=0 nosaveregexp - local magic magicchar=^$.[* noignorecase - r !!man !2 - set bd=man - try 1 s/^Reformatting.*ait\.\.\.$// - try % s/\\/\\\\/g - try % s/_\(.\)/\\fI\1\\fR/g - try % s/.\(.\)/\\fB\1\\fR/g - try % s/\\fR\\fB//g - try % s/\\fR\\fI//g - 1 i .nf - set nomod -} diff -urN elvis-2.2_0/data/scripts/note.ex elvis-2.2_1/data/scripts/note.ex --- elvis-2.2_0/data/scripts/note.ex 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/scripts/note.ex 2004-03-26 22:35:30 +0100 @@ -0,0 +1,53 @@ +" This file contains a simple :note alias and some commands that use it. + +alias note { + "Add/change/remove a note for a given range of lines + if "!*" = "" + then !%unr note + else !%reg note !* +} +alias nextnote { + "Search forward for the next line with a note + local l + let l = current("line") + try + + else error no more notes + while current("line") < buflines && current("region") != "note" + do + + if current("region") != "note" + then { + =l + error no notes below + } +} +alias prevnote { + "Search backward for the previous line with a note + local l + let l = current("line") + try - + else error no more notes + while current("line") > 1 && current("region") != "note" + do - + if current("region") != "note" + then { + =l + error no notes above + } +} + +"Some maps to make searching easier +map gn :nextnote +map gN :prevnote + +"Notes are only useful if persistfile stores regions +if persistfile="" +then warning You should set persistfile to make notes be permanent +if !persist.region +then { + warning You should run :mkexrc to add "regions" to the persist option. + let persist |= "regions" +} + +"I deliberately don't define any attribute for the "note" face. You can if +"you want, outside of this file, but my personal opinion is that coloring +"lines with notes would make them too distracting. diff -urN elvis-2.2_0/data/scripts/sfb.ex elvis-2.2_1/data/scripts/sfb.ex --- elvis-2.2_0/data/scripts/sfb.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/sfb.ex 2004-03-26 22:35:30 +0100 @@ -17,9 +17,11 @@ 1 eval insert (d)

    (d)

    $a - if !userprotocol - then eval file (d)/ - else 1i + "The directory name must end with an OS-dependent slash + if file[,-1] != ""/"" + then eval file (d/"") + if userprotocol + then 1i "Move to the first file so that will move to the second 1 /HREF diff -urN elvis-2.2_0/data/scripts/shuffle.ex elvis-2.2_1/data/scripts/shuffle.ex --- elvis-2.2_0/data/scripts/shuffle.ex 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/data/scripts/shuffle.ex 2004-03-26 22:35:30 +0100 @@ -0,0 +1,10 @@ +alias shuffle { + "Randomly unsort all lines in a buffer, or just a range of lines. + local a=!(1)< z + let z=!(buflines)> + while a < z-1 + do { + eval (a) m (a + rand(z - a)) + let a += 1 + } +} diff -urN elvis-2.2_0/data/scripts/since.ex elvis-2.2_1/data/scripts/since.ex --- elvis-2.2_0/data/scripts/since.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/since.ex 2004-03-26 22:35:30 +0100 @@ -2,18 +2,18 @@ alias since { " Highlight the differences between current buffer and its file - "local a s=since f t=/tmp/diff report=0 u=/tmp/diff.ex - set s=since t=/tmp/diff report=0 u=/tmp/diff.ex + local a s=since f t=/tmp/diff report=0 let f = "!*" || filename if !exists(filename) then error usage: since [filename] eval unr (s) - w! (t) - let a = "diff" f t - let a = a;"| sed -n 's/^[0-9,]*a\\([0-9,]*\\)$/\\1reg diff added/p;s/^[0-9,]*c\\([0-9,]*\\)$/\\1reg diff changed/p' >";u - eval !!(a) - safely source (u) - eval !!rm (t) + try w! (t) + then { + let a = "diff" f t + let a = a;"| sed -n 's/^[0-9,]*a\\([0-9,]*\\)$/\\1reg diff added/p;s/^[0-9,]*c\\([0-9,]*\\)$/\\1reg diff changed/p'" + eval safely source !!(a) + eval !!rm (t) + } } alias rcssince { @@ -22,12 +22,14 @@ eval unr (s) if exists("RCS"/filename;",v") || exists(filename;",v") then { - w! (t) - let a = "co -p !1 2>/dev/null" filename "| diff - " t - let a = a;"| sed -n 's/^[0-9,]*a\\([0-9,]*\\)$/\\1reg" s "added/p;s/^[0-9,]*c\\([0-9,]*\\)$/\\1reg" s "changed/p'" - let a = shell(a) - eval (a) - eval !!rm (t) + try w! (t) + then { + let a = "co -p !1 2>/dev/null" filename "| diff - " t "| sed -n '" + let a = a;"s/^[0-9,]*a\\([0-9,]*\\)$/\\1reg" s "added/p;" + let a = a;"s/^[0-9,]*c\\([0-9,]*\\)$/\\1reg" s "changed/p'" + eval safely source !!(a) + eval !!rm (t) + } } } diff -urN elvis-2.2_0/data/scripts/xbuf.ex elvis-2.2_1/data/scripts/xbuf.ex --- elvis-2.2_0/data/scripts/xbuf.ex 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/scripts/xbuf.ex 2004-03-26 22:35:30 +0100 @@ -224,6 +224,6 @@ set nostatusbar set nofocusnew " for now no toolbar, it will show once you have more than one buffer -" and you can toogle it with  +" and you can toogle it with set notoolbar diff -urN elvis-2.2_0/data/stubs/ansistub.c elvis-2.2_1/data/stubs/ansistub.c --- elvis-2.2_0/data/stubs/ansistub.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/data/stubs/ansistub.c 2004-03-26 22:35:30 +0100 @@ -327,7 +327,9 @@ { } -/* Change fp's I/O offset */ +/* Change fp's I/O offset. The 'whence' parameter is one of + * SEEK_SET, SEEK_CUR, or SEEK_END. + */ int fseek(FILE *fp, long int offset, int whence) { } @@ -734,8 +736,9 @@ { } -/* Append the rear string onto the end of the front string, up - * to an overall length limit. +/* Append the first "length" chars from the "rear" string onto the + * end of the "front" string. It is assumed that "front" is a buffer large + * enough to contain strlen(front)+length+1 characters. */ char *strncat(char *front, const char *rear, size_t length) { diff -urN elvis-2.2_0/digraph.c elvis-2.2_1/digraph.c --- elvis-2.2_0/digraph.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/digraph.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_digraph[] = "$Id: digraph.c,v 2.12 2003/10/17 17:41:23 steve Exp $"; +char id_digraph[] = "$Id: digraph.c,v 2.13 2004/03/21 23:24:41 steve Exp $"; #endif #ifndef NO_DIGRAPH @@ -326,9 +326,7 @@ { static CHAR text[] = "digraph! XX Y\n"; DIGRAPH *dp; - MARK append; - append = markalloc(buf, o_bufchars(buf)); for (dp = digs; dp; dp = dp->next) { if (dp->save) @@ -336,11 +334,9 @@ text[9] = dp->in1; text[10] = dp->in2; text[12] = dp->out; - bufreplace(append, append, text, QTY(text) - 1); - markaddoffset(append, QTY(text) - 1); + bufappend(buf, text, QTY(text) - 1); } } - markfree(append); } # endif /* FEATURE_MKEXRC */ #endif diff -urN elvis-2.2_0/dmmarkup.c elvis-2.2_1/dmmarkup.c --- elvis-2.2_0/dmmarkup.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/dmmarkup.c 2004-03-26 22:35:29 +0100 @@ -10,7 +10,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_dmmarkup[] = "$Id: dmmarkup.c,v 2.136 2003/10/19 23:13:33 steve Exp $"; +char id_dmmarkup[] = "$Id: dmmarkup.c,v 2.140 2004/03/21 19:30:12 steve Exp $"; #endif #ifdef DISPLAY_ANYMARKUP @@ -688,6 +688,15 @@ /* not TEXT, probably SUBMIT or RESET button */ button = ElvTrue; font = fontcode['\b']; + + /* SUBMIT/RESET buttons have default values*/ + if (validx == 0) + { + validx = i; + for (vallen = 1; elvalnum(token->text[i + vallen]); vallen++) + { + } + } } } else if (!CHARncmp(&token->text[i], toCHAR("checked"), 7)) @@ -983,10 +992,10 @@ scannext(refp); #ifdef SGML_HACK - /* If '/' and we were expecting '/' to be interpreted as an SGML-style - * terminator, then do that. + /* If '/' or '>' and we were expecting an SGML-style terminator, + * then do that. */ - if (rettok.text[0] == '/' && *sgmltag) + if ((rettok.text[0] == '/' || rettok.text[0] == '>') && *sgmltag) { /* replace the '/' with the SGML terminator tag name */ CHARcpy(rettok.text, sgmltag); @@ -1103,6 +1112,54 @@ /* when computing line breaks, assume this markup is hidden */ rettok.width = 0; + +#ifdef FEATURE_MISC + /* Many HTML documents use
  • to make a list with vertical + * gaps between items. This looks ugly in elvis, and there is + * no really good fix, so we use a hack here: If this is

  • + * tag, then look ahead to see if it is followed by

    , and + * if so then include the

    as part of this tag's text. + */ + if (rettok.markup && rettok.markup->fn == htmlli && *refp) + { + CHAR *peek; + MARK mark; + + /* skip whitespace between

  • and possible

    */ + scandup(&peek, refp); + while (peek && elvspace(*peek)) + { + scannext(&peek); + offset++; + } + + /* is next text

    ? */ + if (peek && *peek == '<' + && scannext(&peek) && elvtolower(*peek) == 'p' + && scannext(&peek) && elvtolower(*peek) == '>' + && scannext(&peek)) + { + /* stuff

    into token's chars */ + i = rettok.nchars; + rettok.text[i] = '<'; + rettok.offset[i++] = offset++; + rettok.text[i] = 'p'; + rettok.offset[i++] = offset++; + rettok.text[i] = '>'; + rettok.offset[i++] = offset++; + rettok.nchars = i; + + /* move *refp past the

    */ + mark = scanmark(&peek); + scanfree(&peek); + scanseek(refp, mark); + } + else + { + scanfree(&peek); + } + } +#endif } else if (rettok.text[0] <= ' ') { @@ -1126,7 +1183,7 @@ && rettok.nchars < QTY(rettok.text) - 1 && **refp > ' ' /* !elvspace(**refp) */ #ifdef SGML_HACK - && !(**refp == '/' && *sgmltag) + && !((**refp == '/' || **refp == '>') && *sgmltag) #endif && **refp != '<'; offset++, scannext(refp)) @@ -2289,10 +2346,9 @@ start++; switch (token->text[start]) { - case 'n': i = (int)f; break; case 'i': i = (int)(f * 10); break; case 'p': i = (int)(f / 7.2); break; - default: i = 0; + default: i = (int)f; } if (i > 0 && indent + i < 40) moreindent = i; diff -urN elvis-2.2_0/dmnormal.c elvis-2.2_1/dmnormal.c --- elvis-2.2_0/dmnormal.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/dmnormal.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_dmnormal[] = "$Id: dmnormal.c,v 2.63 2003/10/17 17:41:23 steve Exp $"; +char id_dmnormal[] = "$Id: dmnormal.c,v 2.64 2004/03/19 16:21:25 steve Exp $"; #endif #include @@ -843,7 +843,7 @@ } /* end the line */ - if (o_list(w) && !w->state->acton && *cp == '\n') + if (o_list(w) && !w->state->acton && (!cp || *cp == '\n')) { col += dmnlistchars(*cp, offset, col, o_tabstop(markbuffer(w->cursor)), draw); } diff -urN elvis-2.2_0/doc/bugs.txt elvis-2.2_1/doc/bugs.txt --- elvis-2.2_0/doc/bugs.txt 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/bugs.txt 2004-03-26 22:35:31 +0100 @@ -11,6 +11,479 @@ list, so some items are just unimplemented features that sounded like a good idea at one time or another. +* Add a new warpto value, "window", which moves the mouse pointer as little + as possible. Use XQueryPointer() and XTranslateCoordinates() to do the + coordinate math. + + And maybe use XTranslateCoordinates() to choose the position of a + pop-up dialog too. + +* Something adds buffers with names that aren't full pathnames of files. + Maybe the :make command? This is a problem because it allows multiple + buffers to be open for the same file. + +* Running "elvis -Gtermcap README.html" starts with a scrambled display. + + This has something to do with the rcssince alias. If I disable the + autocmd that runs rcssince, it looks okay. + + It is apparently due to quirks of the guitcap->prgclose() function. + That function tries to be clever about waiting for a keystroke with + the cursor on the bottom row, which is basically what "scrambled" + means in this context. This is probably the nastiest, most complex + aspect of the termcap interface -- it uses a couple of variables + that are used in many functions, in subtle ways. Ugh. (The purpose + of all this cleverness is to allow programs to use the whole screen + instead of just one window. The portable part of Elvis doesn't know + that guitcap.c is trying to do this, so guitcap.c needs to do some + pretty bizarre things.) + + Current status is that it works okay, except that if you switch to + another file, and that file has an RCS file, then Elvis will wait + for you to hit before switching to the other file. Only + in the termcap interface. + + What about vio? + +* When the :gdb interface switches buffers, it doesn't always update the + window name to reflect the name of the new buffer. (This is a bug in + Elvis' buffer-switching code, not the gdb interface.) + +* Something weird with instman.sh, where it gives priority to "share" + directories. It isn't looking for the existence of directories correctly. + +* The "html" display mode doesn't hide contents. + +* Is there some way I could make the persist.args flag avoid changing the + args in some cases? I'm specifically thinking of when Elvis is used as + an external editor. I don't want "~/.sylpheed/tmp/tmp.98S498DS" becoming + my default argument string. + + Maybe add a -p flag to disable updates of the persistent information. + Still allow it to be loaded, just not saved. Though it might be nice + to make saving/not-saving be buffer-specific, the args list isn't + buffer-specific so that would be impractical. (Vim uses "-iNONE", + sort of.) + +* In a search expression, ^X00 doesn't cause elvis to search for a NUL byte. + + The regbuild() function should probably convert any NUL bytes into + \0 escape sequences. The incsearch code may need special help. + +----------------------------------------------------------------------------- +Fixed between 2.2.0 and 2.2.1 + +/ The "x11" interface can generate a BadMatch error for the X_SetInputFocus + request. This has been reported for both icewm and ratpoison WMs, though + in different contexts. + +/ When using incremental search, probably the search expression should be + appended to history when user hits . Even if incsearch doesn't + allow you to look back through history interactively, it should still be + saved for the benefit of persistfile. + + I wanted to find a way to edit it, ideally by switching to the + non-incremental version of a search since that supports all vi + commands via a prefix. But that quickly became very + complex. For now, incremental searches support ^Ok and ^Oj, and + that's good enough to make the and arrow keys work. + +/ Allow :source to read from filters. That would be handy for programs that + generate ex commands, such as the one used by the rcssince alias. + +/ Describe the :load scripts in the Tips chapter. + +/ The HTML tag


    shows as "---->" instead of just "----". More generally, + it seems that some XML/HTML editors generate instead of when + there is no closing . Elvis should handle this. + +/ Many problems with the data/scripts/augz.ex script. + + / When elvis sends the gzipped text out to the gunzip filter program, + it appends a newline. There's no way around this, but it has the + side-effect of making gunzip output an "unexpected end of input" + error. + + Idea: If "partiallastline" is set, then omit the last newline + when writing to the filter. When reading back, if there is a + final newline then clean up the "partiallastline" situation + (delete the bogus newline and turn off "partiallastline"). + + / After gunzipping, the display mode and other options aren't set + to reflect the file's uncompressed contents. For example, editing + a gzipped man page will leave the screen in "hex" display mode + instead of "man" display mode. + + This can be solved by temporarily changing the filename option + and then running the "elvis.arf" script. The only problem: + the filename option is locked. You can change it via the + :file command, but that command produces output. Maybe extend + it so :file! (with ! suffix) produces no output? + +/ Create a set of HTML buttons, loadable via ":load html". + +/ The :eval command can get confused if the command that it runs also performs + any calculations. :eval should make a copy of the value returned by + calculate(), and pass the copy to exstring(). + +/ At the end of an alias, elvis generates an AliasEnter event instead of + an AliasLeave. + +/ Backslash processing isn't quite right, in "simpler syntax" expressions. + + This is a little tricky because it is used for Windows file names, + where backslashes are literal text. The best compromise I could + think of is to say \(, \), \$, and \\ are quoted characters anywhere + except that at the front of the string \\ is two literal backslashes + so that \\machine\dir\file names work. + +/ The :suspend command doesn't work. "Bad command name suspend". Also, + the shortest abbreviation should be ":su" according to POSIX, but Elvis + requires ":sus". + +/ After ":load since" and ":mkexrc", loading a file that has been changed + since the last RCS checkin should have the changed lines highlighted, but + they aren't always. Similarly, ":au BufRead * 1d" fails on the first file, + but works on any later files (loaded via ":e"). + + This is due to the rcssince alias using some commands that aren't + allowed during initialization. The initialization is actually + complete by the time BufRead events are executed, but ex.c doesn't + know that because it detects initialization phase by testing for + the existence of at least one window. + + The cleanest way to fix it is to add a new "initializing" option, + which is set during initialization and and cleared when an edit + buffer is created for the first text file. ex.c should check that + instead of the existence of a window. + +/ The hlobject option should allow commas between object names. + +/ In Unix, dirperm() doesn't return "directory" on directories. + ':calc dirperm(".")' returns "readonly". + + This turned out to be due to the addition of the "dir:" pseudo- + protocol, which was created so you could use ":alias readDIR ..." + to create a directory browser. Easy to fix. + +/ The "ax" text object doesn't allow tag names to contain hyphens or colons. + It should. + +/ In security=safer mode, ":wq" fails even when invoked without a filename. + According to the manual, ":wq" should be allowed. + + This is apparently because :wquit (and :edit and :ex) use the d_File + flag so they always get the current file name by default. + + The :write command has special logic for this, but probably shouldn't. + +/ The current security for ":e name" and ":sp name" is too strict -- even + "elvis -client foo.c" fails. I need to allow ":e name" from clients, + without allowing ":w" from clients. Is this yet another security level? + security=client is exactly like security=normal except that all writing + and !cmd is disabled. + + There are four things that must be avoided to maintain security: + 1) You shouldn't be able to run external programs. + 2) You shouldn't be able to write over any arbitrary file. + 3) You shouldn't be able to load any arbitrary file, modify it, and + write it. + 4) You shouldn't be able to create maps or aliases which trick the + user into doing any of the above. + Items 1, 2, and 4 are pretty easy. Item 3 requires some compromise + and that's why there are two different secure modes. "safer" allows + you to load any file, and modify it, but not write it; this makes + "safer" useless for interactive work. "restricted" only allows you + to load files named on the command line, but you can modify them + and write them (back over the old version of the file, not out to + any random file). + + So using "-S" to set security=safer is pointless; "-S" should set + security=restricted. + + Some of the standard scripts in data/ need to be tweaked to work + correctly with -S. + +/ In "html" display mode,
  • looks ugly in Elvis, but many documents + use that as a way to get gaps between list items. Elvis should handle it + better. + +/ Running :mkexrc in one GUI can clobber options for another GUI. For example, + if you're running -Gtermcap and have some x11 options set, then :mkexrc will + loose the x11 options. + + Just "store & ignore" options with unknown domains. The :color command + already does that, and it works well. Basically, if ":set" detects + that its args start with "gui." where "gui" is anything other than the + current user interface, then it should store the args but not do + anything else with them. For the current user interface, "gui." + should be skipped and the remainder processed normally. Most of this + logic is only needed if FEATURE_MKEXRC is defined. + + / Change the name of the termcap GUI's options from "tcap" to "termcap" + + / Some GUIs have window-specific options. Although these are in the + "guiwin" domain (regardless of the GUI's name), they should still + be stored by :mkexrc as gui.option (where "gui" is the GUI's name). + +/ The default "elvis.ini" creates some maps for keypad keys, without the + "nosave" flag. This means if you run ":mkexrc" while running in an xterm, + you'll create maps which exist every time you run elvis. Must add "nosave"! + +/ doesn't work in "x11" anymore. The switch to ^S instead of + ^K as the prefix character is tripping it up. Also, isn't + recognized, or generated, and neither is #1s for shift-F1. + + / The shift+tab key combination returns , not + or . Since is hard to type, Elvis + should standardize on using . + / Function key labels in #x format can't use 'c' or 's' modifiers. + / Maps defined for function & cursor keys don't show any label. + / :mkexrc adds a bunch of flags to :map commands with the "visual" + keyword. + +/ :%j only joins two lines, but :1,$j works correctly. + +/ Sometimes ":%unr" doesn't remove all regions. In particular, sometimes + writing a file won't cause "unsaved" regions to become normal. Going to + the line and running ":unr" works though. This also affects the :chregion + command. + +/ The :man alias doesn't handle backslashes in the man-page correctly. + They interfere with the handling of \fX sequences. See "man groff_man". + + Probably the simplest way to handle this is to change all backslashes + into some harmless control character, such as ^\. Then do the other + stuff, and then go back and convert ^\ into a "\\" pair. + +/ When a command is misspelled, the error message should give the whole name, + not just the portion that had to be parsed for it to be recognized as bad. + +/ When listing, I need to find a better way to distinguish between + automatically installed keys and user-defined keys. Maybe MAP_NOSAVE? + +/ Make the "spellautoload" option be on by default. It is harmless unless + you use spell-checking, and in that case you almost certainly want it on. + +/ The :map command needs to support a "noselect" keyword, which selects all + of the command map states except "select". Currently this is simply + "command motion" but eventually I plan to implement "operator" and maybe + others too. + +/ The manual still shows ":gui icon" as the way to control elvis' icon. + It should describe the "iconimage" option. + +/ The :chregion command should not change the comment, unless either a new + comment is supplied, or the old comment was identical to the old face. + In the latter case, the comment should be changed to the new face name + (which is what it does now). + + Done. Also fixed a bug: The first char of the new comment was being + skipped. + +/ Near the end of the elvtags man-page, "Other versions of elvtags" should + read "Other versions of ctags". + + The elvtags man-page is generated from the ctags man page. Apparently + the conversion rules aren't quite as smart as they should be. + +/ The ":e +line file" command truly does limit the + argument to being a + line address, not a real command. That's bad! + +/ Trouble entering the ^ character with a Norwegian keyboard in Windows. + +/ ".IP \(bu 4" has a larger-than-expected indentation. Is this because the + indentation number has no suffix? "4n" looks okay. + +/ The command ":normal cwFOO^[" doesn't work. Apparently the c operator + doesn't work in a :normal command. + + This turns out to be due to the way the "c" operator is implemented + in oper(). It calls inputchange() to create the input state, but + inputchange() doesn't create unless the state stack contains only + a single vi command state. During execution of a :normal command, + there are at least 2 states (both vi command states) on the stack. + The solution: Make inputchange() be smarter about when to reuse an + existing input state. + +/ When setting up a map in "x11", is converted to ^K0062. Single-letter + names in brackets should always be left unchanged. In fact, if the + resulting string is a single ASCII character then the X11 name should + be ignored; as it is now, you can't even use to get the < character. + (Though works.) + +/ If you use ":e dirname" to edit the directory "dirname", then the links + in the generated HTML aren't interpreted as being relative to dirname. + They're treated as being relative to the current directory. + + A directory's filename should end with "/". If the user gives a + name without a "/" then elvis should add one. + +/ The :dict alias (after ":load dict") doesn't handle single words correctly. + +/ At ex.c:1605, the third argument to calculate() should be cast to + CALCRULE, not ELVFNR. Why doesn't GCC complain about that? + +/ The :put command doesn't accept a cut buffer name. + +/ In a file full of blank lines, "d)" causes a core dump. So does ")". + +/ Lots of little changes to the OS/2 port. This doesn't affect other ports. + +/ Implement timeouts in -Gx11. + + Actually, timeouts were implemented for "usertime" (and aren't needed + for "keytime"). The bug turned out to be that after a timeout, Elvis + wasn't setting the flag that made it update the screen, so the screen + would only be updated after another command or something like losing + and regaining input focus. I've fixed it so it sets the flag. + +/ In visual command mode, no longer generates a beep. This is a change. + Why was it changed? Some people need to hear that beep. + + The behavior changed accidentally when I added as a way to + cancel visible selections for vim compatibility. The selection + cancelling function should fail for if there is no selection + pending. + +/ In HTML mode, the default strings for and + should be "Submit" and "Reset" respectively. As it is + now, those buttons disappear unless you supply an explcit value=... string. + +/ In HTTP requests, elvis should send a User-Agent: header line. Some web + sites demand this. + +/ The addition of filenamerules apparently broke the handling of newlines + in the filename string. They aren't treated as name delimiters anymore. + This causes problems for things like ":n `grep -lw somesymbol *.c`" + See line 1943 of ex.c. + +/ The :andale alias was using the "luxi mono" font instead of "andale mono". + (This alias is only defined for the "x11" user interface.) + +/ Sometimes it would be nice if there was a way to set the application mode. + For example, the GDB interface could use it to indicate whether the program + was currently running or not. + + Maybe just a simple "state" option with no preset meaning, and a + new "state" keyword in the "show" option which displays the state. + +/ Implement an "elvgdb" program to act as a wrapper around the read GDB + program. Elvgdb will parse the output of GDB and send important information + to Elvis. + +/ Write a set of aliases to work eith "elvgdb". + +/ Extend "elvgdb" to allow Elvis to send commands to GDB. This is important + because GDB doesn't output stack information unless you ask for it. + +/ Add and to tinytcap.c entries. + +/ The termcap interface should allow terminfo-emulating-termcap's key codes + for shift-Fn and control-Fn keys. Assume 12 keys so the 13th function key + is really shift-F1, and the 25th function key is really control-F1. + + Terminfo-emulating-termcap uses :F1=: for , :F2=: for , + and then continues through :F9=: for or , and then + :FA=: for or , and continuing on through the letters. + +/ You can compute a target buffer name by giving (=expression) in the + address, but there's no easy way to compute a line number. In aliases, + it would often be nice if you could use something like =expression to + compute a line number. + + Problem: How would the parser know where the line number ends and + the command begins? I'm tempted to use (expression) but that would + look too much like a buffer name. + + Maybe just say =option fetches the value of the named option, and + not allow expressions? Or =(expr) for expressions? + +/ It's almost impossible to combine the use of visual text selections and + the :normal command. This is important because it means you can't create + a [Bold] GUI button which does ":normal cw^P" to embolden text. + + Created a new notation. In :gui commands, you can now use + ":gui [label]" to create a button named "label" which, when pushed, + causes the square brackets and label to be sent as though typed. + You can then :map this to something useful. + +/ Add a :phelp command, which is like :help except that it doesn't + split. Alternatively, add a help() function which returns the URL for + the help for a given topic; then ":alias phelp push (help("!*"))" would + achieve the same effect. + +/ This is probably a good time to add the GuiEnter event. + +/ Add persistent information, for storing the cursor position and maybe other + information. Add a "persistfile" option to store the filename, and a + "persist" option to control what gets stored/loaded there. + + cursor Move the cursor to its previous location + change Move the cursor to the previous change; if both + "cursor" and "change" then "cursor" rules, and '' + mark is set to "change". + hours:hours If entry is more than "hours" old, then don't move + the cursor; instead, set '' to location where cursor + would have gone. + marks Restore named marks that were in file. + folds Restore folds (and unfolds) + regions Restore highlight regions. + search:lines Save regexp history and current search + ex:lines Save ex history + max:bytes Approximate size limit on persistent information + args Default filenames + +/ Need a way to remove folds. This is different from merely unfolding, which + remembers the attributes of the fold. Add a :nofold command. + +/ Add support for %< and #< to remove the extension from the current file name + or alternate file name, respectively. Vim has a similar feature. (This is + separate from Vim's fnamemodify() feature.) + +----------------------------------------------------------------------------- + +* Aliases shouldn't change the 'alternate file' (i.e., previousfile option). + +* Add a real "note" facility. Allow each note to have an icon, which is + displayed in the left margin. On text systems, a text symbol would be + displayed instead. The :note command would always use the text version. + A separate command could be used to associate icon images with names. + + Use :note to associate a note with a given line, and :icon to + associate an icon image with a name. Splitting the association + like this is good for themes. + + This could tie in nicely with the toolbar buttons. If I work it + right, toolbars could get icons at very little cost. The names + could correspond to the button names. + + Should a single line support multiple notes? If :gdb uses notes to + mark breakpoints and the current line, then what if the current line + is a breakpoint? + + Maybe notes should be accessible via '"label" and definable via + m"label" or m"label:comment". Search via '">label" (or '">" for + any symbol). Notes would be drawn on the screen at their exact + location, under the text. On non-graphic GUIs, the notes would be + revealed sort of like tags in showmarkup mode. + +* The data/elvis.clr script should be able to use ":color!" (with a !) but + can't because some of the compiled-in defaults are executed after that script + is sourced, so the compiled-in defaults override ":color!". + +* Idea for a trivial way to color herefiles: Use a :%s///x command to find + them, and a region to highlight them. + + :color herefile black italic on white + :try %s#<<\\\?\(\S\+\)#+,/^\s*\1$/-region herefile \1#x + + The elvis.syn file already supports color lines. It doesn't allow + you to run any ex commands, but maybe it should. The above line + should work perfectly well with security=safer and locked set. + +* Maybe do something to control cursor motion around newlines. Vim has + an ugly 'whichwrap' option. * In Windows, elvis.exe can accept filenames with spaces in them, but vi.exe can't. @@ -21,18 +494,61 @@ This won't be fixed in time for 2.2. If that's a problem for you, then copy elvis.exe to vi.exe. +* Sometimes it would be nice if there was a "flat" pseudocolor that was the + average color of the background pixmap, after tinting. Elvis already knows + this color; it is used to find the best contrasting foreground color. + * When you give a command like ":dis s c++", elvis stores exactly that as the value of the display option. This can confuse x11's toolbar buttons. The [Syntax] button will not be drawn pushed it, because it expects "syntax". +* See Luigi Mastrangelo's mail for some WinElvis bugs. + + * If :make encounters a large number of errors, then WinElvis can get stuck + in an infinite loop. This didn't happen in 2.1_4. + + * "WinElvis test*" will, if there is no file with the prefix "test", display + an alias on the last line. + + I tried to reproduce this one. For me, it's working correctly. + I've cleaned up the wildcard matching code a lot since 2.2i (which + he's using), so maybe that explains it. I hope so. + +* How about a gM operator command which stores the endpoints of the affected + area and its paste-type, and a gA command which recalls that region as a + visual selection (char or line style, as appropriate). + + Vim always remembers visual selections, and can use gv to recall them. + But I want to support motion commands too, such as gM} to select text + to the end of the current paragraph. I believe this will be more + useful in maps. + +* If there was periodic autocmd event, then Elvis could use it to detect + changes in files by other external programs, and reload the file. This + would be handy for a "more" program. + +* I'm not sure, but I think that if you request the same URL with different + parameters, elvis just uses the same copy every time. The resource name + is the same either way so they'd both be stored in the same buffer, and + that's probably the cause of the problem. + + This isn't likely to be a problem very often since Elvis' forms are + only cosmetic, not functional. But it is possible to embed parameters + in a link, and that's what triggers this problem. + + But there are other types of URLs which shouldn't be cached. + Ideally Elvis should look at the reply header to detect these, and + ... maybe set a "nocacheable" option? + +* Alias debugger would be nice -- maybe ":break alias foo" to stop at the + :foo alias. Note that :break already parses prefixes used by :map, so + this would just need another prefix. Plus code to make the prefix actually + do something, of course. + * For "inputtab=identifier", the normal tag search doesn't look for tags in elvispath, so it doesn't find library functions. Is that a good thing or a bad thing? -* The data/elvis.clr script should be able to use ":color!" (with a !) but - can't because some of the compiled-in defaults are executed after that script - is sourced, so the compiled-in defaults override ":color!". - * MAYBE support "or color" for backgrounds. Try to minimize the contrast with the normal background, instead of maximizing it, so the foreground colors still look good. The "or color" backgrounds don't need to support images. @@ -47,19 +563,38 @@ Actually, it does use it to determine whether XML tag pairs should be highlighted by showmatch, but that's all. -* See Luigi Mastrangelo's mail for some WinElvis bugs. - - * If :make encounters a large number of errors, then WinElvis can get stuck - in an infinite loop. This didn't happen in 2.1_4. - - * "WinElvis test*" will, if there is no file with the prefix "test", display - an alias on the last line. +* In "man" display mode, the .TS and .TE commands should not cause a blank + line to be output. If the user wants blank lines around a table, then + he/she should add .PP commands before .TS and after .TE. + + Actually, there seems to be a bug in the way multiple line breaks + are handled. .TS and .TE try to do just a line break, but if you + use any macro that does a line break at the start of a line, then + you get a blank line. Elvis *should* ignore the line break request + since the line has already been broken. + +* The following doesn't look right in "html" display mode: + + + +* Add commands for storing/retrieving a count argument. This would be useful + in maps. For example, 33#! could store 33 in a register somewhere, and + later #? could retrieve it for use by another command. + + ##, #+ Add value to number + #- Subtract value from number + #* Multiply number by value + #/ Divide number by value + #= Set number to value + #< If number is greater than value, then set to value + #> If number is less than value, then set to value + #! Set internal option to value + #? Retrieve internal option, use as count for next cmd. - I tried to reproduce this one. For me, it's working correctly. - I've cleaned up the wildcard matching code a lot since 2.2i (which - he's using), so maybe that explains it. I hope so. + Alternatively, #a could store the value in cut buffer a, and then + @a would naturally retrieve the value. -* The tag stack doesn't seem to work right for user-defined protocols. +/ The tag stack doesn't seem to work right for user-defined protocols. Directories (the "readDIR" alias) fail completely when you hit ^T, and others such as readDICT move the cursor to the wrong place. @@ -90,6 +625,30 @@ and also because the tags aren't going to be processed in "html" mode. +* Add support for vim-style jump lists. + + Jump lists are like the `` command, except that it maintains a history + of jump locations. Vim uses ^O to move backward through the jump list + and to move forward. ^O is deliberately ignored in elvis because + +key and ":map visual" can both insert superfluous ^O keys before + vi command keys. The key is used for moving to the next + hypertext link in "html" mode, or for folding/unfolding text in + "normal" and "syntax" modes. + + So elvis should use `+ to move forward and `- to move backward. + Users who want vim's keys can map them. + +* Should Undo turn off the "modified" flag, if it reverts to the most recently + saved version? + + This would be another attribute in each buffer's Undo list. Whenever + an undo/redo version is added with "modified" off, any other options + with "modified" off should be changed to show "modified" as being on. + (Or better: whenever the "modified" option is turned off, all undo/redo + versions should have their "modified" flag turned on.) + + It seems like the "edited" flag should come into play here too. + * Elvis' CHAR data type may clash with some standard ones. * Add a help: protocol (readHELP alias) which looks up terms via :help. @@ -99,10 +658,6 @@ * In syntax coloring mode, how about adding a text object for comments? -* Write a wrapper around GDB to allow it to run in a separate xterm window. - The wrapper will send commands to Elvis which force Elvis' windows to - stay in sync with the debugger. See "Annotations" in the GDB info pages. - * For some users, the smartargs option is extremely slow and doesn't find the function's arguments anyway. This has to be due to some quirk in the user's configuration, but what? @@ -120,9 +675,6 @@ instead of invoking ref, just for the sake of removing ref & bash from the scenario? -* Need a way to remove folds. This is different from merely unfolding, which - remembers the attributes of the fold. - * Add a "rulerformat" option to control the appearance of the ruler. Vim has a "rulerformat" option with a very weird syntax. I would @@ -156,6 +708,16 @@ * MAYBE add vim's glob(), globpath(), and expand() functions. fnamemodify() too? +* Add a function to search for tags. Its parameter string should be the + same as the args of the :tag command. It should return the tag as a + comma-delimited list of name:attribute pairs; if there's more than one + match then it should return a \n-delimited list. + + :"List the structs which have a "next" field + :let t=tag("next") + :for i = 1 .. t["\n",0] + :do calc t["\n",i].struct + * Make the default array delimiter be '\n' if the string contains at least one '\n', or whitespace otherwise. This will affect the :for command as well as arrays. This will be handy when glob() is implemented. @@ -168,10 +730,8 @@ newline as an opening quote for a string that extends to the end of the expression. - Also, \n in strings isn't converted into a newline. Changing the - expression parser to support that might break some Windows scripts. - The danger is pretty low, though. Adding \n support makes sense. - Maybe other character escapes too. +* Make the % operator concatenate strings with a newline between them. + This will also allow you to say a[%,0] instead of a["\n",0]. * In elvis.syn, the "config.sys" entry reveals a problem: If a language has "ignorecase", and its keywords aren't given in lowercase, then @@ -406,8 +966,44 @@ "normal" and "idle", some candidates would be "readonly" and "web". * The '' command (go back to previous location) doesn't seem to work as well - as it used to, especially after :s/// commands. - + as it used to, especially after :s/// commands. In Vim, ":help jumplist" + says which Vim commands affect '', though I suspect that list is incomplete. + It doesn't include "gD" for example. + + It would also be nice to support something like vim's jumplist, + albeit with different commands. (Vim uses ^O and ^I. I prefer + Elvis' use for those keys.) Maybe '+ to move forward through + the jumplist and '- to move backward. Maybe do something like + viminfo to remember those marks between Elvis edit sessions. + + Some other useful marks: '< and '> for the ends of the current + visible selection; '. for the position where the last change was + make; [' and ]' to move to the previous/next line with a letter + mark. + +* Maybe implement something like viminfo. It should store all the stuff + that :mkexrc doesn't. It should only be updated when a buffer is freed + (which should certainly occur when Elvis is exiting, and maybe before + that too). At a minimum, it should store the most recent line number. + It should ideally also store regions and folds. + + This might be possible with autocmds and scripts. No changes + to elvis necessary. Check it out. I know regions could be + done this way. Folds could be trickier, since they can nest. + +* An idea: Support "invalidated" buffers. Give each buffer a "valid" option. + If it is invalid, then the next time that it is accessed, a BufInvalid + event is generated, which should update the buffer. This could be used + (with a little extra magic, like a :internalsave command and :invalidate + command) to update the "Elvis custom initalization" buffer. + + This is probably more trouble than it's worth. My original goal + was to provide a way to efficiently update the file-specific + information for viminfo. Then I tried to make it generic since + :mkexrc's "Elvis custom initialization" buffer works in a similar + way. But this is all low-level stuff that doesn't really correspond + to ex commands; it would be a forced fit, not a natural fit. + * Apparently "elvis -Gx11" doesn't always exit when X does -- it can get stuck in a loop where it uses all available CPU. diff -urN elvis-2.2_0/doc/ctags.man elvis-2.2_1/doc/ctags.man --- elvis-2.2_0/doc/ctags.man 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/ctags.man 2004-03-26 22:35:31 +0100 @@ -9,7 +9,7 @@ .I files... .SH VERSION This page describes the -.B Elvis 2.2_0 +.B Elvis 2.2_1 version of .BR c\&tags . See diff -urN elvis-2.2_0/doc/elvgdb.man elvis-2.2_1/doc/elvgdb.man --- elvis-2.2_0/doc/elvgdb.man 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/doc/elvgdb.man 2004-03-26 22:35:31 +0100 @@ -0,0 +1,352 @@ +.TH ELVGDB 1 "" "" "User commands" +.SH NAME +elvgdb \- allows gdb and elvis to work together +.SH SYNOPSIS +.ad l +.B elvgdb +.RI [ gdbargs ] +.br +.B elvgdb +.RB [ \-t +.IR gdbcommand ] +.ad b +.SH DESCRIPTION +.B elvgdb +is a program that allows the +.BR gdb (1) +debugger and the +.BR elvis (1) +editor to work together. +It only functions properly in X windows. +.PP +There are two ways to use it. +Without a +.BI \-t gdbcommand +flag it behaves as a "server", running an interactive +.B gdb +process and allowing that +.B gdb +to send information to elvis. +With a +.BI \-t gdbcommand +flag it behaves as a "client", pasting the +.I gdbcommand +into the +.BR xterm (1X) +where the +.BR elvgdb / gdb +server is running. +.PP +Usually, you will use it by starting +.B elvis +with its "x11" user interface, +and then running ":gdb \fIprogram\fR [\fIcore\fR]". +This will start an +.B xterm +process with +.B elvgdb +(running as a server, without "-t") and +.B gdb +running inside it. +Various +.B elvis +aliases and buttons may invoke +.B elvgdb +with the "-t" to send a command to the debugger. + +.SH SERVER +When invoked without a +.B \-t +flag, +.B elvgdb +invokes gdb, passing it all of the command-line parameters and also +inserting a "--annotate=2" parameter which causes gdb to output extra +information that may be useful to elvis. +.PP +.B elvgdb +also filters +.BR gdb "'s" +output to extract that information (called "annotations" in the +.B gdb +info pages) so it can send it to elvis. +There is a "elvgdb.ini" file (described in ELVGDB.INI below) which tells +.B elvgdb +which annotations elvis is likely to care about, and which surrounding +text to send back. +.PP +The information is sent to +.B elvis +via the equivalent of +.BR elvis "'s" +-client mechanism, which is only supported by +.BR elvis "'s" +"x11" user interface. +You must start +.B elvis +before you start +.BR elvgdb , +because +.B elvgdb +only tries to locate +.B elvis +during its initialization. +.PP +The information is sent to +.B elvis +in the form of a ":fromgdb" command. +.B elvis +has no built-in command by that name; +you are expected to define an ":fromgdb" alias in +.BR elvis . +An example of such an alias is provided with +.BR elvis. +You can load it (and some other useful +.BR gdb -related +things) +by running ":load gdb". +The ":gdb" alias does this automatically. +.P +The first argument of each ":fromgdb" command is the name of the annotation +that triggered the message. +Other text (either extra information in the annotation, or text enclosed +between the triggering annotation and some later annotation) follows +as extra arguments. +Usually, the ":fromgdb" alias will be a big switch statement that checks +the first argument (the annotation name), and then possibly also parses +the extra information in some annotation-dependent way. +.SH CLIENT +The server +.B elvgdb +process attaches an attribute to the display's root window, giving the +Window ID of the +.B xterm +in which the server +.BR elvgdb / gdb +is running. +The client +.B elvgdb +uses this to find the server. +.P +To send the +.I gdbcommand +text, +it first creates an invisible window of its own and +then claims the X selection, simulates a middle-click on the +.B xterm +window, and waits for the +.B xterm +to fetch the selection so the +.B xterm +can paste it. +.SH ELVGDB.INI +The +.I elvgdb.ini +file tells +.B elvgdb +how to handle each annotion. +It can reside anywhere in $ELVISPATH, just like +.BR elvis "'s" +own configuration files. +.PP +It is a text file. +Blank lines, and lines that start with a "#" character, are ignored. +All other lines should be of the form... +.IP +.I annotations +: +.I attributes +.PP +\|... where +.I annotations +is a space-delimited list of annotation names, and +.I attributes +is a space-delimited list of attributes. +.SS ATTRIBUTES +.PP +The following attribute names control the way that the annotation is +handled by +.BR elvgdb . +.PP +.TS +l l. +fromgdb Start a new command to be sent to elvis +args Append arguments to the next command sent to elvis +text Append the following text to the next command sent to elvis +toelvis Send a ":fromgdb name args text" command to elvis. +table Store the annotation name for use with "record" attributes +record Send previous record (if any), and start a new one. +flush Flush output after each character because user is typing +trace Show the annotation name, to help debug the configuration +server If following text begins with "server" then suppress output +limit Try to avoid sending multiple copies of the message +.TE +.PP +The "table" and "record" attributes, +and the special "field\fIn\fR" pseudo-annotations described below, +are all intended to help work around the obnoxious way that +.B gdb +annotates its breakpoints table. +The idea is that +the "breakpoints-table" annotation will have the "table" attribute, +the "record" annotation will have the "record" attribute, +selected "field\fIn\fR" annotations will have the "text" attribute, and +the "breakpoints-table-end" annotation will have a normal "toelvis" attribute. +This will cause each record to send a ":fromgdb breakpoints-table" message to +elvis with selected fields appended as arguments. +.PP +The "server" attribute is used to suppress output from commands issued by +elvis (via "elvgdb -t \fIgdbcommands\fR"), as opposed to those commands +entered into gdb directly by the user. +Generally, any annotation which has the "flush" attribute should also have +the "server" attribute. +.PP +The "limit" attribute is mostly due to the fact that +.B gdb +sometimes sends many "breakpoints-invalid" messages between prompts, but +we only want elvis to update its breakpoints once. +.PP +In addition, the following attributes can be used to alter the appearance +of text that follows particular annotations: +.br +.TS +l l. +black Use black foreground for the following text +gray Use gray foreground for the following text +red Use red foreground for the following text +green Use green foreground for the following text +brown Use brown foreground for the following text +yellow Use yellow foreground for the following text +blue Use blue foreground for the following text +magenta Use magenta foreground for the following text +cyan Use cyan foreground for the following text +white Use white foreground for the following text +bold Switch to bold/bright text +underline Switch to underlined text +highlight Don't switch back to normal +.TE +.SS ANNOTATIONS +.PP +For the names and descriptions of annotations, see the +.B gdb +info pages. +.B elvgdb +also uses a few pseudo-annotations for special purposes. +These are: +.IP "field\fIn\fR" +When +.B gdb +emits a "field" annotation with a numeric argument \fIn\fR, +.B elvgdb +converts that into a "field\fIn\fR" annotation before looking up its attributes. +In other words, "field\fIn\fR" in the +.I elvgdb.ini +file is used to specify the attributes of a "field" annotation that has +the argument "\fIn\fR". +This is intented to help work around the obnoxious annotations used for +the breakpoint table. +.IP elvgdb-all +Merged with the attributes of all real annotations. +This is mostly so you can say "elvgdb-all:trace" to trace all annotations. +.IP elvgdb-default +Used to supply the attributes of any annotation that isn't specifically +mentioned in the elvgdb.ini configuration file. +For example, "elvgdb-default: trace" would cause any recently added +(or otherwise unhandled) annotations to be shown. +.IP elvgdb-init +Simulated before +.B gdb +starts. +Its highlighting attributes are used for the +.B gdb +copyright statement. +.IP elvgdb-term +Simulated after +.B gdb +terminates. +You can use the "fromgdb toelvis" attribute pair to have a message be sent to +.B elvis +so it knows when +.BR elvgdb / gdb +isn't running anymore. +.IP elvgdb-trace +The highlighting attributes of this pseudo-annotation are +used when displaying the name of any traced annotation. +For example, +"elvgdb-trace: magenta" would cause traced annotations to appear in magenta. +.IP +Also, if the "elvgdb-trace" annotation has the "fromgdb" attribute, then +elvgdb will mark the start of any command that it is preparing to send +to elvis. +The "toelvis" attribute will cause it to display the whole command when it is +actually sent. +The "table" attribute will cause elvis to mark the start and end of any table. +The "server" attribute will inhibit the effect of "server" on any real +annotation, so that server commands will be visible. +.SH OPTIONS +.PP +When used as a server (without +.BR \-t\fIcommands\fP ), +.B elvgdb +passes all of its parameters to +.BR gdb . +See +.BR gdb (1) +for a description of the options that it supports. +.PP +When used as a filter, you must use a +.BI \-t gdbcommand +flag, as follows: +.IP "\fB\-t\fP \fIgdbcommand\fP" +Paste +.I gdbcommand +into the +.BR xterm (1X) +where the +.BR elvgdb / gdb +server is running. +Assuming +.B gdb +is prompting for a command, this should cause gdb to execute the +.IR gdbcommand . +.SH ENVIRONMENT +.TP +$ELVISPATH +This is a list of directories where the "elvis.ini" file may reside. +.TP +$secret +This contains the value of +.BR elvis ' +.I secret +option. +.B elvgdb +includes this in the requests that it sends back to elvis. +This is important because the for +.B elvis +to respond to the "breakpoints-invalid" annotation, it must send +an "info breakpoints" command back to +.B elvgdb +by running ":!elvgdb -t info breakpoints". +Normally +.B elvis +would refuse to execute ":!\fIshellcmd\fR" for a client +due to security concerns, but we know that +.B elvgdb +can be trusted because it knows the right "secret" value. +.SH FILES +.TP +.I elvgdb.ini +This file resides somewhere in $ELVISPATH. +It describes the appearance and behavior of each annotation. +See the ELVGDB.INI section, above, for details. +.SH "SEE ALSO" +.BR elvis (1), +.BR gdb (1), +.BR xterm (1X) +.P +Run "info gdb Annotations" for information about +.BR gdb 's +annotations. +.SH AUTHOR +Steve Kirkendall +.br +kirkenda@cs.pdx.edu diff -urN elvis-2.2_0/doc/elvis.html elvis-2.2_1/doc/elvis.html --- elvis-2.2_0/doc/elvis.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvis.html 2004-03-26 22:35:31 +0100 @@ -1,7 +1,7 @@ -Elvis-2.2_0 Documentation +Elvis-2.2_1 Documentation -

    TABLE OF CONTENTS FOR ELVIS-2.2_0

    +

    TABLE OF CONTENTS FOR ELVIS-2.2_1

  •  1. What is Elvis? (includes a summary of special features) @@ -32,7 +32,8 @@
  • elvis(1) Man-page for Elvis
  • ctags(1) Man-page for ctags (or elvtags)
  • ref(1) Man-page for ref -
  • fmt(1) Man-page for fmt +
  • fmt(1) Man-page for fmt (or elvfmt) +
  • elvgdb(1) Man-page for elvgdb
  • HINT: If you're reading this via Elvis' built-in @@ -69,7 +70,7 @@ posting a message to the comp.editors newsgroup. -

    1. WHAT IS ELVIS-2.2_0

    +

    1. WHAT IS ELVIS-2.2_1

    Elvis is a clone of vi/ex, the standard UNIX editor. Elvis supports nearly all of the vi/ex commands, in both visual mode and ex mode. diff -urN elvis-2.2_0/doc/elvis.man elvis-2.2_1/doc/elvis.man --- elvis-2.2_0/doc/elvis.man 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvis.man 2004-03-26 22:35:31 +0100 @@ -11,7 +11,7 @@ .RB [ -s | - ] .RB [ -b ] .RB [ -R ] -.RB [ -S | -SS ] +.RB [ -S ] .RB [ -f .IR session ] .RB [ -o @@ -27,7 +27,7 @@ .IR blksize ] .RI [ file ]... .SH VERSION -Elvis 2.2_0 +Elvis 2.2_1 .SH DESCRIPTION .PP .B Elvis @@ -139,19 +139,14 @@ causes all new buffers to be marked as "readonly" so you won't accidentally overwrite the original file. .IP \fB-S\fR -Sets security=safer, making -.B Elvis -paranoid about certain potentially harmful commands. -The intent is to protect the user against writing by malicious scripts. -The ./.exrc file and modelines are executed with security=safer temporarily -regardless of whether \fB-S\fR was given. -The \fB-S\fR flag is just used to make -.B Elvis -permanently paranoid, for the duration of this process. -.IP \fB-SS\fR Sets security=restricted. -This is more extreme security than "-S". -The intent is to protect the system against reading by malicious users. +This is intended to allow +.B Elvis +to be used as a restricted editor. +Be aware that with or without this flag, \fByou use Elvis at your own risk\fR. +I have tried to make +.B -S +secure, but I'm not guaranteeing anything. .IP "\fB-f \fIsession\fR" Makes .B Elvis @@ -162,14 +157,15 @@ Redirects messages and trace information out to .I logfile instead of going to stdout/stderr as usual. -This is useful under Windows95, where stdout/stderr don't show anywhere. -If you're having trouble configuring WinElvis, try running "WinElvis -VVV -o log" +This is useful under Microsoft Windows, where stdout/stderr don't show anywhere. +If you're having trouble configuring WinElvis, +try running "WinElvis -VVV -o log" and then you can find the trace and error messages in the file "log". .IP "\fB-G \fIgui\fR" Makes .B Elvis use the named \fIgui\fR user interface instead of the default. -To see a list of supported user interfaces, give the command "elvis -?". +To see a list of supported user interfaces, give the command "elvis -G?". .IP "\fB-c \fIcommand\fR" After loading the first file, interpret \fIcommand\fR as an ex command line. Several ex command lines can be sent in one line, separated by "|". @@ -194,6 +190,8 @@ .IP "\fB-B \fIblksize\fR" If a new session file is created, this causes it to use blocks of size .IR blksize . +This should be a power of 2 between 512 and 8192. +The default is 2048 except for MS-DOS where it is 1024. .PP In addition, the following options are also supported to maintain backward compatibility, although their future use is discouraged. @@ -246,8 +244,9 @@ .I elvis.ini file. The default -.I elvis.ini -file does this, making the new default font be 18-point Courier.) +.I elvis.x11 +file does this, +making the new default font be Courier in a reasonable point size.) .PP To specify a bold font, use \fB-fb\fI fontname.\fR The specified font should have the same size character cell as the normal @@ -380,7 +379,7 @@ .B Elvis happens to be displaying an HTML document, then tag lookup pursues hypertext links so you can double-click on any underlined text -to view the topic that describes that text. +to view the topic that describes that text (i.e., follow the link). Double-clicking button 3 simulates a ^T keystroke, taking you back to where you did the last tag lookup. .PP diff -urN elvis-2.2_0/doc/elviscut.html elvis-2.2_1/doc/elviscut.html --- elvis-2.2_0/doc/elviscut.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elviscut.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Cut Buffers +Elvis-2.2_1 Cut Buffers

    11. CUT BUFFERS

    @@ -121,7 +121,7 @@

    The visual @ command can be rather finicky. Each character in the buffer is interpreted as a keystroke. -If you load the instructions into the cut buffer via a "zdd command, +If you load the instructions into the cut buffer via a "zdd command, then the newline character at the end of the line will be executed just like any other character, so the cursor would be moved down 1 line. If you don't want the cursor to move down 1 line at the end of each diff -urN elvis-2.2_0/doc/elvisdm.html elvis-2.2_1/doc/elvisdm.html --- elvis-2.2_0/doc/elvisdm.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisdm.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Display Modes +Elvis-2.2_1 Display Modes

    7. DISPLAY MODES

    @@ -1090,6 +1090,22 @@
    +
    '\" letters +
    On some Unix variants (but not Linux), if the first line of a man page +begins with apostrophe-backslash-doublequote, then the rest of the line is +interpreted as a list of letters indicating which preprocessors the page +should be filtered through before being passed to troff. +The most common letter is "t" for the tbl filter. +Other letters may include +"e" for eqn, +"p" for pic, +"r" for refer, and +"v" for vgrind. + +

    Elvis doesn't use any of this because its table commands +(.TS and .TE) are built in, +and it doesn't support filtering while you edit anyway. +

    .\" comment
    Elvis ignores any text on a .\" command line. diff -urN elvis-2.2_0/doc/elvisex.html elvis-2.2_1/doc/elvisex.html --- elvis-2.2_0/doc/elvisex.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisex.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Ex Mode +Elvis-2.2_1 Ex Mode

    4. EX COMMAND MODE

    @@ -61,7 +61,7 @@ :e ~/proj1/src/header.h ...and then realize that you really wanted "header2.h" instead of "header.h". -You simplest way to get "header2.h" is to... +The simplest way to get "header2.h" is to...
    1. Hit the : key to start a new ex command line.
    2. Hit the Up arrow key, or ^O k to move back to the @@ -90,9 +90,11 @@
    3. Hit the Left arrow key five times, or ^O 5 h, to move the cursor back to the last 'e' character in "header2.h".
    4. Hit the Backspace key four times to delete the word "head". - It will still show on the screen, but Elvis will know that it has been - deleted. This is the same sort of behavior that Elvis (and vi) exhibits - when you backspace over newly entered text in input mode. + If you didn't change the default value of the + cleantext option, the word will still show on the screen, but + Elvis will know that it has been deleted. This is the same sort + of behavior that Elvis (and vi) exhibits when you backspace over + newly entered text in input mode.
    5. Type f o o t to insert "foot" where "head" used to be. At this point, the line should look like ":e ~/proj1/src/footer2.h".
    6. Hit Enter to submit the revised command line. @@ -222,10 +224,14 @@

      Line addresses consist of an absolute part and a relative part. -The absolute part of a line specifier may be either an -explicit line number, a mark, a dot to denote the current line, -a dollar sign to denote the last line of the file, or a -forward or backward search. +The absolute part of a line specifier may be either +an explicit line number, +a mark, +a dot to denote the current line, +a dollar sign to denote the last line of the file, +a forward or backward search, or +an expression. + An explicit line number is simply a decimal number, expressed as a string of digits. @@ -241,6 +247,11 @@ surrounded by question marks; searching begins at the line before the default line. +An expression is a = followed by either +the name of an option, or +a () pair containing a more complex +expression. +

      If you omit the absolute part, then the default line is used.

      The relative part of a line specifier is typed as a + @@ -275,7 +286,9 @@ :1,$p | print all lines of the buffer :%p | print all lines of the buffer :(zot)%p | print all lines of the "zot" buffer - :/foo/-2,+4p | print 5 lines around the next "foo" + :/foo/-2,+4p | print 5 lines around the next "foo" + :=x p | print the line whose line number is in x + :(=b)=n p | print computed line n from computed buffer b

      The optional addresses are followed by the command name. Command names may be abbreviated. @@ -304,7 +317,7 @@

      /regexp/newtext/
      This is a regular expression -followed by replacement text. +followed by substitution text.
      count
      This is a number - a string of digits. @@ -373,40 +386,52 @@
      shellcmd
      This is a command line which is passed to the system's command interpreter. -Within the command line, the following character substitutions take place, -unless preceded by a backslash: +Within the command line, the following symbol substitutions take place, +unless preceded by a backslash (or you've removed "special" from +the filenamerules option):
      -	.-----------.----------------------------.
      -	| CHARACTER | REPLACED BY                |
      -	|-----------|----------------------------|
      -	|     %     | Name of current file       |
      -	|     #     | Name of alternate file     |
      -	|     #n    | Name of file whose bufid=n |
      -	|     !     | Previous command line      |
      -	|     \@    | Word at cursor location    |
      -	^-----------^----------------------------^
      -
      -Note that the \@ substitution requires a backslash. + .--------.-----------------------------------------------. + | SYMBOL | REPLACED BY | + |--------|-----------------------------------------------| + | % | Name of current file | + | %< | Name of current file, with extension removed | + | # | Name of alternate file | + | #< | Name of alternate file, with extension removed| + | #n | Name of file whose bufid=n | + | #n< | Name of file whose bufid=n, with ext. removed | + | ! | Previous command line | + | \@ | Word at cursor location | + ^--------^-----------------------------------------------^ + +

      Note that the \@ substitution requires a backslash. This quirk exists for the sake of backward compatibility - the real vi doesn't perform any substitutions for just plain @, and neither does Elvis.

      file or files
      This is one or more file names, or a "wildcard" pattern which matches -the names of zero or more files. File names are subjected to three levels -of processing. First, leading ~ characters and certain other characters -are replaced with text, as follows: +the names of zero or more files. +The handling of filename arguments is controlled by the +filenamerules option). +The default behavior is as follows. +

      +File names are subjected to three levels of processing. +First, leading ~ characters and certain other symbols are replaced with text, +unless preceded by a backslash:

           .-----------.------------------------------------------------.
           | SYMBOL    | REPLACED BY                                    |
           |-----------|------------------------------------------------|
      -    | ~user     | (Unix only) Replaced by home directory of user |
      -    | ~+        | Replaced by current working directory          |
      -    | ~-        | Replaced by previous directory (previousdir)   |
      -    | ~         | Replaced by home directory (home)              |
      -    | %         | Replaced by the name of the current file       |
      -    | #         | Replaced by the name of the alternate file     |
      -    | #n        | Replaced by the filename of buffer with bufid=n|
      +    | ~user     | (Unix only) Home directory of user             |
      +    | ~+        | Current working directory                      |
      +    | ~-        | Previous directory (previousdir)               |
      +    | ~         | Home directory (home)                          |
      +    | %         | Name of the current file                       |
      +    | %<        | Name of current file, with extension removed   |
      +    | #         | Name of the alternate file                     |
      +    | #<        | Name of alternate file, with extension removed |
      +    | #n        | Name of file with bufid=n                      |
      +    | #n<       | Name of file whose bufid=n, with ext. removed  |
           | (space)   | Delimits one file name from another            |
           | `program` | Run program, interpret its output as filenames |
           ^-----------^------------------------------------------------^
      @@ -435,13 +460,13 @@
       matching file.  The exact list of supported wildcards will vary from one
       operating system to another, but the following are typical:
       
      -	.--------.----------------------------------------------.
      -	| SYMBOL | MATCHES                                      |
      -	|--------|----------------------------------------------|
      -	| *      | Any string of characters, of any length      |
      -	| ?      | Any single character                         |
      -	| [A-Z]  | (Unix only) Any single character from A to Z |
      -	^--------^----------------------------------------------^
      +	.--------.-----------------------------------------.
      +	| SYMBOL | MATCHES                                 |
      +	|--------|-----------------------------------------|
      +	| *      | Any string of characters, of any length |
      +	| ?      | Any single character                    |
      +	| [A-Z]  | Any single character from A to Z        |
      +	^--------^-----------------------------------------^
       
      In most operating systems, wildcards are only recognized when they occur in the last file name part of a longer pathname. In other words, you can @@ -493,20 +518,26 @@ |ADDRESS| COMMAND | ARGUMENTS | |-------|-------------------|-----------------------------------| | | h[elp] | topic | +| | ph[elp] | topic | ^-------^-------------------^-----------------------------------^
      h[elp] topic -
      The :help command loads and displays a +
      ph[elp] topic +
      The :help and :phelp commands load and display a help file for a given topic. -There are several help files, covering a wide variety of topics. +The difference between the two commands is that :help splits +a new window, and :phelp displays it in your current window +after pushing your old location onto the tag stack so +^T (Control-T) will bring you back. -

      Elvis looks at the topic you supply, and tries to determine whether +

      There are several help files, covering a wide variety of topics. +Elvis looks at the topic you supply, and tries to determine whether it is an ex command name, vi keystroke, option name, or something else. Based on this, it generates a hypertext link to the topic in the appropriate -help file, and shows the topic in a separate window. +help file, and shows the topic. Elvis uses the following rules to convert your requested topic into a hypertext reference:

      @@ -776,7 +807,7 @@
       |  g   | replace every instance in each line                   | 
       |  .n  | (n is a number) replace the n'th instance in each line|
       |  c   | ask for confirmation before making the change         |
      -|  x   | execute the newtext as an ex command; don't subsitute |
      +|  x   | execute the newtext as an ex command; don't substitute|
       |  e   | don't treat "no match" as an error                    |
       |  p   | print the changed line like :p                        |
       |  l   | print the changed line like :l                        |
      @@ -989,8 +1020,9 @@
       
      The :pop command pops a cursor position off the stack, restoring the cursor to its previous position. -When you're browsing though source code, you will typically use :tag -to go deeper into the call tree, and :pop to come back out again. +When you're browsing through source code, +you will typically use :tag to go deeper into the call tree, +and :pop to come back out again.

      In HTML mode, these all work the same except that :tag expects to be given an URL instead of a tag name. @@ -1078,7 +1110,7 @@ | | rew[ind][!] | | | | la[st] | | | | wn[ext][!] | | -| | f[ile] | [file] | +| | f[ile][!] | [file] | | | e[dit][!] | [+line] [file] | | | ex[!] | [+line] [file] | | | vi[sual][!] | [+line] [file] | @@ -1132,10 +1164,12 @@ (The autowrite option offers a better alternative.) -

      f[ile] [file] +
      f[ile][!] [file]
      The :file command displays information about the current buffer. It can also be used to change the filename associated with this buffer. +When invoked with a "!" suffix, it does not display information about the +current buffer; you can use this to change the filename silently.
      e[dit][!] [+line] [file]
      ex[!] [+line] [file] @@ -1219,7 +1253,7 @@ The :qall command tries to close all of the windows at once. It is equivalent to giving the :quit command in each window. -
      pre[serve] +
      pres[erve]
      The :preserve command closes all windows and exits, but it doesn't delete the session file. @@ -1239,10 +1273,8 @@ |ADDRESS| COMMAND | ARGUMENTS | |-------|-------------------|-----------------------------------| | | @ | cutbuf | -| | so[urce][!] | file | +| | so[urce][!] | file | !shellcmd | | | safel[y] | excmds | -| | al[ias][!] | [name [excmds]] | -| | unal[ias][!] | name | ^-------^-------------------^-----------------------------------^
      @@ -1253,7 +1285,7 @@ The :@ command executes the contents of a cut buffer as a series of ex command lines. -
      so[urce][!] file +
      so[urce][!] file | !shellcmd
      The :source command reads a file, and executes its contents as a series of ex commands. @@ -1270,26 +1302,6 @@ In particular, ":safely source filename" is a good way to run untrusted scripts. -
      al[ias][!] [name [excmds]] -
      The :alias command manipulates the alias list. -(See the Tips section of the manual for -a discussion of aliases.) -With no arguments, :alias lists all user-defined aliases, -and :alias! lists all system-defined aliases. - -

      When given a name but no commands, :alias displays the -complete definition of the named alias. - -

      When given a name and commands, :alias defines (or redefines) -an alias. -Adding a "!" suffix (:alias!) will cause the alias to be marked -as a system alias, which is only significant because the -:mkexrc command doesn't save system aliases. - -

      unal[ias] name -
      -The :unalias command deletes the alias with a given name. -

      4.13 Working with a compiler

      @@ -1573,6 +1585,8 @@ | | se[t][!] | [option=value | option? | all] | | | lo[cal] | [option=value | option ] | | | le[t][!] | option=expr | +| | al[ias][!] | [name [excmds]] | +| | unal[ias][!] | name | | | if | expr | | | th[en] | excmds | | | el[se] | excmds | @@ -1638,14 +1652,13 @@

      The second text argument is character sequence that Elvis should pretend you typed whenever the raw characters are received. -

      Elvis allows you to use symbolic names for some keys and characters. +

      Elvis allows you to use symbolic names for some keys and characters. The following symbols represent individual characters, and are case-insensitive: <Nul>, <BS>, <Tab>, <FF>, <NL>, <LF>, <EOL>, <CR>, <Return>, <Enter>, <Esc>, <CSI>, <Del>, <Nul>, <Space>, <lt>, -<gt>, <Bar>, and <Bslash> - -

      In addition, each user interface may add its own symbols for cursor keys +<gt>, <Bar>, and <Bslash>. +In addition, each user interface may add its own symbols for cursor keys and function keys. The exact list of symbols will vary. Typically, these names will be case-sensitive. See the X11 Keys, @@ -1660,12 +1673,13 @@ .----------.------------------------------------------------------. | FLAG | WHAT IT MEANS | |----------|------------------------------------------------------| -| command | works in the normal "Command" mode | +| select | works when text is selected via V, v, ^V, or mouse | +| command | works in the normal "Command" mode, if no selection | | motion | works when used as the target of an operator | -| select | works while text is selected via V, v, or ^V | +| noselect | synonym for command states other than "select" | | input | works in "Input" or "Replace" mode on main buffer | | history | works when typing an ex command or search expression | -| mode=name| works only if the mapmode option is set to name | +| mode=name| ignore unless the mapmode option is set to name | | visual | always interpret second argument text as vi commands | | noremap | never check second text for maps, regardless of remap| | nosave | prevent mkexrc from saving this map | @@ -1730,8 +1744,7 @@ attributes of text. If invoked without arguments, then it lists any colors/attributes you've set (or for all faces if invoked with a ! suffix). -If invoked with the name of a face -(see below) +If invoked with the name of a face (see below) then it lists the colors/attributes for that single face. If invoked with both a face name and new colors/attributes then it changes the colors/attributes for that face. @@ -1997,7 +2010,9 @@ which uses it mostly to configure the toolbar. -

      se[t][!] [option=value... | option?... | all | everything] +
      se[t][!] [option=value | option | nooption | option? ]... +
      se[t][!] all | everything +
      se[t] gui.[option=value | option | nooption ]...
      The :set command allows you to examine or change the values of options. @@ -2049,6 +2064,17 @@ not been changed. This is used mostly in Elvis' initialization scripts. +

      The special "gui." notation is used mostly by the +:mkexrc command to store +GUI-dependent options. +If the gui happens to match the name of the current user interface +(as stored in the gui option), then the rest +of the line is processed as usual. +For any other gui name, the command line is stored internally, +and incorporated into the file generated by :mkexrc. +This way, a single ".exrc" file (or "elvis.rc" or ".elvisrc") can store +settings for multiple GUIs. +

      lo[cal] option=value... | option...
      The :local command is similar to :set, and is intended to be used in aliases and scripts. @@ -2094,7 +2120,8 @@

      Note that even Boolean options use the "=" notation here. You can not say ":let nowrap" to turn off the -wrap option, for example. +wrap option, for example, +but ":let wrap=false" works.

      The "=~ excmds" form is only available if Elvis is compiled with FEATURE_EQUALTILDE defined (i.e., if :calc feature("equaltilde") returns True). @@ -2118,6 +2145,26 @@ and mark the option has having not been changed. This is used in some of Elvis' initialization scripts. +

      al[ias][!] [name [excmds]] +
      The :alias command manipulates the alias list. +(See the Tips section of the manual for +a discussion of aliases.) +With no arguments, :alias lists all user-defined aliases, +and :alias! lists all system-defined aliases. + +

      When given a name but no commands, :alias displays the +complete definition of the named alias. + +

      When given a name and commands, :alias defines (or redefines) +an alias. +Adding a "!" suffix (:alias!) will cause the alias to be marked +as a system alias, which is only significant because the +:mkexrc command doesn't save system aliases. + +

      unal[ias] name +
      +The :unalias command deletes the alias with a given name. +
      if expr
      th[en] excmds
      el[se] excmds @@ -2475,6 +2522,7 @@ |-------|-------------------|-----------------------------------| | range | fo[ld][!] | [name] | | range | unf[old][!] | [name] | +| range | nof[old][!] | | ^-------^-------------------^-----------------------------------^ @@ -2553,6 +2601,19 @@ containing "tag" in it somewhere.)
       	:g/^{/,/^}/fold {(current("tag"))(":" $1 "lines")}
      + +
      range nof[old][!] +
      This causes Elvis to forget any folds that are wholly or partially contained +within the given address range (or the current line if you omit the range). +This differs from the :unfold command in that after +:nofold, you can't easily refold a region. + +

      Normally it only forgets one layer of nested folds, but the "!" suffix +makes it forget all layers of nested folds within the address range. +In particular, +the command ":%nofold!" wipes out all previous folds. +

    +

    There are also folded() and unfolded() functions. @@ -2568,10 +2629,13 @@ else fold } +

    The <Tab> visual command toggles +a FOLD between its folded and unfolded states. +The above alias give ex commands a way to do the same thing. +

    Also, see the folding option for a way to enable folding in one window but disable it in another. -

    4.20 Regions

    .-------.-------------------.-----------------------------------.
    @@ -2645,6 +2709,8 @@
     
    range chr[egion] face newface [newcomment]
    The :chregion command changes one type of region into another type, based on the face. +If you supply a new comment, it will change that too. +

    The following is a nifty trick which automatically marks changed lines as "unsaved" while you're editing, and then converts those to "saved" when you write the file. @@ -2815,7 +2881,7 @@ | range | norm[al][!] | [keystrokes] | | | sh[ell] | | | | st[op][!] | | -| | sus[pend][!] | | +| | su[spend][!] | | | | ve[rsion] | | | line | go[to] | | | line | ma[rk] | mark | @@ -2894,7 +2960,7 @@ Then Elvis and the shell can then run simultaneously.)

    st[op][!] -
    sus[pend][!] +
    su[spend][!]
    The :stop and :suspend commands are identical to each other. If the operating system and user interface support it, they will suspend Elvis and resume the shell that started Elvis. @@ -2970,11 +3036,12 @@ | | ec[ho] | text | | | e[dit][!] | [+line] [file] | | | el[se] | excmds | +| range | nof[old][!] | | | | er[rlist][!] | [file] | | | erro[r] | text | | | ev[al] | expr | | | ex[!] | [+line] [file] | -| | f[ile] | [file] | +| | f[ile][!] | [file] | | range | fo[ld][!] | [name] | | | for[each] | option ["in"] expression | | range | g[lobal][!] | /regexp/ excmds | @@ -3004,6 +3071,7 @@ | range | nu[mber] | [count] | | | on[ly] | | | | o[pen][!] | [+line] [file] | +| | ph[elp] | topic | | | po[p][!] | | | | pres[erve] | | | | pre[vious][!] | | @@ -3026,14 +3094,14 @@ | | sl[ast] | | | | sne[w] | | | | sn[ext] | [file...] | -| | so[urce][!] | file | +| | so[urce][!] | file | !shellcmd | | | sp[lit] | [+line] [file | !shellcmd] | | | sre[wind][!] | | | | stac[k] | | | | sta[g] | [tag] | | | st[op][!] | | | range | s[ubstitute] | /regexp/newtext/[g][p][x][count] | -| | sus[pend][!] | | +| | su[spend][!] | | | | sw[itch] | expr | | | ta[g][!] | [tag] | | | th[en] | excmds | diff -urN elvis-2.2_0/doc/elvisex.html.orig elvis-2.2_1/doc/elvisex.html.orig --- elvis-2.2_0/doc/elvisex.html.orig 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/doc/elvisex.html.orig 2004-03-26 22:35:31 +0100 @@ -0,0 +1,3104 @@ + +Elvis Ex Mode + + +

    4. EX COMMAND MODE

    + +Ex is an editing mode in which Elvis acts like a line editor. +This means that you type in a command line, and when the line is complete +Elvis executes it on the current text buffer. +I.e., in ex each line (or group of lines) is a command, +as opposed to vi where each character (or group of characters) is a +command. +The commands are listed below either grouped by function +or listed in alphabetical order. + +

    Typically, ex commands are used to do perform complex actions such as +global search & replace, or actions which require an argument such as +writing the edit buffer out to a different file. + +

    Ex is also used as the configuration language for Elvis; +configuration scripts such as elvis.ini, +.exrc (or elvis.rc), and elvis.arf +contain a series of ex commands. + +

    You can switch freely between vi and ex. +If you're in vi mode, you can enter a single ex command line via the +visual : command, or more permanently switch via +the visual Q command. +If you're in ex mode, you can switch to vi mode via ex's +:vi command. + +

    Normally Elvis will start in vi mode, but you can force it to start in +ex mode by supplying a -e command line flag. +On UNIX systems, you can link Elvis to a name which ends with "x" to +achieve the same effect. + +

    The remainder of this section discusses how to enter lines, the general +syntax of an ex command line, and the specific commands which Elvis supports. + +

    4.1 Entering lines

    +In Elvis, when you're typing in an ex command line +you're really inputting text into a buffer named "Elvis ex history". +All of the usual input mode commands are available, +including Backspace to erase the previous character, +Control-W to erase the previous word, and so on. + +

    Any previously entered lines will still be in the "Elvis ex history" +buffer, and you can use the arrow keys to move back and edit earlier commands. +You can even use the Control-O input-mode command with +the ?regexp visual command, +to search for an earlier command line. + +

    When you hit the Enter key on a line in the "Elvis ex history" +buffer, Elvis sends that line to the ex command parser, +which is described in the next section. + +

    4.1.1 An example

    + +Suppose you enter the command... +
    +	:e ~/proj1/src/header.h
    +
    +...and then realize that you really wanted "header2.h" instead of "header.h". +You simplest way to get "header2.h" is to... +
      +
    1. Hit the : key to start a new ex command line. +
    2. Hit the Up arrow key, or ^O k to move back to the + preceding command line (which was ":e ~/proj1/src/header.h"). + ^O k works because ^O reads and executes one vi + command, and the k vi command moves the cursor back one line. + The Up arrow key works because it is mapped to "visual k", + which does exactly the same thing as ^O k. +
    3. Hit the Left arrow key twice, or ^O 2 h, to move + the cursor back to the '.' character in "header.h". +
    4. Hit 2 to insert a '2' before the '.' character. At this point, + the line should look like ":e ~/proj1/src/header2.h". +
    5. Hit Enter to submit the revised command line. +
    + +

    Or suppose you really wanted "footer2.h" instead of "header2.h". +This is a little trickier because you want to delete characters in the +middle of the command line, before inserting the correct text. +The simplest way to do this is move the cursor to a point just after +the last character that you want to delete, and then backspace over them. +The steps are: +

      +
    1. Hit the : key to start a new ex command line. +
    2. Hit the Up arrow key or ^O k repeatedly to move + back to the ":e ~/proj1/src/header2.h"command line. +
    3. Hit the Left arrow key five times, or ^O 5 h, to move + the cursor back to the last 'e' character in "header2.h". +
    4. Hit the Backspace key four times to delete the word "head". + It will still show on the screen, but Elvis will know that it has been + deleted. This is the same sort of behavior that Elvis (and vi) exhibits + when you backspace over newly entered text in input mode. +
    5. Type f o o t to insert "foot" where "head" used to be. At this + point, the line should look like ":e ~/proj1/src/footer2.h". +
    6. Hit Enter to submit the revised command line. +
    + +

    4.1.2 The TAB key

    +

    The Tab key has a special function when you're inputting +text into the "Elvis ex history" buffer. +It is used for name completion. +(Exception: Under MS-DOS, this feature is disabled in order to reduce the +size of the program, so it will fit in the lower 640K.) + + +

    Name completion works like this: +The preceding word is assumed to be a partial name for an ex command, +an option, a tag, or a file. +The type of name is determined by the context in which it appears -- +commands appear at the start of an ex command line, and the others +can only occur after certain, specific command names. +Elvis searches for all matches of the appropriate type. + +

    If there are multiple matches, then Elvis fills in as many +characters of the name as possible, and then stops; +or, if no additional characters are implied by the matching names, +then Elvis lists all matching names and redisplays the command line. +If there is a single match, then Elvis completes the name and appends a space + character or some other appropriate character. +If there are no matches, then Elvis simply inserts a tab character. + +

    Also, if while entering a :set command you hit the +Tab key immediately after "option=" then Elvis +will insert the current value of the option. +You can then edit that value before submitting the command line. + +

    I tried to make Elvis smart enough that the Tab key will +only attempt file/command/option completion in contexts where it makes sense to +do so, but that code might not be 100% correct. +You can bypass the completion by typing a Control-V +before the Tab key. +You can also disable name completion altogether by setting the +"Elvis ex history" buffer's inputtab +option to "tab", via the following command: +

    +	:(Elvis ex history)set inputtab=tab
    +
    +or the abbreviated form: +
    +	:("Eeh)se it=t
    + +

    By default, Elvis ignores binary files when performing filename +completion. +The completebinary option can +be used to make Elvis include binary files. +That's a global option (unlike inputtab +which is associated with a specific buffer), so you don't need to specify +the buffer name; a simple :set completebinary will set it. + +

    4.2 Syntax and Addressing

    +In general, ex command lines can begin with an optional window id. +This may be followed by an optional buffer id, +and then 0, 1, or 2 line addresses, +followed by a command name, and perhaps some arguments after that +(depending on the command name). + +

    A window ID is typed in as a decimal number followed by a colon character. +If you don't supply a window ID (and you almost never will) then it defaults +to the window where you typed in the command line. +The :buffer command lists the buffers, and shows which +one is being edited in which window. +Also, the windowid option indicates the +ID of the current window. + +

    A buffer ID is given by typing an opening parenthesis, the name of the +buffer, and a closing parenthesis. +For user buffers, the name of the buffer is usually identical to the name of +the file that it corresponds to. +For example, a file named .Xdefaults would be loaded into a buffer which +could be addressed as (.Xdefaults). +Elvis also assigns numbers to user buffers, which may be more convenient +to type since numbers are generally shorter than names. +If .Xdefaults is the first file you've edited since starting Elvis, then +its buffer could be addressed as (#1). +The :buffer command shows the number for each user +buffer. + +

    Elvis also has several internal buffers, all of which have names that start +with "Elvis ", such as (Elvis cut buffer x) and +(Elvis error list). +The :buffer! command (with a ! suffix) will list them all. +For the sake of brevity, Elvis allows you to refer to cut buffers as +("x). +Similarly, the other internal buffers can be referred to via a " character +and the initial letter in each word of the full name, such as +("Eel) for (Elvis error list). + +

    The parentheses can also contain an '=' followed by an +expression, +in which case Elvis will evaluate the expression and use +the result as the buffer name. +For example, if the x option is set to "run2000", +then ":(=x)%p" is equivalent to ":(run2000)%p". +(They both print the contents of the buffer named "run2000".) +This is often handy in aliases. + +

    Commands which don't access the text, such as ":quit", +don't allow any line addresses. +Other commands, such as ":mark", +only allow a single line address. +Most commands, though, allow two line addresses; +the command is applied to all lines between the two specified lines, +inclusively. +The tables below indicate how many line addresses each command allows. + +

    Line addresses are always optional. +The first line address of most commands usually defaults to the current line. +The second line address usually defaults to be the same as the first line address. +Exceptions are :write, :lpr, +:global, and :vglobal, +which act on all lines of the file by default, and +:!, which acts on no lines by default. + +

    If you use the visual V command to mark +a range of lines, and then use the visual : +command to execute a single ex command, +then the default range affected by the ex command will +be the visibly marked text. + +

    Line addresses consist of an absolute part and +a relative part. +The absolute part of a line specifier may be either +an explicit line number, +a mark, +a dot to denote the current line, +a dollar sign to denote the last line of the file, +a forward or backward search, or +an expression. + + +An explicit line number is simply a decimal number, +expressed as a string of digits. + +A mark is typed in as an apostrophe followed by a letter. +Marks must be set before they can be used. +You can set a mark in visual command mode by typing "m" and a letter, +or you can set it in ex command mode via the "mark" command. + +A forward search is typed in as a regular expression surrounded by +slash characters; searching begins at the default line. +A backward search is typed in as a regular expression +surrounded by question marks; +searching begins at the line before the default line. + +An expression is a = followed by either +the name of an option, or +a () pair containing a more complex +expression. + +

    If you omit the absolute part, then the default line is used. + +

    The relative part of a line specifier is typed as a + +or - character followed by a decimal number. +The number is added to or subtracted from the absolute part of the line +specifier to produce the final line number. + +

    To use a range of addresses, give the expressions for the first and last +line separated by either a comma or semicolon. +When separated by a comma, both lines are addressed relative to the default +line (where the cursor is, generally). +When separated by a semicolon, the second address will be relative to the +first address. +You can also give more than two addresses, in which case the last two will +define the range. + +

    As a special case, the % character may be used to specify +all lines of the file. +It is roughly equivalent to saying 1,$. +This can be a handy shortcut. + +

    Here are some addressing examples, using the :p command: +

    +   COMMAND      | ACTION
    +   -------------|-------------------------------------------
    +   :p           | print the current line
    +   :37p         | print line 37
    +   :'gp         | print the line which contains mark g
    +   :/foo/p      | print the next line that contains "foo"
    +   :$p          | print the last line of the buffer
    +   :20,30p      | print lines 20 through 30
    +   :1,$p        | print all lines of the buffer
    +   :%p          | print all lines of the buffer
    +   :(zot)%p     | print all lines of the "zot" buffer
    +   :/foo/-2,+4p | print 5 lines around the next "foo"
    +   :=x p        | print the line whose line number is in x
    +   :(=b)=n p    | print computed line n from computed buffer b
    + +

    The optional addresses are followed by the command name. +Command names may be abbreviated. +In the sections that follow, the command's full name is given with the +optional part enclosed in square brackets. + +

    Some commands allow a '!' character to appear immediately after the +command name. +The significance of the '!' varies from one command to another, +but typically it forces the command to do something dangerous that it would +ordinarily refuse to do. +For example, :w file refuses to overwrite an +existing file, but :w! file will do it. + +

    Many commands allow (or even require) additional arguments. +The descriptions below list which arguments each command accepts +with optional commands denoted by square brackets. +The most common argument types are: + +

    + +
    /regexp/ +
    This is a regular expression. +You can use any punctuation character to delimit it, but the '/' character +is the most commonly used. + +
    /regexp/newtext/ +
    This is a regular expression +followed by replacement text. + +
    count +
    This is a number - a string of digits. +Generally, it is used as the repeat count for certain commands. + +
    cutbuf +
    This is the name of a cut buffer - a single letter. +Elvis also allows (but does not require) a quote character before the letter. + +
    excmds +
    This is another ex command, or list of ex commands. +Traditionally, the whole list of commands had to appear on the same line, +delimited by '|' characters. +Elvis has the added versatility of allowing a '{' character on the first line, +each command on a separate following line, and then '}' on a line by itself to mark +the end of the ex command list. + +
    lhs +
    This is string of characters. +If whitespace characters are to be included in it, then they must be +quoted by embedding a ^V character before them. + +
    face +
    This is the name of a text face -- that is, a type of text. +The :color command is used to configure the appearance +of the face, and :check defines the spell-checking rules. + +
    line +
    This is a line address, as described earlier. + +
    +line +
    Some commands which cause a file to be loaded also allow you to specify +some other command to be executed after the loading is complete. +To use this feature, you mist give a "+" followed by the command, in between +the command name and the file name. +Here's an example that loads foo and then moves the cursor to line 40. +
    +	:e +40 foo
    + +

    Usually the command is just a line number, so this is denoted as "+line" +in this documentation. +Other commands are allowed though, such as "+/text" to search for text, +or "+normal" to force it to use the normal +display mode. + +

    Traditionally, commands supplied in this manner weren't allowed to contain +whitespace, because that makes parsing the command line harder. +This is too limiting, though, so Elvis allows you to embed spaces in the +command by wrapping the entire deferred command in double-quotes, like this: +

    +	:e +"set bufdisplay=man" filedb.8
    + +
    mark +
    This is the name of a mark - a single lowercase letter. +Elvis allows (but does not require) an apostrophe before the letter. + +
    rhs +
    This is a string of characters. +If it begins with a whitespace character, then that character must be quoted +by embedding a ^V character in the command line before it. +Other whitespace characters in the string do not need to be quoted. + +
    expr +
    This is an arithmetic expression +using the normal syntax. + +
    shellcmd +
    This is a command line which is passed to the system's command interpreter. +Within the command line, the following character substitutions take place, +unless preceded by a backslash: +
    +	.-----------.----------------------------.
    +	| CHARACTER | REPLACED BY                |
    +	|-----------|----------------------------|
    +	|     %     | Name of current file       |
    +	|     #     | Name of alternate file     |
    +	|     #n    | Name of file whose bufid=n |
    +	|     !     | Previous command line      |
    +	|     \@    | Word at cursor location    |
    +	^-----------^----------------------------^
    +
    +Note that the \@ substitution requires a backslash. +This quirk exists for the sake of backward compatibility - +the real vi doesn't perform any substitutions for just plain @, +and neither does Elvis. + +
    file or files +
    This is one or more file names, or a "wildcard" pattern which matches +the names of zero or more files. File names are subjected to three levels +of processing. First, leading ~ characters and certain other characters +are replaced with text, as follows: +
    +    .-----------.------------------------------------------------.
    +    | SYMBOL    | REPLACED BY                                    |
    +    |-----------|------------------------------------------------|
    +    | ~user     | (Unix only) Replaced by home directory of user |
    +    | ~+        | Replaced by current working directory          |
    +    | ~-        | Replaced by previous directory (previousdir)   |
    +    | ~         | Replaced by home directory (home)              |
    +    | %         | Replaced by the name of the current file       |
    +    | #         | Replaced by the name of the alternate file     |
    +    | #n        | Replaced by the filename of buffer with bufid=n|
    +    | (space)   | Delimits one file name from another            |
    +    | `program` | Run program, interpret its output as filenames |
    +    ^-----------^------------------------------------------------^
    +
    +The second stage of processing evaluates each name using the +simpler expression syntax. +This basically means that expressions of the form +$NAME will be replaced with the value of +the environment variable named NAME. +Also, you can use parentheses around option names or more complex expressions. +For example, if the user option f contains +the name of a file, then you could say ":e (f)" to edit that file. + +

    In either of the first two stages, +backslashes may be used to prevent the special symbols from +having their usual meaning; they'll be treated as normal text instead. +In particular, a backslash-space sequence can be used to give a filename +which includes spaces; e.g., to edit "C:\Program Files\foo" you would type +":e C:\Program\ Files\foo". +Note that backslashes which are followed by a normal character are simply +retained as normal characters, so you rarely need to type a double-backslash +when your file name needs only a single backslash. + +

    The third stage of processing checks for "wildcard" characters in the name, +and if there are any then the whole name is replaced by the name of each +matching file. The exact list of supported wildcards will vary from one +operating system to another, but the following are typical: +

    +	.--------.----------------------------------------------.
    +	| SYMBOL | MATCHES                                      |
    +	|--------|----------------------------------------------|
    +	| *      | Any string of characters, of any length      |
    +	| ?      | Any single character                         |
    +	| [A-Z]  | (Unix only) Any single character from A to Z |
    +	^--------^----------------------------------------------^
    +
    +In most operating systems, wildcards are only recognized when they occur +in the last file name part of a longer pathname. In other words, you can +use wildcards for file names, +but not in directory names leading up to file names. + +

    Traditionally, vi has used the Unix shell to expand wildcards. +However, this interferes with the use of spaces in file names, isn't easily +portable to non-Unix operating systems, and is a potential security hole. +So Elvis performs all wildcard expansion itself. The only disadvantage +of this is that you loose other shell notations such as +{alt1,alt2}. +

    + +

    Most commands can be followed by a '|' character and another ex command. +Others can't. In particular, any command which takes a excmd +or shellcmd argument doesn't treat '|' as a command delimiter. + +

    If a command does treat '|' as a delimiter, and you want '|' to be treated +as part of a command argument, then you'll need to quote the '|' character +by preceding it with a backslash or ^V, depending on the command. +(Sadly, different commands require different quote characters.) + +

    4.3 Ex Commands, Grouped by Function

    + +
  • 4.4 The help command itself +
  • 4.5 Editing commands +
  • 4.6 Global edit commands +
  • 4.7 Displaying text +
  • 4.8 Tags +
  • 4.9 File I/O commands +
  • 4.10 The args list, and selecting a file to edit +
  • 4.11 Quitting +
  • 4.12 Scripts and macros +
  • 4.13 Working with a compiler +
  • 4.14 Built-in calculator +
  • 4.15 Buffer commands +
  • 4.16 Window commands +
  • 4.17 Configuration +
  • 4.18 Auto commands +
  • 4.19 Folding +
  • 4.20 Regions +
  • 4.21 Spell checking +
  • 4.22 Miscellaneous +
  • + +

    4.4 The help command itself

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | h[elp]            | topic                             |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    h[elp] topic +
    The :help command loads and displays a +help file for a given topic. +There are several help files, covering a wide variety of topics. + +

    Elvis looks at the topic you supply, and tries to determine whether +it is an ex command name, vi keystroke, option name, or something else. +Based on this, it generates a hypertext link to the topic in the appropriate +help file, and shows the topic in a separate window. +Elvis uses the following rules to convert your requested topic into +a hypertext reference: +

    +  .-------------------.-------------------------------------------.
    +  | COMMAND           | ELVIS' INTERPRETATION                     |
    +  |-------------------|-------------------------------------------|
    +  | :help             | With no topic, Elvis loads the table of   |
    +  |                   |   contents. This has hypertext links that |
    +  |                   |   can lead you to any other topic.        |
    +  | :help ex          | Elvis loads the chapter describing ex     |
    +  |                   |   commands.                               |
    +  | :help vi          | Elvis loads the chapter describing vi     |
    +  |                   |   commands.                               |
    +  | :help set XXX     | If XXX is an option name, Elvis will show |
    +  |                   |   the description of that option; else it |
    +  |                   |   will list groups of all options.        |
    +  | :help display XXX | If XXX is the name of a display mode, then|
    +  |                   |   Elvis will show the description of that |
    +  |                   |   mode.  Otherwise it shows the top of the|
    +  |                   |   display mode chapter                    |
    +  | :help autocmd XXX | If XXX is the name of an autocmd event,   |
    +  |                   |   then Elvis will show the description of |
    +  |                   |   that event; else it will take you to the|
    +  |                   |   top of the event list                   |
    +  | :help :XXX        | If XXX is an ex command name, Elvis will  |
    +  |                   |   show its description; else Elvis will   |
    +  |                   |   list groups of all ex commands.         |
    +  | :help XXX()       | Elvis loads the chapter describing the    |
    +  |                   |   built-in calculator, and moves to the   |
    +  |                   |   section describing function XXX.        |
    +  | :help <XXX>       | Describe Elvis' implementation of the HTML|
    +  |                   |   tag <XXX>                               |
    +  | :help XXX         | If XXX appears to be a keystroke then     |
    +  |                   |   Elvis will assume it is meant to be a   |
    +  |                   |   vi command and will show the command's  |
    +  |                   |   description.  Else if it is an option   |
    +  |                   |   name Elvis will show that. Else if it   |
    +  |                   |   is an ex command, Elvis will show that. |
    +  |                   |   Else Elvis will show this description   |
    +  |                   |   of the :help command itself.            |
    +  ^-------------------^-------------------------------------------^
    +

    Although this chart only mentions chapters on +ex commands, vi commands, options, functions, autocmd events, and html tags, +there are many other chapters which are only +accessible via the table of contents shown by ":help" with no arguments. + +

    All of these help files are HTML documents. +Elvis' standard HTML editing facilities are available while you're +viewing the help text. +Some of the highlights of this are: +

      +
    • To close this help window, type ZQ. Actually, this works + for all windows. (You must hold the Shift key + as you type ZQ, because lowercase zq does + something else entirely: nothing!) +
    • Any underlined text is a hypertext reference. This means that you + can move the cursor onto it, and hit ^] + (Control-]) and the cursor will move to a topic describing the + underlined text. + Usually when viewing HTML documents, the Enter key will be + mapped to ^] so you can use it too. +
    • To return to your original position after following a hypertext reference, +hit ^T (Control-T). +
    • The Tab key moves the cursor forward to the next + hypertext reference. +
    +

    You can use Elvis to print the document via the :lpr +command. This assumes you have set the printing +options correctly. + +

    + +

    NOTE: In addition to the :help command, +most versions of Elvis also support two aliases which you may find handy. +The ":howto words..." alias +searches for given words in the title lines of a short "howto.html" document. +The ":kwic word" alias finds every +instance of a given word in any section of Elvis' documentation, and builds a +table showing each instance along with some of the surrounding text; +you can then follow hypertext links to the actual location in the manual. + +

    4.5 Editing commands

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +| line  | a[ppend][!]       | [text]                            |
    +| line  | i[nsert][!]       | [text]                            |
    +| range | c[hange][!]       | [count]                           |
    +| range | d[elete]          | [cutbuf] [count]                  |
    +| range | y[ank]            | [cutbuf] [count]                  |
    +| line  | pu[t]             | [cutbuf]                          |
    +| range | co[py]            | line                              |
    +| range | m[ove]            | line                              |
    +| range | t[o]              | line                              |
    +| range | !                 | shellcmd                          |
    +| range | >                 |                                   |
    +| range | <                 |                                   |
    +| range | j[oin][!]         |                                   |
    +|       | u[ndo]            | [count]                           |
    +|       | red[o]            | [count]                           |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    line a[ppend][!] [text] +
    The :append command inserts text after the +current line. +If no new text is supplied on the command line, then Elvis will wait for +you to type in text; +you can then mark the end of the new text by typing a "." (period) on a +line by itself. +In the real vi, adding a '!' suffix temporarily toggles the +autoindent option, but Elvis just +ignores the '!'. + +
    line i[nsert][!] [text] +
    The :insert command inserts text before the +current line. +Other than that, it is identical to the :append +command. +In the real vi, adding a '!' suffix temporarily toggles the +autoindent option, but Elvis just +ignores the '!'. + +
    range c[hange][!] [count] [text] +
    The :change command deletes old text lines +(copying them into the anonymous cut buffer) and then waits for you to enter +new text to replace it. +You can then mark the end of the new text by typing a "." (period) on a +line by itself. +In the real vi, adding a '!' suffix temporarily toggles the +autoindent option, but Elvis just +ignores the '!'. + +
    range d[elete] [cutbuf] [count] +
    range y[ank] [cutbuf] [count] +
    The :delete command copies +text into a cut buffer, and then deletes it from the edit buffer. +The :yank command copies text into a cut buffer but leaves the +edit buffer unchanged. + +
    line pu[t] [cutbuf] +
    The :put command "pastes" text from a cut buffer +back into the edit buffer. +The cut buffer's contents are inserted after the addressed line. +If you want to insert before the first line, you can use address 0 like +this: +
    +:0put
    + +
    range co[py] line +
    range t[o] line +
    +The :copy and :to commands are identical. +They both make a copy of a portion of an edit buffer, and insert that copy +at a specific point. +The destination line can be specified with an optional buffer name and the +full address syntax as described in section 4.2. +Consequently, you can use this command to copy part of one edit buffer +into another edit buffer. +The following example copies an 11-line window from the current buffer +onto the end of a buffer named "otherbuf" +
    +:-5,+5t(otherbuf)$
    + +
    range m[ove] line +
    +The :move command resembles :copy except that +:move deletes the original text. + +
    range ! shellcmd +
    +The :! command allows you to send parts of your edit buffer though +some external "filter" program. +The output of the program then replaces the original text. +For example, this following will sort lines 1 through 10 using the "sort" +program. +
    +:1,10!sort
    + +

    If you use the :! command without any line addresses, then +Elvis will simply execute the program and display its output. +This is only guaranteed to work correctly for non-interactive programs; +to execute an interactive program you should use the :shell +command. + +

    range < +
    range > +
    The :< and :> commands adjust the indentation on the +addressed lines. +The :< command decreases the leading whitespace by the number of +spaces indicated in the shiftwidth +option, and :> does the reverse. +You can use multiple < or > characters in a single command to increase +the shift amount; for example, :>>> shifts text by triple +the shiftwidth amount. +Normally Elvis' versions of these commands will leave blank lines unchanged, +but if you append a '!' (as in :>!) then the command will affect +blank lines in addition to other lines. + +
    range j[oin][!] +
    +The :join command joins multiple lines together so they form one +long line. +Normally it will intelligently decide how much whitespace it should place +between lines, depending on the sentenceend, +sentencegap, and +sentencequote options. +When invoked with a '!' suffix (as in :join!), it joins the lines +without doing fancy things to whitespace. + +
    u[ndo] [count] +
    red[o] [count] +
    The :undo command undoes recent changes. +The number of undoable changes is controllable on a buffer-by-buffer basis, +via the undolevels option. +The :redo command undoes an undo. + +
    + +

    4.6 Global edit commands

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +| range | g[lobal][!]       | /regexp/ excmds                   |
    +| range | v[global][!]      | /regexp/ excmds                   |
    +| range | s[ubstitute]      | /regexp/new/[g|.n][x][c][e][p|l|#]|
    +| range | &                 | [g|.n][p|l|#][x][c]               |
    +| range | ~                 | [g|.n][p|l|#][x][c]               |
    +|       | noh[lsearch]      |                                   |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    range g[lobal][!] /regexp/ excmds +
    range v[global][!] /regexp/ excmds +
    +The :global command searches for lines which contain the +/regexp/ and executes the given excmds +for each matching line. +The :vglobal command executes the excmds for each line +which does not match the /regexp/. + +

    In script files, you can supply multiple command lines to a single +:global or :vglobal by placing a '{' character on the +:global/:vglobal line, +following that with any number of command lines, and then finally a '}' +character on a line by itself to mark the end. +This notation doesn't allow nesting; you can't use {...} inside a larger +{...} command list. +(Hopefully this limitation will be lifted soon.) + +

    range s[ubstitute] /regexp/new/[g|.instance][c][x][e][p|l|#][count] +
    +The :substitute command searches for the /regexp/ in each +line, and replaces the matching text with newtext. +The interpretation of new text is described in +section 5.2 + +

    Briefly, flags supported by :s are... +

    +.------.-------------------------------------------------------.
    +| FLAG | WHAT IT MEANS                                         |
    +|------|-------------------------------------------------------|
    +|  g   | replace every instance in each line                   | 
    +|  .n  | (n is a number) replace the n'th instance in each line|
    +|  c   | ask for confirmation before making the change         |
    +|  x   | execute the newtext as an ex command; don't substitute|
    +|  e   | don't treat "no match" as an error                    |
    +|  p   | print the changed line like :p                        |
    +|  l   | print the changed line like :l                        |
    +|  #   | print the changed line like :nu                       |
    +^------^-------------------------------------------------------^
    + + +

    The newtext can be followed by a g flag to +replace all instances in each line. +Without the g flag, only the first match within each line is changed +(unless the gdefault option is set). +To replace some other instance in each line, give a decimal point followed by +the instance number, such as .3 to replace the third instance of +matching text in each line. + +

    You can also supply a p flag. +This causes each affected line to be printed (like :p), +after all substitutions have been made to that line. +Similarly, l lists it (like :l), and +# prints it with a line number (like :nu or :#). + +

    You can also make Elvis ask for confirmation before each substitution by +appending a c flag. +The :s command will locate the first match and then exit immediately, +but it will leave the window in an unusual input state in which +y performs a substitution and then moves on to the next match, +n does not perform the substitution but still moves to the next match, and +Esc cancels the operation. +Most other keys act like y in this mode. + +

    NOTE: +Elvis doesn't allow the c flag to be combined with the +:g command. +Instead of using ":g/regexp/s//newtext/gc", I suggest you get +in the habit of using ":%s/regexp/newtext/gc". +There is no way to do the more complex +":g/regexp1/s/regexp2/newtext/gc" in Elvis at this time. + +

    Elvis supports a special x flag. +Instead of performing each substitution, +Elvis will execute the final replacement text as an ex command line. +This is used in the implementation of modelines, like this: +

    +	try 1,5 s/ex:\(.*\):/\1/x
    +	try $-4,$ s/ex:\(.*\):/\1/x
    + +

    The :try command is there so that if no +modelines are found, Elvis won't consider that to be an error. +This is important because an error would cause the script to be aborted. +Another way to avoid errors when there is no match is to use the e +flag. + +

    range & [g|.instance][c][p|n|#][x][count] +
    range ~ [g|.instance][c][p|n|#][x][count] +
    The :& and :~ commands both repeat the previous +:substitute command, discarding any previous flags. +The difference between them is that :& uses the regular +expression from the previous :s command, but :~ +uses the most recent regular expression from any context. + +
    noh[lsearch] +
    +The :nohlsearch temporarily disables the +hlsearch option's highlighting. +It doesn't change that option's value; +it merely makes Elvis forget that it was supposed to highlight anything. +The next time you perform a search, the hlsearch option will +again highlight the matching text. + +
    + +

    4.7 Displaying text

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +| range | p[rint]           | [count]                           |
    +| range | l[ist]            | [count]                           |
    +| range | nu[mber]          | [count]                           |
    +| range | #                 | [count]                           |
    +| line  | z                 | [spec]                            |
    +| range | =                 |                                   |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    range p[rint] [count] +
    +The :print command displays lines from the edit buffer. +It displays them the normal way -- with tabs expanded and so on. + +
    range l[ist] [count] +
    +The :list command also displays lines, but it tries to make +all non-printing characters visible, and it marks the end of each line with +a '$' character. + +
    range nu[mber] [count] +
    range # [count] +
    The :number and :# commands are identical to each other. +They both display lines the normal way except that each line is preceded by +its line number. + +
    line z [spec] +
    +The :z command shows a "window" of lines surrounding the current line. +The default size of the "window" is taken from the +window option. +If a line address is supplied, then it becomes the current line before this +command is executed. +The spec can be one of the following characters; +the default is z+. +
    +   .------.-----------------------------------------------------.
    +   | SPEC | OUTPUT STYLE                                        |
    +   |------|-----------------------------------------------------|
    +   |  -   | Place the current line at the bottom of the window. |
    +   |------|-----------------------------------------------------|
    +   |  +   | Place the current line at the top of the window.    |
    +   |      | Upon completion of this command, the last line      |
    +   |      | output will become the current line.                |
    +   |------|-----------------------------------------------------|
    +   |  ^   | Jump back 2 windows' worth of lines, and then do    |
    +   |      | the equivalent of z+.  Note that z+ is like paging  |
    +   |      | forward and z^ is like paging backward.             |
    +   |------|-----------------------------------------------------|
    +   |  .   | Place the current line in the middle of the window. |
    +   |      | Upon completion of this command, the last line      |
    +   |      | output will become the current line.                |
    +   |------|-----------------------------------------------------|
    +   |  =   | Place the current line in the middle of the window, |
    +   |      | and surround it with lines containing hyphens.      |
    +   ^------^-----------------------------------------------------^ 
    + +
    range = +
    +The := command displays the line number of the current line, +or the addressed line if given one address. +If given a range of addresses, it tells you the line numbers of the two +endpoints and the total number of lines in the range. + +
    + +

    4.8 Tags

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | ta[g][!]          | [tag]                             |
    +|       | stac[k]           |                                   |
    +|       | po[p][!]          |                                   |
    +|       | pus[h][!]         | [+line] [file]                    |
    +|       | br[owse][!]       | restrictions                      |
    +^-------^-------------------^-----------------------------------^
    +
    + +Tags provide a way to associate names with certain places within certain files. +Typically, you will run the ctags program to create a file +named "tags" which describes the location of each function and macro +used in the source code for your project. +The tag names are the same as the function names, in this case. + +

    In HTML mode, Elvis uses the tags commands to follow hypertext links, +but we'll generally ignore that in the following discussions. + +

    + +
    ta[g][!] [tag] +
    +The :tag command performs tag lookup. +It reads the "tags" file to locate the named tag. +It then loads the source file where that tag is defined, and moves the +cursor to the specific point within that buffer where the tag is defined. +Elvis' implementation of :tag also allows you to give extra +restrictions and hints. +There is also a :stag command which creates a new window +and moves its cursor to the tag's definition point. + +
    pus[h][!] [+line] [file] +
    +The :push command is similar to :edit, +except that :push saves the cursor position first. +Specifically, invoking ":push" with no arguments pushes +the cursor position onto the tag stack -- nothing else. +Invoking ":push file" will push the cursor position +and then switch to a new file. + +
    br[owse][!] restrictions +
    +The :browse command extracts selected tags from the tags file, +constructs an HTML document listing those tags (with hypertext links to their +definition points inside your source code) and displays it in the current +window. +There is also a :sbrowse command which displays the +same list in a new window. +If invoked with no args, they browse all tags in the current file. +If invoked with a '!' suffix, they browse all tags. +See chapter 14. Tags for a full description of +restrictions and hints, and +browsing. + + + +
    stac[k] +
    +Before moving the cursor, Elvis will save the old cursor position on a stack. +You can use the :stack command to display the contents of that stack. +Each window has an independent stack. + +
    po[p][!] +
    +The :pop command pops a cursor position off the stack, restoring +the cursor to its previous position. +When you're browsing though source code, you will typically use :tag +to go deeper into the call tree, and :pop to come back out again. + +

    In HTML mode, these all work the same except that :tag expects to +be given an URL instead of a tag name. +URLs don't depend on having a "tags" file, so the "tags" file is ignored +when in HTML mode. +For more information, see the discussion of the +<a ...> tag in the Display Modes chapter. +The following example would move the cursor to the start of this section: +

    +    :tag elvisopt.html#TAGS
    + +
    + +

    4.9 File I/O commands

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +| line  | r[ead]            | file | !shellcmd                  |
    +| range | w[rite][!]        | [file | >>file | !shellcmd]       |
    +| range | lp[r][!]          | [file | >>file | !shellcmd]       |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    line r[ead] file | !shellcmd +
    +The :read command reads a file or external program, +and inserts the new text into the edit buffer after the addressed line. +If you don't explicitly give a line address, then the text will be +inserted after the current line. +To insert the file's contents into the top of the buffer (before line 1), +you should specify line 0. +For example, to insert the contents of "foo.txt" before line 1, you would +give the command... +
    +    :0 read foo.txt
    + +
    range w[rite][!] [file | >>file | !shellcmd] +
    +The :write command writes either the entire edit buffer (if no +address range is given) or a part of it (if a range is given) out to either +a file or an external filter program. +If you don't specify the output file or external command, +then Elvis will assume it should write to the file that the buffer was +originally loaded from. + +

    Elvis will normally prevent you from overwriting existing files. +(The exact details of this protection depend on the +edited, +filename, +newfile, +readonly, and +writeany options.) +If you want to force Elvis to overwrite an existing file, +you can append a "!" to the end of the command name, but before the file name. +In order to avoid ambiguity, there must not be any whitespace between +the "write" command name and the "!" character when you want to +overwrite an existing file. +Conversely, when writing to an external program there should be +whitespace before the "!" that marks the start of the program's command line. +The ">>file" notation tells Elvis to append to "file" instead of overwriting it. + +

    range lp[r][!] [file | >>file | !shellcmd] +
    +The :lpr command sends text to the printer. +It is similar to :write except that :lpr +formats the buffer contents as defined by the +bufdisplay option and the +printing options. +If no output file or external program is specified, +then the printer output is sent to the file or external program +specified by the lpout option. + +
    + +

    4.10 The args list, and selecting a file to edit

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | ar[gs]            | [file...]                         |
    +|       | n[ext][!]         | [file...]                         |
    +|       | N[ext][!]         |                                   |
    +|       | pre[vious][!]     |                                   |
    +|       | rew[ind][!]       |                                   |
    +|       | la[st]            |                                   |
    +|       | wn[ext][!]        |                                   |
    +|       | f[ile]            | [file]                            |
    +|       | e[dit][!]         | [+line] [file]                    |
    +|       | ex[!]             | [+line] [file]                    |
    +|       | vi[sual][!]       | [+line] [file]                    |
    +|       | o[pen][!]         | [+line] [file]                    |
    +^-------^-------------------^-----------------------------------^
    +
    + +The "args list" is a list of file names. +It provides an easy way to edit a whole series of files, one at a time. +Initially, it contains any file names that you named on the command line +when you invoked Elvis. + +
    + +
    ar[gs] [file...] +
    +The :args command displays the args list, with the +current file name enclosed in brackets. +You can also use :args to replace the args list with a new +set of files; +this has no effect on whatever file you're editing at that time, but +it will affect any :next commands that you give later. + +
    n[ext][!] [file...] +
    +The :next command switches to the next file in the args list. +This means it loads the next file from the args list into an edit buffer, +and makes that edit buffer be the current buffer for this window. +You can also give a new args list on the :next command line; +this acts like a :args command to set the args list, followed by +an argumentless :next command to load the next (first) file in +that list. + +
    N[ext][!] +
    pre[vious][!] +
    The :Next (with a capital "N") and :previous commands +are identical to each other. +They both move backwards through the args list. + +
    rew[ind][!] +
    la[st] +
    The :rewind and :last commands switch to the first and +last files in the args list, respectively. + +
    wn[ext][!] +
    +The :wnext command is like a :write command +followed by a :next command. +It saves any changes made to the current file before switching to the next +file. +(The autowrite option offers a better +alternative.) + +
    f[ile] [file] +
    +The :file command displays information about the current buffer. +It can also be used to change the filename associated with this buffer. + +
    e[dit][!] [+line] [file] +
    ex[!] [+line] [file] +
    The :edit and :ex commands are identical to each other. +They both switch to a new file, or if no file is named then they reread +the current file. +This has no effect on the args list. + +
    vi[sual][!] [+line] [file] +
    o[pen][!] [+line] [file] +
    The :visual and :open commands switch to a new file if +one is named; otherwise they continue to use the current buffer without +reloading it from the original file. +These commands have the side-effect of switching the window mode from ex mode +to either the normal visual mode or the uglier "open" mode, respectively. +"Open" mode allows you to use all of the visual commands, but it only displays +a single line (the line that the cursor is on) at the bottom of the screen. +The sole advantage that "open" mode has over "visual" mode is that "open" +mode doesn't need to know what kind of terminal you're using. + +
    + +

    4.11 Quitting

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | cl[ose][!]        |                                   |
    +|       | q[uit][!]         |                                   |
    +|       | wq[uit][!]        | [file]                            |
    +|       | x[it][!]          | [file]                            |
    +|       | qa[ll][!]         |                                   |
    +|       | pres[erve]        |                                   |
    +^-------^-------------------^-----------------------------------^
    +
    + +Except for :qall, all of these commands attempt to close the current +window without losing any changes. +When the last window is closed, Elvis exits. +The differences between these commands concern how modified buffers are handled. +In the discussions below, it is assumed that +tempsession is True and the buffer's +retain option is False, which is usually +the case. + +
    + +
    cl[ose][!] +
    +The :close command is the simplest. +If the current window is the only window and one or more buffers have been +modified but not yet saved, then :close will fail; +otherwise the current window will be closed. +The visual ^Wq command uses this command internally. +If the window's buffer was modified, then Elvis will just have a modified +buffer lying around, which may or may not be visible in some other window. +That's okay. +The other quitting commands won't allow you to lose that buffer accidentally. +You can make some other window view that buffer by giving that buffer's +name in parentheses on an ex command line in that other window. + +
    q[uit][!] +
    +The :quit command fails if the current buffer has been modified. +If you wish to abandon the changes made to the current buffer, you can add +a "!" to the end of the command name; this has the effect of turning off +the buffer's modified flag. + +
    x[it][!] [file] +
    +The :xit command saves the file if it has been modified, and then +closes the window. +The visual ZZ command uses this command internally. + +
    wq[uit][!] [file] +
    +The :wquit command saves the file regardless of whether it has been +modified, and then closes the window. + +
    qa[ll][!] +
    +The :qall command tries to close all of the windows at once. +It is equivalent to giving the :quit command in each window. + +
    pre[serve] +
    +The :preserve command closes all windows and exits, but it doesn't +delete the session file. +You can restart the same edit session later by giving the command... +
    +	elvis -ssessionfile
    +
    +...where sessionfile is the name of the session file, +usually "/var/tmp/elvis1.ses". +You may want to check the value of the +session option first, just to make sure. + +
    + +

    4.12 Scripts and macros

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | @                 | cutbuf                            |
    +|       | so[urce][!]       | file                              |
    +|       | safel[y]          | excmds                            |
    +|       | al[ias][!]        | [name [excmds]]                   |
    +|       | unal[ias][!]      | name                              |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    @ cutbuf +
    +The :@ command executes the contents of a cut buffer as a series +of ex command lines. + +
    so[urce][!] file +
    +The :source command reads a file, and executes its contents as a +series of ex commands. +Normally, Elvis would issue an error message if the requested file didn't +exist but when a "!" is appended to the command name, Elvis will silently +ignore the command if it doesn't exist. + +
    safel[y][!] excmds +
    +The :safely executes its arguments as an ex command line. +While the argument commands are running, +the security option is temporarily set +to "safer" so most dangerous commands (security holes) are blocked. +In particular, ":safely source filename" +is a good way to run untrusted scripts. + +
    al[ias][!] [name [excmds]] +
    The :alias command manipulates the alias list. +(See the Tips section of the manual for +a discussion of aliases.) +With no arguments, :alias lists all user-defined aliases, +and :alias! lists all system-defined aliases. + +

    When given a name but no commands, :alias displays the +complete definition of the named alias. + +

    When given a name and commands, :alias defines (or redefines) +an alias. +Adding a "!" suffix (:alias!) will cause the alias to be marked +as a system alias, which is only significant because the +:mkexrc command doesn't save system aliases. + +

    unal[ias] name +
    +The :unalias command deletes the alias with a given name. + +
    + +

    4.13 Working with a compiler

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | cc[!]             | [args]                            |
    +|       | mak[e][!]         | [args]                            |
    +|       | er[rlist][!]      | [file]                            |
    +^-------^-------------------^-----------------------------------^
    +
    + +If you use Elvis to edit source code for programs, then you can have +Elvis read the output of your compiler and parse that output for error +messages. +When Elvis finds an error message, it can move the cursor to the file and +line number where the error was reported. + +

    To parse the compiler output, Elvis first breaks the output into lines. +Each line is then broken into words. +If a word looks like a number, then it is assumed to be a line number. +If a word looks like the name of an existing file, then it is assumed to +be a file name. +Any line which contains both a line number and a file name is treated as +an error report (with the remainder of the line serving as a description +of the error); lines which don't have both of these are simply ignored. + +

    + +
    cc[!] [args] +
    mak[e][!] [args] +
    The :cc and :make commands use the +ccprg and +makeprg options, respectively, +to run your compiler or "make" utility, and collect the output. +Elvis will then move the cursor to where the first error was detected. +(If there were no errors, Elvis will say so and leave the cursor unchanged.) + +
    er[rlist][!] [file] +
    +After that, the :errlist command can be used repeatedly to move +to each successive error. +You can also use the :errlist command with a file name argument +to load a new batch of error messages from a file; the cursor is then moved +to the first error in that batch. + +
    + +

    4.14 Built-in calculator

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | ca[lculate]       | expr                              |
    +|       | ev[al]            | expr                              |
    +^-------^-------------------^-----------------------------------^
    +
    + +Elvis has a built-in calculator which uses a C-like syntax. +It is described in section 12: Arithmetic Expressions. +The :if, :while, +:switch, and :let +commands also use the calculator. + +
    + +
    ca[lculate] expr +
    +The :calculate command evaluates an expression and displays the +result. + +
    ev[al] expr +
    +The :eval command evaluates an expression using the simpler syntax +(which basically means that text outside of parentheses is left alone), +and then executes the result as an ex command line. +This provides a way to use expressions with commands which would not +ordinarily use expressions. +For example, the following command line inserts the value the +elvispath option into the current +edit buffer. +
    +	:eval insert elvispath=(elvispath)
    + +

    Note: +There is a hardcoded limit of (normally) 1023 characters for the result of +any expression. This limit will sometimes impact the use of :eval. +For example, if your $EXINIT environment variable is longer +than 1023 characters then Elvis will be unable to interpret it during +initialization. + +

    + +

    4.15 Buffer commands

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | al[l][!]          | excmds                            |
    +|       | b[uffer][!]       | [buffer]                          |
    +|       | (                 | buffer                            |
    +|       | bb[rowse][!]      |                                   |
    +|       | sbb[rowse][!]     |                                   |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    al[l][!] excmds +
    +The :all command applies a given ex command line to each edit buffer +in turn. +Normally the command is applied just to the user edit buffers, but if you +append a "!" to the command name, then the ex command line is applied to +internal buffers as well. +For example, the following sets the "bufdisplay" option of all user +edit buffers: +
    +	:all set bufdisplay=normal
    + +

    In script files, you can supply multiple command lines to a single +:all commands +by placing a '{' character on the :all +line, following that with any number of command lines, and then finally a '}' +character on a line by itself to mark the end. +This notation doesn't allow nesting; you can't use {...} inside a larger +{...} command list. +(Hopefully this limitation will be lifted soon.) + +

    b[uffer][!] [buffer] +
    +The :buffer command lists either all user edit buffers, or +(when "!" is appended to the command name) all buffers including +internal ones. +If the buffer is being edited in one or more windows, then the window ID +is also displayed. +Buffers which have been modified will be marked with an asterisk. + +

    You can also use the :buffer command to make the current window +display a different buffer. + +

    ( buffer +
    +The :(buffer notation causes the current window to display the +named buffer, instead of the current buffer. +This isn't really a command; +it is part of an address. +Whenever you give an address without specifying a command, Elvis +moves the cursor to the addressed line. +In this particular case, we're addressing the most recently changed line +of a given buffer, so that's where the cursor is moved to. +For more information, see the discussion of Buffer IDs +earlier in this chapter (in the discussion of addresses). + +
    bb[rowse] +
    sbb[rowse] +
    +The :bbrowse and :sbbrowse commands create an HTML document +which lists the names of all user buffers (or, when a '!' is appended to the +command name, all buffers including internal buffers). +You can then go to one of the buffers just by following the hypertext link. +The difference between these two commands is that :bbrowse displays +the list in the current window, but :sbbrowse creates a new +window to display it. + +
    + +

    4.16 Window commands

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | sp[lit]           | [+line] [file | !shellcmd]        |
    +|       | new               |                                   |
    +|       | on[ly]            |                                   |
    +|       | sne[w]            |                                   |
    +|       | sn[ext]           | [file...]                         |
    +|       | sN[ext]           |                                   |
    +|       | sre[wind]         |                                   |
    +|       | sl[ast]           |                                   |
    +|       | sta[g]            | [tag]                             |
    +|       | sb[rowse]         | restrictions                      |
    +|       | sa[ll]            |                                   |
    +|       | wi[ndow]          | [ +[+] | -[-] | number | buffer]  |
    +|       | di[splay]         | [modename [language]]             |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    sp[lit] [+line] [file | !shellcmd] +
    +The :split command creates a new window. +If you supply a file name, then it will load that file into an edit buffer +and the new window will show that buffer. +If you supply a shell command line preceded by a '!' character, then it +will create an untitled buffer, and read the output of that command line +into the buffer. +Otherwise, the new window will show the same buffer as the current window. + +
    new +
    sne[w] +
    +The :new and :snew commands are identical to each other. +They both create a new empty buffer, and then create a new window to +show that buffer. + +
    on[ly] +
    +Close all windows except the current one. +(To close only the current window, use the :close command.) + +
    sn[ext] [file...] +
    sN[ext] +
    sre[wind][!] +
    sl[ast] +
    sta[g] [tag] +
    sb[rowse] restrictions +
    +The :snext, :sNext, :srewind, :slast, :stag, and :sbrowse +commands resemble the +:next, +:Next, +:rewind, +:last, +:tag, and +:browse +commands, respectively, +except that these "s" versions create a new window for the newly loaded file, +and leave the current window unchanged. + +
    sa[ll] +
    +The :sall command creates a new window for any files named in the +args list, which don't already have a window. +(See section 4.10: The args list... for a discussion +of the args list.) + +
    wi[ndow] [+ | ++ | - | -- | number | buffer ] +
    +The :window command either lists all windows +(when invoked with no arguments) or switches to a given window. +You can specify which to switch to by giving one of the following +arguments. +
    +    .----------.-----------------------------------------------.
    +    | ARGUMENT | MEANING                                       |
    +    |----------|-----------------------------------------------|
    +    |    +     | Switch to the next window, like ^Wk           |
    +    |    ++    | Switch to the next window, wrapping like ^W^W |
    +    |    -     | Switch to the previous window, like ^Wj       |
    +    |    --    | Switch to the previous window, wrapping       |
    +    |  number  | Switch to the window whose windowid=number    |
    +    |  buffer  | Switch to the window editing the named buffer |
    +    ^----------^-----------------------------------------------^
    +
    di[splay] [modename [language]] +
    +The :display command switches the window to a new display mode, +overriding the value of the bufdisplay +option. +The display option indicates the current +display mode. +If you omit the new modename, then the :display command will list +all supported display modes, with an asterisk next to the current mode. +The "syntax" mode allows you to specify which language's syntax it is supposed +to use; if you don't specify a language, Elvis will guess the language from +the file name's extension. + +
    + +

    4.17 Configuration

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | ab[breviate][!]   | [lhs rhs]                         |
    +|       | una[bbreviate][!] | lhs                               |
    +|       | map[!]            | [flags] [lhs [flags] rhs]         |
    +|       | unm[ap][!]        | [flags] lhs                       |
    +|       | bre[ak][!]        | [flags] lhs                       |
    +|       | unb[reak][!]      | [flags] lhs                       |
    +|       | dig[raph][!]      | [lhs [rhs]]                       |
    +|       | col[or][!]        | [face [attributes]]               |
    +|       | gu[i]             | text                              |
    +|       | se[t][!]          | [option=value | option? | all]    |
    +|       | lo[cal]           | [option=value | option ]          |
    +|       | le[t][!]          | option=expr                       |
    +|       | if                | expr                              |
    +|       | th[en]            | excmds                            |
    +|       | el[se]            | excmds                            |
    +|       | try               | excmds                            |
    +|       | wh[ile]           | expr                              |
    +|       | do[loop]          | excmds                            |
    +|       | for[each]         | option ["in"] expression          |
    +|       | sw[itch]          | expr                              |
    +|       | cas[e]            | value [excmds]                    |
    +|       | def[ault]         | excmds                            |
    +|       | mk[exrc][!]       | [file]                            |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    ab[breviate][!] [lhs rhs] +
    una[bbreviate][!] lhs +
    +The :abbreviate and :unabbreviate commands add and remove +entries to the abbreviation table, respectively. +Also, the :abbreviate command can be used with no arguments to list +the current contents of the abbreviation table. +For a discussion of abbreviations, see section +3.3: Abbreviations. +Normal abbreviations are only active while you're typing in a normal text +buffer; adding a '!' suffix to the command name causes the macro to be active +while you're entering ex command lines. + +
    map[!] [flags] [all | lhs [flags] rhs] +
    unm[ap][!] [flags] lhs +
    +The :map and :unmap commands add and remove entries to the +map table, respectively. + +

    +When the :map command is given without any text to map, it lists +the contents of a map table, excluding cursor keys. +When invoked with the word "all" instead of text to map, it lists all +entries from the map table including cursor keys. + +

    The primary purpose of the map table is to assign actions to the cursor keypad +and the function keys. +Each of these keys sends an arbitrary but distinctive sequence of characters +when pressed. +The map tables are used to convert these arbitrary character sequences into +command keystrokes that Elvis can do something useful with. +For example, arrow keys are normally mapped to the +h, +j, +k, and +l commands. + +

    The first text argument to :map is the raw character sequence +sent by a key. +This can be either a literal sequence of characters, or a gui-dependent +symbol representing a particular keystroke. +See the User Interfaces chapter for lists of +keystrokes. +Also, function keys can usually be denoted by #1 for the <F1> key, +#2 for the <F2> key, and so on. + +

    The second text argument is character sequence that Elvis should pretend you +typed whenever the raw characters are received. + +

    Elvis allows you to use symbolic names for some keys and characters. +The following symbols represent individual characters, and are case-insensitive: +<Nul>, <BS>, <Tab>, <FF>, <NL>, +<LF>, <EOL>, <CR>, <Return>, <Enter>, +<Esc>, <CSI>, <Del>, <Nul>, <Space>, <lt>, +<gt>, <Bar>, and <Bslash>. +In addition, each user interface may add its own symbols for cursor keys +and function keys. The exact list of symbols will vary. +Typically, these names will be case-sensitive. +See the X11 Keys, +Windows Keys, and +Termcap Keys manual sections. + +

    Flags may precede either argument. +Some flags select the context in which the map applies, and some affect +the way the second argument's text is used. + +

    +.----------.------------------------------------------------------.
    +|  FLAG    | WHAT IT MEANS                                        |
    +|----------|------------------------------------------------------|
    +| select   | works when text is selected via V, v, ^V, or mouse   |
    +| command  | works in the normal "Command" mode, if no selection  |
    +| motion   | works when used as the target of an operator         |
    +| noselect | synonym for command states other than "select"       |
    +| input    | works in "Input" or "Replace" mode on main buffer    |
    +| history  | works when typing an ex command or search expression |
    +| mode=name| ignore unless the mapmode option is set to name      |
    +| visual   | always interpret second argument text as vi commands |
    +| noremap  | never check second text for maps, regardless of remap|
    +| nosave   | prevent mkexrc from saving this map                  |
    +^----------^------------------------------------------------------^
    + +

    Using :map! (with a "!") causes Elvis to act as though you +used the "input" and "history" context flags. +If you don't use any context flags or "!", then Elvis will assume you +want "command", "motion", and "select" contexts. +Using "visual" implies "input" and "history", unless you explicitly supply at least one of those context flags. + +

    You can use contexts with a :map command that has no text +arguments to selectively list only those maps which work in that context. +You can also use contexts with :unmap to selectively delete +maps in a given context. + +

    bre[ak][!] [flags] lhs +
    unb[reak][!] [flags] lhs +
    +The :break and :unbreak commands set and reset the breakpoint +flag for a given macro, respectively. +Using a '!' suffix causes the breakpoint to be set for an input-mode map. +This is used for debugging macros, as described in section +16.3: How to debug macros. +If a macro has its breakpoint flag set, and the +maptrace option is set to run, +then when that map is encountered Elvis will automatically switch maptrace +to step mode. + +

    NOTE: +The flags are the sames as those used by :map, above, +but :break and :unbreak only partially support them. +This is because each entry in the map table may apply to multiple contexts, +but only has a single "break" flag. +So when you set or clear a break point in one context, it may also affect +other contexts. +Usually this isn't a problem. + +

    dig[raph][!] [lhs [rhs]] +
    +The :digraph command manipulates the digraph table. +(See section 3.2: Digraphs for a discussion +on digraphs.) +With no arguments, it lists the digraph table. +With one argument, it removes the given digraph from the table. +With two arguments, it adds the given digraph to the table, or +if the same two ASCII characters are already in the table then it alters +the existing entry. + +

    Normally, the :digraph command sets the most significant bit +in the last argument's character. +That way you don't need to be able to type a non-ASCII character on your +keyboard in order to enter it into the table; you can type the ASCII +equivalent and allow Elvis to convert it to non-ASCII before storing the +digraph. +If you don't want Elvis to set the most significant bit, then append a +"!" to the end of the command name. + +

    col[or][!] [face [attributes]] +
    +The :color command is used for configuring the colors and other +attributes of text. +If invoked without arguments, then it lists any colors/attributes you've set +(or for all faces if invoked with a ! suffix). +If invoked with the name of a face (see below) +then it lists the colors/attributes for that single face. +If invoked with both a face name and new colors/attributes +then it changes the colors/attributes for that face. + +

    The list of possible face names is not entirely preset. +Different display modes can be configured to use totally new faces +for any purpose. +A few of the faces are built into Elvis, and several more are used in +the syntax and markup descriptions included in the standard Elvis distribution. +These are: +

    +.------------.--------------.--------------------------------------.
    +| FACE NAME  | INHERIT FROM | USED FOR                             |
    +|------------^--------------^--------------------------------------|
    +|In all display modes and all user interfaces...                   |
    +| normal     | --           | default when window has input focus  |
    +| idle       | normal       | default when window loses input focus|
    +| bottom     | --           | ex commands at the bottom of a window|
    +| lnum       | (normal/idle)| line numbers for :set number         |
    +| showmode   | (normal/idle)| input mode name for :set showmode    |
    +| ruler      | (normal/idle)| line/column numbers for :set ruler   |
    +| selection  | --           | selected text for v, V, and ^V cmds  |
    +| hlsearch   | --           | matching text for the hlsearch option|
    +| hlobjectn  | --           | highlighting via hlobject & hllayers |
    +| spell      | --           | highlighting via spell-checking      |
    +| fold       | --           | regions folded via the :fold command |
    +| header     | --           | page headers if lpheader is set      |
    +|------------^--------------^--------------------------------------|
    +|In the "syntax" display modes...                                  |
    +| comment    | (normal/idle)| comments                             |
    +| string     | (normal/idle)| string literals                      |
    +| char       | string       | character literals                   |
    +| regexp     | string       | regular expression literals          |
    +| regsub     | regsub       | substitution text after regexp       |
    +| number     | (normal/idle)| number literals                      |
    +| keyword    | (normal/idle)| keywords                             |
    +| other      | keyword      | names matching "other" keyword descr.|
    +| function   | (normal/idle)| names which appear to be functions   |
    +| variable   | (normal/idle)| any other name                       |
    +| prep       | (normal/idle)| preprocessor directives              |
    +| prepquote  | (normal/idle)| filenames in preprocessor directives |
    +| doc        | (normal/idle)| embedded documentation               |
    +| docmarkup  | doc          | markup lines in embedded docs        |
    +| docindent  | doc          | embedded doc lines that are indented |
    +| kindk      | (normal/idle)| tags with "kind=k" if tagkind is set |
    +| libk       | (normal/idle)| library tags w/"kind=k" if taglibrary|
    +|------------^--------------^--------------------------------------|
    +| In "normal" and "syntax" display modes...                        |
    +| specialkey | (normal/idle)| control characters if list is on     |
    +| nontext    | specialkey   | end-of-line marker if list is on     |
    +| extends    | specialkey   | side-scrolling arrows if wrap is off |
    +|------------^--------------^--------------------------------------|
    +|In the "hex" display mode...                                      |
    +| hexheading | (normal/idle)| headings in the hex display mode     |
    +| hexoffset  | (normal/idle)| offsets, at the start of each line   |
    +| hexcursor  | (normal/idle)| hex code for character at cursor     |
    +|------------^--------------^--------------------------------------|
    +|In the "html", "man", and "tex" display modes...                  |
    +| formatted  | (normal/idle)| normal text in markup display modes  |
    +| bold       | formatted    | boldface text                        |
    +| italic     | formatted    | italic text                          |
    +| underlined | formatted    | underlined text                      |
    +| fixed      | formatted    | fixed-pitch text                     |
    +| link       | formatted    | HTML hypertext reference             |
    +| definition | bold         | definition of a term within text     |
    +| graphic    | fixed        | line-drawing chars for <pre graphic> |
    +| bullet     | (normal/idle)| bullets in unordered list, like <ul> |
    +| markup     | (normal/idle)| markups revealed by list/showmarkups |
    +| form       | (normal/idle)| common attributes of form inputs     |
    +| form_button| form         | buttons such as "Submit"             |
    +| form_radio | form         | values of radio buttons              |
    +| form_check | form         | checkbox                             |
    +| form_text  | form         | text input fields, including textarea|
    +| form_other | form         | other form inputs                    |
    +|------------^--------------^--------------------------------------|
    +|In the "x11" user interface...                                    |
    +| cursor     | --           | cursor color                         |
    +| tool       | --           | toolbar buttons                      |
    +| toolbar    | --           | toolbar & labels of disabled buttons |
    +| scroll     | tool         | scrollbar buttons (background only)  |
    +| scrollbar  | toolbar      | scrollbar background                 |
    +| status     | tool         | text boxes at statusbar's right edge |
    +| statusbar  | toolbar      | status bar & text on its left edge   |
    +^------------^--------------^--------------------------------------^
    + +

    The "normal" and "idle" distinction is made so that you can configure +Elvis to display the current window differently than other windows. +For example, ":color idle on gray80" in the x11 user interface +will cause idle windows to be displayed with a dull background color, while +the current window is displayed with the normal background color. + +

    Normally, the new attributes you specify will completely replace the +face's existing attributes. +However, you can add or subtract the new attributes from the face's +existing attributes by placing "+=" or "-=" +at the front of the attribute string. +Also, when using the "-=" notation you can simply say +"color" instead of the face's real color; +this will remove any existing color. +For example... +

    +	:color hlsearch += red
    +
    ... will cause hlsearch text to be +red (in addition to any other attributes -- usually bold), and... +
    +	:color hlsearch -= color
    +
    +... will remove that coloration, but keep the bold attribute. + +

    The :color command allows you to specify other attributes +besides color. +You can specify which font it should inherit any unspecified colors +or attributes from, via a "like" clause. +You can also give attributes such as "underlined". +The complete list of attributes includes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    color +The foreground color. +If you don't specify a foreground color, then the inherited foreground color +is used. +The exact list of acceptable colors will vary, depending on your hardware +and the user interface. +For X-windows, you can use any of the standard color names such as black, +royal blue, or #800028. +For the termcap interface and most others, the list includes +black, red, green, brown, blue, magenta, cyan, white, gray, light red, +light green, yellow, light blue, light magenta, light cyan, and +bright white... with the caveat that the "bold" attribute +may interact strangely with the "light" or "bright" colors. +There is also default color, but not all ANSI-ish terminals +implement it correctly, so use it with caution. +
    or color +An alternate foreground color. +Elvis will choose the foreground color which gives the highest contrast +against the normal background color. +(If no background color has been set, then the +background option may affect the choice.) +Elvis also remembers the color which had the highest contrast with white, +for use when printing whenever the lpcolor +option is set. +
    on color +The background color. +If you don't specify a background color, then the inherited background color +is used. +The list of color names also varies, just as it does for foreground colors. +For most user interfaces, the list of background colors is identical to the list +of foreground colors, but the termcap interface limits you to the first 8 colors +(black through white in the above list). +

    +The x11 interface has experimental support for +images for some backgrounds. +For example, "color normal on blue sand.xpm" will load the "sand.xpm" image, +tint it blue, and use that as the background for normal text. +See the X11 Background Images discussion +for more information. +

    +The termcap interface also has experimental support for a +transparent background color, which resets the background +to its default (whatever that happens to be). +You can also use default, which tries to achieve the same +effect in a slightly different way. +If you use this feature, then you should probably set the +background option. +

    like otherface +All faces ultimately inherit from either "normal" or "idle", +depending whether the window has input focus or not. +This attribute allows you to add another font in the inheritance chain between +this font and "normal" or "idle". +For example, ":color char like string" causes character literals +to be displayed using the same colors and attributes as string literals. +
    bold +
    underlined +
    italic +
    boxed
    +These are all attributes that can be attached to a face. +Any inherited attributes are retained; these keywords only allow you to +add new attributes to the inherited ones. +For example, ":color x underlined|color y like x bold", will cause the +"y" font to be both bold and underlined. + +

    Some user interfaces may not be able to display all of these attributes. +And even if the user interface can display them all individually, it may not +be able to display all possible combinations. + +

    The boxed attribute attempts to draw a box around the text; +for some user interfaces, or when printing to some types of printers, the +box may be implemented by changing the background. +In the termcap user interface, it uses the standout attribute. +

    graphic +This is a special attribute. +It causes some characters to be converted to line-drawing characters. +This is used for implementing the <pre graphic> tag in HTML. +
    fixed +
    proportional
    +On your screen these attributes have no effect, but when printing via the +:lpr command they may select between fixed-pitch and +variable-pitch fonts. +Some lptype settings don't support this, +and among those that do, some support it better than others. + +

    Printing with proportional fonts is a little quirky because Elvis' +text formatting was designed to support only fixed-pitch fonts. +The "epson", "pana", "ibm", and "hp" lptypes +support proportional printing, but are unable to make columns line up +correctly when you use it. +Because proportional text tends to be narrower than fixed-pitch text, +you may want to increase lpcolumns +from 80 to about 110, if your document consists mostly of proportional text. + +

    The "ps", "ps2", and "windows" lptypes +handle proportional text in a different way. +In order to prevent overlaps or large gaps when mixing fonts on +a line, these drivers adjust the width of +each chunk of proportional text to match the width it would have had +if it was fixed-pitch. +For large chunks you'll probably never notice, but if you have a single +word in a proportional font, and most of the letters in that word happen +to be narrow, then the stretching may be significant. +

    + +

    gu[i] text +
    +The :gui command provides a way to pass unusual commands to the +user interface. +Currently, the only user interface which uses this is the "x11" interface, +which uses it mostly to +configure the toolbar. + +
    se[t][!] [option=value | option | nooption | option? ]... +
    se[t][!] all | everything +
    se[t] gui.[option=value | option | nooption ]... +
    +The :set command allows you to examine or change the values of +options. + +

    With no arguments, :set lists the names and values of any +options that have been altered or are of frequent interest. +If given the argument "all" it will list the names and values of +most (but not really all) options. +If given the argument "everything", it really will list all options. +If given the name of an option followed by a "?" character, +:set will output the option's name and value. +If given the name of a group of options, followed by a "?" character, +:set will output the names and values of all options in that group. + +

    To turn a Boolean option on, just give the name of the option. +You can turn it off by adding the prefix "no" to the option name, and you +can negate it by adding the "neg" prefix to its name. + +

    To change the value of a non-Boolean option, give the name followed +immediately by an "=" and the new value. +If the new value contains whitespace, you should either enclose the +entire value in quotes, or precede each whitespace character with a backslash. + +

    If you give the name of a non-Boolean option, without either +"=value" or "?", then Elvis will display its value. + +

    +.-----------.----------------------------------------------------.
    +| EXAMPLE   | WHAT IT DOES                                       |
    +|-----------|----------------------------------------------------|
    +| :set      | display names & values of changed/important options|
    +| :set all  | display names & values of most POSIX-compliant opts|
    +| :set ts?  | display name & value of the tabstop option         |
    +| :set lp?  | display names & values of all printing options     |
    +| :set ts=4 | set value of the tabstop option to 4               |
    +| :set ai   | turn on the autoindent option                      |
    +| :set noai | turn off the autoindent option                     |
    +| :set negai| toggle the autoindent option                       |
    +^-----------^----------------------------------------------------^
    + +

    Adding a "!" to the end of the command name (:set!) +affects the behavior in two ways. +First, it causes any displayed options to be shown with the short name, and +the name of their group. +For example, ":set! tabstop" shows "buf.ts=8". + +

    The other difference is that :set! changes the option's default +value in addition to its current value, and then marks the option as having +not been changed. +This is used mostly in Elvis' initialization scripts. + +

    The special "gui." notation is used mostly by the +:mkexrc command to store +GUI-dependent options. +If the gui happens to match the name of the current user interface +(as stored in the gui option), then the rest +of the line is processed as usual. +For any other gui name, the command line is stored internally, +and incorporated into the file generated by :mkexrc. +This way, a single ".exrc" file (or "elvis.rc" or ".elvisrc") can store +settings for multiple GUIs. + +

    lo[cal] option=value... | option... +
    The :local command is similar to :set, and is +intended to be used in aliases and scripts. +In addition to setting options' values, it also pushes the old values onto a +stack; the old values are automatically restored at the end of the alias or +script. +Another difference is that where :set would output an option, +:local merely pushes its old value, without outputting or changing +the option's value. +This means that you can save a non-Boolean option simply by mentioning its name +on a :local command line; Boolean options can also be saved without +altering them, but you must put a question mark after the option's name. + +

    Here's a simple alias which uses :local. +It adds up the numbers in all lines from the current line forward to the next +line which contains the "total:", and stores the sum in the "total:" line. +

    +    :alias total {
    +        local nowrapscan ignorecase t=0
    +        .,/total:/-1 s/\d\+/let t=t+&/x
    +        eval /total:/ s/total:.*/total: (t)/
    +    }
    + +
    le[t][!] option [oper]= expr +
    le[t][!] option =~ excmds +
    +Both forms of the :let command compute a new value for an option. +The "= expr" (or "oper= expr") form +evaluates an expression to produce the new value. +The oper, if used, can be any of the +expression operators, and must be +followed immediately by the "=", without any intervening whitespace. +As in C, using an operator in this way causes the assigned option to be +treated as the left-hand operand for the operator, and the rest of the +expression as the right-hand operand. +
    +    :let a = 2+2
    +    :calc a
    +    4
    +    :let a <<= 3
    +    :calc a
    +    32
    + +

    Note that even Boolean options use the "=" notation here. +You can not say ":let nowrap" to turn off the +wrap option, for example, +but ":let wrap=false" works. + +

    The "=~ excmds" form is only available if Elvis is compiled +with FEATURE_EQUALTILDE defined (i.e., if :calc feature("equaltilde") returns True). +This form stores the option's old value into a buffer, +applies the excmds to that buffer, and then +copies the resulting buffer back into the option. +This is most useful when used with the :s command. +For example, the following capitalizes the first letter of each word in "a". +

    +    :let a =~ s/\<\w/\u&/g
    + +

    If Elvis is compiled with array support +(that is, if :calc feature("array") says True) +then you can also use a subscript after the option name, to change just +part of its value. +For more information about subscripts, see the discussion in the +Arithmetic Expressions chapter. + +

    When invoked as :let! (with a '!' suffix), +Elvis will set both the current and default values of the option, +and mark the option has having not been changed. +This is used in some of Elvis' initialization scripts. + +

    if expr +
    th[en] excmds +
    el[se] excmds +
    The :if command evaluates an expression, +and sets an internal variable according to whether the result was true or false. +Later, the :then and :else commands can be used to test +that variable, and conditionally execute other ex commands. + +

    Note that after an :if command, any other ex commands which +don't start with :then or :else will be executed +unconditionally. + +

    In aliases or script files, you can supply multiple command lines to a single +:then or :else by placing a '{' character on the +:then/:else line, +following that with any number of command lines, and then finally a '}' +character on a line by itself to mark the end. +The following example demonstrates this syntax, and also shows that you +can safely use :if inside a :then or +:else command: +

    +	:if i <= 0
    +	:then {
    +		if i == 0
    +		then echo zero
    +		else echo negative
    +	}
    +	:else echo positive
    + +
    try excmds +
    +The :try command executes its argument text as an ex command line. +Regardless of whether that command line succeeds or fails, the :try +command itself always succeeds. +That's significant because when a command fails, all pending aliases, macros, +and scripts are canceled; :try prevents that. +Error messages and warning messages are disabled while the command line runs. +Afterward, the then/else is set to indicate whether the command line succeeded. +This command is useful for implementing specialized error handing in an +alias or script. +The following example will search for "foo"; +if there is no "foo" then it will search for "bar": +
    +    :try /foo
    +    :else /bar
    + +
    wh[ile] expr +
    do[loop] excmds +
    The :while command stores an expression. It should be followed by +a :do command; the :do command repeatedly evaluates +the expression, and as long as the result is true it executes the commands +which follow the :do. The following example counts from +1 to 10: +
    +    :let i=1
    +    :while i <= 10
    +    :do {
    +        calc i
    +        let i=i+1
    +    }
    + +
    for[each] option [in] files... +
    for[each] option expression +
    The :foreach or :for command is similar to +:while in that it sets up information that +:do uses for looping. +The difference is that it sets up different information: A variable name, +and a list of values that the variable should take on. +

    +If the list expression begins with the word "in", then "in" will be +stripped off and the remainder will be interpreted as a space-delimited list +of file names. +You can use backslash-space to embed actual spaces in the names. +If the file names contain wildcard characters, then they'll be expanded to +the actual file names. +The body of the loop is executed separately for each matching file name. +

    +    for i in *.h
    +    do calc i
    +

    +Without the word "in", the remaining arguments are evaluated using the +normal expression syntax, and the result is then divided into +whitespace-delimited words. +The body of the loop is executed separately for each word. +

    +    foreach i (1..10)
    +    do calc i
    + +
    sw[itch] expr +
    cas[e] label [excmds] +
    def[ault] excmds +
    The :switch command evaluates an expression and stores the result. +The :case command compares that result to a given value, and executes +an ex command line if it matches. +If you omit the command line then it will carry forward to the next :case which does have an +ex command line; this allows multiple cases to share a single +ex command line. +The :default command executes its ex command line if no previous case +was matched. +Here's an example: +
    +    :switch os
    +    :case unix
    +    :case win32 echo Elvis has graphical and text-mode interfaces.
    +    :case os2 {
    +      echo Elvis has been ported natively as a text-mode program.
    +      echo You can also compile it to use the X11 interface from
    +      echo Unix, but you need the EMX libraries to run it.
    +    }
    +    :case msdos echo Elvis is slow and ugly under DOS.
    +    :default echo How are you even running this?
    +
    + +Notice that there is no punctuation after the case value, and that there is +no "break" or "endswitch" command. +This example says "Elvis has graphical and text mode interfaces" for both +the "unix" and "win32" cases; the "unix" case has no command, so it falls +through to the "win32" case. + +

    The :if/:then/:else, :while/:do, and +:switch/:case/:default command structures all permit nesting. +I.e., the commands in a :then command +can't affect the "if" variable to cause the :else command to +also be executed. + +

    mk[exrc][!] [file] +
    +The :mkexrc command creates a file containing ex commands which +recreate most of configuration features of Elvis, including: + + +

    If invoked with a filename, then +the mkexrcfile option will be set to +that name; +this setting will be stored in the script, along with your other settings. +If the named file already exists, then you must use :mkexrc! +(with a "!" suffix) to overwrite it. + +

    If you don't specify a filename, then it will write to the file whose name +is already stored in the mkexrcfile +option. +If that file already exists, then :mkexrc will overwrite the +file without requiring a "!" suffix. + +

    If mkexrcfile hasn't been set, +and you don't specify a name on the command line, then :mkexrc +will act as though you invoked it with a default name -- either ".elvisrc" +or "elvis.rc" in the home directory, +depending on the operating system. +Elvis' default initialization will :source that file, +so you don't need to explicitly :source it yourself each time +you start Elvis. +That's convenient. + +

    In summary: +The first time you run :mkexrc without arguments, it will store +the configuration in a standard place. +After that, when you invoke :mkexrc without arguments, it will +overwrite the previous configuration file. +You can also explicitly make it write the configuration out to some other +file if you want to. + +

    + +

    4.18 Auto commands

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | aue[vent][!]      | [event] ...                       |
    +|       | aug[roup][!]      | [group]                           |
    +|       | au[tocmd][!]      | [group] [events [file [excmd]]]   |
    +|       | doa[utocmd]       | [group] event [file]              |
    +^-------^-------------------^-----------------------------------^
    +
    + +These commands only exist if the FEATURE_AUTOCMD feature was +enabled when Elvis was compiled. +(The command `:calc +feature("autocmd")' should return True.) +

    +This is vim's way to run commands automatically in certain situations. +See the discussion in the Tips chapter. +It is sort of like Elvis' elvis.arf +file and related files, but much more versatile. +I'm trying to add it to Elvis to gain that versatility. +It is extremely complex, though, so you should expect to be baffled as you +read the following... + +

    + +
    aue[vent][!] [event] ... +
    This lets you create new event types (as additions to the built-in list). +The events won't be triggered automatically, but you can explicitly trigger +them via the :doautocmd command. +For example, the following commands create a new event named "BufAdd", +and arrange for it to behave mostly as a synonym for the built-in +BufCreate event. +
    +	:auevent BufAdd
    +	:au BufCreate * doau BufAdd
    + +

    For a more complex example, +the following commands create a new event named "FileChangedRO", +arrange for it to be triggered on the first modification that you make to +a readonly file, and then use it to give a warning when you start modifying +a readonly file: +

    +	:auevent FileChangedRO
    +	:au OptSet modified {
    +	  if readonly
    +	  then doau FileChangedRO
    +	}
    +	:au FileChangedRO * message ^GChanging a readonly file!
    +

    Note: +Vim doesn't have a :auevent command. +I added it to Elvis because vim is rapidly acquiring new events, and +it seemed easier to add a general solution like this than to try to +reimplement all of vim's new events in Elvis. + +

    aug[roup][!] [group] +
    Auto commands are divided into groups, for the sake of convenience. +The :augroup command creates groups, lists them, or selects one +for editing. +It has no effect on which events get run, though -- it is used purely for +editing. + +

    When invoked without arguments, it lists the current groups. + +

    When invoked with a group name as an argument, it selects that group as +being the one that later :autocmd commands will edit. +The default group is named "END", so most sequences of autocmd configuration +commands begin with ":aug group", contain any +number of :au commands, and then end with +":aug END". + +

    You can create your own groups. +If the group name that you specify didn't exist before this command, +then :aug will create it. + +

    The "!" suffix is used to indicate whether the named group should be +saved by the :mkexrc command. +Generally, you won't use "!" in your own :aug commands. +Elvis' standard scripts use ":aug!" +to set up a standard set of auto commands. +You wouldn't want them in your .exrc file, since they're already in the +standard scripts. + +

    au[tocmd][!] [group] [events [file [excmd]]] +
    The :au command lists, adds, or deletes auto command entries +from the current group. +The events are described in the Tips +chapter. + +

    The group, events, and file arguments are +used to select the event. +The group can be any group name that was created by an earlier +:augroup command; if omitted, it defaults to the name +used in the most recent ":augroup group" +command. +The events parameter is a comma-delimited list of events +as described in the Tips chapter, +or "*" for all events; if you omit it (and all parameters after it), +it defaults to "*", which is handy when listing files. +The file argument is a wildcard pattern such as "*.c"; if you +omit it (and all parameters after it), it defaults to "*" so the pattern will +work for any files. +The excmd is any ex command line, or {...} delimited group of lines; +it may access the +auevent, +aufilename, and +auforce options to determine what triggered +the event. + +

    Vim allows the special keyword "nested" to appear at the start of the +excmd to indicate that it can be run recursively. +Elvis allows the "nested" flag, but ignores it. +Elvis never allows auto commands to be recursive. + +

    Listing: +If you don't give either a ! after the command name +(not ":au!"), or a new excmd to run, then +:au will list the matching auto commands. +Some examples: +

    +	:au		list all commands in the current group
    +	:au END		list all commands in the default group
    +	:au BufRead	list all commands for BufRead events
    +	:au * *.html	list all commands for HTML files
    + +

    Deleting: +With a ! after the command name (":au!"), +then it deletes the matching auto commands, instead of listing them. +

    +	:au!		delete all commands in the current group
    +	:au! END	delete all commands in the default group
    +	:au! BufRead	delete all commands for BufRead events
    +	:au! * *.html	delete all commands for HTML files
    + +

    Adding: +To add an entry, use the same arguments with an ex command at then end. +The new command will be added to the end of the group. +(When multiple commands match a particular event, they're executed from +top to bottom in the list, so any existing commands will be executed +before the newly added command. +The following example adds a rule that makes all HTML files be read-only. +

    +	:au BufRead *.html set readonly
    + +

    Replacing: +You can delete old auto commands and then add a new one in a single step, +by invoking :au with both the ! suffix and an +new excmd to execute. +The following example replaces the previous one. +

    +	:au! BufRead *.html set noreadonly
    + +
    doa[utocmd] [group] event [file] +
    This simulates an event, causing the associated auto commands to be run. +This is handy for testing your configuration, or for rerunning the commands +after you've changed your configuration. + +

    By default, it runs commands in all groups, but if you specify a +group then it will only run auto commands in that group. +If there is no such group, it gives an error message. + +

    The event argument selects the particular event you want to +simulate. + +

    The file, if given, is the matched against the wildcard patterns. +If you omit it, then the current file name will be used (as indicated by the +filename option); this is usually what +you want to do. + +

    Note: Vim allows this command to be abbreviated to +":do", but most users abbreviate it as ":doau". +That's a good thing, because Elvis already has a :do +command, used for looping. + +

    Note: Vim also has a ":doautoall" command. +I don't expect to implement that one, since you can achieve the same effect +in Elvis by running ":all doau". + +

    + +

    4.19 Folding

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +| range | fo[ld][!]         | [name]                            |
    +| range | unf[old][!]       | [name]                            |
    +^-------^-------------------^-----------------------------------^
    +
    + +These commands are only available if your version of Elvis was compiled with +the folding feature is enabled. +(The command `:calc feature("fold")' should return True.) +"Folding" allows you to temporarily hide portions of your text, without +actually deleting it. + +

    Elvis allows you to create named regions called "FOLDs". +Each FOLD is either folded or unfolded, and +you can toggle a FOLD between those two states at will. +Folded regions, no matter how large, are displayed as a single line +which shows the FOLD's name. +Unfolded regions are displayed exactly like text that isn't in a FOLD. +The only reason that Elvis bothers to remember unfolded FOLDs is to +allow you to refold it easily. + +

    There are some limitations: +You can nest one FOLD inside another, +but you can't have overlapping FOLDs, or +different folds with exactly the same endpoints. +Folding only affects the appearance of the +normal and +syntax display modes. + +

    You can use the ":color fold +attributes" command to control the appearance of folded FOLDs. + +

    + +
    range fo[ld][!] [name] +
    range unf[old][!] [name] +
    The :fold and :unfold commands both have a very similar +syntax. +When invoked with a range of lines and a name, they create a FOLD which +is initially either folded or unfolded, respectively. +When invoked with either just a range of lines or just a name, they +alter the state of any existing FOLDs. +The following table shows this in greater detail: +
    +.--------------------.---------------------------------------------.
    +| COMMAND            | WHAT IT DOES                                |
    +|--------------------|---------------------------------------------|
    +| :range fold name   | Create a folded FOLD with the given name.   |
    +| :range fold        | Refold any existing FOLDs which contain     |
    +|                    |   lines in the given range.                 |
    +| :fold name         | Refold any existing FOLDs which have the    |
    +|                    |   given name.                               |
    +| :fold              | Refold the FOLD containing the current line.|
    +|--------------------|---------------------------------------------|
    +| :range unfold name | Create an unfolded FOLD with the given name.|
    +| :range unfold      | Unfold any existing FOLDs which contain     |
    +|                    |   lines in the given range.                 |
    +| :unfold name       | Unfold any existing FOLDs which have the    |
    +|                    |   given name.                               |
    +| :unfold            | Unfold the FOLD containing the current line.|
    +^--------------------^---------------------------------------------^
    + +

    +Both commands can accept a "!" modifier. +When FOLDs are nested inside each other, the :fold and +:unfold commands normally refold or unfold a single layer; +the "!" causes them to refold or unfold all layers. +In particular, you can unfold all FOLDs via the following command: +

    +	:%unfold!
    + +

    +For both commands, the name argument is evaluated using the +simpler expression syntax, with +$1 being replaced by the number of lines in the range. +The following shows how this could be used to fold the bodies of C functions +and give the folds the same name as their function. +(This depends on the show option +containing "tag" in it somewhere.) +

    +	:g/^{/,/^}/fold {(current("tag"))(":" $1 "lines")}
    +

    +There are also folded() and +unfolded() functions. +If the cursor is in a folded FOLD, then the folded() function +returns its name. +Otherwise it returns "" -- even if the cursor is in an unfolded FOLD. +The unfolded() function does the opposite. +This allows you to do things like the following, which toggles folding. +

    +	:alias negfold {
    +		if folded()
    +		then unfold
    +		else fold
    +	}
    + +

    Also, see the folding option +for a way to enable folding in one window but disable it in another. + +

    + +

    4.20 Regions

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +| range | reg[ion]          | [face [comment]]                  |
    +| range | unr[egion]        | [face]                            |
    +| range | chr[egion]        | face newface [newcomment]         |
    +^-------^-------------------^-----------------------------------^
    +
    + +

    These commands are only available if the region feature is enabled. +(The command `:calc feature("region")' should say True.) + +

    Regions give you a way to change the appearance of specific lines. +Each region has the following attributes: +

      +
    • a span of lines to which it applies, +
    • a face to use instead of the "normal" or "idle" face for those lines, and +
    • an optional comment. +
    +The face names are the same ones that are used with the +:color command. + +

    The show option +can also contain a "region" word, +which causes the current region's comment to be displayed at the bottom of +the window. +You can use current("region") or +current("rcomment") to access the current +region's face name or comment, respectively. + +

    All three of these commands act on the current line by default. +These are plain old '\n'-delimited lines, by the way -- the same definition +of "line" as is used by ex addresses, and the +normal and +syntax display modes. +When you're using any other display mode, the region highlighting may be +unreliable. + +

    + +
    range reg[ion] [face [comment]] +
    This creates a region, or lists existing regions. +

    +When invoked without a face name, it lists any regions which lie at least +partly within the given range of lines. +The following command lists all regions in the current buffer: +

    +	:%reg
    + +

    When invoked with a face name and optional comment, it creates a region. +If you don't specify a comment, then the face name will serve as the comment. +Regions aren't allowed to overlap, so if there were any other regions in +the given range before you invoke :region, they'll be clobbered. +The following comment creates a region that uses the "notes" face, covering +the first 10 lines of the file: +

    +	:1,10reg notes These are the first 10 lines
    + +
    range unr[egion] [face] +
    The :unregion command cancels the region highlighting for +the given range of lines. +If you supply a face name, then it will only cancel regions which were +using that face; otherwise it cancels all regions within the range. +The following example gets rid of all "notes" regions, but leaves other +regions unchanged: +
    +	:%unr notes
    + +
    range chr[egion] face newface [newcomment] +
    The :chregion command changes one type of region into +another type, based on the face. +If you supply a new comment, it will change that too. +

    +The following is a nifty trick which +automatically marks changed lines as "unsaved" while you're editing, +and then converts those to "saved" when you write the file. +

    +	:color unsaved on red
    +	:color saved on green
    +	:autocmd Edit * '[,']region unsaved
    +	:autocmd BufWritePost * %chregion unsaved saved
    + +
    +

    Also, running ":load inregion" +will add an ":inregion face excmds" alias, which you can +use to execute commands on lines in a given type of region. + +

    4.21 Spell checking

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | wo[rds][!]        | [+ | -] words...                  |
    +|       | wordf[ile][!]     | [filename...]                     |
    +|       | che[ck][!]        | [* | + | -] faces...              |
    +^-------^-------------------^-----------------------------------^
    +
    + +

    +These commands are only available if the spell-checking feature is enabled. +(The command `:calc feature("spell")' should say True.) +For more information about the spell checker, see the section in the +Tips chapter, and the +spelling options. + +

    + +
    wo[rds][!] + [+|-] + [words...] +
    Adds words to the natural-language dictionary. +Words that follow a "-" flag will be added as *BAD* words; otherwise the +words are added as good words. + +

    When invoked without any arguments, it lists any words that you've added +with previous invocations of the :words command. + +

    If you use a "!" suffix on the command name, then the added words will +not be marked as though they were added via :words. This is used mostly in +Elvis' initialization scripts. +Words added this way won't be listed by an argumentless :words +command, and won't be saved via the :mkexrc +command. +

    +    .------------.-------------------------------------------.
    +    | COMMAND    | WHAT IT DOES                              |
    +    |------------|-------------------------------------------|
    +    | :wo word   | Add word to personal dictionary as "good" |
    +    | :wo -word  | Add word to personal dictionary as "bad"  |
    +    | :wo! word  | Add word as "good", but not "personal"    |
    +    | :wo! -word | Add word as "bad" but not "personal"      |
    +    |            |   (This effectively removes the word from |
    +    |            |   the dictionary.)                        |
    +    ^------------^-------------------------------------------^
    +

    Words given in lowercase will be assumed to be case-insensitive. +Words containing any uppercase letters will be case-sensitive. +Also, there's a minor bug involving case-sensitive words and the +spellsuffix option; +see the "Options" chapter for details. + +

    wordf[ile][!] + [filename...] +
    Scan a text file for words, and add them to the natural-language +dictionary. +The text file shouldn't contain any markups such as HTML tags; it must be +a plain text file. +However, the words do not need to be sorted or formatted in any special way. +You can use the :wascii alias to generate +a plain text file from an HTML, man, or TeX source file. + +

    When invoked without any arguments, :wordfile loads the words +from the file indicated by the spelldict +option. +Doing this will take a noticeable amount of time, but it will allow the +spell() function to work better. + +

    When invoked with filenames as arguments, it scans those files for words +and adds them to your personal dictionary, so they'll be saved by the +:mkexrc command. +You can also add words temporarily by using :wordfile! +(with a ! suffix). + +

    che[ck][!] + [*|+|-] + [faces...] +
    This command allows you to reduce the amount of spell-checking that is +performed on specific text faces. +The face names are the same ones the :color command uses. +By default, most faces are spell-checked; Elvis' default configuration +files (mostly elvis.spe) reduce spell +checking for a few carefully-chosen faces. + +

    If invoked without any arguments, it will list any fonts that you've +changed with previous invocations of the :check command. + +

    If invoked with arguments, then the arguments should be a mixture of +flags and face names. +Each flag indicates which type of spell-checking is allowed on any text that +is drawn in the faces that follow it. +The flags are: + +

        * Check tags and natural-language words. +
        + Check tags, but not natural-language words. +
        - Don't check against either list. + +

    If you don't use any of those flags, then "+" is assumed. + +

    "tags" refers to the list of symbol names defined in a file named "tags", +in any directory named in the tags option. +For convenience, it also looks for "tags" in the directories listed in the +elvispath option; many people set up +a list of standard library functions there. + +

    "natural-language words" refers to the list of words maintained by the +:words command, or stored in an external file named via +the spelldict option. + +

    Some examples: +

    +.-----------------------.----------------------------------------.
    +| COMMAND               | WHAT IT DOES                           |
    +|-----------------------|----------------------------------------|
    +| :che +variable        | enable tag-only checking for variables |
    +| :che variable         | same as ":check +variable"             |
    +| :che *string          | enable full checking for strings       |
    +| :che -variable string | turn off all checking for those fonts  |
    +^-----------------------^----------------------------------------^
    +

    For example, the default configuration disables spell-checking on variable +names, since most tag-generator programs don't generate tags for all variables. +If you use a tag generator that does generate tags for all variables, then +you may want to enable checking against tags. You still wouldn't want to +check variable names against natural-language words, though. +The command to enable this checking for variables is: +

    +	:check variable
    + +

    Strings aren't normally spell-checked, because strings often contain +quirky things like "\n" and "%d", which causes many false alarms. +However, if you want to enable natural-language checking for strings, +you can do it with this command: +

    +	:check *string
    + +

    Appending a "!" suffix to the command name will prevent the changed font +from being listed by a later, argumentless :check command, or +from being saved by a :mkexrc command. +Elvis' initialization scripts invoke it this way. + +

    + +

    4.22 Miscellaneous

    +
    .-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | "                 | text                              |
    +|       | cd[!]             | [directory]                       |
    +|       | chd[ir][!]        | [directory]                       |
    +|       | ec[ho]            | text                              |
    +|       | me[ssage]         | text                              |
    +|       | wa[rning]         | text                              |
    +|       | erro[r]           | text                              |
    +| range | norm[al][!]       | [keystrokes]                      |
    +|       | sh[ell]           |                                   |
    +|       | st[op][!]         |                                   |
    +|       | sus[pend][!]      |                                   |
    +|       | ve[rsion]         |                                   |
    +| line  | go[to]            |                                   |
    +| line  | ma[rk]            | mark                              |
    +| line  | k                 | mark                              |
    +|       | {                 |                                   |
    +^-------^-------------------^-----------------------------------^
    +
    + +
    + +
    " text +
    +The :" command causes the remainder of the line to be ignored. +It is used for inserting comments into ex scripts. + +
    cd[!] [directory] +
    chd[ir][!] [directory] +
    The :cd and :chdir commands are identical. +They both change the current working directory for Elvis and all its windows. +If you don't specify a new directory name then Elvis will switch to your +home directory. + +
    ec[ho] text +
    +The :echo command displays its arguments as a message. +This may be useful in ex scripts. + +
    me[ssage] text +
    wa[rning] text +
    erro[r] text +
    The :message, :warning, and :error commands +all output their arguments as a message. +The command name indicates the importance of the message. +This is differs from :echo as follows: the messages are +translated via the elvis.msg file, +then evaluated using the simpler syntax, +and finally stuffed into the message queue. +The message queue collects all messages, and outputs them immediately before +waiting for the next keystroke. +Also, the :error command has the side-effect of terminating any +macros, aliases, or scripts. + +

    When used inside an autocmd, error and warning +messages are normally hidden. +To enable them in an autocmd, you should turn on the +eventerrors option. + +

    When used inside a try command, errors and warnings +are always hidden. + +

    range norm[al][!] [keystrokes] +
    +The :normal command does two totally separate things. +When invoked without any parameters, it switches to the normal display mode. + +

    +When :normal is invoked with parameter text, though, it leaves +the display mode unchanged and interprets the characters of the text as though +they were vi commands. +If no addresses were given, then those commands are executed once, without +moving the cursor initially; +if an address or range of addresses were given, then it moves the cursor to +the first character of each line and repeats the vi command keys there. + +

    +The "!" suffix has no effect in Elvis. +In vim, it would prevent maps from being applied to the +simulated keystrokes, but Elvis never applies maps to :normal +keystrokes. +

    sh[ell] +
    +The :shell command starts up an interactive shell +(command-line interpreter). +Elvis will be suspended while the shell executes. +(Exception: the "x11" GUI runs the shell in a separate xterm window. +Then Elvis and the shell can then run simultaneously.) + +
    st[op][!] +
    sus[pend][!] +
    The :stop and :suspend commands are identical to each other. +If the operating system and user interface support it, they will suspend +Elvis and resume the shell that started Elvis. +(This is like hitting ^Z on many UNIX systems.) +If the OS or GUI don't support it, then Elvis will generally treat these +commands as synonyms for the :shell command. + +
    ve[rsion] +
    +The :version command identifies this version number of Elvis, +and displays credits. + +
    line go[to] +
    The :goto moves the cursor to the addressed line. + +

    If you give an address without any ex command, then Elvis will assume +you want to use the :goto command. + +

    line ma[rk] mark +
    line k mark +
    The :mark and :k commands are identical to each other. +They set a named mark to equal the addressed line, or the current line if +no address was given. + +
    { commands } +
    The { commands } notation isn't really a command; +it is a feature of Elvis' syntax which allows you to pass several command lines +to a command which normally expects a single command line as its argument. +It is supported by the +:global, :vglobal, +:all, :then, :else, +:alias, and :autocmd commands. +Instead of placing the argument command at the end of one of those command +lines, you can place a single '{' character there. +That should be followed by one or more command lines, and terminated +by a '}' on a line by itself. + +
    + +

    4.23 Alphabetical list of ex commands

    + +
    +.-------.-------------------.-----------------------------------.
    +|ADDRESS| COMMAND           | ARGUMENTS                         |
    +|-------|-------------------|-----------------------------------|
    +|       | ab[breviate][!]   | [lhs rhs]                         |
    +|       | al[ias]           | [name [excmds]]                   |
    +|       | al[l][!]          | excmds                            |
    +| line  | a[ppend][!]       | [text]                            |
    +|       | ar[gs]            | [file...]                         |
    +|       | aug[roup][!]      | [group]                           |
    +|       | au[tocmd][!]      | [group] [events [file [excmd]]]   |
    +|       | bb[rowse]         |                                   |
    +|       | bre[ak][!]        | [flags] lhs                       |
    +|       | br[owse][!]       | restrictions                      |
    +|       | b[uffer][!]       | [buffer]                          |
    +|       | ca[lculate]       | expr                              |
    +|       | cas[e]            | value [excmds]                    |
    +|       | cc[!]             | [args]                            |
    +|       | cd[!]             | [directory]                       |
    +| range | c[hange][!]       | [count] [text]                    |
    +|       | chd[ir][!]        | [directory]                       |
    +|       | che[ck][!]        | [* | + | -] faces...              |
    +| range | chr[egion]        | face newface [newcomment]         |
    +|       | cl[ose][!]        |                                   |
    +|       | col[or]           | [face [attributes]]               |
    +| range | co[py]            | line                              |
    +|       | def[ault]         | excmds                            |
    +| range | d[elete]          | [cutbuf] [count]                  |
    +|       | dig[raph][!]      | [lhs [rhs]]                       |
    +|       | di[splay]         | [modename [language]]             |
    +|       | do[loop]          | excmds                            |
    +|       | ec[ho]            | text                              |
    +|       | e[dit][!]         | [+line] [file]                    |
    +|       | el[se]            | excmds                            |
    +|       | er[rlist][!]      | [file]                            |
    +|       | erro[r]           | text                              |
    +|       | ev[al]            | expr                              |
    +|       | ex[!]             | [+line] [file]                    |
    +|       | f[ile]            | [file]                            |
    +| range | fo[ld][!]         | [name]                            |
    +|       | for[each]         | option ["in"] expression          |
    +| range | g[lobal][!]       | /regexp/ excmds                   |
    +| line  | go[to]            |                                   |
    +|       | gu[i]             | text                              |
    +|       | h[elp]            | topic                             |
    +|       | if                | expr                              |
    +| line  | i[nsert][!]       | [text]                            |
    +| range | j[oin][!]         |                                   |
    +| line  | k                 | mark                              |
    +|       | la[st]            |                                   |
    +|       | le[t][!]          | option=expr                       |
    +| range | l[ist]            | [count]                           |
    +|       | lo[cal]           | [option=value | option ]          |
    +| range | lp[r][!]          | [ file | >>file | !shellcmd ]     |
    +|       | mak[e][!]         | [args]                            |
    +|       | map[!]            | [flags] [lhs [flags] rhs]         |
    +| line  | ma[rk]            | mark                              |
    +|       | me[ssage]         | text                              |
    +|       | mk[exrc][!]       | [file]                            |
    +| range | m[ove]            | line                              |
    +|       | new               |                                   |
    +|       | n[ext][!]         | [file...]                         |
    +|       | N[ext][!]         |                                   |
    +|       | noh[lsearch]      |                                   |
    +| range | norm[al][!]       | keystrokes                        |
    +| range | nu[mber]          | [count]                           |
    +|       | on[ly]            |                                   |
    +|       | o[pen][!]         | [+line] [file]                    |
    +|       | po[p][!]          |                                   |
    +|       | pres[erve]        |                                   |
    +|       | pre[vious][!]     |                                   |
    +| range | p[rint]           | [count]                           |
    +|       | pus[h][!]         | [+line] [file]                    |
    +| line  | pu[t]             | [cutbuf]                          |
    +|       | qa[ll][!]         |                                   |
    +|       | q[uit][!]         |                                   |
    +| line  | r[ead]            | file | !shellcmd                  |
    +|       | red[o]            | [count]                           |
    +| range | reg[ion]          | [face [comment]]                  |
    +|       | rew[ind][!]       |                                   |
    +|       | sN[ext]           |                                   |
    +|       | safel[y][!        | excmds                            |
    +|       | sa[ll]            |                                   |
    +|       | sbb[rowse]        |                                   |
    +|       | sb[rowse]         | restrictions                      |
    +|       | se[t][!]          | [option=value | option? | all]    |
    +|       | sh[ell]           |                                   |
    +|       | sl[ast]           |                                   |
    +|       | sne[w]            |                                   |
    +|       | sn[ext]           | [file...]                         |
    +|       | so[urce][!]       | file                              |
    +|       | sp[lit]           | [+line] [file | !shellcmd]        |
    +|       | sre[wind][!]      |                                   |
    +|       | stac[k]           |                                   |
    +|       | sta[g]            | [tag]                             |
    +|       | st[op][!]         |                                   |
    +| range | s[ubstitute]      | /regexp/newtext/[g][p][x][count]  |
    +|       | sus[pend][!]      |                                   |
    +|       | sw[itch]          | expr                              |
    +|       | ta[g][!]          | [tag]                             |
    +|       | th[en]            | excmds                            |
    +| range | t[o]              | line                              |
    +|       | try               | excmds                            |
    +|       | una[bbreviate][!] | lhs                               |
    +|       | unal[ias][!]      | name                              |
    +|       | unb[reak][!]      | [flags] lhs                       |
    +|       | u[ndo]            | [count]                           |
    +| range | unf[old][!]       | [name]                            |
    +|       | unm[ap][!]        | [flags] lhs                       |
    +| range | unr[egion]        | [face]                            |
    +|       | ve[rsion]         |                                   |
    +| range | v[global][!]      | /regexp/ excmds                   |
    +|       | vi[sual][!]       | [+line] [file]                    |
    +|       | wa[rning]         | text                              |
    +|       | wh[ile]           | expr                              |
    +|       | wi[ndow]          | [+ | - | number | buffer ]        |
    +|       | wn[ext][!]        |                                   |
    +|       | wordf[ile][!]     | [filename...]                     |
    +|       | wo[rds][!]        | [+ | -] words...                  |
    +|       | wq[uit][!]        | [file]                            |
    +| range | w[rite][!]        | [file | >>file | !shellcmd]       |
    +|       | x[it][!]          | [file]                            |
    +| range | y[ank]            | [cutbuf] [count]                  |
    +| line  | z                 | [spec]                            |
    +| range | !                 | shellcmd                          |
    +|       | "                 | text                              |
    +| range | #                 | [count]                           |
    +| range | &                 |                                   |
    +|       | (                 | buffer                            |
    +| range | <                 |                                   |
    +| range | =                 |                                   |
    +| range | >                 |                                   |
    +|       | @                 | cutbuf                            |
    +|       | {                 |                                   |
    +| range | ~                 |                                   |
    +^-------^-------------------^-----------------------------------^
    +
    +
    + + diff -urN elvis-2.2_0/doc/elvisexp.html elvis-2.2_1/doc/elvisexp.html --- elvis-2.2_0/doc/elvisexp.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisexp.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Arithmetic Expressions +Elvis-2.2_1 Arithmetic Expressions

    13. ARITHMETIC EXPRESSIONS

    @@ -541,6 +541,7 @@ "mapdb"map debugger, via maptrace and maplog options. "mkexrc":mkexrc command "normal"Vim's :normal command +"persist"Behavior related to the persistfile option "proto"add new protocols via aliases "ram"-f ram command-line option (mostly for MS-DOS) "region":region and related commands @@ -775,7 +776,7 @@ :calc a[2 3 4] is a test
    -

    Note that subscripts start 1, not 0 as in C. +

    Note that subscripts start with 1, not 0 as in C. Positive subscripts count from the left edge of the string, and negative subscripts count from the right edge. Zero returns the number of items in the string. @@ -898,7 +899,7 @@ listchars option uses this format. Consequently, you can use named subscripts to access its fields.

    -	:let listchars.esc=""
    + :let listchars.esc="<Esc>"

    13.3.4 Subscript idioms

    @@ -1018,10 +1019,10 @@ a,b,c,e :calc "a:1,b:2,c:3" | "b:two,d:four" a:1,b:two,c:3,d:four - :calc listchars? + :set listchars? listchars=tab:>- :let listchars |= "trail:_" - :calc listchars? + :set listchars? listchars=tab:>-,trail:_ Notice that set operators can be handy for manipulating the diff -urN elvis-2.2_0/doc/elvisgui.html elvis-2.2_1/doc/elvisgui.html --- elvis-2.2_0/doc/elvisgui.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisgui.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 User Interfaces +Elvis-2.2_1 User Interfaces

    8. USER INTERFACES

    @@ -206,6 +206,25 @@
    This leaves a small gap between the previous button and the following button. +
    :gui [label] keys +
    This creates a button named label. +Whenever you click the button, +elvis will act as though you typed the keys. +The keys can use symbolic names +for keys, just like the :map command. + +

    +If you define a button without specifying the keys, then +elvis will send the button label enclosed in square brackets. +You can then use the :map command +to map that to whatever you want. +This can be handy because Elvis allows you to make context-sensitive maps. + +

    +:gui [Bold]
    +:map select mode=html [Bold] c<b><C-P><\b><Esc>
    +:map select mode=man [Bold] c\fB<C-P>\fP<Esc>
    +
    :gui label : excommand
    This creates a button named label. Whenever you click the button, the excommand will be interpreted @@ -265,7 +284,7 @@ When you click on the toolbar button, the dialog appears immediately. You can then edit some values, and then hit the [Submit] button to store the edited values into options and -run the toolbar button's ex command (if any), or hit the [Cancel] button +run the toolbar button's keys and/or ex command (if any), or hit the [Cancel] button to do nothing.

    The simplest dialog is specified by giving just a pair of semicolons after @@ -387,6 +406,8 @@ Function keys and cursor keys have no standard translation, so Elvis converts them to a ^K character followed the Keysym binary value, expressed as four hex digits. +The shift and control versions of the keys use ^S and ^C as the prefix +character, respectively.

    You can use the "^Kxxxx" character sequences as the first argument to a :map command. @@ -411,36 +432,22 @@ if ":calc feature("image")" returns True) then you can use the -:gui command to change Elvis' icon. -

    -
    :gui icon -
    Display the name of the current icon, if any. -
    :gui icon filename.xpm -
    Load an image from an XPM file, and use the image as Elvis' icon. -If filename.xpm isn't found in the current directory then -Elvis will search for it in the elvispath. -
    - -

    Even without FEATURE_IMAGE, you may still be able to use the icons with -some window managers. -For example, with FVWM2 you could put the following in your ~/.fvwm2rc file... -

    -	Style "elvis" Icon /usr/include/X11/pixmaps/elvis.xpm
    +iconimage option to change Elvis' icon.

    The following color icons are available:

    -    .------------.------------------------------------------------.
    -    |    NAME    | DESCRIPTION                                    |
    -    |------------|------------------------------------------------|
    -    | elvis.xpm  | 48x32, 4 colors, same as the monochrome icon   |
    -    | kde.xpm    | 32x32, a resized version of elvis.xpm          |
    -    | mini.xpm   | 16x14, 6 colors, for fvwm95 taskbar            |
    -    | normal.xpm | 56x46, on a shaded button for NextStep-ish WMs |
    -    | small.xpm  | 21x18, on a shaded button for NextStep-ish WMs |
    -    | elvis1.xpm | 32x32, Spike                                   |
    -    | elvis2.xpm | 32x32, 2 1/2 Years (among others)              |
    -    | elvis3.xpm | 32x32, My Aim Is True                          |
    -    ^------------^------------------------------------------------^
    +    .----------.------------------------------------------------.
    +    | XPM NAME | DESCRIPTION                                    |
    +    |----------|------------------------------------------------|
    +    |  elvis   | 48x32, 4 colors, same as the monochrome icon   |
    +    |  kde     | 32x32, a resized version of elvis.xpm          |
    +    |  mini    | 16x14, 6 colors, for fvwm95 taskbar            |
    +    |  normal  | 56x46, on a shaded button for NextStep-ish WMs |
    +    |  small   | 21x18, on a shaded button for NextStep-ish WMs |
    +    |  elvis1  | 32x32, Spike                                   |
    +    |  elvis2  | 32x32, 2 1/2 Years (among others)              |
    +    |  elvis3  | 32x32, My Aim Is True                          |
    +    ^----------^------------------------------------------------^
     
    The last three use a lot of colors, and should be avoided if you're using a Pseudocolor display (8 bits per pixel or less). @@ -452,6 +459,12 @@ But if you don't normally use icons on shaded buttons, then you should probably use only the first three icons. +

    Even without FEATURE_IMAGE, you may still be able to use the icons with +some window managers. +For example, with FVWM2 you could put the following in your ~/.fvwm2rc file... +

    +	Style "elvis" Icon /usr/include/X11/pixmaps/elvis2.xpm
    +

    8.1.7 X11 Background Images

    Elvis supports the use of images in some backgrounds. Specifically, you can use image backgrounds for the "normal" and "idle" @@ -531,7 +544,7 @@ In addition to all the ASCII keys, WinElvis allows you to :map any cursor keys or function keys. In fact, the cursor keys all have rather convenient -maps built-in; you can see them by running ":map" with no arguments. +maps built-in; you can see them by running
    ":map all".

    All of the cursor keys and function keys send multi-character sequences to WinElvis. WinElvis then uses its standard mapping facilities to convert @@ -768,6 +781,16 @@ things get strange because termcap field names must be two characters long. Also, there was no way to describe shift-function keys, control-function keys, or alt-function keys, so I invented by own fields for them. +(Note that most Unix variants, including Linux, use <Alt-Fn> +to switch console screens, so applications such as Elvis can't use +<Alt-Fn> themselves.) +When using terminfo, there are standard termcap names for the terminfo +function key names, and elvis uses them, but terminfo simply supports 46 +different <Fn> keys, not <Shift-Fn> or +<Ctrl-Fn> keys; to work around this in the PC world, +terminfo databases are set up with <Shift-Fn> configured +as <F13> through <F24>, and <Ctrl-Fn> keys +as <F25> through <F36>.

    The following table lists all of the key field names, and the keys they refer to. @@ -802,36 +825,42 @@ | #8 | :k8=: | F8 key | | #9 | :k9=: | F9 key | | #10 | :k0=:ka=:k;=: | F10 key | -| #1s | :s1=: | Shift-F1 key (ELVIS ONLY)| -| #2s | :s2=: | Shift-F2 key (ELVIS ONLY)| -| #3s | :s3=: | Shift-F3 key (ELVIS ONLY)| -| #4s | :s4=: | Shift-F4 key (ELVIS ONLY)| -| #5s | :s5=: | Shift-F5 key (ELVIS ONLY)| -| #6s | :s6=: | Shift-F6 key (ELVIS ONLY)| -| #7s | :s7=: | Shift-F7 key (ELVIS ONLY)| -| #8s | :s8=: | Shift-F8 key (ELVIS ONLY)| -| #9s | :s9=: | Shift-F9 key (ELVIS ONLY)| -| #10s | :s0=: | Shift-F10 key (ELVIS ONLY)| -| #1c | :c1=: | Control-F1 key (ELVIS ONLY)| -| #2c | :c2=: | Control-F2 key (ELVIS ONLY)| -| #3c | :c3=: | Control-F3 key (ELVIS ONLY)| -| #4c | :c4=: | Control-F4 key (ELVIS ONLY)| -| #5c | :c5=: | Control-F5 key (ELVIS ONLY)| -| #6c | :c6=: | Control-F6 key (ELVIS ONLY)| -| #7c | :c7=: | Control-F7 key (ELVIS ONLY)| -| #8c | :c8=: | Control-F8 key (ELVIS ONLY)| -| #9c | :c9=: | Control-F9 key (ELVIS ONLY)| -| #10c | :c0=: | Control-F10 key (ELVIS ONLY)| -| #1a | :a1=: | Alt-F1 key (ELVIS ONLY)| -| #2a | :a2=: | Alt-F2 key (ELVIS ONLY)| -| #3a | :a3=: | Alt-F3 key (ELVIS ONLY)| -| #4a | :a4=: | Alt-F4 key (ELVIS ONLY)| -| #5a | :a5=: | Alt-F5 key (ELVIS ONLY)| -| #6a | :a6=: | Alt-F6 key (ELVIS ONLY)| -| #7a | :a7=: | Alt-F7 key (ELVIS ONLY)| -| #8a | :a8=: | Alt-F8 key (ELVIS ONLY)| -| #9a | :a9=: | Alt-F9 key (ELVIS ONLY)| -| #10a | :a0=: | Alt-F10 key (ELVIS ONLY)| +| #11 | :F1=: | F11 key | +| #12 | :F2=: | F12 key | +| #1s | :s1=:F3=: | Shift-F1 key | +| #2s | :s2=:F4=: | Shift-F2 key | +| #3s | :s3=:F5=: | Shift-F3 key | +| #4s | :s4=:F6=: | Shift-F4 key | +| #5s | :s5=:F7=: | Shift-F5 key | +| #6s | :s6=:F8=: | Shift-F6 key | +| #7s | :s7=:F9=: | Shift-F7 key | +| #8s | :s8=:FA=: | Shift-F8 key | +| #9s | :s9=:FB=: | Shift-F9 key | +| #10s | :s0=:FC=: | Shift-F10 key | +| #11s | :FD=: | Shift-F11 key | +| #12s | :FE=: | Shift-F12 key | +| #1c | :c1=:FF=: | Control-F1 key | +| #2c | :c2=:FG=: | Control-F2 key | +| #3c | :c3=:FH=: | Control-F3 key | +| #4c | :c4=:FI=: | Control-F4 key | +| #5c | :c5=:FJ=: | Control-F5 key | +| #6c | :c6=:FK=: | Control-F6 key | +| #7c | :c7=:FL=: | Control-F7 key | +| #8c | :c8=:FM=: | Control-F8 key | +| #9c | :c9=:FN=: | Control-F9 key | +| #10c | :c0=:FO=: | Control-F10 key | +| #11c | :FP=: | Control-F11 key | +| #12c | :FQ=: | Control-F12 key | +| #1a | :a1=: | Alt-F1 key (DOS/WINDOWS ONLY)| +| #2a | :a2=: | Alt-F2 key (DOS/WINDOWS ONLY)| +| #3a | :a3=: | Alt-F3 key (DOS/WINDOWS ONLY)| +| #4a | :a4=: | Alt-F4 key (DOS/WINDOWS ONLY)| +| #5a | :a5=: | Alt-F5 key (DOS/WINDOWS ONLY)| +| #6a | :a6=: | Alt-F6 key (DOS/WINDOWS ONLY)| +| #7a | :a7=: | Alt-F7 key (DOS/WINDOWS ONLY)| +| #8a | :a8=: | Alt-F8 key (DOS/WINDOWS ONLY)| +| #9a | :a9=: | Alt-F9 key (DOS/WINDOWS ONLY)| +| #10a | :a0=: | Alt-F10 key (DOS/WINDOWS ONLY)| ^-----------^---------------^-----------------------------------^ diff -urN elvis-2.2_0/doc/elvisinp.html elvis-2.2_1/doc/elvisinp.html --- elvis-2.2_0/doc/elvisinp.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisinp.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Input Mode +Elvis-2.2_1 Input Mode

    3. INPUT MODE

    diff -urN elvis-2.2_0/doc/elvismsg.html elvis-2.2_1/doc/elvismsg.html --- elvis-2.2_0/doc/elvismsg.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvismsg.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Messages +Elvis-2.2_1 Messages

    12. MESSAGES

    diff -urN elvis-2.2_0/doc/elvisnet.html elvis-2.2_1/doc/elvisnet.html --- elvis-2.2_0/doc/elvisnet.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisnet.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 and the Internet +Elvis-2.2_1 and the Internet

    15. THE INTERNET

    diff -urN elvis-2.2_0/doc/elvisopt.html elvis-2.2_1/doc/elvisopt.html --- elvis-2.2_0/doc/elvisopt.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisopt.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Options +Elvis-2.2_1 Options

    6. OPTIONS

    @@ -38,7 +38,7 @@ last number should be repeated.

    Each option serves as an attribute of something. -The group of an option designates what it is an attribute of. +The group of an option designates what it is an attribute of. For example, the "filename" option is an attribute of buffers; when you switch to a different buffer, it will have a different value for the "filename" option. @@ -48,17 +48,19 @@ .---------.-------------------------------------------------------. | GROUP | DESCRIPTION | |---------|-------------------------------------------------------| -| buf | Attributes of buffers | -| win | Attributes of windows | -| syntax | Attributes of the "syntax" display mode | -| x11 | Attributes of the "x11" user interface | -| tcap | Attributes of the "termcap" user interface | -| windows | Attributes of the "windows" user interface | -| win32 | User interface attributes for the Win32 port | | global | Global options | +| user | User variables a - z (Global, useful in ex scripts) | | lp | Printing options | +| buf | Attributes of each buffer | +| win | Attributes of each window | +| syntax | Attributes of the "syntax" display mode | +| x11 | Attributes of the "x11" user interface | +| windows | Attributes of the "windows" user interface | +| termcap | Attributes of the "termcap" user interface | +| vio | Attributes of the "vio" user interface (OS/2 console) | +| win32 | Attributes of the text-mode Win32 port | +| au | Used only when executing an autocmd | | bang | Used only when writing a file | -| user | User variables a - z (Global, useful in ex scripts) | ^---------^-------------------------------------------------------^ You don't need to know an option's group to set that option. @@ -161,6 +163,10 @@ When you restart the session, the buffer will still exist with all its changed text intact. By default, the retain option is false (":set noretain") because that mimics traditional vi behavior. + +

    It also prevents Elvis from destoying the buffer during an edit session. +Normally, Elvis will destroy buffers if they aren't shown in any window, and +their contents haven't been modified since they were loaded or written.

    modified, mod (Boolean, buf)
    The modified option indicates whether the @@ -753,7 +759,7 @@ The default value includes all of these keywords. Users of Microsoft Windows may want to remove "space" from the value, so that spaces can be used in filenames more easily. -You can still give multiple file names by separating then with <Tab>. +You can still give multiple file names by separating them with <Tab>.

    6.7 Window statistics

    @@ -807,12 +813,13 @@ | display, mode | String | win | name of current display mode| | number, nu | Boolean | win | display line numbers | | ruler, ru | Boolean | win | display cursor's line/column| -| guidewidth, gw | Tab-list| buf | draw vertial lines on screen| +| guidewidth, gw | Tab-list| buf | draw vertical guide lines | | hlobject, hlo | String | buf | type of object to highlight | | hllayers, hll | Number | win | how many layers to highlight| | background, bg | One-of | global | assumed background color | | folding, fold | Boolean | win | enable folding | | show | String | global | what to show on bottom row | +| state | String | global | may be shown via show option| | showmatch, sm | Boolean | win | highlight matching parens | | showmode, smd | Boolean | win | display the command state | | nonascii, asc | One-Of | global | how to display non-ascii | @@ -1049,17 +1056,28 @@ that you want Elvis to highlight around the cursor. Its value will usually be the two-character name of a single type of text object, but you can also -set it to a whole list of objects to use for different layers of highlighting. +set it to a whole list of objects +(optionally delimited via whitespace or commas) +to use for different layers of highlighting. To highlight whole lines, instead of the exact extent of the text object, you can put a "V" before the text object's name. -(For example, hlobject="Va{" will highlight whole lines -via brace-delimited blocks.) If you set hllayers to more layers than you've defined in this option, then the last object type will be repeated with increasing counts. The default value is "" which inhibits highlighting. For highlighting to occur, you must set both hlobject to a valid object name, and hllayers to a non-zero value. +Examples: +
    +.-------------------.---------------------------------------.
    +| Object list       | What it highlights                    |
    +|-------------------|---------------------------------------|
    +| hll=1 hlo="al"    | the line containing the cursor        |
    +| hll=1 hlo="Va{"   | whole lines via brace-delimited blocks|
    +| hll=2 hlo="ix,ax" | XML tags and their contents           |
    +^-------------------^---------------------------------------^
    +(Larger values of hll (hllayers) will do interesting +and useful things.)

    NOTE: I recommend that you get in the habit of enclosing the value in quotes. @@ -1078,6 +1096,11 @@ The outermost layer will use the highlighting defined by the font "hlobject1", the next layer will use "hlobject2", and so on; you can use the :color command to set these up. +Also, for the x11 and +windows user interfaces you can run +":load shade" +to set up all of the "hlobjectn" faces with +shades of gray background.

    background, bg (One of, global)
    The background option does not change the background color! @@ -1139,6 +1162,7 @@ | link | destination of an HTML link at the cursor position | | spell | suggested corrections for a misspelled word | | region | comment of current region (as used by :region) | +| state | value of the state option | ^---------^-----------------------------------------------------^

    Many of the above keywords won't always generate output. @@ -1178,6 +1202,11 @@ This causes Elvis to display spelling suggestions if the cursor is on a misspelled word, or the tag name and region comment otherwise. +

    state (String, global) +
    The value of the state option may be shown at the bottom of the +screen if the show option contains the keyword "state". +This is the only thing that state is used for. +Its default value is "".
    showmatch, sm (Boolean, win)
    The showmatch option helps you locate matching parentheses. @@ -1303,10 +1332,13 @@ This is desirable because Elvis will only suggest words that have been loaded, so if you haven't loaded the whole dictionary then it won't be able to make very many suggestions. -However, loading the whole dictionary takes some time (usually about 1 second) -and memory (about 1 megabyte) so you may prefer to load the dictionary -explicitly ahead of time via the :wordfile -command. +The spellautoload option is on by default. + +

    Loading the whole dictionary takes some time (usually about 1 second) +and memory (about 1 megabyte) so you may prefer to +turn off spellautoload to avoid this. +You could then explicitly load it via the +:wordfile command, if you want.

    spellsuffix, sps (String, global)
    This stores a list of possible suffixes for natural-language words. @@ -1445,12 +1477,12 @@
    .---------------------.---------.--------.-----------------------------.
     | OPTION NAMES        | TYPE    | GROUP  | DESCRIPTION                 |
     |---------------------|---------|--------|-----------------------------|
    -| term, ttytype       | String  | tcap   | terminal's termcap entry    |
    -| ttyrows, ttylines   | Number  | tcap   | height of screen            |
    -| ttycolumns, ttycols | Number  | tcap   | width of screen             |
    -| ttyunderline, ttyu  | Boolean | tcap   | okay to mix color & underln |
    -| ttyitalic, ttyi     | Boolean | tcap   | okay to use "dim" for italic|
    -| ttywrap, ttyw       | Boolean | tcap   | trust termcap's line wrap   |
    +| term, ttytype       | String  | termcap| terminal's termcap entry    |
    +| ttyrows, ttylines   | Number  | termcap| height of screen            |
    +| ttycolumns, ttycols | Number  | termcap| width of screen             |
    +| ttyunderline, ttyu  | Boolean | termcap| okay to mix color & underln |
    +| ttyitalic, ttyi     | Boolean | termcap| okay to use "dim" for italic|
    +| ttywrap, ttyw       | Boolean | termcap| trust termcap's line wrap   |
     | codepage, cp        | Number  | win32  | console character set       |
     |---------------------|---------|--------|-----------------------------|
     | scrollbar, sb       | Boolean | (gui)  | enable the scrollbar        |
    @@ -1492,6 +1524,7 @@
     | outlinemono, om     | Number  | x11    | char outlining for X11-mono |
     | antialias, aa       | Boolean | x11    | use antialiased fonts       |
     | aasqueeze, aas      | Boolean | x11    | reduce the gap between lines|
    +| secret              | Number  | x11    | identifies trusted clients  |
     ^---------------------^---------^--------^-----------------------------^
     
    @@ -1499,9 +1532,9 @@
    -
    term, ttytype (String, tcap) -
    ttyrows, ttylines (Number, tcap) -
    ttycolumns, ttycols (Number, tcap) +
    term, ttytype (String, termcap) +
    ttyrows, ttylines (Number, termcap) +
    ttycolumns, ttycols (Number, termcap)
    The term, ttyrows, and ttycolumns options are only present if you're using the termcap user interface. They indicate the name of the termcap entry being used and the size of the screen. @@ -1514,7 +1547,7 @@ configuration settings), or, as a last resort, from the termcap/terminfo entry. -
    ttyunderline, ttyu (Boolean, tcap) +
    ttyunderline, ttyu (Boolean, termcap)
    The ttyunderline option is only present if you're using the termcap interface. It indicates whether it is safe to try underlining text when colors @@ -1546,7 +1579,7 @@ :set nottyunderline :color normal on transparent -
    ttyitalic, ttyi (Boolean, tcap) +
    ttyitalic, ttyi (Boolean, termcap)
    Elvis normally displays italic text using the "dim" attribute, but standard PC VGA hardware can't do that very well. The Linux console driver implements it by using gray, which is unfortunate @@ -1564,7 +1597,7 @@ Underlining is influenced by the ttyunderline option. -
    ttywrap, ttyw (Boolean, tcap) +
    ttywrap, ttyw (Boolean, termcap)
    Elvis normally tries to be smart about line-wrap, more so than most programs. But this only works right if the terminal's termcap/terminfo description is @@ -1679,7 +1712,7 @@ If you set a titleformat in your elvis.rc file, then its value will affect all windows that are created later. This is the most useful place to change titleformat. -See the :mkexrc command. +See the :mkexrc command.
    @@ -1928,6 +1961,26 @@ should be. 3 is the thickest supported outline, and 0 is no outline at all. The default is 2. +
    secret (Number, x11) +
    Normally, when any clients sends ex commands to a server elvis +(via "elvis -client -c excmd", for example), +those commands are executed with +security=safer. +The secret option provides a way to recognize trusted clients +which are not forced into this high-security mode. +If secret is non-zero, and +a command is received which begins with the secret value +enclosed in double-quote characters, then elvis will run the command without +forcing security=safer. +

    +Initally secret is 0, which will disable this feature so that all +clients' requests are run in security=safer mode. +If you set secret to a random value, +and then pass that value to a program started by elvis, +then elvis will be able to recognize that program's requests as coming from +a client that it trusts. +This mechanism is used by the gdb interface. +

    6.14 Regular expression options

    @@ -2596,7 +2649,8 @@
    ccprg, cp (String, buf)
    makeprg, mp (String, buf) -
    The ccprg and makeprg are the programs used by the +
    The ccprg and makeprg options store the shell commands +that are used by the :cc and :make commands. Before the program strings are executed, they are subjected to the same @@ -2713,7 +2767,7 @@ For MS-DOS: -The default home directory is the one containing ELVIS-2.2_0 +The default home directory is the one containing ELVIS-2.2_1 @@ -2775,17 +2829,33 @@
    .---------------------.---------.--------.-----------------------------.
     | OPTION NAMES        | TYPE    | GROUP  | DESCRIPTION                 |
     |---------------------|---------|--------|-----------------------------|
    +| initializing, ing   | Boolean | global | has first file been loaded? |
     | exrc, ex            | Boolean | global | interpret ./.exrc file      |
     | modeline, ml        | Boolean | global | interpret modelines         |
     | modelines, mls      | Number  | global | positions of modelines      |
     | security, sec       | One-of  | global | normal, safer,or restricted |
     | initialstate, init  | One-Of  | global | command mode of new windows |
     | mkexrcfile, rc      | String  | global | name of user's init script  |
    +| persistfile, perf   | String  | global | file that remembers cursors |
    +| persist, pers       | Packed  | global | what to store in persistfile|
     ^---------------------^---------^--------^-----------------------------^
     
    +
    initializing, ing (Boolean, global) +
    The initializing option indicates whether Elvis is currently +in the early stages of its initialization, before an edit buffer has been +created for first file. +You can't modify this option yourself; +Elvis changes it when appropriate. +It will be set while running the elvis.ini +script (which runs your ~/.elvisrc or ~/elvis.rc file). +It is cleared while running the elvis.brf +script, and for BufReadPre and +BufReadPost events. +This is significant because commands that access the edit buffer are disabled +while intializing is true.
    exrc, ex (Boolean, global)
    The exrc option has no built-in meaning to Elvis, however the default elvis.ini file uses this option to determine whether @@ -2819,6 +2889,26 @@ "normal" has no security rules, "safer" tries to protect the user against writing by malicious scripts, and "restricted" tries to protect the system against reading by a malicious user. +

    +There are four things that must be avoided to maintain security: +

      +
    1. You shouldn't be able to run external programs. +
    2. You shouldn't be able to write over any arbitrary file. +
    3. You shouldn't be able to load any arbitrary file, modify it, and + write it. +
    4. You shouldn't be able to create maps or aliases which trick the + user into doing any of the above. +
    +

    +Items 1, 2, and 4 are pretty easy. +Item 3 requires some compromise and that's +why there are two different secure modes. +"safer" allows you to load any file, and modify it, but not write it; +this makes "safer" useless for interactive work. +"restricted" only allows you to load files named on the command line, but +you can modify them and write them (back over the old version of the file, +not out to any random file). +

    Specifically... @@ -2830,56 +2920,94 @@
    + - + +
    safer -This is an intermediate level of protection. -It is intended to make modelines and a .exrc file in the current directory +This is intended to make modelines and a .exrc file in the current directory safe to use, but I'm not making any promises. -When security=safer, certain commands are disabled, wildcard -expansion in filenames is disabled, and certain options are locked (including -the security option itself). +When security=safer, certain commands are disabled, +wildcard expansion in filenames is disabled, and +certain options are locked (including the security option itself). Typically you will use the ex command -:safely source to execute an untrusted script, +":safely source filename" +to execute an untrusted script, rather than futz with the value of the safer option directly.

    The disabled ex commands are :!, :abbreviate, :alias, -:args, -:augroup, :autocmd, :cc, :cd, :chdir, -:last, :lpr, :make, :map, :mkexrc, -:next, -:Next, -:previous, -:rewind, :shell, -:slast, -:snew, -:snext, -:sNext, -:srewind, and -:write. +:write, +:wquit, and +:xit. + +

    The locked options are +ccprg, +elvispath, +equalprg, +home, +keywordprg, +lpout, +makeprg, +modeline, +persistfile, +secret, +security, +shell, +spelldict, +stopshell, and +tagprg. -

    Some commands are allowed only when invoked without a filename argument. -These are +

    In expressions, the shell() function will fail. +
    +

    restricted +This is intended to make Elvis safe for use as a restricted editor. +Although "restricted" is generally stricter than "safer", it does allow +you to save your files while "safer" does not. +

    +The disabled ex commands are: +:!, +:abbreviate, +:alias, +:autocmd, +:cc, +:cd, +:chdir, +:errlist, +:lpr, +:make, +:map, +:mkexrc, +:read, +:shell, +:source, +:stop, and +:suspend. +

    +Also, the following ex commands can only be invoked without any arguments: +:args, :edit, :ex, :file, +:next, :open, :push, +:snext, :split, :visual, +:wordfile, +:write, :wquit, and :xit. - -

    The locked options are +

    +"restricted" locks the same options as "safer": ccprg, elvispath, equalprg, @@ -2888,29 +3016,13 @@ lpout, makeprg, modeline, +persistfile, +secret, security, shell, -spelldict, and +spelldict, +stopshell, and tagprg. - -

    In expressions, the shell() function will fail. -
    -

    restricted -This is the most secure setting. -It is intended to make Elvis safe for use as a restricted editor, -e.g. to be invoked on a specific file via the sudo(8) program. -

    -In addition to all of the rules implied by "safer" level, -"restricted" disables the -:stop, -:source, -:suspend commands. -Also, the -:errlist, -:read, and -:wordfile -commands won't allow filename arguments.

    The "restricted" level also inhibits filename completion via the <Tab> key. @@ -2918,8 +3030,12 @@ time(filename) function will fail if invoked with a filename parameter, and the exists(), -dirperm(), and -fileeol() functions always fail. +dirperm(), +fileeol(), and +shell() functions always fail. +

    initialstate, init (One-Of, global)
    The initialstate option determines @@ -2934,6 +3050,130 @@ It has no default value, but scripts generated by :mkexrc always set this option to the name of that script file. +
    persistfile, perf (String, global) +
    persist, pers (Packed, global) +
    Elvis can store some information about buffers between invocations. +This resembles Vim's 'viminfo' option. +For example, it can save your cursor location in each buffer so that the +next time you edit the same file, your cursor can start in the same place. +This only works if Elvis was compiled with FEATURE_PERSIST +(i.e., if ":calc feature("persist")" returns True.) + +

    The persistfile option tells Elvis where to save these things, +and the persist option controls what gets saved and restored. + +

    The default value of persistfile is an empty string, +which disables persistent information. +This behavior is more compatible with vi. +You must set it to some other value to enable the "persist" feature. +You can set it to either a relative file such as "elvisinfo" to give +each directory its own list of current positions, or an absolute file +such as ~/elvisinfo to use a single file for all of your persistent +information. + +

    The persist option's value is a comma-delimited list of +keywords identifying the things that should be saved and restored. +The list of keywords includes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SYMBOLMEANING
    cursorRestore the cursor location.
    changeStart with the cursor at the location of the last change, except that if cursor is also given then set the '' mark to the change position.
    hours:hoursIf the last change was at least hours hours ago then don't move cursor; set the '' mark instead.
    marksSave & restore the named marks, 'a - 'z.
    regionsSave & restore any highlighting regions.
    foldsSave & restore any folds (both folded & unfolded)
    external:adjustHow to deal with changes made by other programs. + external:top tells Elvis to expect changes at the + top of the file, and external:skip tells Elvis to + avoid loading the persistent information if there's a change. + Else expect changes at the bottom of the file.
    ex:linesSave the last lines lines of ex history
    search:linesSave the last lines lines of search history
    argsSave the current args list as the default
    max:bytesImpose a size limit on the persistfile
    + +

    Note that setting hours:0 never allows the cursor to move, +but you can still use cursor or change to set +the '' mark. +To completely disable timeouts, +simply omit the hours:hours item from the value +of persist. + +

    The external:adjust field is intended to help +Elvis deal with changes made to the file by other programs. +For example, the RCS ci program could alter RCS keywords +such as $Id$ in your file. +If such changes usually occur near the bottoms of your files, then the change +won't affect any stored cursors, marks, folds, or regions so you won't need +an external:adjust field. +If the changes usually occur near the tops of your files, then you should +use external:top which tells Elvis to adjust the character +offsets and line numbers to be relative to the end of the file. +If the changes are likely to be scattered throughout the file, then you can +use external:skip to avoid reloading the persistent information +when the file changes. + +

    The ex:lines, +search:lines, and args +symbols are global; i.e., they aren't associated with any specific buffer. + +

    The max:bytes field can be used to impose an +overall size limit on the persist file. +The bytes is a number, optionally followed by "K" or "M" to scale +it to be kilobytes or megabytes. +The limit causes less recently accessed files to be removed from the +persist file. +If omitted, then the size is unlimited. + +

    The format of the persist option is compatible with +field notation and +set notation, +so you can do things such as... +

    +	:let persist.max="32K"
    +	:let persist|="args"
    +	:set persist^="change"
    + +

    The default value of persistfile is any empty string which +disabled persistent information. +The default value of persist is +cursor,change,hours:8,marks,regions,folds,ex:50,search:20,args.

    6.22 Keyboard map options

    @@ -3070,7 +3310,7 @@

    You can also selectively turn off error messages by running the command via :try, like this...

    -	:au BufNew *.html try r skeleton.html
    + :au BufNewFile *.html try r skeleton.html
    aufilename, afile (String, au)
    While an auto command is running, the aufilename option is set to @@ -3574,7 +3814,7 @@ | g | String | user | user variable | | gdefault, gd | Boolean | global | default change all instances| | gui | String | global | name of user interface | -| guidewidth, gw | Tab-list| buf | draw vertial lines on screen| +| guidewidth, gw | Tab-list| buf | draw vertical guide lines | | h | String | user | user variable | | hardtabs, ht | Number | global | width of terminal's tabs | | help, Help | String | x11 | locale's Help label | @@ -3589,6 +3829,7 @@ | ignorecase, ic | Boolean | global | uppercase matches lowercase | | includepath, inc | String | syntax | where to find #include files| | incsearch, is | Boolean | global | / and ? search incrementally| +| initializing, ing | Boolean | global | has first file been loaded? | | initialstate, init | One-Of | global | command mode of new windows | | initialsyntax, isyn | Boolean | buf | start in "syntax" mode? | | inputtab, it | One-Of | buf | input mode's (Tab) key | @@ -3648,6 +3889,8 @@ | p | String | user | user variable | | paragraphs, para | String | buf | nroff paragraph commands | | partiallastline, pll| Boolean | buf | file didn't end with newline| +| persist, pers | Packed | global | what to store in persistfile| +| persistfile, perf | String | global | file that remembers cursors | | pollfrequency, pf | Number | global | rate of testing for ^C | | prefersyntax, psyn | String | global | when to set initialsyntax | | previouscommand | String | global | previous shell command line | @@ -3677,6 +3920,7 @@ | scrollbarwidth, xsw | Number | x11 | size of scrollbar, in pixels| | scrollbgimage, sbi | Boolean | (gui) | scroll background image | | scrollwheelspeed,sws| Number | (gui) | adjust speed of scroll wheel| +| secret | Number | x11 | identifies trusted clients | | sections, sect | String | buf | nroff section commands | | security, sec | One-of | global | normal, safer,or restricted | | sentenceend, se | String | global | punct at end of sentence | @@ -3698,6 +3942,7 @@ | spelldict, spd | String | global | name of dictionary file | | spellsuffix, sps | String | global | list of suffixes | | stagger | Number | x11 | offset for next new window | +| state | String | global | may be shown via show option| | statusbar, stb | Boolean | (gui) | enable the statusbar | | stopshell, ssh | String | x11 | interactive shell command | | submit, Submit | String | x11 | locale's Submit label | @@ -3709,7 +3954,7 @@ | tags, tagpath | String | global | list of possible tag files | | tagstack, tsk | Boolean | global | remember origin of tag srch | | tempsession, temp | Boolean | global | delete session file on exit | -| term, ttytype | String | tcap | terminal's termcap entry | +| term, ttytype | String | termcap| terminal's termcap entry | | terse, te | Boolean | global | don't translate messages | | textcursor, tc | Number | x11 | one of hollow, opaque, xor | | textwidth, tw | Number | buf | width for word-wrap, or 0 | @@ -3717,11 +3962,11 @@ | timestamp, time | String | buf | time when file was modified | | toolbar, tb | Boolean | (gui) | enable the toolbar | | true, True | String | global | locale's True value | -| ttycolumns, ttycols | Number | tcap | width of screen | -| ttyrows, ttylines | Number | tcap | height of screen | -| ttyitalic, ttyi | Boolean | tcap | okay to use "dim" for italic| -| ttyunderline, ttyu | Boolean | tcap | okay to mix color & underln | -| ttywrap, ttyw | Boolean | tcap | trust termcap's line wrap | +| ttycolumns, ttycols | Number | termcap| width of screen | +| ttyrows, ttylines | Number | termcap| height of screen | +| ttyitalic, ttyi | Boolean | termcap| okay to use "dim" for italic| +| ttyunderline, ttyu | Boolean | termcap| okay to mix color & underln | +| ttywrap, ttyw | Boolean | termcap| trust termcap's line wrap | | tweaksection, twks | Boolean | global | allow text before { section?| | u | String | user | user variable | | undolevels, ul | Number | buf | number of undoable commands | diff -urN elvis-2.2_0/doc/elvisos.html elvis-2.2_1/doc/elvisos.html --- elvis-2.2_0/doc/elvisos.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisos.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Operating System Notes +Elvis-2.2_1 Operating System Notes

    9. Operating System Notes

    diff -urN elvis-2.2_0/doc/elvisqr.html elvis-2.2_1/doc/elvisqr.html --- elvis-2.2_0/doc/elvisqr.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisqr.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Quick Reference +Elvis-2.2_1 Quick Reference

    diff -urN elvis-2.2_0/doc/elvisre.html elvis-2.2_1/doc/elvisre.html
    --- elvis-2.2_0/doc/elvisre.html	2003-10-21 04:32:26 +0200
    +++ elvis-2.2_1/doc/elvisre.html	2004-03-26 22:35:31 +0100
    @@ -1,5 +1,5 @@
     
    -Elvis-2.2_0 Regular Expressions
    +Elvis-2.2_1 Regular Expressions
     
     
     

    5. REGULAR EXPRESSIONS

    @@ -271,7 +271,7 @@ non-greedy /\d.*\?\d/ matches just "2three4". -

    5.2 Substitutions

    +

    5.2 Substitutions

    The :s command has at least two arguments: a regular expression, and a substitution string. The text that matched the regular expression is replaced by text diff -urN elvis-2.2_0/doc/elvisses.html elvis-2.2_1/doc/elvisses.html --- elvis-2.2_0/doc/elvisses.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisses.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Sessions +Elvis-2.2_1 Sessions

    10. SESSIONS, INITIALIZATION, AND RECOVERY

    @@ -240,12 +240,12 @@ then { augroup! html au! - " gt; jumps forward one page - au DispMapEnter html map nosave command gt; gt; - au DispMapLeave html unmap command gt; - " gt; follows a hypertext link - au DispMapEnter html map nosave command gt; gt; - au DispMapLeave html unmap command gt; + " <Space> jumps forward one page + au DispMapEnter html map nosave command <Space> <C-F> + au DispMapLeave html unmap command <Space> + " <Enter> follows a hypertext link + au DispMapEnter html map nosave command <Enter> <C-]> + au DispMapLeave html unmap command <Enter> augroup END }
    @@ -471,7 +471,7 @@ session file via "rm /var/tmp/elvis*.ses", or whatever the session file's name is. -For DOS/Windows users, the command would be "DEL \TEMP\ELVIS-2.2_0". +For DOS/Windows users, the command would be "DEL \TEMP\ELVIS-2.2_1".

    If you can figure out how to reproduce the problem, please let me know! My email address is

    kirkenda@cs.pdx.edu
    diff -urN elvis-2.2_0/doc/elvistag.html elvis-2.2_1/doc/elvistag.html --- elvis-2.2_0/doc/elvistag.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvistag.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Tags +Elvis-2.2_1 Tags

    14. Tags

    @@ -132,7 +132,7 @@ This syntax will be described later. You should check the manual page for a list of options. -

    14.4 Using tags with Elvis

    When starting Elvis, you can use the -ttagname flag to start with the cursor at the definition point of a given function in your diff -urN elvis-2.2_0/doc/elvistip.html elvis-2.2_1/doc/elvistip.html --- elvis-2.2_0/doc/elvistip.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvistip.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Tips +Elvis-2.2_1 Tips

    16. TIPS

    @@ -23,7 +23,8 @@
  • 16.8.3 Events
  • 16.8.4 Patterns -
  • 16.9 How to make Elvis run faster +
  • 16.9 Script library +
  • 16.10 How to make Elvis run faster

    16.1 Information via the Web

    @@ -854,7 +855,7 @@ :howto! (with a ! suffix).
    :kwic word -
    Build a table showing all occurrences of word in the online manual. +
    Build a table showing all occurrences of word in Elvis' online manual. This macro depends on the "grep" program to do the actual searching; if your system lacks "grep" then this won't work correctly. (Windows users should consider using the CygWin tools.) @@ -874,7 +875,7 @@
    :courier [size] ["bold"]
    :luxi [size] ["bold"]
    :andale [size] -
    X11 only. Select the Courier or Luxi mono fonts of the given size. +
    X11 only. Select the Courier, Luxi mono, or Andale fonts of the given size. If no size is specified, then it uses the default size, which is 14-point.
    :fork program @@ -947,6 +948,16 @@ Elvis comes with a variety of scripts to configure Elvis for various purposes. In most cases, if you run :mkexrc after running a script, then the effects of the script become permanent. +The scripts are described in the Script Library +section, below. + +
    :gdb [gdboptions] program [core|pid] +
    For "x11" only. +This starts the gdb debugger inside an xterm +window, and connects it to elvis via the elvgdb +program. +It also uses the :load alias to load some other GDB-related +toolbar buttons and aliases.
    :theme [name]
    List all installed themes, or load the theme with a given name. @@ -1265,7 +1276,7 @@ spelldict file. If Elvis finds it, great! Elvis will add it to its dictionary as a correct word. -Otherwise, Elvis will will try suffix substitution, as specified via the +Otherwise, Elvis will try suffix substitution, as specified via the spellsuffix option, and check the resulting word against the spelldict file again. @@ -1582,7 +1593,7 @@ A window's display mode is about to change. This is useful for reverting options that were changed via a DisplayEnter event. -The pattern is compared to the name of the new display mode, not the +The pattern is compared to the name of the old display mode, not the file name.
    DispMapEnter (not in vim)
    @@ -1646,7 +1657,7 @@ This is different from BufReadPost, which loads a file into a buffer. FileReadPost is triggered by the :r -command, but not the :e command. +command, but not the :e command. The auto command can use '[ and '] marks to determine which lines are new. See also FileReadPre for before the text has been @@ -1658,7 +1669,7 @@ This is different from BufReadPre, which loads a file into a buffer. FileReadPre is triggered by the :r -command, but not the :e command. +command, but not the :e command. See also FileReadPost for after the text has been inserted, and FilterReadPre for reading from a filter program. @@ -1722,7 +1733,15 @@ Not implemented.
    GUIEnter
    -Not implemented. +A graphical user interface is started. +This event is +generated after the first file is loaded the first window is created, +but only for true graphical user interfaces such as +x11 and +windows. +It is not generated for the +termcap interface. +Note that there is no "GuiLeave" event.
    OptChanged (not in vim)
    A particular option's value is changed. @@ -1888,11 +1907,252 @@

    Although the syntax for [] wildcards is similar to the syntax for the [] metacharacter in regular expressions, the two are not the same. -For example, you cannot use [[:alpha:]] to match +For example, you cannot use [[:alpha:]] to match any locale-dependent letter in a filename wildcard, though you can in regular expressions. -

    16.9 How to make Elvis run faster

    +

    16.9 Script Library

    +The :load alias can load a variety of scripts, +stored in a standard directory. +This section describes those scripts. + +

    Most of the scripts set up maps, +autocmds, or other aspects of +Elvis' configuration. +So running the script doesn't change your text, it changes Elvis. +The effects of these changes disappear when you exit Elvis, unless you +run the :mkexrc command to save the +altered configuration. + +

    Not all of these scripts do practical things. +Some are intended to serve merely as demonstrations of some of Elvis' features. + +

    Even the practical scripts may not be exactly what you want. +If that's the case, then you have a choice: +Either create a custom version of the script by running +":customize scripts/scriptname.ex"; +or load the normal version, alter its effects via Elvis' +configuration commands, and save the +altered version via :load" without any arguments will list the available +scripts. +This should include the following: +

    +
    align +
    Defines an :align alias which aligns = signs (or any +other delimiter that you supply as an argument) within a given range of lines. +This can be handy when you're trying to make a Makefile look pretty. + +
    gzip +
    Sets up some autocmd sequences for handling files that are compressed with +gzip. + +
    cb +
    Defines some aliases for managing cut buffers. +:cbsave and :cbload save your cut buffers to a file, +and load them again, respectively. +:cbshow lists the current contents and +putstyle of each cut buffer. + +
    cursor +
    Defines a :cursor alias which moves the cursor to a given +line of a given file. +If the file isn't loaded into a buffer already, then this alias will load it. + +
    decode +
    Defines a :decode alias, is sort of a "secret decoder ring". +Each letter is assigned a number. +You invoke this alias on a range of lines containing a series of numbers, +and pass it the number corresponding to 'a', and it converts the message's +numbers back into letters. + +
    define +
    Defines a "define:word" protocol which looks up word +in TechWeb.com's online technical encyclopedia. +Also defines a :define alias which uses this protocol. + +
    dict +
    Defines a "dict:word" protocol which uses the +dict program to look up word in a variety of +online dictionaries. +Also defines a :dict alias which uses this protocol. + +
    ellipse +
    Defines an :ellipse alias which inserts an ellipse into your +text. The parameters are width and height. +If you omit the height, then it is assumed to be half the width; +for most fonts, this makes the ellipse be roughly circular. +If you omit the width, then it is assumed to be either +textwidth or +(if textwidth isn't set) +columns. + +
    find +
    Defines a :find alias which repeats the previous search, +like the n command, except that if no match is +found in the current file then it performs a +:next command and tries again. +If you like this, you might want to map a key to invoke :find... +
    +	:map <C-N> :find<Enter>
    + +
    fontsize +
    For the x11 interface only, +this adds a toolbar button that lets you choose a font size. +It also defines a :fontsize alias. + +
    gdb +
    This is used by the :gdb alias. +You should never need to load this one manually. +It contains a variety of aliases and other settings that are used +by the GDB interface. + +
    herefile +
    Sets up :au events that attempt to +use regions to highlight "herefiles" in shell scripts. +A herefile is text embedded in a shell script between +<<SYMBOL and the following line containing just +SYMBOL. +The normal syntax coloring doesn't do herefiles properly, +so this workaround may be useful if you edit a lot of shell scripts. + +
    html +
    Sets up a lot of things that might be handy if you're editing HTML. +Honestly, I don't expect anybody to like everything in here. +You'll probably want to run ":customize scripts/html.ex" and +edit out big chunks of this. + +
    info +
    info2 +
    These are two slightly different attempts to make elvis use Gnu "info" +pages. +After loading one of these scripts, you should be able to run ":info gcc" +to see the info pages for the GCC compiler. + +
    inregion +
    Defines an :inregion alias for applying an ex command to +each line in a given type of region. +The first argument is a face name identifying the region, +and the remaining arguments are an ex command line to execute on each such line. + +
    isearch +
    Defines vim-compatible :isearch and :ilist +aliases, and some maps that use those aliases. +(See "likevim", below, for more vim-compatibility tricks.) + +
    life +
    Adjusts elvis for maximum speed while running the vi macro package that +implement's Conway's "life". +This also includes a copy of the "life" macros. + +
    likevim +
    Defines many aliases and maps to allow elvis to emulate some +of vim's commands. + +
    mail +
    Defines a :Mail alias. +This alias sets up elvis for editing mail messages. +If your email client can be configured to use an external editor, +then you might want to load this alias, run ":mkexrc" to store +the :Mail alias in your ~/.elvisrc file, and then tell your +email client to run "elvis -cMail" as the external editor. + +
    mailto +
    Defines a "mailto:" protocol. +This can be handy if you're using Elvis as a lightweight web browser, and +click on a "writeto:" link. +It uses the system's mail command to actually send the mail. + +
    makehtml +
    Defines a :makehtml alias, which converts plain text into HTML. +This does a pretty good job! +It can convert the whole file, or just a given range of lines. + +
    match +
    Defines a :match alias, which jumps between matching pairs +of keywords. +This is sort of like the % command, +but for keywords instead of single punctuation characters. +The list of keywords is easily adjustable by editing the script. + +
    note +
    Defines a simple :note alias for adding a note to a +given line, and :nextnote and :prevnote aliases +for searching the next/previous note. +It also sets up gn and gN maps for searching. + +

    I expect to add a "real" note facility to Elvis eventually. +This script uses regions, which can be +dangerous because if you're using regions for anything else then you could +easily lose your notes accidentally. + +

    pig +
    Defines a :piglatin alias which converts text to Pig Latin. +Finally something practical! + +
    reverse +
    Defines a :reverse alias which reverses characters in each +line. + +
    rot13 +
    Defines a :rot13 alias, which performs Rot13 encoding/decoding +for a range of lines. +Rot13 is a simple character substitution cipher in which the first 13 letters +in the alphabet are swapped with the last 13 letters. +Rot13 is sometimes used in Usenet news posts to protect unsuspecting readers +from potentially offensive jokes. + +
    sfb +
    Defines an :sfb alias for browsing directories. +The standard Elvis configuration includes a :readDIR alias +which loads this script and runs :sfb if you attempt to +edit a directory. + +
    shade +
    Sets up shades of gray for the hllayers +option. +If the background is light, then it will use light gray shades; +if dark, it will use dark shades. + +
    show +
    Defines a simple :show alias which displays the values +of various alias symbols such as !? and !1. + +
    shuffle +
    Defines a :shuffle alias, which randomly unsorts a range of +lines, or an entire buffer. + +
    since +
    Defines :since and :rcssince aliases. +These use :region to highlight changes +since the last write, or the last RCS checkin. +It also sets up some autocmds to run :rcssince automatically +when a file is loaded or saved, and to highlight changes. + +
    tags +
    This configures Elvis to automatically convert the value of the +tags option. +Traditionally, this option's value has been a space-delimited path, +but Elvis uses the operating system's path delimiter (colon or semicolon). +After loading this script, any time you change the "tags" value, Elvis +will go in and change any spaces to colons or semicolons as appropriate. + +
    wc +
    Defines :wc, a simple word counter. + +
    whois +
    Defines a "whois:" protocol, and a :whois command that uses it. +This is used to fetch information about an IP address or domain name. + +
    xbuf +
    For the "x11" interface only, +this reconfigures the toolbar to act like tabs for switching between buffers. + +
    + +

    16.10 How to make Elvis run faster

    This section describes some ways you can "tune" Elvis to run faster. None of these suggestions require recompiling Elvis. diff -urN elvis-2.2_0/doc/elvistip.html.orig elvis-2.2_1/doc/elvistip.html.orig --- elvis-2.2_0/doc/elvistip.html.orig 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/doc/elvistip.html.orig 2004-03-26 22:35:31 +0100 @@ -0,0 +1,2069 @@ + +Elvis Tips + + +

    16. TIPS

    +This section of the manual explains some of the more complex, obscure, +and useful features of Elvis (or larger subjects). +The following subjects are discussed: + +
  • 16.1 Information via the Web +
  • 16.2 Using Elvis as a Web browser +
  • 16.3 How to debug macros +
  • 16.4 Running your compiler from within Elvis +
  • 16.5 Internationalization +
  • 16.6 Aliases + +
  • 16.6.1 Some example aliases +
  • 16.6.2 Using aliases to add network protocols +
  • +
  • 16.7 The spell-checker +
  • 16.8 Auto commands + +
  • 16.8.3 Events +
  • 16.8.4 Patterns +
  • +
  • 16.9 How to make Elvis run faster +
  • + +

    16.1 Information via the Web

    +Here are some URLs (World Wide Web links to other documents) +which are relevant to vi. +Each of these, in turn, has links to other sites. +Directly or indirectly, these links will lead you to a huge amount +of information about vi. + +

    I've tried to limit this list to advertised sites; +there are others that I run across occasionally, but their URLs +tend to vary over time, so it isn't a good idea to place them in a +static document such as this one. +It makes for a short list, though. + +

    + +
    +ftp://ftp.cs.pdx.edu/pub/elvis/README.html +
    The "home" site of Elvis. +This is where you can find the latest official release. + +
    +ftp://ftp.cs.pdx.edu/pub/elvis/unreleased/README.html +
    Prerelease versions of Elvis can often be found here. +Prerelease versions are identified by a letter appended to the version number +they they're expected to be released as. For example, 2.2a is a prerelease +version of what will eventually be released as version 2.2. Also, I append +"-alpha" in the early stages when new features are still being added, or +"-beta" if no new features are expected before the release. Typically, +new versions are uploaded once a month or so; watch for announcements on +the comp.editors newsgroup. + +
    +http://elvis.vi-editor.org/index.html +
    This where Herbert +(a.k.a. Martin Dietze, who ported Elvis to OS/2) +is putting an Elvis home page. +It has links to all relevant web pages, archives, and +people's email addresses. +The manual will also be available here. +He is also considering adding a searchable online database of +aliases and how-to articles. +This may also become the preferred way to submit bug reports, suggestions, +or any other contribution to the project. + +
    +http://georg.f-451.net/elvis/ +
    This is Georg Neis' web page for Elvis. +He's the maintainer of the Debian Elvis package. + +
    +http://groups.yahoo.com/group/elvis-editor/ +
    This is a Yahoo mailing group. +It is used mostly by Elvis' developers, but user questions are +welcome too. + +
    +http://www.phys.columbia.edu/~flame/vi.htm +
    This is a Web page for Elvis, maintained by JaeSub Hong. +It has some screen shots, macros, and syntax-coloring definitions. +It also has the +online manual. + +
    +http://www.thomer.com/vi/vi.html +
    "The VI lover's home page," by Thomer Gil. +This contains links to a wide variety of vi documentation, and practically all vi clones. +A very good resource! +This is a new location; previously it was located at + +http://www.cs.vu.nl/~tmgil/vi.html. + +
    vi-editor.org +
    Sven Guckes' generic vi page. +He and Thomer Gil seem to have a friendly competition going on to see who +can make the best vi page, and we are all beneficiaries. + +
    +http://www.bsyse.wsu.edu/~rnelson/editors/editors.htm +
    A compendium of text editors. +It describes all kinds of text editors, not just vi clones. +It lists the features and supported platforms for each editor. + +
    +http://bluneon.gq.nu/puter/ed00.html +
    Another compendium of text editors.' +This one is oriented toward writing natural language text, +instead of computer source code. +The maintainer specifically mentions the +alt.tv.x-files.creative newsgroup. + +
    +http://darren.hiebert.com/ctags/ +
    Home page for Darren Hiebert's exuberant ctags program. +It supports all features of Elvis' ctags, except for the "ln" attribute, +and the "-r" flag for generating a "refs" file. +Exuberant ctags has a smarter parsing algorithm, which causes it to generate +fewer bogus tags (i.e., tags for things that really shouldn't have tags). +It also adds the ability to generate tags for "enum" values and a few +other useful things. + +
    +http://www.fleiner.com/jtags/ +
    Home page of Claudio Fleiner's "jtags" program -- a tag file generator +for Java source. + +
    +http://www.tamacom.com/global/ +
    Home page for Shigio Yamaguchi's global function +reference utility. You can make Elvis use it instead of the normal built-in +tag searcher by giving Elvis the following command: +
    +:se tagprg="global -t $1"
    + +

    Once you have run global's +gtags utility, you can do some powerful things such as +search for each place where a function (e.g., m_front()) is called, like this: +

    +:ta -r m_front
    + +
    +http://www.nicemice.net/par/ +
    Home page for Adam Costello's par program, which is a much +more sophisticated text formatter than the fmt program +distributed with Elvis. +It even does a very good job of reformatting comments! +Sadly, it is one of those rare programs that doesn't handle tab characters +correctly. + +
    +http://www.cygwin.com/ +
    This is the home page for the CygWin +tools -- ports of GNU utilities to Microsoft Windows, by Cygnus and Red Hat. +If you're looking for more Unix utilities to go with Elvis, this is the place. + +
    +ftp://alf.uib.no/pub/vi +
    An archive site containing many macro packages and other information about +vi. Nearly all of it should apply equally well to Elvis. + +
    +http://developer.berlios.de/projects/ex-vi/ +
    This is the source code to the real vi! + +
    +http://www.vim.org/ +
    +http://invisible-island.net/vile/vile.html +
    +http://www.bostic.com/vi/ +
    +http://www.winvi.de/ +
    +http://www.fwiarda.com/software.htm#pvic +
    +http://jvi.sourceforge.net/ +
    These are the home pages for some other vi clones: +vim, vile, nvi, WinVi, pvic, and javi respectively. +The last one is interesting because it is written in Java! + +
    +http://www.vim.org/util.html +
    The Vim utilities page. +Most of these also work with Elvis. + +
    +ftp://ftp.funet.fi/pub/doc/posix/p1003.2a/d8/5.10 +
    +ftp://ftp.funet.fi/pub/doc/posix/p1003.2a/d8/5.35 +
    These are old drafts of the POSIX standards for +ex and vi, respectively. +These URLs might not be valid very long. + +
    +http://docs.freebsd.org/44doc/usd/12.vi/paper.html +
    This is the official BSD documentation for vi. + +
    +http://roxanne.roxanne.org/~eric/vi_editor/ +
    An HTML version of +E. Larry Lidz' "vi editor FAQ". +A plain-text version of this FAQ is occasionally posted in the +comp.editors newsgroup. +(I think the official URL of the HTML version is +http://www.macom.co.il/vi/index.html, +but that site seems to be unreachable now.) + +
    +http://alumni.caltech.edu/~dank/nansi/ +
    This is a home page for the NANSI.SYS and NNANSI.SYS drivers, which +accelerate the screen updates under MS-DOS. + +
    +ftp://ftp.leo.org:/pub/comp/os/os2/leo/gnu/emx+gcc/ +
    +ftp://ftp-os2.cdrom.com:/pub/os2/emx09d/ +
    +ftp://ftp-os2.nmsu.edu:/pub/os2/dev/emx/v0.9d/ +
    +These are all places where you can find the EMX.DLL library for OS/2. +The first one is the "home" site, and the others are popular OS/2 archives. +You need EMX only if you want to run the "termcap" (elvisemx.exe) +or "x11" (elvisx11.exe) versions of Elvis under OS/2. + +
    +http://set.gmd.de/~veit/os2/xf86os2.html +
    +This is the home page for the OS/2 version of XFree86. +You need this (in addition to EMX) +if you want to run the graphical X11 version of Elvis. + +
    +ftp://ftp.ox.ac.uk/pub/wordlists/ +
    A collection of word lists, for a variety of languages. +This may be useful in conjunction with Elvis' +spell checker. +The home page for these lists is +http://www.hyphenologist.co.uk/. + +
    +http://www.mso.anu.edu.au/~ralph/OPTED/ +
    OPTED is a public domain english-language dictionary, +distributed as a set of HTML files. +It is part of Project Gutenburg, +and is derived from an old Webster's Unabridged Dictionary. +This is more than just a word list -- it includes definitions for the words. + +
    +http://www.dcs.shef.ac.uk/research/ilash/Moby/ +
    The Moby project -- a collection of word lists and similar resources. + +
    +http://www.htmlcodetutorial.com/quicklist.html +
    This is an online HTML authoring site. +Despite the name, it works better as a reference than as a tutorial. +The above link is actually just a page within the larger site, +because the main page +(http://www.htmlcodetutorial.com/) +has a big nasty pop-up advertisement. +Sadly, their pages look ugly when viewed with Elvis because they depend +on JavaScript and forms. +
    + +

    16.2 Using Elvis as a Web browser

    + +NOTE: The following information doesn't apply to the MS-DOS +version of Elvis, because that version doesn't support the ftp +and http protocols. But for Win32, Unix, and OS/2... + +

    You can use Elvis as a light-weight Web browser. +Surfing with Elvis isn't as much fun as surfing with a multimedia-capable +browser such as Netscape or MSIE, but Elvis does have some advantages: +it starts up much faster, it feels like vi, and you can edit whatever +you download. + +

    There's no special trick to loading a Web page. +Just give a URL where Elvis expects a filename, and Elvis will read the +Web page via the Internet. +You can follow links in Web pages just as you do in Elvis' online manual. +HTML pages are displayed in the "html" display mode, and anything else +uses the "hex" or "normal" display mode by default. +All data is fetched in binary so data files aren't mangled; however, +this also means that newlines aren't converted, which may make non-HTML +text files look ugly. + +

    Elvis has built-in support for the HTTP and FTP protocols. +Other protocols may be indirectly supported, via an HTTP proxy as indicated +by the elvis.net configuration file. + +

    By default, FTP access is anonymous. +However, if you give a file name which starts with "/~/" then Elvis will +attempt to login to the FTP server using you own account, as described in the +elvis.ftp or ~/.netrc configuration file. +You can also use "/~username/" to use some other user account listed in +.netrc. +For example, "ftp://localhost/directory/file" uses anonymous FTP, but +"ftp://localhost/~/directory/file" uses your own account. + +

    Elvis can write via FTP as well as read; see the +Internet chapter. + +

    Elvis also doesn't support inline graphic images, but that isn't as big +of a problem as you might think. +If you download an image, Elvis will simply load it into a buffer and then +display that buffer in the "hex" display mode. +You can then write that buffer's contents to a file, or in Unix you can send it +directly to an image viewer via a command such as ":w !xv -". + +

    The easiest way to save an image (or any other buffer) to a local file +is via the command ":w (dirfile(filename))". +In fact, you might want to add the following lines to your ~/.exrc file +to make the (F2) key save the current buffer to a file, +and the (F3) key send it to the xv image viewer: +

    +	map #2 :w (dirfile(filename))^M
    +	map #3 :w !xv -^M
    + +

    To make images easier to fetch, any <IMG SRC=url> tag +which isn't already part of a hypertext link will be interpreted as a link to +the SRC url. +This allows you to download an image by moving the cursor onto it and hitting +the (Enter) key. + +

    Elvis doesn't support frames either, so a similar trick was used for +<FRAME SRC=url> tags. +Elvis displays the name of each frame; +those names serve as links to the contents of the frame. + +

    Because Elvis is primarily an editor, not a Web browser, I deliberately +made the "html" display mode rather picky, so that any questionable entities +in your own HTML documents will call attention to themselves. +When you're using Elvis to browse other peoples' documents, though, this +can be annoying, so I modified it slightly to be more forgiving when you're +viewing read-only documents. +(All Web pages are read-only.) + +

    And you already know that Elvis' support for the <TABLE> macros is +very poor, right? +If you encounter a Web page which looks really ugly in Elvis, +you can bet it uses tables. + +

    Elvis doesn't support forms, or secure connections. +Well, Elvis can display mock-ups of forms; they just don't work. +They probably never will. +You have to draw the line somewhere. + +

    Elvis doesn't always choose the best display mode for HTML pages. +It uses "html" if the file name ends with ".html" or ".htm", or if the +document's text begins with "<!", "<H", or "<h". +For all other documents, it uses the "normal" or "hex" display mode by default. +If Elvis chooses the wrong display mode, you can use the +:display command to switch to a +different display mode. + +

    The command ":e foo" will always load the local file "foo" from +your current directory. +This is true of all commands which normally act on files -- unless you +give a complete URL, Elvis assumes it should work with local files. +However, while in the "html" display mode, the command ":ta foo" +will use the same protocol, site, and directory as the page you're already +viewing, because that's how the "html" display mode interprets tags. + +

    16.3 How to debug macros

    + +There are two ways to create a macro in Elvis: +You can either assign a series of commands to a keystroke (or series of +keystrokes) via the :map command, or you +can store a series of commands in a cut buffer and execute them via the +visual @x command. +You will often use a combination of techniques, in which :map macro +constructs a customized @x macro and runs it. + +

    (Aliases are a separate issue, +discussed later in this chapter. +The information in this section does not apply to aliases. +Elvis does not yet offer any special tools for debugging aliases.) + +

    Elvis has several features that make debugging macros much easier. +For example, you can create a window which continuously displays the +contents of a given cut buffer, such as "m, via the command: +

    +	:(Elvis cut buffer m)split
    +
    +or, more concisely: +
    +	:("m)sp
    +
    + +

    Note: The cut buffer must exist before you can display it. +Cut buffers are created the first time anything is yanked into them. + +

    The maptrace option allows you to +trace the execution of macros. +You can either allow it to run through the macro, or wait for a keypress +before each mapped command character. +You can also use the :break and +:unbreak commands to set or clear a +breakpoint on a given :map macro. +Breakpoints cause the maptrace option to switch from "run" to "step" when +that macro is expanded. + +

    The maplog option can be used to +log the trace information to a buffer named "Elvis map log". +The idea here is that you will give the command... +

    +	:se mt=r mlog=r
    +
    +... (or its full-length form, :set maptrace=run maplog=reset) +before starting the macro, and then when the macro fails you can +give the command... +
    +	:("Eml)sp
    +
    +... (or its full-length form, :(Elvis map log)split) +to see what it was doing shortly before the failure. +Note that the maplog option has no effect if maptrace is "off". + +

    Warning: Elvis has a single keystroke queue which is +shared by all windows. +Because of this, while Elvis is running a macro in one window you can't +switch to another window and type in commands. +Even if the GUI allows you to switch windows without using the keyboard, +doing so will simply force the macro to continue execution in the new window. +So don't switch windows while a macro is running! + +

    Here's a debugging methodology that works for me: +

      +
    1. Begin by loading the macro package and a test file. +
    2. Give the command ":se mt=r mlog=r", and run the macro. +
    3. If the macro fails, give the command ":("Eml)sp" + to find out what commands executed immediately before the failure. + In particular look for a :map macro that was expanded shortly before + the failure. +
    4. Set a breakpoint on that macro with ":bre macrokey". +
    5. Turn off logging, via ":se mlog=o". +
    6. Reload the test file. +
    7. Execute the macro again. When the macro with the breakpoint is encountered, + Elvis will switch to single-step mode. Step slowly through the next few + instructions, looking for one which does something unexpected. +
    + +

    If your macro reveals a bug in Elvis, please let me know! +My email address is +kirkenda@cs.pdx.edu. +Please tell me which version of Elvis you're using, as reported by the +:version command. + +

    16.4 Running your compiler from within Elvis

    + +Elvis can parse most compilers' error messages. +When it parses an error message, Elvis loads the faulty file, moves the +cursor to the line where the error was reported, and shows the descriptive +portion of the error message on the bottom row of the window. +You can step through all reported errors very quickly, making changes +along the way. + +

    Usually, you will invoke your compiler or "make" utility via the +:cc or :make +commands. +The only difference between these commands is that :cc invokes +the program named by the ccprg option, +and :make uses the makeprg option. + +

    Both of those options' values are evaluated using the +simpler expression syntax, with $1 set to +any extra command-line parameters, and $2 set to the current file name. + +

    You can also read error messages from some other program with the command +":errlist !program", +or read them from a file with the command +":errlist filename". + +

    I often invoke Elvis via the command "elvis +make" so +Elvis will attempt to compile the program, and move the cursor to the +first error (if there are any errors). + +

    All of the compiler's output text is collected into a buffer named +"Elvis error list". +If you wish, you can view this list in a separate window via this command: +

    +:(Elvis error list)split
    + +

    Here's how Elvis parses each line of compiler output: +Starting from the left, it divides the line into "words", which are defined as +a series of letters, digits, and/or certain punctuation characters. + +

    If the word is the name of an existing directory, then Elvis remembers +that directory name. +In later lines, Elvis will allow file names to be given relative to that +directory, in addition to the current directory. +This particular feature is intended to work with the directory lines +generated by the GNU version of the "make" program. + +

    If the word looks like a number, and no line number has been seen yet, +then the word is taken to be a line number. +If the word is the name of an existing, writable file +(or any existing file if the anyerror +option is set) in either the current directory or the directory remembered +from a previous line as described above, then the word is taken to be a +file name. +Other words are ignored. + +

    When Elvis has found both a file name and a line number, then it skips +over any whitespace or punctuation immediately following them, and uses +the remainder of the line as the error's description. + +

    If Elvis fails to find a file name/line number pair, then it skips that +whole line of compiler output. + +

    Immediately after collecting compiler output, Elvis moves the cursor to +the source of the first error. +After that, you can use :errlist +(with no arguments) or the visual * command +to step through each following error. + +

    Each time Elvis collects a new set of error messages, it remembers how many +lines are in each buffer. +Later, when you insert or delete lines to correct an error, Elvis can +compare the current number of lines to original number of lines, and adjust +the reported line numbers accordingly. + + +

    Here's something that may be useful for PERL programmers. +PERL's error messages follow two distinct formats: + +

    +description in file file at line line +
    description at file line line +
    + +Neither of these looks like any recognizable compiler error message format; +consequently, Elvis can't parse PERL's error messages directly. +But here's a way around that. +The following PERL program is a filter that reformats PERL's error messages +to look like normal compiler error messages. +
    +	#!/usr/bin/perl
    +	$\ = "\n";
    +	while (<>) {
    +	    chop;
    +	    s/(.*) in file ([^ ]*) at line (\d*).*/$2($3): $1/;
    +	    s/(.*) at ([^ ]*) line (\d*)\.$/$2($3): $1/;
    +	    print;
    +	}
    + +

    To use this script, store it in a file named "perlerr" and turn on the file's "execute" permissions, and then set +Elvis' ccprg option as follows: + + + + + +
    For CSH::set ccprg="perl -c ($1?$1:$2) |& perlerr"
    Other shells::set ccprg="perl -c ($1?$1:$2) 2>&1 | perlerr"
    + +

    NOTE: You can't simply cut&paste the above Perl script into a +file, because it contains some HTML code which Perl wouldn't understand. +(The diamond is written as "&lt;&gt;".) A better way +is to visually select those lines via the +shift-V command, and then use the +:wascii alias to save the formatted +text to a file as plain ASCII text. +You'll still need to edit the text file to remove leading whitespace and possibly some blank lines, but that's pretty easy. + +

    16.5 Internationalization

    + +Elvis can be configured to translate its messages into different languages, +and to use different symbol sets. +These things are accomplished via the +elvis.msg file and +:digraph command, respectively. + +

    Elvis locates the elvis.msg file during initialization. +Ordinarily it searches through each directory named in the ELVISPATH +environment variable. +However, if there is an environment variable named LC_ALL, LC_MESSAGES, +or LANG (listed in order or precedence) which is set to a non-null value, +then Elvis will look for elvis.msg first in a subdirectory whose +name matches the environment variable's value. +For example, if LC_ALL is unset, LC_MESSAGES=german, and +ELVISPATH=~/.elvis:/usr/local/lib/elvis, then Elvis would try to load +its messages from... +

      +
    1. ~/.elvis/german/elvis.msg +
    2. ~/.elvis/elvis.msg +
    3. /usr/local/lib/elvis/german/elvis.msg +
    4. /usr/local/lib/elvis/elvis.msg +
    + +

    The digraph table tells Elvis which pairs of ASCII characters can be +combined to form a single non-ASCII character. This table is configured +via the :digraph command. +To enter a digraph, type <Ctrl-K> and then the two ASCII +characters. Elvis will store the corresponding non-ASCII character instead +of the two ASCII characters. +See the Input Mode chapter for more information. + +

    The digraph table affects more than just keyboard input. +It also affects "html" mode, and character type classifications. + +

    Digraphs are used by the "html" display mode to translate +character entities into characters. +For example, when Elvis encounters &ntilde; in an HTML document, +it tries to find a digraph which combines 'n' with '~'. +If there is such a digraph, Elvis will use it to display an 'ñ'; +if not, then Elvis will display a plain 'n' character. + +

    The digraph table affects the character classes, too. +This, in turn, affects the definition of a "word", as used by the visual +w command, among others. +A non-ascii character is treated as an uppercase letter if, according +to the digraph table, it is the result of combining an ASCII uppercase letter +with either a punctuation character or a second uppercase letter. +A similar rule holds for lowercase letters. + +

    Also, Elvis tries to find uppercase/lowercase pairs through the digraph +table. +This is used for case conversions, as performed by the visual ~ command, or the \U metacharacter in the :s/old/new command. + +

    There is no way to specify a sorting order. +This means, in particular, that the +regular expression +/[a-z]/ will only match the ASCII lowercase letters, +not the non-ASCII ones. However, the regular expression +/[[:lower:]]/ will match all lowercase letters +including the non-ASCII ones. + +

    The default elvis.ini file tries +to load digraphs by executing either +elvis.pc8 for MS-DOS, OS/2, or text-mode Win32, +or elvis.lat for any other operating +system. + +

    The "win32" version of the "termcap" user interface has a +codepage option which determines +which symbol set is used for console output. +If you change codepage, you should also adjust your digraph table. + +

    16.6 Aliases

    + +Aliases provide a simple way to add a new name for an existing ex command, +or series of ex commands. + +

    The syntax of Elvis' :alias command +is intended to resemble that of the csh Unix shell. The simplest +example of an alias is... +

    +:alias save w
    +
    +... which would allow you to write your file out by running ":save", as an +alternative to the standard ":w". If you pass any arguments to ":save" then +they'll be appended to the ":w" command. For example, ":save foo" would +be interpreted as ":w foo". + +

    Here's another example. On Unix systems, this will make ":ls" display +a directory listing. +

    +:alias ls !!ls -C
    + +

    Note that the above example requires two exclamation marks. +This is because the "!" character is special in aliases -- +Elvis' aliases allow you to use special symbols to indicate where arguments +belong in the command text, and all of those symbols begin with a "!" character. +When you invoke the alias, all of the symbols are replaced by argument values +before the command text is executed. +Here is a complete list of the replacement symbols: +

    +     .--------.-------------------------------------------------.
    +     | SYMBOL | REPLACED BY                                     |
    +     |--------|-------------------------------------------------|
    +     |   !<   | first address line, if any addresses given      |
    +     |   !>   | last address line, if any addresses given       |
    +     |   !%   | address range, if any addresses given           |
    +     |   !?   | "!" if the alias is invoked with a "!" suffix   |
    +     |   !*   | the entire argument string except for "!" suffix|
    +     |   !^   | the first word from the argument string         |
    +     |   !$   | the last word from the argument string          |
    +     |   !$*  | all but the last word from the argument string  |
    +     |   !n   | the nth word (where n is a single digit)        |
    +     |   !n*  | everything from the nth word to the end         |
    +     |   !!   | a single, literal "!" character                 |
    +     | !name= | value from a name=value argument                |
    +     | !name& | URL-encoded version of !name=                   |
    +     ^--------^-------------------------------------------------^
    + +

    Using any of the !*, !^, +!$, !name=, +!name&, or +!1 through !9 symbols +in the command string has the side-effect of disabling the normal behavior of +appending the arguments to the command. +Or to phrase that another way: If the command text doesn't explicitly say +what to do with arguments, then Elvis will assume it should simply append them. + +

    The other symbols, such as !% and !?, +have no such default behavior. If your macro is going to use addresses or a +"!" suffix, then you must explicitly include !% or +!? (respectively) in the command string. + +

    Here's a simple alias for playing around with these: +

    +:alias show echo !!<=!< !!%=!% !!?=!? !!*=!* !!^=!^ !!2=!2 !!$=!$
    + +

    The !name= and +!name& symbols are intended +mostly for use in user defined protocols, where +they offer an easy way to examine the values of URL form fields. +In any other type of alias, they search through the alias's arguments +for one of the form name=value, and return the +value portion of that arguments. +Note that "!=" (without a name) is not substituted, so you don't need +to do anything special to use the != operator in expressions within aliases. + +

    Here's a more sophisticated version of the ":save" alias. This version +allows you to use ":save!" as an alias for ":w!". +

    +:alias save w!?
    + +

    Here's a macro that converts a range of lines to uppercase. If invoked +without any addresses, it will change only the current line, because that's +the default for the :s command. +

    +:alias upper !%s/.*/\U&/
    + +

    You can define multi-line aliases by enclosing the lines in curly braces. +The following example uses this technique to make a slightly smarter version +of the "save" alias: +

    +:alias save {
    + "Write a file, but only if it has been modified
    + if modified
    + then w!? !*
    +}
    + +

    Note that the first line of the alias's body is a comment. +(Comments start with a " character.) +This is a good idea because when the :alias +command is invoked with no arguments, it lists the names and first lines of +all aliases. +Putting a descriptive comment in the first line allows you to see what each +alias does simply by examining that list. + +

    If a multi-line alias is going to use arguments, then it must include +!*, !^, !$, or +!n symbols. Elvis does not, by default, +append arguments to the end of a multi-line alias; it only does that for +single-line aliases. + +

    An alias can have the same name as a built-in command, but aliases can't +be recursive. Together, these two rules mean that you can use an alias to +change the behavior of a built-in command. For example, the following alias +makes the :w command perform an RCS checkout +operation if you don't already have write permission for a file. +The "w" command inside the command text refers to the normal +:write command since it isn't allowed to be +a recursive call to the "w" alias. +

    +:alias w {
    + "Write a file, checking it out first if necessary
    + if readonly && "!%!?!*" == ""
    + then !!co -l %
    + then w!!
    + else !%w!? !*
    +}
    +
    + +You can optionally insert a ':' character between the '!' and the second +character of any of these symbols. +This has no effect; it is allowed simply to remain a little closer to CSH's +alias syntax. + +

    You can also optionally insert a '\' character between the '!' and the +second character. +This does have an effect: +It causes a backslash to be inserted before any characters which would +otherwise receive special treatment if they appeared in a regular expression. +Specifically, it will always insert a backslash before '\', '/', '^', '$', +'.', '[', or '*'. +Note that this is not sensitive to the +magic or +magicchar options; +in effect, it assumes that magic and magicchar +are set to their default values. +Also, it never inserts a backslash before a '?' character even if it is used +in a regular expression which is delimited by '?' characters. +The following "find" alias will search for literal text: +

    +:alias find /!\*
    +
    + +In addition, you can optionally specify a default value for an argument, +by placing the value in parentheses between the '!' and the second character. +Here's an example which acts like echo, except that if you don't tell it what +to echo then it will echo "Howdy!": +
    +:alias greet echo !(Howdy!)*
    +
    + +If necessary, you can insert both a backslash and a parenthesized default value. +The backslash quoting will be applied to the given argument value, but not the +parenthesized default value. +Here's a variation of the "find" alias which searches for literal text, or +if you don't specify any text to find then it searches for a { character at +the front of a line. +
    +:alias find /!(^{)\*
    +
    + +Some vi commands are implemented via ex commands. If you create an alias +with the same name as a built-in ex command, then the corresponding visual +command will be affected. For example, the ZZ +visual command runs :x, +so the following alias would break the ZZ command... +
    +:alias x echo Winners never quit, and quitters never win
    +
    + +

    16.6.1 Some example aliases

    +The distribution comes with some handy aliases in a file named +lib/elvis.ali. +I suggest you look at them. +The simple ones should give you some ideas of how to structure your own aliases, +and the complex examples will give you a feel of what can be accomplished. + +

    Remember that the names of aliases must be spelled out in full; +you can't abbreviate alias names the way can for built-ins. +Also, you can display the definition of any alias by running +":alias aliasname". + +

    These examples are intended to be useful as well as instructive. +They are loaded automatically when Elvis starts. +The aliases in that file include: +

    + +
    :lf [directory] +
    List the contents of the current directory, or of a named directory. +On Unix systems this works by invoking "ls -CF" on the arguments; +on other systems it invokes "dir/w". + +
    :pwd +
    Display the name of the current directory. + +
    :howto[!] word [word2] +
    Load the "How To" appendix in a separate window, and search for a topic +containing the given word or words. +The words should be typed in lowercase. +If you want to search all lines (not just topic lines) then run +:howto! (with a ! suffix). + +
    :kwic word +
    Build a table showing all occurrences of word in Elvis' online manual. +This macro depends on the "grep" program to do the actual searching; if your +system lacks "grep" then this won't work correctly. +(Windows users should consider using the CygWin tools.) + +
    :man [section] topic +
    Unix only. Read a man-page and display it in a new window. + +
    :save [filename] +
    Write this file, but only if it has been modified. + +
    :[range]ww[!] [filename] +
    Like the normal :w command, except that +if you try to write a whole file back over itself, and that file is readonly, +then the :ww alias will attempt to perform an RCS "checkout" +operation on that file by running "!co -l filename". + +
    :courier [size] ["bold"] +
    :luxi [size] ["bold"] +
    :andale [size] +
    X11 only. Select the Courier, Luxi mono, or Andale fonts of the given size. +If no size is specified, then it uses the default size, which is 14-point. + +
    :fork program +
    X11 only. Start running program in parallel with Elvis, with +its stdio disconnected from Elvis. +This is necessary because if you just ran +":!program &" Elvis would wait +for the program to exit, so it could display the program's output in the +Elvis window. + +
    :copying +
    Display the license. + +
    :features +
    Report the configuration of your copy of Elvis. +I.e., list the features which were enabled when Elvis was compiled. + +
    :customize filename +
    Create a personal copy of one of Elvis' configuration files +(unless you already have a personal copy of it), +and start editing it. +A typical example would be ":customize elvis.syn" +to edit the syntax coloring rules. + +
    :[range]left +
    :[range]right +
    :[range]center +
    For each line in the given range (or only the current line if no +addresses are given), adjust the indentation so that its text is +moved to the left, right, or center of the line. + +
    :[range]wascii[!] file +
    Write WYSIWYG formatted text out to a file as plain ASCII text. +This is intended to make it easy to save ex scripts (or other source code) +that are embedded within HTML pages such as this manual. +It works by temporarily setting lptype +to "dumb", and then writing the text via :lp. + +
    :[range]lpd[!] file +
    Print text, formatting it in the current display mode, regardless of the +buffer's usual display mode. +It works by temporarily setting the buffer's +bufdisplay option to the value of the +window's display option. + +
    :[range]cfmt +
    Adjust the line breaks in a C or C++ comment block. + +
    :wrapset [label] optionname +
    Display the value of an option, inserting spaces after each comma and +wrapping it to fit the width of the screen. +The optional label may contain multiple words, and causes the option's value +to be neatly indented. + +
    :text words +
    :btext words +
    Search through all the *.c or *.h files in the +current directory for the given words, and treat the found +locations as a series of matching tags. +The :text alias moves the cursor to the first location; you +can use an argumentless :tag command to move' +the each successive location. +The :btext alias browses the matches, similar to the +:browse command. + +
    :load [name] +
    List the installed scripts, or run the script with a given name. +The scripts reside in a "scripts/" subdirectory inside any of the directories +listed in elvispath. +Elvis comes with a variety of scripts to configure Elvis for various purposes. +In most cases, if you run :mkexrc after +running a script, then the effects of the script become permanent. + +
    :gdb [gdboptions] program [core|pid] +
    For "x11" only. +This starts the gdb debugger inside an xterm +window, and connects it to elvis via the elvgdb +program. +It also uses the :load alias to load some other GDB-related +toolbar buttons and aliases. + +
    :theme [name] +
    List all installed themes, or load the theme with a given name. +All of the themes use background images, and only the +"x11" and +"windows" interfaces +currently support images, +so this alias is only defined if you're using one of those. + +

    Themes are basically the same as :load scripts. +They just reside in a different subdirectory, and are intended to +configure colors instead of aliases and options. + +

    :mktheme name +
    For "x11" and +"windows" only. +Create a theme by bundling up the current color configuration and the +images it uses. +You only need to do this if you want to share the theme; +the :mkexrc command is perfectly capable +of storing your color settings for your own use. +

    +You should give this command in an empty edit buffer, with Elvis configured +the way you want it to look, and any background images located in the +current directory. +After you run this alias, the edit buffer will be filled with an ex script and +the images. +You'll want to edit it to add a description, add your name to it, and maybe +tweak the settings. +Then save it to a file, and send file to me at +kirkenda@cs.pdx.edu. +

    +The theme should set the foreground & background for "normal", "idle", +and the widgets and cursor. +It may also set the background only of highlight faces such as "selection", +"hlsearch", and "spell". +Other faces, such as "comment", should not be set in the theme; instead, +users are responsible for setting up their own favorite colors using the +:color command's "or colorname" +clauses to supply a variety of colors to choose from. + +

    readTHEME +
    For "x11" and +"windows" only. +This alias isn't intended to be run by the user directly. +Instead, it implements the "theme:" network protocol, using the +techniques described in the next section. +You can run ":e theme:/" to see a web page of downloadable themes. + +
    + +

    16.6.2 Using aliases to add network protocols

    + +Elvis has built-in support for URLs that use the +"ftp:" and +"http:" protocols, +as well as the "file:" and "buffer:" pseudo-protocols that access local +files or buffers. + +

    Most Elvis versions also allow you to add support for new protocols +by defining aliases that handle reading and writing via that protocol. +(Expressions can use the feature("proto") +function to test for this feature.) +The aliases must have the names "readXXX" and "writeXXX", +where "XXX" is the uppercase name of the protocol. + +

    The following example supports the "mailto:" protocol, on Unix/Linux systems: +

    +	alias readMAILTO {
    +	  "initialize a mailto: message
    +	  se noro reol=text
    +	  if exists($HOME/".signature")
    +	    read ~/.signature
    +	    1 i --
    +	  }
    +	}
    +	alias writeMAILTO {
    +	  "send a mailto: message
    +	  w !!mail -s"!(no subject)subject=" !2 >/dev/null 2>&1
    +	  se nomod
    +	}
    + +

    After loading these aliases, the command +":e mailto:user@system.com" will create an empty buffer named +"mailto:user@system.com", and then run the readMAILTO alias +with the cursor located in that buffer. + +

    The first thing that readMAILTO does is turn off the +readonly option, and set the +readeol option to "text". +Elvis normally sets these to readonly and reol=binary +because that's safest when downloading files via FTP or HTTP. +Since the whole point of the "mailto:" protocol is to write text, though, +those settings are inappropriate, so readMAILTO changes them. + +

    Other than that, readMAILTO merely needs to insert a copy +of the ~/.signature file, if one exists. + +

    You can then edit the message however you like, interactively. +When you want to send the message, +give the :w command. +Because the buffer's name +(actually the filename option) +starts with "mailto:", Elvis knows it should use the writeMAILTO +alias to write it. + +

    The writeMAILTO alias pipes the message out to the +standard Unix "mail" program. +This is a little trickier than it should be, because "mail" can fork off +a spooler process which can run for several minutes. +This could make Elvis' x11 user interface hang, +because it waits for stdout/stderr to close before resuming its normal activity, +and the spooler process inherits the stdout/stderr from the mail process. +The solution is to redirect the mail process' stdout/stderr to +/dev/null. + +

    After that, it turns off the buffer's +modified option, so that other commands +will know it is safe to delete that buffer. + +

    Both the readXXX and writeXXX +aliases are invoked with arguments derived from the URL. +The arguments contain pieces of the URL, as follows: +

    +.--------.-------------------------------------------------------.
    +| SYMBOL | REPLACEMENT TEXT                                      |
    +|--------|-------------------------------------------------------|
    +|   !*   | Whole URL - protocol://sitename/resource#anchor?args  |
    +|   !1   | Site name, if the URL contained one.                  |
    +|   !2   | Resource name                                         |
    +|   !3   | The anchor name, if the URL contained one.            |
    +| !4 - !9| Form fields, if any (name=value, URL-decoded)         |
    +| !name= | Value of the form field named name, URL-decoded       |
    +| !name& | Value of the form field named name, URL-encoded       |
    +^--------^-------------------------------------------------------^
    +
    +Example:                                                  !term&
    +                                                         .------.
    +  http://www.techweb.com/encyclopedia/defineterm.yb?term=firewall
    +         ^------!1-----^^----------!2-------------^ ^-----!4----^
    +

    In the "mailto:" example above, writeMAILTO used !2 as the +email address of the person being mailed to. +It also used the subject field value, if one was supplied, but instead of +trying to locate it by searching through !4 - !9, it searched by name +using the !name= notation. +Specifically, it used "!(no subject)subject=" to find the +value of the subject field, or use "no subject" by default. + +

    The difference between the !name= and +!name& notations is that +!name& is replaced with +URL-encoding intact, while +!name= is replaced with the +plain-text form of the parameter. +So !name& works better for +plugging a parameter into a newly constructed URL, while +!name= works better for most other +purposes. + +

    The userprotocol option is turned +on for buffers loaded via a readPROTOCOL alias. +The default elvis.arf script is sensitive to this; it skips +certain setup steps, since the default setup steps might not be appropriate +for a user-defined protocol. +If you don't like this behavior, +then simply add a "set nouserprotocol" command +to your readPROTOCOL alias. + +

    16.7 The spell-checker

    +Elvis can be compiled with a built-in spell checker. +To find out if your version of Elvis includes the spell-check feature, +run the following: +
    +	:calc feature("spell")
    + +

    If it says True then you're all set. +You should be able to enable spell-checking via the command: +

    +	:set spell
    +

    After that, any suspected misspellings will be highlighted. +You can change the highlighting style via +":color spell ..." + +

    16.7.1 Dictionaries

    + +Elvis has two spelling dictionaries: +One loaded from "tags" files, which is useful mostly for detecting misspelled +function names while you're editing source code; and +one for natural-language words, which can be loaded from a large sorted +file, or configured via the :words command. + +

    Elvis is intended primarily for editing the source code of programs. +In source code, some words should be checked only against the "tags" +dictionary (function names and data types), some should be checked against +both dictionaries (comments, mostly), and some should be unchecked +(variables, since they often are not listed in the "tags" file). +Elvis' spell checker can do that! + +

    The spell-checking rules are oriented around faces. +Faces are also used to control the font & color attributes of text, +as configured via the :color command. +Each face has a name, such as "comment" or "function". +The spell checker doesn't care about the appearance of a face, but it +cares a great deal about its name. + +

    For each face, Elvis allows you to specify one of three levels of +spell-checking: +

    +          .------.-----------------------------------------.
    +          | FLAG | TYPE OF SPELL-CHECKING PERFORMED        |
    +          |------|-----------------------------------------|
    +          |  *   | Check against both dictionaries         |
    +          |  +   | Check against only the tags dictionary  |
    +          |  -   | Don't perform any spell checking        |
    +          ^------^-----------------------------------------^
    + +

    By default, most faces check against both dictionaries. +The elvis.spe initialization file +configures some faces to check against only the tags dictionary, +or skip checking entirely. + +

    If the defaults don't meet your needs, you can use the +:check command to change the rules for +any face. +For example, the "variable" face isn't normally subjected to any type +of spell checking. +It would be nice if this could be checked against the tags dictionary, +but most tags generators don't generate tags for all variables, so +many valid variable names would be marked as misspelled. +However, if you have a tags generator that does a thorough job on variables +then you might want to enable spell-checking of variables against the tags +dictionary. +You probably wouldn't want to check variable names against the +natural-language dictionary, though. +The following command configures variable checking this way: +

    +	:check variable
    + +

    Similarly, the "string" face isn't normally checked because +strings tend to contain non-human text such as "\n" or "%d". +If you want to enable checking against both dictionaries, you can +use the following command: +

    +	:check *string
    + +

    The "*" causes Elvis to use both dictionaries. +In the earlier "variable" example, we could also have used a "+" flag to select +just the tags dictionary, but that's the default so we omitted it. +The "-" flag disables spell-checking: +

    +	:check -variable string
    + +

    By the way, the :check command supports +name completion, so you can use the <Tab> key to see what +faces are available. + +

    16.7.2 Configuring the tags dictionary

    + +If any buffer has its spell option +turned on, then Elvis will automatically load the tags dictionary from any +"tags" files that it finds. +(For a discussion of tags, see the Tags chapter, +and the ctags man-page.) + +

    When loading tags, Elvis searches through all of the file names in the +tags and +elvispath options. +If any of those names is a directory, then Elvis looks for a file named +"tags" in that directory. + +

    Elvis loads every tag from every file that it finds this way. +All of these tag names are combined in RAM to form a single tags directory. +Other tag information is ignored; Elvis only stores the names. + +

    As long as you generate tags files in the usual way, +Elvis should be able to find them without any trouble. + +

    To make it even easier, if the "tags" file in the current directory +is altered then Elvis will reload the tags dictionary automatically. +(It doesn't check the "tags" files in other directories, though.) + +

    All words in the tags dictionary are considered to be case-sensitive. + +

    16.7.3 Configuring the natural-language dictionary

    + +There are three ways to load words into the natural-language dictionary: +the spelldict option, and the +:words and +:wordfile commands. + +

    The way Elvis uses this dictionary is a bit tricky. +The first thing you must realize is that the dictionary is maintained in RAM. +It can pull words from the spelldict file +as needed, but that file isn't the dictionary -- the in-memory data structure +is. + +

    The next big quirk is that the dictionary contains both correct and +misspelled words. +Elvis must remember misspelled words so that it can recognize them again +quickly, without having to look them up in the +spelldict file every time. +This is very important because Elvis spell-checks every word on the screen, +after every keystroke. +Elvis can check any word against its in-memory dictionary in a fraction of +a microsecond, but file searches are far slower. + +

    You can use the :words command to add words +to the natural-language dictionary. +If you precede the words with a "-" then they'll be flagged as being incorrect. +Any time Elvis displays that word on the screen, it'll be shown highlighted +as an error. +Words added without a "-" flag will be added as correct words. + +

    If Elvis looks for a word in its dictionary, and doesn't find it, then +it will try to find the word in the +spelldict file. +If Elvis finds it, great! +Elvis will add it to its dictionary as a correct word. +Otherwise, Elvis will will try suffix substitution, as specified via the +spellsuffix option, and check the +resulting word against the +spelldict file again. +If Elvis finds that word, then it will add both the found word and the original +word, both flagged as correct words. +Otherwise, Elvis will add the original word, flagged as incorrect. + +

    Words pulled from the spelldict file +are always considered to be case-insensitive, even if they're capitalized in +that file. +Words added via :wordfile are also +case-insensitive. +However, words added via the :words command are +considered to be case-insensitive only when they're given in lowercase; +if the a word contains any uppercase letters then it will be case-sensitive. + +

    Words added via :word or +:wordfile are flagged as being personal, +unless you append a "!" suffix to the command name. +The distinction between personal words and other natural-language words +is important, because :mkexrc will store any +personal words in your .exrc file. + +

    16.7.4 Correcting errors

    + +Elvis has no built-in command for finding and correcting all of the spelling +errors in a file. +For that, I recommend an external program such as ispell. + +

    However, Elvis does have an spell +option for highlighting misspelled words, and the +show option supports a "spell" keyword +which displays suggested corrections at the bottom of the screen. +It also has a gs command for +moving to the next misspelled word. +If the cursor is already on a misspelled word before gs, +and the show option is presenting a list of suggestions, +then you can invoke gs with a "count" argument to fix the current +word before moving to the next word. +If none of the suggested alternative spellings are correct, you can use +c +gS (with an uppercase "S") +to replace the word manually. + +

    Elvis' built in calculator has functions named spell() and +spelltag(), which offer a way to access the +spelling suggestions in your own aliases or scripts. + +

    The spell() function only checks the in-memory dictionary; +it doesn't scan the spelldict file. +Because of this, you'll probably want to load all words from that file into +memory. +There are two ways to do that: +either invoke the :wordfile command +explicitly, +or set the spellautoload option +to have it be loaded automatically the first time you need it. + +

    16.8 Auto commands

    +

    16.8.1 Overview of Auto Commands

    +Auto commands give you a way to cause commands to be executed automatically +whenever a certain event occurs. +This is sort of like hardware interrupts. +Many of the events resemble GUI events. + +

    Elvis maintains a list of auto commands. +Each auto command contains: +

      +
    • A group name, which makes it easier to list or edit related auto commands. +
    • A set of events which trigger the auto command. +
    • A set of patterns. Most events have a file name + associated with them; patterns allow you to selectively apply a given + auto command to only certain types of files. Also, some events use names + of things other than files. +
    • An ex command line to run. +
    + +

    The whole auto command feature is omitted from the MS-DOS version of +Elvis, for the sake of compactness. +Under MS-DOS, Elvis will continue to depend on +elvis.arf and the related files. + +

    16.8.2 Groups

    +For ease of editing, auto commands may be divided into groups. +Each group has a name. +The default group is named "END", but other groups have no preset names; +you can choose your own names. + +

    To select a group for editing +(and to create the group if it didn't exist before), +use the :augroup command. +Typically, you'll begin by using +":aug groupname" to select +a group to edit, then wipe out any existing auto commands in that group and +define new ones, and then use +":aug END" +to mark the end of the group. +

    +	:aug buflist
    +	:au!
    +	:au BufNewFile,BufReadPost * morebuffers
    +	:au BufDelete * lessbuffers
    +	:aug END
    + +

    Note that the :augroup command +only affects the behavior of later :autocmd +commands. +Afterward, when events occur, they will trigger all appropriate auto commands +regardless of the group name. +I.e., groups are useful for editing the auto command list, but have no +effect on its actions. + +

    Well, actually there is one exception: +The :doau command can optionally be told +a specific group name to run. +If you don't specify the group name, then it will trigger all appropriate +events in all groups, just like a real +(non-:doau) event. + +

    Elvis' version of :aug has a minor +extension beyond vim's capabilities: +when invoked with ! suffix +(":aug! groupname") +it marks that group as being a "system" group. +Elvis' standard configuration scripts may use this notation to mark its own +groups. +The significance of this is, "system" groups aren't saved by the +:mkexrc command -- +they don't need to be stored in your custom initialization file since they're +created by a standard script. + +

    16.8.3 Events

    + +

    Event names are case-insensitive, so "BufCreate" can be written as +"bufcreate", or even "BuFcReAtE". + +

    The :doau command only accepts +a single event name -- the one that it is supposed to simulate. +However, the :au command accepts a +comma-delimited list of event names (without any whitespace between them), +or * to represent all events. + +

    When deleting/replacing events, if an auto command has been created with +multiple events and you only delete/replace some of them, then the remaining +ones will still be in effect. +In other words, Elvis will remove the given events from each auto command's +set of matching events, and will only completely delete an auto command if +the remaining set of events is empty. +(When deleting/replacing, it only effects auto commands where at least one +of the new patterns is identical to one of the +existing patterns.) + +

    Here's a list of built-in events, and what they mean in Elvis. +Note that even "Not implemented" events can be triggered explicitly by +:doau, so they aren't totally useless. +You can also create new events with the +:auevent command. + +

    + +
    AliasEnter (not in vim)
    +At the start of an alias. +The pattern is compared to the name of the alias, not a file, but you can +still use the "*" wildcard. +One common use for this is to set local options. +For example, if you like to use Perl-ish regular expressions for interactive +commands but still want to use traditional regular expression syntax inside +aliases, you could use the following to temporarily reset the +magicchar and +magicperl options while running aliases: +
    +	:au AliasEnter * local magicchar=^$.*[ nomagicperl
    + +
    AliasLeave (not in vim)
    +At the end of an alias. +The opposite of AliasEnter, and not nearly as useful. +Maybe good for tracing execution? + +
    BgChanged (not in vim)
    +The normal background color is changed. +The :color command is used to change the +normal background color. +The pattern is compared to "light" or "dark", depending on the chosen color. +You can use this to adjust other backgrounds: +
    +	:au BgChanged light color x11.spell on pink
    +	:au BgChanged dark  color x11.spell on red
    + +
    BufCreate
    +A user buffer is created. +A user buffer is one in which the internal +option is off. +All buffers that contain your text files are user buffers. + +

    Vim also sends this event after a buffer is renamed, but Elvis doesn't +normally. +If you want to make Elvis perform BufCreate when a buffer is +renamed, then make the BufFilePost event run +
    ":doau BufCreate", +like this: +

    +	:au BufFilePost * doau BufCreate
    + +
    BufDelete
    +A user buffer is destroyed. +Note that Elvis has no explicit command for freeing buffers. +It chooses when to free them automatically, if they aren't being used and +haven't been modified. +You can prevent Elvis from destroying a buffer by settings its +retain option. + +

    You could use this event with BufCreate to maintain +a list of open buffers. +The data/scripts/xbuf.ex file, distributed with Elvis, contains an example +of how this might be done in Elvis' x11 +user interface. + + +

    BufEnter
    +A buffer becomes the "current" buffer. +Specifically, this event is triggered when the buffer-specific options +are swapped in, to be accessible via commands such as +:set, or in +expressions. +See also the BufLeave event. + +

    Warning: +Elvis can switch buffers extremely often. +For example, if you're using the "x11" user +interface with multiple windows and toolbars, then Elvis will make each +window's buffer be the "current" buffer while it is evaluating the states +of each toolbar button, after each keystroke. + +

    BufFilePost
    +After changing a buffer's name. +A buffer's name can be changed two ways: +explicitly via the :file command, or +implicitly by saving an anonymous buffer out to a file. + +
    BufFilePre
    +Before changing a buffer's name. +See also the BufFilePost event. + +
    BufHidden
    +Not implemented. + +
    BufLeave
    +A buffer will no longer be the "current" buffer. +This is the other half of BufEnter event. +When Elvis is switching buffers, it triggers a BufLeave +event (with the old buffer) before switching, and a +BufEnter event (with the new buffer) afterward. + +
    BufNewFile
    +A buffer is created for a file that doesn't exist yet. +This is similar to BufReadPost, except that +BufNewFile is triggered only when there is no file to be read. +You can use this to create a skeleton version of a file. + +
    BufReadPost
    +After loading a file's contents. +See also BufReadPre for before it has loaded, +FileReadPost for inserting text from another file +into an existing file's buffer, +and FilterReadPost for inserting from a filter. + +
    BufReadPre
    +Before loading a file's contents. +This is useful for setting the readeol +option. +See also BufReadPost for after it has loaded, +FileReadPre for inserting text from another file +into an existing file's buffer, +and FilterReadPre for inserting from a filter. + +
    BufRead
    +Synonym for BufReadPost + +
    BufUnload
    +Immediately before BufDelete events, +for Elvis. +Vim has an extra level of decrepitude for buffers, where the text has been +discarded but the name and options have not yet been forgotten; +vim performs BufUnload when a buffer enters this state, and BufDelete +when it discards the rest of the buffer. +Elvis doesn't have that intermediate step, so BufUnload and +BufDelete are effectively the same thing. + +
    BufWritePost
    +After a buffer has been saved to its file. + +
    BufWritePre
    +Before a buffer will be saved to its file. +If any auto command triggered by this event causes an error and the +eventerrors option is set, +then the text will not be written. + +
    BufWrite
    +Synonym for BufWritePre. + +
    CursorHold
    +Not implemented. + +
    DisplayEnter (not in vim)
    +A window's display mode has changed. +This is useful for changing options in a display-mode dependent way. +The pattern is compared to the name of the new display mode, not the +file name. +See DisplayLeave for a way to change them back +afterward, or DispMapEnter for a way to adjust +the map table. + +
    DisplayLeave (not in vim)
    +A window's display mode is about to change. +This is useful for reverting options that were changed via a +DisplayEnter event. +The pattern is compared to the name of the new display mode, not the +file name. + +
    DispMapEnter (not in vim)
    +Keystrokes are received in a different display mode. +This is useful for installing maps that are +only intended to be used in specific display modes. +The pattern is compared against the name of the new display mode, not the +file name. +Note that this event can be triggered simply by switching windows, if the +two windows are using different display modes. + +

    Generally, Elvis will trigger a DispMapLeave +event on the old mode before triggering the +DispMapEnter event on the new mode. +Both of these events will be triggered before the newly received keystrokes +are subjected to maps. + +

    DispMapLeave (not in vim)
    +Keystrokes are received after an old display mode is abandoned. +This is useful for removing display-sensitive +maps that were installed via +DispMapEnter. +The pattern is compared against the name of the old display mode, not the +file name. +Note that this event can be triggered simply by switching windows, if the +two windows are using different display modes. + +
    Edit (Not in vim)
    +Text is changed. +While the event's auto commands are running, the '[ and +'] marks indicate the changed region. + +

    The Edit event is triggered every time the buffer is changed. +If you want to trigger an event for only the first +change to a buffer, then you can use the OptSet event to +watch for changes to the modified option. +(However, OptSet doesn't set the +'[ and '] marks.) + +

    FileAppendPost
    +After appending all or part of the buffer onto a file. + +
    FileAppendPre
    +Before appending all or part of the buffer onto a file. +While the event's auto commands are running, the '[ and +'] marks indicate the region to be written, and the +aufilename option indicates the name +of the file that it'll be written to. +If any auto command triggered by this event causes an error and the +eventerrors option is set, +then the text will not be written. + +
    FileChangedShell
    +Not implemented. + +
    FileEncoding
    +Not implemented. + +
    FileReadPost
    +After inserting from a file. +This is different from BufReadPost, +which loads a file into a buffer. +FileReadPost is triggered by the :r +command, but not the :e command. +The auto command can use '[ and '] marks to +determine which lines are new. +See also FileReadPre for before the text has been +inserted, and FilterReadPost for reading from a +filter program. + +
    FileReadPre
    +Before inserting from a file. +This is different from BufReadPre, +which loads a file into a buffer. +FileReadPre is triggered by the :r +command, but not the :e command. +See also FileReadPost for after the text has been +inserted, and FilterReadPre for reading from a +filter program. + +
    FileType
    +Not implemented. +Elvis doesn't have a "filetype" option, though I may add one later. +The mapmode +and bufdisplay +options serve a similar purpose. + +
    FileWritePost
    +After writing all or part of the buffer out to a different file. +While the event's auto commands are running, the +aufilename option indicates the name +of the file that was written. + +
    FileWritePre
    +Before writing all or part of the buffer out to a different file. +While the event's auto commands are running, the '[ and +'] marks indicate the region to be written, and the +aufilename option indicates the name +of the file that it'll be written to. +If any auto command triggered by this event causes an error and the +eventerrors option is set, +then the text will not be written. + +
    FilterReadPost
    +After reading from a filter program. +The auto command can use '[ and '] marks to +determine which lines are new. +See also FilterReadPre for before the text has been +inserted, and FileReadPost for reading from a file. + +
    FilterReadPre
    +Before reading from a filter program. +See also FilterReadPost for after the text has +been inserted, and FileReadPre for reading from a +file. + +
    FilterWritePost
    +After writing all or part of the buffer out to a filter program. +While the event's auto commands are running, the +aufilename option sores a copy of +the name stores a copy of the command that it is writing to. + +
    FilterWritePre
    +Before writing all or part of the buffer out to a filter program. +While the event's auto commands are running, the '[ and +'] marks indicate the region to be written, and the +aufilename option stores a copy of +the command that it is writing to. +If any auto command triggered by this event causes an error and the +eventerrors option is set, +then the text will not be written. + +
    FocusGained
    +Not implemented. + +
    FocusLost
    +Not implemented. + +
    GUIEnter
    +Not implemented. + +
    OptChanged (not in vim)
    +A particular option's value is changed. +The pattern for this event is a list of option names, +not file name wildcards. +While the auto command is running, +the aufilename option contains the name +of the actual option that was changed. + +

    NOTE: +Options changed via the +:set, +:let, and +:local +commands always trigger this event for any changed options, but +some options are changed internally by Elvis as a normal consequence +of operation, and +those changes don't always trigger the OptChanged event. +For example, the bufchars option +changes any time you insert or delete text, but this doesn't trigger +OptChanged. + +

    OptSet (not in vim)
    +A particular Boolean option is set or reset. +The pattern for this event is a list of option names, +not file name wildcards. +To detect when a Boolean option is set (becomes true), use the name without +any prefix; to detect when it is reset (becomes false), use the name with a +"no" prefix. +While the auto command is running, +the aufilename option contains the name +of the actual option that was changed, +with a "no" prefix if it just became false. +The following example causes the novice +option to change a few other options: +
    +	:au OptSet novice set nomagic report=1 showmode
    + +

    NOTE: +As with OptChanged, +Elvis changes some options internally, and +those changes don't always trigger an OptSet event. + +

    ScriptEnter (not in vim)
    +At the start of a script. +The pattern is compared to the name of the script file. +One common use for this event is for setting local options. +For example, if you like to use Perl-ish regular expressions for interactive +commands but still want to use traditional regular expression syntax inside +scripts, you could use the following to temporarily reset the +magicchar and +magicperl options while running scripts: +
    +	:au ScriptEnter * local magicchar=^$.*[ nomagicperl
    + +

    Note that ScriptEnter and ScriptLeave +are executed both for scripts that are explicitly run via the +:so command, and the configuration scripts +that are run automatically: +elvis.brf, +elvis.arf, +elvis.bwf, and +elvis.awf. + +

    ScriptLeave (not in vim)
    +At the end of a script. +The opposite of ScriptEnter, +and not nearly as useful. +Maybe good for tracing execution? + +
    StdinReadPost
    +Not implemented. + +
    StdinReadPre
    +Not implemented. + +
    Syntax
    +Not implemented. +Elvis has no "syntax" option. +The bufdisplay option serves a similar +purpose, but isn't quite similar enough to justify triggering a +Syntax event. +You could have Elvis simulate it via the OptChanged +event: +
    +	:au OptChanged bufdisplay doau Syntax
    + +
    TermChanged
    +Not implemented. +Elvis doesn't allow the term option to be +changed after initialization is complete. + +
    User
    +Never. +The User event can only be triggered explicitly via the +:doau command. + +
    VimEnter
    +Not implemented. + +
    VimLeavePre
    +Not implemented. + +
    VimLeave
    +Not implemented. + +
    WinEnter
    +A window becomes the "current" window. +Specifically, this is triggered when the window-specific options for a given +window are swapped in so they're accessible via commands such as +:set, and in +expressions. +See also BufEnter and WinLeave. + +

    Warning: +Elvis can switch windows extremely often. +For example, if you're using the "x11" user +interface with multiple windows and toolbars, then Elvis will make each +window be the "current" window while it is evaluating the states +of each toolbar's buttons, after each keystroke. + +

    WinLeave
    +A window will no longer be the "current" window. +When switching from one window to another, Elvis will first trigger a +WinLeave event (with the old window), then switch windows, +and then trigger a WinEnter event (with the new window). +See also BufLeave. + +
    + +

    16.8.4 Patterns

    + +Patterns are used mostly to select file names. +They use the same "wildcard" characters that are used for matching filenames +on the command line. +Different operating systems have slightly different rules. +Specifically... +
      +
    • "*" matches any text, of any length. + For example, "*.html" matches all the names that end with + ".html". +
    • "?" matches any single character. +
    • For all operating systems except MS-DOS, "[chars]" matches + any single character in the chars list. +
    • For all operating systems except MS-DOS, "[^chars]" matches + any single character not in the chars list. +
    • For Unix, letters are compared in a case-sensitive manner; for all + other operating systems, letters are compared case-insensitively. +
    • Other characters must match exactly. +
    + +

    The contents of [] wildcards is always interpreted in +a case-sensitive manner, even in operating systems such as Windows which +are normally case-insensitive with respect to filenames. +If you want a [] expression to be case-insensitive, then you +must explicitly give both the uppercase and lowercase versions of the +letter. + +

    The chars list may be individual characters, or ranges of +characters with a '-' between them. For example, [_a-zA-Z] +matches an underscore or a letter. + +

    Although the syntax for [] wildcards is similar to the +syntax for the [] metacharacter in regular expressions, +the two are not the same. +For example, you cannot use [[:alpha:]] to match +any locale-dependent letter in a filename wildcard, though you can in +regular expressions. + +

    16.9 How to make Elvis run faster

    +This section describes some ways you can "tune" Elvis to run faster. +None of these suggestions require recompiling Elvis. + +

    For example, my computer (AMD K6-200) can run 10 +generations of the "life" macros in 41 seconds with the default configuration. If I invoke Elvis with a reduced block size +(-b1024 on the command line) and an increased cache +(:set blkcache=200 blkhash=300), +it can run 10 generations in just 24 seconds. + +

    The blksize option

    +Elvis uses fixed-size blocks to store buffers. The block size is chosen +when the session file is created. The default is 2048 bytes (or 1024 bytes +for MS-DOS), but you can override that by invoking Elvis with a +-bblksize flag. +The size must be a power of two, between 512 and 8192. + +

    The blksize option indicates the +current block size. This is a read-only option; once Elvis has started, +(and hence has already created the session file) it is too late to request +a different block size. + +

    Generally, smaller blocks are better if your CPU is slow or you're only +editing small files. Larger blocks are better if your disk is slow (e.g., the +temporary file is stored on a remote disk, accessed via a network) or you're +editing large files. + +

    The block cache

    +In the interest of speed, Elvis has its own cache of blocks from the session +file. The blkcache option tells Elvis +how many blocks to store in the cache. You can change this value at any time. +If Elvis requires more cached blocks for a given editing operation than the +blkcache allows, then Elvis ignores blkcache and loads the required blocks into +the expanded cache; you can't make blkcache too small. +The default blkcache is 20 (except for MS-DOS, where it is 10), +and the upper bound is 200 blocks. +In MS-DOS, setting blkcache too high can cause Elvis to crash. + +

    The blkhit +and blkmiss options count the number +of cache hits and misses, so you can compute the efficiency of the cache +as follows: +

    +	:calc (bh*100/(bh+bm))"%"
    + +

    You'll probably find that 98% or more of the block requests are being +satisfied from the cache. However, since each miss takes thousands of +times longer to complete than a hit, each fraction of a percent means a lot. + +

    In addition to the blocks themselves, the cache contains a hash table +which allows Elvis to quickly determine whether a block is in the cache +or not. If you increase the size of the cache, then you'll probably want to +increase the size of the table as well. The table size is controlled by the +blkhash option. Ideally, it should +be set to a prime number somewhat larger than blkcache... +or simply the largest possible value, since hash table entries are small. +The default is 61, and the upper bound is 300. + +

    Syncing

    +Elvis has a sync option which, if set, +causes Elvis to force all dirty blocks out to disk occasionally. This is +a very slow operation, so the sync option is normally turned off. +If Elvis seems to be running exceptionally slowly, then you might want to +verify that sync is off. +You can check it by giving the command ":set sync?". + +

    Temporary files

    +The session file, and any other temporary files, should be stored on a local +hard disk. Storing them on a network drive will slow Elvis down a lot. + +

    The session option indicates where +the current session file is stored, and the +sessionpath option indicates which +directories Elvis looked through when deciding where to put the session file. +These are read-only options, since it is too late to choose a new location +for the session file after the session file is already created. +If you need to force Elvis to store its session files in a different +directory, you should set the SESSIONPATH environment variable +to a list of acceptable directories. Elvis will use the first directory +from that list which exists and is writable. + +

    The directory option tells Elvis +where to store other temporary files, such as those used for piping text +through external programs. You can change its value at any time. (Note: +the real vi also has a directory option, but only allows you to change it +during initialization.) + +

    Screen updates

    +Options which add information to the bottom row of the window, such as +ruler and +showmode, can slow down screen updates. +If speed is critical, you should turn those options off. + +

    The optimize option attempts to +eliminate superfluous screen updates while a macro is executing. +It is normally on, but you may want to verify that. +Some animation macros force it off. + +

    Elvis also has an animation option +which, if optimize is on, causes Elvis +to bypass some of the animation steps. The default value is 3. If animations +look choppy then try reducing it to 1. Or set it to 10 or so for faster +animation. + +

    The exrefresh option controls whether +Elvis should refresh the screen after each line output by an ex command, or +wait until the command completes and then update the screen once. +It is normally off, so the screen is only updated once. + +

    Interestingly, the syntax-coloring display mode seems to run about as fast +as the normal display mode. One possible exception would be if you're running +Elvis over a slow modem connection then the extra escape sequences required for +sending color information may slow down screen updates. + +

    If you have long lines, then Elvis may run somewhat faster when the +wrap option is set. This is because Elvis +always formats entire lines, even if only part of the line is visible on +the screen, and the "nowrap" display style shows more long lines (one per row) +than the "wrap" display style. + +

    Input

    +The pollfrequency option indicates +how often Elvis checks for an abort request from the user. (Abort requests +are usually given by typing ^C or by clicking on a window while a macro or +other time-consuming command is running). Smaller numbers give a quicker +response to an abort request, but will cause the command itself to run slower. + +

    The keytime option indicates how long +Elvis should wait after receiving an Esc character to distinguish between +the <Esc> key, and some other function key which begins with an Esc. +Longer times are more reliable, especially when you're running over a network. +But shorter times allow a quicker response to the <Esc> key. + +

    MS-DOS-specific tips

    +The single biggest improvement you can make is to switch from the 16-bit +MS-DOS version to the 32-bit text-mode Win32 version. It only runs under Windows95 +or WindowsNT, not MS-DOS, but you can make it run in full-screen mode which +feels like MS-DOS. And it is *much* faster, because I really had to mangle +the MS-DOS version of Elvis to make it fit in the lower 640k. + +

    The fancier ANSI drivers such as NANSI.SYS also help. They allow Elvis +to redraw the screen very quickly. The URLs section +of this chapter tells you where you can find NANSI.SYS on the Internet. + +

    Installing smartdrv.exe can be a big help. +Storing temporary files on a RAM disk (in extended/expanded memory please!) +can also help. + +

    Elvis also has a compile-time option, controlled by the +FEATURE_RAM +declaration in config.h, which allows Elvis to store its buffers +in EMS/XMS memory instead of a file. This makes Elvis run much +faster, but it has some disadvantages. If Elvis crashes, there will be no +way to recover the contents of the edit buffers. Also the Microsoft functions +for accessing EMS/XMS memory are very bulky, and also require a fairly large +buffer; so if you enable FEATURE_RAM, then you must disable most of the other +FEATURE_XXXX features in config.h, and even then Elvis may run out +of memory occasionally. If you enable FEATURE_RAM, then to actually use that +feature, you must invoke Elvis with "-f ram" on the command line. + +

    If you often use "-b 2048" or "-f ram", then you might consider setting up +a batch file which runs them. For example, you could create a +elvis.bat file containing... +

    +	elvis.exe -b 2048 -f ram %1 %2 %3 %4 %5 %6 %7 %8 %9
    +
    + diff -urN elvis-2.2_0/doc/elvisvi.html elvis-2.2_1/doc/elvisvi.html --- elvis-2.2_0/doc/elvisvi.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/elvisvi.html 2004-03-26 22:35:31 +0100 @@ -1,5 +1,5 @@ -Elvis-2.2_0 Visual Command Mode +Elvis-2.2_1 Visual Command Mode

    2. VISUAL COMMAND MODE

    diff -urN elvis-2.2_0/doc/fmt.man elvis-2.2_1/doc/fmt.man --- elvis-2.2_0/doc/fmt.man 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/fmt.man 2004-03-26 22:35:31 +0100 @@ -18,7 +18,7 @@ .ad b .SH VERSION This page describes the -.B Elvis 2.2_0 +.B Elvis 2.2_1 version of .BR fmt . See diff -urN elvis-2.2_0/doc/howto.html elvis-2.2_1/doc/howto.html --- elvis-2.2_0/doc/howto.html 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/howto.html 2004-03-26 22:35:31 +0100 @@ -1,6 +1,6 @@ -Elvis-2.2_0 How To +Elvis-2.2_1 How To

    C. How to...

    @@ -76,7 +76,7 @@ For example, adding the following line into elvis.arf would cause any file that looks like a patch to be displayed using "syntax cdiff"
    -	1s/---\|***/set bufdisplay="syntax cdiff"/g
    + 1s/---\|\*\*\*/set bufdisplay="syntax cdiff"/x

    If you don't want to modify elvis.arf, you could achieve a similar effect via the BufReadPost autocmd event. @@ -103,7 +103,7 @@

    Change the default settings
    Before the first buffer is loaded or the first window is created, -and buffer/window options you set will be used as the defaults for +any buffer/window options you set will be used as the defaults for the buffers/windows that are created later. In other words, although setting a buffer-specific option like equalprg or a window-specific option @@ -287,12 +287,17 @@ This is one good reason to skip the map, and get in the habit of using ^T to increase indentation. The autotab option helps here, too. + +
    Erase text immediately when backspacing +
    The cleantext option tells Elvis +when to delete text that you've backspaced over. +Try ":set cleantext=long,bs,ex".

    C.4 Buffers

    Switch to a different buffer in the same window -
    This is easier that you might think. +
    This is easier than you might think. On an ex command line, if you give an address but no command then Elvis will move the cursor to there. So to switch buffers all you need to do is give an address that's in @@ -381,6 +386,11 @@ #!/bin/sh exec elvis -Gtermcap "$@" +

    A more elegant solution uses the $ELVISGUI environment variable: +

    +	#!/bin/sh
    +	ELVISGUI=termcap exec elvis "$@"
    +

    If you never want to use the "x11" user interface, then you should probably reconfigure Elvis to leave it out. This will make Elvis considerably smaller. @@ -388,7 +398,7 @@ execute the following shell commands:

     	make clean
    -	configure --with-x=no
    +	./configure --with-x=no
     	make
    Run Elvis from a [Start] menu @@ -493,7 +503,7 @@ I plan to clean that up some day, by making Elvis smart enough to avoid reading stdout/stderr when the command line ends with a '&' character. -
    Run an interactive program under X11 +
    Run an interactive program in an Elvis window under X11
    Sadly, this can't be done with Elvis' "x11" user interface because Elvis' windows don't have a built-in terminal emulator. This is expected to be added for Elvis 2.3, but that doesn't help you @@ -852,8 +862,8 @@ } -

    The other way is simpler and more versatile, but it requires the use of -an external file. +

    The other way is simpler and more versatile, +though it does require the use of an external file. It uses the :lpr command with lptype=html. Since Elvis' print mechanism supports all of Elvis' display modes, @@ -884,7 +894,7 @@ <Ctrl-V><Esc> to get the ^[ character.)

    -
    Display the size in a window when it is resized +
    Display the size of a window when it is resized
    You can use the :au OptChanged command to detect when the lines or columns options change, and display a message showing the new values. diff -urN elvis-2.2_0/doc/ref.man elvis-2.2_1/doc/ref.man --- elvis-2.2_0/doc/ref.man 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/doc/ref.man 2004-03-26 22:35:31 +0100 @@ -7,7 +7,7 @@ .RI [ restrictions ]... .SH VERSION This page describes the -.B Elvis 2.2_0 +.B Elvis 2.2_1 version of .BR ref . See diff -urN elvis-2.2_0/draw.c elvis-2.2_1/draw.c --- elvis-2.2_0/draw.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/draw.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_draw[] = "$Id: draw.c,v 2.131 2003/10/17 17:41:23 steve Exp $"; +char id_draw[] = "$Id: draw.c,v 2.133 2004/03/07 21:37:49 steve Exp $"; #endif #if defined (GUI_WIN32) @@ -95,7 +95,7 @@ /* build the vinf textobject command */ prevcount = vinf.count; vinf.count = 0L; - while (elvspace(*obj)) + while (*obj == ',' || elvspace(*obj)) obj++; if (elvdigit(*obj)) { @@ -1525,6 +1525,10 @@ if (win->di->cursface < colornpermanent) arg = colorinfo[(int)win->di->cursface].name; } + else if (!CHARncmp(cp, "state", 5)) + { + arg = o_state; + } #ifdef DISPLAY_HTML else if (!CHARncmp(cp, "link", 4)) { diff -urN elvis-2.2_0/elvgdb.c elvis-2.2_1/elvgdb.c --- elvis-2.2_0/elvgdb.c 1970-01-01 01:00:00 +0100 +++ elvis-2.2_1/elvgdb.c 2004-03-26 22:35:29 +0100 @@ -0,0 +1,1064 @@ +/* elvgdb.c */ + +/* Copyright 2004 by Steve Kirkendall. This program may be freely redistributed + * under the terms of the Perl "Clarified Artistic License". + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "elvis.h" + +/* This typedef is used for storing the attributes of an annotation. The + * first three bits indicate the highlighting color for subsequent text, + * and every other attribute is simply a one-bit boolean flag. + */ +typedef enum { + EG_BLACK = 0, /* black foreground */ + EG_RED = 1, /* red foreground */ + EG_GREEN = 2, /* green foreground */ + EG_BROWN = 3, /* brown/yellow foreground */ + EG_BLUE = 4, /* blue foreground */ + EG_MAGENTA = 5, /* magenta foreground */ + EG_CYAN = 6, /* cyan foreground */ + EG_WHITE = 7, /* white foreground */ + EG_COLOR = 8, /* change the color */ + EG_BOLD = 16, /* turn on the bold/bright bit */ + EG_UNDERLINE = 32, /* turn on the underline bit */ + EG_HIGHLIGHT = 64, /* don't turn off colors or other attributes */ + + EG_FROMGDB = 256, /* start a :fromgdb command */ + EG_TOELVIS = 512, /* end a :fromgdb command, and send it */ + EG_ARGS = 1024, /* append this annotation's args to command */ + EG_TEXT = 2048, /* append the following text to command */ + EG_TABLE = 4096, /* save name of table */ + EG_RECORD = 8192, /* send previous record, start a new one */ + EG_FLUSH = 16384, /* flush output after each character */ + EG_TRACE = 32768, /* display the annotation's name */ + EG_SERVER = 65536, /* hide output if "server" command */ + EG_LIMIT = 131072 /* guard against multiple messages */ +} attrib_t; +#define EG_YELLOW (EG_BROWN|EG_BOLD) +#define EG_GRAY (EG_BLACK|EG_BOLD) +#define EG_COLORMASK (EG_WHITE) + +static struct +{ + char *name; /* name of an attribute */ + attrib_t attrib;/* bits that it should set */ +} attribname[] = +{ + {"black", EG_BLACK|EG_COLOR}, + {"red", EG_RED|EG_COLOR}, + {"green", EG_GREEN|EG_COLOR}, + {"brown", EG_BROWN|EG_COLOR}, + {"blue", EG_BLUE|EG_COLOR}, + {"magenta", EG_MAGENTA|EG_COLOR}, + {"cyan", EG_CYAN|EG_COLOR}, + {"white", EG_WHITE|EG_COLOR}, + {"yellow", EG_BROWN|EG_BOLD|EG_COLOR}, + {"gray", EG_BLACK|EG_BOLD|EG_COLOR}, + {"bold", EG_BOLD}, + {"underline", EG_UNDERLINE}, + {"highlight", EG_HIGHLIGHT}, + {"fromgdb", EG_FROMGDB}, + {"toelvis", EG_TOELVIS}, + {"args", EG_ARGS}, + {"text", EG_TEXT}, + {"table", EG_TABLE}, + {"record", EG_RECORD}, + {"flush", EG_FLUSH}, + {"trace", EG_TRACE}, + {"server", EG_SERVER}, + {"limit", EG_LIMIT} +}; + + +typedef struct annot_s +{ + struct annot_s *next; /* some other annotation */ + attrib_t attrib; /* attributes of this annotation */ + int sent; /* Boolean: have we sent one already? */ + char name[1];/* storage space for name of annotation */ +} annot_t; + +/* Forward declarations for functions */ +#ifndef P_ +# if __stdc__ +# define P_(X) X +# else +# define P_(X) () +# endif +#endif +static void openx P_((void)); +static annot_t *findannot P_((char *name)); +static char *searchpath P_((char *pathlist, char *filename)); +static void loadannot P_((char *filename)); +static FILE *opengdb P_((int argc, char **argv)); +static int closegdb P_((FILE *fromgdb)); +static void highlight P_((attrib_t attrib)); +static attrib_t doannot P_((Window elviswin, char *name, char *args)); +static attrib_t annotation P_((FILE *fromgdb, Window elviswin)); +static void echoch P_((attrib_t attrib, int ch)); +static int rungdb P_((int argc, char **argv)); +static Window findgdb P_((void)); +static int tellgdb P_((int argc, char **argv)); +extern int main P_((int argc, char **argv)); + +static annot_t *annotlist; /* list of annotations */ + +static attrib_t defattrib = (attrib_t)0; /* default attributes */ +static attrib_t traceattrib = EG_HIGHLIGHT; /* trace highlight attributes */ + +/* This stores the :fromgdb command that will be sent to elvis */ +static char toelvis[1000]; +static char *buildtoelvis; +static char tablename[100]; +static long secret; + +/* This is used to handle "server" suppression. If hideserver=NULL, then + * output as normal. Else if pointing to a non-'\0' character, then compare + * the next output char with *hideserver, and increment *hideserver if match + * or set it to NULL if mismatch. Else (when pointing to a '\0') suppress + * output. + */ +static char *hideserver; + +/* These store info about the X server */ +static Display *display; /* display */ +static Window root; /* root window of default screen */ +static Atom elvis_server; /* window attribute tag for finding elvis */ +static Atom elvgdb_server; /* window attribute tag for finding elvgdb */ +static Atom targets; /* the TARGETS atom */ + + +/* This does most of the work needed for opening a connection to the X server */ +static void openx() +{ + char name[100]; + + /* open the display */ + display = XOpenDisplay(""); + if (!display) + { + fprintf(stderr, "elvgdb: could not access the X server\n"); + exit(2); + } + + /* find the root window of the default screen */ + root = RootWindow(display, DefaultScreen(display)); + + /* convert attribute names to atoms */ + targets = XInternAtom(display, "TARGETS", True); + sprintf(name, "ELVIS_SERVER_%d@", geteuid()); + gethostname(name + strlen(name), sizeof name - strlen(name)); + elvis_server = XInternAtom(display, name, True); + sprintf(name, "ELVGDB_SERVER_%d@", geteuid()); + gethostname(name + strlen(name), sizeof name - strlen(name)); + elvgdb_server = XInternAtom(display, name, False); +} + +/* locate an annotation's info. If not found, then return NULL */ +static annot_t *findannot(name) + char *name; /* name of the annotation to find */ +{ + annot_t *scan; + + /* search for it */ + for (scan = annotlist; + scan && strcmp(scan->name, name); + scan = scan->next); + + return scan; +} + +/* search through a path for a given file */ +static char *searchpath(pathlist, filename) + char *pathlist; /* colon-delimited list of directories */ + char *filename; /* name to search for */ +{ + static char fullname[300]; + char *home, *build; + + /* get the value of $HOME */ + home = getenv("HOME"); + + /* for each directory in the pathlist... */ + do + { + /* if empty, then use current directory */ + if (*pathlist == ':' || *pathlist == '\0') + { + strcpy(fullname, filename); + } + else /* use the given directory name */ + { + /* if starts with "~/" then use $HOME/ */ + build = fullname; + if (*pathlist == '~' && !isalnum(pathlist[1]) && home) + { + strcpy(fullname, home); + build = fullname + strlen(fullname); + pathlist++; + } + + /* copy the directory name */ + while (*pathlist != ':' && *pathlist) + { + *build++ = *pathlist++; + } + + /* append a slash unless the dir name already has one */ + if (build != fullname && build[-1] != '/') + *build++ = '/'; + + /* append the filename */ + strcpy(build, filename); + } + + /* if the file exists here, then return the name */ + if (access(fullname, F_OK) >= 0) + return fullname; + } while (*pathlist++ == ':'); + + /* not found */ + return NULL; +} + + +/* load annotation attributes */ +static void loadannot(filename) + char *filename; /* name of file containing annotation info */ +{ + FILE *fp; /* used for scanning the annotation info */ + char buf[1000];/* a line from the file */ + char *name; /* pointer to an annotation name in buf */ + attrib_t attrib;/* the attribute flags */ + int lnum; /* line number */ + annot_t *annot; /* an annotation struct */ + annot_t *all; /* the "all" pseudo-annotation */ + char *str; + int i; + + /* open the file */ + fp = fopen(filename, "r"); + if (!fp) + return; + + /* for each line... */ + lnum = 0; + while (fgets(buf, sizeof buf, fp)) + { + lnum++; + + /* skip leading whitespace */ + for (name = buf; isspace(*name); name++) + { + } + + /* skip if empty line or it starts with "#" */ + if (*name == '\0' || *name == '#') + continue; + + /* look for the ':' delimiting annotations from attributes */ + str = strchr(name, ':'); + if (!str) + { + fprintf(stderr, "elvgdb: %s line %d has no ':'\n", + filename, lnum); + continue; + } + *str++ = '\0'; + if (!*name) + { + fprintf(stderr, "elvgdb: %s line %d has no annotations\n", + filename, lnum); + continue; + } + + /* scan the attribute string... */ + for (attrib = (attrib_t)0, name = NULL; *str; str++) + { + /* did we reach the end of a name? */ + if (!isalnum(*str) && name) + { + /* terminate the name */ + *str = '\0'; + + /* see if we recognize it */ + for (i = 0; i < QTY(attribname) && strcmp(attribname[i].name, name); i++) + { + } + if (i < QTY(attribname)) + attrib |= attribname[i].attrib; + else + { + fprintf(stderr, "elvgdb: unknown attribute \"%s\" in file \"%s\" line %d\n", name, filename, lnum); + } + + /* reset for next */ + name = NULL; + } + + /* are we starting a new attribute name? */ + if (!name && isalnum(*str)) + name = str; + } + /* NOTE: Lucky for us, fgets() keeps the newline at the end of + * an input line. This means that the last attribute name is + * always followed by a newline, if nothing else, so we don't + * need to worry about the case of dangling attribute name. + * By the time we reach this point, name=NULL. + */ + + /* Scan the annotation string, and add these attributes to + * each annotation. + */ + str = buf - 1; + name = NULL; + do + { + /* next character */ + str++; + + /* end of a name? */ + if (name && !isalnum(*str) && *str != '-') + { + /* find the annotation, or add it */ + i = *str; + *str = '\0'; + annot = findannot(name); + if (!annot) + { + annot = (annot_t *)malloc(sizeof(annot_t) + strlen(name)); + strcpy(annot->name, name); + annot->attrib = (attrib_t)0; + annot->next = annotlist; + annotlist = annot; + } + *str = (char)i; + + /* merge new attributes with any previous */ + if (attrib & EG_COLOR) + annot->attrib &= ~(EG_COLORMASK|EG_COLOR); + annot->attrib |= attrib; + + /* reset for next name */ + name = NULL; + } + + /* start of a name? */ + if (!name && isalnum(*str)) + name = str; + + } while (*str); + } + + /* close the file*/ + fclose(fp); + + /* if there's an "all" annotation, merge its attributes */ + all = findannot("elvgdb-all"); + if (all) + { + for (annot = annotlist; annot; annot = annot->next) + { + /* skip the pseudo-annotations */ + if (!strncmp(annot->name, "elvgdb-", 7)) + continue; + + /* merge the attributes */ + if (annot->attrib & EG_COLOR) + annot->attrib |= all->attrib & ~EG_COLORMASK; + else + annot->attrib |= all->attrib; + } + } + + /* if there's a "default" annotation, then remember its attributes */ + annot = findannot("elvgdb-default"); + if (annot) + defattrib = annot->attrib; + + /* if there's a "trace" annotation, then remember its attributes */ + annot = findannot("elvgdb-trace"); + if (annot) + traceattrib = annot->attrib; +} + +/* Fork gdb, with its stdout coming back to elvgdb through a pipe */ +static FILE *opengdb(argc, argv) + int argc; /* number of args */ + char **argv; /* values of the args */ +{ + int r0w1[2]; /* the pipe fd's */ + char **newargv; /* tweaked copy of args */ + int i; + + /* create a pipe */ + if (pipe(r0w1) < 0) + return NULL; + + /* fork gdb */ + switch (fork()) + { + case -1: /* error */ + close(r0w1[0]); + close(r0w1[1]); + return NULL; + + case 0: /* child */ + /* close the read end of the pipe */ + close(r0w1[0]); + + /* redirect stdout/stderr to go to the write end of the pipe */ + close(1); + dup(r0w1[1]); + close(2); + dup(r0w1[1]); + close(r0w1[1]); + + /* create a copy of argv with "--annotate=2" inserted */ + newargv = (char **)malloc((argc + 2) * sizeof(char *)); + if (!newargv) + return NULL; + newargv[0] = "gdb"; + newargv[1] = "--annotate=2"; + for (i = 1; i < argc; i++) + newargv[i + 1] = argv[i]; + newargv[argc + 1] = NULL; + + /* execute gdb */ + execvp("gdb", newargv); + exit(1); + /*NOTREACHED*/ + + default: /* parent */ + /* close the write end of the pipe */ + close(r0w1[1]); + + /* use buffering for the read end */ + return fdopen(r0w1[0], "r"); + } +} + +/* close the pipe created by opengdb, and return gdb's exit code */ +static int closegdb(fromgdb) + FILE *fromgdb; /* pipe that was opened by opengdb */ +{ + int status; + + /* close the socket */ + fclose(fromgdb); + + /* get gdb's exit code */ + wait(&status); + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else + return 1; +} + + +/* alter the highlighting for a given annotation attribute */ +static void highlight(attrib) + attrib_t attrib; /* attributes, including highlight info */ +{ + static int highlighted; + + /* maybe end previous attributes */ + if (highlighted && !(attrib & EG_HIGHLIGHT)) + { + printf("\033[m"); + highlighted = 0; + } + + /* maybe start new attributes */ + if (attrib & (EG_COLOR|EG_BOLD|EG_UNDERLINE)) + { + if (attrib & EG_COLOR) + printf("\033[3%d%s%sm", attrib & EG_COLORMASK, + attrib & EG_BOLD ? ";1" : "", + attrib & EG_UNDERLINE ? ";4": ""); + else if (attrib & EG_BOLD) + printf("\033[1%sm", attrib & EG_UNDERLINE ? ";4" : ""); + else + printf("\033[4m"); + highlighted = 1; + } +} + +static attrib_t doannot(elviswin, name, args) + Window elviswin;/* where to send elvis commands */ + char *name; /* name of the annotation */ + char *args; /* any other text in the annotation itself */ +{ + annot_t *annot; + attrib_t attrib; + int i; + + /* look up this annotation's attributes */ + annot = findannot(name); + attrib = annot ? annot->attrib : defattrib; + + /* if supposed to guard against multiple messages, and this has been + * seen before, then don't start a message this time. + */ + if (attrib & EG_LIMIT) + { + if (annot->sent) + attrib &= ~EG_FROMGDB; + else + annot->sent = 1; + } + + /* maybe trace this annotation */ + if (attrib & EG_TRACE) + { + highlight(traceattrib); + printf("[%s]", name); + } + + /* maybe remember this annotation name for table records */ + if (attrib & EG_TABLE) + { + /* maybe trace */ + if (traceattrib & EG_TABLE) + { + highlight(traceattrib); + printf("(TABLE-BEGIN)"); + } + + strcpy(tablename, name); + } + + /* maybe start a new :fromgdb command */ + if (attrib & EG_FROMGDB) + { + /* maybe trace it */ + if (traceattrib & EG_FROMGDB) + { + highlight(traceattrib); + printf("(fromgdb %s)", tablename); + } + + if (secret) + sprintf(toelvis, "\"%ld\"fromgdb %s", secret, name); + else + sprintf(toelvis, "fromgdb %s", name); + } + + /* can't use "args" and "text" unless toelvis is filling up */ + if (!*toelvis) + attrib &= ~(EG_ARGS | EG_TEXT); + + /* maybe append args to :toelvis command */ + if ((attrib & EG_ARGS) && *args) + { + strcat(toelvis, " "); + strcat(toelvis, args); + } + + /* maybe send :fromgdb command to elvis */ + if ((attrib & (EG_TOELVIS|EG_RECORD)) && *toelvis) + { + /* maybe trace the messages */ + if (traceattrib & EG_TOELVIS) + { + highlight(traceattrib); + printf("<%s>", toelvis); + } + + /* add a newline to mark the end of the command */ + strcat(toelvis, "\n"); + + /* send the command to elvis */ + XChangeProperty(display, elviswin, elvis_server, + XA_STRING, 8, PropModeAppend, + (unsigned char *)toelvis, strlen(toelvis)); + + /* clobber buf */ + *toelvis = '\0'; + } + + /* maybe start a new record */ + if ((attrib & EG_RECORD) && *tablename) + { + /* maybe trace it */ + if (traceattrib & EG_FROMGDB) + { + highlight(traceattrib); + printf("(fromgdb %s)", tablename); + } + + if (secret) + sprintf(toelvis, "\"%ld\"fromgdb %s",secret, tablename); + else + sprintf(toelvis, "fromgdb %s", tablename); + } + + + /* if this is tablename with "-end", then clobber the tablename */ + i = strlen(tablename); + if (!strncmp(name, tablename, i) && !strcmp(name + i, "-end")) + { + /* maybe trace */ + if (traceattrib & EG_TABLE) + { + highlight(traceattrib); + printf("(TABLE-END)"); + } + + *tablename = '\0'; + } + + /* if this annotation has "server" attribute, and elvgdb-trace doesn't, + * then start watching for a "server " prefix on the command line. + */ + if ((attrib & EG_SERVER) && !(traceattrib & EG_SERVER)) + hideserver = "server "; + + /* we'll want a space before args of "text" */ + if ((attrib & EG_TEXT) && *toelvis) + { + buildtoelvis = toelvis + strlen(toelvis); + if (buildtoelvis[-1] != ' ') + *buildtoelvis++ = ' '; + } + + /* update attributes for this annotation */ + highlight(attrib); + + /* maybe flush stuff too */ + if (attrib & EG_FLUSH) + { + /* flush commands to elvis */ + XFlush(display); + + /* reset the "sent" flags for any annotations */ + for (annot = annotlist; annot; annot = annot->next) + annot->sent = 0; + } + + /* The EG_FLUSH, EG_TEXT, and EG_SERVER attributes all affect the + * handling of text between annotations. + */ + return attrib; +} + +/* Read & process an annotation line. We assume the + * sequence has already been read. Return a boolean value indicating whether + * text should be flushed for subsequent chars. + */ +static attrib_t annotation(fromgdb, elviswin) + FILE *fromgdb; /* pipe that was opened by opengdb */ + Window elviswin; /* window of elvis server */ +{ + char name[100]; + char args[1000]; + int ch; + unsigned i; + + /* read the name */ + for (i = 0; + i < sizeof name - 1 && (ch = getc(fromgdb)) != EOF && !isspace(ch); + i++) + name[i] = ch; + name[i] = '\0'; + + /* if args, then read them too */ + if (ch != '\n' && ch != EOF) + { + for (i = 0; + i < sizeof args - 1 && (ch = getc(fromgdb)) != EOF + && ch != '\n'; + i++) + args[i] = ch; + args[i] = '\0'; + } + else + args[0] = '\0'; + + /* convert "field n" to "fieldn" */ + if (!strcmp(name, "field") && isdigit(args[0])) + { + strcat(name, args); + *args = '\0'; + } + + /* if not end of line yet, then keep reading */ + while (ch != EOF && ch != '\n') + ch = getc(fromgdb); + + /* handle it */ + return doannot(elviswin, name, args); +} + +/* write a character to stdout */ +static void echoch(attrib, ch) + attrib_t attrib;/* attributes, especially EG_FLUSH */ + int ch; /* character to write */ +{ + /* detect "server" command prefix */ + if (hideserver != NULL && *hideserver != '\0') + { + if (ch == *hideserver) + { + hideserver++; + if (*hideserver == '\0') + { + fputs("\b\b\b\b\b\b \b\b\b\b\b\b", stdout); + } + } + else + { + hideserver = NULL; + } + } + + /* echo the char to the user */ + if (hideserver == NULL || *hideserver != '\0') + { + putchar(ch); + + /* flush immediately, if prompting from user */ + if ((attrib & EG_FLUSH) || ch == '\n') + fflush(stdout); + } + + /* maybe add to :fromgdb command */ + if ((attrib & EG_TEXT) && buildtoelvis < &toelvis[sizeof toelvis + 2]) + { + if (isgraph(ch)) + *buildtoelvis++ = ch; + else if (buildtoelvis[-1] != ' ') + *buildtoelvis++ = ' '; + *buildtoelvis = '\0'; + } +} + +/* run gdb, and watch for annotations in its output */ +static int rungdb(argc, argv) + int argc; /* number of args */ + char **argv; /* values of the args */ +{ + FILE *fromgdb; + attrib_t attrib = (attrib_t)0; + int ch; + char *str; + Atom type; + unsigned long ul, dummy; + int format; + unsigned char *data; + Window elviswin; + + /* open a connection to the X server */ + openx(); + + /* find the elvis server's window */ + XGetWindowProperty(display, root, elvis_server, 0L, 1L, False, + XA_WINDOW, &type, &format, &ul, &dummy, &data); + if (ul != 1 || type != XA_WINDOW || format != 32) + { + fprintf(stderr, "elvgdb: warning: can't find elvis\n"); + elviswin = None; + } + else + { + elviswin = *(Window *)data; + XFree(data); + } + + /* store elvgdb's xterm windowid as the elvgdb server attribute */ + str = getenv("WINDOWID"); + if (!str) + { + fprintf(stderr, "elvgdb: warning: -t only possible when run in an xterm (with $WINDOWID set)\n"); + } + else + { + ul = strtol(str, NULL, 0); + XChangeProperty(display, root, elvgdb_server, XA_WINDOW, 32, + PropModeReplace, (unsigned char *)&ul, 1); + XFlush(display); + } + + /* did elvis share its secret code for bypassing security? */ + str = getenv("secret"); + if (str) + secret = strtol(str, NULL, 0); + + /* load annotation attributes */ + str = getenv("ELVISPATH"); + if (!str) + str = OSLIBPATH; + str = searchpath(str, "elvgdb.ini"); + if (!str) + fprintf(stderr, "elvgdb: Warning: could not find \"elvgdb.ini\" in $ELVISPATH\n"); + else + loadannot(str); + + /* simulate an "elvgdb-init" annotation before gdb starts */ + doannot(elviswin, "elvgdb-init", ""); + + /* if couldn't open gdb then fail */ + fromgdb = opengdb(argc, argv); + if (!fromgdb) + { + doannot(elviswin, "elvgdb-term", ""); + perror("elvgdb"); + return 2; + } + + /* ignore termios signals */ + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + + /* process gdb's output */ + while ((ch = getc(fromgdb)) != EOF) + { + /* watch for annotation lines */ + if (ch == '\n') + { + if ((ch = getc(fromgdb)) == ELVCTRL('Z')) + { + if ((ch = getc(fromgdb)) == ELVCTRL('Z')) + { + attrib = annotation(fromgdb, elviswin); + if (attrib & EG_FLUSH) + fflush(stdout); + } + else + { + echoch(attrib, '\n'); + echoch(attrib, ELVCTRL('Z')); + ungetc(ch, fromgdb); + } + } + else + { + echoch(attrib, '\n'); + ungetc(ch, fromgdb); + } + } + else + { + echoch(attrib, ch); + } + } + + /* get the exit status */ + format = closegdb(fromgdb); + + /* simulate a "elvgdb-term" annotation after gdb terminates */ + doannot(elviswin, "elvgdb-term", ""); + + /* remove the ELVGDB_SERVER attribute from the root window */ + XDeleteProperty(display, root, elvgdb_server); + XFlush(display); + + /* close the pipe, return gdb's exit code */ + return format; +} + +static Window findgdb() +{ + Atom type; + unsigned long ul, dummy; + int format; + unsigned char *data; + Window elvgdbwin, wroot, wparent, *wchild; + unsigned int nchild, scan, largest; + unsigned long scanpixels, largestpixels; + XWindowAttributes wattr; + + /* find elvgdb's xterm */ + XGetWindowProperty(display, root, elvgdb_server, 0L, 1L, False, + XA_WINDOW, &type, &format, &ul, &dummy, &data); + if (ul != 1 || type != XA_WINDOW || format != 32) + { + fprintf(stderr, "elvgdb: warning: can't find elvgdb\n"); + return None; + } + elvgdbwin = *(Window *)data; + XFree(data); + + /* We actually need to paste into the vt100 widget within that window. + * Fetch the information about its children. + */ + if (!XQueryTree(display, elvgdbwin, &wroot, &wparent, &wchild, &nchild)) + { + fprintf(stderr, "elvgdb: the elvgdb xterm seems weird -- no widgets\n"); + return None; + } + + /* scan for the largest child window */ + for (largestpixels = 0, scan = 0; scan < nchild; scan++) + { + /* get info on this window */ + if (!XGetWindowAttributes(display, wchild[scan], &wattr)) + continue; + + scanpixels = wattr.width * wattr.height; + if (largestpixels == 0 || scanpixels > largestpixels) + { + largest = scan; + largestpixels = scanpixels; + } + } + if (largestpixels == 0) + { + fprintf(stderr, "elvgdb: the elvgdb xterm seems weird -- widgets are untouchable\n"); + wroot = None; + } + else + wroot = wchild[largest]; + XFree(wchild); + return wroot; +} + +static int tellgdb(argc, argv) + int argc; /* number of args */ + char **argv; /* values of the args */ +{ + Window gdbvt100, win; + XEvent event, notify; + int i, len; + char *buf; + + /* count the combined arg length */ + len = 1; + i = 2; + if (argv[1][2] != '\0') + len += strlen(&argv[1][2]); + if (len == 1 && i < argc) + len = 0; + for (; i < argc; i++) + len += strlen(argv[i]) + 1; + if (len == 1) + { + fprintf(stderr, "-t requires text\n"); + return 2; + } + + /* combine the args, with spaces between them and a CR at end. */ + buf = (char *)malloc(len + 1); + i = 2; + buf[0] = '\0'; + if (argv[1][2] != '\0') + { + strcpy(buf, &argv[1][2]); + } + for (; i < argc; i++) + { + if (*buf) + strcat(buf, " "); + strcat(buf, argv[i]); + } + strcat(buf, "\r"); + len = strlen(buf); + + /* open a connect to the X server */ + openx(); + + gdbvt100 = findgdb(); + if (gdbvt100 == None) + { + /* error message already given */ + return 2; + } + + /* Create a window but don't map it. We need a window that we can + * use to receive SelectionRequest events on. + */ + win = XCreateSimpleWindow(display, root, 0, 0, 1, 1, 0, 0L, 0L); + + /* claim the selection */ + XSetSelectionOwner(display, XA_PRIMARY, win, CurrentTime); + if (XGetSelectionOwner(display, XA_PRIMARY) != win) + { + fprintf(stderr, "Could not claim X selection\n"); + return 2; + } + + /* simulate a middle-click on elvgdb's xterm */ + memset(&event, 0, sizeof event); + event.xbutton.type = ButtonPress; + event.xbutton.display = display; + event.xbutton.window = gdbvt100; + event.xbutton.root = root; + event.xbutton.subwindow = None; + event.xbutton.state = Button2Mask|ShiftMask; + event.xbutton.button = Button2; + event.xbutton.same_screen = True; + XSendEvent(display, gdbvt100, True, ButtonPressMask, &event); + event.xbutton.type = ButtonRelease; + event.xbutton.state = ShiftMask; + XSendEvent(display, gdbvt100, True, ButtonReleaseMask, &event); + + /* wait for an event -- expect SelectionRequest */ + XNextEvent(display, &event); + if (event.type != SelectionRequest) + { + fprintf(stderr, "Got event.type=%d instead of SelectionRequest\n", event.type); + return 2; + } + + /* fill in most fields of the SelectionNotify event */ + memset(¬ify, 0, sizeof notify); + notify.type = SelectionNotify; + notify.xselection.requestor= event.xselectionrequest.requestor; + notify.xselection.selection= event.xselectionrequest.selection; + notify.xselection.target = event.xselectionrequest.target; + notify.xselection.time = event.xselectionrequest.time; + notify.xselection.property = event.xselectionrequest.property; + + /* store the selection's value into the property */ + XChangeProperty(display, + event.xselectionrequest.requestor, + event.xselectionrequest.property, + event.xselectionrequest.target, + 8, PropModeReplace, + (unsigned char *)buf, len); + + /* notify the requestor */ + XSendEvent(display, notify.xselection.requestor, False, 0L, ¬ify); + XFlush(display); + + return 0; +} + +int main(argc, argv) + int argc; /* number of args */ + char **argv; /* values of the args */ +{ + int exitcode; + + if (argc == 2 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "?"))) + { + printf("Usage: elvgdb [gdbargs] run gdb, and communicate with elvis\n"); + printf(" or: elvgdb -t commandline paste commandline into elvgdb's xterm\n"); + exitcode = 0; + } + else if (argc == 2 && (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-v"))) + { + printf("elvgdb (elvis) %s\n", VERSION); + exitcode = 0; + } + else if (argc >= 2 && !strncmp(argv[1], "-t", 2)) + { + exitcode = tellgdb(argc, argv); + } + else + { + exitcode = rungdb(argc, argv); + } + + return exitcode; +} diff -urN elvis-2.2_0/elvis.h elvis-2.2_1/elvis.h --- elvis-2.2_0/elvis.h 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/elvis.h 2004-03-26 22:35:29 +0100 @@ -48,6 +48,7 @@ #define TRACE_BUF "Elvis map log" #define BBROWSE_BUF "Elvis buffer list" #define EQUALTILDE_BUF "Elvis equal tilde" +#define PERSIST_BUF "Elvis persist" /* Names of files that store default contents of buffers */ #define INIT_FILE "elvis.ini" /* executed before first file is loaded */ diff -urN elvis-2.2_0/ex.c elvis-2.2_1/ex.c --- elvis-2.2_0/ex.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/ex.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_ex[] = "$Id: ex.c,v 2.226 2003/10/19 23:13:33 steve Exp $"; +char id_ex[] = "$Id: ex.c,v 2.244 2004/03/26 21:33:27 steve Exp $"; #endif #if USE_PROTOTYPES @@ -39,6 +39,7 @@ /* These are the possible arguments for a command. These may be combined * via the bitwise OR operator to describe arbitrary combinations of these. */ +#define a_None 0x00000000L /* no arguments */ #define a_Line 0x00000001L /* single line specifier */ #define a_Range 0x00000002L /* range of lines */ #define a_Multi 0x00000004L /* command character may be stuttered */ @@ -61,24 +62,25 @@ /* The following values indicate the default values of arguments */ #define d_All 0x00080000L /* default range is all lines */ -#define d_2Lines 0x00100000L /* default range is two lines (for :join) */ -#define d_None 0x00180000L /* default range is no lines (else current line) */ +#define d_None 0x00100000L /* default range is no lines (else current line) */ #define d_LnMask 0x00180000L /* mask value for extracting line defaults */ #define d_File 0x00200000L /* default file is current file (else no default) */ /* The following indicate other quirks of commands */ +#define q_None 0x0000L /* no quirks */ #define q_Unsafe 0x0001L /* command can't be executed if "safer" */ #define q_FileUnsafe 0x0002L /* command can't take filename if "safer" */ -#define q_Restricted 0x0004L /* "Unsafe" flags only apply if "restricted" */ -#define q_Autop 0x0008L /* autoprint current line */ -#define q_Zero 0x0010L /* allow Target or Line to be 0 */ -#define q_Exrc 0x0020L /* command may be run in a .exrc file */ -#define q_Undo 0x0040L /* save an "undo" version before this command */ -#define q_Custom 0x0080L /* save options/maps after command */ -#define q_Ex 0x0100L /* only allowed in ex mode, not vi's <:> cmd */ -#define q_CtrlV 0x0200L /* use ^V for quote char, instead of \ */ -#define q_MayQuit 0x0400L /* may cause window to disappear */ -#define q_SwitchB 0x0800L /* may move cursor to a different buffer */ +#define q_Restricted 0x0004L /* command can't be executed if "restricted" */ +#define q_FileRestr 0x0008L /* command can't take filename if "restricted"*/ +#define q_Autop 0x0010L /* autoprint current line */ +#define q_Zero 0x0020L /* allow Target or Line to be 0 */ +#define q_Exrc 0x0040L /* command may be run in a .exrc file */ +#define q_Undo 0x0080L /* save an "undo" version before this command */ +#define q_Custom 0x0100L /* save options/maps after command */ +#define q_Ex 0x0200L /* only allowed in ex mode, not vi's <:> cmd */ +#define q_CtrlV 0x0400L /* use ^V for quote char, instead of \ */ +#define q_MayQuit 0x0800L /* may cause window to disappear */ +#define q_SwitchB 0x1000L /* may move cursor to a different buffer */ /* This array maps ex command names to command codes. The order in which @@ -108,30 +110,30 @@ } cmdnames[] = { /* cmd name cmd code function flags (describing arguments) quirks */ -/*! */{"!", EX_BANG, ex_bang, a_Range | a_Cmds | d_None, q_Exrc | q_Unsafe | q_Undo }, -/*# */{"#", EX_NUMBER, ex_print, a_Range | a_Count | a_Pflag }, +/*! */{"!", EX_BANG, ex_bang, a_Range | a_Cmds | d_None, q_Exrc | q_Unsafe | q_Restricted | q_Undo }, +/*# */{"#", EX_NUMBER, ex_print, a_Range | a_Count | a_Pflag, q_None }, /*& */{"&", EX_SUBAGAIN, ex_substitute, a_Range | a_Rhs, q_Undo }, /*< */{"<", EX_SHIFTL, ex_shift, a_Range | a_Multi | a_Bang | a_Count, q_Autop | q_Undo }, /*= */{"=", EX_EQUAL, ex_file, a_Range }, /*> */{">", EX_SHIFTR, ex_shift, a_Range | a_Multi | a_Bang | a_Count, q_Autop | q_Undo }, #ifdef FEATURE_MISC -/*@ */{"@", EX_AT, ex_at, a_Buffer }, +/*@ */{"@", EX_AT, ex_at, a_Buffer, q_None }, #endif -/*N */{"Next", EX_PREVIOUS, ex_next, a_Bang, q_Unsafe | q_SwitchB }, +/*N */{"Next", EX_PREVIOUS, ex_next, a_Bang, q_SwitchB }, /*" */{"\"", EX_COMMENT, ex_comment, a_Cmds, q_Exrc }, /*a */{"append", EX_APPEND, ex_append, a_Line | a_Bang | a_Cmds | a_Text, q_Zero | q_Undo | q_Ex }, -/*ab */{"abbreviate", EX_ABBR, ex_map, a_Bang | a_Lhs | a_Rhs, q_Exrc|q_Custom|q_Unsafe|q_CtrlV}, +/*ab */{"abbreviate", EX_ABBR, ex_map, a_Bang | a_Lhs | a_Rhs, q_Exrc | q_Custom | q_Unsafe | q_Restricted | q_CtrlV}, #ifdef FEATURE_MISC -/*al */{"all", EX_ALL, ex_all, a_Bang | a_Cmds, q_Exrc }, +/*al */{"all", EX_ALL, ex_all, a_Bang | a_Cmds, q_None }, #endif #ifdef FEATURE_ALIAS -/*ali */{"alias", EX_ALIAS, ex_alias, a_Bang | a_Lhs | a_Cmds, q_Exrc | q_Unsafe | q_Custom }, +/*ali */{"alias", EX_ALIAS, ex_alias, a_Bang | a_Lhs | a_Cmds, q_Exrc | q_Unsafe | q_Restricted | q_Custom }, #endif -/*ar */{"args", EX_ARGS, ex_args, a_Files, q_Exrc | q_Unsafe }, +/*ar */{"args", EX_ARGS, ex_args, a_Files, q_Exrc | q_FileRestr }, #ifdef FEATURE_AUTOCMD -/*au */{"autocmd", EX_AUTOCMD, ex_autocmd, a_Bang | a_Cmds, q_Exrc | q_Unsafe | q_Custom }, +/*au */{"autocmd", EX_AUTOCMD, ex_autocmd, a_Bang | a_Cmds, q_Exrc | q_Unsafe | q_Restricted | q_Custom }, /*aue */{"auevent", EX_AUEVENT, ex_auevent, a_Bang | a_Rhs, q_Exrc | q_Custom }, -/*aug */{"augroup", EX_AUGROUP, ex_augroup, a_Bang | a_Lhs, q_Exrc | q_Unsafe }, +/*aug */{"augroup", EX_AUGROUP, ex_augroup, a_Bang | a_Lhs, q_Exrc }, #endif #ifdef FEATURE_MISC /*b */{"buffer", EX_BUFFER, ex_buffer, a_Bang | a_Rhs, q_SwitchB }, @@ -144,21 +146,21 @@ /*bre */{"break", EX_BREAK, ex_map, a_Bang | a_Rhs, q_CtrlV }, #endif /*c */{"change", EX_CHANGE, ex_append, a_Range | a_Bang | a_Count | a_Text, q_Undo | q_Ex }, -/*cha */{"chdir", EX_CD, ex_cd, a_Bang | a_File, q_Exrc | q_Unsafe }, +/*cha */{"chdir", EX_CD, ex_cd, a_Bang | a_File, q_Exrc | q_Unsafe | q_Restricted}, #ifdef FEATURE_SPELL /*che */{"check", EX_CHECK, ex_check, a_Bang | a_Rhs, q_Exrc | q_Custom }, #endif #ifdef FEATURE_REGION -/*chr */{"chregion", EX_CHREGION, ex_region, a_Range | a_Rhs | a_Lhs }, +/*chr */{"chregion", EX_CHREGION, ex_region, a_Range | a_Rhs | a_Lhs, q_None }, #endif #ifdef FEATURE_CALC /*ca */{"calculate", EX_CALC, ex_comment, a_Cmds, q_Exrc }, /*cas */{"case", EX_CASE, ex_case, a_Lhs | a_Cmds, q_Exrc }, #endif #ifdef FEATURE_MAKE -/*cc */{"cc", EX_CC, ex_make, a_Bang | a_Rhs, q_Unsafe | q_SwitchB }, +/*cc */{"cc", EX_CC, ex_make, a_Bang | a_Rhs, q_Unsafe | q_Restricted | q_SwitchB}, #endif -/*cd */{"cd", EX_CD, ex_cd, a_Bang | a_File, q_Exrc | q_Unsafe }, +/*cd */{"cd", EX_CD, ex_cd, a_Bang | a_File, q_Exrc | q_Unsafe | q_Restricted}, /*cl */{"close", EX_CLOSE, ex_xit, a_Bang, q_MayQuit }, /*co */{"copy", EX_COPY, ex_move, a_Range | a_Target | a_Pflag, q_Autop | q_Undo }, /*col */{"color", EX_COLOR, ex_color, a_Bang | a_Lhs | a_Rhs, q_Exrc | q_Custom }, @@ -174,18 +176,18 @@ #ifdef FEATURE_AUTOCMD /*doa */{"doautocmd", EX_DOAUTOCMD, ex_doautocmd, a_Rhs, q_Exrc }, #endif -/*e */{"edit", EX_EDIT, ex_edit, a_Bang | a_Plus | a_File | d_File, q_FileUnsafe | q_SwitchB }, +/*e */{"edit", EX_EDIT, ex_edit, a_Bang | a_Plus | a_File | d_File, q_FileRestr | q_SwitchB }, /*ec */{"echo", EX_ECHO, ex_comment, a_Rhs, q_Exrc }, /*el */{"else", EX_ELSE, ex_then, a_Cmds, q_Exrc }, #ifdef FEATURE_MAKE -/*er */{"errlist", EX_ERRLIST, ex_errlist, a_Bang | a_File | a_Filter, q_SwitchB|q_FileUnsafe|q_Restricted}, +/*er */{"errlist", EX_ERRLIST, ex_errlist, a_Bang | a_File | a_Filter, q_SwitchB | q_Restricted }, #endif /*erro*/{"error", EX_ERROR, ex_message, a_Rhs, q_Exrc }, #ifdef FEATURE_CALC /*ev */{"eval", EX_EVAL, ex_if, a_Cmds, q_Exrc }, #endif -/*ex */{"ex", EX_EDIT, ex_edit, a_Bang | a_Plus | a_File | d_File, q_FileUnsafe | q_SwitchB }, -/*f */{"file", EX_FILE, ex_file, a_Bang | a_File, q_FileUnsafe }, +/*ex */{"ex", EX_EDIT, ex_edit, a_Bang | a_Plus | a_File | d_File, q_FileRestr | q_SwitchB }, +/*f */{"file", EX_FILE, ex_file, a_Bang | a_File, q_FileUnsafe | q_FileRestr }, #ifdef FEATURE_FOLD /*fo */{"fold", EX_FOLD, ex_fold, a_Range | a_Bang | a_Rhs }, #endif @@ -202,10 +204,10 @@ #ifdef FEATURE_CALC /*if */{"if", EX_IF, ex_if, a_Cmds, q_Exrc }, #endif -/*j */{"join", EX_JOIN, ex_join, a_Range | a_Bang | a_Count | d_2Lines, q_Autop | q_Undo }, +/*j */{"join", EX_JOIN, ex_join, a_Range | a_Bang | a_Count, q_Autop | q_Undo }, /*k */{"k", EX_MARK, ex_mark, a_Line | a_Lhs }, /*l */{"list", EX_LIST, ex_print, a_Range | a_Count | a_Pflag }, -/*la */{"last", EX_LAST, ex_next, 0, q_Unsafe | q_SwitchB }, +/*la */{"last", EX_LAST, ex_next, 0, q_SwitchB }, #ifdef FEATURE_CALC /*le */{"let", EX_LET, ex_set, a_Bang | a_Cmds, q_Exrc | q_Custom }, #endif @@ -213,66 +215,72 @@ /*se */{"local", EX_LOCAL, ex_set, a_Rhs, q_Exrc }, #endif #ifdef FEATURE_LPR -/*lp */{"lpr", EX_LPR, ex_lpr, a_Range|a_Bang|a_Append|a_File|a_Filter|d_All, q_Unsafe }, +/*lp */{"lpr", EX_LPR, ex_lpr, a_Range|a_Bang|a_Append|a_File|a_Filter|d_All, q_Unsafe | q_Restricted }, #endif /*m */{"move", EX_MOVE, ex_move, a_Range | a_Target, q_Autop | q_Undo }, /*ma */{"mark", EX_MARK, ex_mark, a_Line | a_Lhs }, #ifdef FEATURE_MAKE -/*mak */{"make", EX_MAKE, ex_make, a_Bang | a_Rhs, q_Unsafe | q_SwitchB }, +/*mak */{"make", EX_MAKE, ex_make, a_Bang | a_Rhs, q_Unsafe | q_Restricted | q_SwitchB}, #endif -/*map */{"map", EX_MAP, ex_map, a_Bang | a_Rhs, q_Exrc|q_Custom|q_Unsafe|q_CtrlV}, +/*map */{"map", EX_MAP, ex_map, a_Bang | a_Rhs, q_Exrc | q_Custom | q_Unsafe | q_Restricted | q_CtrlV}, /*me */{"message", EX_MESSAGE, ex_message, a_Rhs, q_Exrc }, #ifdef FEATURE_MKEXRC -/*mk */{"mkexrc", EX_MKEXRC, ex_mkexrc, a_Bang | a_File, q_Unsafe }, +/*mk */{"mkexrc", EX_MKEXRC, ex_mkexrc, a_Bang | a_File, q_Unsafe | q_Restricted }, #endif -/*n */{"next", EX_NEXT, ex_next, a_Bang | a_Files, q_Unsafe | q_SwitchB }, +/*n */{"next", EX_NEXT, ex_next, a_Bang | a_Files, q_FileRestr | q_SwitchB }, #ifdef FEATURE_SPLIT -/*ne */{"new", EX_SNEW, ex_split }, +/*ne */{"new", EX_SNEW, ex_split, a_None, q_None }, #endif /*no */{"normal", EX_NORMAL, ex_display, a_Range | a_Bang | a_Cmds | d_None, q_Undo }, +#ifdef FEATURE_FOLD +/*nof */{"nofold", EX_NOFOLD, ex_fold, a_Range | a_Bang }, +#endif #ifdef FEATURE_HLSEARCH -/*noh */{"nohlsearch", EX_NOHLSEARCH, ex_nohlsearch }, +/*noh */{"nohlsearch", EX_NOHLSEARCH, ex_nohlsearch, a_None, q_None }, #endif -/*nu */{"number", EX_NUMBER, ex_print, a_Range | a_Count | a_Pflag }, -/*o */{"open", EX_OPEN, ex_edit, a_Bang | a_Plus | a_File, q_SwitchB | q_FileUnsafe }, -/*on */{"only", EX_ONLY, ex_qall, a_Bang | d_None }, -/*p */{"print", EX_PRINT, ex_print, a_Range | a_Count | a_Pflag }, -/*pre */{"previous", EX_PREVIOUS, ex_next, a_Bang, q_Unsafe | q_SwitchB }, +/*nu */{"number", EX_NUMBER, ex_print, a_Range | a_Count | a_Pflag, q_None }, +/*o */{"open", EX_OPEN, ex_edit, a_Bang | a_Plus | a_File, q_SwitchB | q_FileRestr }, +/*on */{"only", EX_ONLY, ex_qall, a_Bang | d_None, q_None }, +/*p */{"print", EX_PRINT, ex_print, a_Range | a_Count | a_Pflag, q_None }, +/*ph */{"phelp", EX_PHELP, ex_help, a_Lhs | a_Rhs, q_SwitchB }, +/*pre */{"previous", EX_PREVIOUS, ex_next, a_Bang, q_SwitchB }, /*pres*/{"preserve", EX_PRESERVE, ex_qall, d_None, q_MayQuit }, /*po */{"pop", EX_POP, ex_pop, a_Bang, q_SwitchB }, -/*pu */{"put", EX_PUT, ex_put, a_Line, q_Zero | a_Buffer | q_Undo }, -/*pus */{"push", EX_PUSH, ex_edit, a_Bang | a_Plus | a_File, q_FileUnsafe | q_SwitchB }, +/*pu */{"put", EX_PUT, ex_put, a_Line | a_Buffer, q_Zero | a_Buffer | q_Undo }, +/*pus */{"push", EX_PUSH, ex_edit, a_Bang | a_Plus | a_File, q_FileRestr | q_SwitchB }, /*q */{"quit", EX_QUIT, ex_xit, a_Bang, q_MayQuit }, /*qa */{"qall", EX_QALL, ex_qall, a_Bang, q_MayQuit }, -/*r */{"read", EX_READ, ex_read, a_Line | a_File | a_Filter, q_Zero|q_Undo|q_Unsafe|q_Restricted}, +/*r */{"read", EX_READ, ex_read, a_Line | a_File | a_Filter, q_Zero | q_Undo | q_Restricted }, /*red */{"redo", EX_REDO, ex_undo, a_Lhs, q_Autop }, #ifdef FEATURE_REGION -/*reg */{"region", EX_REGION, ex_region, a_Range | a_Lhs | a_Rhs }, +/*reg */{"region", EX_REGION, ex_region, a_Range | a_Lhs | a_Rhs, q_None }, #endif -/*rew */{"rewind", EX_REWIND, ex_next, a_Bang, q_Unsafe | q_SwitchB }, -/*s */{"substitute", EX_SUBSTITUTE, ex_substitute, a_Range|a_RegExp|a_RegSub|a_Rhs|a_Count|a_Pflag, q_Autop|q_Undo|q_Exrc }, +/*rew */{"rewind", EX_REWIND, ex_next, a_Bang, q_SwitchB }, +/*s */{"s", EX_SUBSTITUTE, ex_substitute, a_Range|a_RegExp|a_RegSub|a_Rhs|a_Count|a_Pflag, q_Autop|q_Undo|q_Exrc }, +/*su */{"suspend", EX_SUSPEND, ex_suspend, a_Bang, q_Unsafe | q_Restricted }, +/*sub */{"substitute", EX_SUBSTITUTE, ex_substitute, a_Range|a_RegExp|a_RegSub|a_Rhs|a_Count|a_Pflag, q_Autop|q_Undo|q_Exrc }, #ifdef FEATURE_SPLIT -/*sN */{"sNext", EX_SPREVIOUS, ex_next, 0, q_Unsafe }, -/*sa */{"sall", EX_SALL, ex_sall, 0 }, +/*sN */{"sNext", EX_SPREVIOUS, ex_next, 0, q_None }, +/*sa */{"sall", EX_SALL, ex_sall, 0, q_None }, #endif -/*saf */{"safely", EX_SAFELY, ex_then, a_Cmds, q_Exrc }, +/*saf */{"safely", EX_SAFELY, ex_then, a_Cmds, q_Exrc }, #if defined(FEATURE_SPLIT) && defined(FEATURE_MISC) -/*sbb */{"sbbrowse", EX_SBBROWSE, ex_buffer, a_Bang }, +/*sbb */{"sbbrowse", EX_SBBROWSE, ex_buffer, a_Bang, q_None }, #endif #ifdef FEATURE_BROWSE /*sbr */{"sbrowse", EX_SBROWSE, ex_browse, a_Bang|a_Rhs }, #endif /*se */{"set", EX_SET, ex_set, a_Bang | a_Rhs, q_Exrc | q_Custom }, -/*sh */{"shell", EX_SHELL, ex_suspend, 0, q_Unsafe }, +/*sh */{"shell", EX_SHELL, ex_suspend, 0, q_Unsafe | q_Restricted }, #ifdef FEATURE_SPLIT -/*sl */{"slast", EX_SLAST, ex_next, 0, q_Unsafe }, -/*sn */{"snext", EX_SNEXT, ex_next, a_Files, q_Unsafe }, -/*snew*/{"snew", EX_SNEW, ex_split, 0, q_Unsafe }, +/*sl */{"slast", EX_SLAST, ex_next, 0, q_None }, +/*sn */{"snext", EX_SNEXT, ex_next, a_Files, q_FileRestr }, +/*snew*/{"snew", EX_SNEW, ex_split, 0, q_None }, #endif -/*so */{"source", EX_SOURCE, ex_source, a_Bang | a_File, q_Exrc | q_Unsafe | q_Restricted }, +/*so */{"source", EX_SOURCE, ex_source, a_Bang | a_File | a_Filter, q_Exrc | q_Restricted }, #ifdef FEATURE_SPLIT -/*sp */{"split", EX_SPLIT, ex_split, a_Line | a_Plus | a_File | a_Filter, q_FileUnsafe }, -/*sr */{"srewind", EX_SREWIND, ex_next, a_Bang, q_Unsafe }, +/*sp */{"split", EX_SPLIT, ex_split, a_Line | a_Plus | a_File | a_Filter, q_FileRestr }, +/*sr */{"srewind", EX_SREWIND, ex_next, a_Bang, q_None }, #endif /*st */{"stop", EX_STOP, ex_suspend, a_Bang, q_Unsafe | q_Restricted }, #ifdef FEATURE_SPLIT @@ -281,7 +289,6 @@ #ifdef FEATURE_MISC /*stac*/{"stack", EX_STACK, ex_stack, d_None }, #endif -/*su */{"suspend", EX_SUSPEND, ex_suspend, a_Bang, q_Unsafe | q_Restricted }, #ifdef FEATURE_CALC /*sw */{"switch", EX_SWITCH, ex_switch, a_Cmds, q_Exrc }, #endif @@ -306,8 +313,8 @@ #endif /*v */{"vglobal", EX_VGLOBAL, ex_global, a_Range|a_Bang|a_RegExp|a_Cmds|d_All, q_Undo }, /*ve */{"version", EX_VERSION, ex_version, 0, q_Exrc }, -/*vi */{"visual", EX_VISUAL, ex_edit, a_Bang | a_Plus | a_File, q_FileUnsafe | q_SwitchB }, -/*w */{"write", EX_WRITE, ex_write, a_Range|a_Bang|a_Append|a_File|a_Filter|d_All, q_Unsafe }, +/*vi */{"visual", EX_VISUAL, ex_edit, a_Bang | a_Plus | a_File, q_FileRestr | q_SwitchB }, +/*w */{"write", EX_WRITE, ex_write, a_Range|a_Bang|a_Append|a_File|a_Filter|d_All|d_File, q_Unsafe | q_FileRestr }, /*wa */{"warning", EX_WARNING, ex_message, a_Rhs, q_Exrc }, #ifdef FEATURE_CALC /*wh */{"while", EX_WHILE, ex_while, a_Cmds, q_Exrc }, @@ -318,10 +325,10 @@ /*wn */{"wnext", EX_WNEXT, ex_next, a_Bang, q_SwitchB }, #ifdef FEATURE_SPELL /*wo */{"words", EX_WORDS, ex_check, a_Bang | a_Rhs, q_Exrc | q_Custom }, -/*wordf*/{"wordfile", EX_WORDFILE, ex_wordfile, a_Bang | a_Files, q_Exrc|q_Custom|q_FileUnsafe|q_Restricted}, +/*wordf*/{"wordfile", EX_WORDFILE, ex_wordfile, a_Bang | a_Files, q_Exrc | q_Custom | q_FileRestr }, #endif -/*wq */{"wquit", EX_WQUIT, ex_xit, a_Bang | a_File | d_File, q_FileUnsafe | q_MayQuit }, -/*x */{"xit", EX_XIT, ex_xit, a_Bang | a_File , q_FileUnsafe | q_MayQuit }, +/*wq */{"wquit", EX_WQUIT, ex_xit, a_Bang | a_File | d_File, q_Unsafe | q_FileRestr | q_MayQuit }, +/*x */{"xit", EX_XIT, ex_xit, a_Bang | a_File , q_Unsafe | q_FileRestr | q_MayQuit }, /*y */{"yank", EX_YANK, ex_delete, a_Range | a_Buffer | a_Count }, #ifdef FEATURE_MISC /*z */{"z", EX_Z, ex_z, a_Line | a_Rhs }, @@ -817,6 +824,87 @@ lnum = o_buflines(markbuffer(&xinf->defaddr)); break; +#ifdef FEATURE_MISC + case '=': + /* if followed immediately by a letter or '(' then it is used + * as a computed address. + */ + if (!scannext(refp)) + return ElvFalse; + if (**refp == '(' || elvalpha(**refp)) + { + CHAR *expr, *value; + int nest; + CHAR string; + + /* collect chars of the expression */ + expr = NULL; + if (**refp == '(') + { + /* collect to matching ')' */ + for (nest = 1, string = '\0'; + nest > 0 && **refp && **refp != '\n'; + (*refp)++) + { + /* append char to expression */ + buildCHAR(&expr, **refp); + + /* recognize nested () */ + if (!string) + { + switch (**refp) + { + case '\'': + case '"': + string = **refp; + break; + + case '(': + nest++; + break; + + case ')': + nest--; + break; + } + } + else if (**refp == string) + string = '\0'; + else if (**refp == '\\' && (*refp)[1] == string) + (*refp)++; + } + } + else + { + /* collect chars of option name */ + while (elvalnum(**refp)) + { + buildCHAR(&expr, **refp); + (*refp)++; + } + } + + /* evaluate the expression */ + value = calculate(expr, NULL, CALC_ALL); + safefree(expr); + if (!value) + /* error msg already given */ + return ElvFalse; + + /* sanity checks */ + if (!calcnumber(value) + || (lnum = CHAR2long(value)) < 0 + || lnum > o_buflines(markbuffer(&xinf->defaddr))) + { + msg(MSG_ERROR, "bad calculated line number"); + return ElvFalse; + } + break; + } + /* else fall through so '=' is parsed later as a command... */ + scanprev(refp); +#endif /* FEATURE_MISC */ + default: /* use the default address, but don't consume any chars */ lnum = markline(&xinf->defaddr); @@ -880,6 +968,7 @@ int len; /* number of characters in name so far */ MARK start; /* where the command name started */ int i; + CHAR *cp; /* if no command, then assume either "goto" or comment */ if (!*refp || **refp == '\n' || **refp == '|') @@ -974,6 +1063,12 @@ /* If we still haven't found anything, give up! */ if (matches == 0) { + /* try to read additional letters */ + scandup(&cp, refp); + len--; + for (; len < QTY(cmdname) && cp && elvalpha(*cp); scannext(&cp)) + cmdname[len++] = *cp; + scanfree(&cp); cmdname[len] = '\0'; msg(MSG_ERROR, "[s]bad command name $1", cmdname); return ElvFalse; @@ -1394,11 +1489,12 @@ { ELVBOOL shell; /* is this command for a shell? */ ELVBOOL bol; /* at front of a line? */ - CHAR *scan; + CHAR *scan, *scanend; CHAR ch; MARKBUF end; MARK start; int i; + ELVFNR rules; /* if the command doesn't use cmds, then do nothing */ if ((flags & a_Cmds) == 0) @@ -1441,20 +1537,25 @@ /* shell commands are more complex, due to substitutions... */ bol = ElvTrue; + rules = exfilenamerules(o_filenamerules); while (*refp && **refp && **refp != '\n') { /* copy most characters literally, but perform * substitutions for !, %, # */ ch = **refp; + scanend = NULL; switch (ch) { case '%': - scan = o_filename(markbuffer(&xinf->defaddr)); - break; - case '#': - scan = buffilenumber(refp); + if (!(rules & ELVFNR_SPECIAL)) + { + buildCHAR(&xinf->rhs, **refp); + scan = xinf->rhs; + break; + } + scan = buffilenumber(markbuffer(&xinf->defaddr), refp, &scanend); break; case '!': @@ -1515,8 +1616,12 @@ /* we want to... but do we have the string? */ if (scan) { - for ( ; *scan; scan++) - buildCHAR(&xinf->rhs, *scan); + if (scanend) + for ( ; scan != scanend; scan++) + buildCHAR(&xinf->rhs, *scan); + else + for ( ; *scan; scan++) + buildCHAR(&xinf->rhs, *scan); } else { @@ -1603,8 +1708,8 @@ { /* expand any environment variables */ filename = tochar8(calculate(toCHAR(filename), NULL, - (ELVFNR)(((rules & ELVFNR_DOLLAR) ? CALC_DOLLAR : 0) | - ((rules & ELVFNR_PAREN) ? CALC_PAREN : 0)))); + (CALCRULE)(((rules&ELVFNR_DOLLAR) ? CALC_DOLLAR : 0) | + ((rules&ELVFNR_PAREN) ? CALC_PAREN : 0)))); if (!filename) return ElvFalse; } @@ -1720,6 +1825,7 @@ { CHAR *filename; CHAR *scan, *val; + CHAR ch; ELVFNR rules; #ifdef FEATURE_BACKTICK CHAR *expr; @@ -1838,6 +1944,7 @@ break; case '#': + case '%': /* if filenamerules doesn't contain "special" just add char */ if (!(rules & ELVFNR_SPECIAL)) { @@ -1848,42 +1955,19 @@ /* replace # with name of alternate file, or a numbered * file. */ - scan = buffilenumber(refp); + ch = **refp; + scan = buffilenumber(markbuffer(&xinf->defaddr), refp, &val); if (!scan) { - msg(MSG_ERROR, "[c]no value to substitute for $1", '#'); + msg(MSG_ERROR, "[C]no value to substitute for $1", ch); goto Error; } - for ( ; *scan; scan++) + for ( ; scan != val; scan++) { buildCHAR(&filename, *scan); } break; - case '%': - /* filenamerules doesn't contain "special" just add char */ - if (!(rules & ELVFNR_SPECIAL)) - { - buildCHAR(&filename, **refp); - break; - } - - /* replace % with name of current file */ - scan = o_filename(markbuffer(&xinf->defaddr)); - if (scan) - { - for ( ; *scan; scan++) - { - buildCHAR(&filename, *scan); - } - } - else - { - msg(MSG_ERROR, "[c]no value to substitute for $1", '%'); - goto Error; - } - break; - case '\0': msg(MSG_ERROR, "NUL not allowed in file name"); goto Error; @@ -1940,7 +2024,9 @@ */ for (; *val; val++) { - if (*val == '\t' || (*val == ' ' && (rules & ELVFNR_SPACE))) + if (*val == '\t' + || *val == '\n' + || (*val == ' ' && (rules & ELVFNR_SPACE))) { if (filename) { @@ -2152,7 +2238,11 @@ xinf->anyaddr = ElvTrue; sel = ElvFalse; } - else if ((*refp && strchr("./?'0123456789$+-,;", (char)**refp))) + else if (*refp + && (strchr("./?'0123456789$+-,;", (char)**refp) + || (**refp == '=' + && ((*refp)[1] == '('/*)*/ + || elvalpha((*refp)[1]) )))) { do { @@ -2274,16 +2364,15 @@ quirks = cmdnames[xinf->cmdidx].quirks; /* is the command legal in this context? */ - if (!win && 0 == (quirks & q_Exrc)) + if (o_initializing && 0 == (quirks & q_Exrc)) { msg(MSG_ERROR, "[s]$1 is illegal during initialization", xinf->cmdname); return RESULT_ERROR; } - if (((0 == (quirks & q_Restricted)) ? o_security != 'n' /* !normal */ - : o_security == 'r')/* restricted */ - && 0 != (quirks & q_Unsafe)) + if (((quirks & q_Unsafe) != 0 && o_security == 's' /* safer */) + || ((quirks & q_Restricted) != 0 && o_security == 'r' /* restricted */)) { - msg(MSG_ERROR, "[s]$1 is unsafe", xinf->cmdname); + msg(MSG_ERROR, "[s]unsafe to :$1", xinf->cmdname); return RESULT_ERROR; } @@ -2444,13 +2533,22 @@ { return RESULT_ERROR; } - if (((0 == (quirks & q_Restricted)) ? o_security != 'n' /* !normal */ - : o_security == 'r')/* restricted */ - && 0 != (quirks & q_FileUnsafe) - && xinf->nfiles > 0) - { - msg(MSG_ERROR, "[s]$1 filename is unsafe", xinf->cmdname); - return RESULT_ERROR; + if (xinf->nfiles > 0 && + (((quirks & q_FileUnsafe) != 0 && o_security == 's' /* safer */) + || ((quirks & q_FileRestr) != 0 && o_security == 'r' /* restricted */))) + { + /* We have a filename. However, some commands use the + * current filename by default; if that is what's happing + * here, then allow it. Else error. + */ + if (xinf->nfiles > 1 + || !bufdefault + || !o_filename(bufdefault) + || CHARcmp(toCHAR(xinf->file[0]), o_filename(bufdefault))) + { + msg(MSG_ERROR, "[s]unsafe to :$1 filename", xinf->cmdname); + return RESULT_ERROR; + } } /* for some commands, parse a long argument string which @@ -2539,14 +2637,6 @@ xinf->to = o_buflines(markbuffer(&xinf->defaddr)); } - /* if only one address was given, and the default range - * include should include 2 lines, then add second line. - */ - if (!twoaddrs && (flags & d_LnMask) == d_2Lines) - { - xinf->to = xinf->from + 1; - } - /* if there was a count, add it to "from" to make "to" */ if (xinf->count > 0) { @@ -2583,7 +2673,7 @@ bufreplace(marktmp(logstart, log, 0L), marktmp(logend, log, o_bufchars(log)), NULL, 0L); o_maplog = 'a'; } - bufreplace(marktmp(logend, log, o_bufchars(log)), &logend, toCHAR(":"), 1L); + bufappend(log, toCHAR(":"), 1L); if (logstr) { if (*refp) @@ -2591,13 +2681,12 @@ else loglen = CHARlen(logstr); assert(loglen > 0L); - bufreplace(marktmp(logend, log, o_bufchars(log)), - &logend, logstr, loglen); + bufappend(log, logstr, loglen); } else bufpaste(marktmp(logend, log, o_bufchars(log)), &orig, scanmark(refp)); - bufreplace(marktmp(logend, log, o_bufchars(log)), &logend, toCHAR("\n"), 1L); + bufappend(log, toCHAR("\n"), 1L); } #endif /* FEATURE_MAPDB */ @@ -2730,7 +2819,8 @@ /* most commands aren't allowed to switch buffers */ if (xinf->newcurs - && markbuffer(xinf->window->cursor) != markbuffer(xinf->newcurs) + && (!xinf->window + || markbuffer(xinf->window->cursor) != markbuffer(xinf->newcurs)) && !(quirks & q_SwitchB)) { markfree(xinf->newcurs); @@ -2813,15 +2903,13 @@ tochar8(o_bufname(markbuffer(xinf->window->cursor))), tochar8(o_bufname(markbuffer(xinf->newcurs))), loglines); - bufreplace(marktmp(logend, log, o_bufchars(log)), - &logend, - toCHAR(line), - (long)strlen(line)); + bufappend(log, toCHAR(line), strlen(line)); } #endif /* FEATURE_MAPDB */ optprevfile(o_filename(markbuffer(xinf->window->cursor)), markline(xinf->window->cursor)); +#if 0 if (gui->retitle) { (*gui->retitle)(xinf->window->gw, @@ -2833,6 +2921,9 @@ dispset(xinf->window, o_initialsyntax(markbuffer(xinf->newcurs)) ? "syntax" : tochar8(o_bufdisplay(markbuffer(xinf->newcurs)))); +#else + winchgbuf(xinf->window, markbuffer(xinf->newcurs), ElvTrue); +#endif bufoptions(markbuffer(xinf->newcurs)); } @@ -3455,10 +3546,12 @@ /* Many commands take ex commands as their arguments. The a_Cmds * flag is set for these commands, but it is also set for a few - * others. Oh well, it's close enough. Also, the :help command's - * arguments resemble an ex command. + * others. Oh well, it's close enough. Also, the :help and :phelp + * commands' arguments resemble an ex command. */ - if ((cmdnames[i].flags & a_Cmds) != 0 || cmdnames[i].code == EX_HELP) + if ((cmdnames[i].flags & a_Cmds) != 0 + || cmdnames[i].code == EX_HELP + || cmdnames[i].code == EX_PHELP) return excomplete(win, marktmp(tmp, markbuffer(to), offset), to); /* does the command take filename arguments or a target address? */ diff -urN elvis-2.2_0/ex.h elvis-2.2_1/ex.h --- elvis-2.2_0/ex.h 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/ex.h 2004-03-26 22:35:29 +0100 @@ -38,9 +38,9 @@ EX_JOIN, EX_LAST, EX_LET, EX_LIST, EX_LOCAL, EX_LPR, EX_MAKE, EX_MAP, EX_MARK, EX_MESSAGE, EX_MKEXRC, EX_MOVE, - EX_NEXT, EX_NOHLSEARCH, EX_NORMAL, EX_NUMBER, + EX_NEXT, EX_NOFOLD, EX_NOHLSEARCH, EX_NORMAL, EX_NUMBER, EX_ONLY, EX_OPEN, - EX_POP, EX_PRESERVE, EX_PREVIOUS, EX_PRINT, EX_PUSH, EX_PUT, + EX_PHELP, EX_POP, EX_PRESERVE, EX_PREVIOUS, EX_PRINT, EX_PUSH, EX_PUT, EX_QALL, EX_QUIT, EX_READ, EX_REDO, EX_REGION, EX_REWIND, EX_SALL, EX_SAFELY, EX_SBBROWSE, EX_SBROWSE, EX_SET, EX_SHELL, diff -urN elvis-2.2_0/exaction.c elvis-2.2_1/exaction.c --- elvis-2.2_0/exaction.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/exaction.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_exaction[] = "$Id: exaction.c,v 2.120 2003/10/18 04:47:18 steve Exp $"; +char id_exaction[] = "$Id: exaction.c,v 2.127 2004/03/22 00:20:03 steve Exp $"; #endif #ifdef FEATURE_MISC @@ -403,7 +403,7 @@ STATE *s; /* used for stepping though state stack */ CHAR *p; /* used for scanning movement string */ EXINFO xinfb; /* dummy command buffer, used for parsing address */ - long line=1; /* default line number to start on */ + long line=0; /* default line number to start on (0 = no default) */ assert(xinf->command == EX_EDIT || xinf->command == EX_OPEN || xinf->command == EX_VISUAL || xinf->command == EX_PUSH); @@ -507,7 +507,10 @@ */ memset((char *)&xinfb, 0, sizeof xinfb); xinfb.defaddr.buffer = newbuf; - xinfb.defaddr.offset = lowline(bufbufinfo(newbuf), line); + if (line > 0) + xinfb.defaddr.offset = lowline(bufbufinfo(newbuf), line); + else + xinfb.defaddr.offset = newbuf->docursor; if (xinf->lhs && (o_newfile(newbuf) || o_bufchars(newbuf) > 0)) { (void)scanstring(&p, xinf->lhs); @@ -518,6 +521,12 @@ xinfb.to); } scanfree(&p); + +#if 1 + marksetbuffer(xinf->window->cursor, newbuf); + marksetoffset(xinf->window->cursor, xinfb.defaddr.offset); + exstring(xinf->window, xinf->lhs, "+"); +#endif } /* change the buffer of this window. */ @@ -537,6 +546,7 @@ } /* both commands accept a "+line" argument */ + /*!!! THIS ONLY HANDLES LINE NUMBERS, NOT WHOLE COMMANDS */ if (xinf->lhs) { xinfb.defaddr = xinf->defaddr; @@ -630,16 +640,17 @@ } /* output statistics of this file */ - if (markbuffer(xinf->window->cursor) == buf && o_buflines(buf) > 0) - { - msg(MSG_INFO, - "[dd](filename)(readonly?\" [READONLY]\")(modified?\" [MODIFIED]\")(!edited?\" [NOT EDITED]\")(newfile?\" [NEW FILE]\") ($1 * 100 / $2)%", - lnum, o_buflines(buf)); - } - else + if (!xinf->bang && xinf->window != NULL) { - msg(MSG_INFO, - "(filename)(readonly?\" [READONLY]\")(modified?\" [MODIFIED]\")(!edited?\" [NOT EDITED]\")(newfile?\" [NEW FILE]\")"); + if (markbuffer(xinf->window->cursor) == buf && o_buflines(buf) > 0) + { + msg(MSG_INFO, "[dd](filename)(readonly?\" [READONLY]\")(modified?\" [MODIFIED]\")(!edited?\" [NOT EDITED]\")(newfile?\" [NEW FILE]\") ($1 * 100 / $2)%", + lnum, o_buflines(buf)); + } + else + { + msg(MSG_INFO, "(filename)(readonly?\" [READONLY]\")(modified?\" [MODIFIED]\")(!edited?\" [NOT EDITED]\")(newfile?\" [NEW FILE]\")"); + } } break; } @@ -872,7 +883,7 @@ else #endif { - xinf->newcurs = markalloc(newbuf, 0); + xinf->newcurs = markalloc(newbuf, newbuf->docursor); } } @@ -953,6 +964,8 @@ CHAR iobuf[4096]; int len; ELVBOOL origrefresh; + ELVBOOL partiallast; + ELVBOOL last; assert(xinf->command == EX_BANG); @@ -1023,6 +1036,11 @@ return RESULT_ERROR; } + /* if partial last line, then omit the newline from the range */ + last = (ELVBOOL)(markoffset(xinf->toaddr) == o_bufchars(markbuffer(xinf->toaddr))); + if (o_partiallastline(markbuffer(xinf->toaddr)) && last) + markaddoffset(xinf->toaddr, -1L); + /* write the original text from buffer to filter */ mark = markdup(xinf->fromaddr); scanalloc(&cp, mark); @@ -1057,11 +1075,35 @@ bufreplace(xinf->fromaddr, xinf->toaddr, NULL, 0); /* read the new input lines */ + partiallast = ElvFalse; while ((len = prgread(iobuf, QTY(iobuf))) > 0) { /* insert a chunk of text into buffer */ bufreplace(mark, mark, iobuf, (long)len); markaddoffset(mark, len); + partiallast = (ELVBOOL)(iobuf[len - 1] != '\n'); + } + + /* if we had a partial last line before filtering, but not after, + * then clean up + */ + marksetoffset(xinf->toaddr, o_bufchars(markbuffer(xinf->toaddr))); + if (last && o_partiallastline(markbuffer(xinf->toaddr)) && !partiallast) + { + /* delete the bogus newline that elvis added at the end of the + * partial last line + */ + bufreplace(mark, xinf->toaddr, NULL, 0L); + o_partiallastline(markbuffer(mark)) = ElvFalse; + } + /* if we had a complete last line before, but not now, fix it */ + else if (last && !o_partiallastline(markbuffer(xinf->toaddr)) && partiallast) + { + /* add a bogus newline. Elvis wants to see one there even if + * it isn't really part of the buffer's intended text. + */ + bufreplace(xinf->toaddr, xinf->toaddr, toCHAR("\n"), 1L); + o_partiallastline(markbuffer(mark)) = ElvTrue; } /* clean up & exit */ @@ -1086,50 +1128,58 @@ assert(xinf->command == EX_SOURCE); /* the file name is REQUIRED! */ - if (xinf->nfiles != 1) + if (xinf->nfiles != 1 && xinf->rhs == NULL) { msg(MSG_ERROR, "[s]$1 requires a file name", xinf->cmdname); return RESULT_ERROR; } - + /* if ! appeared after the command name, and the file doesn't exist, * then do nothing but return with no error. */ - if (xinf->bang && dirperm(xinf->file[0]) == DIR_NEW) + if (xinf->bang && xinf->rhs == NULL && dirperm(xinf->file[0]) == DIR_NEW) { return RESULT_COMPLETE; } /* open the file */ - if (!ioopen(xinf->file[0], 'r', ElvFalse, ElvFalse, 't')) + if (xinf->rhs == NULL + ? !ioopen(xinf->file[0], 'r', ElvFalse, ElvFalse, 't') + : !ioopen(tochar8(xinf->rhs), 'r', ElvTrue, ElvFalse, 't')) return RESULT_ERROR; /* create a temp buffer */ buf = bufalloc(NULL, 0, ElvTrue); assert(buf != NULL); - o_filename(buf) = CHARdup(toCHAR(xinf->file[0])); - optflags(o_filename(buf)) |= OPT_FREE; + if (xinf->rhs == NULL) + { + o_filename(buf) = CHARdup(toCHAR(xinf->file[0])); + optflags(o_filename(buf)) |= OPT_FREE; + } /* fill the temp buffer with text read from the file */ io = (CHAR *)safealloc(1024, sizeof(CHAR)); while ((nbytes = ioread(io, 1024)) > 0) { - bufreplace(marktmp(end, buf, o_bufchars(buf)), &end, io, nbytes); + bufappend(buf, io, nbytes); } safefree(io); - (void)ioclose(); + if (!ioclose()) + { + return RESULT_ERROR; + } /* execute the contents of the buffer as a series of ex commands */ #ifdef FEATURE_MISC popopt = optlocal(NULL); #endif #ifdef FEATURE_AUTOCMD - (void)auperform(xinf->window, ElvFalse, NULL, AU_SCRIPTENTER, toCHAR(xinf->file[0])); + (void)auperform(xinf->window, ElvFalse, NULL, AU_SCRIPTENTER, o_filename(buf)); #endif result = experform(xinf->window, marktmp(start, buf, 0), marktmp(end, buf, o_bufchars(buf))); #ifdef FEATURE_AUTOCMD - (void)auperform(xinf->window, ElvFalse, NULL, AU_SCRIPTLEAVE, toCHAR(xinf->file[0])); + (void)auperform(xinf->window, ElvFalse, NULL, AU_SCRIPTLEAVE, o_filename(buf)); #endif #ifdef FEATURE_MISC (void)optlocal(popopt); @@ -1441,8 +1491,10 @@ FOLD fold; RESULT result = RESULT_COMPLETE; CHAR *args[2], arg[20]; + int flags; - assert(xinf->command == EX_FOLD || xinf->command == EX_UNFOLD); + assert(xinf->command == EX_FOLD || xinf->command == EX_UNFOLD + ||xinf->command == EX_NOFOLD); /* evaluate the name, if any */ if (xinf->rhs) @@ -1466,7 +1518,18 @@ markaddoffset(&tobuf, -1L); /* Decide how to behave, based on presence/absence of args */ - if (xinf->anyaddr && name) + if (xinf->command == EX_NOFOLD) + { + /* Discard any FOLDs (either folded or unfolded) that are + * partially or wholly in the given range. + */ + flags = FOLD_INSIDE|FOLD_OUTSIDE|FOLD_DESTROY; + if (xinf->bang) + flags |= FOLD_NESTED; + (void)foldbyrange(xinf->fromaddr, &tobuf, ElvTrue, flags); + (void)foldbyrange(xinf->fromaddr, &tobuf, ElvFalse, flags); + } + else if (xinf->anyaddr && name) { /* Create a new fold/unfold */ fold = foldalloc(xinf->fromaddr, &tobuf, name); diff -urN elvis-2.2_0/exconfig.c elvis-2.2_1/exconfig.c --- elvis-2.2_0/exconfig.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/exconfig.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_exconfig[] = "$Id: exconfig.c,v 2.147 2003/10/19 23:13:33 steve Exp $"; +char id_exconfig[] = "$Id: exconfig.c,v 2.154 2004/03/21 23:24:41 steve Exp $"; #endif @@ -698,7 +698,7 @@ # endif result = exstring(xinf->window, cmd, alias->name); # ifdef FEATURE_AUTOCMD - (void)auperform(xinf->window, ElvFalse, NULL, AU_ALIASENTER, toCHAR(alias->name)); + (void)auperform(xinf->window, ElvFalse, NULL, AU_ALIASLEAVE, toCHAR(alias->name)); # ifdef FEATURE_MISC (void)optlocal(popopt); # endif @@ -719,7 +719,6 @@ BUFFER custom; /* the buffer to which the :au commands are added */ { ELVBOOL anyout; /* any groups output yet? */ - MARKBUF end; alias_t *alias; CHAR *cmd, *word; @@ -738,9 +737,7 @@ if (!anyout) { anyout = ElvTrue; - (void)marktmp(end, custom, o_bufchars(custom)); - bufreplace(&end, &end, - toCHAR("try {\n"), 6L); + bufappend(custom, toCHAR("try {\n"), 6); } /* construct an alias command string */ @@ -775,8 +772,7 @@ } /* add the command to the buffer */ - end.offset = o_bufchars(custom); - bufreplace(&end, &end, cmd, CHARlen(cmd)); + bufappend(custom, cmd, 0); /* free the string form of the command */ safefree(cmd); @@ -786,8 +782,7 @@ /* if any groups were output, then we need to end "try {" */ if (anyout) { - end.offset = o_bufchars(custom); - bufreplace(&end, &end, toCHAR("}\n"), 2L); + bufappend(custom, toCHAR("}\n"), 2); } } @@ -992,6 +987,7 @@ } +/* implements the :display and :normal commands. */ RESULT ex_display(xinf) EXINFO *xinf; { @@ -1070,7 +1066,7 @@ { displist(xinf->window); } - else + else if (xinf->window) { /* trim trailing whitespace from the mode name */ if (xinf->rhs) @@ -1082,8 +1078,8 @@ /* set the mode */ if (!dispset(xinf->window, tochar8(xinf->rhs))) return RESULT_ERROR; + xinf->window->di->logic = DRAW_CHANGED; } - xinf->window->di->logic = DRAW_CHANGED; return RESULT_COMPLETE; } @@ -1356,7 +1352,8 @@ * the tag stack. */ bufwilldo(tagdefn, ElvFalse); - if ((*gui->creategw)(tochar8(o_bufname(markbuffer(tagdefn))), "")) + if (xinf->command == EX_HELP + && (*gui->creategw)(tochar8(o_bufname(markbuffer(tagdefn))), "")) { return RESULT_COMPLETE; } @@ -1392,7 +1389,8 @@ RESULT ex_if(xinf) EXINFO *xinf; { - CHAR *result; + CHAR *value; + RESULT result; /* expression is required */ if (!xinf->rhs) @@ -1401,9 +1399,11 @@ return RESULT_ERROR; } + /* evaluate expression */ - result = calculate(xinf->rhs, NULL, xinf->command == EX_EVAL ? CALC_MSG : CALC_ALL); - if (!result) + value = calculate(xinf->rhs, NULL, + xinf->command == EX_EVAL ? CALC_MSG : CALC_ALL); + if (!value) { return RESULT_ERROR; } @@ -1411,13 +1411,16 @@ if (xinf->command == EX_IF) { /* set "exthenflag" based on result of evaluation */ - exctlstate.thenflag = calctrue(result); + exctlstate.thenflag = calctrue(value); return RESULT_COMPLETE; } else /* command == EX_EVAL */ { /* execute the result as an ex command */ - return exstring(xinf->window, result, NULL); + value = CHARdup(value); + result = exstring(xinf->window, value, NULL); + safefree(value); + return result; } } #endif /* FEATURE_CALC */ @@ -1815,6 +1818,7 @@ flags |= maphelp2(refcp, "command", MAP_COMMAND); flags |= maphelp2(refcp, "motion", MAP_MOTION); flags |= maphelp2(refcp, "select", MAP_SELECT); + flags |= maphelp2(refcp, "noselect", MAP_COMMAND|MAP_MOTION); flags |= maphelp2(refcp, "visual", MAP_ASCMD); flags |= maphelp2(refcp, "noremap", MAP_NOREMAP); flags |= maphelp2(refcp, "nosave", MAP_NOSAVE); @@ -1922,24 +1926,26 @@ if (xinf->bang) flags |= MAP_INPUT|MAP_HISTORY; - /* "visual" implies at least one of "input history" */ - if ((flags & (MAP_INPUT|MAP_HISTORY|MAP_ASCMD)) == MAP_ASCMD) - flags |= MAP_INPUT|MAP_HISTORY; - /* if no other context specified, assume "command motion select" */ if ((flags & MAP_WHEN) == 0) flags |= MAP_COMMAND|MAP_MOTION|MAP_SELECT; + + /* "visual" implies at least one of "input history" */ + if ((flags & (MAP_INPUT|MAP_HISTORY|MAP_ASCMD)) == MAP_ASCMD) + flags |= MAP_INPUT|MAP_HISTORY; } /* either list, unmap, or map */ if (!lhs) { + if (all) + flags |= MAP_NOSAVE; + /* can't list maps before the first window is created */ if (xinf->window) - while ((line = maplist(flags & (MAP_WHEN|MAP_ABBR), mode, &len)) != (CHAR *)0) + while ((line = maplist(flags & (MAP_WHEN|MAP_ABBR|MAP_NOSAVE), mode, &len)) != (CHAR *)0) { - if (*line == ' ' || all) - drawextext(xinf->window, line, len); + drawextext(xinf->window, line, len); } } else if (!rhs) @@ -1957,8 +1963,12 @@ #ifdef FEATURE_EQUALTILDE +/* Apply an ex command to a string instead of a buffer. Return the resulting + * string, or NULL if the command failed or has no characters. This is used + * by the ":let x =~ excmd" command. + */ static CHAR *equaltilde(value, len, cmd) - CHAR *value; /*value to act on */ + CHAR *value; /* value to act on */ int len; /* length of value (which might not be NUL terminated)*/ CHAR *cmd; /* ex command to apply to the value */ { @@ -1972,30 +1982,17 @@ /* store the value into the buffer */ bufreplace(marktmp(top, buf, 0L), marktmp(bottom, buf, o_bufchars(buf)), value, len); - bufreplace(marktmp(bottom, buf, o_bufchars(buf)), &bottom, toCHAR("\n"), 1); + bufappend(buf, toCHAR("\n"), 1); -#if 0 - /* temporarily move the cursor to this buffer */ - top = *windefault->cursor; - marksetoffset(windefault->cursor, 0L); - marksetbuffer(windefault->cursor, buf); -#else /* temporarily make this the default buffer */ prevdef = bufdefault; bufoptions(buf); -#endif /* apply the ex command line to the buffer */ result = exstring(windefault, cmd, "equaltilde"); -#if 0 - /* restore the cursor */ - marksetbuffer(windefault->cursor, top.buffer); - marksetoffset(windefault->cursor, top.offset); -#else /* restore the buffer */ bufoptions(prevdef); -#endif /* if the command failed or has no characters, return NULL */ if (result != RESULT_COMPLETE || o_bufchars(buf) == 0L) diff -urN elvis-2.2_0/exedit.c elvis-2.2_1/exedit.c --- elvis-2.2_0/exedit.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/exedit.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_exedit[] = "$Id: exedit.c,v 2.68 2003/10/17 17:41:23 steve Exp $"; +char id_exedit[] = "$Id: exedit.c,v 2.71 2004/03/19 16:28:59 steve Exp $"; #endif @@ -211,6 +211,8 @@ * line then we should assume we're supposed to join two lines. */ newlines = xinf->to - xinf->from; + if (newlines == 0) + newlines = 1; if (xinf->from + newlines > o_buflines(markbuffer(xinf->fromaddr))) { msg(MSG_ERROR, "nothing to join with this line"); @@ -424,14 +426,17 @@ * command, this should be the start of the first line read; else it * should be the start of the last line read. */ - if (xinf->window->state->flags & ELVIS_1LINE) + if (xinf->window) { - marksetoffset(xinf->newcurs, offset); - } - else - { - marksetoffset(xinf->newcurs, markoffset( - (*xinf->window->md->move)(xinf->window, xinf->newcurs, -1, 0, ElvFalse))); + if (xinf->window->state->flags & ELVIS_1LINE) + { + marksetoffset(xinf->newcurs, offset); + } + else + { + marksetoffset(xinf->newcurs, markoffset( + (*xinf->window->md->move)(xinf->window, xinf->newcurs, -1, 0, ElvFalse))); + } } return RESULT_COMPLETE; } @@ -626,21 +631,11 @@ { name = tochar8(xinf->rhs); } - else if (xinf->nfiles >= 1) + else { assert(xinf->nfiles == 1); name = xinf->file[0]; } - else - { - name = tochar8(o_filename(markbuffer(xinf->fromaddr))); - if (!name) - { - msg(MSG_ERROR, "[S]no file name for $1", - o_bufname(markbuffer(xinf->fromaddr))); - return RESULT_ERROR; /* nishi */ - } - } /* if writing to a different filename, remember that name */ if (name[0] != '!' diff -urN elvis-2.2_0/exmake.c elvis-2.2_1/exmake.c --- elvis-2.2_0/exmake.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/exmake.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_make[] = "$Id: exmake.c,v 2.43 2003/10/18 04:47:18 steve Exp $"; +char id_make[] = "$Id: exmake.c,v 2.44 2004/03/14 23:18:24 steve Exp $"; #endif #ifdef FEATURE_MAKE @@ -45,9 +45,9 @@ * discarded. Usually, this discarded text consists simply of a colon and some * whitespace. * - * Returns ElvTrue normally, or ElvFalse at the end of the list. If it returns ElvTrue, - * then the errfile, errline, and errdesc variables will have been set to - * reflect anything that was found in the line; if all three are non-NULL + * Returns ElvTrue normally, or ElvFalse at the end of the list. If it returns + * ElvTrue, then the errfile, errline, and errdesc variables will have been set + * to reflect anything that was found in the line; if all three are non-NULL * then the line contained an error message. */ static ELVBOOL parse_errmsg() diff -urN elvis-2.2_0/fold.c elvis-2.2_1/fold.c --- elvis-2.2_0/fold.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/fold.c 2004-03-26 22:35:29 +0100 @@ -3,7 +3,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_fold[] = "$Id: fold.c,v 2.10 2003/10/17 17:41:23 steve Exp $"; +char id_fold[] = "$Id: fold.c,v 2.11 2004/03/19 23:03:39 steve Exp $"; #endif #undef DEBUG_FOLD @@ -156,11 +156,11 @@ /* Locate FOLDs by region, and either delete them or unfold/refold them. * Return RESULT_COMPLETE if at least one region was deleted/moved, or - * RESULT_COMPLETE if it had no effect. + * RESULT_ERROR if it had no effect. * * This search always acts on regions which overlap the from/to range, * or which exactly match the from/to range. They can also optionally - * affected wholely enclosed FOLDs, and/or FOLDs which are nested inside + * affected wholly enclosed FOLDs, and/or FOLDs which are nested inside * other FOLDs which are affected by this command. */ RESULT foldbyrange(from, to, infold, flags) diff -urN elvis-2.2_0/gui.c elvis-2.2_1/gui.c --- elvis-2.2_0/gui.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/gui.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_gui[] = "$Id: gui.c,v 2.32 2003/10/19 19:19:53 steve Exp $"; +char id_gui[] = "$Id: gui.c,v 2.33 2004/02/12 17:57:34 steve Exp $"; #endif /* This is a pointer to the chosen GUI. */ @@ -287,7 +287,8 @@ /* Translate a key name or raw key sequence into both an official key name * and rawin sequence, and return the length of the rawin sequence. This is * a wrapper around the (*gui->keylabel)() function, and it adds support for - * some standard keys. + * some standard keys. It also adds the intelligence needed to handle a series + * of keys, as opposed to a single key that sends multiple characters. */ int guikeylabel(given, givenlen, label, rawptr) CHAR *given; /* what the user typed in as a key code */ @@ -302,6 +303,7 @@ CHAR ch[1]; CHAR first; CHAR hashnotation[30]; + int keystrokes; static struct { CHAR *label; int len; @@ -343,7 +345,10 @@ return givenlen; } - /* Allow the GUI to translate "#number" function keys */ + /* Allow the GUI to translate "#number" function keys. (The "#number" + * notation isn't allowed to be mixed with other characters, so the + * conversion loop below doesn't handle it. So we do it here.) + */ if (gui->keylabel && given[0] == '#') { rawlen = (*gui->keylabel)(given, givenlen, label, rawptr); @@ -356,12 +361,15 @@ safefree(build); /* else we'll build a string by looking for names */ + keystrokes = 0; + symlabel = NULL; for (build = NULL, scan = given; scan < &given[givenlen]; scan++) { /* anything other than '<' is added literally */ if (*scan != '<') { buildCHAR(&build, *scan); + keystrokes++; continue; } @@ -465,6 +473,7 @@ /* add the symbol's raw chars to the buffer */ while (rawlen-- > 0) buildCHAR(&build, *symraw++); + keystrokes++; /* move the scan variable past the symbolic name */ scan += labellen - 1; @@ -473,6 +482,8 @@ /* stick a on the end, and return the length without the null */ rawlen = buildCHAR(&build, '\0') - 1; *rawptr = build; - /* ...but leave (*label) unchanged */ + if (keystrokes == 1 && label && symlabel) + *label = symlabel; + /* ...else leave (*label) unchanged */ return rawlen; } diff -urN elvis-2.2_0/guitcap.c elvis-2.2_1/guitcap.c --- elvis-2.2_0/guitcap.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/guitcap.c 2004-03-26 22:35:29 +0100 @@ -167,21 +167,21 @@ } keys[] = { - {"", "ku", "k", MAP_ALL}, - {"", "kd", "j", MAP_ALL}, - {"", "kl", "h", MAP_ALL}, - {"", "kr", "l", MAP_ALL}, - {"", "PUkPk2", "\002", MAP_ALL}, - {"", "PDkNk5", "\006", MAP_ALL}, - {"", "HMkhK1", "^", MAP_ALL}, - {"", "ENkHK5@7", "$", MAP_ALL}, - {"", "kI", "i", MAP_ALL}, + {"", "ku", "k", MAP_NOSAVE|MAP_ALL}, + {"", "kd", "j", MAP_NOSAVE|MAP_ALL}, + {"", "kl", "h", MAP_NOSAVE|MAP_ALL}, + {"", "kr", "l", MAP_NOSAVE|MAP_ALL}, + {"", "PUkPk2", "\002", MAP_NOSAVE|MAP_ALL}, + {"", "PDkNk5", "\006", MAP_NOSAVE|MAP_ALL}, + {"", "HMkhK1", "^", MAP_NOSAVE|MAP_ALL}, + {"", "ENkHK5@7", "$", MAP_NOSAVE|MAP_ALL}, + {"", "kI", "i", MAP_NOSAVE|MAP_ALL}, #ifdef FEATURE_MISC - {"", "kD", "x", MAP_ALL}, - {"", "k+", "\013", MAP_INPUT}, - {"", "#4KL", "B", MAP_ALL}, - {"", "%iKR", "W", MAP_ALL}, - {"", "kB", "g\t", MAP_COMMAND}, + {"", "kD", "x", MAP_NOSAVE|MAP_ALL}, + {"", "k+", "\013", MAP_NOSAVE|MAP_INPUT}, + {"", "#4KL", "B", MAP_NOSAVE|MAP_ALL}, + {"", "%iKR", "W", MAP_NOSAVE|MAP_ALL}, + {"", "kB", "g\t", MAP_NOSAVE|MAP_COMMAND}, #endif {"#1", "k1"}, {"#2", "k2"}, @@ -194,26 +194,32 @@ {"#9", "k9"}, {"#10", "k0kak;"}, #ifdef FEATURE_MISC - {"#1s", "s1"}, - {"#2s", "s2"}, - {"#3s", "s3"}, - {"#4s", "s4"}, - {"#5s", "s5"}, - {"#6s", "s6"}, - {"#7s", "s7"}, - {"#8s", "s8"}, - {"#9s", "s9"}, - {"#10s", "s0"}, - {"#1c", "c1"}, - {"#2c", "c2"}, - {"#3c", "c3"}, - {"#4c", "c4"}, - {"#5c", "c5"}, - {"#6c", "c6"}, - {"#7c", "c7"}, - {"#8c", "c8"}, - {"#9c", "c9"}, - {"#10c", "c0"}, + {"#11", "F1"}, + {"#12", "F2"}, + {"#1s", "s1F3"}, + {"#2s", "s2F4"}, + {"#3s", "s3F5"}, + {"#4s", "s4F6"}, + {"#5s", "s5F7"}, + {"#6s", "s6F8"}, + {"#7s", "s7F9"}, + {"#8s", "s8FA"}, + {"#9s", "s9FB"}, + {"#10s", "s0FC"}, + {"#11s", "FD"}, + {"#12s", "FE"}, + {"#1c", "c1FF"}, + {"#2c", "c2FG"}, + {"#3c", "c3FH"}, + {"#4c", "c4FI"}, + {"#5c", "c5FJ"}, + {"#6c", "c6FK"}, + {"#7c", "c7FL"}, + {"#8c", "c8FM"}, + {"#9c", "c9FN"}, + {"#10c", "c0FO"}, + {"#11c", "FP"}, + {"#12c", "FQ"}, {"#1a", "a1"}, {"#2a", "a2"}, {"#3a", "a3"}, @@ -1355,7 +1361,7 @@ o_ttyunderline = ElvTrue; o_ttyitalic = ElvTrue; o_ttywrap = ElvTrue; - optinsert("tcap", QTY(goptdesc), goptdesc, &ttygoptvals.term); + optinsert("termcap", QTY(goptdesc), goptdesc, &ttygoptvals.term); /* initialize the termcap stuff */ starttcap(); @@ -1495,10 +1501,10 @@ * * JohnW 13/08/96 - try to sort out keeping program * output on screen until vi mode is entered again. - * We have some program output on the screen and we - * may want to keep looking at it while we do another - * command, so don't do a big refresh until we're - * out of bottom-line mode + * We have some program output on the screen and we + * may want to keep looking at it while we do another + * command, so don't do a big refresh until we're + * out of bottom-line mode * * Steve 9/12/96 - switched it back, partially, because * moving the ttyresume() call to the afterprg==2 @@ -2160,26 +2166,39 @@ /* resume curses */ if (!isread) { - ttyresume(ElvFalse); + if (windows != NULL) + { + ttyresume(ElvFalse); - /* Okay, now we're in a weird sort of situation. The screen is - * about to be forced to display "Hit to continue" on - * the bottom of the window in open mode, and then wait for a - * keystroke. That's a Good Thing. But there are two problems - * we need to address: - * * We want that prompt to appear at the bottom of the - * screen, not the bottom of the window. - * * After the user hits a key, we want to redraw all - * windows. - * - * We'll set a flag indicating this situation. The movecurs() - * function will test for that flag, and merely pretend to move - * the cursor when it is set. The loop() function will test - * that flag after each keystroke, and expose all windows if - * it is set. - */ - afterprg = 2; - afterscrl = 0; + /* Okay, now we're in a weird sort of situation. + * The screen is about to be forced to display + * "Hit to continue" on the bottom of the + * window in open mode, and then wait for a keystroke. + * That's a good thing. But there are two problems + * we need to address: + * * We want that prompt to appear at the bottom + * of the screen, not the bottom of the window. + * * After the user hits a key, we want to redraw + * all windows. + * + * We'll set a flag indicating this situation. The + * movecurs() function will test for that flag, and + * merely pretend to move the cursor when it is set. + * The loop() function will test that flag after each + * keystroke, and expose all windows if it is set. + */ + afterprg = 2; + afterscrl = 0; + } + else + { + /* A program was run during initialization, probably + * as part of an autocmd BufReadPost event. The first + * window hasn't been displayed yet, so there's nothing + * the user needs to see. Don't wait for keys + */ + ttyresume(ElvTrue); + } } #ifdef FEATURE_MISC diff -urN elvis-2.2_0/guiwin32/guiwin.c elvis-2.2_1/guiwin32/guiwin.c --- elvis-2.2_0/guiwin32/guiwin.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/guiwin32/guiwin.c 2004-03-26 22:35:32 +0100 @@ -114,72 +114,72 @@ static char vkeyAF12[] = { '\xFF', 'A', VK_F12 , '\0' }; static struct vkey gwkeys[] = { - { "", "k", MAP_ALL, vkeyUp }, - { "", "j", MAP_ALL, vkeyDown }, - { "", "h", MAP_ALL, vkeyLeft }, - { "", "l", MAP_ALL, vkeyRight }, - { "", "B", MAP_ALL, vkeyCLeft }, - { "", "W", MAP_ALL, vkeyCRight }, - { "", "\x02", MAP_ALL, vkeyPgUp }, - { "", "\x06", MAP_ALL, vkeyPgDn }, - { "", "^", MAP_ALL, vkeyHome }, - { "", "$", MAP_ALL, vkeyEnd }, - { "", "1G", MAP_ALL, vkeyCPgUp }, - { "", "G", MAP_ALL, vkeyCPgDn }, - { "", "1G", MAP_ALL, vkeyCHome }, - { "", "G", MAP_ALL, vkeyCEnd }, - { "", "i", MAP_ALL, vkeyIns }, - { "", "x", MAP_ALL, vkeyDel }, - { "", "g\t", MAP_COMMAND, vkeySTab }, - { "#1", 0, MAP_ALL, vkeyF1 }, - { "#2", 0, MAP_ALL, vkeyF2 }, - { "#3", 0, MAP_ALL, vkeyF3 }, - { "#4", 0, MAP_ALL, vkeyF4 }, - { "#5", 0, MAP_ALL, vkeyF5 }, - { "#6", 0, MAP_ALL, vkeyF6 }, - { "#7", 0, MAP_ALL, vkeyF7 }, - { "#8", 0, MAP_ALL, vkeyF8 }, - { "#9", 0, MAP_ALL, vkeyF9 }, - { "#10", 0, MAP_ALL, vkeyF10 }, - { "#11", 0, MAP_ALL, vkeyF11 }, - { "#12", 0, MAP_ALL, vkeyF12 }, - { "#1s", 0, MAP_ALL, vkeySF1 }, - { "#2s", 0, MAP_ALL, vkeySF2 }, - { "#3s", 0, MAP_ALL, vkeySF3 }, - { "#4s", 0, MAP_ALL, vkeySF4 }, - { "#5s", 0, MAP_ALL, vkeySF5 }, - { "#6s", 0, MAP_ALL, vkeySF6 }, - { "#7s", 0, MAP_ALL, vkeySF7 }, - { "#8s", 0, MAP_ALL, vkeySF8 }, - { "#9s", 0, MAP_ALL, vkeySF9 }, - { "#10s", 0, MAP_ALL, vkeySF10 }, - { "#11s", 0, MAP_ALL, vkeySF11 }, - { "#12s", 0, MAP_ALL, vkeySF12 }, - { "#1c", 0, MAP_ALL, vkeyCF1 }, - { "#2c", 0, MAP_ALL, vkeyCF2 }, - { "#3c", 0, MAP_ALL, vkeyCF3 }, - { "#4c", 0, MAP_ALL, vkeyCF4 }, - { "#5c", 0, MAP_ALL, vkeyCF5 }, - { "#6c", 0, MAP_ALL, vkeyCF6 }, - { "#7c", 0, MAP_ALL, vkeyCF7 }, - { "#8c", 0, MAP_ALL, vkeyCF8 }, - { "#9c", 0, MAP_ALL, vkeyCF9 }, - { "#10c", 0, MAP_ALL, vkeyCF10 }, - { "#11c", 0, MAP_ALL, vkeyCF11 }, - { "#12c", 0, MAP_ALL, vkeyCF12 }, - { "#1a", 0, MAP_ALL, vkeyAF1 }, - { "#2a", 0, MAP_ALL, vkeyAF2 }, - { "#3a", 0, MAP_ALL, vkeyAF3 }, - { "#4a", 0, MAP_ALL, vkeyAF4 }, - { "#5a", 0, MAP_ALL, vkeyAF5 }, - { "#6a", 0, MAP_ALL, vkeyAF6 }, - { "#7a", 0, MAP_ALL, vkeyAF7 }, - { "#8a", 0, MAP_ALL, vkeyAF8 }, - { "#9a", 0, MAP_ALL, vkeyAF9 }, - { "#10a", 0, MAP_ALL, vkeyAF10 }, - { "#11a", 0, MAP_ALL, vkeyAF11 }, - { "#12a", 0, MAP_ALL, vkeyAF12 }, - { 0, 0, 0, 0 } + { "", "k", MAP_NOSAVE|MAP_ALL, vkeyUp }, + { "", "j", MAP_NOSAVE|MAP_ALL, vkeyDown }, + { "", "h", MAP_NOSAVE|MAP_ALL, vkeyLeft }, + { "", "l", MAP_NOSAVE|MAP_ALL, vkeyRight }, + { "", "B", MAP_NOSAVE|MAP_ALL, vkeyCLeft }, + { "", "W", MAP_NOSAVE|MAP_ALL, vkeyCRight }, + { "", "\x02", MAP_NOSAVE|MAP_ALL, vkeyPgUp }, + { "", "\x06", MAP_NOSAVE|MAP_ALL, vkeyPgDn }, + { "", "^", MAP_NOSAVE|MAP_ALL, vkeyHome }, + { "", "$", MAP_NOSAVE|MAP_ALL, vkeyEnd }, + { "", "1G", MAP_NOSAVE|MAP_ALL, vkeyCPgUp }, + { "", "G", MAP_NOSAVE|MAP_ALL, vkeyCPgDn }, + { "", "1G", MAP_NOSAVE|MAP_ALL, vkeyCHome }, + { "", "G", MAP_NOSAVE|MAP_ALL, vkeyCEnd }, + { "", "i", MAP_NOSAVE|MAP_ALL, vkeyIns }, + { "", "x", MAP_NOSAVE|MAP_ALL, vkeyDel }, + { "", "g\t", MAP_NOSAVE|MAP_COMMAND, vkeySTab }, + { "#1", 0, MAP_NOSAVE|MAP_ALL, vkeyF1 }, + { "#2", 0, MAP_NOSAVE|MAP_ALL, vkeyF2 }, + { "#3", 0, MAP_NOSAVE|MAP_ALL, vkeyF3 }, + { "#4", 0, MAP_NOSAVE|MAP_ALL, vkeyF4 }, + { "#5", 0, MAP_NOSAVE|MAP_ALL, vkeyF5 }, + { "#6", 0, MAP_NOSAVE|MAP_ALL, vkeyF6 }, + { "#7", 0, MAP_NOSAVE|MAP_ALL, vkeyF7 }, + { "#8", 0, MAP_NOSAVE|MAP_ALL, vkeyF8 }, + { "#9", 0, MAP_NOSAVE|MAP_ALL, vkeyF9 }, + { "#10", 0, MAP_NOSAVE|MAP_ALL, vkeyF10 }, + { "#11", 0, MAP_NOSAVE|MAP_ALL, vkeyF11 }, + { "#12", 0, MAP_NOSAVE|MAP_ALL, vkeyF12 }, + { "#1s", 0, MAP_NOSAVE|MAP_ALL, vkeySF1 }, + { "#2s", 0, MAP_NOSAVE|MAP_ALL, vkeySF2 }, + { "#3s", 0, MAP_NOSAVE|MAP_ALL, vkeySF3 }, + { "#4s", 0, MAP_NOSAVE|MAP_ALL, vkeySF4 }, + { "#5s", 0, MAP_NOSAVE|MAP_ALL, vkeySF5 }, + { "#6s", 0, MAP_NOSAVE|MAP_ALL, vkeySF6 }, + { "#7s", 0, MAP_NOSAVE|MAP_ALL, vkeySF7 }, + { "#8s", 0, MAP_NOSAVE|MAP_ALL, vkeySF8 }, + { "#9s", 0, MAP_NOSAVE|MAP_ALL, vkeySF9 }, + { "#10s", 0, MAP_NOSAVE|MAP_ALL, vkeySF10 }, + { "#11s", 0, MAP_NOSAVE|MAP_ALL, vkeySF11 }, + { "#12s", 0, MAP_NOSAVE|MAP_ALL, vkeySF12 }, + { "#1c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF1 }, + { "#2c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF2 }, + { "#3c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF3 }, + { "#4c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF4 }, + { "#5c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF5 }, + { "#6c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF6 }, + { "#7c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF7 }, + { "#8c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF8 }, + { "#9c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF9 }, + { "#10c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF10 }, + { "#11c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF11 }, + { "#12c", 0, MAP_NOSAVE|MAP_ALL, vkeyCF12 }, + { "#1a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF1 }, + { "#2a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF2 }, + { "#3a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF3 }, + { "#4a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF4 }, + { "#5a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF5 }, + { "#6a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF6 }, + { "#7a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF7 }, + { "#8a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF8 }, + { "#9a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF9 }, + { "#10a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF10 }, + { "#11a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF11 }, + { "#12a", 0, MAP_NOSAVE|MAP_ALL, vkeyAF12 }, + { 0, 0, 0, 0 } }; static OPTDESC gw_opt_desc[] = { diff -urN elvis-2.2_0/guix11/guix11.c elvis-2.2_1/guix11/guix11.c --- elvis-2.2_0/guix11/guix11.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/guix11/guix11.c 2004-03-26 22:35:32 +0100 @@ -5,7 +5,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_guix11[] = "$Id: guix11.c,v 2.82 2003/10/17 17:41:23 steve Exp $"; +char id_guix11[] = "$Id: guix11.c,v 2.89 2004/03/22 00:22:15 steve Exp $"; #endif #ifdef GUI_X11 # include "guix11.h" @@ -80,6 +80,7 @@ #if USE_PROTOTYPES static void beep(GUIWIN *gw); static int catchErrors(Display *disp, XErrorEvent *err); +static int ignoreErrors(Display *disp, XErrorEvent *err); static void moveto(GUIWIN *gw, int column, int row); static ELVBOOL scroll(GUIWIN *gw, int qty, ELVBOOL notlast); static ELVBOOL shift(GUIWIN *gw, int qty, int rows); @@ -193,37 +194,32 @@ MAPFLAGS flags; } keys[] = { - { "", XK_Up, "k", MAP_ALL }, - { "", XK_KP_Up, "k", MAP_ALL }, - { "", XK_Down, "j", MAP_ALL }, - { "", XK_KP_Down, "j", MAP_ALL }, - { "", XK_Left, "h", MAP_ALL }, - { "", XK_KP_Left, "h", MAP_ALL }, - { "", XK_Right, "l", MAP_ALL }, - { "", XK_KP_Right, "l", MAP_ALL }, - { "", XK_Prior, "\002", MAP_ALL }, - { "", XK_KP_Prior, "\002", MAP_ALL }, - { "", XK_Next, "\006", MAP_ALL }, - { "", XK_KP_Next, "\006", MAP_ALL }, - { "", XK_Home, "^", MAP_ALL }, - { "", XK_KP_Home, "^", MAP_ALL }, - { "", XK_Begin, "^", MAP_ALL }, - { "", XK_KP_Begin, "^", MAP_ALL }, - { "", XK_End, "$", MAP_ALL }, - { "", XK_KP_End, "$", MAP_ALL }, - { "", XK_Insert, "i", MAP_ALL }, - { "",XK_KP_Insert, "i", MAP_ALL }, - { "", XK_Delete, "x", MAP_ALL }, - { "",XK_KP_Delete, "x", MAP_ALL }, - { "", XK_Undo, "u", MAP_ALL }, - { "", XK_Help, ":help\r",MAP_ALL }, -#ifdef XK_ISO_Left_Tab - { "", XK_ISO_Left_Tab,"g\t", MAP_COMMAND }, -#endif -#ifdef XK_3270_BackTab - { "", XK_3270_BackTab,"g\t", MAP_COMMAND }, -#endif - { "",XK_Multi_key, "\013", MAP_INPUT|MAP_HISTORY } + { "", XK_Up, "k", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Up, "k", MAP_NOSAVE|MAP_ALL }, + { "", XK_Down, "j", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Down, "j", MAP_NOSAVE|MAP_ALL }, + { "", XK_Left, "h", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Left, "h", MAP_NOSAVE|MAP_ALL }, + { "", XK_Right, "l", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Right, "l", MAP_NOSAVE|MAP_ALL }, + { "", XK_Prior, "\002", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Prior, "\002", MAP_NOSAVE|MAP_ALL }, + { "", XK_Next, "\006", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Next, "\006", MAP_NOSAVE|MAP_ALL }, + { "", XK_Home, "^", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Home, "^", MAP_NOSAVE|MAP_ALL }, + { "", XK_Begin, "^", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_Begin, "^", MAP_NOSAVE|MAP_ALL }, + { "", XK_End, "$", MAP_NOSAVE|MAP_ALL }, + { "", XK_KP_End, "$", MAP_NOSAVE|MAP_ALL }, + { "", XK_Insert, "i", MAP_NOSAVE|MAP_ALL }, + { "",XK_KP_Insert, "i", MAP_NOSAVE|MAP_ALL }, + { "", XK_Delete, "x", MAP_NOSAVE|MAP_ALL }, + { "",XK_KP_Delete, "x", MAP_NOSAVE|MAP_ALL }, + { "", XK_Undo, "u", MAP_NOSAVE|MAP_ALL }, + { "", XK_Help, ":help\r",MAP_NOSAVE|MAP_ALL }, + { "", XK_Tab, "g\t", MAP_NOSAVE|MAP_ALL }, + { "",XK_Multi_key, "\013", MAP_NOSAVE|MAP_INPUT|MAP_HISTORY } }; @@ -266,7 +262,8 @@ {"cancel", "Cancel", optsstring, optisstring }, {"help", "Help", optsstring, optisstring }, {"synccursor", "xsync", NULL, NULL }, - {"scrollbgimage", "sbi",NULL, NULL } + {"scrollbgimage", "sbi",NULL, NULL }, + {"secret", "secret", optnstring, optisnumber } #ifdef FEATURE_XFT ,{"antialias", "aa", NULL, NULL }, {"aasqueeze", "aas", optnstring, xoptisnumber, "0:10"} @@ -307,8 +304,9 @@ { int i; Atom gottype; - long length, dummy; + unsigned long length, dummy; char *type; + unsigned char *utype; XrmDatabase db; XrmValue value; @@ -345,9 +343,8 @@ XGetWindowProperty(x_display, root, x_resource_manager, 0L, 65536L, ElvFalse, XA_STRING, &gottype, &i, - (unsigned long *)&length, - (unsigned long *)&dummy, - (unsigned char **)&type); + &length, &dummy, &utype); + type = (char *)utype; } if (type && i == 8 && gottype == XA_STRING) { @@ -771,7 +768,6 @@ } -#if 0 /* dummy X11 error handler */ static int ignoreErrors(disp, err) Display *disp; @@ -779,7 +775,6 @@ { return 0; } -#endif /* Test whether this GUI is available in this environment. @@ -984,6 +979,8 @@ ELVBOOL mustfork = ElvFalse; char *geomstr = NULL; GUI *oldgui; + struct timeval tv; + struct timezone tz; /* initialization */ if (!x_display) @@ -1246,6 +1243,8 @@ optpreset(o_xencoding, toCHAR(DEFAULT_XENCODING), OPT_HIDE); optpreset(o_scrollwheelspeed, DEFAULT_SCROLLWHEELSPEED, OPT_HIDE); optpreset(o_scrollbgimage, ElvTrue, OPT_HIDE); + gettimeofday(&tv, &tz); + optpreset(o_secret, 0L, OPT_HIDE|OPT_UNSAFE); optinsert("x11", QTY(x11desc), x11desc, (OPTVAL *)&x_optvals); /* convert geometry string, if given */ @@ -1294,6 +1293,8 @@ { if (keys[i].sym == XK_Delete) sprintf(raw, "%c", ELVCTRL('?')); + else if (keys[i].sym == XK_Tab) + sprintf(raw, "%c%04lx", ELVCTRL('S'), (long)XK_Tab); else sprintf(raw, "%c%04lx",ELVCTRL('K'), (long)keys[i].sym); mapinsert(toCHAR(raw), (int)strlen(raw), toCHAR(keys[i].cooked), (int)strlen(keys[i].cooked), toCHAR(keys[i].label), keys[i].flags, NULL); @@ -1719,6 +1720,7 @@ guicmd(NULL, "newtoolbar"); /* warp the cursor back to the original (non-Elvis) window */ + XSetErrorHandler(ignoreErrors); if (o_warpback && fromwin != root) { XGetInputFocus(x_display, &curfocus, &dummy); @@ -2234,12 +2236,18 @@ op = *extra++; else op = '\0'; - for (label = extra; *extra && !strchr(":\";=?~", *extra); extra++) + if (*extra == '[') + extra++; + for (label = extra; *extra && !strchr("]:\";=?~", *extra); extra++) { } end = extra; if (*extra) - op = *extra++; + { + if (!op) + op = *extra; + extra++; + } /* Trim whitespace */ while (label < end && elvspace(end[-1])) @@ -2372,7 +2380,7 @@ goto Found; } - /* Maybe it is a label in foo or format? */ + /* Maybe it is a label in format? */ if (given[0] == '<' && given[givenlen - 1] == '>' && givenlen < QTY(lblbuf)-1) { /* Look for "C-" or "S-" modifier */ @@ -2387,19 +2395,21 @@ CHARncpy(lblbuf, given, (size_t)givenlen); givenlen -= 2; } + /* Maybe it is a function key label in #n format? */ else if (given[0] == '#' && givenlen < QTY(lblbuf) - 2) { + /* look for "c" or "s" modifier */ + i = elvtoupper(given[givenlen - 1]); + if (i == 'C' || i == 'S') + { + modifier = i; + givenlen--; + } + /* standardize the format of the #nn string */ lblbuf[1] = 'F'; CHARncpy(lblbuf + 2, given + 1, (size_t)givenlen); } -#if 0 - else if (givenlen < QTY(lblbuf)-3) - { - /* standardize the format of the foo string */ - CHARncpy(lblbuf + 1, given, (size_t)givenlen); - } -#endif else { /* too long to be a key label */ @@ -2410,7 +2420,7 @@ lblbuf[givenlen + 1] = '\0'; name = tochar8(lblbuf + 1); key = XStringToKeysym(name); - if (key == NoSymbol) + if (key == NoSymbol || (unsigned)key <= 127) { return 0; } @@ -2420,7 +2430,7 @@ */ /* if function key, then convert label to #n format (else ) */ - if (key >= XK_F1 && key <= XK_F10) + if (key >= XK_F1 && key <= XK_F35) { if (modifier) sprintf((char *)lblbuf, "#%ld%c", (long)(key - XK_F1 + 1), elvtolower(modifier)); @@ -2429,16 +2439,22 @@ } else { - lblbuf[0] = '<'; - if (modifier) + /* we want to build the label in "lblbuf", but "name" may be a + * pointer into "lblbuf" so we must be careful... + */ + if (toCHAR(name) != lblbuf + 1) { - lblbuf[1] = modifier; - lblbuf[2] = '-'; - lblbuf[3] = '\0'; + lblbuf[0] = '<'; + if (modifier) + { + lblbuf[1] = modifier; + lblbuf[2] = '-'; + lblbuf[3] = '\0'; + } + else + lblbuf[1] = '\0'; + CHARcat(&lblbuf[1], toCHAR(name)); } - else - lblbuf[1] = '\0'; - CHARcat(&lblbuf[1], name); CHARcat(lblbuf, toCHAR(">")); } diff -urN elvis-2.2_0/guix11/guix11.h elvis-2.2_1/guix11/guix11.h --- elvis-2.2_0/guix11/guix11.h 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/guix11/guix11.h 2004-03-26 22:35:32 +0100 @@ -122,7 +122,7 @@ autoiconify, altkey, stagger, warpback, warpto, focusnew, textcursor, outlinemono, borderwidth, xrootwidth, xrootheight, xencoding, scrollwheelspeed, submit, cancel, help, synccursor, - scrollbgimage; + scrollbgimage, secret; #ifdef FEATURE_XFT OPTVAL antialias, aasqueeze; #endif @@ -165,6 +165,7 @@ #define o_help x_optvals.help.value.string #define o_synccursor x_optvals.synccursor.value.boolean #define o_scrollbgimage x_optvals.scrollbgimage.value.boolean +#define o_secret x_optvals.secret.value.number #ifdef FEATURE_XFT # define o_antialias x_optvals.antialias.value.boolean # define o_aasqueeze x_optvals.aasqueeze.value.number diff -urN elvis-2.2_0/guix11/xdialog.c elvis-2.2_1/guix11/xdialog.c --- elvis-2.2_0/guix11/xdialog.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/guix11/xdialog.c 2004-03-26 22:35:33 +0100 @@ -3,7 +3,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_xdialog[] = "$Id: xdialog.c,v 2.32 2003/10/18 18:20:08 steve Exp $"; +char id_xdialog[] = "$Id: xdialog.c,v 2.33 2004/02/01 02:09:45 steve Exp $"; #endif #ifdef GUI_X11 #include "guix11.h" @@ -449,10 +449,11 @@ /* create a new dialog */ -void x_dl_add(xw, name, desc, excmd, spec) +void x_dl_add(xw, name, desc, vicmd, excmd, spec) X11WIN *xw; /* window where the command should be performed */ char *name; /* name of the toolbar button */ char *desc; /* one-line description of the "submit" action */ + CHAR *vicmd; /* keys to push into input queue if "submit" pressed */ char *excmd; /* the command to execute if "submit" is pressed */ char *spec; /* list of options to use as fields */ { @@ -477,6 +478,7 @@ dia->xw = xw; dia->name = safedup(name); dia->desc = safedup(desc ? desc : name); + dia->vicmd = vicmd ? CHARdup(vicmd) : NULL; dia->excmd = excmd ? safedup(excmd) : NULL; dia->spec = safedup(spec); dia->current = -2; @@ -731,6 +733,8 @@ if (dia->name) safefree(dia->name); safefree(dia->desc); + if (dia->vicmd) + safefree(dia->vicmd); if (dia->excmd) safefree(dia->excmd); safefree(dia->spec); @@ -1001,6 +1005,7 @@ char tmp[300]; long l, min, max; GUIWIN *gw; + CHAR *vicmd; char *excmd; switch (key) @@ -1024,10 +1029,18 @@ * be destroyed. */ gw = (GUIWIN *)dia->xw; + vicmd = dia->vicmd ? CHARdup(dia->vicmd) : NULL; excmd = dia->excmd ? safedup(dia->excmd) : NULL; if (!dia->pinned) x_dl_delete(dia); + /* push the vi keystrokes, if any */ + if (vicmd) + { + eventkeys(gw, vicmd, CHARlen(vicmd)); + safefree(vicmd); + } + /* execute the ex command, if any */ if (excmd) { diff -urN elvis-2.2_0/guix11/xdialog.h elvis-2.2_1/guix11/xdialog.h --- elvis-2.2_0/guix11/xdialog.h 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/guix11/xdialog.h 2004-03-26 22:35:33 +0100 @@ -37,6 +37,7 @@ X11WIN *xw; /* window where command should be run */ char *name; /* name of the dialog, from toolbar button */ char *desc; /* one-line description of what "submit" does */ + CHAR *vicmd; /* chars to push into input queue if "submit" pressed */ char *excmd; /* the command to execute if "submit" pressed */ char *spec; /* descriptions of the fields */ X_FIELD *field; /* details about each field */ @@ -62,7 +63,7 @@ } dialog_t; -extern void x_dl_add P_((X11WIN *xw, char *name, char *desc, char *excmd, char *spec)); +extern void x_dl_add P_((X11WIN *xw, char *name, char *desc, CHAR *vicmd, char *excmd, char *spec)); extern void x_dl_delete P_((dialog_t *dia)); extern void x_dl_destroy P_((X11WIN *xw)); extern void x_dl_event P_((Window w, XEvent *event)); diff -urN elvis-2.2_0/guix11/xevent.c elvis-2.2_1/guix11/xevent.c --- elvis-2.2_0/guix11/xevent.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/guix11/xevent.c 2004-03-26 22:35:33 +0100 @@ -2,7 +2,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_xevent[] = "$Id: xevent.c,v 2.30 2003/10/17 17:41:23 steve Exp $"; +char id_xevent[] = "$Id: xevent.c,v 2.33 2004/02/12 17:57:34 steve Exp $"; #endif #ifdef GUI_X11 @@ -185,7 +185,7 @@ KeySym mykey; ELVISSTATE state; Atom gottype; - char *excmd; + char *excmd, *scan; unsigned long exlen, ldummy; int i, j; XEvent event2; @@ -388,8 +388,8 @@ /* if notification of timeout, then just send 0 keystrokes */ if (!event->xkey.display) { - eventkeys((GUIWIN *)w, NULL, 0); - xw->state = eventkeys((GUIWIN *)xw, toCHAR(text), 0); + xw->state = eventkeys((GUIWIN *)xw, NULL, 0); + x_didcmd = ElvTrue; break; } @@ -456,6 +456,29 @@ i = 1; } #endif +#if 1 + /* THIS IS A HACK! The XK_ISO_Left_Tab and XK_3270_Back_Tab + * keys are unreliable, and usually involve shifting. For the + * sake of uniformity, we'll convert them into Shift+Tab + * combinations. + */ +# ifdef XK_ISO_Left_Tab + if (mykey == XK_ISO_Left_Tab) + { + prefix = ELVCTRL('S'); + mykey = XK_Tab; + i = 0; + } +# endif +# ifdef XK_3270_BackTab + if (mykey == XK_3270 BackTab) + { + prefix = ELVCTRL('S'); + mykey = XK_Tab; + i = 0; + } +# endif +#endif if (i == 0) { if (!IsModifierKey(mykey) && mykey != XK_Mode_switch) @@ -623,7 +646,33 @@ if (gottype == XA_STRING && i == 8) { excmd[exlen] = '\0'; - eventex((GUIWIN *)xw, excmd, ElvTrue); + + /* look for secret key */ + if (o_secret != 0 && *excmd == '"') + { + sprintf(text, "\"%ld\"", o_secret); + i = strlen(text); + if (!strncmp(excmd, text, i)) + { + /* delete every "secret" prefix */ + for (scan = excmd; + *scan; + scan++) + { + if (!strncmp(scan, text, i)) + memmove(scan, scan + i, strlen(scan + i) + 1); + } + + /* run the command with security=normal */ + eventex((GUIWIN *)xw, excmd, ElvFalse); + } + /* else wrong security -- ignore */ + } + else + { + /* run the command with security=safer */ + eventex((GUIWIN *)xw, excmd, ElvTrue); + } x_didcmd = ElvTrue; } XFree(excmd); diff -urN elvis-2.2_0/guix11/xtool.c elvis-2.2_1/guix11/xtool.c --- elvis-2.2_0/guix11/xtool.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/guix11/xtool.c 2004-03-26 22:35:33 +0100 @@ -5,7 +5,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_xtool[] = "$Id: xtool.c,v 2.20 2003/10/18 18:20:08 steve Exp $"; +char id_xtool[] = "$Id: xtool.c,v 2.22 2004/02/05 23:31:19 steve Exp $"; #endif #ifdef GUI_X11 # include "guix11.h" @@ -20,9 +20,10 @@ { struct tool_s *next; /* another toolbar button */ char *label; /* toolbar button legend */ + CHAR *vicmd; /* keys to stuff into input queue */ char *excmd; /* command to execute */ CHAR *when; /* condition when button works */ - CHAR *in; /* condition when button drawn as "in" */ + CHAR *in; /* condition when button drawn as "in"*/ CHAR *comment; /* one-line description of the button */ char *spec; /* pop-up dialog specificaton */ int width; /* width of button's label */ @@ -137,11 +138,13 @@ /* free its memory */ safefree(tool->label); + if (tool->vicmd) safefree(tool->vicmd); if (tool->excmd) safefree(tool->excmd); if (tool->when) safefree(tool->when); if (tool->in) safefree(tool->in); if (tool->comment) safefree(tool->comment); if (tool->spec) safefree(tool->spec); + safefree(tool); } @@ -205,19 +208,51 @@ _char_ op; CHAR *value; { + int len; + /* if NULL value, then do nothing */ if (!value || !*value) return; /* build a command */ buildstr(retptr, " gui "); + if (op == ']') + buildCHAR(retptr, '['); buildstr(retptr, label); buildCHAR(retptr, op); - for (; *value; value++) - buildCHAR(retptr, *value); - /* Note that we don't need an explicit '\n' added here, because all of - * the value strings end with '\n' already. + len = strlen(label); + if (op != ']' + || value[0] != '[' + || CHARncmp(toCHAR(label), value+1, len) + || value[len + 1] != ']' + || value[len+2]) + { + for (; *value; value++) + { + /* Convert control chars to ^c notation, except that + * newlines should remain newlines for all attributes + * except the vi command string. + */ + if (*value < ' ' || *value == 127) + { + if (*value == '\n' && op != ']') + buildCHAR(retptr, *value); + else + { + buildCHAR(retptr, '^'); + buildCHAR(retptr, ELVCTRL(*value)); + } + } + else + buildCHAR(retptr, *value); + } + } + + /* For vicmd we need to append a newline. All others have newline + * in the value string already. */ + if (op == ']') + buildCHAR(retptr, '\n'); } /* This returns a dynamically-allocated string describing the attributes @@ -245,6 +280,7 @@ { if (tool->gap && !(label && *label)) buildstr(&ret, " gui gap\n"); + addline(&ret, tool->label, ']', tool->vicmd); addline(&ret, tool->label, ':', toCHAR(tool->excmd)); addline(&ret, tool->label, '?', tool->when); addline(&ret, tool->label, '=', tool->in); @@ -474,7 +510,7 @@ { /* compute the button's new state */ newstate = TB_REDRAW; - if (tool->excmd == NULL && tool->spec == NULL) + if (!tool->vicmd && !tool->excmd && !tool->spec) { newstate = 0; /* flat, inactive */ } @@ -608,12 +644,20 @@ * the [Submit] button, the excmd will be executed. */ x_dl_add(xw, clicked->label, clicked->comment ? tochar8(clicked->comment) : NULL, - clicked->excmd, clicked->spec); + clicked->vicmd, clicked->excmd, clicked->spec); } - else if (clicked->excmd) + else { - /* execute its ex command */ - eventex((GUIWIN *)xw, clicked->excmd, clicked->safer); + if (clicked->vicmd) + { + /* push the keys into the input queue */ + eventkeys((GUIWIN *)xw, clicked->vicmd, CHARlen(clicked->vicmd)); + } + if (clicked->excmd) + { + /* execute its ex command */ + eventex((GUIWIN *)xw, clicked->excmd, clicked->safer); + } } x_didcmd = ElvTrue; @@ -643,6 +687,8 @@ { TOOL *tool; ELVBOOL changed;/* do we need to reconfigure after this? */ + int len; + CHAR *rawin; /* if no label was given, then clobber all tools */ if (!label) @@ -670,6 +716,31 @@ /* apply the operator to the tool */ switch (op) { + case ']': + if (tool->vicmd) safefree(tool->vicmd); + if (value) + { + /* find length, excluding newline */ + len = strlen (value); + if (len > 0 && value[len-1] == '\n') + len--; + + /* convert symbolic keys? */ + len = guikeylabel(toCHAR(value), len, NULL, &rawin); + + /* store it */ + tool->vicmd = CHARdup(rawin); + } + else + { + /* use the button label, with brackets */ + tool->vicmd = (CHAR *)safealloc((strlen(label) + 3), sizeof(CHAR)); + tool->vicmd[0] = '['; + CHARcpy(tool->vicmd+1, toCHAR(label)); + CHARcat(tool->vicmd, toCHAR("]")); + } + break; + case ':': if (tool->excmd) safefree(tool->excmd); tool->excmd = (value ? safedup(value) : NULL); diff -urN elvis-2.2_0/http.c elvis-2.2_1/http.c --- elvis-2.2_0/http.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/http.c 2004-03-26 22:35:29 +0100 @@ -2,7 +2,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_http[] = "$Id: http.c,v 2.11 2003/10/17 17:41:23 steve Exp $"; +char id_http[] = "$Id: http.c,v 2.12 2003/12/28 20:29:02 steve Exp $"; #endif #ifdef PROTOCOL_HTTP @@ -35,6 +35,7 @@ msg(MSG_STATUS, "[s]requesting $1", resource); if (!netputline(sb, "GET", resource, "HTTP/1.0") || !netputline(sb, "Host:", site_port, NULL) + || !netputline(sb, "User-Agent:", "Elvis", VERSION) || !netputline(sb, "", NULL, NULL)) { /* error message already given */ diff -urN elvis-2.2_0/input.c elvis-2.2_1/input.c --- elvis-2.2_0/input.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/input.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_input[] = "$Id: input.c,v 2.83 2003/10/18 04:47:18 steve Exp $"; +char id_input[] = "$Id: input.c,v 2.84 2003/12/28 20:29:47 steve Exp $"; #endif /* These data types are used to store the parsing state for input mode @@ -1202,7 +1202,7 @@ /* Was this command issued via from input mode? * If not, then we'll need to push one. */ - if (!win->state->pop) + if (!win->state->pop || win->state->perform == _viperform) { inputpush(win, 0, 'i'); } diff -urN elvis-2.2_0/io.c elvis-2.2_1/io.c --- elvis-2.2_0/io.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/io.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_io[] = "$Id: io.c,v 2.62 2003/10/18 04:47:18 steve Exp $"; +char id_io[] = "$Id: io.c,v 2.63 2004/03/20 23:00:10 steve Exp $"; #endif #if USE_PROTOTYPES @@ -664,8 +664,11 @@ /* This function implements filename completion. You pass it a partial * filename and it uses dirfirst()/dirnext() to extend the name. If you've - * given enough to uniquely identify a file, then it will also append a - * tab after the filename. + * given enough to uniquely identify a file, then it will also append an + * endchar after the filename. + * + * As a special case, if endchar='\0' then it simply performs tilde-expansion + * and returns that, without attempting to complete the filename. */ char *iofilename(partial, endchar) char *partial; /* a partial filenam to expand */ @@ -729,6 +732,13 @@ partial = homed; safefree(str); + /* if endchar='\0' then simply return the tilde-expanded name */ + if (endchar == '\0') + { + strcpy(match, homed); + return match; + } + /* count the matching filenames */ for (nmatches = matchlen = 0, fname = dirfirst(partial, ElvTrue); fname; diff -urN elvis-2.2_0/main.c elvis-2.2_1/main.c --- elvis-2.2_0/main.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/main.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_main[] = "$Id: main.c,v 2.74 2003/10/18 04:47:18 steve Exp $"; +char id_main[] = "$Id: main.c,v 2.77 2004/03/19 23:10:12 steve Exp $"; #endif #include /* for time(), used to seed the random number generator */ @@ -93,8 +93,7 @@ msg(MSG_INFO, " -b Mark new buffers as \"readeol=binary\""); msg(MSG_INFO, " -e Start in ex mode instead of vi mode"); msg(MSG_INFO, " -i Start in input mode instead of vi mode"); - msg(MSG_INFO, " -S Set security=safer, to protect against Trojan horses"); - msg(MSG_INFO, " -SS Set security=restricted, for maximum security"); + msg(MSG_INFO, " -S Set security=restricted, for maximum security"); msg(MSG_INFO, " -w lines Set scroll amount to \"lines\""); msg(MSG_INFO, " -f session Use \"session\" as the session file"); msg(MSG_INFO, " -G gui Use the \"gui\" user interface \\(see below\\)"); @@ -344,10 +343,7 @@ break; case 'S': - if (o_security == 'n' /* normal */) - o_security = 's'; /* safer */ - else - o_security = 'r'; /*restricted*/ + o_security = 'r'; /*restricted*/ del = 1; break; @@ -673,6 +669,12 @@ { BUFFER buf; + /* Initialization is done. Any autocmd events generated while loading + * the first buffer should be allowed to do things like alter the + * edit buffer or write it out. + */ + o_initializing = ElvFalse; + /* If "Elvis args" is empty */ if (!arglist[0]) { @@ -836,12 +838,23 @@ /* Store the filename arguments in a list */ buildargs(argc, argv); +#ifdef FEATURE_PERSIST + bufpersistinit(); +#endif + /* start the first file (i.e., make sure we have at least 1 window) */ startfirst(); #ifdef FEATURE_AUTOCMD - /* do a BgChanged event, so highlight colors can be chosen relative - * the current background color. + /* if the user interface appears to be graphical, then do a GuiEnter + * event. + */ + if (gui->movecost == 0 && gui->retitle) + auperform(windefault, ElvFalse, NULL, AU_GUIENTER, NULL); + + /* if the normal background color has been set, then do a BgChanged + * event so highlight colors can be chosen relative the current + * background color. */ if (colorinfo[COLOR_FONT_NORMAL].da.bits & COLOR_BG) (void)auperform(windefault, ElvFalse, NULL, AU_BGCHANGED, @@ -850,11 +863,6 @@ colorinfo[COLOR_FONT_NORMAL].da.bg_rgb[2]>=384 ? "light" : "dark")); -# if 0 - else - (void)auperform(windefault, ElvFalse, NULL, AU_BGCHANGED, - o_background == 'l' ? "light" : "dark"); -# endif #endif } @@ -872,6 +880,8 @@ gui->term(); gui = NULL; + bufpersistsave(NULL); + /* Flush any final messages */ msgflush(); diff -urN elvis-2.2_0/makos2.cmd elvis-2.2_1/makos2.cmd --- elvis-2.2_0/makos2.cmd 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/makos2.cmd 2004-03-26 22:35:30 +0100 @@ -28,12 +28,13 @@ echo deleting some object files, don't worry if they do not exist... del calc.obj dmmarkup.obj ex.obj http.obj io.obj osnet.obj url.obj ftp.obj buffer.obj echo building non-tcp/ip elvis... -make -f osos2\Makefile.os2 ALL="elvis-no-tcp.exe ref.exe ctags.exe fmt.exe +make -f osos2\Makefile.os2 wcc-no-tcp goto done :gcc echo copying config file for non tcp/ip compile using gcc... -copy osos2\config-no-tcp.h config.h +rem copy osos2\config-no-tcp.h config.h +copy osos2\config-with-tcp.h config.h echo building non-tcp/ip elvis with emx/gcc... make -f osos2\Makefile.os2 gcc goto done @@ -63,14 +64,14 @@ echo copying config file for tcp/ip compile... copy osos2\config-with-tcp.h config.h echo building elvis and misc programs... -make -f osos2\Makefile.os2 all +make -f osos2\Makefile.os2 wcc goto done :package cd exeos2 del *gcc.exe cd .. -make -f osos2/Makefile.os2 elvis-2.2j-os2.tar.gz +make -f osos2/Makefile.os2 elvis-2.2_1-os2.tar.gz goto done :all diff -urN elvis-2.2_0/map.c elvis-2.2_1/map.c --- elvis-2.2_0/map.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/map.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_map[] = "$Id: map.c,v 2.54 2003/10/17 17:41:23 steve Exp $"; +char id_map[] = "$Id: map.c,v 2.58 2004/03/21 23:24:41 steve Exp $"; #endif #ifdef FEATURE_MAPDB @@ -364,12 +364,12 @@ bufreplace(marktmp(logstart, log, 0L), marktmp(logend, log, o_bufchars(log)), NULL, 0L); o_maplog = 'a'; } - bufreplace(marktmp(logend, log, o_bufchars(log)), &logend, toCHAR(where), (long)strlen(where)); + bufappend(log, toCHAR(where), 0); ch[0] = ':'; - bufreplace(marktmp(logend, log, o_bufchars(log)), &logend, ch, 1L); - bufreplace(marktmp(logend, log, o_bufchars(log)), &logend, traceimg, (long)CHARlen(traceimg)); + bufappend(log, ch, 1); + bufappend(log, traceimg, 0); ch[0] = '\n'; - bufreplace(marktmp(logend, log, o_bufchars(log)), &logend, ch, 1L); + bufappend(log, ch, 1); } /* maybe arrange for single-stepping to occur on next keystroke */ @@ -393,7 +393,7 @@ MAP *scan; /* used for scanning through maps */ int ambkey, ambuser;/* ambiguous key maps and user maps */ MAP *match; /* longest fully matching map */ - ELVBOOL ascmd = ElvFalse; /* did we just resolve an ASCMD map? */ + ELVBOOL ascmd = ElvFalse;/* did we just resolve an ASCMD map? */ ELVBOOL didtimeout; /* did we timeout? */ MAPFLAGS now; /* current keystroke parsing state */ BUFFER buf; /* a cut buffer that is in "learn" mode */ @@ -776,11 +776,18 @@ static CHAR buf[200]; CHAR *scan, *build; int i; + MAPFLAGS nosave; + + /* extract the MAP_NOSAVE flag */ + nosave = ~flags & MAP_NOSAVE; + flags &= ~MAP_NOSAVE; /* find first/next map item */ m = (m ? m->next : (flags & MAP_ABBR) ? abbrs : maps); flags &= ~MAP_ABBR; - while (m && ((m->flags & flags) == 0 || (mode && (!m->mode || CHARcmp(mode, m->mode))))) + while (m && ((m->flags & flags) == 0 + || (m->flags & nosave) != 0 + || (mode && (!m->mode || CHARcmp(mode, m->mode))) )) { m = m->next; } @@ -993,6 +1000,9 @@ } +/* This checks for possible abbreviations. If an abbreviation is detected, + * this will also perform the expansion. + */ CHAR *mapabbr(bkwd, oldptr, newptr, exline) CHAR *bkwd; /* possible abbreviation, BACKWARDS */ long *oldptr;/* where to store the length of short form */ @@ -1050,24 +1060,15 @@ void mapsave(buf) BUFFER buf; /* the buffer to append to */ { - MARKBUF append; /* where to put the command */ static MAP *m; /* used for scanning map list */ static CHAR text[200]; - long len; + int len; CHAR *scan; int i; - (void)marktmp(append, buf, o_bufchars(buf)); - /* for each map... */ for (m = maps; m; m = m->next) { - /* if for a GUI-specific key, ignore it */ - if (m->label && *m->label != '#') - { - continue; - } - /* if specifically marked as "nosave", ignore it */ if (m->flags & MAP_NOSAVE) { @@ -1086,6 +1087,12 @@ case MAP_COMMAND|MAP_MOTION|MAP_SELECT: break; + case MAP_INPUT|MAP_HISTORY|MAP_COMMAND|MAP_MOTION|MAP_SELECT: + if (m->flags & MAP_ASCMD) + /* "visual" implies "input history" */ + break; + /* else fall through... */ + default: if (m->flags & MAP_INPUT) CHARcat(text, toCHAR(" input")); @@ -1230,8 +1237,7 @@ text[len++] = '\n'; /* append the command to the buffer */ - bufreplace(&append, &append, text, len); - markaddoffset(&append, len); + bufappend(buf, text, len); } /* for each abbreviation... */ @@ -1267,8 +1273,7 @@ text[len++] = '\n'; /* append the command to the buffer */ - bufreplace(&append, &append, text, len); - markaddoffset(&append, len); + bufappend(buf, text, len); } } #endif /* def FEATURE_MKEXRC */ diff -urN elvis-2.2_0/message.c elvis-2.2_1/message.c --- elvis-2.2_0/message.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/message.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_message[] = "$Id: message.c,v 2.52 2003/10/18 04:47:18 steve Exp $"; +char id_message[] = "$Id: message.c,v 2.53 2004/03/19 23:04:10 steve Exp $"; #endif #if USE_PROTOTYPES # include @@ -288,7 +288,11 @@ } /* can't nest msg() calls. If another call is in progress, exit now */ +#if 0 if (*verbose || (msghiding && (imp == MSG_ERROR || imp == MSG_WARNING))) +#else + if (*verbose || msghiding) +#endif { if (imp == MSG_FATAL) { diff -urN elvis-2.2_0/move.c elvis-2.2_1/move.c --- elvis-2.2_0/move.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/move.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_move[] = "$Id: move.c,v 2.66 2003/10/17 17:41:23 steve Exp $"; +char id_move[] = "$Id: move.c,v 2.67 2003/12/28 20:31:11 steve Exp $"; #endif #ifdef FEATURE_G @@ -1620,6 +1620,7 @@ long para; long offset; long count; + MARKBUF tmp; DEFAULT(1); @@ -1651,6 +1652,7 @@ else { para = 0; + scanseek(&cp, marktmp(tmp, markbuffer(win->state->cursor), 0L)); } marksetoffset(win->state->cursor, offset); if (para == offset) diff -urN elvis-2.2_0/operator.c elvis-2.2_1/operator.c --- elvis-2.2_0/operator.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/operator.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_operator[] = "$Id: operator.c,v 2.47 2003/10/17 17:41:23 steve Exp $"; +char id_operator[] = "$Id: operator.c,v 2.48 2004/03/14 03:35:56 steve Exp $"; #endif @@ -102,6 +102,7 @@ CHAR *cmd; /* used for collecting the characters of the command line */ CHAR *cp; /* used for scanning the command-line buffer */ CHAR *sub; /* used for scanning a substitution value (for ! % #) */ + CHAR *subend;/* end of substitution string */ char err; /* error message (if this is an error) */ long i; @@ -131,14 +132,12 @@ { case '!': sub = o_previouscommand; + subend = sub + CHARlen(sub); break; case '%': - sub = o_filename(markbuffer(win->cursor)); - break; - case '#': - sub = buffilenumber(&cp); + sub = buffilenumber(markbuffer(win->cursor), &cp, &subend); break; case '\\': @@ -165,7 +164,7 @@ } else { - for (; *sub; sub++) + for (; sub != subend; sub++) { buildCHAR(&cmd, *sub); } diff -urN elvis-2.2_0/optglob.c elvis-2.2_1/optglob.c --- elvis-2.2_0/optglob.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/optglob.c 2004-03-26 22:35:29 +0100 @@ -6,7 +6,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_optglob[] = "$Id: optglob.c,v 2.110 2003/10/21 00:18:16 steve Exp $"; +char id_optglob[] = "$Id: optglob.c,v 2.119 2004/03/26 21:34:40 steve Exp $"; #endif #ifdef FEATURE_LISTCHARS @@ -128,6 +128,11 @@ {"listchars", "lcs", optsstring, optislistchars, "eol:,tab:,trail:,ff:,cr:,esc:,bs:,del:,nul:,precedes:,extends:,markup" }, {"cleantext", "ct", optsstring, optispacked, "bs,input,short,long,ex" }, {"filenamerules", "fnr",optsstring, optispacked, "tilde,dollar,paren,wildcard,special,space" }, + {"state", "state", optsstring, optisstring }, + {"initializing", "ing", NULL, NULL }, + {"persistfile", "perf", optsstring, optisstring }, + {"persist", "pers", optsstring, optispacked, "cursor,change,hours:,marks,regions,folds,external:,ex:,search:,args,max:"}, + /* added these for the sake of backward compatibility : */ {"more", "mo", NULL, NULL }, {"hardtabs", "ht", optnstring, optisnumber, "1:1000"}, @@ -308,6 +313,7 @@ o_incsearch = ElvFalse; optpreset(o_spelldict, NULL, OPT_HIDE | OPT_UNSAFE); optpreset(o_spellsuffix, NULL, OPT_HIDE); + optpreset(o_spellautoload, ElvTrue, OPT_HIDE); optpreset(o_locale, NULL, OPT_HIDE); optpreset(o_mkexrcfile, NULL, OPT_HIDE); optpreset(o_prefersyntax, 'n', OPT_HIDE); /* never */ @@ -320,6 +326,9 @@ #endif optpreset(o_cleantext, toCHAR("long"), OPT_HIDE); optpreset(o_filenamerules, toCHAR("tilde,dollar,paren,wildcard,special,space"), OPT_HIDE); + optpreset(o_initializing, ElvTrue, OPT_HIDE|OPT_LOCK); + optpreset(o_persistfile, NULL, OPT_HIDE | OPT_UNSAFE); + optpreset(o_persist, toCHAR("cursor,change,hours:8,marks,regions,folds,ex:50,search:20,args"), OPT_HIDE); /* Set the "home" option from $HOME */ envval = getenv("HOME"); diff -urN elvis-2.2_0/optglob.h elvis-2.2_1/optglob.h --- elvis-2.2_0/optglob.h 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/optglob.h 2004-03-26 22:35:29 +0100 @@ -119,12 +119,16 @@ #define o_listchars optglob[107].value.string #define o_cleantext optglob[108].value.string #define o_filenamerules optglob[109].value.string +#define o_state optglob[110].value.string +#define o_initializing optglob[111].value.boolean +#define o_persistfile optglob[112].value.string +#define o_persist optglob[113].value.string /* For backward compatibility with older releases of elvis : */ -#define o_more optglob[110].value.boolean -#define o_hardtabs optglob[111].value.number -#define o_redraw optglob[112].value.boolean -#define QTY_GLOBAL_OPTS 113 +#define o_more optglob[114].value.boolean +#define o_hardtabs optglob[115].value.number +#define o_redraw optglob[116].value.boolean +#define QTY_GLOBAL_OPTS 117 #ifdef FEATURE_LPR # define o_lptype lpval[0].value.string diff -urN elvis-2.2_0/options.c elvis-2.2_1/options.c --- elvis-2.2_0/options.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/options.c 2004-03-26 22:35:29 +0100 @@ -10,7 +10,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_options[] = "$Id: options.c,v 2.77 2003/10/17 17:41:23 steve Exp $"; +char id_options[] = "$Id: options.c,v 2.79 2004/03/21 23:24:41 steve Exp $"; #endif #ifndef OPT_MAXCOLS @@ -57,6 +57,17 @@ /* valid anymore when values get restored */ } OPTSTK; + +/* This stores the args of a ":set gui.options..." command line, where "gui" + * is anything other than the current user interface. + */ +typedef struct optforeign_s +{ + struct optforeign_s *next; /* some other options */ + CHAR *args; /* the arguments of the :set command */ +} OPTFOREIGN; + + #if USE_PROTOTYPES static ELVBOOL optshow(char *name); static void optoutput(ELVBOOL domain, ELVBOOL all, ELVBOOL set, CHAR *outbuf, size_t outsize); @@ -74,6 +85,15 @@ #ifdef FEATURE_MISC /* stack of local options */ static OPTSTK *stack = (OPTSTK *)1; + +# ifdef FEATURE_MKEXRC +/* list of foreign GUI settings. Note that we also store a tail pointer, + * so we can easily add items to the end of the list. This is important + * because sometimes it matters which option gets set first; e.g., xll.font + * must be set before x11.italicfont. + */ +static OPTFOREIGN *foreignhead, *foreigntail; +# endif #endif @@ -1222,6 +1242,41 @@ ELVBOOL b; int i; +#ifdef FEATURE_MISC + /* check whether this is for a foreign GUI */ + for (i = 0; elvalnum(args[i]); i++) + { + } + if (args[i] == '.') + { + /* this is a GUI-specific setting -- For foreign GUI? */ + if (strlen(gui->name) != (size_t)i || CHARncmp(toCHAR(gui->name), args, i)) + { + /* This is a foreign GUI setting */ + +# ifdef FEATURE_MKEXRC + /* save the settings */ + OPTFOREIGN *f = (OPTFOREIGN *)safealloc(sizeof(OPTFOREIGN), 1); + f->args = CHARdup(args); + f->next = NULL; + if (foreigntail) + foreigntail->next = f; + else + foreignhead = f; + foreigntail = f; +# endif + + /* don't do anything else with foreign settings */ + return ElvTrue; + } + else /* setting for this GUI */ + { + /* skip past the "gui." part of args */ + args += i + 1; + } + } +#endif + /* be optimistic. Begin by assuming this will succeed. */ ret = ElvTrue; @@ -1574,7 +1629,6 @@ void optsave(custom) BUFFER custom; /* where to stuff the "set" commands */ { - MARKBUF m; OPTDOMAIN *dom; int i, j, pass; CHAR *str; @@ -1619,12 +1673,18 @@ /* then add it to the custom buffer */ if (dom->desc[i].asstring) { + /* Non-Boolean */ str = (*dom->desc[i].asstring)(&dom->desc[i], &dom->val[i]); - tmp = (char *)safealloc(11 + strlen(dom->desc[i].longname) + 2 * CHARlen(str), sizeof(char)); - if (pass == 2 || (dom->val[i].flags & OPT_UNSAFE)) + tmp = (char *)safealloc(12 + strlen(gui->name) + strlen(dom->desc[i].longname) + 2 * CHARlen(str), sizeof(char)); + if (dom->val[i].flags & OPT_UNSAFE) strcpy(tmp, "try set "); else strcpy(tmp, "set "); + if (pass == 2) + { + strcat(tmp, gui->name); + strcat(tmp, "."); + } strcat(tmp, dom->desc[i].longname); strcat(tmp, "="); for (j = strlen(tmp); *str; ) @@ -1640,18 +1700,40 @@ } else { - tmp = (char *)safealloc(12 + strlen(dom->desc[i].longname), sizeof(char)); - sprintf(tmp, "%sset %s%s\n", - (pass == 2 || (dom->val[i].flags & OPT_UNSAFE)) ? "try " : "", - dom->val[i].value.boolean ? "" : "no", - dom->desc[i].longname); + /* Boolean */ + tmp = (char *)safealloc(13 + strlen(gui->name) + strlen(dom->desc[i].longname), sizeof(char)); + if (pass == 1) + sprintf(tmp, "%sset %s%s\n", + (dom->val[i].flags & OPT_UNSAFE) ? "try " : "", + dom->val[i].value.boolean ? "" : "no", + dom->desc[i].longname); + else + sprintf(tmp, "%sset %s.%s%s\n", + (dom->val[i].flags & OPT_UNSAFE) ? "try " : "", + gui->name, + dom->val[i].value.boolean ? "" : "no", + dom->desc[i].longname); } - bufreplace(marktmp(m, custom, o_bufchars(custom)), &m, toCHAR(tmp), (long)strlen(tmp)); + bufappend(custom, toCHAR(tmp), 0); safefree((void *)tmp); } } } } + +# ifdef FEATURE_MISC + /* we also need to save options for foreign GUIs */ + { + OPTFOREIGN *f; + + for (f = foreignhead; f; f = f->next) + { + bufappend(custom, toCHAR("set "), 4); + bufappend(custom, f->args, 0); + bufappend(custom, toCHAR("\n"), 1); + } + } +# endif } #endif /* FEATURE_MKEXRC */ diff -urN elvis-2.2_0/osmsdos/osconfig.h elvis-2.2_1/osmsdos/osconfig.h --- elvis-2.2_0/osmsdos/osconfig.h 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osmsdos/osconfig.h 2004-03-26 22:35:32 +0100 @@ -30,6 +30,7 @@ #undef FEATURE_HLOBJECT /* the hlobject and hllayers options */ #undef FEATURE_HLSEARCH /* the hlsearch option */ #undef FEATURE_INCSEARCH /* the incsearch option */ +#undef FEATURE_LISTCHARS /* the listchars option */ #undef FEATURE_LITRE /* faster searches for literal strings */ #define FEATURE_LPR /* the ":lpr" command */ #define FEATURE_MAKE /* the :make and :cc commands */ @@ -38,6 +39,7 @@ #undef FEATURE_MKEXRC /* the ":mkexrc" command */ #define FEATURE_MOUSE /* allow the mouse to be used for selections & tags */ #undef FEATURE_NORMAL /* vim-style :normal command */ +#undef FEATURE_PERSIST /* the persistfile option */ #undef FEATURE_PROTO /* using aliases to add new protocols */ #undef FEATURE_RAM /* if invoked with "-f ram" then use XMS/EMS */ #undef FEATURE_RCSID /* include RCS Id strings for all source files */ @@ -51,7 +53,6 @@ #undef FEATURE_TEXTOBJ /* text objects */ #define FEATURE_V /* the v/V/^V marking commands */ #undef FEATURE_XFT /* antialiased fonts in X11 -- useless in MSDOS */ -#undef FEATURE_LISTCHARS /* the listchars option */ /* The following provide custom implementation of some common functions which * are either missing or poorly implemented on some systems. diff -urN elvis-2.2_0/osos2/Makefile.os2 elvis-2.2_1/osos2/Makefile.os2 --- elvis-2.2_0/osos2/Makefile.os2 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/Makefile.os2 2004-03-26 22:35:32 +0100 @@ -1,5 +1,3 @@ -################################################################################ -# Herbert 1998: # Makefile for building and installing elvis under OS/2, # derived from Makefile created by configure for linux. # Works with GNU make and nmake. @@ -10,7 +8,26 @@ # both for compiling and for linking. Typical values are "cc -g" or "cc -O". # If you're compiling with X-windows support, you may need to add a # "-I/usr/X11/include" flag or something similar. -CC=icc -O -Q -DOS2 -I/work/ibmcpp/include -I/usr/include -I/tcpip/include + +# +# IBM VisualAge C++ 3.0 Compiler: +# +# This used to be the default, but since I've experienced some problems +# with its optimization and due to the lack of further maintenance by +# IBM I now recommend the OpenWatcom compiler which is now the default +# choice if Elvis is built from the `..\makos2.cmd' batch file. +# +CC=icc -O -Q -D__SPC__ -DOS2 -I/Software/ibmcpp/include -I/Software/toolkit/h -I/tcpip/include + +# +# Other Compilers: +# +# - OpenWatcom works fine, but for TCP/IP support you will need to create +# import library for `so32dll.dll' and `tcp32dll.dll'. It is now the +# default. +# - gcc is fine with versions prior to 3.2.2 (innotek builds). The latest +# versions still don't work with the X11 interface. +# ################################################################################ # This should be "unix" for all UNIX variants. It causes the compiler to use @@ -172,7 +189,7 @@ move$(OBJ) more$(OBJ) need$(OBJ) operator$(OBJ) regexp$(OBJ)\ region$(OBJ) regsub$(OBJ) search$(OBJ) spell$(OBJ) state$(OBJ)\ tinytcap$(OBJ) tag$(OBJ) tagsrch$(OBJ) tagelvis$(OBJ) url$(OBJ)\ - vi$(OBJ) vicmd$(OBJ) window$(OBJ) + vi$(OBJ) vicmd$(OBJ) window$(OBJ) autocmd$(OBJ) OBJS= $(OBJ1) $(OBJ2) $(OBJ3) REFOBJS=ref$(OBJ) tag$(OBJ) tagsrch$(OBJ) safe$(OBJ) CTOBJS= ctags$(OBJ) tag$(OBJ) safe$(OBJ) @@ -182,7 +199,7 @@ EVERY= $(ALL) elvdump$(EXE) calc$(EXE) verify$(EXE) # Herbert 1998: SHELL needs to be blanked out under OS/2 if using GNU make. #SHELL= /bin/sh -VERSION=2.2 +VERSION=2.2_0 DISTRIB=elvis-$(VERSION) DOSEXE=exedos WIN32EXE=exewin32 @@ -204,26 +221,36 @@ "CC=gcc -Wall -DOS2 -D__WITH_TERMCAP -O3 \ -I/emx/include -I/software/ibmcpp/include \ -I/software/ibmcpp/include/os2" \ - "LIBFILES=-lsocket -ltermcap" "FLAGO=-o " + "LIBFILES=-L/usr/lib/tcpipv4 -lsocket -ltermcap" \ + "FLAGO=-o " # Elvis compiled for a.out format and linked against emx.dll with x11... debug: ; $(MAKE) -f osos2\\Makefile.os2 "OBJ=.o" "EXE=x11.exe" \ "CC=gcc -g -Wall -DOS2 -D__WITH_TERMCAP -O3 \ -Zmtd -D__D_ST_MT_ERRNO__ -D__WITH_X11" \ - "FLAGO=-o " \ - "LIBFILES=-L/usr/lib/x11 -lsocket -ltermcap -lx11" + "FLAGO=-o " "LIBFILES=-L/usr/lib/x11 \ + -L/usr/lib/tcpipv4 -lsocket -ltermcap -lx11" # Elvis compiled for a.out format and linked against emx.dll with x11... x11: ; $(MAKE) elvisx11.exe -f osos2\\Makefile.os2 "OBJ=.o" "EXE=x11.exe" \ "CC=gcc -Wall -DOS2 -D__WITH_TERMCAP -O3 \ -Zmtd -D__D_ST_MT_ERRNO__ -D__WITH_X11 \ -I/usr/include -I/emx/include" "FLAGO=-o " \ - "LIBFILES=-L/usr/lib/x11 -lsocket -ltermcap -lx11" + "LIBFILES=-L/usr/lib/x11 -L/usr/lib/tcpipv4 \ + -lsocket -ltermcap -lx11" + +gcc: ; $(MAKE) -f osos2\\Makefile.os2 "EXE=gcc.exe" "FLAGO=-o " "OBJ=.o" \ + "CC=gcc -Wall -DOS2 -Zomf -O3 -I/emx/include" \ + "LIBFILES=-L/usr/lib/x11 -L/usr/lib/tcpipv4 -lsocket" + +wcc: ; $(MAKE) -f osos2\\Makefile.os2 "FLAGO=-fe=" "OBJ=.obj" \ + "CC=wcl386 -zq -otexan -I\\tcpip\\include -dexplicit=expl"\ + "LIBFILES=so32dll.lib tcp32dll.lib" DEFFILE="" + +wcc-no-tcp: ; $(MAKE) elvis-no-tcp$(EXE) -f osos2\\Makefile.os2 "FLAGO=-fe=" \ + "CC=wcl386 -zq -otexan -I\\tcpip\\include -dexplicit=expl"\ + LIBFILES="" DEFFILE="" -gcc: ; $(MAKE) -f osos2\\Makefile.os2 "EXE=gcc.exe" "FLAGO=-o " \ - "CC=gcc -Wall -DOS2 -Zsys -Zomf -O3 -I/emx/include" \ - "LIBFILES=" - elvis$(EXE): $(HDRS) main$(OBJ) $(OBJS) $(GUIOBJS) $(LPOBJS) $(CC) $(CFLAGS) $(LDFLAGS) main$(OBJ) $(OBJS) $(GUIOBJS) $(LPOBJS) $(LIBFILES) $(DEFFILE) $(FLAGO)elvis$(EXE) @@ -310,31 +337,31 @@ # broken down differently. guix11$(OBJ): guix11/guix11.c $(XBM) - $(OSCC) guix11/guix11.c + $(OSCC) guix11$(SLASH)guix11.c xclip$(OBJ): guix11/xclip.c - $(OSCC) guix11/xclip.c + $(OSCC) guix11$(SLASH)xclip.c xevent$(OBJ): guix11/xevent.c - $(OSCC) guix11/xevent.c + $(OSCC) guix11$(SLASH)xevent.c xmisc$(OBJ): guix11/xmisc.c - $(OSCC) guix11/xmisc.c + $(OSCC) guix11$(SLASH)xmisc.c xscroll$(OBJ): guix11/xscroll.c - $(OSCC) guix11/xscroll.c + $(OSCC) guix11$(SLASH)xscroll.c xstatus$(OBJ): guix11/xstatus.c - $(OSCC) guix11/xstatus.c + $(OSCC) guix11$(SLASH)xstatus.c xtext$(OBJ): guix11/xtext.c - $(OSCC) guix11/xtext.c + $(OSCC) guix11$(SLASH)xtext.c xtool$(OBJ): guix11/xtool.c - $(OSCC) guix11/xtool.c + $(OSCC) guix11$(SLASH)xtool.c xdialog$(OBJ): guix11/xdialog.c - $(OSCC) guix11/xdialog.c + $(OSCC) guix11$(SLASH)xdialog.c ############################################################################### # Handy commands diff -urN elvis-2.2_0/osos2/Makefile.os2,v elvis-2.2_1/osos2/Makefile.os2,v --- elvis-2.2_0/osos2/Makefile.os2,v 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/Makefile.os2,v 2004-03-26 22:35:32 +0100 @@ -1,10 +1,15 @@ -head 1.5; +head 1.6; access; symbols; locks; strict; comment @# @; +1.6 +date 2003.10.23.23.35.45; author steve; state Exp; +branches; +next 1.5; + 1.5 date 2003.10.07.15.44.07; author steve; state Exp; branches; @@ -36,15 +41,12 @@ @ -1.5 +1.6 log -@Tweaks from Herbert since 2.2i-beta. -Changed version number to 2.2 +@Herbert's latest changes. @ text -@################################################################################ -# Herbert 1998: -# Makefile for building and installing elvis under OS/2, +@# Makefile for building and installing elvis under OS/2, # derived from Makefile created by configure for linux. # Works with GNU make and nmake. ################################################################################ @@ -54,7 +56,26 @@ # both for compiling and for linking. Typical values are "cc -g" or "cc -O". # If you're compiling with X-windows support, you may need to add a # "-I/usr/X11/include" flag or something similar. -CC=icc -O -Q -DOS2 -I/work/ibmcpp/include -I/usr/include -I/tcpip/include + +# +# IBM VisualAge C++ 3.0 Compiler: +# +# This used to be the default, but since I've experienced some problems +# with its optimization and due to the lack of further maintenance by +# IBM I now recommend the OpenWatcom compiler which is now the default +# choice if Elvis is built from the `..\makos2.cmd' batch file. +# +CC=icc -O -Q -D__SPC__ -DOS2 -I/Software/ibmcpp/include -I/Software/toolkit/h -I/tcpip/include + +# +# Other Compilers: +# +# - OpenWatcom works fine, but for TCP/IP support you will need to create +# import library for `so32dll.dll' and `tcp32dll.dll'. It is now the +# default. +# - gcc is fine with versions prior to 3.2.2 (innotek builds). The latest +# versions still don't work with the X11 interface. +# ################################################################################ # This should be "unix" for all UNIX variants. It causes the compiler to use @@ -216,7 +237,7 @@ move$(OBJ) more$(OBJ) need$(OBJ) operator$(OBJ) regexp$(OBJ)\ region$(OBJ) regsub$(OBJ) search$(OBJ) spell$(OBJ) state$(OBJ)\ tinytcap$(OBJ) tag$(OBJ) tagsrch$(OBJ) tagelvis$(OBJ) url$(OBJ)\ - vi$(OBJ) vicmd$(OBJ) window$(OBJ) + vi$(OBJ) vicmd$(OBJ) window$(OBJ) autocmd$(OBJ) OBJS= $(OBJ1) $(OBJ2) $(OBJ3) REFOBJS=ref$(OBJ) tag$(OBJ) tagsrch$(OBJ) safe$(OBJ) CTOBJS= ctags$(OBJ) tag$(OBJ) safe$(OBJ) @@ -226,7 +247,7 @@ EVERY= $(ALL) elvdump$(EXE) calc$(EXE) verify$(EXE) # Herbert 1998: SHELL needs to be blanked out under OS/2 if using GNU make. #SHELL= /bin/sh -VERSION=2.2 +VERSION=2.2_0 DISTRIB=elvis-$(VERSION) DOSEXE=exedos WIN32EXE=exewin32 @@ -248,26 +269,36 @@ "CC=gcc -Wall -DOS2 -D__WITH_TERMCAP -O3 \ -I/emx/include -I/software/ibmcpp/include \ -I/software/ibmcpp/include/os2" \ - "LIBFILES=-lsocket -ltermcap" "FLAGO=-o " + "LIBFILES=-L/usr/lib/tcpipv4 -lsocket -ltermcap" \ + "FLAGO=-o " # Elvis compiled for a.out format and linked against emx.dll with x11... debug: ; $(MAKE) -f osos2\\Makefile.os2 "OBJ=.o" "EXE=x11.exe" \ "CC=gcc -g -Wall -DOS2 -D__WITH_TERMCAP -O3 \ -Zmtd -D__D_ST_MT_ERRNO__ -D__WITH_X11" \ - "FLAGO=-o " \ - "LIBFILES=-L/usr/lib/x11 -lsocket -ltermcap -lx11" + "FLAGO=-o " "LIBFILES=-L/usr/lib/x11 \ + -L/usr/lib/tcpipv4 -lsocket -ltermcap -lx11" # Elvis compiled for a.out format and linked against emx.dll with x11... x11: ; $(MAKE) elvisx11.exe -f osos2\\Makefile.os2 "OBJ=.o" "EXE=x11.exe" \ "CC=gcc -Wall -DOS2 -D__WITH_TERMCAP -O3 \ -Zmtd -D__D_ST_MT_ERRNO__ -D__WITH_X11 \ -I/usr/include -I/emx/include" "FLAGO=-o " \ - "LIBFILES=-L/usr/lib/x11 -lsocket -ltermcap -lx11" + "LIBFILES=-L/usr/lib/x11 -L/usr/lib/tcpipv4 \ + -lsocket -ltermcap -lx11" + +gcc: ; $(MAKE) -f osos2\\Makefile.os2 "EXE=gcc.exe" "FLAGO=-o " "OBJ=.o" \ + "CC=gcc -Wall -DOS2 -Zomf -O3 -I/emx/include" \ + "LIBFILES=-L/usr/lib/x11 -L/usr/lib/tcpipv4 -lsocket" + +wcc: ; $(MAKE) -f osos2\\Makefile.os2 "FLAGO=-fe=" "OBJ=.obj" \ + "CC=wcl386 -zq -otexan -I\\tcpip\\include -dexplicit=expl"\ + "LIBFILES=so32dll.lib tcp32dll.lib" DEFFILE="" + +wcc-no-tcp: ; $(MAKE) elvis-no-tcp$(EXE) -f osos2\\Makefile.os2 "FLAGO=-fe=" \ + "CC=wcl386 -zq -otexan -I\\tcpip\\include -dexplicit=expl"\ + LIBFILES="" DEFFILE="" -gcc: ; $(MAKE) -f osos2\\Makefile.os2 "EXE=gcc.exe" "FLAGO=-o " \ - "CC=gcc -Wall -DOS2 -Zsys -Zomf -O3 -I/emx/include" \ - "LIBFILES=" - elvis$(EXE): $(HDRS) main$(OBJ) $(OBJS) $(GUIOBJS) $(LPOBJS) $(CC) $(CFLAGS) $(LDFLAGS) main$(OBJ) $(OBJS) $(GUIOBJS) $(LPOBJS) $(LIBFILES) $(DEFFILE) $(FLAGO)elvis$(EXE) @@ -354,31 +385,31 @@ # broken down differently. guix11$(OBJ): guix11/guix11.c $(XBM) - $(OSCC) guix11/guix11.c + $(OSCC) guix11$(SLASH)guix11.c xclip$(OBJ): guix11/xclip.c - $(OSCC) guix11/xclip.c + $(OSCC) guix11$(SLASH)xclip.c xevent$(OBJ): guix11/xevent.c - $(OSCC) guix11/xevent.c + $(OSCC) guix11$(SLASH)xevent.c xmisc$(OBJ): guix11/xmisc.c - $(OSCC) guix11/xmisc.c + $(OSCC) guix11$(SLASH)xmisc.c xscroll$(OBJ): guix11/xscroll.c - $(OSCC) guix11/xscroll.c + $(OSCC) guix11$(SLASH)xscroll.c xstatus$(OBJ): guix11/xstatus.c - $(OSCC) guix11/xstatus.c + $(OSCC) guix11$(SLASH)xstatus.c xtext$(OBJ): guix11/xtext.c - $(OSCC) guix11/xtext.c + $(OSCC) guix11$(SLASH)xtext.c xtool$(OBJ): guix11/xtool.c - $(OSCC) guix11/xtool.c + $(OSCC) guix11$(SLASH)xtool.c xdialog$(OBJ): guix11/xdialog.c - $(OSCC) guix11/xdialog.c + $(OSCC) guix11$(SLASH)xdialog.c ############################################################################### # Handy commands @@ -429,6 +460,69 @@ @ +1.5 +log +@Tweaks from Herbert since 2.2i-beta. +Changed version number to 2.2 +@ +text +@a0 2 +################################################################################ +# Herbert 1998: +d11 20 +a30 1 +CC=icc -O -Q -DOS2 -I/work/ibmcpp/include -I/usr/include -I/tcpip/include +d192 1 +a192 1 + vi$(OBJ) vicmd$(OBJ) window$(OBJ) +d202 1 +a202 1 +VERSION=2.2 +d224 2 +a225 1 + "LIBFILES=-lsocket -ltermcap" "FLAGO=-o " +d231 2 +a232 2 + "FLAGO=-o " \ + "LIBFILES=-L/usr/lib/x11 -lsocket -ltermcap -lx11" +d239 14 +a252 1 + "LIBFILES=-L/usr/lib/x11 -lsocket -ltermcap -lx11" +a253 4 +gcc: ; $(MAKE) -f osos2\\Makefile.os2 "EXE=gcc.exe" "FLAGO=-o " \ + "CC=gcc -Wall -DOS2 -Zsys -Zomf -O3 -I/emx/include" \ + "LIBFILES=" + +d340 1 +a340 1 + $(OSCC) guix11/guix11.c +d343 1 +a343 1 + $(OSCC) guix11/xclip.c +d346 1 +a346 1 + $(OSCC) guix11/xevent.c +d349 1 +a349 1 + $(OSCC) guix11/xmisc.c +d352 1 +a352 1 + $(OSCC) guix11/xscroll.c +d355 1 +a355 1 + $(OSCC) guix11/xstatus.c +d358 1 +a358 1 + $(OSCC) guix11/xtext.c +d361 1 +a361 1 + $(OSCC) guix11/xtool.c +d364 1 +a364 1 + $(OSCC) guix11/xdialog.c +@ + + 1.4 log @Changed the version number to 2.2i-beta diff -urN elvis-2.2_0/osos2/config-no-tcp.h elvis-2.2_1/osos2/config-no-tcp.h --- elvis-2.2_0/osos2/config-no-tcp.h 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/config-no-tcp.h 2004-03-26 22:35:32 +0100 @@ -42,11 +42,13 @@ #define FEATURE_CACHEDESC /* store syntax/markup descriptions in RAM */ #define FEATURE_CALC /* the calculator, and all cmds that use it */ #define FEATURE_COMPLETE /* filename completion */ +#define FEATURE_EQUALTILDE /* :let option =~ excmdline */ #define FEATURE_FOLD /* the :fold and :unfold commands */ #define FEATURE_G /* most of the visual 'g' commands */ #define FEATURE_HLOBJECT /* the hlobject and hllayers options */ #define FEATURE_HLSEARCH /* the hlsearch option */ #define FEATURE_INCSEARCH /* the incsearch option */ +#define FEATURE_LISTCHARS /* the listchars option */ #define FEATURE_LITRE /* faster searches for literal strings */ #define FEATURE_LPR /* the :lpr command */ #define FEATURE_MAKE /* the :make and :cc commands */ @@ -54,6 +56,7 @@ #define FEATURE_MISC /* lots of little things */ #define FEATURE_MKEXRC /* the :mkexrc command */ #define FEATURE_NORMAL /* vim-style :normal command */ +#define FEATURE_PERSIST /* the persistfile option */ #define FEATURE_PROTO /* using aliases to add new protocols */ #define FEATURE_RAM /* using ram instead of disk for session files */ #undef FEATURE_RCSID /* include RCS Id strings for all source files */ @@ -67,8 +70,6 @@ #define FEATURE_TEXTOBJ /* text objects */ #define FEATURE_V /* the v/V/^V marking commands */ #undef FEATURE_XFT /* antialiased fonts in X11 */ -#define FEATURE_LISTCHARS /* the listchars option */ -#define FEATURE_EQUALTILDE /* :let option =~ excmdline */ /* The following provide custom implementation of some common functions which diff -urN elvis-2.2_0/osos2/config-with-tcp.h elvis-2.2_1/osos2/config-with-tcp.h --- elvis-2.2_0/osos2/config-with-tcp.h 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/config-with-tcp.h 2004-03-26 22:35:32 +0100 @@ -48,11 +48,13 @@ #define FEATURE_CACHEDESC /* store syntax/markup descriptions in RAM */ #define FEATURE_CALC /* the calculator, and all cmds that use it */ #define FEATURE_COMPLETE /* filename completion */ +#define FEATURE_EQUALTILDE /* :let option =~ excmdline */ #define FEATURE_FOLD /* the :fold and :unfold commands */ #define FEATURE_G /* most of the visual 'g' commands */ #define FEATURE_HLOBJECT /* the hlobject and hllayers options */ #define FEATURE_HLSEARCH /* the hlsearch option */ #define FEATURE_INCSEARCH /* the incsearch option */ +#define FEATURE_LISTCHARS /* the listchars option */ #define FEATURE_LITRE /* faster searches for literal strings */ #define FEATURE_LPR /* the :lpr command */ #define FEATURE_MAKE /* the :make and :cc commands */ @@ -60,6 +62,7 @@ #define FEATURE_MISC /* lots of little things */ #define FEATURE_MKEXRC /* the :mkexrc command */ #define FEATURE_NORMAL /* vim-style :normal command */ +#define FEATURE_PERSIST /* the persistfile option */ #define FEATURE_PROTO /* using aliases to add new protocols */ #define FEATURE_RAM /* using ram instead of disk for session files */ #undef FEATURE_RCSID /* include RCS Id strings for all source files */ @@ -73,8 +76,6 @@ #define FEATURE_TEXTOBJ /* text objects */ #define FEATURE_V /* the v/V/^V marking commands */ #undef FEATURE_XFT /* antialiased fonts in X11 */ -#define FEATURE_LISTCHARS /* the listchars option */ -#define FEATURE_EQUALTILDE /* :let option =~ excmdline */ /* The following provide custom implementation of some common functions which diff -urN elvis-2.2_0/osos2/guivio.c elvis-2.2_1/osos2/guivio.c --- elvis-2.2_0/osos2/guivio.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/guivio.c 2004-03-26 22:35:32 +0100 @@ -6,9 +6,17 @@ * adapted to Elvis 2.2 by Herbert. * * $Log: guivio.c,v $ - * Revision 1.9 2003/10/17 17:41:23 steve - * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with - * types defined other headers. + * Revision 1.11 2004/02/06 01:13:19 steve + * Made maps use the "nosave" attribute to distinguish automatically mapped + * keys from user-defined keys. This affects both saving via :mkexrc, and + * listing via :map. + * + * Revision 1.10 2003/10/23 23:35:45 steve + * Herbert's latest changes. + * + * Revision 1.9 2003/10/17 17:41:23 steve + * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with + * types defined other headers. * * Revision 1.8 2003/10/12 18:36:18 steve * Changed elvis' ctype macro names to start with "elv" @@ -31,9 +39,21 @@ * */ +#define CHAR ELVCHAR #include "elvis.h" #ifdef GUI_VIO #include "guivio.h" +#ifdef CHAR +# undef CHAR +#endif +#define INCL_VIO +#define INCL_KBD +#define INCL_DOSPROCESS +#define INCL_DOSERRORS +#include + +#include + /*#undef NDEBUG*/ #include "debug.h" #include @@ -56,33 +76,33 @@ } keys[] = { /* Grey keys. */ - { "", "\013e048", "k", MAP_ALL }, - { "", "\013e050", "j", MAP_ALL }, - { "", "\013e04b", "h", MAP_ALL }, - { "", "\013e04d", "l", MAP_ALL }, - { "", "\013e049", "\002", MAP_ALL }, - { "", "\013e051", "\006", MAP_ALL }, - { "", "\013e047", "^", MAP_ALL }, - { "", "\013e04f", "$", MAP_ALL }, - { "", "\013e052", "i", MAP_ALL }, - { "", "\013e053", "x", MAP_ALL }, + { "", "\013e048", "k", MAP_NOSAVE|MAP_ALL }, + { "", "\013e050", "j", MAP_NOSAVE|MAP_ALL }, + { "", "\013e04b", "h", MAP_NOSAVE|MAP_ALL }, + { "", "\013e04d", "l", MAP_NOSAVE|MAP_ALL }, + { "", "\013e049", "\002", MAP_NOSAVE|MAP_ALL }, + { "", "\013e051", "\006", MAP_NOSAVE|MAP_ALL }, + { "", "\013e047", "^", MAP_NOSAVE|MAP_ALL }, + { "", "\013e04f", "$", MAP_NOSAVE|MAP_ALL }, + { "", "\013e052", "i", MAP_NOSAVE|MAP_ALL }, + { "", "\013e053", "x", MAP_NOSAVE|MAP_ALL }, /* Numeric keypad keys (with Num Lock off.) */ - { "", "\0130048", "k", MAP_ALL }, - { "", "\0130050", "j", MAP_ALL }, - { "", "\013004b", "h", MAP_ALL }, - { "", "\013004d", "l", MAP_ALL }, - { "", "\0130049", "\002", MAP_ALL }, - { "", "\0130051", "\006", MAP_ALL }, - { "", "\0130047", "^", MAP_ALL }, - { "", "\013004f", "$", MAP_ALL }, - { "", "\0130052", "i", MAP_ALL }, - { "", "\0130053", "x", MAP_ALL }, - { "", "\0132fe0", "/", MAP_ALL }, - { "", "\0130de0", "\r", MAP_ALL }, + { "", "\0130048", "k", MAP_NOSAVE|MAP_ALL }, + { "", "\0130050", "j", MAP_NOSAVE|MAP_ALL }, + { "", "\013004b", "h", MAP_NOSAVE|MAP_ALL }, + { "", "\013004d", "l", MAP_NOSAVE|MAP_ALL }, + { "", "\0130049", "\002", MAP_NOSAVE|MAP_ALL }, + { "", "\0130051", "\006", MAP_NOSAVE|MAP_ALL }, + { "", "\0130047", "^", MAP_NOSAVE|MAP_ALL }, + { "", "\013004f", "$", MAP_NOSAVE|MAP_ALL }, + { "","\0130052", "i", MAP_NOSAVE|MAP_ALL }, + { "","\0130053", "x", MAP_NOSAVE|MAP_ALL }, + { "", "\0132fe0", "/", MAP_NOSAVE|MAP_ALL }, + { "", "\0130de0", "\r", MAP_NOSAVE|MAP_ALL }, /* Unshifted function keys. */ - { "#1", "\013003b", ":help\r", MAP_ALL }, + { "#1", "\013003b", ":help\r",MAP_NOSAVE|MAP_ALL }, { "#2", "\013003c" }, { "#3", "\013003d" }, { "#4", "\013003e" }, @@ -91,48 +111,48 @@ { "#7", "\0130041" }, { "#8", "\0130042" }, { "#9", "\0130043" }, - { "#10", "\0130044" }, - { "#11", "\0130085" }, - { "#12", "\0130086" }, + { "#10", "\0130044" }, + { "#11", "\0130085" }, + { "#12", "\0130086" }, /* Shift-function keys. */ - { "#1s", "\0130054" }, - { "#2s", "\0130055" }, - { "#3s", "\0130056" }, - { "#4s", "\0130057" }, - { "#5s", "\0130058" }, - { "#6s", "\0130059" }, - { "#7s", "\013005a" }, - { "#8s", "\013005b" }, - { "#9s", "\013005c" }, + { "#1s", "\0130054" }, + { "#2s", "\0130055" }, + { "#3s", "\0130056" }, + { "#4s", "\0130057" }, + { "#5s", "\0130058" }, + { "#6s", "\0130059" }, + { "#7s", "\013005a" }, + { "#8s", "\013005b" }, + { "#9s", "\013005c" }, { "#10s", "\013005d" }, { "#11s", "\0130087" }, { "#12s", "\0130088" }, /* Ctrl-function keys. */ - { "#1c", "\013005e" }, - { "#2c", "\013005f" }, - { "#3c", "\0130060" }, - { "#4c", "\0130061" }, - { "#5c", "\0130062" }, - { "#6c", "\0130063" }, - { "#7c", "\0130064" }, - { "#8c", "\0130065" }, - { "#9c", "\0130066" }, + { "#1c", "\013005e" }, + { "#2c", "\013005f" }, + { "#3c", "\0130060" }, + { "#4c", "\0130061" }, + { "#5c", "\0130062" }, + { "#6c", "\0130063" }, + { "#7c", "\0130064" }, + { "#8c", "\0130065" }, + { "#9c", "\0130066" }, { "#10c", "\0130067" }, { "#11c", "\0130089" }, { "#12c", "\013008a" }, /* Alt-function keys. */ - { "#1a", "\0130068" }, - { "#2a", "\0130069" }, - { "#3a", "\013006a" }, - { "#4a", "\013006b" }, - { "#5a", "\013006c" }, - { "#6a", "\013006d" }, - { "#7a", "\013006e" }, - { "#8a", "\013006f" }, - { "#9a", "\0130070" }, + { "#1a", "\0130068" }, + { "#2a", "\0130069" }, + { "#3a", "\013006a" }, + { "#4a", "\013006b" }, + { "#5a", "\013006c" }, + { "#6a", "\013006d" }, + { "#7a", "\013006e" }, + { "#8a", "\013006f" }, + { "#9a", "\0130070" }, { "#10a", "\0130071" }, { "#11a", "\013008b" }, { "#12a", "\013008c" } @@ -445,7 +465,8 @@ /* Boxing is simulated as color swapping. This has to be done on * the final color, so we don't care about this now. */ - if (resetting & COLOR_BOXED|COLOR_LEFTBOX|COLOR_RIGHTBOX) + /*if (resetting & COLOR_BOXED|COLOR_LEFTBOX|COLOR_RIGHTBOX) */ + if (resetting & (COLOR_BOXED|COLOR_LEFTBOX|COLOR_RIGHTBOX)) { currentbits &= ~COLOR_BOXED; } @@ -852,7 +873,7 @@ long fg, /* foreground color */ long bg, /* background color */ int bits, /* other attributes */ - CHAR *text, /* text to draw */ + ELVCHAR *text, /* text to draw */ int len) /* length of text */ { VWIN *vw = (GUIWIN *)gw; @@ -1554,10 +1575,10 @@ /* This function converts key labels to raw codes */ static int -keylabel (CHAR *given, /* what the user typed in as the key name */ +keylabel (ELVCHAR *given, /* what the user typed in as the key name */ int givenlen, /* length of the "given" string */ - CHAR **label, /* standard name for that key */ - CHAR **rawptr) /* control code sent by that key */ + ELVCHAR **label, /* standard name for that key */ + ELVCHAR **rawptr) /* control code sent by that key */ { int i; @@ -1591,7 +1612,7 @@ /* This function defines colors for fonts */ static ELVBOOL vio_color(int fontcode, /* name of font being changed */ - CHAR *name, /* name of new color */ + ELVCHAR *name, /* name of new color */ ELVBOOL isfg, /* ElvTrue for foreground, ElvFalse for background */ long *colorptr, /* where to store the color number */ unsigned char rgb[3]) /* color broken down into RGB components */ diff -urN elvis-2.2_0/osos2/guivio.h elvis-2.2_1/osos2/guivio.h --- elvis-2.2_0/osos2/guivio.h 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/guivio.h 2004-03-26 22:35:32 +0100 @@ -12,20 +12,6 @@ #if !defined(_GUIVIO_H) #define _GUIVIO_H -#define INCL_VIO -#define INCL_KBD -#define INCL_DOSPROCESS -#define INCL_DOSERRORS -#ifdef __EMX__ -# define USE_OS2_TOOLKIT_HEADERS -#endif -#include -#ifdef CHAR -# undef CHAR -#endif - -#include - /* * A VIO color index. The four high-order bits contain the background * color, while the four low-order bits contain the foreground colour. diff -urN elvis-2.2_0/osos2/osblock.c elvis-2.2_1/osos2/osblock.c --- elvis-2.2_0/osos2/osblock.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/osblock.c 2004-03-26 22:35:32 +0100 @@ -8,9 +8,12 @@ * this way, anyhow. :-) * * $Log: osblock.c,v $ - * Revision 1.5 2003/10/17 17:41:23 steve - * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with - * types defined other headers. + * Revision 1.6 2003/10/23 23:35:45 steve + * Herbert's latest changes. + * + * Revision 1.5 2003/10/17 17:41:23 steve + * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with + * types defined other headers. * * Revision 1.4 2002/07/30 17:02:46 steve * OS/2 changes from Herbert. @@ -32,7 +35,7 @@ #define INCL_DOSFILEMGR #define INCL_DOSERRORS #ifdef __EMX__ -# define USE_OS2_TOOLKIT_HEADERS +#define CHAR OS2CHAR #endif #include #ifdef CHAR diff -urN elvis-2.2_0/osos2/osdir.c elvis-2.2_1/osos2/osdir.c --- elvis-2.2_0/osos2/osdir.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/osdir.c 2004-03-26 22:35:32 +0100 @@ -11,9 +11,8 @@ * Martin "Herbert" Dietze. * * $Log: osdir.c,v $ - * Revision 1.14 2003/10/17 17:41:23 steve - * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with - * types defined other headers. + * Revision 1.15 2003/10/23 23:35:45 steve + * Herbert's latest changes. * * Revision 1.13 2003/10/12 18:36:18 steve * Changed elvis' ctype macro names to start with "elv" @@ -55,13 +54,14 @@ #include #ifdef __IBMC__ /* Herbert: not needed for emx/gcc */ # include +# include #endif #include #include #if !defined(JUST_DIRFIRST) && !defined(JUST_DIRPATH) # include "elvis.h" # ifdef FEATURE_RCSID -char id_osdir[] = "$Id: osdir.c,v 1.14 2003/10/17 17:41:23 steve Exp $"; +char id_osdir[] = "$Id: osdir.c,v 1.15 2003/10/23 23:35:45 steve Exp $"; # endif #endif @@ -77,7 +77,8 @@ #define INCL_DOSFILEMGR #define INCL_DOSERRORS #ifdef __EMX__ -# define USE_OS2_TOOLKIT_HEADERS +/*# define USE_OS2_TOOLKIT_HEADERS*/ +#define CHAR OS2CHAR #endif #include #ifdef CHAR @@ -526,11 +527,11 @@ return DIR_BADPATH; } } - if ((st.st_mode & S_IFMT) == S_IFDIR) + if ((st.st_mode & S_IFDIR) != 0) { return DIR_DIRECTORY; } - else if ((st.st_mode & S_IFMT) != S_IFREG) + else if ((st.st_mode & S_IFREG) == 0) { return DIR_NOTFILE; } diff -urN elvis-2.2_0/osos2/osnet.c elvis-2.2_1/osos2/osnet.c --- elvis-2.2_0/osos2/osnet.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/osnet.c 2004-03-26 22:35:32 +0100 @@ -5,9 +5,12 @@ * Herbert * * $Log: osnet.c,v $ - * Revision 1.5 2003/10/17 17:41:23 steve - * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with - * types defined other headers. + * Revision 1.6 2003/10/23 23:35:45 steve + * Herbert's latest changes. + * + * Revision 1.5 2003/10/17 17:41:23 steve + * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with + * types defined other headers. * * Revision 1.4 2003/10/12 18:36:18 steve * Changed elvis' ctype macro names to start with "elv" @@ -77,6 +80,12 @@ # define BSD_SELECT # include # endif +# ifdef __WATCOMC__ +# define BSD_SELECT + typedef long off_t; + #include + #include +# endif # ifdef __EMX__ # include # include @@ -86,7 +95,6 @@ # ifdef __EMX__ # include # include -# include # endif # include # ifdef __IBMC__ diff -urN elvis-2.2_0/osos2/osprg.c elvis-2.2_1/osos2/osprg.c --- elvis-2.2_0/osos2/osprg.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/osprg.c 2004-03-26 22:35:32 +0100 @@ -7,9 +7,12 @@ * Martin "Herbert" Dietze. * * $Log: osprg.c,v $ - * Revision 1.5 2003/10/17 17:41:23 steve - * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with - * types defined other headers. + * Revision 1.6 2003/10/23 23:35:45 steve + * Herbert's latest changes. + * + * Revision 1.5 2003/10/17 17:41:23 steve + * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with + * types defined other headers. * * Revision 1.4 2001/10/23 01:37:09 steve * Sometweaks of FEATURE_XXXX names @@ -38,14 +41,14 @@ #include #include "elvis.h" #ifdef FEATURE_RCSID -char id_osprg[] = "$Id: osprg.c,v 1.5 2003/10/17 17:41:23 steve Exp $"; +char id_osprg[] = "$Id: osprg.c,v 1.6 2003/10/23 23:35:45 steve Exp $"; #endif #define INCL_DOSQUEUES #define INCL_DOSPROCESS #define INCL_DOSERRORS #ifdef __EMX__ -# define USE_OS2_TOOLKIT_HEADERS +#define CHAR OS2CHAR #endif #include #ifdef CHAR diff -urN elvis-2.2_0/osos2/ostext.c elvis-2.2_1/osos2/ostext.c --- elvis-2.2_0/osos2/ostext.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osos2/ostext.c 2004-03-26 22:35:32 +0100 @@ -5,9 +5,12 @@ * Martin "Herbert" Dietze. * * $Log: ostext.c,v $ - * Revision 1.5 2003/10/17 17:41:23 steve - * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with - * types defined other headers. + * Revision 1.6 2003/10/23 23:35:45 steve + * Herbert's latest changes. + * + * Revision 1.5 2003/10/17 17:41:23 steve + * Renamed the BOOLEAN data type to ELVBOOL to avoid name clashes with + * types defined other headers. * * Revision 1.4 2001/10/23 01:37:09 steve * Sometweaks of FEATURE_XXXX names @@ -31,12 +34,12 @@ #include #include #include -#ifdef __EMX__ +#if defined __EMX__ || defined __WATCOMC__ # define EACCESS EPERM #endif #include "elvis.h" #ifdef FEATURE_RCSID -char id_ostext[] = "$Id: ostext.c,v 1.5 2003/10/17 17:41:23 steve Exp $"; +char id_ostext[] = "$Id: ostext.c,v 1.6 2003/10/23 23:35:45 steve Exp $"; #endif diff -urN elvis-2.2_0/osunix/osnet.c elvis-2.2_1/osunix/osnet.c --- elvis-2.2_0/osunix/osnet.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/osunix/osnet.c 2004-03-26 22:35:32 +0100 @@ -48,7 +48,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_osnet[] = "$Id: osnet.c,v 2.22 2003/10/17 17:41:23 steve Exp $"; +char id_osnet[] = "$Id: osnet.c,v 2.23 2004/02/25 19:20:14 steve Exp $"; #endif #if defined(PROTOCOL_HTTP) || defined(PROTOCOL_FTP) @@ -84,7 +84,7 @@ #ifdef NEED_INET_ATON /* This is to avoid clashes with declarations in libraries. You might think - * that no compiler would declare this in a function without providing it in + * that no compiler would declare this in a header without providing it in * a library, but in fact that is the case in Cygwin, and probably others. */ # define inet_aton elvis_iten_aton diff -urN elvis-2.2_0/oswin32/osconfig.h elvis-2.2_1/oswin32/osconfig.h --- elvis-2.2_0/oswin32/osconfig.h 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/oswin32/osconfig.h 2004-03-26 22:35:32 +0100 @@ -30,6 +30,7 @@ #define FEATURE_CACHEDESC /* store syntax/markup descriptions in RAM */ #define FEATURE_CALC /* the calculator, and all cmds that use it */ #define FEATURE_COMPLETE /* filename completion */ +#define FEATURE_EQUALTILDE /* :let option =~ excmdline */ #define FEATURE_FOLD /* the :fold and :unfold commands */ #define FEATURE_G /* most of the visual 'g' commands */ #define FEATURE_HLOBJECT /* the hlobject and hllayers options */ @@ -38,6 +39,7 @@ #define FEATURE_IMAGE /* gui can use background image */ #endif #define FEATURE_INCSEARCH /* the incsearch option */ +#define FEATURE_LISTCHARS /* the listchars option */ #define FEATURE_LITRE /* faster searches for literal strings */ #define FEATURE_LPR /* the ":lpr" command */ #define FEATURE_MAKE /* the :make and :cc commands */ @@ -45,6 +47,7 @@ #define FEATURE_MISC /* lots of little things */ #define FEATURE_MKEXRC /* the ":mkexrc" command */ #define FEATURE_NORMAL /* vim-style :normal command */ +#define FEATURE_PERSIST /* the persistfile option */ #define FEATURE_PROTO /* using aliases to add new protocols */ #undef FEATURE_RAM /* store edit buffers in RAM if "-f ram" */ #undef FEATURE_RCSID /* include RCS Id strings for all source files */ @@ -58,8 +61,6 @@ #define FEATURE_TEXTOBJ /* text objects */ #define FEATURE_V /* the v/V/^V marking commands */ #undef FEATURE_XFT /* antialiased fonts in X11 -- not useful for Windows */ -#define FEATURE_LISTCHARS /* the listchars option */ -#define FEATURE_EQUALTILDE /* :let option =~ excmdline */ /* The following provide custom implementation of some common functions which * are either missing or poorly implemented on some systems. diff -urN elvis-2.2_0/oswin32/tcaphelp.c elvis-2.2_1/oswin32/tcaphelp.c --- elvis-2.2_0/oswin32/tcaphelp.c 2003-10-21 04:32:26 +0200 +++ elvis-2.2_1/oswin32/tcaphelp.c 2004-03-26 22:35:32 +0100 @@ -3,7 +3,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_tcaphelp[] = "$Id: tcaphelp.c,v 2.34 2003/10/17 17:41:23 steve Exp $"; +char id_tcaphelp[] = "$Id: tcaphelp.c,v 2.35 2004/01/30 00:55:08 steve Exp $"; #endif #if defined(GUI_TERMCAP) || defined(GUI_OPEN) # define CHAR CHAR_nt @@ -436,7 +436,8 @@ /* Ctrl-6 should be a ^^ character */ buf[got++] = ELVCTRL('^'); } - else if (!strchr("EF68*:\x1d", (char)event.Event.KeyEvent.wVirtualScanCode)) + else if (event.Event.KeyEvent.wVirtualScanCode >= ' ' + && !strchr("EF68*:", (char)event.Event.KeyEvent.wVirtualScanCode)) { buf[got++] = '#'; buf[got++] = (char)event.Event.KeyEvent.wVirtualScanCode; diff -urN elvis-2.2_0/region.c elvis-2.2_1/region.c --- elvis-2.2_0/region.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/region.c 2004-03-26 22:35:29 +0100 @@ -89,19 +89,19 @@ /* for each region... */ if (lag) *lag = after; for (r = after ? after->next : markbuffer(from)->regions; - r && markoffset(r->to) <= markoffset(from); + r && markoffset(r->from) < markoffset(to); r = r->next) { + /* did we find a match? */ + if (markoffset(r->to) > markoffset(from) + && (!font || r->font == font)) + /* Yes! return it */ + return r; + + /* update the lag pointer */ if (lag) *lag = r; } - /* did we find a match? */ - if (r - && markoffset(r->from) < markoffset(to) - && (!font || r->font == font)) - /* Yes! return it */ - return r; - /* no matching region was found */ return NULL; } @@ -333,7 +333,7 @@ return rgnfind(mark, &tmp, '\0', NULL, NULL); } -/* This implements the :region and :unregion commands. */ +/* This implements the :region, :unregion, and :chregion commands. */ RESULT ex_region(xinf) EXINFO *xinf; /* details about the command */ { @@ -409,13 +409,11 @@ if (comment) { *comment++ = '\0'; - while (*comment == ' '); + while (*comment == ' ') comment++; if (*comment == '\0') - comment = xinf->rhs; + comment = NULL; } - else - comment = xinf->rhs; newfont = colorfind(xinf->rhs); /* for each matching region... */ @@ -424,8 +422,11 @@ { /* change the font & comment */ r->font = newfont; - safefree(r->comment); - r->comment = CHARdup(comment); + if (comment || !CHARcmp(r->comment, xinf->lhs)) + { + safefree(r->comment); + r->comment = CHARdup(comment ? comment : xinf->rhs); + } } /* clean up abutting regions, etc. */ diff -urN elvis-2.2_0/search.c elvis-2.2_1/search.c --- elvis-2.2_0/search.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/search.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_search[] = "$Id: search.c,v 2.56 2003/10/17 17:41:23 steve Exp $"; +char id_search[] = "$Id: search.c,v 2.57 2004/03/21 23:23:01 steve Exp $"; #endif static RESULT searchenter P_((WINDOW win)); @@ -742,6 +742,10 @@ ELVBOOL success; /* did the search succeed? */ CHAR dir; /* '/' for forward, or '?' for backward */ CHAR text[115]; /* the search regexp so far, as text */ +#ifdef FEATURE_MISC + ELVBOOL edit; /* in the middle of an edit command? */ + long line; /* line number in history */ +#endif } INCINFO; @@ -755,6 +759,7 @@ ELVBOOL oldhide; RESULT rc; CHAR *cp, *retext, *build, *scan; + BUFFER history; /* add this keystroke into the regexp string */ if (ii->quote) @@ -768,6 +773,57 @@ else guibeep(ii->win); } +#ifdef FEATURE_MISC + else if (ii->edit) + { + MARK mark; + CHAR *scan; + int i; + + ii->edit = ElvFalse; + switch (key) + { + case 'k': + case 'j': + history = bufalloc(toCHAR(REGEXP_BUF), 0, ElvTrue); + if ((key == 'k' && ii->line <= 1) || (key == 'j' && ii->line >= o_buflines(history))) + { + guibeep(ii->win); + return RESULT_MORE; + } + + /* adjust the line number */ + if (key == 'k') + ii->line--; + else + ii->line++; + + /* copy that line into text[] */ + mark = markalloc(history, 0); + marksetline(mark, ii->line); + scanalloc(&scan, mark); + if (*scan == '/' || *scan == '?') + { + ii->dir = *scan; + scannext(&scan); + } + for (i = 0; + i < QTY(ii->text) - 2 && scan && *scan != '\n'; + i++, scannext(&scan)) + { + ii->text[i] = *scan; + } + ii->text[i] = '\0'; + scanfree(&scan); + markfree(mark); + break; + + default: + /* other commands aren't supported */ + guibeep(ii->win); + } + } +#endif else { switch (key) @@ -783,7 +839,14 @@ break; } - /* Otherwise we've already searched */ + /* Otherwise we've already searched; the cursor is + * where it belongs. All we need to do now is save + * the search expression in the history. + */ + history = bufalloc(toCHAR(REGEXP_BUF), 0, ElvTrue); + bufappend(history, &ii->dir, 1); + bufappend(history, ii->text, len); + bufappend(history, toCHAR("\n"), 1); return RESULT_COMPLETE; case '\177': @@ -807,6 +870,10 @@ ii->dir, ii->text); return RESULT_MORE; + case ELVCTRL('O'): + ii->edit = ElvTrue; + return RESULT_MORE; + default: if (len < QTY(ii->text) - 2) ii->text[len] = key; @@ -1091,17 +1158,21 @@ win->state->perform = incperform; win->state->shape = incshape; win->state->info = ii = safealloc(1, sizeof (INCINFO)); - win->state->mapflags = (MAPFLAGS)0; + win->state->mapflags = MAP_HISTORY; win->state->modename = "IncSrch"; /* initialize the INCINFO */ ii->win = win; ii->from = markdup(win->cursor); - ii->quote = ElvFalse; ii->rightward = 0L; + ii->quote = ElvFalse; ii->success = ElvFalse; ii->dir = vinf->command; ii->text[0] = '\0'; +#ifdef FEATURE_MISC + ii->edit = ElvFalse; + ii->line = o_buflines(bufalloc(toCHAR(REGEXP_BUF), 0, ElvTrue)) + 1; +#endif /* show the prompt as a status message */ msg(MSG_STATUS, "[CS]$1$2", ii->dir, ii->text); diff -urN elvis-2.2_0/spell.c elvis-2.2_1/spell.c --- elvis-2.2_0/spell.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/spell.c 2004-03-26 22:35:29 +0100 @@ -9,7 +9,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_spell[] = "$Id: spell.c,v 1.38 2003/10/17 17:41:23 steve Exp $"; +char id_spell[] = "$Id: spell.c,v 1.39 2004/03/21 23:24:41 steve Exp $"; #endif #define MAXWLEN 100 /* maximum word length */ @@ -799,7 +799,6 @@ void spellsave(custom) BUFFER custom; /* buffer to append spell commands to, or NULL */ { - MARKBUF end; int i, col, len; spellcheck_t level; @@ -820,9 +819,7 @@ CHARcat(saveline, toCHAR("\n")); if (custom) { - end.buffer = custom; - end.offset = o_bufchars(custom); - bufreplace(&end, &end, saveline, CHARlen(saveline)); + bufappend(custom, saveline, 0); } else { @@ -835,8 +832,6 @@ return; /* also save the :check commands */ - end.buffer = custom; - end.offset = o_bufchars(custom); for (level = SPELL_CHECK_ALL; level <= SPELL_CHECK_NONE; level++) { for (i = 1, col = 0; i < colornpermanent; i++) @@ -850,37 +845,32 @@ { if (col > 0) { - bufreplace(&end, &end, toCHAR("\n"), 1); - end.offset++; + bufappend(custom, toCHAR("\n"), 1); } - bufreplace(&end, &end, + bufappend(custom, toCHAR(level == SPELL_CHECK_NONE ? "try check -" : level == SPELL_CHECK_TAGONLY ? "try check +" : "try check *"), 11); - end.offset += 11; col = 11; } else { /* space between words */ - bufreplace(&end, &end, blanks, 1); - end.offset++; + bufappend(custom, blanks, 1); col++; } /* add this font name */ - bufreplace(&end, &end, colorinfo[i].name, len); - end.offset += len; + bufappend(custom, colorinfo[i].name, len); } /* end the line */ if (col > 0) { - bufreplace(&end, &end, toCHAR("\n"), 1); - end.offset++; + bufappend(custom, toCHAR("\n"), 1); } } } diff -urN elvis-2.2_0/state.c elvis-2.2_1/state.c --- elvis-2.2_0/state.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/state.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_state[] = "$Id: state.c,v 2.43 2003/10/17 17:41:23 steve Exp $"; +char id_state[] = "$Id: state.c,v 2.44 2004/02/05 15:47:35 steve Exp $"; #endif #if USE_PROTOTYPES @@ -299,7 +299,7 @@ * function, then end it now. */ if (windefault - && ((focus->state->acton->flags & ELVIS_BOTTOM) != 0 + && ((focus->state->acton && (focus->state->acton->flags & ELVIS_BOTTOM) != 0) || (focus->state->flags & (ELVIS_ONCE|ELVIS_1LINE|ELVIS_POP)) == 0)) drawopencomplete(focus); diff -urN elvis-2.2_0/tinytcap.c elvis-2.2_1/tinytcap.c --- elvis-2.2_0/tinytcap.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/tinytcap.c 2004-03-26 22:35:29 +0100 @@ -22,7 +22,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_tinytcap[] = "$Id: tinytcap.c,v 2.26 2001/10/23 01:37:09 steve Exp $"; +char id_tinytcap[] = "$Id: tinytcap.c,v 2.27 2004/01/30 23:53:18 steve Exp $"; #endif #ifdef NEED_TGETENT # include @@ -110,7 +110,7 @@ "nansi", ":al=\033[L:dl=\033[M:AL=\033[%dL:DL=\033[%dM:am:bs:ce=\033[K:cl=\033[2J:\ :cm=\033[%i%d;%dH:co#80:\ -:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\ +:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:F1=#W:F2=#X:\ :s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\ :c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\ :a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\ @@ -123,7 +123,7 @@ "pcbios", ":al=\033[L:dl=\033[M:AL=\033[%dL:DL=\033[%dM:am:bs:ce=\033[K:cl=\033[2J:\ :cm=\033[%i%d;%dH:co#80:\ -:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\ +:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:F1=#W:F2=#X:\ :s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\ :c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\ :a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\ @@ -139,7 +139,7 @@ "cygwin", ":al=\033[L:dl=\033[M:AL=\033[%dL:DL=\033[%dM:am:xn:bs:ce=\033[K:cl=\033[2J:\ :cm=\033[%i%d;%dH:co#80:\ -:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\ +:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:F1=#W:F2=#X:\ :s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\ :c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\ :a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\ @@ -155,7 +155,7 @@ "dosansi", ":am:bs:ce=\033[K:cl=\033[2J:\ :cm=\033[%i%d;%dH:co#80:do=\033[B:\ -:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:\ +:k1=#;:k2=#<:k3=#=:k4=#>:k5=#?:k6=#@:k7=#A:k8=#B:k9=#C:k0=#D:F1=#W:F2=#X:\ :s1=#T:s2=#U:s3=#V:s4=#W:s5=#X:s6=#Y:s7=#Z:s8=#[:s9=#\\:s0=#]:\ :c1=#^:c2=#_:c3=#`:c4=#a:c5=#b:c6=#c:c7=#d:c8=#e:c9=#f:c0=#g:\ :a1=#h:a2=#i:a3=#j:a4=#k:a5=#l:a6=#m:a7=#n:a8=#o:a9=#p:a0=#q:\ diff -urN elvis-2.2_0/url.c elvis-2.2_1/url.c --- elvis-2.2_0/url.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/url.c 2004-03-26 22:35:29 +0100 @@ -2,7 +2,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_url[] = "$Id: url.c,v 2.24 2003/10/18 17:01:29 steve Exp $"; +char id_url[] = "$Id: url.c,v 2.25 2004/03/07 20:10:28 steve Exp $"; #endif static char url_protocol[10]; @@ -216,7 +216,8 @@ */ if (!parseurl(url) || !strcmp(url_protocol, "mailto") - || !strcmp(url_protocol, "file")) + || !strcmp(url_protocol, "file") + || !strcmp(url_protocol, "dir")) return ElvFalse; return ElvTrue; } diff -urN elvis-2.2_0/version.h elvis-2.2_1/version.h --- elvis-2.2_0/version.h 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/version.h 2004-03-26 22:35:30 +0100 @@ -6,7 +6,7 @@ * README.html, search for the actual version number */ -#define VERSION "2.2.0" +#define VERSION "2.2.1" #define COPY1 "Copyright (c) 1995-2003 by Steve Kirkendall" #if 1 # define COPY2 "Permission is granted to redistribute the source or binaries under the terms of" diff -urN elvis-2.2_0/vi.c elvis-2.2_1/vi.c --- elvis-2.2_0/vi.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/vi.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_vi[] = "$Id: vi.c,v 2.94 2003/10/17 17:41:23 steve Exp $"; +char id_vi[] = "$Id: vi.c,v 2.96 2004/03/07 21:38:21 steve Exp $"; #endif #if USE_PROTOTYPES @@ -325,7 +325,6 @@ /* g{ not defined */ { NULL, WHEN_NEVER, TWEAK_NONE }, /* g| not defined */ { NULL, WHEN_NEVER, TWEAK_NONE }, /* g} not defined */ { NULL, WHEN_NEVER, TWEAK_NONE }, -/* g~ not defined */ { NULL, WHEN_NEVER, TWEAK_NONE }, /* g~ toggle case op */ { NULL, WHEN_OPEN, TWEAK_DOT_OPER_UNDO }, /* gDEL not defined */ { NULL, WHEN_NEVER, TWEAK_NONE } }; @@ -411,7 +410,7 @@ scanprev(&scan); /* scan forward for the count'th unmatched " names onto a stack, and * pop them when we get a . To handle unpaired tags, * should always pop back to the matching name; or, if there is no @@ -444,8 +443,20 @@ /* collect chars of the name */ assert(name == NULL); - for (; scan && elvalnum(*scan); scannext(&scan)) + for (; + scan && (elvalnum(*scan) || + *scan == ':' || + (*scan == '-' && prev != '-')); + scannext(&scan)) + { buildCHAR(&name, vinf->key2 == 'X' ? elvtolower(*scan) : *scan); + prev = *scan; + } + if (scan && *scan == '-') + { + scanprev(&scan); + name[CHARlen(name) - 1] = '\0'; + } if (!scan || !name) goto Fail; @@ -525,12 +536,17 @@ /* does the name match? */ inname = name; if (vinf->key2 == 'X') - while (*inname && elvalnum(*intag) && *inname++ == elvtolower(*intag)) + while (*inname && *inname++ == elvtolower(*intag)) scannext(&intag); else - while (*inname && elvalnum(*intag) && *inname++ == *intag) + while (*inname && *inname++ == *intag) scannext(&intag); - if (!*inname && (!intag || !elvalnum(*intag))) + /* !!! Note: the following if() statement isn't quite right. + * It doesn't handle - correctly. Consequently may + * be paired up with , provided there is no + * between them. + */ + if (!*inname && (!intag || !(elvalnum(*intag)||*intag == ':'))) { /* yes, the name matches -- adjust nest */ if (slash) diff -urN elvis-2.2_0/vicmd.c elvis-2.2_1/vicmd.c --- elvis-2.2_0/vicmd.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/vicmd.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_vicmd[] = "$Id: vicmd.c,v 2.83 2003/10/19 23:13:33 steve Exp $"; +char id_vicmd[] = "$Id: vicmd.c,v 2.84 2003/12/28 20:33:29 steve Exp $"; #endif @@ -953,6 +953,9 @@ win->selattop = ElvFalse; win->seltype = 'r'; break; + + case ELVCTRL('['): + return RESULT_ERROR; } return RESULT_COMPLETE; #endif /* FEATURE_V */ diff -urN elvis-2.2_0/window.c elvis-2.2_1/window.c --- elvis-2.2_0/window.c 2003-10-21 04:32:25 +0200 +++ elvis-2.2_1/window.c 2004-03-26 22:35:29 +0100 @@ -4,7 +4,7 @@ #include "elvis.h" #ifdef FEATURE_RCSID -char id_window[] = "$Id: window.c,v 2.72 2003/10/17 17:41:23 steve Exp $"; +char id_window[] = "$Id: window.c,v 2.74 2004/03/19 16:43:08 steve Exp $"; #endif #if USE_PROTOTYPES @@ -185,6 +185,8 @@ newp->gw = gw; newp->guivals = gvals; newp->cursor = markalloc(buf, buf->docursor); + if (buf->docursor != buf->changepos) + newp->prevcursor = markalloc(buf, buf->changepos); newp->wantcol = 0; newp->cursx = newp->cursy = -1; @@ -450,6 +452,12 @@ bufoptions(buf); } + /* if the change location is different from docursor, then + * use it as the previous location for this window. + */ + if (buf->changepos != buf->docursor) + win->prevcursor = markalloc(buf, buf->changepos); + /* switch to the new buffer's preferred display mode */ dispset(win, o_initialsyntax(buf) ? "syntax" : tochar8(o_bufdisplay(buf)));