Nextvi(1)                   General Commands Manual                  Nextvi(1)

NAME
     Nextvi - A small vi/ex terminal text editor

SYNOPSIS
     vi [-aemsv] [file ...]

DESCRIPTION
     Nextvi is a modern clone of the command-line text editor vi(1),
     initially developed by Bill Joy in 1976 for Unix-based systems.
     Nextvi builds upon many standard features from vi(1) including
     a unique modal interface that allows users to switch between normal,
     insert, and command modes for efficient text manipulation.
     Additional enhancements include an unrestricted macro system,
     syntax highlighting, keymaps, bidirectional UTF-8 support, and
     numerous other features. Nextvi remains highly efficient, portable,
     and hackable, ensuring its continued relevance and high quality
     for years to come.

OPTIONS
     -a      Enable alternate terminal screen
     -e      Enter ex mode on startup
     -m      Disable initial file read message
     -s      Enter raw ex mode on startup
     -v      Unset all options

MANPAGE NOTATION
     <x>     A closure where x represents a character literal
     [x]     A closure where x represents optional argument
     {x}     A closure where x represents required argument
     "x"     A closure where x represents a string
     <^X>    Represents a ctrl key X
     < >     Space separates alternatives in a closure
     #       Decimal representation in a closure
     x-y     Range from x to y

