movement = _{ down | up | left | right | start | end | bottom }
down = { "j" | "[B" }
up = { "k" | "[A" }
left = { "h" | "[D" }
right = { "l" | "[C" }
start = { "0" }
end = { "$" }
bottom = { "G" }
replace = { "r" }
replacement = { &replace ~ ANY ~ (anything_but_escape) }
replaceend = { &replace ~ ANY ~ (anything_but_escape)* ~ escape_char }
remove = { "x" }
dd = { ASCII_DIGIT* ~ &"dd" }
insert = { "i" }
insertstuff = { &insert ~ ANY ~ (anything_but_escape)+ }
insertend = { &insert ~ ANY ~ (anything_but_escape)* ~ escape_char }
jumpascii = { "J" }
helpfile = { "?" }
repeat = { "." }
gg = { ASCII_DIGIT* ~ &"gg" }
quickstuffescaped = _{ replaceend | replacement | replace | insertend | insertstuff | insert | remove | dd | jumpascii | helpfile | repeat | gg }
searchstr = { (!(escape_char | "\n") ~ ANY)* }
search = { "/" ~ searchstr ~ "\n" }
hex_digit = @{ ASCII_HEX_DIGIT | 'x'..'x' | 'X'..'X' }
searchbytes = { ( hex_digit{2} )* }
hexsearch = { "/" ~ searchbytes ~ "\n" }
quickstuff = _{ hexsearch | search }
saveandexit = { (":" ~ ("wq!" | "wq") ~ "\n") | "ZZ" } // careful, notice priority
exit = { (":" ~ ("q!" | "q") ~ "\n") | "ZQ" } // careful, notice priority
save = { (":" ~ ("write!" | "write" | "w!" | "w") ~ "\n") } // careful, notice priority
cmd = _{ ( saveandexit | exit | save ) }
// Escape character definition:
escape_char = _{ "\u{1b}" }
// Escape character not present:
anything_but_escape = _{ !(escape_char) ~ ANY }
// Escape thought to be used as fallback to terminate all other operations
escape = { (anything_but_escape)* ~ escape_char }
// consume any "not backspaces" until first backspace
backspace_char = _{ "\u{7f}" }
backspace = { (!(backspace_char) ~ ANY)* ~ backspace_char }
// Not escape and not Enter
gatherone = @{ !(escape_char | "\n") ~ ANY }
gatherall = { gatherone* }
cmd_list = _{ ( movement | quickstuffescaped | escape | quickstuff | backspace | cmd | gatherall ) }