mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-14 19:27:58 +08:00
edit: Manage insert and command bindings in their structs.
This commit is contained in:
parent
cbf6e7c67d
commit
d30826d02d
|
@ -105,7 +105,7 @@ func complAccept(ed *Editor) {
|
|||
if 0 <= c.selected && c.selected < len(c.filtered) {
|
||||
ed.buffer, ed.dot = c.apply(ed.buffer, ed.dot)
|
||||
}
|
||||
ed.mode = &ed.insert
|
||||
ed.SetModeInsert()
|
||||
}
|
||||
|
||||
func complDefault(ed *Editor) {
|
||||
|
|
25
edit/edit.go
25
edit/edit.go
|
@ -40,8 +40,6 @@ type Editor struct {
|
|||
active bool
|
||||
activeMutex sync.Mutex
|
||||
|
||||
insertBinding BindingMap
|
||||
commandBinding BindingMap
|
||||
completionBinding BindingMap
|
||||
navigationBinding BindingMap
|
||||
|
||||
|
@ -68,7 +66,9 @@ type Editor struct {
|
|||
maxHeight float64
|
||||
|
||||
// Modes.
|
||||
hist *hist
|
||||
insert *insert
|
||||
command *command
|
||||
hist *hist
|
||||
|
||||
editorState
|
||||
}
|
||||
|
@ -94,8 +94,6 @@ type editorState struct {
|
|||
|
||||
mode Mode
|
||||
|
||||
insert insert
|
||||
command command
|
||||
completion completion
|
||||
navigation navigation
|
||||
|
||||
|
@ -196,12 +194,18 @@ func (ed *Editor) SetBuffer(buffer string, dot int) {
|
|||
|
||||
// SetMode sets the current mode of the Editor.
|
||||
func (ed *Editor) SetMode(m Mode) {
|
||||
if deiniter, ok := ed.mode.(deiniter); ok {
|
||||
deiniter.Deinit()
|
||||
}
|
||||
ed.mode = m
|
||||
if initer, ok := m.(initer); ok {
|
||||
initer.Init()
|
||||
}
|
||||
}
|
||||
|
||||
// SetModeInsert sets the current mode of the Editor to insert mode.
|
||||
func (ed *Editor) SetModeInsert() {
|
||||
ed.mode = &ed.insert
|
||||
ed.SetMode(ed.insert)
|
||||
}
|
||||
|
||||
func (ed *Editor) flash() {
|
||||
|
@ -317,13 +321,16 @@ func (ed *Editor) finishReadLine() error {
|
|||
ed.active = false
|
||||
|
||||
// Refresh the terminal for the last time in a clean-ish state.
|
||||
ed.mode = &ed.insert
|
||||
ed.SetModeInsert()
|
||||
ed.tips = nil
|
||||
ed.dot = len(ed.buffer)
|
||||
if !ed.RpromptPersistent {
|
||||
ed.rpromptContent = nil
|
||||
}
|
||||
errRefresh := ed.refresh(false, false)
|
||||
if deiniter, ok := ed.mode.(deiniter); ok {
|
||||
deiniter.Deinit()
|
||||
}
|
||||
ed.out.WriteString("\n")
|
||||
ed.writer.ResetCurrentBuffer()
|
||||
|
||||
|
@ -356,7 +363,7 @@ func (ed *Editor) ReadLine() (string, error) {
|
|||
}
|
||||
}()
|
||||
|
||||
ed.mode = &ed.insert
|
||||
ed.SetModeInsert()
|
||||
|
||||
// Find external commands asynchronously, so that slow I/O won't block the
|
||||
// editor.
|
||||
|
@ -425,7 +432,7 @@ MainLoop:
|
|||
restoreTerminal: ed.restoreTerminal,
|
||||
isExternal: ed.isExternal,
|
||||
}
|
||||
ed.mode = &ed.insert
|
||||
ed.SetModeInsert()
|
||||
continue MainLoop
|
||||
case sys.SIGWINCH:
|
||||
fullRefresh = true
|
||||
|
|
|
@ -26,14 +26,11 @@ type hist struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
atEditorInit(func(ed *Editor, ns eval.Ns) {
|
||||
ed.hist = initHist(ed, ns)
|
||||
})
|
||||
atEditorInit(initHist)
|
||||
}
|
||||
|
||||
func initHist(ed *Editor, ns eval.Ns) *hist {
|
||||
func initHist(ed *Editor, ns eval.Ns) {
|
||||
hist := &hist{ed: ed, binding: EmptyBindingMap}
|
||||
|
||||
if ed.Daemon() != nil {
|
||||
fuser, err := history.NewFuser(ed.Daemon())
|
||||
if err != nil {
|
||||
|
@ -43,6 +40,7 @@ func initHist(ed *Editor, ns eval.Ns) *hist {
|
|||
ed.AddAfterReadline(hist.appendHistory)
|
||||
}
|
||||
}
|
||||
ed.hist = hist
|
||||
|
||||
subns := eval.Ns{
|
||||
"binding": eval.NewVariableFromPtr(&hist.binding),
|
||||
|
@ -58,8 +56,6 @@ func initHist(ed *Editor, ns eval.Ns) *hist {
|
|||
})
|
||||
|
||||
ns.AddNs("history", subns)
|
||||
|
||||
return hist
|
||||
}
|
||||
|
||||
func (h *hist) Binding(ed *Editor, k ui.Key) eval.Callable {
|
||||
|
|
|
@ -14,12 +14,12 @@ import (
|
|||
// Builtins related to insert and command mode.
|
||||
|
||||
func init() {
|
||||
atEditorInit(func(ed *Editor, ns eval.Ns) {
|
||||
initCoreModes(ed, ns)
|
||||
})
|
||||
atEditorInit(initCoreFns)
|
||||
atEditorInit(initInsert)
|
||||
atEditorInit(initCommand)
|
||||
}
|
||||
|
||||
func initCoreModes(ed *Editor, ns eval.Ns) {
|
||||
func initCoreFns(ed *Editor, ns eval.Ns) {
|
||||
ns.AddBuiltinFns("edit:", map[string]interface{}{
|
||||
"kill-line-left": ed.killLineLeft,
|
||||
"kill-line-right": ed.killLineRight,
|
||||
|
@ -50,27 +50,14 @@ func initCoreModes(ed *Editor, ns eval.Ns) {
|
|||
"end-of-history": ed.endOfHistory,
|
||||
"redraw": ed.redraw,
|
||||
})
|
||||
|
||||
insertNs := eval.Ns{
|
||||
"binding": eval.NewVariableFromPtr(&ed.insertBinding),
|
||||
}
|
||||
insertNs.AddBuiltinFns("edit:insert:", map[string]interface{}{
|
||||
"start": ed.insertStart,
|
||||
"default": ed.insertDefault,
|
||||
})
|
||||
ns.AddNs("insert", insertNs)
|
||||
|
||||
commandNs := eval.Ns{
|
||||
"binding": eval.NewVariableFromPtr(&ed.commandBinding),
|
||||
}
|
||||
commandNs.AddBuiltinFns("edit:command:", map[string]interface{}{
|
||||
"start": ed.commandStart,
|
||||
"default": ed.commandDefault,
|
||||
})
|
||||
ns.AddNs("command", commandNs)
|
||||
}
|
||||
|
||||
type insert struct {
|
||||
binding BindingMap
|
||||
insertState
|
||||
}
|
||||
|
||||
type insertState struct {
|
||||
quotePaste bool
|
||||
// The number of consecutive key inserts. Used for abbreviation expansion.
|
||||
literalInserts int
|
||||
|
@ -79,6 +66,24 @@ type insert struct {
|
|||
insertedLiteral bool
|
||||
}
|
||||
|
||||
func initInsert(ed *Editor, ns eval.Ns) {
|
||||
insert := &insert{binding: EmptyBindingMap}
|
||||
ed.insert = insert
|
||||
|
||||
insertNs := eval.Ns{
|
||||
"binding": eval.NewVariableFromPtr(&insert.binding),
|
||||
}
|
||||
insertNs.AddBuiltinFns("edit:insert:", map[string]interface{}{
|
||||
"start": ed.SetModeInsert,
|
||||
"default": ed.insertDefault,
|
||||
})
|
||||
ns.AddNs("insert", insertNs)
|
||||
}
|
||||
|
||||
func (ins *insert) Deinit() {
|
||||
ins.insertState = insertState{}
|
||||
}
|
||||
|
||||
// ui.Insert mode is the default mode and has an empty mode.
|
||||
func (ins *insert) ModeLine() ui.Renderer {
|
||||
if ins.quotePaste {
|
||||
|
@ -87,26 +92,38 @@ func (ins *insert) ModeLine() ui.Renderer {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (*insert) Binding(ed *Editor, k ui.Key) eval.Callable {
|
||||
return ed.insertBinding.GetOrDefault(k)
|
||||
func (ins *insert) Binding(ed *Editor, k ui.Key) eval.Callable {
|
||||
return ins.binding.GetOrDefault(k)
|
||||
}
|
||||
|
||||
type command struct{}
|
||||
type command struct {
|
||||
binding BindingMap
|
||||
}
|
||||
|
||||
func initCommand(ed *Editor, ns eval.Ns) {
|
||||
command := &command{binding: EmptyBindingMap}
|
||||
ed.command = command
|
||||
|
||||
commandNs := eval.Ns{
|
||||
"binding": eval.NewVariableFromPtr(&command.binding),
|
||||
}
|
||||
commandNs.AddBuiltinFns("edit:command:", map[string]interface{}{
|
||||
"start": ed.commandStart,
|
||||
"default": ed.commandDefault,
|
||||
})
|
||||
ns.AddNs("command", commandNs)
|
||||
}
|
||||
|
||||
func (*command) ModeLine() ui.Renderer {
|
||||
return modeLineRenderer{" COMMAND ", ""}
|
||||
}
|
||||
|
||||
func (*command) Binding(ed *Editor, k ui.Key) eval.Callable {
|
||||
return ed.commandBinding.GetOrDefault(k)
|
||||
}
|
||||
|
||||
func (ed *Editor) insertStart() {
|
||||
ed.mode = &ed.insert
|
||||
func (cmd *command) Binding(ed *Editor, k ui.Key) eval.Callable {
|
||||
return cmd.binding.GetOrDefault(k)
|
||||
}
|
||||
|
||||
func (ed *Editor) commandStart() {
|
||||
ed.mode = &ed.command
|
||||
ed.SetMode(ed.command)
|
||||
}
|
||||
|
||||
func (ed *Editor) killLineLeft() {
|
||||
|
|
|
@ -82,7 +82,7 @@ func (b *lastcmd) Filter(filter string) int {
|
|||
|
||||
func (b *lastcmd) Accept(i int, ed *Editor) {
|
||||
ed.insertAtDot(b.filtered[i].s)
|
||||
ed.insertStart()
|
||||
ed.SetModeInsert()
|
||||
}
|
||||
|
||||
func lastcmdStart(ed *Editor) {
|
||||
|
@ -112,7 +112,7 @@ func lastcmdAltDefault(ed *Editor) {
|
|||
logger.Println("accepting")
|
||||
}
|
||||
} else {
|
||||
ed.insertStart()
|
||||
ed.SetModeInsert()
|
||||
ed.SetAction(ReprocessKey)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ var listingFns = map[string]func(*Editor){
|
|||
"accept": func(ed *Editor) { getListing(ed).accept(ed) },
|
||||
"accept-close": func(ed *Editor) {
|
||||
getListing(ed).accept(ed)
|
||||
ed.insertStart()
|
||||
ed.SetModeInsert()
|
||||
},
|
||||
"default": func(ed *Editor) { getListing(ed).defaultBinding(ed) },
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ func (l *listing) handleFilterKey(k ui.Key) bool {
|
|||
|
||||
func (l *listing) defaultBinding(ed *Editor) {
|
||||
if !l.handleFilterKey(ed.lastKey) {
|
||||
ed.insertStart()
|
||||
ed.SetModeInsert()
|
||||
ed.SetAction(ReprocessKey)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ func (loc *location) Accept(i int, ed *Editor) {
|
|||
if err != nil {
|
||||
ed.Notify("%v", err)
|
||||
}
|
||||
ed.mode = &ed.insert
|
||||
ed.SetModeInsert()
|
||||
}
|
||||
|
||||
func locStart(ed *Editor) {
|
||||
|
|
|
@ -11,6 +11,14 @@ type Mode interface {
|
|||
Binding(*Editor, ui.Key) eval.Callable
|
||||
}
|
||||
|
||||
type initer interface {
|
||||
Init()
|
||||
}
|
||||
|
||||
type deiniter interface {
|
||||
Deinit()
|
||||
}
|
||||
|
||||
// CursorOnModeLiner is an optional interface that modes can implement. If a
|
||||
// mode does and the method returns true, the cursor is placed on the modeline
|
||||
// when that mode is active.
|
||||
|
|
|
@ -25,7 +25,7 @@ var narrowFns = map[string]func(*Editor){
|
|||
"accept": func(ed *Editor) { getNarrow(ed).accept(ed) },
|
||||
"accept-close": func(ed *Editor) {
|
||||
getNarrow(ed).accept(ed)
|
||||
ed.insertStart()
|
||||
ed.SetModeInsert()
|
||||
},
|
||||
"toggle-ignore-duplication": func(ed *Editor) {
|
||||
l := getNarrow(ed)
|
||||
|
@ -291,7 +291,7 @@ func (l *narrow) handleFilterKey(ed *Editor) bool {
|
|||
l.changeFilter(l.filter + string(k.Rune))
|
||||
if len(l.filtered) == 1 && l.opts.AutoCommit {
|
||||
l.accept(ed)
|
||||
ed.insertStart()
|
||||
ed.SetModeInsert()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ func (l *narrow) handleFilterKey(ed *Editor) bool {
|
|||
|
||||
func (l *narrow) defaultBinding(ed *Editor) {
|
||||
if !l.handleFilterKey(ed) {
|
||||
ed.insertStart()
|
||||
ed.SetModeInsert()
|
||||
ed.SetAction(ReprocessKey)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ func navInsertSelected(ed *Editor) {
|
|||
|
||||
func navInsertSelectedAndQuit(ed *Editor) {
|
||||
ed.insertAtDot(parse.Quote(ed.navigation.current.selectedName()) + " ")
|
||||
ed.mode = &ed.insert
|
||||
ed.SetModeInsert()
|
||||
}
|
||||
|
||||
func navDefault(ed *Editor) {
|
||||
|
@ -150,7 +150,7 @@ func navDefault(ed *Editor) {
|
|||
n.refreshDirPreview()
|
||||
}
|
||||
} else {
|
||||
fn := ed.insertBinding.GetOrDefault(k)
|
||||
fn := ed.insert.binding.GetOrDefault(k)
|
||||
if fn == nil {
|
||||
ed.Notify("key %s unbound and no default binding", k)
|
||||
} else {
|
||||
|
|
|
@ -20,7 +20,7 @@ func (ed *Editor) startInsertRaw() {
|
|||
func insertRaw(ed *Editor, r rune) {
|
||||
ed.insertAtDot(string(r))
|
||||
ed.reader.SetRaw(false)
|
||||
ed.mode = &ed.insert
|
||||
ed.SetModeInsert()
|
||||
}
|
||||
|
||||
func (rawInsert) Binding(*Editor, ui.Key) eval.Callable {
|
||||
|
|
Loading…
Reference in New Issue
Block a user