readline/vim.go

177 lines
2.8 KiB
Go
Raw Permalink Normal View History

2015-10-01 17:44:43 +03:00
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() {
2015-10-02 05:37:21 +03:00
o.vimMode = VIM_INSERT
2015-10-01 17:44:43 +03:00
}
func (o *opVim) IsEnableVimMode() bool {
return o.cfg.VimMode
}
2015-10-02 05:37:21 +03:00
func (o *opVim) handleVimNormalMovement(r rune, readNext func() rune) (t rune, handled bool) {
rb := o.op.buf
handled = true
2015-10-01 17:44:43 +03:00
switch r {
2015-10-02 05:37:21 +03:00
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()
2015-10-02 05:58:43 +03:00
case 'b', 'B':
2015-10-02 05:37:21 +03:00
rb.MoveToPrevWord()
case 'w', 'W':
2015-10-02 05:37:21 +03:00
rb.MoveToNextWord()
case 'e', 'E':
rb.MoveToEndWord()
2015-10-02 05:37:21 +03:00
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:
2015-10-01 17:44:43 +03:00
return r, false
}
2015-10-02 05:37:21 +03:00
return t, true
}
func (o *opVim) handleVimNormalEnterInsert(r rune, readNext func() rune) (t rune, handled bool) {
2015-10-01 17:44:43 +03:00
rb := o.op.buf
2015-10-02 05:37:21 +03:00
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()
2015-10-01 17:44:43 +03:00
}
2015-10-02 05:37:21 +03:00
default:
return r, false
2015-10-01 17:44:43 +03:00
}
2015-10-02 05:37:21 +03:00
o.EnterVimInsertMode()
return
}
func (o *opVim) HandleVimNormal(r rune, readNext func() rune) (t rune) {
switch r {
case CharEnter, CharInterrupt:
o.ExitVimMode()
return r
2015-10-01 17:44:43 +03:00
}
2015-10-02 05:37:21 +03:00
if r, handled := o.handleVimNormalMovement(r, readNext); handled {
return r
}
if r, handled := o.handleVimNormalEnterInsert(r, readNext); handled {
return r
2015-10-01 17:44:43 +03:00
}
// invalid operation
o.op.t.Bell()
2015-10-02 05:37:21 +03:00
return 0
2015-10-01 17:44:43 +03:00
}
func (o *opVim) EnterVimInsertMode() {
o.vimMode = VIM_INSERT
}
func (o *opVim) ExitVimInsertMode() {
o.vimMode = VIM_NORMAL
}
2015-10-02 05:37:21 +03:00
func (o *opVim) HandleVim(r rune, readNext func() rune) rune {
2015-10-01 17:44:43 +03:00
if o.vimMode == VIM_NORMAL {
return o.HandleVimNormal(r, readNext)
}
if r == CharEsc {
o.ExitVimInsertMode()
2015-10-02 05:37:21 +03:00
return 0
2015-10-01 17:44:43 +03:00
}
switch o.vimMode {
case VIM_INSERT:
2015-10-02 05:37:21 +03:00
return r
2015-10-01 17:44:43 +03:00
case VIM_VISUAL:
}
2015-10-02 05:37:21 +03:00
return r
2015-10-01 17:44:43 +03:00
}