summary refs log tree commit diff
path: root/vendor/github.com/chzyer/readline/vim.go
diff options
context:
space:
mode:
authorEmile <git@emile.space>2024-10-25 15:55:50 +0200
committerEmile <git@emile.space>2024-10-25 15:55:50 +0200
commitc90f36e3dd179d2de96f4f5fe38d8dc9a9de6dfe (patch)
tree89e9afb41c5bf76f48cfb09305a2d3db8d302b06 /vendor/github.com/chzyer/readline/vim.go
parent98bbb0f559a8883bc47bae80607dbe326a448e61 (diff)
vendor HEAD main
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 0000000..bedf2c1
--- /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
+}