summaryrefslogtreecommitdiff
path: root/vendor/github.com/chzyer/readline/vim.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/chzyer/readline/vim.go')
-rw-r--r--vendor/github.com/chzyer/readline/vim.go176
1 files changed, 176 insertions, 0 deletions
diff --git a/vendor/github.com/chzyer/readline/vim.go b/vendor/github.com/chzyer/readline/vim.go
new file mode 100644
index 000000000..bedf2c1a6
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/vim.go
@@ -0,0 +1,176 @@
+package readline
+
+const (
+ VIM_NORMAL = iota
+ VIM_INSERT
+ VIM_VISUAL
+)
+
+type opVim struct {
+ cfg *Config
+ op *Operation
+ vimMode int
+}
+
+func newVimMode(op *Operation) *opVim {
+ ov := &opVim{
+ cfg: op.cfg,
+ op: op,
+ }
+ ov.SetVimMode(ov.cfg.VimMode)
+ return ov
+}
+
+func (o *opVim) SetVimMode(on bool) {
+ if o.cfg.VimMode && !on { // turn off
+ o.ExitVimMode()
+ }
+ o.cfg.VimMode = on
+ o.vimMode = VIM_INSERT
+}
+
+func (o *opVim) ExitVimMode() {
+ o.vimMode = VIM_INSERT
+}
+
+func (o *opVim) IsEnableVimMode() bool {
+ return o.cfg.VimMode
+}
+
+func (o *opVim) handleVimNormalMovement(r rune, readNext func() rune) (t rune, handled bool) {
+ rb := o.op.buf
+ handled = true
+ switch r {
+ case 'h':
+ t = CharBackward
+ case 'j':
+ t = CharNext
+ case 'k':
+ t = CharPrev
+ case 'l':
+ t = CharForward
+ case '0', '^':
+ rb.MoveToLineStart()
+ case '$':
+ rb.MoveToLineEnd()
+ case 'x':
+ rb.Delete()
+ if rb.IsCursorInEnd() {
+ rb.MoveBackward()
+ }
+ case 'r':
+ rb.Replace(readNext())
+ case 'd':
+ next := readNext()
+ switch next {
+ case 'd':
+ rb.Erase()
+ case 'w':
+ rb.DeleteWord()
+ case 'h':
+ rb.Backspace()
+ case 'l':
+ rb.Delete()
+ }
+ case 'p':
+ rb.Yank()
+ case 'b', 'B':
+ rb.MoveToPrevWord()
+ case 'w', 'W':
+ rb.MoveToNextWord()
+ case 'e', 'E':
+ rb.MoveToEndWord()
+ case 'f', 'F', 't', 'T':
+ next := readNext()
+ prevChar := r == 't' || r == 'T'
+ reverse := r == 'F' || r == 'T'
+ switch next {
+ case CharEsc:
+ default:
+ rb.MoveTo(next, prevChar, reverse)
+ }
+ default:
+ return r, false
+ }
+ return t, true
+}
+
+func (o *opVim) handleVimNormalEnterInsert(r rune, readNext func() rune) (t rune, handled bool) {
+ rb := o.op.buf
+ handled = true
+ switch r {
+ case 'i':
+ case 'I':
+ rb.MoveToLineStart()
+ case 'a':
+ rb.MoveForward()
+ case 'A':
+ rb.MoveToLineEnd()
+ case 's':
+ rb.Delete()
+ case 'S':
+ rb.Erase()
+ case 'c':
+ next := readNext()
+ switch next {
+ case 'c':
+ rb.Erase()
+ case 'w':
+ rb.DeleteWord()
+ case 'h':
+ rb.Backspace()
+ case 'l':
+ rb.Delete()
+ }
+ default:
+ return r, false
+ }
+
+ o.EnterVimInsertMode()
+ return
+}
+
+func (o *opVim) HandleVimNormal(r rune, readNext func() rune) (t rune) {
+ switch r {
+ case CharEnter, CharInterrupt:
+ o.ExitVimMode()
+ return r
+ }
+
+ if r, handled := o.handleVimNormalMovement(r, readNext); handled {
+ return r
+ }
+
+ if r, handled := o.handleVimNormalEnterInsert(r, readNext); handled {
+ return r
+ }
+
+ // invalid operation
+ o.op.t.Bell()
+ return 0
+}
+
+func (o *opVim) EnterVimInsertMode() {
+ o.vimMode = VIM_INSERT
+}
+
+func (o *opVim) ExitVimInsertMode() {
+ o.vimMode = VIM_NORMAL
+}
+
+func (o *opVim) HandleVim(r rune, readNext func() rune) rune {
+ if o.vimMode == VIM_NORMAL {
+ return o.HandleVimNormal(r, readNext)
+ }
+ if r == CharEsc {
+ o.ExitVimInsertMode()
+ return 0
+ }
+
+ switch o.vimMode {
+ case VIM_INSERT:
+ return r
+ case VIM_VISUAL:
+ }
+ return r
+}