VI NORMAL
     [#]j          Move # lines down
     [#]k          Move # lines up
     [#]+
     [#]<^M>
     [#]<Enter>
                   Move # lines down, cursor after indent
     [#]-          Move # lines up, cursor after indent
     [#]h          Move # columns left
     [#]l          Move # columns right
     [#]f{arg}     Move to arg character found forward # times
     [#]F{arg}     Move to arg character found backward # times
     [#]t{arg}     Move until arg character found forward # times
     [#]T{arg}     Move until arg character found backward # times
     [#],          Repeat last <f F t T> move backward # times
     [#];          Repeat last <f F t T> move forward # times
     [#]E          Move to end of word # times, skip punctuation
     [#]e          Move to end of word # times
     [#]B          Move to start of word backward # times, skip punctuation
     [#]b          Move to start of word backward # times
     [#]W          Move to start of word forward # times, skip punctuation
     [#]w          Move to start of word forward # times
     vw            Toggle single-line mode for <E e B b W w Space Backspace>
                   regions
     [#](          Move to next sentence boundary down # times
     [#])          Move to next sentence boundary up # times
     [#]{          Move to next <{> section down # times
     [#]}          Move to next <{> section up # times
     [#][          Move to next <Newline> section down # times
     [#]]          Move to next <Newline> section up # times
     ^             Move to start of line after indent
     0             Move to start of line
     $             Move to end of line
     [#]|          Goto # column
     [#]<Space>    Move # characters forward
     [#]<^H>
     [#]<Backspace>
                   Move # characters backward
     %             Move to closest <] ) } [ ( {> pair
     {#}%          Move to # percent line number
     '{<mark>}     Move to a line mark
     `{<mark>}     Move to a line mark with cursor position
     gg            Goto first line in buffer
     [#]G          Move to last line in buffer or # line
     H             Move to highest line on a screen
     L             Move to lowest line on a screen
     M             Move to middle line on a screen
     z.            Center screen at cursor
     z<^M>
     z<Enter>
                   Center screen at top row
     z-            Center screen at bottom row
     [#]<^E>       Scroll down 1 or # lines, retain # and cursor position
     [#]<^Y>       Scroll up 1 or # lines, retain # and cursor position
     [#]<^D>       Scroll down half a screen size. If [#], set scroll to #
                   lines
     [#]<^U>       Scroll up half a screen size. If [#], set scroll to # lines
     <^B>          Scroll up full screen size
     <^F>          Scroll down full screen size
     #             Show global and relative line numbers
     2#            Toggle show global line numbers permanently
     4#            Toggle show relative line numbers after indent permanently
     8#            Toggle show relative line numbers permanently
     V             Toggle show hidden characters:<Space Tab Newline>
     <^C>          Toggle show line motion numbers for <l h e b E B w W>
     {<1-5>}<^C>   Select line motion number mode 1-5
     <^V>          Loop through line motion number modes
     [#]<^R>       Redo # times
     [#]u          Undo # times
     <^I>
     <Tab>
                   Open file path from cursor to end of line
     <^K>          Write current buffer to file. Force write on 2nd attempt
     [#]<^W>{arg}  Unindent arg region # times
     [#]<{arg}     Indent left arg region # times
     [#]>{arg}     Indent right arg region # times
     [#]"{<arg>}{cmd}
                   Execute normal cmd using register arg. # applies to cmd
     [#]"{<arg>}q  Start recording and set rr ex option to arg register. #
                   keeps register contents
     q             Stop recording and set rr ex option to 0
     R             Print registers and their contents
     [#]&{<arg>}   Execute arg register macro in non-blocking mode # times
     [#]@{<arg>}   Execute arg register macro in blocking mode # times
     [#]@@         Execute last macro # times, blocking
     [#]&&         Execute last macro # times, non-blocking
     [#]@:
     [#]&:
                   Execute <:> register as an ex command # times
     [#].          Repeat last normal command # times. Repeatable commands:
                   x X D C s S Y p P r d c ~ gu gU g~ ! > < <^W> i I a A o O
                   ci di J K
     [#]v.         Repeat last normal command moving down across # lines
     [#]Q          Enter ex mode recursively. # retains current horizontal
                   scroll
     :             Enter ex prompt
     [#]!{arg}     Enter pipe ex prompt based on # or arg region
     vv            Enter ex prompt with the last line from history buffer b-1
     [#]vr         Enter %s/ ex prompt. Insert # words from cursor
     [#]vt[#arg]   Enter .,.+0s/ ex prompt. Insert # of lines from cursor.
                   Insert #arg words from cursor
     [#]v/         Enter re ex prompt to set regex keyword. Insert # words
                   from cursor
     v;            Enter ! ex prompt
     [#]vi         Enter %s/ ex prompt. Contains regex for changing spaces to
                   tabs. # modifies tab width
     [#]vI         Enter %s/ ex prompt. Contains regex for changing tabs to
                   spaces. # modifies tab width
     vo            Remove trailing white spaces and <\r> line endings
     <^G>          Print buffer status info
     1<^G>         Enable permanent status row
     2<^G>         Disable permanent status row
     ga            Print character info
     1ga           Enable permanent character info row
     2ga           Disable permanent character info row
     [#]gw         Hard word wrap a line to # column limit. Default: 80
     [#]gq         Hard word wrap a buffer to # column limit. Default: 80
     [#]g~{arg}    Switch character case for arg region # times
     [#]gu{arg}    Switch arg region to lowercase # times
     [#]gU{arg}    Switch arg region to uppercase # times
     [#]~          Switch character case # times forward
     i             Enter insert mode
     I             Enter insert mode at start of line after indent
     A             Enter insert mode at end of line
     a             Enter insert mode 1 character forward
     o             Create a new line down and enter insert mode
     O             Create a new line up and enter insert mode
     [#]s          Delete # characters and enter insert mode
     [#]S          Delete all across # lines and enter insert mode
     [#]c{arg}     Delete arg region # times and enter insert mode
     C             Delete from cursor to end of line and enter insert mode
     [#]d{arg}     Delete arg region # times
     D             Delete from cursor to end of line
     [#]x          Delete # characters from cursor forward
     [#]X          Delete # characters from cursor backward
     [#]di{<arg>}  Delete inside arg pairs, skip # matches
     [#]ci{<arg>}  Delete inside arg pairs and enter insert mode. Skip #
                   matches
     [#]r{arg}     Replace # characters with arg from cursor forward
     [#]K          Split a line # times
     [#]J          Join # lines
     [#]y{arg}     Yank arg region # times
     [#]Y          Yank # lines
     [#]p          Paste default register below current line or after cursor
                   position # times
     [#]P          Paste default register above current line or before cursor
                   position # times
     m{<mark>}     Set buffer local line mark
     <^T>          Set global line mark 0. Global marks are always valid
     {<0 2 4 6 8>}<^T>
                   Set a global line mark #
     {<1 3 5 7 9>}<^T>
                   Switch to a global line mark #
     [#]<^7>{<0-9>}
     [#]<^_>{<0-9>}
     [#]<^/>{<0-9>}
                   Show buffer list and switch based on # or 0-9 index when
                   prompted
     <^^>
     <^6>
                   Swap to previous buffer
     [#]<^N>       Swap to next buffer, # reverses direction between forward
                   and backward
     \             Swap to /fm/ buffer b-2
     {#}\          Refresh secondary directory listing in b-2
     vb            Recurse into b-1 history buffer. Insert current line into
                   ex prompt on exit
     z1            Set alternative keymap to Farsi keymap
     z2            Set alternative keymap to Russian keymap
     ze            Switch to English keymap
     zf            Switch to alternative keymap
     zL            Set td ex option to 2
     zl            Set td ex option to 1
     zr            Set td ex option to -1
     zR            Set td ex option to -2
     [#]/          Regex search prompt, move down 1 or # matches
     [#]?          Regex search prompt, move up 1 or # matches
     [#]n          Repeat regex search, move 1 or # matches
     [#]N          Repeat regex search, inverted move 1 or # matches
     <^A>          Regex search 1 word from cursor, no center, wraparound move
                   up or down
     *             Regex search, no center, wraparound move up or down
     {#}*
     {#}<^A>       Regex search, set keyword to # words from cursor
     <^]>          Filesystem regex search forward based on directory listing
                   in b-2. Sets global line mark 0 for <^P> fallback
     {#}<^]>       Filesystem regex search forward, set keyword to # words
                   from cursor
     [#]<^P>       Filesystem regex search backward
     <^Z>          Suspend vi
     <^L>          Force redraw whole screen and update terminal dimensions
     [#]Z{<Any>}   Force exit and clean terminal, quit # recursion levels
     [#]Zz         Force exit and submit history command, quit # recursion
                   levels
     ZZ            Exit and write unsaved changes to a file
     <ESC ^C>      Cancel any pending input or command

VI REGIONS
     Regions are vi normal commands that define [h v]range for vi motions.
     Commands described with the word "move" define a region.

     j + <^M> <Enter> - k h l f F t T , ; B E b e W w ( ) { } [ ] ^ 0 $
             <Space> <^H> <Backspace> % ' ` G H L M / ? n N * <^A>

             All regions

VI MOTIONS
     Motions are vi normal commands that run in a [h v]range.
     Commands described with the word "region" consume a region.
     Motions can be prefixed or suffixed by [#].

     <^W> > < ! c d y g~ gu gU
             All motions

     dd yy cc g~~ guu gUU >> << <^W><^W> !!
             Special motions that can use [#] as number of lines

     Examples:
     3d/int  Delete text until 3rd instance of "int" keyword
     3dw     Delete 3 words (prefix [#])
     d3w     Delete 3 words (suffix [#])
     "ayl    Yank a character into <a> register
     "Ayw    Append a word to <a> register

VI/EX INSERT
     <^H>
     <Backspace>
                   Delete a character, reset ex mode when empty
     <^U>          Delete until <^X> mark or all
     <^W>          Delete a word
     <^T>          Increase indent
     <^D>          Decrease indent
     <^]>          Select paste register from 0-9 registers in a loop
     <^\>{<arg>}   Select paste register arg. <^\> selects default register
     <^P>          Paste a register
     <^X>          Mark autocomplete and <^U> starting position. <^X> resets
                   the mark
     <^G>          Index current buffer for autocomplete
     <^Y>          Reset all indexed autocomplete data
     <^R>          Loop through autocomplete options backward
     <^N>          Loop through autocomplete options forward
     <^B>          Print autocomplete options when in vi insert
     <^B>          Recurse into b-1 history buffer when in ex prompt. Insert
                   current line into ex prompt on exit
     <^A>          Loop through lines in a history buffer b-1
     <^Z>          Suspend vi/ex
     <^L>          Redraw screen in vi mode, clean terminal in ex
     <^O>          Switch between vi and ex modes recursively
     <^E>          Switch to English keymap
     <^F>          Switch to alternative keymap
     <^V>{<arg>}   Read a literal character arg
     <^K>{arg}     Read a digraph sequence arg
     <^C>
     <ESC>
                   Exit insert mode in vi, reset in ex
     <^M>
     <Enter>
                   Insert <Newline> in vi, submit command in ex

EX
     Ex is a powerful line editor for Unix systems, initially developed
     by Bill Joy in 1976. This essential tool serves as the backbone
     of vi, enabling it to execute commands, macros and even transform
     into a purely command-line interface (CLI) when desired.

EX PARSING
     Parsing follows the structure:
     [<sep>][prefix][cmd][<pad>][args]
     Ex commands are initiated and separated by <sep>. Fields can
     be padded by <Space> or <Tab>. [prefix] is a field consumed by
     [cmd], which accepts [range] structure characters. Padding inside
     [prefix] structure is collapsed, except within nested blocks.
     There can only be one pad in between [cmd] and [args]. To avoid
     ambiguity in scripts, it is recommended to always use a pad between
     [cmd] and [args].

     Examples:
     :evi.c
             Evaluates to ":e vi.c"
     :efbc
             Evaluates to ":ef bc" not ":e fbc"
     :e  vi.c
             Edit " vi.c". <pad> is required

EX ESCAPES
     Special characters in [args] and [prefix] blocks will become
     regular when escaped with <\>. Escapes are governed by a non-POSIX
     parity rule: escapes directly before a special are halved, an
     odd amount makes the special regular, and escapes anywhere else
     are literal.

     ( ^ ] -
             Specials in regex "[]" expression
     ( ) { + * ? ^ $ [ | \ . \< \>
             Specials in regex
     \ : % !
             Specials in ex

EX EXPANSION
     <%> in [args] expands to current buffer pathname or any buffer
     pathname when followed by a corresponding buffer number.
     %# expands to last swapped buffer pathname.
     %@ expands to register specified.

     Example: make a copy of the current file and edit it
     :!cp % %_:e %_
     Example: insert current buffer pathname
     :&i%
     Example: echo the value of <a> register
     :!echo %@97

     <!> in [args] starts and optionally ends a block containing
     external commands. This block executes and expands to stdout
     and stderr produced.

     Example: substitute "int" with the value of $RANDOM
     :%s/int/!printf "%s" $RANDOM!
     Example: insert output of ls shell command
     :&i!ls
     Example: insert output of ls more efficiently
     :;c!ls!<^V><ESC>

EX RANGES
     Some ex commands can be prefixed with ranges.
     [range] prefix implements vertical and horizontal ranges.
     [vrange] prefix implements vertical range and horizontal position.
     Without [cmd], [vrange] replaces [prefix].

     [% |][, ;][#][. $ ' > <][- + * / %][#num]
             All ranges structure
     {|}{cmd}[|]
             Ex subcommand structure
     {>}[regex][>]
             Search forward structure
     {<}[regex][<]
             Search backward structure
     '{#mark}
             Mark structure

     %       Range from first to last line
     |       Begin ex subcommand block
     ,       Vertical range separator
     ;       Horizontal range separator
     #       Rebase to previous value in range structure
     .       Current position
     $       Last line of a buffer or end of line
     '       Begin mark structure
     >       Begin search forward block
     <       Begin search backward block
     -       Subtract following number
     +       Add following number
     *       Multiply by the following number
     /       Divide by the following number
     %       Modulo by the following number
     #num    Number or position

     Examples:
     :1,5p   Print lines 1,5
     :.-5,.+5p
             Print 5 lines around current position
     :>int>p
             Print first occurrence of "int"
     :<int<p
             Print first occurrence of "int" in reverse
     :.,>int>p
             Print until "int" is found
     :<int<,.p
             Print until "int" is found in reverse
     :>      Search using previously set regex keyword
     :'100,'97p
             Print lines from mark <d> to mark <a>
     :%p     Print all lines in a buffer
     :$p     Print last line in a buffer
     :$*50/100+1
             Goto 50% of the file
     :;50    Goto character offset 50
     :10;50  Goto line 10 character offset 50
     :10;.+5
             Goto line 10 +5 character offset
     :'97;'97
             Goto line mark <a> offset mark <a>
     :;$     Goto end of line
     :5;>int>
             Search for "int" on line 5
     :.;<int<
             Search for "int" in reverse on the current line
     :;5;+10=
             +10 is relative to the initial current offset, not 5
     :;5;#+10=
             +10 is relative to 5
     :;>int>+3;#>>p
             Print text enclosed by "int" on the current line
     :|grp1|;>(a)+>+1|grp|;#>>p
             Print text enclosed by a non-deterministic pattern "a+"

EX COMMANDS
     [range]f>[regex]
     [vrange]f<[regex]
             Ranged search

             No argument uses previously set regex keyword.
             Returns error if target not found.
             If cursor is out of bounds, forward search pins to range start,
             backward search to range end.

             Example: no range given, current line only
             :f>int
             Example: reverse
             :f<int
             Example: range given
             :10,100f>int

     [range]f+[regex]
     [vrange]f-[regex]
             Incrementing ranged search

             Equivalent to the f> and f< commands, except subsequent commands
             advance past match boundary. Cannot match inplace.

     [vrange]f[regex]
             Fuzzy search prompt

             Enters a fuzzy search prompt with a list of matches.
             Matches are prefixed by selection numbers and line numbers.
             Match can be selected using numbers 0-9 if there are less than
             10 matches.
             <^C> or <ESC> to abort.
             <^M> or <Enter> to input a selection number larger than 9.

             No range evaluates to <%> range.
             No range displays a maximum of xrows * 3 matches.

     [vrange]g[<Delim>][regex][<Delim>][cmd]
             Global command

             Execute an ex command on a range of lines that matches an
             enclosed regex.
             Returns error if no line matches the pattern or [cmd] fails.

             No range evaluates to <%> range or <.> range when nested.

             Example: remove all empty lines
             :g/^$/d

             Example: print lines matching previously set regex keyword
             :g//p

             Multiple ex commands can be chained in one global command.
             To chain commands, the ex separator <:> must be escaped once.

             Example: print and append lines matching "int" to register <a>
             :g/int/p\:ya+ 97

             It is possible to nest global commands inside of global commands.
             The first global command will not be executed on lines that
             were changed by a nested global command.

             Example: nested global command
             Append "has a semicolon" to all lines that contain "int" and
             end with <;>.
             :g/int/g/;$/& A has a semicolon

             Example: extract/print data enclosed in "()"
             :grp1:err4:g/./;0\:;>(\().+\)>;#>.+(\))>+1p:err1:grp

     [vrange]g![<Delim>][regex][<Delim>][cmd]
             Inverted global command

     [range]re[regex]
             Set regex keyword

             Range escapes its text and uses it as the regex.

             Example: set keyword to "int"
             :re int
             Example: set keyword from lines 1 to 3
             :1,3re

     [vrange]i[str]
             Enter ex insert mode

             [str] specifies initial input into the insertion buffer.
             [str] in raw ex mode is injected directly and bypasses the
             interactive mode.

             Example: insert "hello" in vi/ex
             :i hello<^M><ESC>
             Example: insert "hello" in vi/ex trimming <Newline>
             :i hello<^M><^M><Backspace>
             Example: discard changes in vi/ex
             :i hello<^M><^C>
             Example: immediately insert "hello"
             :i hello<^V><ESC>
             Example: insert "hello" before specified position
             :-1i hello<^V><ESC>
             Example: insert "hello" before line 1 (special case)
             :0i hello<^V><ESC>
             Example: insert "hello" in raw ex mode
             i hello
             Example: insert two lines in raw ex mode
             i hello<^M>world
             Example: insert "hello" in raw ex mode (interactive)
             i<^M>hello<^M>.<^M>

     [range]c[str]
             Enter ex change mode

             In combination with seq and lim ex options, this command is
             optimal for modifying very long lines.
             Max insertion buffer is ~1.33GB on a 32 bit build.
             Max addressable line is 2.0GB on a 32 bit build.

             Example: replace current line with "hello"
             :c hello<^M><ESC>
             Example: replace lines 1-5 with "hello"
             :1,5c hello<^M><ESC>
             Example: insert "hello" at current character offset
             :;c hello<^M><ESC>
             Example: insert "hello" at end of line
             :;$c hello<^M><ESC>
             Example: insert "hello" at line 5 and end of line
             :5;$c hello<^M><ESC>
             Example: delete 5 characters from current position
             :;;+5c<^M><ESC>

     [range]d
             Delete line(s)

             Example: delete from current position to the start of the buffer
             :1,.;0;d
             Example: delete from current position to the end of the buffer
             :.,$;;$d

     [vrange]j[any]
             Join line(s)

             Range of two or more lines joins exactly those lines.
             Any argument activates padding mode.
             Returns error if there is nothing to join.

             Example: join all lines
             :%j
             Example: join all lines with space padding
             :%j x

     [range]s[<Delim>][regex][<Delim>][str][<Delim>][<g>][<m>][<^>][#reg]
             Substitute

             Find and replace text in a range of lines that matches an
             enclosed regex with an enclosed replacement string.
             Returns error if no substitution is performed.

             Example: range scoping
             :1,5;5;5s/term1/term2/

             Example: replace matching previously set regex keyword
             :%s//term2/

             Substitution backreference in [str] inserts the text of matched
             group specified by \# where # is a group number. Digits are
             consumed greedily up to the highest existing group, rest are
             literal.

             Example: substitution backreference
             this is an example text for subs and has int or void
             :%s/(int)|(void)/pre\0after
             this is an example text for subs and has preintafter or void
             :%s/(int)|(void)/pre\2after/g
             this is an example text for subs and has prepreafterafter or prevoidafter

             Example: global replacement with <g>
             :%s/term1/term2/g

             Example: anchor ^ at every search with <^>, implies <g>
             aaa
             :%s/^a/X/^
             XXX

             Example: multiline mode <m>
             :.,+1s/term1<^V><^M>term2/term3/m

             Example: edit register <a> inplace
             :s/term1/term2/97g

     ud      Undo

             Returns error if there is nothing to undo.

     rd      Redo

             Returns error if there is nothing to redo.

     [range]p[str]
             Print line(s) from a buffer

             No range prints a line based on the value of left ex option.
             Argument prints the evaluated argument.

             Example: utilize character offset ranges
             :1,10;5;5p
             Example: interleaved character offset ranges
             :1;5,10;5p
             Example: print current line from offset 5 to 10
             :.;5;10p
             Example: print buffer pathname
             :p %

     [range]=[<0-3 Any>][any]
             Print range numbers

             Argument 0-3 selects a specific number.
             Any non-<0-3> or extra argument bypasses the buffer range check.
             No argument prints all range numbers.

             Example: print current character offset only
             :;= 2
             Example: print value of mark <a>
             :'97=
             Example: calculate 75 - 100
             :,75-100=1p

     =?[any]
             Print last error

             Any argument forwards the error status.

     [range]m{#marks}
             Set line mark(s)

             Marks are ids separated by spaces, set alternating between start
             and end of the range.

             Example: store ranges in <a> and <s> for later reuse in f> command
             :>top>,#>bottom>m 97 115:'97,'115f>middle

     m![#marks]
             Unset line mark(s)

             No argument unsets all marks in the current buffer.

     [range]ya[#reg]
             Yank into a register

             No argument yanks into default register.

             Example: yank into <a> using ranges
             :1,5;5;5ya 97

     [range]ya+[#reg]
             Yank and append to a register

             Example: append to register <1>
             :ya+ 49

     ya![#reg]
             Free a register

     [range]pu[#reg][any][\!{cmd}]
             Paste or pipe a register

             Example: paste <a> at line 1 character offset 5
             :1;5pu 97
             Example: paste <a> before line 1 (special case)
             :0pu 97
             Example: copy default register to X11 clipboard
             :pu \!xclip -selection clipboard
             Example: copy register <a> to X11 clipboard
             :pu 97 \!xclip -selection clipboard

     [#reg]reg[str]
             Print registers or put into a register

             Prefix selects a register and argument replaces its contents.
             Prefix with no argument reassigns the default register.

             Example: shift the printing position to view offscreen register parts
             :1left:reg
             Example: put "hello" into register <1>
             :49reg hello

     [#reg]reg+[str]
             Print registers or append to a register

     e[path]
             Open a file at a path

             No argument opens "unnamed" buffer.
             Files larger than 2.0GB are truncated on a 32 bit build.
             Line breaking happens until the first nul terminator or EOF.

     e![path]
             Force open a file at a path

             No argument re-reads the current buffer from the filesystem.

     [vrange]ef[regex]
             Open file using fuzzy search prompt

             Requires the b-2 buffer to have a directory listing backfilled.

             Example: backfill b-2 using fd command
             :fd
             Example: backfill b-2 using find
             :b-2:%!find .

             Prompt behavior is equivalent to the f command.

             Example: enter prompt & print entire listing
             :ef
             Example: search for pathname containing "v"
             :ef v

     [vrange]ef![regex]
             Forced version of ef command

     [range]r[path]
     [range]r[\!{cmd}]
             Read a file or a pipe

             Range is computed on a target.
             No range evaluates to <%> range.
             No argument evaluates to current buffer path.

             Example: read a file
             :r vi.c
             Example: pipe in all data
             :r \!ls
             Example: pipe in only lines 3,5
             :3,5r \!ls

     [range]w[path]
     [range]w[\!{cmd}]
             Write a file or a pipe

             No range evaluates to <%> range.
             No argument evaluates to current buffer path.

             Example: write a file
             :w vi.c
             Example: pipe out all data into less
             :w \!less
             Example: pipe out only first 10 lines
             :1,10w \!less

     [range]w![path]
             Force write a file

     [range]wq[path]
     [range]wq[\!{cmd}]
             Write a file or a pipe and exit

     [range]wq![path]
     [range]wq![\!{cmd}]
             Force write a file or a pipe and force quit

     [range]x[path]
             Write unsaved changes and exit

     [range]x![path]
             Force write unsaved changes and force quit

     [#lvl]q[0-255]
             Exit

             Prefix exits [#lvl] ex recursion levels.
             Argument specifies shell exit code.

             Example: conditionally exit this level and 1 above
             :%f>marker:??!p no marker\:1q:s/old/new/g:w

     [#lvl]q![0-255]
             Force quit

             Prefix force quits [#lvl] recursion levels.
             No prefix quits all recursion levels.

             Example: set register <#0> to "hello" 3 levels deep, force quit
             this level and 2 above, print the register outside
             :&Q&Q\\\:&Q0reg hello\\\\\\\:2q\\\\\\\!:p %@0

     b[#index]
             Print buffers or switch to a buffer

             Temporary buffers are separate from the main buffers
             and are selected by a negative index.

             Example: switch to the 5th buffer
             :b5
             Example: switch to the /hist/ ex history buffer
             :b-1
             Example: switch to the /fm/ directory listing buffer
             :b-2
             Example: switch to the /sc/ scratch buffer
             :b-3
             Example: clear history and return to previous (#) main buffer
             :b-1:%d:b-1

     bp[path]
             Set current buffer path

     bs[any]
             Set current buffer saved

             Argument resets undo/redo history

     bx[#]   Set max number of buffers allowed

             Buffers will be deallocated if the number specified is lower
             than the number of buffers currently in use.
             No argument resets to the default value of 10.

     cd[path]
             Set a working directory

             No argument relinks the current directory in case it got removed
             or unmounted.

             Currently open buffers' file paths will be automatically adjusted
             to reflect a newly set working directory.

     fp[path]
             Clear or set a secondary directory path

     fd[path]
             Calculate directory listing in b-2 buffer

             No argument uses secondary or a working directory path.

     inc[regex]
             Include regex for fd command calculation

             No argument disables the filter.

             Example: include only files in submodule directory that end with .c
             :inc submodule.*\.c$
             Example: exclude .git and submodule folders
             :inc (^(?\:(?\!^\.git|^submodule).)+[^/]+$)

     [range]![cmd]
             Run an external program

             When a range is specified, the buffer's data is piped to an external
             program. The resulting stdout and stderr are then piped back into the
             buffer, replacing the contents of the original range.
             No range returns an error if shell exit code is not zero.

             Example: infamously sort a buffer
             :%!sort
             Example: replace "int" with "uint" using sed
             :%!sed -e 's/int/uint/g'
             Example: pipe in result of ls command without line replacement
             :;$+1!ls
             Example: capitalize word at current position using tr
             :;;>\\\>>!tr '[\:lower\:]' '[\:upper\:]'

     &{macro}
             Global non-blocking macro

             Execute raw vi input sequence.
             A non-blocking macro shall not wait for input when the end of
             the sequence is reached. A non-blocking macro executing other
             macros will always reach a terminating point.

             Example: execute vi insert statement
             :& ihello
             Example: execute :hello
             :& \:hello<^V><^M>
             Example: execute vi "ci(int" macro
             :& ci(int
             Example: nest blocking macro inside non-blocking
             :& \:@ \\\:blocking<^V><^M>i continue in non-blocking
             Example: enable permanent vi line numbers
             :& 2#

     @{macro}
             Global blocking macro

             Execute raw vi input sequence.
             A blocking macro shall wait for input when the end of the sequence
             is reached. A blocking macro executing other macros may cause
             input congestion.

             Example: execute vi insert statement
             :@ ihello
             Example: insert "hello" into <:> vi prompt
             :@ \:hello
             Example: execute vi "ci(int" macro
             :@ ci(int
             Example: execute "ci(int" exiting insert mode
             :@ ci(int<^V><^C>
             Example: execute "ci)INT" as a follow-up
             :@ ci(int<^V><^C>ci)INT
             Example: execute vi "dw" command after user exits insert
             :@i:@dw

     [#count <$>]?[cond]
             While loop

             Repeat [cond] [#count] times or infinite with [<$>].
             While loop is broken once [cond] returns an error or count exceeded.
             Error status of [cond] is forwarded.
             No prefix defaults [#count] to 1.

             Example: attempt to join every line in file using arbitrary count
             :10000? & J
             Example: undo everything
             :$? ud
             Example: repeat chain of ex commands 10 times
             :10? 1p\:5p\:10p

     [#count <$>]?![cond]
             Inverted while loop

     [prefix]??[then]
     {prefix}??
             Conditional

             Branching depends on the error status of the last command.
             Error status of [then] is forwarded.
             No prefix and no argument forwards the last error status.

             A prefix without arguments captures the current error status
             at that point in a command chain into capture id specified.
             Capture ids are global across all nested command contexts.

             A prefix with arguments branches based on the boolean expression
             in DNF over the most recent captures of each referenced id.
             If id has no capture, the branch is skipped.

             Prefix operators:
             Numerical capture id
             , AND (higher precedence)
             ; OR (lower precedence)

             Example: calculate directory only if cd command succeeded
             :cd /blah:?? fd
             Example: print a line only if it contains "int" at offset 5
             :;5;#>^int>:?? p
             Example: edit vi.c only if it exists
             :![ -f ./vi.c ]:??e ./vi.c:mpt1
             Example: capture error status at id 5, branch later
             :>int>:5??:;=:5??p
             Example: skip if id was never set
             :2??.=
             Example: AND -- branch only if both ids captured success
             :f>int:1??:f>void:2??:1,2??p found both
             Example: OR -- branch if either id captured success
             :f>int:1??:f>void:2??:1;2??p found one
             Example: DNF -- (1 AND 2) OR (3 AND 4)
             :1,2;3,4??p then

     [prefix]??![then]
     {prefix}??!
             Inverted conditional

             Example: inverted capture
             :f>int:1??!:1??p int was absent

     {prefix}???
             Evaluate capture ids

             This is a nop command that evaluates a boolean expression
             at prefix and returns the result.

             Example: control while loop
             :$? \%f+int\:1??\:\%f+void\:2??\:1,2??p\:1,2???

     [#id]?~[any]
             Control capture ids lifetime

             Prefix selects a specific id to free.
             No argument and no prefix frees all captured error statuses.
             Argument toggles capture status preservation across
             separate ex command chains.

             Example: id 2 capture leaks into unrelated code
             :f>int:2??:f>zzz:1??:1??f>int\:2??:2??p LEAKED
             Example: prevent id 2 leak
             :f>int:2??:2?~:f>zzz:1??:1??f>int\:2??:2??p LEAKED

             Example: use a capture at the next <:> prompt
             :?~x:![ -f ./vi.c ]:1??
             :1??p vi.c exists

     ft[filetype]
             Set a filetype

             No argument prints the current file type.
             Reloads the highlight ft, which makes it possible to reset dynamic
             highlights created by options like "hlw".

     cm[keymap]
             Set a keymap

             No argument prints the current keymap name.

     cm![keymap]
             Set an alternative keymap

     ac[regex]
             Set autocomplete filter regex

             No argument resets to the default word filter regex as defined
             in led.c.

             Example: autocomplete using whole lines from a buffer
             :ac .+

     [<0-3>]sc[<esc>][<sep>][<exp>][<exe>]
             Set ex special characters

             Prefix selects a specific character to change.
             Missing arguments default to <\ : % !>.

             Example: change <%> to <a>
             :2sc a
             Example: utilize newly set separator in a single command chain
             :|1sc a|: p cmd1 a p cmd2 a|sc|a0?:p cmd3

     [<0-3>]sc![<esc>][<sep>][<exp>][<exe>]
             Set ex special characters

             Missing arguments default to <#0>.

             Example: disable <exp> and <exe>
             :sc! \\\:

     uc      Toggle multi-byte UTF-8 decoding

             This command is particularly useful when editing files with
             mixed encodings, binary files, or when the terminal does not
             support UTF-8 or lacks the necessary fonts to display UTF-8
             characters. It is often paired with ph command to achieve
             hex editor-like functionality.

     uz      Toggle zero-width character placeholders

             Hides zero-width characters rather than rendering them as placeholders.

     ub      Toggle multi-codepoint sequence placeholders

             Passes multi-codepoint sequences such as emojis to the terminal
             for native rendering rather than substituting placeholders.

     ph[#clow] [#chigh] [#width] [#blen][<Space>][str]
             Redefine placeholders

             This command replaces placeholders defined in conf.c
             and subsequent ph commands expand the list of placeholders.

             Example: render 8 bit ascii (Extended ASCII) as <~>
             :ph 128 255 1 1~
             Example: flawless ISO/IEC 8859-1 (latin-1) support
             :uc:ph 128 160 1 1~
             Example: render control byte 03 as "^C"
             :ph 3 3 2 1^C
             Example: reset to default as in conf.c
             :ph
             Example: disable default placeholders in conf.c
             :ph:ph0

EX OPTIONS
     Ex options are ex commands designed to alter global variables.
     Variables hold a signed integer. Argument sets the value. A non-numeric
     argument yields its first byte. No argument logically inverts
     the current value, unless stated otherwise.

     Argument notation shows the default value.

     ai[1]   Indent new lines

             This is a max indent length multiplier: value * 128

     ic[1]   Ignore case in regular expressions

     ish[0]  Interactive shell

             Run every <!> command through an interactive shell.
             The shell will source the .rc file before command execution.
             This makes it possible to use predefined functions, aliases
             and ENV variables from the .rc file.
             Precondition 1:
                     .rc refers to a shell-specific filename, such as .bashrc
                     in Bash or .zshrc in Zsh.
             Precondition 2:
                     The environment variable $SHELL determines the default
                     shell, otherwise it defaults to /bin/sh.
             Precondition 3:
                     There must be no stdout or stderr output created by .rc
                     file for <!> commands to return expected results.

     grp[0]  Regex search group

             Defines a target search group for any regex search operation.
             This becomes necessary when the result of a regex search is to
             be based on some group rather than the default match group.

             Example: position on a character prefixed by "int"
             :grp 1:%f+int(.):grp

     hl[1]   Highlight text based on rules defined in conf.c

             Value greater than 1 highlights using C extensions only.

     hlr[0]  Highlight text in reverse direction
     hll[0]  Highlight current line based on filetype hl
     hlp[0]  Highlight "[]" "()" "{}" pairs based on filetype hl
     hlw[0]  Highlight current word based on filetype hl
     led[1]  Enable all terminal output

     vis[0]  Control startup flags

             bit 1: raw ex mode
             bit 2: ex mode
             bit 3: disable e command message
             bit 4: alternate terminal screen

             Example: enable raw ex mode
             :vis 3
             Example: disable raw ex mode
             :vis 2

     mpt[0]  Control vi prompts

             When set to 0 or 1 after an ex command is called from vi, disables
             the "[any key to continue]" prompt.
             If mpt is negative, the prompt will remain disabled.

             Example: disable the prompt and the last print
             :p:p:p:mpt 0
             Example: disable the prompt but not the last print
             :p:p:p:mpt 1

     order[1]
             Reorder characters based on rules defined in conf.c
     shape[1]
             Perform Arabic script letter shaping
     pac[0]  Print autocomplete suggestions on the fly
     ts[8]   Number of spaces used to represent a tab
     td[1]   Current text direction context

             value  2: exclusively left-to-right
             value  1: follow dctxs[] in conf.c, default left-to-right
             value -1: follow dctxs[] in conf.c, default right-to-left
             value -2: exclusively right-to-left

     pr[0]   Print register

             Set a special register with a character or a number.
             Once the register is set, all ex printed output will
             be stored in the register.

             If the register is uppercase, <Newline> characters are added
             to match the exact output that was printed.

             Print register contents cannot be displayed with R or reg command
             when register is assigned (self-referential problem).

             Example: paste current buffer list exactly like from b command
             :pr A:ya! 65: b:pu 65
             Example: store a line printed with p command
             :pr A:ya! 65:p

     fr[0]   Find register

             Set a register with a character or a number.
             Once the register is set, the f> and f+ commands perform a
             multi-line search forward on the contents of the register instead
             of the current buffer. Range maps the match to a position in
             the current buffer. No range tests the match inplace.

             Example: search register <a> for "int"
             :fr a:f>int:??p yes:??!p no:fr
             Example: search for "int" followed by "void" on next line
             :%ya97:fr 97:%f>int.void:fr

     rr[0]   Record register

             Set a register with a character or a number.
             Once the register is set, every byte read from the terminal is
             appended to the register. Input replayed from registers is not
             recorded.

             Example: record keystrokes into register <a>
             :rr a
             Example: stop recording
             :rr
             Example: replay recording from register <a>
             :& %@97

     lim[-1]
             Line length render limit

             Set render cutoff length for non cursor lines in vi and all
             lines in ex mode.

             Improves redraw performance when editing a file containing one
             or many long lines (1MB+ per line).

             Example: reasonable value
             :lim 5000
             Example: render only the cursor line
             :lim 0
             Example: disable the limit
             :lim -1

     seq[1]  Control Undo/Redo

             When seq is 0, multiple distinct operations undo/redo in a
             single step.

             To optimize memory usage under heavy workloads, undo/redo
             tracking can be disabled by setting seq to a negative value.

             Example: test undo/redo operations in a single step
             :&ocontrol test:seq 0:&a step1:&a step2:&a step3:seq
             Example: completely disable undo/redo
             :seq -1

     [hscroll]left[0]
             Control horizontal scroll

             No argument calculates the value using current character offset.
             hscroll computes the value using: xcols / 2 * hscroll

     err[1]  Control ex errors

             bit 1: print errors
             bit 2: early return
             bit 3: ignore errors

             Example: silence and ignore errors
             :err 4
             Example: report and return on first error
             :err 3
             Example: report and consider only last command for error status
             :err 1

EXINIT ENV VAR
     EXINIT defines a chain of ex commands to be performed at startup,
     executed once after all files are opened. This is the only way
     for scripting and customizing Nextvi outside of C or Unix pipes.
     Many standard text processing utils such as grep, awk, sed can
     be replaced by Nextvi with EXINIT in mind.

     printf with octal escapes is the standard way to embed control
     characters into EXINIT.

     Examples:

     export EXINIT='td 2:order 0:lim 5000'
             Set ex options for optimal long line performance

     export EXINIT='b-1:r ./vi.c:b-1'
             Load vi.c into a history buffer

     export EXINIT="$(printf 'e ./vi.c:& i\007\003:bx 1:bx')"
             Index vi.c for autocomplete

     export EXINIT="$(printf '97reg o{\n}\003kA\n\t')"
             Setup @ macro in register <a>

             @a macro creates <{> and closing <}> below the cursor leaving
             cursor in insert mode in between the braces.

     export EXINIT='98reg \:mpt-1\:;;$w \\\!xclip -selection clipboard\:mpt'
             Setup @ macro in register <b>

             @b macro pipes the current line into X11 clipboard.

     export EXINIT='rr z:vis 2:&Q:b-3:pu 122:wq! bugreport.txt'
             Capture session for a bug report

             Recording starts into register <z>. Setting vis 2 makes <Q>
             toggle straight into a regular vi session where the user takes
             over.  Quitting it with q command resumes the macro, which writes
             the recording to bugreport.txt.

REGEX
     Pikevm is a fast non-backtracking NFA simulation regex engine
     developed for Nextvi. It ensures regular expressions are evaluated
     in constant space and O(n * k) time complexity where <n> is
     the input string length and <k> represents the regex's structural
     complexity (e.g., state transitions or alternations). While
     this does not guarantee strict O(n) linear runtime performance,
     it ensures computational and memory resources are distributed
     linearly and evenly across the input, with <k> directly influencing
     the constant factor. This principle is similar to the concept
     utilized in radix sort algorithms.

     Pikevm's syntax is akin to regexp(7) from Plan 9.
     Disregard manpage notation in this section.

     .       Match any single character
     [N-M]   Match a set of alternate ranges N to M
     {N,M}   Match N to M times
     ()      Capture grouping
     (?:)    Non capture grouping
     *       Repeated zero or more times
     +       Repeated one or more times
     |       Union, alternative branch
     ?       One or zero matches greedy
     ??      One or zero matches lazy
     ^       Assert start of line
     $       Assert end of line
     \<      Assert start of word
     \>      Assert end of word
     (?=)    Assert positive lookahead
     (?!)    Assert negative lookahead
     (?>)    Assert positive lookbehind
     (?<)    Assert negative lookbehind
     (?#)    Lookbehind offset in bytes

     Lookaround expressions enable the creation of regular expressions
     that would be impossible to construct without them. They can
     be used anywhere within a regex, though some considerations
     must be taken into account.
     Aspect 1:
             Lookarounds contain a full regular expression.
     Aspect 2:
             Lookarounds can have nested lookarounds.
     Aspect 3:
             Static lookarounds like (?=^word) are optimized, bypassing
             the regex engine.
     Aspect 4:
             Lookarounds are best suited for asserting near the end of a
             complex pattern, where the engine has already narrowed down
             potential matches.
     Aspect 5:
             Lookbehind without offset or 0 offset begins at previous character.
             Offset begins scanning from current position minus specified
             value. Negative offset begins at the start of the string.

SPECIAL MARKS
     *       Position of previous ex command chain
     [       First position of previous change
     ]       Last position of previous change
     '       Position of previous line region
     `       Position of previous line region

SPECIAL REGISTERS
     /       Previous regex keyword
     :       Previous ex command
     <#0>    Default register
     <0>     Previous value of default register (atomic)
             Atomic means the operation did not include a <Newline>.
     <1-9>   Previous value(s) of default register (nonatomic)

CODE MAP
     +------------------+----------------------+
     | 537 kmap.h       |  keymap translation  |
     | 622 vi.h         |  definitions/aux     |
     +------------------+----------------------+
     | 352 term.c       |  low level IO        |
     | 379 conf.c       |  hl/ft/td config     |
     | 462 ren.c        |  positioning/syntax  |
     | 620 uc.c         |  UTF-8 support       |
     | 674 lbuf.c       |  file/line buffer    |
     | 774 regex.c      |  pikevm              |
     | 805 led.c        |  insert mode/output  |
     | 1862 vi.c        |  normal mode/general |
     | 2003 ex.c        |  ex options/commands |
     | 7199 patch2vi.c  |  patch converter     |
     | 15130 total      |  wc -l *.c|sort      |
     +------------------+----------------------+

COMPILING
     export CC='g++ -x c'
             Set compiler, g++ example
     export CFLAGS='-s'
             Set CFLAGS, strip example
     ./cbuild.sh
             Build once
     ./cbuild.sh build
             Build
     ./cbuild.sh debug
             Build with symbols, static analysis, dynamic analysis, and no
             optimizations
     ./cbuild.sh pgobuild
             PGO build can lead to a significant performance boost on some
             application specific tasks
     ./cbuild.sh install
             Install vi to $DESTDIR$PREFIX/bin
     ./cbuild.sh fetch
             Merge commits from upstream repository
     ./cbuild.sh bench
             Performance bench test 2000 word deletions on vi.c

PHILOSOPHY
     Most text editors accumulate significant technical debt. They
     cannot be quickly mastered, deeply understood, or easily changed.
     Nextvi is designed around three pillars: fundamental, lean, and
     flexible. Fundamental means a complete yet minimal command set
     for unlimited text transformation. Lean means a concise, efficient,
     coherent implementation with a bus factor of zero. Flexible means
     deep composability and a versatile, extensible C codebase. By
     conventional wisdom, these three pillars would be considered
     oxymoronic. Maintaining all three challenges the notion that
     a text editor must sacrifice one for another. Nextvi proves that
     coexistence is not only possible but essential to what a great
     text editor should be.

     "All software sucks, but some do more than others."
             - Kyryl Melekhin

SEE ALSO
     New functionality can be obtained through optional patches provided
     in the patches branch. If you have a meaningful contribution
     and would love to make it public, the patch can be submitted
     via email or GitHub pull request.
     https://github.com/kyx0r/nextvi/tree/patches

     Patch2vi support utility
     https://github.com/kyx0r/nextvi/tree/patch2vi

     Unit tests
     https://github.com/kyx0r/nextvi/tree/test

     Scripts used to generate this manual
     https://github.com/kyx0r/nextvi/tree/manual

     Unified tagged releases
     https://github.com/kyx0r/nextvi/tree/release

     Original Neatvi repository
     https://github.com/aligrudi/neatvi

     Posix vi(1)
     https://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html

     Posix ex(1)
     https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html

     NFA regular expressions by Russ Cox
     https://swtch.com/~rsc/regexp/regexp1.html

     Plan 9 regexp(7)
     https://man.cat-v.org/p9p/7/regexp

AUTHORS
     Nextvi was written by Kyryl Melekhin <k.melekhin@gmail.com>.  It is based
     on neatvi(1), which was written by Ali Gholami Rudi <ali@rudi.ir>.  This
     manual page was inspired by nepeta <nepeta@canaglie.net>.

Nextvi 7.8                    September 28, 2026                    Nextvi 7.8

NEXTVI PATCHES
==============
Nextvi features a robust, context-aware and customizable patching system.
The patch2vi support program facilitates script transformations.

Apply one: ./name.sh
Apply a stack: ./lsp.sh visual.sh splits.sh
Each script applies itself, adds its name to $P2VI_PATCH and hands the
rest of the chain on, which lets a patch carrying a compat block for
another see it.
If the scripts did not run as a chain, assert the applied set:
P2VI_PATCH="lsp.sh visual.sh" ./splits.sh
Every line below is one full chain, in an order that applies.
Patches not listed are unconstrained. Combinations are generated
by compat_order in patch2vi.sh.

./grep.sh lsp.sh rstr.sh visual.sh splits.sh cxref.sh
./lsp.sh rstr.sh visual.sh splits.sh incsearch.sh detect_indent.sh
./lsp.sh rstr.sh visual.sh splits.sh incsearch.sh
./lsp.sh threaded_redraw.sh visual.sh splits.sh linewrap_v2.sh
./lsp.sh threaded_redraw.sh visual.sh splits.sh linewrap_v2.sh mouse_normal.sh
./lsp.sh visual.sh nvi_status.sh
./lsp.sh visual.sh splits.sh
./lsp.sh rstr.sh visual.sh splits.sh arrowkeys_insert.sh incsearch.sh detect_indent.sh tab_complete.sh
./rstr.sh threaded_search.sh
./lsp.sh visual.sh

patch2vi.sh
--------------
Maintainer utils.

64bit.sh
--------------
Converts the entire codebase to 64 bit integers instead of 32 bit.
This enables Nextvi to read files and buffers up to 9,223,372 terabytes.
In addition, this may improve performance on 64 bit CPUs due to
matching pointer <---> integer alignment and possibly more compiler
optimizations.
Run this after you've applied the patches.

gen-widechars.sh
--------------
A script I use to update zwchars and dwchars in uc.c

arrowkeys_normal.sh
--------------
Adds arrow key support in normal mode.

arrowkeys_insert.sh
--------------
Adds arrow key support in insert and command modes. In command
mode, Up/Down arrows select lines from the history buffer.

threaded_search.sh
--------------
Multithreaded version of lbuf_search(). Adjust the number of threads in use
and buffer stepping in lbuf.c. Ensure that your system supports POSIX threads,
aka libpthread.

async.sh
--------------
Adds 2 new ex commands "as" and "as!". An ex command in the command chain
after "as" runs on a separate thread. "as!" is a join command that waits
for all threads to finish. POSIX thread support is required. The patch is
intended for expert users because races are possible depending on the
commands used.
Example: run the :fd command without blocking the editor
:as:fd

threaded_redraw.sh
--------------
Moves the main redraw onto a separate thread. This frees up the input thread
and reduces the input latency. No editor state is ever shared because the
frame is joined before the next command runs. POSIX thread support is required.

hl_part.sh
--------------
Allows syntax highlighting to continue past the terminal dimensions up to
a certain limit. To customize the depth, adjust the LEDFORW and LEDBACK
definitions in led.c.
Alters the meaning of the <^> and <$> assertions in syntax highlighting
regex, as the line is considered to start/end beyond the visible columns.
Works in the reverse direction and with reordered text.

hl_naive.sh
--------------
Allow syntax highlight to continue past the terminal dimensions unlimited.
Performance will degrade on very long lines.

blockhl_cache.sh
--------------
Cache multiline syntax highlighting blocks. Falls outside the scope
of core Nextvi as it violates the immediate mode rendering principle and
is more complex.

debug.sh
--------------
Frees reachable memory upon termination.
Use for debugging.
Note: in some features leaks won't be freed - for example hlw (which is not
enabled by default). Also initializes sdense in regex.c so that valgrind
stops freaking out.

grep.sh
--------------
Adds a special temporary buffer /grep/ much like the default /hist/ or /fm/.
When the new ^x keybind is executed, vi performs fs_search on every file and
stores the results in the /grep/ buffer. Finally, the user is switched to
/grep/. Line information is stored and displayed with new syntax highlighting
rules. The searched keyword is also highlighted. Use the familiar keybind
^i or TAB on the wanted line to immediately open the file and go to the
line specified. To quickly open /grep/ use the new keybind: vx
The format of the stored lines is specifically designed to mirror the output
of grep -r -n "str" .
The feature can be substituted with a pipe command in case of a higher
performing grep implementation or loading of cached results from a script.

cxref.sh
--------------
Adds a special temporary buffer /xref/ and the keybind gx, for C only.
gx collects the definition of the symbol under the cursor and, recursively,
the definitions of everything it calls, then switches to /xref/. A count
limits how deep it goes: 1gx is the definition alone, 2gx adds what it
calls, no count means unlimited. To quickly open /xref/ use the new keybind:
vf
Every definition gets a header line in grep -n style, followed by its
code verbatim, highlighted as C. TAB on a header opens that file at that
line, which is where you edit: /xref/ itself is only for reading.
Definitions are looked up in the C files :fd lists.

rstr.sh
--------------
Adaptation from upstream Neatvi, where simple operations are optimized by
running a specialized search routine instead of the full regex engine. rstr
can yield up to 30% faster search on non-regex patterns. Not included in
base Nextvi due to the underlying complexity.

incsearch.sh
--------------
Search as you go in the / and ? prompts. Every typed key redraws the screen
with the matches of the keyword highlighted and the cursor moved to the first
match, scrolling the buffer when the match is off screen. Enter keeps
that position and searches normally, leaving counts and messages
unchanged. An interrupt, or an erase key on an already empty keyword, restores
the view, the previous keyword and the search direction. While in the prompt
TAB moves to the next match and ^_ moves in reverse.

stdin_pipe.sh
--------------
Lets you use vi like a pager (less), except you need to specify - as a
command line argument (just like in vim).
Example:
$ dmesg | vi -

ec_closebuf.sh
--------------
Allows the user to close a buffer using the new ex command "cx".
Specify a number as an argument to select which buffer to close; with no
argument, the current buffer is closed.
Modified buffers require "cx!" to discard their edits and undo history.
The whole range is checked before any buffer is closed; at least one must remain.
When a buffer is closed, all buffers above it are shifted and renumbered.
A range can be supplied like so: :cx0-5
This closes buffers 0 to 5 inclusive.
Omitting a parameter of the range assumes the current buffer index for
that parameter (the range is then not inclusive on that side).
Example: :cx-5 or :cx5-

filetype_shebang.sh
--------------
Detect and set the corresponding filetype based on the shebang
or specific data in the file. Currently supports only shell
and python.

kbd_layout.sh
--------------
Changes hjkl to work well with other keyboard layouts.
In this example hjkl is changed to yneo (workman keyboard layout)
Note: this patch can be used as a base for remapping any base keybinds.

quickexit.sh
--------------
Added kj sequence to quickly exit insert mode.
There is one caveat: if input comes too fast, for example a paste from the
terminal, and the sequence has "kj" in it, insert mode is canceled
mid-way and the paste is wrong. Luckily this almost never happens, as such
letter combinations are extremely rare.
The delay time (in ms) can be set via :qe N or disabled by setting N to 0.

hl_mark.sh
-------------
Adds a new ex option "hlm" which highlights lbuf marks. Each mark has its
own color, up to 16; higher marks may duplicate the colors.
Lazy redraw, use <^L> if needed.

c_option.sh
-------------
Adds the -c command line option. This can be used to pass in ex commands instead
of EXINIT.

exrc.sh
-------------
Adds support for reading the .exrc file from the XDG, .config or home directories.
This can be used to pass in ex commands instead of EXINIT.

readonly.sh
-------------
Adds a new ex option "ro" and the read-only -R command line option

remove_vla_cliterals.sh
--------------
Removes variable length arrays and compound literals for portability reasons.

undojump.sh
--------------
Adds a new keybind ^o which allows jumping through the undo marks
without actually undoing.

undo_branches.sh
--------------
Adds a basic multi-level undo implementation. New ex command "up"
prints divergent changes. Each path has an index; switch to it
with "up" and a number as an argument. Example: :up1
The current undo branch is stored as the last index before swapping.

alternate-w-behaviour.sh
--------------
Implements more vim-like d/c/yw

ac_context.sh
--------------
Improvements to autocomplete: the word completion now also uses
text that prefixes the insert when it makes sense. This makes it
possible to autocomplete in more situations.

tab_complete.sh
--------------
Adds path completion to the ex prompt, bound to TAB. The word before
the cursor is completed as a path, relative to the working directory
or to the directory that the word itself names. A single match is
filled in, with a trailing </> when it is a directory. Several matches
fill in their common prefix, and once nothing is left to fill in, they
are listed. With "tc" set to 1 the prompt never scrolls: the list is
drawn next to the prompt and the cursor stays where it was. With "tc"
set to 2 the screen is cleared and the list is drawn below the prompt
instead, wrapped at word boundaries; TAB then pages it and any other
key leaves it. New keybind ^_ completes like "tc" set to 2 whatever
"tc" is, keeping the full listing always one key away.
When nothing matches, TAB inserts a literal tab.
Adds a new ex option "tc" to control the completion, on by default.
Example: turn it off, TAB is then always a literal tab
:tc 0

linewrap_v1.sh
--------------
Soft line wrap implementation using a buffer only approach.
Adds a new :lw command which can be used to specify the maximum column
at which soft linewrap lines break. Given no argument the column is
elastic: it tracks the terminal width and the buffer is re-wrapped
on every resize, as soon as it holds no unsaved changes.
Adds a new ex option "hllw" to highlight linewrapped boundaries.
Trades off flexibility for simplicity. Cannot change linewrapping
while the buffer is modified. Different edit semantics: visual edits
are line based.

linewrap_v2.sh
--------------
Soft line wrap implementation using a render only approach.
Adds a new :lw command which can be used to specify the maximum column
at which soft linewrap lines break. Given no argument it toggles an
elastic column, which follows the terminal across resizes, or the
window it is drawn in with splits.sh.
Adds a new ex option "hllw" to highlight linewrapped boundaries.
No limitation from v1. Default edit semantics. Visual edits are
geometry based.

ex-scripting.sh
--------------
Adds new ex commands "sr" and "sx".
NEXTVI_FT - current buffer filetype
NEXTVI_ROW - current line number
NEXTVI_OFF - current byte offset
NEXTVI_COFF - current character offset
NEXTVI_LINE - current line
NEXTVI_WORD - current word
"sr" runs a command with the environment variables above
"sx" runs a command with the environment variables above and
executes its stdout as ex commands

ex_marks.sh
--------------
Lets an ex command range address a letter mark.
Example:
:'a,'bs/foo/bar

chunked_read_write.sh
--------------
Reduces the upper memory requirement for reading files. By default vi
reads the whole file into the buffer and then splits it into lines; with
this patch the file is read in 4k chunks and split into lines as it
loads. This helps a lot when reading binary files: the whole file no
longer has to be loaded into memory just to find out that it should
be truncated.
In addition, it reduces the number of write syscalls by using chunks
when writing a file.

visual.sh
--------------
Adds character-wise (gv), line-wise (gV), and block (gb) visual selection
modes. Move the cursor to extend the selection; the selected region is
highlighted with inverted colors. Press the same key again to exit
that mode; ESC also cancels the selection.
The current mode (-- VISUAL --, -- VISUAL LINE --, -- VISUAL BLOCK --)
appears in the ^g status bar; when the permanent status bar is enabled
it shows continuously alongside the file information.
Supported operators applied to the selection:
  y  yank          d  delete         c/C/S  change
  >  indent        <  dedent         !  pipe through shell command
  ~  toggle case   u  lowercase      U  uppercase
  :  enter ex prompt with a scoped range
Block mode (gb) also supports:
  I  insert at the left edge of the block on every selected line;
     lines shorter than the left edge are skipped
  A  append after the right edge of the block on every selected line;
     for lines shorter than the right edge, text is appended at EOL

splits.sh
--------------
Implements "sp" and "vs" ex commands for horizontal and vertical splits.
Adds the vc and vd normal commands to switch and close views. A view can
also be closed with "q".
The new ex command "eq" can be used to balance the vertical and horizontal
split space in the nearest dimension.

alt_sections.sh
--------------
Implements section keybindings closer to standard vi(1):
[#])          Move to next sentence boundary down # times
[#](          Move to next sentence boundary up # times
[#]]          Move to next <{> section down # times
[#][          Move to next <{> section up # times
[#]}          Move to next <Newline> section down # times
[#]{          Move to next <Newline> section up # times

key_remap_cmds.sh
--------------
Adds "im", "im!", "nm" and "nm!" ex commands to dynamically remap keybinds
in normal and insert modes.
Remapping a to hello in insert mode
:im ahello
Remapping a to i in normal mode
:nm ai

modal.sh
--------------
Integrates modal programming language interpreter.
https://wiki.xxiivv.com/site/modal.html
The new ex command [vrange]md[script] evaluates the contents of the
current buffer and the argument as a modal script.
Adds a new phase, ($ ...), to execute ex command chains
from within the modal script.

agent.sh
--------------
Turns Nextvi into an AI agent harness that uses ex commands to inspect
and edit buffers and run shell commands. Requires curl and a model with
tool calling support. Configure api_key, endpoint and request_extra in
conf.c, then rebuild. The default is a local Chat Completions server on
port 8080. For OpenRouter, set LOCAL to 0 and OPENROUTER to 1, then supply
the API key and model ID. request_timeout and max_tool_rounds limit requests
and tool execution.

The new ex command "a" opens or resumes the conversation; a range includes
that buffer text in the prompt. ESC submits a prompt or, while the agent is
working, stops it and returns to the agent prompt. Enter adds a newline.
^C cancels and exits the conversation; ^O enters the editor, suspending
the agent. "a!" clears the conversation; "a~" restarts from the edited
conversation.

The new ex command "exspec" prints ex command specifications.
The new ex option "aspec" forces agent to read specifications before
executing new commands.

New "ar" ex option toggles display and logging of returned reasoning.
It defaults to off (xar in conf.c). Reasoning appears before the answer
after each response completes, if the server supplies reasoning_content
or reasoning text.

The new ex command "ast" shows model state, context and settings.
The new ex command "apack" to compact the conversation using current agent 
context.
The new ex command "apack!" to compact the conversation by starting a
fresh agent.
The new ex command "acm" activates caveman mode skill.
The new ex option "aco" automatically uses "apack" command once a certain
token threshold reached. Default is 85k.
The new ex option "aco!" automatically uses "apack!" command once a certain
token threshold reached. Default is 85k.

Adds temporary buffers /conversation/ for the conversation and /skills/
for the system prompt. Both restart commands reload the skills buffer.
These buffers are saved automatically under $HOME/.nextvi/logs, or log_dir
if set.

Example: ask about the whole buffer
:%a Explain this code

lsp.sh
--------------
LSP support for Nextvi.
Adds a new ex command "lsp" to start the LSP server, for example:
:lsp c clangd
Check that it is running:
:lsp
Once the server is up, new normal keybinds can be used:
gK - show hover documentation for the symbol at the cursor
gd - goto definition of the symbol at the cursor
Also supports on-the-fly hinting.

treesitter.sh
--------------
Incremental Tree-sitter syntax highlighting, with C configured at compile
time. Apply to the pristine patches-branch sources with ./treesitter.sh.
The default hl is 2. hl 0 disables highlighting, hl 1 selects the existing
regex highlighter, and other positive values select Tree-sitter with regex
fallback. C is selected for buffers of filetype c whose filename ends in
.c or .h. C++/C# filename aliases, other languages, /ex, prompts, messages,
status bars, and other internal filetypes retain regex highlighting.

Build with ./cbuild.sh build (or ./cbuild.sh for the first build).
The build fetches tree-sitter v0.25.10 and tree-sitter-c v0.24.1 from GitHub,
checks their pinned commits, and compiles the runtime and generated C parser
directly into vi. Git and network access are needed only for the first fetch;
no system Tree-sitter library, pkg-config, Rust, or Tree-sitter CLI is needed.

Sources are cached in .treesitter/ and reused by build, debug, and pgobuild.
The cache is ignored by Git and retained by clean, allowing offline rebuilds.
Remove .treesitter/ to fetch fresh copies on the next build. The editor itself
performs no downloads and needs no Tree-sitter files installed at runtime.

Configure ts_languages and ts_attributes in conf.c, then rebuild. The supplied
predicate-free C query covers comments, strings, characters, escapes, numbers,
types, keywords, preprocessor tokens, operators, and functions. Later query
patterns take precedence, merging attributes with syn_merge(); unknown
capture names contribute nothing. Unsupported predicates/directives, invalid
queries, or a grammar/runtime ABI mismatch produce one diagnostic and select
regex fallback. Syntax errors in the document still use Tree-sitter's tree.
Injections, local-variable tracking, additional languages, and arbitrary
third-party query compatibility are not included.

The registered syntax extension runs before transient and registered overlays.
hll and hlw use their existing patterns and colors after Tree-sitter syntax;
hlp, hlr, visual selection, and other extension overlays remain composable.
Buffer edits update the existing tree immediately and defer parsing to the
next draw. Insert/change commands use a separate incremental preview, including
surrounding lines; nested editor entry suspends it. Queries read document
bytes, including off-screen text, and painting maps captures to visible
character attributes. Capture caches are invalidated on every document edit.

Tree-sitter API contracts:
https://tree-sitter.github.io/tree-sitter/using-parsers/2-basic-parsing.html
https://tree-sitter.github.io/tree-sitter/using-parsers/3-advanced-parsing.html
https://tree-sitter.github.io/tree-sitter/using-parsers/queries/3-predicates-and-directives.html

sse.sh
--------------
SIMD optimizations for Nextvi.

mouse_normal.sh
--------------
Adds mouse support in normal mode, with a new ex option "ms" to toggle it.
Clicking positions the cursor and the mouse wheel scrolls using ^Y or ^E.
Terminal mouse selections can still be made while holding Shift on most
terminal emulators.

detect_indent.sh
--------------
Scans lines to guess the indentation format.
Adds 3 new ex options:
"et" - expandtab. Tabs are replaced with spaces.
"sw" - space width. How many literal spaces are injected for a tab.
"idt" - indent detect. Enables indent guessing and sets the line
limit (default 500).

mhash.sh
--------------
A hash map implementation for marks which aims to take O(n) mark
search down to ~O(1). An exercise. Unjustified complexity for
regular use.

writeall.sh
--------------
Adds the "wa", "wa!", "wqa", "wqa!", "xa" and "xa!" ex commands to write
all buffers to the filesystem. q commands always write, while x commands
only write modified buffers.

ins_cursor.sh
--------------
Changes cursor to a thin vertical bar when in insert mode.
This is a good indicator for insert mode.

cbas.sh
--------------
Adds syntax highlighting for Coders Basilisk
https://codeberg.org/gek/coders_basilisk/src/branch/main

highlight_cmd.sh
--------------
Adds a new ex command "hi". This command can be used to create
additional syntax highlighting rules on demand. The command prefix
specifies comma separated attributes, one per regex group, each a
bitmask conf.c can express. Figuring out the right value requires
some effort and reading vi.h helps.
Example: highlight int as keyword (RE color)
:1hi int
Example: highlight multiple different keywords
:0,1,5,3hi \<(int)|(void)|(if)\>
Example: disable rules
:hi
Example: highlight text inside parens
:5hi \(.*?\)

spell.sh
--------------
Spell checking with an external speller that speaks the ispell pipe
protocol. Adds a new ex commands "sl", "sl!" and the keybind gs.
"sl" runs the speller over the buffer, highlights the misspelled words
and keeps their suggestions, "sl!" clears both. Argument sets the
speller, which defaults to "aspell -a" as defined in conf.c.
gs replaces the word under the cursor with its first suggestion, a
count selects another one. The suggestions of the word under the
cursor are printed as an ex message, numbered by the count that
picks them: "1:weird 2:wired 3:weirdo".
Results are invalidated only once "sl" runs again.
Example: check with a German dictionary
:sl aspell -a --lang=de
Example: check with hunspell
:sl hunspell -a

nvi_status.sh
--------------
Rewords the <^G> status line the way nvi puts it:
"file: modified: line 3 of 10 (22%) col 1 [b0]"

My current EXINIT setup:
--------------
How it works:
|sc!||1sc | - disable special characters
97reg - put macro into a register
ish - enable interactive shell
inc (^(?:(?!^\.git).)+[^/]+$) always excludes the .git folder from :fd
pac - print autocomplete options
|sc|? - default special characters; ? is a nop cycle required for
separator reset. Scripts can append more commands to EXINIT.

Macros:
@q = creates a structure like this:
{

}
@w = creates a structure like this:
whatever {
	whatever
	a
}
@e = brings :e !p $c into the ex prompt
Note: p is an alias for printf. $c[0-9] is an env var containing some path.
@a = creates a comment like this:
/* whatever */
@s = from the cursor creates a comment like this:
/* whatever */
@d = uncomment /* */ comment
@x = indent % region left
@f = brings :cd !p $c into the ex prompt
Note: p is an alias for printf. $c[0-9] is an env var containing some path.
@l = brings the !cp % %_|w|!git diff --no-index %_ % macro into the ex prompt.
Use it to create patch and diff files fast. It relies on
you not saving the file prior to running the macro.
@z = control character mapping placeholders
@t = works with the ./tags file generated by ctags
and goes to the definition matching the current regex keyword
@r = goto definition while in the ./tags file

export EXINIT="$(printf '%b' '|sc!||1sc |:108reg :!cp % %_:w:!git diff --no-index %_ %113reg o{\n}kA\n	115reg i/*A*/119reg A {jo}koa120reg >%<<$%<<122reg :ph1 1 2 1^A:ph2 2 2 1^B:ph3 3 2 1^C:ph4 4 2 1^D:ph5 5 2 1^E:ph6 6 2 1^F:ph7 7 2 1^G:ph8 8 2 1^H:ph9 9 2 1^I:ph10 10 2 1^J:ph11 11 2 1^K:ph12 12 2 1^L:ph13 13 2 1^M:ph14 14 2 1^N:ph15 15 2 1^O:ph16 16 2 1^P:ph17 17 2 1^Q:ph18 18 2 1^R:ph19 19 2 1^S:ph20 20 2 1^T:ph21 21 2 1^U:ph22 22 2 1^V:ph23 23 2 1^W:ph24 24 2 1^X:ph25 25 2 1^Y:ph26 26 2 1^Z:ph27 27 2 1^[:ph28 28 2 1^\\\\:ph29 29 2 1^]:ph30 30 2 1^^:ph31 31 2 1^_102reg :cd !p $c101reg :e !p $c97reg I/*A*/100reg /\/\*\n2x/\*\/\n2x116reg :51reg %@47:e ./tags:1;0:;>unescaped>:??!\%s/[\\\\](.)/\\1/g\:1i unescaped:ic:%f>^%@51	:??!p "%@51" not found in tags\:ic\:e %#\:re %@51\:1q:;>	>+1;#>	>ya49:;>	/\^>+3;#>\$/;">re:??!;>	[0-9]+>+1;#>;>ya50\:??\!p bad format\\\\\:ic\\\\\:e %#\\\\\:re %@51\\\\\:2q\:e %@49\:?\%@50\:re %@51\:ic\:1q:e %@49:1:%f>:re %@51:ic114reg :51reg %@47:;>	>+1;#>	>ya49:;>	/\^>+3;#>\$/;">re:??!;>	[0-9]+>+1;#>;>ya50\:??\!p bad format\\\\\:re %@51\\\\\:2q\:e %@49\:?\%@50\:re %@51\:1q:e %@49:1:ic:%f>:re %@51:icinc (^(?:(?!^\.git).)+[^/]+$)pacish|sc|?')"
