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()
|
2016-02-24 17:35:22 +03:00
|
|
|
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()
|
|
|
|
}
|
2017-10-02 06:57:50 +03:00
|
|
|
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()
|
2016-07-26 16:40:22 +03:00
|
|
|
case 'w', 'W':
|
2015-10-02 05:37:21 +03:00
|
|
|
rb.MoveToNextWord()
|
2016-07-26 16:40:22 +03:00
|
|
|
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()
|
2016-02-24 17:35:22 +03:00
|
|
|
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
|
|
|
}
|