ViEmu for Xcode: vi/vim emulation for Xcode

ViEmu for Xcode Documentation


Index:

1. General
2. Integration with Xcode
3. ViEmu settings dialog
4. The status bar
5. Miscellaneous Xcode integration info
6. The vi/vim input model
7. Regular expressions
8. The ex command line
9. Differences with vi and vim
10. Support
11. Change log



1. General

ViEmu is a plug-in for Xcode which enables vi/vim-like text editing for Apple's IDE.

ViEmu for Xcode incorporates the same core vi/vim emulator as its Microsoft's Visual Studio brother.

Since version 1.0 in 2005, ViEmu provides a large part of the vi/vim input model (motions, commands, operators, marks, keystroke macros, multiple registers and selection types, etc..). Version 1.1 brought a completely new architecture that provided the best integration of the vi/vim editing model with Visual Studio, with Intellisense, and with third party editor enhancement tools. ViEmu 1.2 brought code folding / outline support, basic window splitting and navigation features, and some important emulation improvements. Version 1.3 implemented regular expressions and ex command line emulation to ViEmu, finally bringing powerful text editing capabilities to Visual Studio. ViEmu 1.4 supported Visual Studio 2005 natively, together with some nice emulation additions such as bringing in the contents of a register in command-line editing and insert modes with ^R. The maintenance releases of ViEmu 1.4 added basic :map support, .viemurc initialization script support, multi-line replacement strings for :s, and many other improvements.

ViEmu 2.0 provided a much more advanced vi/vim emulator and much better integration: it uses Visual Studio colored text markers to implement hlsearch, much better emulation of vim's visual modes, proper repetition of Intellisense-autocompleted input, faithful emulation of undo-grouping, full wordwrapping support, automatic removal and management of clashing VS keybindings, and many other features.

ViEmu 2.1 and 2.2 were "maturity" releases of 2.0, with many improvements, new commands and motions, that make the experience closer yet to editing with vi or vim.

ViEmu 2.5, brought a few major new features: multiple key chord mappings (for example, ":nmap end $"), full Ctrl-A/Ctrl-X support to increment and decrement numbers, Ctrl-Y and Ctrl-E in insert mode to copy text from above or below, and finally, the new licensing key system.

ViEmu 3.0 brought even more features to ViEmu: the much requested 'c' switch for the search and replace command which displays a confirmation dialog, support for the 'i' (case insensitive) and 'I' (case sensitive) switches also for the search and replace command, Ctrl-N/Ctrl-P in insert mode to navigate through a generated list of matches for the partially written word, and an improved compatibility with 3rd party extensions such as ReSharper and Visual Assist.

ViEmu 3.1 and later finally brought ViEmu to the Mac world, as a plug-in for the number one IDE for Mac developers.

ViEmu 3.5 added more features such as it/at XML tag text object motions, and unified of version numbers with all other ViEmu editions.

This documentation reviews the details of integration with Xcode, and the vi/vim input model, ex command line, and regular expressions as implemented by ViEmu.

We hope you will find ViEmu useful!



2. Integration with Xcode

ViEmu is an Xcode plug-in, and it works by intercepting character typing operations to perform vi commands in response to regular keypresses: j to move down a line, etc...

You needn't do anything specific to use ViEmu, just open source or text files within Xcode and start editing as if you were using vi or vim. The block will change its shape as soon as you press any key or mouse button, showing the regular vi/vim normal mode block cursor.

If you want to disable ViEmu temporarily, you can use the "Enable/disable ViEmu" setting under the ViEmu menu.


3. ViEmu settings

ViEmu settings and preferences are accessible from the ViEmu menu, just select "ViEmu Settings at the bottom. ViEmu provides a simple way to edit settings in this dialog, which are saved to the Xcode user-defaults, and re-read next time Xcode starts. Their changes also act instantly. Apart from this mechanism, you can use the _viemurc initialization file to set vi/vim variables following the standard vi/vim way. The initialization file is processed after the UI-set settings, so it takes priority.

ViEmu options page

  • Enable ViEmu: As mentioned above, use this checkbox to enable or disable ViEmu within Xcode.

  • ignorecase, smartcase, incsearch, hlsearch: These options control the vi/vim standard variables of the same names, which are usually accessed using the :set commmand. Unlike when setting them using the :set command, when set through this dialog their value is persisted by the preferences system.

    • ignorecase controls the case sensitivity of the searches done using the '/' and '?' commands.

    • smartcase: This option activates 'Smart case sensitivity'. This setting only works if 'ignorecase' is on. In that situation, if a search string is entered containing at least one upper-case character, case-sensitive behavior is used for that search. These allows using case insensitive searches most of the time, by typing only lowercase characters, and still for case sensitive behavior for a given search by typing some uppercase character.

    • incsearch this setting controls incremental search, that is, whether the cursor is placed at the first match of the search target while the search is being typed (the match is also higlighted).

    • hlsearch this setting controls search highlighting, which will mark with a different background the all matches of the search string in the current file. It will also highlight them when switching to a new file. ViEmu goes to great lengths not to scan unnecessarily, and to perform incremental calculations, so this feature should not noticeably impact performance even in the case of very large files.

  • The 'Colors' section allows to change the colors used for incremental and highlight search.
  • The 'Useful links' section of the preferences page provides links to this documentation, to the ViEmu web site, to the support forum and to the ViEmu FAQ.
  • The 'License' section shows a note on the registration info of the current copy of ViEmu and allows to remove the current license key or enter a new one.




4. The status bar

ViEmu adds a status bar at the bottom of Xcode source views. When you are editing a file with ViEmu, you will notice that the status bar shows the current state of ViEmu. It first shows the mode ViEmu is in (NORMAL, INSERT, REPLACE, VISUAL, VISUAL-LINES or VISUAL-BLOCK). Apart from this, it also shows the current partial command that you have input, as is common in vi/vim.


5. Miscellaneous Xcode integration info

When you enter input mode, all input is filtered through Xcode's input system, which includes autocompletion and possibly other editor enhancements. This way, you have all regular autocomplete features available. Starting with ViEmu 2.0, ViEmu takes note of the input generated by these actions, and can thus properly reproduce this input afterwards: if you enter input mode with '2i', the text typed will be repeated after ending input mode with ESC whatever autocomplete actions you performed.

The support for the whole :*map familiy of functions (including their regular and their :*noremap side) is fairly complete: starting with ViEmu 2.5, both single keypresses and chords can be mapped (for example, ":map c_ ct_") to an unlimited sequence of keystrokes. This requires managing ambiguous input sequences and timing limits to resolve them, as governed by the 'timeout' and 'timeoutlen' vi/vim variables.

ViEmu does its own clipboard handling, both for internal named registers (0-9, a-z) and for the default clipboard. This allows ViEmu to recreate vi/vim's distinction of character, line and block selections.

ViEmu supports a quite functional ex command line subset emulation. Check the ex emulation section below for details.


6. The vi/vim input model

We have made available a
vi/vim graphical reference and tutorial, which covers the most important part of the vi/vim input model. Be sure to check it out if you want a good reference or a general introduction to vi/vim editing.

ViEmu accepts commands along the vi/vim input model. This means that input is separated in pieces that are parsed as they are entered, and the command is 'kicked' when the parsing determines that there is a complete command to execute. The partial input entered up to the moment is displayed on the status bar. An incomplete command can be cancelled by pressing ESC.

A command may be composed by the following elements:
  • One or more register specifiers (a quote followed by another character, for example, "a)
  • One or more counts (a decimal number, such as 12)
  • A command (which may be followed by other elements depending of the type of commands)
All commands may be preceded by a count that usually indicates the number of times to perform the command, and a register specifier, which indicates which register to use in the case of yank/paste/delete commands. If there is more than one count present (separated by another input element), the different counts are multiplied together.

Some commands are direct-action commands (for example, 'x' deletes the current character). These commands kick ViEmu to act as they are typed, optionally with a count and/or register specifier.

Other commands require a character argument (for example, 'm' which requires a mark identifier afterwards, or 't' which expects which character to look for after it). These commands wait for the character and then kick the action.

Another set of commands are called 'motions', which involve moving around the edited file. They are also kicked as soon as typed (for example, 'l' means 'move cursor right' or 'w' means 'next beginning of word).

Finally a very important set of commands are called 'operators'. These commands act upon a region of text doing some action on it (for example, 'd' deletes the region, 'gU' makes it uppercase, and 'y' copies the region to a register). These commands wait for a motion after entering them, and then act on the text between the current position and the motion target. The motion can have a count itself, such that 'd2w' deletes the next two words. In visual selection mode, operators don't wait for a motion and, instead, act on the selected region of text - this is an improvement of vim over the original vi and is actually very useful.

ViEmu implements most of vi/vim's core commands, including operators and motions. Some obscure ones are not implemented (such as ROT13 encoding), as well as some advanced ones (such as line autocompletion in input mode).

Motions

  • 0: move to hard beg-of-line (column 0)
  • '$': move to end-of-line
  • '^': move to soft beg-of-line (first non-space character)
  • '-': move to soft beg-of-line of the previous line
  • '+', <RETURN>: move to soft beg-of-line of the next line
  • '_': move to soft beg-of-line of the current line (if count given, N lines below)
  • '|': move to column as given by count (default 0)
  • hjkl move left, down, up and right
  • Ctrl-P/Ctrl-N: up and down (same as k/j)
  • w: move to next beginning of "word"
  • b: move to previous beginning of "word"
  • e: move to next end of "word"
  • ge: move to previous end of "word"
  • W: move to next beginning of "WORD"
  • B: move to previous beginning of "WORD"
  • E: move to next end of "WORD"
  • gE: move to previous end of "WORD"
  • f* ('*' is any character you type): move to next appearance of the character in this line
  • F*: move to previous appearance of the character in this line
  • t*: move to just before the next appearance of the character in this line
  • T*: move to just after the previous appearance of the character in this line
  • ';': repeat last character-in-line search done (one of tTfF)
  • ',': repeat backwards last character-in-line search done (one of tTfF)
  • H: move to soft beg-of-line of the line at the top of the screen
  • M: move to soft beg-of-line of the line at the middle of the screen
  • L: move to soft beg-of-line of the line at the bottom of the screen
  • '`*' ('*' is a mark specifier): move to the position of the given mark) - mark '.' is the last edited position, '<' and '>' are the last visual selection endpoints, '[' and ']' are the start and end-point of the last text modification, yank or paste, and '^' is the location where insert mode was last exited. Lowercase marks are local to the buffer, uppercase ones are global (and jumping to them isn't really a 'motion')
  • ''*' ('*' is a mark specifier): move to the soft-beg-of-line of the position of the given mark)
  • gg: move to the top of the file (if a count is given, move to that line)
  • G: move to the end of the file (if a count is given, move to that line)
  • '%': move to the matching parenthesis (or similar). If not on matching character, first scan for the next matching character on the line. If beyond end of line, try maching at the last character of the line. If a count is given, move to that percent of the whole file instead
  • '/arg<return>': (find) move the next occurlnce of "arg" in the file - incrementally shows place while parsing, but you can press ESC to cancel it and go back to where you where
  • '?arg<return>': same as previous one, but backwards
  • n: repeat last find ('/' or '?', or '*' or '#')
  • N: repeat last find with reversed sense (will do backwards if it was '/' or forwards '?')
  • '*': (literal asterisk) find the next occurrence of the identifier under the cursor
  • '#': (literal hash) find the previous occurrence of the identifier under the cursor
  • 'g*': (literal asterisk) find the next occurrence of the identifier under the cursor, not required to be a full-word match
  • 'g#': (literal hash) find the previous occurrence of the identifier under the cursor, not required to be a full-word match
  • Ctrl-d: move the cursor down and scroll half a screenful of text - this works in vim, but is not a motion
  • Ctrl-u: move the cursor up and scroll half a screenful of text - this works in vim, but is not a motion
  • Ctrl-f: move the cursor down and scroll a screenful of text - this works in vim, but is not a motion
  • Ctrl-b: move the cursor up and scroll a screenful of text - this works in vim, but is not a motion
  • ( or ): move to previous beginning or next end of sentence, as indicated by periods or other punctuation signs.
  • { or }: move to the previous beginning or next end of paragraph, as indicated by fully empty lines
  • [[ or ]]: move to the previous or next open brace in the first column - useful to navigate C/C++ source code.
  • [] or []: move to the previous or next close brace in the first column - useful to navigate C/C++ source code.
  • z<return>, z. or z-: move to the soft beg-of-line, but also scroll the file to put the current line at the top/center/bottom of the screen
  • [( and ]): move to previous or next unmatched parenthesis - it steps over properly matched parentheses
  • [{ and ]}: likewise with braces
  • Ctrl-i and Ctrl-o: move to next or previous position in the "position history" of last visited places. If the previous position is in another file, it doesn't act like a motion, but if it is on the same file, it acts as a motion (unlike vi/vim.)
  • special text-block motions: these motions act especially, as they determine not only the end but also the beginning of the acted upon region. They cannot be entered as regular motions in normal mode, as they start with 'i' or 'a' which are valid commands - they can only be used as arguments to operators or in visual mode. They fully determine the region on which to operate when used as operator arguments, and they extend the current selection in visual mode. The 'inner' version does not pick spaces afterwards, while the 'a' version does:
    • iw or aw ("inner word"/"a word"): "word" currently under the cursor
    • iW or aW: likewise with a "WORD"
    • is or as: likewise with a sentence (see '(' and ')')
    • ip or ap: likewise with a paragraph (see '{' and '}')
    • i) or a): (also works with '(') ) parentheses delimited block
    • i] or a]: (also works with '[') ) square bracket delimited block
    • i> or a>: (also works with '<') ) angle-bracket delimited block
    • i' or a': single-quote delimited block, limited to the current line, ignores '\' escaped quotes, counts quotes from start-of-line if done from an ambiguous quote
    • i" or a": double-quote delimited block, limited to the current line, ignores '\' escaped quotes, counts quotes from start-of-line if done from an ambiguous quote

