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" }
querry = { "?" }
repeat = { "." }
gg = { ASCII_DIGIT* ~ &"gg" }
quickstuffescaped = _{ replaceend | replacement | replace | insertend | insertstuff | insert | remove | dd | jumpascii | querry | repeat | gg }
search = { "/" }
searchstr = { (!(escape_char | NEWLINE) ~ ANY)* }
searchend = { &search ~ ANY ~ searchstr ~ NEWLINE }
hex_digit = @{ ASCII_HEX_DIGIT | 'x'..'x' | 'X'..'X' }
hexsearchend = { &search ~ ANY ~ hex_digit* ~ NEWLINE }
quickstuff = _{ hexsearchend | searchend }
saveandexit = { (":" ~ ("wq!" | "wq") ~ NEWLINE) | "ZZ" } // careful, notice priority
exit = { (":" ~ ("q!" | "q") ~ NEWLINE) | "ZQ" } // careful, notice priority
save = { (":" ~ ("write!" | "write" | "w!" | "w") ~ NEWLINE) } // 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 | NEWLINE) ~ ANY }
gatherall = { gatherone* }
cmd_list = _{ ( movement | quickstuffescaped | escape | quickstuff | backspace | cmd | gatherall ) }