Regular commands

  • i: enter input mode at current position
  • a: enter input mode just after the character after the current position
  • gi: enter input mode where insert-mode was last exited
  • I: enter input mode at soft beginning-of-line
  • gI: enter input mode at hard beginning-of-line
  • A: enter input mode after end of line
  • R: enter input mode in overtype mode
  • o,O: (normal) insert an empty line (below,above) the current line and enter input mode there
  • s: delete current character and enter input mode
  • S: remove all characters from current line and enter input mode
  • C: remove all characters to end-of-line and enter input mode

  • x: delete character under the cursor
  • X: delete character before the cursor
  • '~': toggle case of current character

  • 'r*' (where '*' is any character): replace current character with the given character

  • J: join the current line with the next one, leaving exactly one space between them
  • gJ: join the current line with the next one, leave whitespace as it is

  • u: undo last action
  • Ctrl-r: redo last undone action

  • D: remove all characters to end-of-line
  • Y: yank current line
  • p: paste after current position
  • P: paste at current position
  • ]p: paste after current position and reindent
  • ]P, [p, [P: paste before current position and reindent
  • gp/gP: paste after or before cursor, then, leave cursor after the pasted test

  • v: enter visual-character selection mode
  • V: enter visual-linewise selection mode
  • Ctrl-v: enter visual-block selection mode (Ctrl-Q also maps to this command)
  • gv: enter visual mode with the last selected range and selection mode
  • o,O: (visual) toggle the cursor between the end and the beginning of the visual region

  • 'q*' (where '*' is a macro specifier character): start recording a macro into given register (same as regular registers)
  • '@*' (where '*' is a macro specifier character): play the macro from given macro register (@@ repeats last)

  • 'm*' (where '*' is a mark specifier character): set the position for mark (lowercase marks are buffer-local, uppercase ones are global)

  • 'zt', 'zz' and 'zb': scroll the view so that current line is at top/middle/bottom of the screen
  • Ctrl-e, Ctrl-y: scroll the view one line upwards/downwards (keep cursor on screen)

  • Ctrl-]: jump to the definition of the symbol under the cursor
  • Ctrl-T: jump back to the position before the previous "go to definition"
  • gd: go to the local definition of the symbol under the cursor (goes to the line above the first '{' in column 0 searching backwards, then searches for symbol)

  • Ctrl-^: jump to the previous buffer (optional count indicates buffer number)

  • ^Ws: split current window if it's not already a split (^W means Ctrl-W)
  • ^W^W, ^Ww, ^Wj, ^Wk, ^W plus up/down cursors: toggle from one split of the current pane to the other

  • zc, zo, za or zA: toggle the current fold from open to closed, or viceversa
  • zd: remove the current fold (not the text, but just the fold markers)
  • zR: expand all folds
  • zM: collapse all folds

  • gf: open file under cursor

  • gt/gT: go to next/previous buffer in buffer list

  • ZZ: save current file and close it (same as :wq)

  • Ctrl-A/Ctrl-X: increment/decrement the number under the cursor (decimal, hex, octal and alpha supported, see nrformats option)

  • '.': (probably the most useful vi/vim command) repeat last command

Operators

They all wait for a motion in normal mode or act on the visually selected region in visual selection mode. They all use the specified register if there is one, or the default if there is no one specified (default may be the "*" Windows clipboard or the internal "0" register depending on an options on the preferences page).
  • d: delete the specified region
  • c: delete the specified region and enter input mode
  • y: yank (copy) the specified region
  • gU: make all the characters in the specified region uppercase
  • gu: make all the characters in the specified region lowercase
  • g~: toggle the case of all the characters in the specified region
  • >: indent all the lines in the specified region
  • <: unindent all the lines in the specified region
  • zf: create and collapse a fold for the enclosed text
  • gq or =: autoreformat the text in the specified region (via Xcode's re-indenting mechanism)

Other

In insert mode, you can use the special Ctrl-T and Ctrl-D to indent/unindent the currently edited line.
Also in insert mode, Ctrl-Y copies the character from the line above, and Ctrl-E the one from the line below.
In insert and command line editing mode, you can use Ctrl-R followed by a register specifier to recall the contents of that register (use " or any other non-alphanumeric symbol after Ctrl-R to recall the contents of the default register).
While editing at the command line, be it a '/' or '?' search or an ex command line, you can use Ctrl-Y to yank the full contents of the command line into the default register/clipboard.
Also in insert or command line editing mode, Ctrl-U deletes back to the start of the edit, and Ctrl-W deletes the word before the cursor.
In insert mode too, you can use Ctrl-N and Ctrl-P to navigate through a list of autocompletion words automatically generated from the current file. To create this list, ViEmu scans 100 lines above and 30 lines below the cursor position.

Search offsets

The '/' and '?' search commands support a functionality called "search offsets", which control cursor placement after a match is found. By default, a search motion positions the cursor at the start of the match, but search offsets allow you to modify this behavior.

Search offsets are added after the regular expression and a search terminator: "/abc/+" for example specifies a regular search of "abc" with a search offset indicated by "+". In this case, this means a line offset of +1, which will move the cursor to the first column in the line below where "abc" is found.

These are all numerical search offsets supported:

Offset type Syntax Notes
Lines above or below +N or -N If N is not given, default is 1
Characters from start b+N, b-N, s+N, s-N If N is not given, default is 1
Characters from end e+N, e-N Search motion becomes inclusive


A very special search offset is specified by using ";" after a search, which allows an extra search term to be appended, which will be searched for starting from the position of the previous match. As many searches as wanted can be given, and each one of them can also include numerical search offsets. For example, /abc/+10;?def?e+1 is a single search involving the following steps: search forward for 'abc', go to the first column 10 lines below the match, search backwards for 'def', then position the cursor in the character right after the 'f'.

When a multi-step search repeated using 'n' or 'N', only the last step is repeated, although in the direction given by the first search step.


7. Regular expressions

7.1. Introduction

Regular expressions are a well known method by which to specify patterns for text searching. Most characters in a regular expression represent themselves, so "ten" interpreted as a regular expression represents the sequence of characters 't', 'e', and 'n', and searching for it will yield all places in the text where the string "ten" appears. Some other characters represent a pattern-matching element, for example, searching for "a*" will yield all sequences of 'a's (given that '*' represents zero-or-more repetitions of the previous element, in this case, the character 'a'). If you want to search for a sequence containing the character '*', you have to 'escape' it so that the regular expression engine will understand 'the literal star character' - this is done by prepending a backslash ('\') to the character. Thus, searching for "a\*" will yield all places in the text where the sequence 'a','*' appears.

The single other most known regular expression element is the dot ('.'), which matches any single character in the input.

ViEmu accepts a large subset of the regular expression features understood by vim. vim, on the other hand, accepts a superset of the features and syntax understood by traditional vi. Actually, ViEmu is also a superset of traditional vi regular expressions (smaller than vim).

For the technically inclined, the regular expression engine that ViEmu uses is an implementation from scratch based on non-deterministic finite automata. Additional state is stored for previously matched subexpressions, positions in the input stream, and repetition counts, in order to implement the most advanced features. The regex engine compiles the expression down to a bytecode-based format, and then the matching engine "executes" this bytecode on the input stream to find matches.

7.2. Searching vs matching

In the rest of this section, we will talk about regular expression elements "matching" parts of input text. Usually, regular expressions are not simply checked to match - when you press '/' in normal mode and enter a regular expression, several things happen. ViEmu compiles the regular expression into an intermediate form, and then it checks whether it matches at the character position right after the one where the cursor is. But if it doesn't match, things don't stop there - given that we're searching, another attempt to match is made at the position after the first one. And on the next, and the next... until the whole file is scanned or a match is found.

When showing examples, we will be showing what text matches a regular expression, but we will also be saying "it matches at the third character", meaning that it doesn't match at the first or second ones".

Not only that, but given that the regular expression actually matches a part of the input text, we will be talking about the regular expression matching a precise part of the input stream. For example, we could say the regular expression "a\+" tested against "bcaade" matches the two 'a's in the middle, meaning that it doesn't match at either the 'b' or the 'c', but it matches at the first 'a' and the match covers the two 'a' characters.

A regular expression element can match a varying amount of the input sequence. "a", for example, will match an 'a' character in the input and consume that character, so that the next regular expression element will try to match the next character in the input. "a*", on the other hand, may consume anything from zero characters (if the character found there is not an 'a', in which case the match is done assuming zero appearances of 'a'), one (if there is a single 'a' in the input and something else afterwards), or five characters (if there are 5 'a's in a row and something else comes afterwards). We talk about zero-width matches for those that do not consume any input character. For example, 'a*' can match with zero-width or non-zero widht, as we've just seen. On the other hand, some regular expression elements that we'll see below always match with zero-width, that is, they check their matching condition, and if this is fulfilled, they keep trying to match the rest of the regular expression without advancing to the next input character.

7.3. Magic

ViEmu actually understands different regular expression syntax "flavors". They are actually the four different flavors supported by vim: verynomagic, nomagic, magic, and verymagic. As you can imagine, they are in increasing order of "magicness". What does this mean? It represents the amount of easiness with which vim or ViEmu understands a character with a special meaning to stand for its special meaning instead of as a literal char.

Take for example the '*' character. We've seen that, if you use this character in a regular expression, it will be taken as meaning "as many repeats as wanted, even zero, of the previous character". If we want our regular expression to match an actual "*" in the source text, we need to escape it by writing "\*".

This is actually the behavior of the '*' character in 'magic' mode, which is the default mode. If we instruct vim or ViEmu to parse the regular expression in 'nomagic' mode, a naked "*" by itself will have no special meaning, and a sequence "\*" will be necessary in the regular expression for the regular expression parser to understand "zero-or-more repetitions of the previous character".

The default parsing mode can be set to either 'magic' or 'nomagic', by use of the :set command. ":set magic" and ":set nomagic" do the trick for both modes. It is not possible to specify a 'verynomagic' or 'verymagic' parsing default, if you want to write a regular expression in one of these modes, it's necessary to start the regular expression with "\v" for 'verymagic' or "\V" for 'verynomagic' (actually, these can be inserted anywhere in the input regular expression and they set the parsing mode until the end of the regular expression, or until another mode-setting token). There are also sequences to set the mode to 'magic' or 'nomagic', namely, "\m" to set 'magic' and "\M" to set 'nomagic' - inserting these tokens sets the parsing mode overridingthe ':set [no]magic' state.

The mode 'verynomagic' is defined as not giving a special meaning to any character unless it's escaped - so it is the best mode if the string you want to match contains a lot of punctuation which is also used in regular expressions, and few regular expression control characters. The mode 'verymagic' is defined as giving a special meaning to any punctuation character which has a meaning in regular expressions, unless it is escaped with a backslash. Thus, it is most useful if you are trying to match a string with not very many special punctuation characters, but the regular expression has quite some repetition, grouping, etc... control characters.

Each regular expression character gains its special meaning in a certain 'magicness' level. The decision seems arbitrary, but it's probably due to making the magic mode as compatible as possible with traditional vi.

For example, the '+' character is taken as meaning "one or more repetitions of the previous element", almost the same as '*' but it will require at least one occurrence of the element to match. '*' in magic mode is taken for its special meaning, while '+' is not taking as such, and requires a backslash in order to be interpretead for its repetition meaning. This is probably due to '+' being a feature not present in the original vi. Of course, both '+' and '*' are taken as repeat indicators in 'verymagic' mode, and taken as regular characters in 'verynomagic' mode.

So, some characters gain a special meaning in 'magic' mode (such as '*'), and others gain their special meaning only in 'verymagic' mode (such as '+'). But what characters gain a special meaning in 'nomagic' mode? That is, what are the (few) characters that are already interpreted specially in 'nomagic' mode? Actually, although the vim documentation is not completely clear with regards to this, it seems only '^' (beginning-of-line) and '$' (end-of-line) are already special in 'nomagic' mode (we'll see the meaning below, and an important note is that these characters only have a special meaning in certain positions of the regular expression)

For the rest of the documentation, we will list each element in the way it works in 'magic' mode. There is a table of the interpretation of all special characters in each mode at the end of the section.

7.4. Basic multis

Apart from literal characters, the most basic element in regular expressions are 'multis' or repeat specifiers. These are the basic multis understood by ViEmu:

  • * zero or more
  • \+ one or more
  • \= zero or one
  • \? zero or one (same as =)

Let's see some examples of them applied to regular characters:

a\+: This matches "a", "aa" or even "aaaaaa". It matches the two 'a's in "bbaacc".

a*: This matches the empty string, "a", "aa" or even "aaaaaa". In "bbaacc", it matches at the first character consuming no input (as zero repetitions are allowed, and there are zero 'a's at the first position).

a\=b: matches "ab", "b", and matches "cdeb" at the 'b' character.

The multis actually apply to the previous element in the regular expression - this can be a character (the examples we've just seen), any of the atoms described below (sets, character classes, etc...) and it can also be a subexpression delimited by parenthesis.

7.5. Beginning and end of line

The characters '^' and '$', which are recognized specially even in 'nomagic', stand for start-of-line and end-of-line. They actually match with zero-width, and they provide a way to 'anchor' the regular expression to the start or end of line. "^a" will match an 'a' only as the first character of the line, and " $" will only match a trailing space (and only the last one if there are several).

These characters are only interpreted as special if they are the first or the last character in the regular expression. If they are anywhere in the middle, they are taking as literal characters. If you want to use them anywhere in the regular expression, you need to use the sequences "\_^" and "\_$", which are always recognized as meaning start- and end-of-line.

vim also gives '^' and '$' special meaning at the start/end of subexpressions and branches, but ViEmu doesn't. As a workaround, you can use the "\_^" or "\_$" forms instead.

7.6. Sets

A set is formed, in its simplest form, by a list of literal characters enclosed between square brackets ('[' and ']'). It matches any of the characters in the set, and none other. For example, "[abc]" matches "a", "b" or "c", but not "d" or any other character.

But sets have a lot of advanced features to make them more useful. For example, "[0123456789]" would match any decimal digit, but you can use the shortcut "[0-9]" to represent all characters between '0' and '9', both included. A set can feature any number of ranges, together with independent characters: "[_a-zA-Z0-9]" represents any alphanumeric character or the underscore character, thus matching any character in a C or C++ identifier. If you want to include a literal hyphen in a set, give it as the first character in the set: "[-0-9]" means any digit or the hyphen character.

It is also possible to specify negative sets, that is, the set of all characters but the ones specified. This is done using the caret or circumflex: "[^0-9]" matches any character which is not a decimal digit. If you want to specify a caret among the characters in the set, just don't put it as the first character: "[0-9^]" represents any digit or the caret.

If you want to include the closing square bracket in a set, give it as the first character: "[]0-9]" means, a bit confusingly, any decimal digit or the closing square bracket.

Sets also allow four "character class tokens". These tokens match, each of them, a certain set of characters. The way to write them is surprisingly verbose:

  • [:alnum:]: alphanumeric character (same as [0-9A-Za-z])
  • [:cntrl:]: control character (ascii 0 through 31)
  • [:graph:]: printable character excluding space (ascii 33 through 126)
  • [:punct:]: punctuation character (those for which the system's ispunct returns true)

They can be used together with other characters and ranges, or on their own: "[[:alnum:]]" is the same as "[0-9A-Za-z]", but you can also use "[,[:alnum:].;]" to match alphanumeric characters, ',', '.' or ';'.

Multis can be applied to sets, such that "[0-9A-Za-z_]\+" will match any C/C++ identifier (and those pseudo-identifiers starting with a digit).

7.7. Character classes

There are some special sequences that are taken as representing a set of characters. These sequences are of the form "\x" where x is an alphabetic character. This is the list of character classes recognized by ViEmu (the same as vim):

  • \i: identifier [_a-zA-Z0-9] (isident)
  • \I: identifier w/o digits [_a-zA-Z]
  • \k: keyword [_a-zA-Z0-9] (iskeyword)
  • \K: keyword w/o digits [_a-zA-Z]
  • \f: filename [_a-zA-Z0-9./\\] (isfname)
  • \F: filename w/o digits [_a-zA-Z./\\]
  • \p: printable [ -~] (isprint)
  • \P: printable w/o digits [ -/:-~]
  • \s: whitespace [ \t]
  • \S: not whitespace [^ \t]
  • \d: digit [0-9]
  • \D: not digit [^0-9]
  • \x: hex digit [0-9A-Fa-f]
  • \X: not hex digit [^0-9A-Fa-f]
  • \o: octal digit [0-7]
  • \O: not octal digit [^0-7]
  • \w: word [0-9A-Za-z_]
  • \W: not word [^0-9A-Za-z_]
  • \h: head of word [A-Za-z_]
  • \H: not head of word [^A-Za-z_]
  • \a: alphabetic [A-Za-z]
  • \A: not alphabetic [^A-Za-z]
  • \l: lowercase [a-z]
  • \L: not lowercase [^a-z]
  • \u: uppercase [A-Z]
  • \U: not uppercase [^A-Z]

The pattern is that lower case letters represent a certain class, and their uppercase counterpart represents either the same class without the 0..9 digits, or a character not belonging to the original class.

The weird ranges in \p and \P represent ASCII values 32..126 (for \p), and that range minus '0'..9' for \p.

vim allows redefining the \i, \k, \f and \p sets (and their uppercase counterparts) through the isident, iskeyword, isfname and isprint options. ViEmu hardcodes them to their default vim values.

There are also four other character classes (alphanumeric, control-codes, graphic and punctuation) which are only available within sets (see above).

As an example, "^\s*\S\+\s*$" matches full lines consisting of a single word formed by non-whitespace characters, possibly with leading and trailing whitespace. A line like " abc " would match, where " ab cd " wouldn't.

7.8. Subexpressions

You can group parts of a regular expression between parentheses (by default "\(" and "\)", which are quite ugly and unreadable, but you can use "\v" at the beginning of the expression to use simple '(' and ')'). Adding doesn't change the interpretation of regular characters, but you can make a multi apply to a whole subexpression this way:

"\(ab\)c" matches the same as "abc", namely, the "abc" string

"\(ab\)*c" matches any count of "ab" pairs followed by a 'c'. For example, it matches "abc", but it also matches "ababc", "ababababababc", and even just "c".

You can also nest them, which combined with other features is pretty powerful: "\(a\(bc\)\+\)*" matches any number of "abc"s followed each of them by as many "bc"s as wanted: "abcbcbcabc" and "abc" are matched, and "def" is matched but with zero width (no repetitions).

Subexpressions given this way can be later refered to in the regular expression with "\1", "\2",... up to "\9". When this appears in the regular expression, it only matches the text that matched the subexpression. For example, given that "\d\+" matches any integer decimal number, you can search for "\(\d\+\) \1" which will find repetitions of numbers separated by a space (for example, "58 58" but not "58 59"). Be careful, because done this way it can match unexpected sequences, such as "58 583" by ignoring the last '3'). In order to do this correctly, have a look at section 7.11 for word begin / word end.

Subexpression numbers are assigned left-to-right by opening parenthesis order as they appear in the regular expression.

If you want to include a subexpression, but are not interesting in refering to it later (either by the \1..\9 tokens described in the paragraph above, or in the :s substitution command), you can open the subexpression with "\%(", which will work the same, not count towards the \1..\9 tokens, and result in a tiny bit faster regular expression when it comes to checking it (use "\)" as normally to close it).

7.9. Advanced multis: counted repetitions and greediness control

Apart from the multis we've seen above, there is another set of multis which allows more control on the repeat counts accepted. But before getting into them, we'll discuss an important aspect of regular expression matching: greediness.

When a pattern involving repetitions is tried to match, it is actually tried to match with the different possible amount of repetitions. For example, if the pattern specifies "a*" and the text contains three 'a's ("aaa"), the regular expression item could be match with zero, one, two or three repetitions. Matches with different repeat counts are attempted, and the first one that makes the whole pattern match is returned. Given that different repeat counts may cause a match, the order in which counts are attempted is very important towards the final match.

A repeat operator that attempts to first match as many valid input characters as possible is called a greedy operator. All multis we saw in section 7.4 are greedy, so actually "a*" will try to match the three 'a's in the example above. If "a*" is the whole pattern, and the input sequence starts with three 'a's followed by something else, that is the end of the story and the three-'a' match is returned. But if the regular expression were "a*a", and the input still "aaa" or "aaab", it's not the end of the story. First, the "a*" tries to match the three 'a's, but then the last 'a' in the regular expression tries to match and fails. Thus, a match is tried to make with the first "a*" matching just the first two 'a's. Then, the next 'a' in the regular expression tries to match, and succeeds - so the "aaa" in the input text is returned as matching, by attributing two repetitions to the '*' character.

The operator which is the center of this section is the counted repetition operator, which is expressed by "\{" (and needs a closing "}" afterwards). It can contain two numbers separated by a comma, which are interpreted as a minimum and maximum count. For example, "a\{2,3}" will match two or three 'a's, but not zero or one, or more than three. Both counts are optional: if the minimum is not present, it is taken as zero, and if the maximum is not present, there is no maximum. Thus, "a\{,5}" means zero-to-five 'a's, and "a\{3,}" means three or more 'a's. If a single number is present, it is taken as meaning exactly that many repetitions. Thus, "a\{3}" will match only three 'a's.

Given as above, the "\{" operator also acts greedily: it will try to match as many input characters as it can, and only try to match less repetitions if the whole pattern didn't match after the attempted count. But if there is a hyphen just after the "\{" opening brace, the operator acts non-greedily: it will attempt to match as few input characters as possible. For example, if the regular expression "a\{-2,}" is tried to match with the input "aaaaa", it will only match the first two 'a's. It could match the whole input, but it tries not to. A regular expression such as "a\{-2,}b" will, though, match the complete "aaaaab" input - the operator needs to consume all 'a's for the 'b' to match.

As a special case of this behavior, "\{}" is the same as "*", and "\{-}" is a non-greedy version of the '*' operator.

7.10. Case sensitivity

Case determination is done as is default given the ViEmu 'ignorecase' and 'smartcase' options.

If 'ignorecase' is turned off, every character matches only itself.

If 'ignorecase' is turned on and 'smartcase' is turned off, the pattern is tried to match disregarding case.

If both 'ignorecase' and 'smartcase' are turned on, then the behavior is a bit more interesting. The first thing done is to check whether the pattern contains any uppercase character. If it doesn't contain any, then the match is tried without paying attention to case. But if the regular expression contains any uppercase character, then the match is attempted without ignoring case. This allows using case-ignoring searches most of the time, and forcing a case-sensitive search by just using any uppercase character in the string.

Apart from this global settings, it is possible to force a regular expression to either check or ignore case. By including the "\c" sequence anywhere in the pattern, the pattern will always be checked ignoring case. By including "\C", the pattern will always be checked paying attention to case. These sequences can be given anywhere in the pattern, and they affect the whole matching process (not only the part after them). They do not take part in the actual pattern matched, so they can be given anywhere in the pattern without changing its properties

Using these flags, if you set both 'ignorecase' and 'smartcase', you can still force a case-sensitive search of a lowercase-only pattern by preceding it with "\C": "\Cabc" will only match "abc", not "ABC" or "Abc".

Character classes, both the regular "\x" ones explained in section 7.7, and the set-specific ones shown in section 7.6, use the case-sensitivity associated with their definition, independently of both global settings and the "\c" or "\C" sequences.

7.11. Miscellaneous

Word beginning/end

In the same way that '^' and '$' provide a way to "anchor" the pattern to the beginning or end of a line, the tokens "\<" and "\>" provide a way to anchor a pattern to the beginning or end of a word. The beginning of a word is defined as a word character ([_a-zA-Z0-9]) following a non-word character (or at beginning of line). The end of a word is defined as a non-word character or end of line, after a word character. These are zero-width matches.

Using these tokens, we can perfect the regular expression shown above in section 7.8 to detect pairs of repeated decimal numbers: "\(\<\d\+\>\) \<\1\>" will match "53 53" or "47 47", but not "53 538" or "112 12". It is much easier to read in verymagic mode: "\v(<\d+>) <\1>" (at least, less hard to read, and if that seems unreadable, have a look at the html source).

Match-extent override

It is possible to instruct the pattern matching engine to check for a large pattern, but only return a part of the matched text when the match succeeds. This is done by using the "\zs" and "\ze" start and end tokens to indicate where the overriding match start and end should be placed. For example, "abc\zs123\zedef" will only match a "abc123def" sequence, but only the "123" part will be returning as matching (ie, it simply won't match "zzz123yyy" at all). This is very useful with the :s ex substitution command: only the delimited text gets substituted, even if the whole match is required.

Branches

It is possible to build a regular expression from two possible patterns, that will match where either or both does. We use the "\|" operator for this: "abc\|def" will match either "abc" or "def". This is the lowest precedence operator, so no parentheses are necessary to group the two sides (but it can be used within a subexpression to make it match either).

Concats

Concats are not really very useful, given the "\zs" and "\ze" match extent overriding tokens. A concat is expressed as "abcdef\&abc", and it matches the input section matched by the last subexpression, but only if the previous one(s) have already matched at the same place. For example, "abc\&def" will never match (as "abc" and "def" cannot appear in the same place). The same effect can be done with "abc\zedef".

Special characters

There are some special characters that must be written especially in a regular expression: "\t" stands for the TAB character, "\e" for the ESC character, "\r" for the CR character (not possible in ViEmu as Xcode interprets it as a line terminator), and "\b" for the BACKSPACE character. "\n" looks similar, but it isn't (see the next section).

7.12. Multi-line matching

All the elements we have seen involve only "regular" characters - thus, any regular expression composed with the above elements will only match sequences within a single line. The regular expression compiler accepts some tokens that allow matching line terminators, and when using these, the matching engine will be able to match at end of line, advance to the first character of the next line, and continue matching there.

Please note that line terminators are treated identically, no matter whether it is a UNIX-type file (lines terminated with LF), an DOS/Window file (terminated with CR-LF) or a Mac file (CR). The actual original representation of the line terminator is not checked at all.

The simplest character that causes this behavior is "\n" - this character matches and consumes a line terminator, advancing to the next line. Thus, the regular expression "abc\ndef" will match at a line which ends in "abc" and a where the next line starts as "def".

Another multi-line extension is the character classes in the form "\_x". All the character classes described in section 7.7 can be given in this form, and this turns them into accepting both their regular character sets, and the newline character.

Sets can also be made to accept newlines. There are two ways: either you include the "\n" character within the set, or you start the set with the sequence "\_[" instead of the regular "[".

An example use of this sequence is to detect sequences of lines starting with the same word: "^\s*\(\w\+\)\>.*\n\s*\1\>" will detect two lines in a row starting with the same word, and "^\s*\(\w\+\)\>.*\(\n\s*\1\>.*\)\+" will match all the lines stating with the same word. These expressions are simpler in 'verymagic' mode, but using magic mode is the most common way (as 'verymagic' is vim-specific and not supported in vi).

7.13. vim regex features not supported by ViEmu

ViEmu implements most, but not all, features of vim regular expressions. vim regular expressions are a superset of traditional vi regular expressions. These are the features of vim regular expressions not implemented by ViEmu:

  • ~ (match last :s substituted string)
  • \@>: which is a multi which does not retry after the first match is done
  • \@=: multi that turns the previous atom in a zero-width match
  • \@!: multi that matches with zero-width if the preceding atom does NOT match
  • \@<=: multi that causes first looking for the second part, then checks for the first
  • \@<!: multi that causes first looking for the second part, then checks that the first does NOT match!
  • \%^ (beg-of-file), \%$ (end-of-file), \%# (cursor-pos), \%23l (specific line), \%23c (col) and \%23v (vcol)
  • \%[: optional tail ("wh\%[atever]")
  • vim detects & prevents "multis" following possibly empty matches (such as \(\)* or even \zs*)
  • ^ and $ detected as "special" not only at pure regex start and end, but also at branch and subexpression endpoints
  • \Z (ignore differences in unicode combining chars)

7.14. Detail of magic mode

This is the way each special character has to be written in each mode for it to be interpreted for its special meaning:

meaning verynomagic nomagic magic verymagic
zero-width end-of-line \$ $ $ $
zero-width start-of-line \^ ^ ^ ^
zero-width end-of-line \. \. . .
zero-or-more times the previous elem \* \* * *
one-or-more times the previous elem \+ \+ \+ +
zero-or-one times the previous elem \= \= \= =
zero-or-one times the previous elem \? \? \? ?
start of set definition \[ \[ [ [
start of counted-repetitions token \{ \{ \{ {
start of grouped subexpression \( \( \( (
end of grouped subexpression \) \) \) )
zero-width beginning of word \< \< \< <
zero-width end of word \> \> \> >
branch separator \| \| \| |
concat separator \& \& \& &

7.15. Operator precedence

These are the operators, in highest-to-lowest precedence order:

  • multis ('*', '\+', '\=', '\?' and '\{}'
  • concat separator ('\&')
  • branch separator ('\|')

Subexpression parentheses (both '\(' and '\%(') can be used to override this precedence. For example, "\(abc\|def\)ghi" will match either "abcghi" or "defghi".





8. The ex command line

General

The ex command line is accessed by pressing ':' from normal or visual mode. It allows you to enter commands known as 'ex' commands, which perform general functions as well as very powerful text editing operations.

The first set of ex commands could be refered to as "environment" commands. They don't operate on the contents of the edited file, but they provide a means to open new files, save them, navigate open files, etc. They provide implementations which are sensible within the Xcode environment. A few of them accept parameters: :e[dit], :mac[ro], :vsc[md], :b[uffer] and :ta[g]. In this list, sequences between square brackets ("[" and "]") are optional.

  • :new: brings up the Xcode "New File" dialog
  • :q[uit]: (that is, the "uit" part is optional and ellidable) closes the current file
  • :qa[ll]: closes all open files
  • :wq or :x: saves and closes the current file
  • :e[dit]: brings up the "Open Quickly" Xcode dialog
  • :w[rite]: saves the current file
  • :wa[ll]: saves all modified files
  • :sp[lit]: shows the Assistant Editor
  • :xa[ll] or :wqa[ll]: saves and closes all open files
  • :clo[se]: closes the current file
  • :f[ile]: shows information about the current file and cursor position in the status bar
  • :ls: shows the buffer list with their buffer numbers in the Output section of the Xcode Debug area
  • :b[uffer] {N}: goes to buffer N (1-based)
  • :bn[ext] or :n[ext]: goes to next file in the buffer list
  • :bp[revious] or :N[ext]: goes to previous file in the buffer list
  • :bui[ld]: starts a build of the current solution
  • :comp[ile]: same as :bui[ld]
  • :deb[ug]: starts a debug session of the current scheme
  • :ern[ext]: jumps to next error
  • :erp[rev]: jumps to previous error
  • :ta[g]: jumps to the definition of the identifier under the cursor
  • :fd: brings up the Xcode Find interface
  • :ve[rsion]: shows the ViEmu version

Apart from these, ViEmu provides a fully functional subset consisting of the most important ex commands, which bring a large part of vi/vim's raw text editing power to Xcode. The general form of all ex commands is:

:[range]command[!]args

The range specifies on which lines the given command is to be applied. It can take many different forms (see below).

The command is one of the ones listed below. Most commands can be abbreviated to a shorter form, for example, substitute can be given as substitute, subst, su or even just s (and all intermediates). Thus, it is often shown as s[ubstitute].

The ! ("bang" or exclamation mark) alters the way the command works in a command-specific way. Not all commands allow !. The description of its function is given with each command.

The arguments are command-specific, and their function is described with each command.

Core ex commands

This is the list of the core ex commands ViEmu implements:

  • :set param - basic implementation allowing [no]ig[norecase]/[no]ic, [no]sm[artcase]/[no]sc, [no]ma[gic], and [no]viu[ndo]
  • :*map family of commands to map an input key sequence to another arbitrary sequence of keys
  • :*noremap family of commands for mapping w/o further mapping processing
  • :*unmap to remove mappings
  • :[range]d[elete] [x] [count] to delete (x is the register)
  • :[range]y[ank] [x] [count] to yank (x is the register)
  • :[range]j[oin] [!] to join the lines in the range, or default to the given line (or cursor line) and the next
  • :[line] pu[t] [!] [x] to paste after (!=before) the given address (x is the register)
  • :[range]co[py] [dest] to copy the lines in range to the destination address (:t is a synonim for this)
  • :[range]m[ove] [dest] to move the lines in range to the destination address
  • :[range]p[rint] [count] to print the lines (send them to the output window) (:P is a synonim for this)
  • :[range]nu[mber] [count] to print the lines (send them to the output window), w/line number (:# is a synonim for this)
  • :[range]s[ubstitute]/re/sub/[gciI] to substitute matches for the given regex with sub (do not give 'g' for only 1st match on each line)
  • :[range]g[lobal] [!]/re/cmd to run ':cmd' on all lines matching the given regex (! = *not* matching)
  • :[range]v[global] /re/cmd to run ':cmd' on all lines *not* matching the given regex
  • :[range]> indents all lines in the range
  • :[range]< unindents all lines in the range
  • :delm[ark] {mark(s)} removes one or more marks (jumping to them will fail afterwards)
  • :noh[lsearch] disables hlsearch highlighting until next search
  • :u[ndo] undoes the last action or action group
  • :red[o] redoes the last undone action or action group

And this is a detailed explanation of each:

:set

ViEmu implements several vi/vim settings: ignorecase, smartcase, magic, incsearch, hlsearch, gdefault, remap, wrapscan, list, nrformats, timeout, timeoutlen. It also implements two settings of its own, viundo and vaxesc. You can set the boolean ones with a prependend 'no' as in vi/vim in order to turn them off, or with 'inv' to toggle them. They allow the abbreviations ic for "ignorecase", scs for "smartcase", ma for "magic", is for "incsearch", hls for "hlsearch", gd for "gdefault", rem for "remap", ws for "wrapscan", nf for "nrformats, to for "timeout" and tm for "timeoutlen".

":set" alone or ":set all" shows the current state of all settings.

"ignorecase" governs whether searches take into account the case of text. It applies both to general character matches, as well as \1..\9 subexpression repetition and sets. As in vim, character classes do not honor this flag.

"smartcase" is only taken into account when "ignorecase" is on. It makes "ignorecase" non-functional if the input search pattern contains any uppercase characters. It allows you to have "ignorecase" on, and force case-checking by just specifying some of the search pattern characters in uppercase. If you need to look for a pattern which is composed only of lowercase characters and force case checking, you can use the "\C" flag anywhere in the sequence (such as "/for\C") to force the search to check the case.

"incsearch" controls whether the cursor/selection are used to show the target of the search while it is being typed.

"hlsearch" enables highlighting of all matches of the last search performed in the current buffer.

"gdefault" toggles the default behavior of the :s command, making it replace all matches in a line by default, and making the 'g' flag limit the substitution to the first match only.

"remap" enables recursively applying mappings to keys gotten from a remapping.

"wrapscan" enables continuing a search from the beginning of the file when the end is reached (and viceversa for backwards searches).

"list" controls the visibility whitespace and tab characters.

"nrformats" controls the formats supported by the Ctrl-A/Ctrl-X increment/decrement commands. It can contain any combination of "octal", "hex" and "alpha", separated by commas. Default is "octal,hex". Increment/decrement will recognize decimal, and the selected types - octal numbers must start with "0", hexadecimal ones with "0x", and alpha operates on single letters.

"timeout" controls whether a timeout triggers interpreting ambiguous input, in the presence of multiple key chord mapping. If set, the partial input will be processed without the mapping after the period specified by "timeoutlen". Default is active.

"timeoutlen" specifies the time after which the resolution processed by "timeout" is performed, in milliseconds. Default is 1000, for a one-second wait.

"viundo" activates a basic simulation of vi's one-item-only undo queue, by actually issuing a redo when an undo is done for the second time in a row.

:d[elete]

:[range]d[elete] [x] [count]

:d deletes the lines indicated by the given range. The range defaults to the current line. 'x' represents a register name to which to copy the text before deleting it. If a count is given, count lines are deleted starting with the last line in the range. Thus, :10d a 5"copies lines 10 to 14 to the "a" register and then deletes them (you can paste them back with "ap).

:y[ank]

:[range]y[ank] [x] [count]

It works the same way as :d[elete], but doesn't delete the text (it copies it to the given register)

:j[oin]

:[range]j[oin][!]

:j[oin] joins together the lines in the given range, forming a single line. The form with "!" doesn't add or remove any whitespace, while the regular form substitutes all the leading whitespace in joined lines by a single space (unlike vim, it doesn't remove extra whitespace from the tail of joined-to lines).

If no range is given, the default range is (current,current+1), joining the line below to the one where the cursor is. If a single line number is given, the default end of range is the line after that one.

:pu[t]

:[line]pu[t][!] [x]

Pastes the text from register x after the given line. Zero is a valid line number here, and pasting after it results in pasting before the first line. If ! is given, it pastes before the given line.

The contents are always pasted in linewise mode, no matter what mode the original text was yanked in.

:co[py] / :t

:[range]co[py] dest

It copies the lines in the range given to just below the given destination line. Zero is a valid line number in this context, so that lines are copied to the beginning of the file. All line designators used in ranges work as the destination argument ('$', searches, etc...).

:t is just a synonym of :co[py].

:m[ove]

:[range]m[ove] dest

It copies the lines in the range given to just below the given destination line, and deletes the original text from its current location. Zero is a valid line number in this context, so that lines are moved to the beginning of the file. All line designators used in ranges work as the destination argument ('$', searches, etc...).

:p[rint] / :# / :nu[mber] / :P[rint]

:[range]p[rint] [count]

:[range]P[rint] [count]

:[range]nu[mber] [count]

:[range]# [count]

All these commands send the lines given by the range to the "ViEmu" tab in the output window. :nu[mber] and :# prepend them with the line number. If a count is given, it will print count lines starting with the last line in the range.

:g[lobal]

:[range]g[lobal][!]/regex/command

:g looks for matches of the given regular expression on all lines of the file, sets the cursor to each line that matches in turn, and then runs the given ex command. The command internally first scans the whole file for matches, sets a mark on each line that matches, and then runs the command once for every mark (after setting the cursor position to that line). Given that marks positions are properly updated for every modification done by the command, it can operate properly for many editing commands.

If the regular expression field is empty (:g//...), the last search string will be used.

If ! is given, the command is run for lines that don't match the given regular expression. This is the same as using the :v[global] command below.

For example, :g/^/m0 is the idiomatic way in vi/vim to invert a file: '^' is the beginning of line indicator, which by definition matches on every line. The "m0" command moves the line to the top of the file. Executing this command for all lines in order results in the file having the order of all of its lines reversed.

Another common idiom is :g/^$/d to delete all lines with no characters on them (if end-of-line matches right after beginning-of-line, it's because there are no characters in the line!). If you want to delete all lines with only whitespace, you can use :g/^\s*$/d which allows any number of whitespace characters but nothing else.

Anecdotally, this command is the source of the name of the popular Unix grep command: :g/re/p, where "re" stands for "regular expression", is the vi way to print out all lines matching the given regular expression, which is what grep does.

:v[global]

:[range]v[global]/regex/command

This is the same as :g[lobal]!, that is, it executes the command on lines not matching the given regular expression.

:s[ubstitute]

:[range]s[ubstitute]/regex/replacement/[gciI]

Together with :g, this is the most powerful ex command. ViEmu supports the 'g' ('global'), 'c' (ask for confirmation), 'i' (case insensitive) and 'I' (case sensitive) options, where vi/vim support some additional ones.

The command searches for matches of the given regular expression in the given range. It then replaces the matched text by the given replacement string. If the 'g' option is not given, a single match is looked for and operated on per line. If 'g' is given, multiple matches per line are searched for and acted on (the text inserted as the result of the substitution is not scanned though). The 'gdefault' preference reverses the default behavior and the meaning of the 'g' flag (see :set).

If the regular expression field is empty (:s//...), the last search string will be used.

The replacement string treats some characters and sequences specially. The character '&' is substituted with the matched text before inserting it (use '\&' if magic is not set). The sequences \1 to \9 are substituted by the corresponding matched subexpression before inserting them. '\r' inserts a line break, allowing multiline replacements. \u and \l make the next character uppercase/lowercase. \U and \L turn on uppercase/lowercase conversion for the rest of the string. \e or \E stop this behavior.

Other characters can be used instead of '/' as delimiters: :s,a,b,g is the same as :s/a/b/g. vim only accepts non-alphanumeric characters, while ViEmu accepts any character (but a space is needed before the first one if it is an alphanumeric character).

As an example, :%s/\s\+$// will delete trailing whitespace on all lines.

:&

:[range]&[g]

Repeats the last :s, overriding the original 'g' option with the given one, on the given range.

:*map family
                :map  <fromkeys> <tokeys>
                :map! <fromkeys> <tokeys>
                :nmap <fromkeys> <tokeys>
                :vmap <fromkeys> <tokeys>
                :omap <fromkeys> <tokeys>
                :imap <fromkeys> <tokeys>
                :lmap <fromkeys> <tokeys>
                :cmap <fromkeys> <tokeys>
              

<fromkeys> can be either a single key or a sequence of keys. The different versions of the mapping command apply the mapping in different contexts. Both <fromkeys> and <tokeys> can use ASCII characters directly, or key 'names' from the following list:

<F1> to <F12>, <Up>, <Down>, <Left>, <Right>, <Home>, <End>, <PageUp>, <PageDown>, <Delete>, <Insert>, <BS> = <Backspace>, <CR> = <Return> = <Enter>, <Space>, <Bslash>, <Bar>, <Esc> <Escape>, <lt>, <gt>, and <Tab>

Use a backslash ('\') to remove the special meaning of < or >. Use "\\" to refer to the backslash key itself.

You can add modifiers inside the angle brackets: <C-F2> means control + F2, <A-S-Up> means Alt + Shift + Up. The Shift modifier is ignored for ASCII character mappings, as its meaning is included in the ASCII code.

These are the different contexts with their meanings:

  • normal, visual, insert: refer to each of the modes.
  • command-line: refers to command line editing, both for '/' searches and ':' ex commands.
  • operator: refers to the situation of ViEmu being waiting for the motion after an operator command
  • language: this refers to insert mode, command line editing, or the part of commands that is composed of content-characters (the argument to the f/F/t/T motions, the argument of 'r', etc...)

The command applies the mapping in the given context. Any entering of the sequence 'fromkeys' given in the left hand side will be substituted by the 'tokeys' list of keys on the right hand side. These keypresses will further be scanned for other mappings (see :*noremap). Raw :map applies the mapping in all normal, visual and operator-pending contexts. :map! applies it to insert mode and command line editing mode. :lmap applies it to insert, command line editing and language-arg contexts.

For a multiple-key-chord mapping (:nmap c_ ct_), if only part of the input has been typed (say, 'c'), ViEmu will wait until the next key disambiguates whether the mapping has to be applied or not. ViEmu by default waits for one second, and if no other key is received, it triggers processing the received keys normally. See the description of the "timeout" and "timeoutlen" :set options for details.

:*noremap family
                :noremap  <fromkeys> <tokeys>
                :noremap! <fromkeys> <tokeys>
                :nnoremap <fromkeys> <tokeys>
                :vnoremap <fromkeys> <tokeys>
                :onoremap <fromkeys> <tokeys>
                :inoremap <fromkeys> <tokeys>
                :lnoremap <fromkeys> <tokeys>
                :cnoremap <fromkeys> <tokeys>
              
See :*map. The operation is the same, except that the right-hand-side key sequence will be interpreted directly and it won't be scanned for mappings.
:*unm[ap] family
                :unmap  <keys>
                :unmap! <keys>
                :nunmap <keys>
                :vunmap <keys>
                :ounmap <keys>
                :iunmap <keys>
                :lunmap <keys>
                :cunmap <keys>
              

These commands remove the sequence <keys> from ViEmu's mapping table for the given context(s), making it return to its regular behavior. If the mapping applied to several context, it is left active for the rest of the contexts.

:delm[ark] {marks}

Removes the given marks, which can be space separated or not, and global (uppercase) or local (lowercase).

Ex ranges

All ranges are composed of a sequence of line specifiers separated by ',' or ';'. If more than two line specifiers are given, only the last two are used. Separating with semicolon makes the next line specifier start from where the previous one left, which is important in relative line specifiers.

The simplest line specifiers are just line numbers (1-based). For example, the range "1,100" represents the first 100 lines. Thus, ":1,100d" will erase the first 100 lines in the file.

There are two simple special line specifiers: '$' stands for the last line in the file, and '.' stands for the current line. Thus, ":.,$d" will erase all lines from the current one to the end of file.

As a special case, '%' is itself a shortcut for '1,$', thus representing the whole file. It is quite common to use '%' with the :s command to perform a substitution in the whole file: ":%s/one/two" will replace the first appearance of "one" by "two" on all lines (append "/g" to do it on all instances).

Marks can also be used as line specifiers: use a quote followed by the mark character to represent the line where the mark is. Special marks such as ''', '.', '<' and '>' can also be used. Actually, when you press ':' in visual mode, the ex command line is started with ":'<,'>", which represents the currently selected visual range of lines. This range can also be specially specified as "*", in the same vein as "%".

Finally, lines can also be specified by forward or backward searches. Use "/re/" to refer to the first match of "re" from the start position (either the cursor position, or the previous range element if separated with ';'). Use "?re?" to find backwards. As an example, ":/abc/;/def/d" will first look for "abc" starting from the cursor position, then look for "def" starting from *that* line, and then delete those lines and all in between.

You can add as many '+N' or '-N' modifiers, where N is a number, to each specifier, modifying the base line it refers to. Typing "N:" from normal mode enters ex command line editing with ":.,.+{N-1}" as a prefix, resulting in a range that specifies N lines starting at the current one.

If a single line is specified for a range, the implicit range depends on the command - see the descriptions above. Actually, only the :j command understands the implicit range to be that line and the next, all other commands understand the one-line range implied by using the given line as both start and end of range.

Initialization file: .viemurc

When ViEmu is started by Xcode, it scans the current user's home folder for a file named '.viemurc'. If it is found, the file is loaded and its contents executed as ex commands (no colons are necessary before each line). Given that these commands are run in a context with no 'current file', the only commands that make sense are :set, :*map and :*unmap. Typically, this file is used to set options that are to be applied always. Within ViEmu, preferences as specified in Tools|Options|ViEmu are loaded before loading .viemurc, so options set in .viemurc overwrite and take precedence over regular settings.

If an error is found in any line, the file name and line number will be output to the Output section of the Debug area of Xcode.

Empty lines are skipped, and comments can be inserted in the file by inserting a " to begin the line




9. Differences with vi and vim

Although ViEmu is designed to provide the most comfortable environment to both vi and vim users, there are many differences between ViEmu and any of them. For one, there are parts of vi and vim which are not (yet) emulated by ViEmu. On the other hand, there are some things that we chose to implement differently because they made more sense within Xcode (a foreign environment to vi/vim editing, and one which imposes a different view on many aspects). This section details both the intended differences, and the yet-to-be-implemented features of vi/vim.

Things emulated slightly differently (for better integration)

If you find that any of these is troublesome, please
tell us so that they can be addressed.
  • Default yank/del/paste buffer can be configured to be the Mac clipboard (special register "*" in vim)
  • C-u, C-d, C-f and C-b are emulated as motions. This means they can be used to extend the current selection or as operator command arguments. There doesn't seem to be any loss in doing this way, there are definite advantages, and it's not easy to understand why they are not motions in vim - except C-u and C-d, which act as motions for visual selection extensions, but not for operator command arguments.
  • Behavior when pasting over a visual-mode selection is slightly different from vim when the pasted register and the selected ranges are of different types. We think ViEmu's model makes a bit more sense, although none of the two models are a very useful editing operation.
  • When repeating with '.' a command that operated on a visual motion, if the range was charwise, it is simulated keeping the line and column offset, in place of per character count. This usually makes more sense.
  • Multi-line input (as invoked with 'I','A', 'C' or 'c' from visual-block selection mode) in vim doesn't work if deleting characters, joining lines or splitting them. ViEmu supports this in most cases (where it makes sense).
  • Multi-line input supports counts for 'c' and 'C' commands as well, not just for 'I' and 'A'
  • "Inner selections" by pairs of delimiter characters ("ib"/"i)"/"i(", "iB"/"i}"/"i{", "i>"/"i<", "i["/"i]") move the last character to the end of the previous line when the closing character is the first non-whitespace in its line. This is done by vim only for curly-brace blocks ("iB"/"i}"/"i{"), but not for the rest. It aids in being able to indent material between delimiters, and even if does not usually appear in C or C-like languages, it is equally useful for the rest of the delimiter pairs.

Limitations / things not emulated

We definitely intend to address these limitations in further releases of ViEmu. Please tell us which features you are more interested in.
  • vi-style abbreviations are not supported.
  • [[,[],][,]] only search braces in column 0, not section boundaries as defined by form-feed characters.
  • Sentence delimiters in ViEmu are '.', '!' or '?' *strictly* followed by either newline, space, tab, ')', ']', '"' or '"', apart from completely empty lines. vim supports a bit more flexibility.
  • Block selections with a non-fixed-width font don't represent well when VS selection is used represent the selection. There are other inconsistencies here as well in the presence of folds or word wrapping. Using the custom-text-markers selection is recommended.
  • "Virtual edit", that is, moving the cursor beyond end of line, is not supported.
  • Auto completion in input mode does not support C-x line completion mode, and is based in Xcode's autocompletion rather than proper vim-emulation.
  • CUA-style (regular Windows) shift+movement-key selection is not supported.
  • % doesn't match C-style comment delimiters or preprocessor #ifdef's
  • Actions in the undo list don't have descriptions
  • ^J, ^N, and ^P bring up Intellisense autocompletion instead of filescan autocompletion.
  • In overtype mode (such as with the R command), BACKSPACE does not restore the last character as vim, it erases it. This is required due to interactions with Intellisense.
  • Numbered registers "0 to "9 do not "roll" like in vim, they are regular registers.
  • Pasting over a visually selected region (p or P in VISUAL mode) does not copy the selection into any register
  • Cursor positions after undo/redo are not the same as in vi/vim. This is due to VS's undo mechanism.
  • ViEmu has only been limitedly tested with non-single-byte or non-left-to-right codepages. There are provisions in the code for these issues, but they are untested and unsupported as of now. No provisions have been made either for right-to-left or bidirectional text. The only feature is resetting the IME (if present) when leaving insert mode. Supporting these features is planned for future versions, and we would be glad to hear from you about how it works for you in this respect.



10. Support

Support is available via e-mail and on the support forums. You can write to
support@symnum.com for any question. All inquiries are answered within two business days, usually much faster.

The support forums are available at www.viemu.com/forums. Apart from support questions, frequent updated builds are announced there.

We try to address as promptly as possible any questions with installation or ViEmu, esp. fixing bugs in the software.

When reporting a problem, please try to provide general information about your system (OS, version of Xcode you are using, other installed add-ins, etc...), and as much information as you can about the context in which the problem appeared (last action performed, state of the sytem, etc...).

If you are not yet a registered customer, but you have found some problem installing or using the evaluation version of ViEmu, we will be glad to answer any question you send to the above support address.



11. Change log

ViEmu 3.7 (November 2016):

  • Added vi/vim search offset support: /something/+1, /something/;/else/e+2, etc...
  • Added support for SQL Server 2016, Xcode 8, improved Visual Assist compatibility

ViEmu 3.6 (August 2015):

  • Enhanced the % motion to fully emulate vim: added suppport for navigating #if/#else/#endif and /* */ C-comments
  • Added support for Visual Studio 2015 and Xcode 7

ViEmu 3.5 (June 2015):

  • Added support for it/at XML-style tag objects
  • Unified back-end build system enabling full new releases of all ViEmu versions

ViEmu 3.3.0 for Xcode (September, 2014):

  • Added support for Xcode 6

ViEmu 3.2.4 for Xcode (April 28, 2014):

  • Fixed a bug that caused ViEmu to not behave correctly when switching between several opened editor windows

ViEmu 3.2.3 for Xcode (April 17, 2014):

  • Fixed a bug that caused duplicated ViEmu status bars
  • Caret and Visual Range related commands that result in an Xcode command, such as =%, work again

ViEmu 3.2.2 for Xcode (April 16, 2014):

  • Fixed a bug that caused Xcode to hang sometimes when executing some commands such as :w
  • Fixed a bug that caused ViEmu status bar to not update its position correctly
  • Fixed a crash due to the delayed processing of events for ambiguous mappings when the view was released after the first key process
  • Fixed a crash when an editor window was released, due to the ViEmu status bar not being correctly detached and released

ViEmu 3.2.1 for Xcode (April 10, 2014):

  • Fixed a bug that caused a crash due to dangling pointers to Xcode views

ViEmu 3.2 for Xcode (April 8, 2014):

  • ViEmu for Xcode 5 released
  • Folding/Unfolding commands zc/zo/zR/zM implemented

ViEmu 3.1.1 for Xcode (July 25, 2013):

  • Fixed several crash-causing bugs
  • Added an option to enable/disable beeps to the ViEmu Settings dialog
  • Added options to change the visual range and caret colors to the ViEmu Settings dialog
  • Ctrl+] should now go to the definition of the object under the caret (same as Cmd+click)

ViEmu 3.0.13 for VS2010 (December 21, 2012):

  • ViEmu setting 'Prevent read-only warning' now works as expected, unsetting the read-only flag on buffers so that ViEmu commands can be executed.
  • Search matches are now automatically unfolded.

ViEmu 3.0.12 for VS2010 (December 3, 2012):

  • Fixed a bug in the code that detects the presence of third party extensions.
  • Fixed a bug in the trial period detection system.

ViEmu 3.0.11 for VS2010 (October 30, 2012):

  • Fixed a bug that caused Visual Studio selections not to clear correctly, which caused many side effects.

ViEmu 3.0.10 for VS2010 (October 19, 2012):

  • Fixed a bug that caused weird scrolling when using some motion commands in VS2012

ViEmu 3.0.9 for VS2010 (September 19, 2012):

  • ViEmu should now detect correctly the presence of 3rd party extensions such as VAX and R# in VS2012 and Windows 8

ViEmu 3.0.8 for VS2010 (September 6, 2012):

  • Fixed a bug that caused VS 2012 to crash on exit.
  • Fixed a bug that caused a support-invalid license not to show its correct message.
  • 'Delete' key doesn't edit view text when we are in search or command mode, and rather edits the status bar text.
  • R#'s rename command is intercepted and ViEmu enters insert mode automatically (this was lost in v3.0).

ViEmu 3.0.7 for VS2010 (August 7, 2012):

  • Fixed a bug that caused buffers not to be deleted from the buffer list when closing a tab with :q command

ViEmu 3.0.6 for VS2010 (July 17, 2012):

  • Optimized search code for a much faster response time
  • Fixed '.' repeat command when using autocomplete features from VS or 3rd party add-ins.
  • Fixed problems when 'Use VS selection for visual mode' is set, such as ViEmu entering visual mode automatically when Visual Assist edited code while typing for options such as 'Insert _ after m and shift'.
  • Fixed a bug that caused strange scrolling behaviour when 'Use VS selection for visual mode' was set and a visual studio selection was active

ViEmu 3.0.5 for VS2010 (July 05, 2012):

  • Fixed a bug that caused R# autocompletion popups to not be dismissed when pressing ESC (and VAXEsc option was active)
  • Fixed a bug that caused macros to record twice input characters when 'Ignore CAPS-LOCK state in NORMAL' option was set
  • Fixed a bug that caused unindent to delete characters in some cases
  • Fixed the "beeping" when entering normal mode when VAXesc is active and no popup is present

ViEmu 3.0.4 for VS2010 (June 29, 2012):

  • Fixed a lag in the ViEmu caret position when typing in insert mode in certain configurations.

ViEmu 3.0.3 for VS2010 (June 27, 2012):

  • Fixed a bug that caused ViEmu caret not to update when cursor position was changed through the mouse.

ViEmu 3.0.2 for VS2010 (June 26, 2012):

  • Fixed a bug that caused ViEmu to not work correctly when the option 'Use VS selection for visual mode' was active.

ViEmu 3.0.1 for VS2010 (June 25, 2012):

  • Added support for the 'c', 'i' and 'I' options of the search and replace command.
  • Added file-scan autocompletion support, with Ctrl-N/Ctrl-P keys in insert mode.
  • Fixed the problem with ReSharper intercepting 'Enter' key while in normal mode if the cursor was in a codedoc comment or a string.
  • Added F1-F12 viemu key commands, with their respective Shift/Alt/Ctrl modifiers, so that they can be mapped to ViEmu commands.
  • Fixed the problem with Visual Assist's autocompletion combo appearing while in normal mode.
  • Support for Visual Studio 2012 RC.
  • Fixed a bug regarding visual block copy/paste.

ViEmu 2.5.10 for VS2010 (October 21, 2010):

  • Fixed Visual Studio lockup on replace command when replacing with an empty string.
  • Fixed some motions that didn't work when the 'Windows-like wordwrap navigation' setting was active.
  • ReSharper should now not add a closing '")]} while in normal mode when 'Auto-insert pair brackets, parentheses and quotes' option is on.
  • The 'multiple Esc presses needed to return to normal mode' with ReSharper and ViEmu should now be alleviated.
  • Added code to enhance general application stability

ViEmu 2.5.9 for VS2010 (October 13, 2010):

  • Remaining ViEmu settings, including 'Use VS Selection for visual mode', implemented.
  • Performance improvements, specially for cut/paste and search&replace operations.
  • ViEmu enters visual mode automatically when an external VS selection is made.
  • ViEmu provides a MEF service that exposes the same functions that the ViEmu NG did.
  • ViEmu caret shows now correct size and position when Windows DPI settings are changed.
  • ViEmu caret should not appear anymore when opening a file while ViEmu is disabled.
  • ViEmu caret blinking time is now read from the system's settings.
  • Fixed a bug that prevented some Visual Studio commands from being executed through the :vsc ex command.
  • Fixed a bug that caused Visual Studio package projects to not be created correctly through the VS New Project Wizard.
  • Fixed an incompatibility bug with Visual Assist that caused the insertion of }])'" in normal/visual mode when the Visual Assist option 'Insert () and closing })]'"' was checked.
  • Added the 'Use adornments for hlsearch and visual range' setting: Text adorments have been used until now for visual range and highlight search markers. These adornments render behind the text and preserve syntax highlight of the text marked, and thus don't allow for text foreground color modification. If this setting is unchecked, the text itself of the hlsearch or visual range will be modified, and the foreground color selected in 'Fonts and Colors' will affect the foreground text color.

ViEmu 2.5.7 for VS2010 (August 16, 2010):

  • vaxesc option support (to make Esc both close down the Visual Assist drop down and exit insert mode)
  • Visual Assist suggestions disabled in normal mode (this was a tough nut to crack)
  • Resharper's Rename command is detected and ViEmu auto-enters insert mode
  • ViEmu's '.' command now works correctly even if Visual Assist is configured to convert it to '->' in some cases
  • ViEmu's 'Default to Windows clipboard' option should now work just fine
  • License detection code now works with temporary licenses (we sometimes send them out manually, to extend trials, etc...)

ViEmu 2.5 for VS2010 (July 2010):

Rather than a list of changes, this version sports a full rewrite of the VS-integration portion of ViEmu. The core vi/vim emulation is the same, template-based C++, this time compiled as managed, .NET C++/CLI. The VS-integration part required a mostly full rewrite to accomodate the new WPF- and MEF-based editor. This will bring some new bugs that will need solving in future versions, but mainly, it will allow us to have the best architecture for new versions of ViEmu moving forwards, which will allow us to benefit from all new features of the fully-rewritten VS2010 text editor architecture.

ViEmu 2.5 (April 20 2010):

Version 2.5 consolidates all 2.2.x improvements, brings important new features, and implements the new Symnum licensing system

2.2.2:
  • Better i' a' i" a" logic
2.2.3:
  • Improved pasting logic
  • Improved handling of RETURN in C# comment areas, with Resharper installed
2.2.4:
  • Improved compatibility with Resharper
2.2.5:
  • Fixed bug that could cause a crash when editing HTML
2.2.6:
  • Minor fixes in installer
  • Removed potential race condition
2.2.7:
  • Better Visual Assist X compatibility (for VA 1707 or later)
2.2.8:
  • Works better with Lua when Visual Assist X is present
  • Fixes "100%" motion (including precise {n}% vim emulation)
  • Better R# compatibility (detects R#-inline-rename mode by presence of VS marker, and auto-enters VS mode)
2.2.9:
  • Fixed {n}| motion behavior (was off by one)
  • :ern[ext]/:erp[rev] commands to navigate errors
  • New EXE-based installer, clearer, and better compatibility with Vista/Win7 UAC
New 2.5 fixes and features:
  • Implemented multiple-key chord mappings (:nnoremap end $), with ambiguity support, timeout, timeoutlen, etc..
  • Implemented Ctrl-A/Ctrl-X command to increment/decrement numbers (or letters), also with 'nrformats' variable
  • Implemented insert mode Ctrl-Y/Ctrl-E to copy character from line above/below
  • Fixed bug: right after 'g' or 'z', normal mode mappings are not applied (technically it's in normal mode, but it's more like a parsing sub-mode)
  • Fixed bug: made searching backwards actually work with \zs somewhere other than at the start
  • Fixed bug: removed buffer from buflist (:ls) after closing it with :q, same as was done before with :bd
  • Fixed bug: K did weird things in visual mode (moved to top), fixed (now it does nothing)
  • Fixed bug: an empty o<esc> would not set the `. mark, now it does
  • Fixed bug: improved compatibility when editing SQL files with VS 2008 Database Edition (cmdline editing issues)
  • New licensing system

ViEmu 2.2 (July 14th, 2008):

Version 2.2 consolidates all 2.1.x improvements, and brings important new features, like vim 7's i'/a'/i"/a" motions text object motions:

2.1.1:
  • Fixed ViEmu not working when editing stored procedures
2.1.2:
  • Removed the warning when you try to paste in a read-only buffer
  • Added user setting to remove "Read-only op" warning
  • Removed dialog box when trying to paste in a readonly dialog
2.1.3:
  • Fixed freeze when using Find in Files... with VS2005+
2.1.4:
  • :n, :N as synonims of :bn, :bp
  • Made 'a or `a or :13 open folds
  • Fixed the "ct<space>" problem when <space> is :mapped to something (changed order when determining current mappin context, lang-arg must come before op-arg)
  • Fixed XML and HTML file interception in VS2005 if you hadn't opened a project (Visual Assist interaction)
2.1.5:
  • Added installation for Orcas March'07 CTP, this adds support for VS2008
2.1.6:
  • Fixed 'zz' problem with wordwrap in VS2005, all languages but C++
2.1.7:
  • Fixed ViEmu not working with SQL files when Visual Assist is present
2.1.8:
  • Fixed crash when searching for "\zs*" due to the 'incsearch' feature
  • Made Ctrl-U in cmdline mode delete back to the start
  • Made Ctrl-W in cmdline mode delete a word
  • Made Ctrl-U in insert mode delete back to the point of insertion
  • Made Ctrl-W in insert mode delete a word
  • Removed "--NORMAL--" and similar modeline info when typing a search or an ex command
  • Better emulation of vim's "vi undo mode"
  • Addressed i_Ctrl-D differences with vim
2.1.9:
  • Fixed ViEmu crashing when enabling/disabling it, in VS 2005 with Service Pack 1, due to mishandling and empty removal-keybinding list
2.1.10:
  • Fixed crash in VS2005 under Vista, after doing a refactor, got minidump (crashed handling with the 'preview' window)
2.1.11:
  • :s options \u \U \l \L didn't work with \1 type submatches, fixed
2.1.12:
  • Fixed crash when setting a number mark (global) (ie, m3)
  • Global marks were not edit-updated in VS
2.1.13:
  • Undo undid too much with Visual Assist and other VS actions
  • Made :s show a message if nothing is found
2.1.14:
  • Block mode editing with VB was wrong, fixed!
2.1.15:
  • Made // and ?? shortcuts repeat last search
2.1.17:
  • Fixed ViEmu - Visual Assist incompatibility in XAML, XOML files under VS2k8
2.1.20:
  • Fixed ViEmu 'undo' crashing if done right after Coderush 'Safe Rename'
2.1.21:
  • Updated Resharper cmd detection to Resharper 3.1
2.1.22:
  • Added proper handling of keybindings in the Korean localized version of Visual Studio
  • Added :ve[rsion] command to show the version and web address for ViEmu
2.1.23:
  • ViEmu didn't work with F# and Visual Assist, fixed
2.1.24:
  • vj$:s/.../ woudn't work, said 'mark not set'
  • Fixed wrapscan fails when searching exactly from beginning-of-file and end-of-file
2.1.25:
  • Fixed ViEmu crash when using <c-]> with Visual Assist
2.1.26:
  • ViEmu froze VS when doing 'undo' when debug-running an ASPX/VB app under VS2008, fixed
2.1.27:
  • Return in XML files was non-functional when Visual Assist is present, fixed
  • Made <c-v>i} always extend selection by changing cursor sanitization to allow EOL in non-chars visual modes
  • Made the fold command create the outlining session if it doesn't exist
  • Made zf move the cursor to the first char, regions weren't always being folded in VS2k5+
  • Made :omap w iw work fine and not screw up "diw", "daw"... by applying it only at the first char after an op (like vim)
  • Made gS only effect if last command in macro (or if stand-alone)
  • Implemented gt/gT to go to next/prev buffer
New 2.2 fixes and features:
  • Fixed bufpos remembering when doing gt/gT/:bn/:bp
  • Implemented gp/gP to paste and leave the cursor after the pasted text
  • Implemented i', i", a', a" vim7 text-object motions

ViEmu 2.1 (February 26th, 2007):

Version 2.1 makes official the many fixes and improvements provided as maintenance releases since the release of 2.0:

2.0.27:
  • :noh[lsearch] implemented
  • hlsearch setting wasn't honored on startup, even if it was shown fine in Tools|Options|Viemu
  • The desired-cursor-col was not reset after moving the cursor by left-clicking
  • :set gdefault would not work in .viemurc
  • Pasting in VB would lead the language service into "partial" corrections and lead to syntax errors
  • The \| operator in regular expressions didn't work fine (would only match the second branch)
  • Keyboard management should now support the Japanese version of Visual Studio
2.0.28:
  • Ctrl-T/Ctrl-D in "virtual space" work fine (after o/O with autoindent)
  • :bd now removes the buffer from the buffer list (it also closes the file if it's the current file, not if it isn't)
  • <c-t> now invokes View.PopBrowseContext (poor man's tag stack pop)
  • :set [no]remap implemented to disable all recursive mapping
  • infinite mapping loops detected & cut (eg, :map n l and :map l n)
  • visual block done by ^Q j $ now extends to the $ of each line
2.0.29:
  • 'A' on a visual block extended to end of line ($) wouldn't work
2.0.30:
  • dd on a single-line file (or dG from the 1st line in any file) would leave a dangling line, fixed
  • Special marks '[, '] (last pasted/changed/yanked/etc... range) and '^ (last insert pos) added
  • Added gi command, to go into insert mode at the last insert position
2.0.31:
  • Proper keybinding management in German Visual Studio
2.0.33:
  • Command line space much larger (it was read & processed, but not properly displayed)
  • Yanking of column blocks with empty lines fixed
  • Playing a macro from an empty register would crash VS (@a)
2.0.34:
  • Special marks '[, '] and '^, introduced in 2.0.30, no longer cause the insertion of VS marks when the relevant option is selected in Tools|Options|ViEmu.
2.0.35:
  • Crash when yanking/deleting a $-extended characterwise block fixed. This is after having added proper $-extended column block handling back in 2.0.28.
2.0.36:
  • AltGr keys in international keyboards (Swedish, Spanish, etc...) didn't work right in normal mode. Esp. the '@' command (AltGr-2).
  • Changed the first-time keybinding removal logic so that it won't remove extra standard keybindings (backspace, ...)
  • Made Ctrl-[ in international keyboards where '[' is not on the same key as on the US keyboard work as Esc again
2.0.37:
  • Fixed the '%' motion to start checking at the last character is the cursor is beyond the end of line (as vim)
2.0.38:
  • Some remaining problems of AltGr key combinations fixed for international keyboard layouts (not repeating AltGr characters with '.')
  • Cursor position was not restored properly after many operations (dd, r*, etc...) - this was broken since 2.0.27
2.0.39:
  • Pasting over a linewise visual selection at end-of-file didn't work well
  • Editing a long command line could result into a crash (only actually likely in versions before 2.0.32, where the buffer was small)
  • '.' would stop working properly for input repetition after switching back and forth between two split views of the same file
2.0.40:
  • Crash that happened when exiting Visual Studio if no ViEmu-subclassed window had been actually used.
2.0.41:
  • Tabify/Untabify commands under Edit|Advanced wouldn't work
  • gu/gU/g~ could get into an infinite loop when modifying lines with hard tabs while using soft tabs (or viceversa)
2.0.42:
  • Shift-Tab in insert mode fixed so that it does its usual VS operation, that is, it unindents the line and cursor position if the cursor is anywhere in the leading whitespace in the line (else it does nothing).
2.0.43:
  • :g and :s with use (when given an empty regex) and modify (in other cases) the 'last-search-string' as vi/vim, the same value used by n/N to repeat the last search
2.0.44:
  • Implemented :> and :< ex commands for indenting/unindenting a range of lines
  • Implemented ":set [no]list" option, it toggles Visual Studio's "View Whitespace" setting
  • Implemented ":set [no]wrapscan" (or ":set [no]ws") option, it toggles wrap-around behavior for searches
2.0.45:
  • The "Use VS Selection for visual mode" and "Windows-style word-wrap navigation" settings weren't honored on startup. They were persisted and read properly, and they'd make effect from the settings UI, but not when starting up VS again.
2.0.46:
  • :g was broken in builds 2.0.43 through 2.0.45, it's fixed here
2.0.47:
  • Experimental support for CUA-style selection (Shift+Arrow Keys or Navigation Keys)
  • Pasting a block at the end of the file would send the cursor up to the top of the file
  • Fixed "//<return>" from creating a slow editing experience because of invisible zero-width markers inserted in between every two characters
2.0.50:
  • Vista compatibility
  • Fixed problems when using 'r' in a $-extended visual selection
  • Fixed highlighting of block visual selection when there were hard tabs in a line
2.0.51:
  • Motions i or a followed by one of {}<>[]bB now are adaptive linewise/charwise, as in vim
  • Ctrl-] followed by Ctrl-O didn't return to the point before Ctrl-], but to the one before that (it failed only in intra-file jumps)
  • When searching with '*' or '#', \<token\> is now added to user-typed search history (you can do /<up> and they'll be there)
  • Fixed bug in "single-line" files (cursor doesn't move) - it's a VS.NET 2003 bug, but ViEmu made it more apparent
  • Implemented ':set'/':set all' to show all the current settings
  • The cursor sometimes wouldn't properly have its block shape since the first moment (hopefully fixed)
2.0.52:
  • gI (input at "hard" beginning-of-line - column 0) implemented
  • The '[' character was not allowed in sets in regular expressions ("[[abc]" means any of a, b, c and '[')
  • Fixed repetition with '.' of input including high-ascii characters (>127)
2.0.53:
  • ViEmu/VS 2.0.52 had debug logging enabled by default
2.0.54i:
  • v$ wasn't represented well when using VS selection for visual mode
  • ESC now removes the status message in normal mode
2.0.55i:
  • InternalUndoGroup() improved to obtain better performance (only slowed down in some installations)
2.0.56:
  • Resharper compatibility extended to Resharper 2.5
2.0.57:
  • Pasting a multiline block in a read-only file will now only warn once
2.0.59:
  • EULA updated to reflect the per-user license type (you could stay with the previous license, but this is just less restrictive)
2.0.60:
  • Tilde key didn't work in swedish keyboard
2.0.61:
  • 5:s syntax and offset-ranges (:.,.+4s/...)
  • Uppercase operators in :s subst string (\u \U \l \L \e \E)
  • gd to go to local definition
  • :u[ndo] and :red[o]
  • " comments allowed in .viemurc
  • 'v' in visual-chars, or 'V' in visual-lines... now exit visual mode
  • HLSearch calculation made incremental, huge boost to the performance of hlsearch with large files
  • Paste auto-reindent (]p)
  • Searching with wrapscan doesn't enter folded #regions or outline folds
  • IME reset when pressing ESC (useful when using Japanese and other Far East languages)
  • /;<cr>i<cr> failed, second <cr> didn't work (ECMD_RETURN was cached disabled)
  • Force undo grouping to be cut on buffer change (same as vim)
2.0.62:
  • :bd wouldn't work in the first buffer (All)
  • :bd wouldn't work after closing a buffer with :bd and reopening it, if no other buffer got the focus in between (All)
  • Find in Files could sometimes freeze if hlsearch was enabled (VS+SQL)
  • The return key wouldn't work in the first opened buffer if Visual Assist is installed (VS)
2.0.63:
  • Fixed another edge case in Visual Assist interaction, which would prevent Return from happening in VS2005 (can also happen in VS.NET 2003, but it's less likely).

ViEmu 2.0 (September 20th, 2006):

ViEmu 2.0 is in many senses a re-implementation, based in a new vi/vim emulation core. A much more advanced integration framework has also been developed. The main new features are the following:
  • hlsearch
  • Proper vim-like visual area representation
  • Proper undo-grouping of operations (cw...)
  • Proper Intellisense-autocompleted input repetition
  • Automatic VS keybinding management
  • Advanced mapping support (":cmap <c-n> <down>", ":map \\ /xkz<esc>"...)
  • Buffer number commands - :ls, :b[uffer] <n>, :bn[ext]/:bp[revious] with these numbers
  • Proper wordwrapping support, better and faster folding support
  • Better incremental search (works also in visual mode)
  • Macros stored in regular registers (use qa to record a macro and paste the contents with "ap)
  • a..z marks local and A..Z global
  • Proper autoindent when repeating input
  • Cursor kept on screen in <c-e>/<c-y>
  • Proper <c-f>/<c-b>/<c-d>/<c-u> which always scroll
  • Proper iw/iW/ib/iB/i)/i}/i>/i] and a*... emulation
  • Proper block selections in the presence of folds/wordwrapping
  • 'o' command in visual mode
  • :delmark command
  • :xa[ll] and :wqa[ll] command
  • :vsc[md] command
  • Count support for the | motion
  • gJ command implemented
  • gS command implemented
  • zR fixed
  • J/:j joins fixed to work as vi/vim (inserts a single space)

ViEmu 1.4 (November 25th, 2005):

New features added:
  • Visual Studio 2005 support
  • ":wa[ll]" to write all files
  • "gf" to open the file under the cursor
  • "gq" operator to reformat code (via VS's autoformatting mechanism)
  • "=" operator (same as gq)
  • "|" motion to go to beg-of-line (same as '0')
  • "%" allowed in non-pair characters - it scans for first one, then jumps from that one
  • Ctrl-R recalls the contents of a register at the command line or in insert mode (as in vim)
  • :macro command implemented: it allows running a Visual Studio macro from the ex command line
Bugs fixed:
  • 'yy' doesn't move the cursor to the beginning of the line any more (similar with other motions for yank)
  • The 'immediate' command window and the 'find results' windows are no longer overtaken by ViEmu
  • The cursor now gains block shape as soon as a window is open
Maintenance release 1.4.2 (Jan 3rd, 2006):
  • Mouse selection after end-of-line now works fine
  • ZZ command implemented (same as :wq, save and quit)
  • Visual Studio's messages on the status bar aren't overridden so often
  • No querying about "backwards range given" when a visual selection is made upwards and an ex command is applied over that
  • /<ENTER> and ?<ENTER> now properly repeat the last search (was broken in 1.3)
  • Cursor position after linewise paste is now correct
Maintenance release 1.4.3 (Feb 5th, 2006):
  • New settings: 'smartcase' and 'remove-vs2005-readonly-warning'
  • MessageBoxes from ex command errors converted to status bar messages
  • 'N lines yanked'/'N more lines' messages for yank/paste commands
  • :set [no]viu[ndo] to revert to single-undo as in the original vi
  • Ctrl-HOME/Ctrl-END now work.
  • */# now act as if 'smartcase' weren't set, as in vim, so that it acts only along the current 'ignorecase' setting.
  • Implements '\r' in the :s replacement string to insert a newline (multi-line matches were supported, but not multi-line replacement strings)
  • <RETURN> now goes to the first non-blank character of the line below
  • Ctrl-N/Ctrl-P work properly both in normal and insert mode
  • '/<RETURN>' and '?<RETURN>' properly update the search direction for further n/N motions.
  • Basic :map/:unmap support which works only with single-character to single-character mapping
  • ViEmu scans its installation folder at startup for a '.viemurc' or '_viemurc' file, and executes it if present (only :set/:map/:unmap actually do anything there)
  • New ex commands :prb[uild] and :qa[all]
  • Ctrl-Y to yank the command line
  • Behavior of the END key slightly altered to fix an interaction problem with Workspace Whiz
Maintenance release 1.4.4 (Mar 13th, 2006):
  • Fixed input of Cyrillic text (and possibly others)
  • Fixed T and F motions range when used as operator argument
  • Fixed '' and `` so that they never jump between buffers, as vim
  • Added experimental VS.NET 2002 support
  • Implemented message 'N substitution on N lines' for :s
  • Added a DLL to the package which prevented ViEmu from loading in some circumstances
  • Fixed a problem when performing a :'<,'>s with the region going to the line before last
  • Fixed a bug resulting in 'smartcase' and 'remove-read-only-warning' preferences not being honored at startup
  • Prevented Intellisense from kicking in when using BACKSPACE in either VISUAL or NORMAL modes (it was causing trouble with VB)
  • Made ViEmu check $HOMEDRIVE/$HOMEPATH and $HOME for the .viemurc or _viemurc file before checking the installation folder
  • Implemented :cn/:cp, although they only work properly if the output window is 'pinned' (that is, it doesn't slide out of view automatically).
  • Fixed cursor position after ^N/^P autocompletion
Maintenance release 1.4.5 (Jun 6th, 2006):
  • :ta[g]
  • ^W<Up>/<Down> to switch windows
  • HOME now jumps to the hard beginning-of-line
  • Ctrl-Shift-Alt-V globally toggles ViEmu on/off
  • g*/g# search for the identifier under the cursor, down and up, w/o requiring a full-word match
  • Implemented Ctrl-^ to switch to the previous buffer
  • :set [no]incsearch/[no]is support
  • CodeRush compatibility plugin implemented
  • ^Wc and :clo[se] to close the current window/file
  • Y in visual mode now returns to normal mode
  • "INSERT --" is now "-- INSERT --" as in vim
  • Cursor now updated after :d
  • Block cursor not lost with some operations
  • Undo/redo now should properly restore the cursor pos in all operations
  • :f[ile] command
  • New Welcome/Trial dialogs, and more links in Tools|Options|ViEmu
Maintenance release 1.4.6 (Jun 27th, 2006):
  • Resharper compatibility: included code to enter insert mode automatically when an inline 'Rename' command is launched
  • Visual Assist compatibility: included code to detect Visual Assist and guarantee proper order of editor window subclassing
  • Visual Assist compatibility: included code to return from insert mode when pressing ESC even if Visual Assist has a drop-down opened
  • Visual Assist compatibility: added :set [no]vax[esc] option to govern the behavior in the previous point

ViEmu 1.3 (November 5th, 2005):

New features added:
  • gv command: gets back into visual mode with the last visually selected range and range type
  • '< and '> marks store the beginning and end of the last visual selection
  • Command line editing with history for '/', '?' and ':' commands
  • ex emulation: :set, :d[elete], :y[ank], :j[oin], :pu[t], :co[py]/:t, :m[ove], :p[rint], :nu[mber]/:#, :s[ubstitute, :&, :g[lobal] and :v[global]
  • Regular expressions in search motions ('/' and '?') and ex commands
  • & command in normal mode
  • The following :set params work: [no]magic, [no]ignorecase, [no]smartcase

ViEmu 1.2 (September 29th, 2005):

New features added:
  • Folding support:
    • Cursor skips over collapsed folds when using 'j' and 'k' (the rest of the motions open the fold)
    • zf{motion} creates a fold for the enclosed text (works also directly in visual mode)
    • zd removes the current fold (not the text, but just the fold markers)
    • zR expands all folds
    • zM collapses all folds
    • zc, zo, za and zA toggle the current fold from open to closed, or viceversa
  • Windowing support:
    • ^Ws splits the current window if it's not already split
    • ^W^W, ^Ww, ^Wj and ^Wk toggle between the two panes of the current file
    • If you issue :q and the current view is a split, the split is removed instead of closing the file
  • Other:
    • Special mark `` (or '') to jump to the last jumped-from position (allows toggling back and forth)
    • '@@' to re-play last played macro
    • Now the result of incremental search (with '/') is shown with selection (except in visual mode)
    • :s[ubstitute] brings up the VS Replace dialog (poor man's :s)
    • :bui[ld], :comp[ile] and :deb[ug] commands
Bugs fixed:
  • Fixed problem in position history which would sometimes require pressing Ctrl-O twice to go back
  • Fixed cursor positioning issue when repeating an 'o' or 'O' command
  • Counts applied to 'o' and 'O' now work properly
  • Much improved multiple-line input repeating with counts, '.', block-visual multi-input and within macros (also TAB)
  • Count given to 'R' command is now honored (it was ignored)
  • Any two-key motion started with 'g' could not be used as an operator (eg, 'dge'). Fixed.
  • Made position-history aware of external file change events (such as Ctrl-Tab or clicking on the solution explorer or error window)
  • Fixed 'r' inserting spurious naked LF's when given RETURN as argument, now it correctly inserts the appropriate terminator
  • Both soft and hard TABs properly implemented in replace mode (for better integration with other tools and Intellisense, done along VS's conventions, not vims)
  • Repeating input wich involved overstrike mode changes during input now works properly
  • Now BACKSPACE and SPACE wrap around end of line, as in vim
  • Fixed position history problems with unnamed files (both "Find results" window and just-created unnamed files)
  • Made ESC in normal mode beep, as in vi/vim
  • "Desired cursor column" is now updated after repeating input, as in vi/vim

ViEmu 1.1 (August 18th, 2005):

Bugs fixed:
  • "Find in Files" would often freeze when reaching a file edited with ViEmu
  • Text input during macro recording was not properly re-input when playing back
  • A '.' command involving line entry in indented lines at end of file did not work well
  • Deleting a character range in the last line moved the cursor to column zero
  • The count in the 's' command applied to the input repetitions, should apply to the # of chars erased
  • '/' without arguments didn't do anything, now it properly repeats the last search forward
  • 'o' or 'O' with a count did not repeat the NewLine operation, only the text input
New features added:
  • ViEmu now intercepts all text editing windows, this provides for better integration in all cases
  • Ctrl-SPACE and Ctrl-Shift-SPACE did not bring up autocompletion/method info in insert mode - now insert mode is quite similar to regular Visual Studio editing and supports these as well as many other shortcuts
  • Mark positions and position history (Ctrl-I/Ctrl-O) are now correctly updated during editing, so they remain tied to the original text where they were set
  • ViEmu now hooks Visual Studio's editor in a way that allows proper compatibility with other editor-enhancement add-ins
  • Added the Ctrl-] command to jump to a symbol's definition
  • 'o' and 'O' now perform correct automatic indentation
  • Added an option to enable/disable ViEmu
  • Ctrl-T/Ctrl-D in insert mode to indent / unindent the current line

ViEmu 1.0 (July 26th, 2005)

First public release.