mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-13 01:47:51 +08:00
edit: Default binding is now set in Elvish script.
This commit is contained in:
parent
68db7fe99c
commit
837f124f13
|
@ -1,4 +0,0 @@
|
|||
package edit
|
||||
|
||||
const bindingElv = `
|
||||
`
|
|
@ -29,21 +29,6 @@ var _ = registerBuiltins(modeCompletion, map[string]func(*Editor){
|
|||
"default": complDefault,
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeCompletion, modeCompletion, map[ui.Key]string{
|
||||
{ui.Up, 0}: "up",
|
||||
{ui.Down, 0}: "down",
|
||||
{ui.Tab, 0}: "down-cycle",
|
||||
{ui.Tab, ui.Shift}: "up-cycle",
|
||||
{ui.Left, 0}: "left",
|
||||
{ui.Right, 0}: "right",
|
||||
{ui.Enter, 0}: "accept",
|
||||
{'F', ui.Ctrl}: "trigger-filter",
|
||||
{'[', ui.Ctrl}: "insert:start",
|
||||
ui.Default: "default",
|
||||
})
|
||||
}
|
||||
|
||||
type completion struct {
|
||||
complSpec
|
||||
completer string
|
||||
|
|
|
@ -146,8 +146,10 @@ func NewEditor(in *os.File, out *os.File, sigs chan os.Signal, ev *eval.Evaler)
|
|||
ev.Editor = ed
|
||||
|
||||
installModules(ev.Builtin, ed)
|
||||
ev.InstallBundled("binding", bindingElv)
|
||||
ev.SourceText("[editor]", "use binding")
|
||||
err = ev.SourceText("[editor]", "use binding; binding:install")
|
||||
if err != nil {
|
||||
fmt.Fprintln(out, "Failed to load default binding:", err)
|
||||
}
|
||||
|
||||
return ed
|
||||
}
|
||||
|
|
|
@ -30,19 +30,24 @@ func TestReadLine(t *testing.T) {
|
|||
}
|
||||
defer master.Close()
|
||||
defer tty.Close()
|
||||
|
||||
// Continually consume tty outputs so that the editor is not blocked on
|
||||
// writing.
|
||||
var outputs []byte
|
||||
go func() {
|
||||
var buf [64]byte
|
||||
var buf [256]byte
|
||||
for {
|
||||
_, err := master.Read(buf[:])
|
||||
nr, err := master.Read(buf[:])
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
outputs = append(outputs, buf[:nr]...)
|
||||
}
|
||||
}()
|
||||
|
||||
ev := eval.NewEvaler()
|
||||
// XXX: Needed for "use" to work.
|
||||
ev.SetLibDir("/non/exist/ent")
|
||||
defer ev.Close()
|
||||
|
||||
for _, test := range readLineTests {
|
||||
|
@ -73,7 +78,9 @@ func TestReadLine(t *testing.T) {
|
|||
t.Errorf("ReadLine() => error %v (input %q)", err, test.input)
|
||||
case <-time.After(readLineTimeout):
|
||||
t.Errorf("ReadLine() timed out (input %q)", test.input)
|
||||
t.Log("\n" + sys.DumpStack())
|
||||
t.Log("Stack trace: \n" + sys.DumpStack())
|
||||
t.Logf("Terminal output: %q", outputs)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,14 +17,6 @@ var _ = registerBuiltins(modeHistoryListing, map[string]func(*Editor){
|
|||
"toggle-case-sensitivity": histlistToggleCaseSensitivity,
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeHistoryListing, modeHistoryListing,
|
||||
map[ui.Key]string{
|
||||
{'G', ui.Ctrl}: "toggle-case-sensitivity",
|
||||
{'D', ui.Ctrl}: "toggle-dedup",
|
||||
})
|
||||
}
|
||||
|
||||
// ErrStoreOffline is thrown when an operation requires the storage backend, but
|
||||
// it is offline.
|
||||
var ErrStoreOffline = errors.New("store offline")
|
||||
|
|
|
@ -22,16 +22,6 @@ var _ = registerBuiltins("history", map[string]func(*Editor){
|
|||
"default": wrapHistoryBuiltin(historyDefault),
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeHistory, "history", map[ui.Key]string{
|
||||
{ui.Up, 0}: "up",
|
||||
{ui.Down, 0}: "down-or-quit",
|
||||
{'[', ui.Ctrl}: "insert:start",
|
||||
{'R', ui.Ctrl}: "switch-to-histlist",
|
||||
ui.Default: "default",
|
||||
})
|
||||
}
|
||||
|
||||
type hist struct {
|
||||
*history.Walker
|
||||
}
|
||||
|
|
|
@ -54,66 +54,6 @@ var (
|
|||
})
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerBindings(modeInsert, "", map[ui.Key]string{
|
||||
// Moving.
|
||||
{ui.Left, 0}: "move-dot-left",
|
||||
{ui.Right, 0}: "move-dot-right",
|
||||
{ui.Up, ui.Alt}: "move-dot-up",
|
||||
{ui.Down, ui.Alt}: "move-dot-down",
|
||||
{ui.Left, ui.Ctrl}: "move-dot-left-word",
|
||||
{ui.Right, ui.Ctrl}: "move-dot-right-word",
|
||||
{'b', ui.Alt}: "move-dot-left-word",
|
||||
{'f', ui.Alt}: "move-dot-right-word",
|
||||
{ui.Home, 0}: "move-dot-sol",
|
||||
{ui.End, 0}: "move-dot-eol",
|
||||
// Killing.
|
||||
{'U', ui.Ctrl}: "kill-line-left",
|
||||
{'K', ui.Ctrl}: "kill-line-right",
|
||||
{'W', ui.Ctrl}: "kill-word-left",
|
||||
{ui.Backspace, 0}: "kill-rune-left",
|
||||
{'H', ui.Ctrl}: "kill-rune-left", // Some terminal send ^H on backspace
|
||||
{ui.Delete, 0}: "kill-rune-right",
|
||||
// Inserting.
|
||||
{'.', ui.Alt}: "insert-last-word",
|
||||
{ui.Enter, ui.Alt}: "insert-key",
|
||||
// Controls.
|
||||
{ui.Enter, 0}: "smart-enter",
|
||||
{'D', ui.Ctrl}: "return-eof",
|
||||
{ui.F2, 0}: "toggle-quote-paste",
|
||||
|
||||
// Other modes.
|
||||
// ui.Key{'[', ui.Ctrl}: "command-start",
|
||||
{ui.Tab, 0}: "completion:smart-start",
|
||||
{ui.Up, 0}: "history:start",
|
||||
{ui.Down, 0}: "end-of-history",
|
||||
{'N', ui.Ctrl}: "navigation:start",
|
||||
{'R', ui.Ctrl}: "histlist:start",
|
||||
{'1', ui.Alt}: "lastcmd:start",
|
||||
{'L', ui.Ctrl}: "location:start",
|
||||
{'V', ui.Ctrl}: "insert-raw",
|
||||
|
||||
ui.Default: "insert:default",
|
||||
})
|
||||
registerBindings(modeCommand, "", map[ui.Key]string{
|
||||
// Moving.
|
||||
{'h', 0}: "move-dot-left",
|
||||
{'l', 0}: "move-dot-right",
|
||||
{'k', 0}: "move-dot-up",
|
||||
{'j', 0}: "move-dot-down",
|
||||
{'b', 0}: "move-dot-left-word",
|
||||
{'w', 0}: "move-dot-right-word",
|
||||
{'0', 0}: "move-dot-sol",
|
||||
{'$', 0}: "move-dot-eol",
|
||||
// Killing.
|
||||
{'x', 0}: "kill-rune-right",
|
||||
{'D', 0}: "kill-line-right",
|
||||
// Controls.
|
||||
{'i', 0}: "insert:start",
|
||||
ui.Default: "command:default",
|
||||
})
|
||||
}
|
||||
|
||||
type insert struct {
|
||||
quotePaste bool
|
||||
// The number of consecutive key inserts. Used for abbreviation expansion.
|
||||
|
|
|
@ -15,12 +15,6 @@ var _ = registerBuiltins(modeLastCmd, map[string]func(*Editor){
|
|||
"alt-default": lastcmdAltDefault,
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeLastCmd, modeLastCmd, map[ui.Key]string{
|
||||
ui.Default: "alt-default",
|
||||
})
|
||||
}
|
||||
|
||||
type lastcmdEntry struct {
|
||||
i int
|
||||
s string
|
||||
|
|
|
@ -29,22 +29,6 @@ var _ = registerBuiltins(modeListing, map[string]func(*Editor){
|
|||
"default": func(ed *Editor) { getListing(ed).defaultBinding(ed) },
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeListing, modeListing, map[ui.Key]string{
|
||||
{ui.Up, 0}: "up",
|
||||
{ui.PageUp, 0}: "page-up",
|
||||
{ui.Down, 0}: "down",
|
||||
{ui.PageDown, 0}: "page-down",
|
||||
{ui.Tab, 0}: "down-cycle",
|
||||
{ui.Tab, ui.Shift}: "up-cycle",
|
||||
{ui.Backspace, 0}: "backspace",
|
||||
{ui.Enter, 0}: "accept-close",
|
||||
{ui.Enter, ui.Alt}: "accept",
|
||||
ui.Default: "default",
|
||||
{'[', ui.Ctrl}: "insert:start",
|
||||
})
|
||||
}
|
||||
|
||||
// listing implements a listing mode that supports the notion of selecting an
|
||||
// entry and filtering entries.
|
||||
type listing struct {
|
||||
|
|
|
@ -23,10 +23,6 @@ var _ = registerBuiltins(modeLocation, map[string]func(*Editor){
|
|||
"start": locStart,
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeLocation, modeLocation, map[ui.Key]string{})
|
||||
}
|
||||
|
||||
// PinnedScore is a special value of Score in storedefs.Dir to represent that the
|
||||
// directory is pinned.
|
||||
var PinnedScore = math.Inf(1)
|
||||
|
|
|
@ -6,8 +6,7 @@ import (
|
|||
"github.com/elves/elvish/eval/vartypes"
|
||||
)
|
||||
|
||||
// Names of modes, used for subnamespaces of edit: and name of binding table in
|
||||
// $edit:binding.
|
||||
// Names of modes, used for subnamespaces of edit:.
|
||||
const (
|
||||
modeInsert = "insert"
|
||||
modeRawInsert = "raw-insert"
|
||||
|
|
|
@ -40,10 +40,6 @@ var _ = registerBuiltins(modeNarrow, map[string]func(*Editor){
|
|||
"default": func(ed *Editor) { getNarrow(ed).defaultBinding(ed) },
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeNarrow, modeNarrow, nil)
|
||||
}
|
||||
|
||||
// narrow implements a listing mode that supports the notion of selecting an
|
||||
// entry and filtering entries.
|
||||
type narrow struct {
|
||||
|
|
|
@ -37,25 +37,6 @@ var _ = registerBuiltins(modeNavigation, map[string]func(*Editor){
|
|||
"default": navDefault,
|
||||
})
|
||||
|
||||
func init() {
|
||||
registerBindings(modeNavigation, modeNavigation, map[ui.Key]string{
|
||||
{ui.Up, 0}: "up",
|
||||
{ui.Down, 0}: "down",
|
||||
{ui.PageUp, 0}: "page-up",
|
||||
{ui.PageDown, 0}: "page-down",
|
||||
{ui.Left, 0}: "left",
|
||||
{ui.Right, 0}: "right",
|
||||
{ui.Up, ui.Alt}: "file-preview-up",
|
||||
{ui.Down, ui.Alt}: "file-preview-down",
|
||||
{ui.Enter, ui.Alt}: "insert-selected",
|
||||
{ui.Enter, 0}: "insert-selected-and-quit",
|
||||
{'H', ui.Ctrl}: "trigger-shown-hidden",
|
||||
{'F', ui.Ctrl}: "trigger-filter",
|
||||
{'[', ui.Ctrl}: "insert:start",
|
||||
ui.Default: "default",
|
||||
})
|
||||
}
|
||||
|
||||
type navigation struct {
|
||||
current *navColumn
|
||||
parent *navColumn
|
||||
|
|
|
@ -2,15 +2,10 @@ package edit
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/elves/elvish/edit/ui"
|
||||
"github.com/elves/elvish/eval"
|
||||
"github.com/elves/elvish/eval/types"
|
||||
"github.com/elves/elvish/eval/vartypes"
|
||||
"github.com/xiaq/persistent/hashmap"
|
||||
)
|
||||
|
||||
// This file contains several "registries", data structure that are written
|
||||
|
@ -67,49 +62,12 @@ func makeNsFromBuiltins(builtins map[string]*BuiltinFn) eval.Ns {
|
|||
return ns
|
||||
}
|
||||
|
||||
var keyBindings = map[string]map[ui.Key]eval.Fn{}
|
||||
|
||||
// registerBindings registers default bindings for a mode to initialize the
|
||||
// global keyBindings map. Builtin names are resolved in the defaultMod
|
||||
// subnamespace using information from builtinMaps. It should be called in init
|
||||
// functions.
|
||||
func registerBindings(
|
||||
mt string, defaultMod string, bindingData map[ui.Key]string) struct{} {
|
||||
|
||||
if _, ok := keyBindings[mt]; !ok {
|
||||
keyBindings[mt] = map[ui.Key]eval.Fn{}
|
||||
}
|
||||
for key, fullName := range bindingData {
|
||||
// break fullName into mod and name.
|
||||
var mod, name string
|
||||
nameParts := strings.SplitN(fullName, ":", 2)
|
||||
if len(nameParts) == 2 {
|
||||
mod, name = nameParts[0], nameParts[1]
|
||||
} else {
|
||||
mod, name = defaultMod, nameParts[0]
|
||||
}
|
||||
if m, ok := builtinMaps[mod]; ok {
|
||||
if builtin, ok := m[name]; ok {
|
||||
keyBindings[mt][key] = builtin
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, "Internal warning: no such builtin", name, "in mod", mod)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, "Internal warning: no such mod:", mod)
|
||||
}
|
||||
}
|
||||
return struct{}{}
|
||||
}
|
||||
|
||||
func makeBindings() map[string]vartypes.Variable {
|
||||
bindings := make(map[string]vartypes.Variable)
|
||||
for mode, binding := range keyBindings {
|
||||
bindingValue := hashmap.Empty
|
||||
for key, fn := range binding {
|
||||
bindingValue = bindingValue.Assoc(key, fn)
|
||||
}
|
||||
bindings := map[string]vartypes.Variable{}
|
||||
// XXX This abuses the builtin registry to get a list of mode names
|
||||
for mode := range builtinMaps {
|
||||
bindings[mode] = vartypes.NewValidatedPtrVariable(
|
||||
BindingTable{types.NewMap(bindingValue)}, shouldBeBindingTable)
|
||||
BindingTable{types.EmptyMap}, shouldBeBindingTable)
|
||||
}
|
||||
return bindings
|
||||
}
|
||||
|
|
118
eval/bundled/binding.elv.go
Normal file
118
eval/bundled/binding.elv.go
Normal file
|
@ -0,0 +1,118 @@
|
|||
package bundled
|
||||
|
||||
const bindingElv = `
|
||||
fn install {
|
||||
edit:insert:binding = (edit:binding-table [
|
||||
&Default= $edit:insert:default~
|
||||
&F2= $edit:toggle-quote-paste~
|
||||
&Up= $edit:history:start~
|
||||
&Down= $edit:end-of-history~
|
||||
&Right= $edit:move-dot-right~
|
||||
&Left= $edit:move-dot-left~
|
||||
&Home= $edit:move-dot-sol~
|
||||
&Delete= $edit:kill-rune-right~
|
||||
&End= $edit:move-dot-eol~
|
||||
&Tab= $edit:completion:smart-start~
|
||||
&Enter= $edit:smart-enter~
|
||||
&Backspace= $edit:kill-rune-left~
|
||||
&Alt-Up= $edit:move-dot-up~
|
||||
&Alt-Down= $edit:move-dot-down~
|
||||
&Alt-Enter= $edit:insert-key~
|
||||
&Alt-.= $edit:insert-last-word~
|
||||
&Alt-1= $edit:lastcmd:start~
|
||||
&Alt-b= $edit:move-dot-left-word~
|
||||
&Alt-f= $edit:move-dot-right-word~
|
||||
&Ctrl-Right= $edit:move-dot-right-word~
|
||||
&Ctrl-Left= $edit:move-dot-left-word~
|
||||
&Ctrl-D= $edit:return-eof~
|
||||
&Ctrl-H= $edit:kill-rune-left~
|
||||
&Ctrl-K= $edit:kill-line-right~
|
||||
&Ctrl-L= $edit:location:start~
|
||||
&Ctrl-N= $edit:navigation:start~
|
||||
&Ctrl-R= $edit:histlist:start~
|
||||
&Ctrl-U= $edit:kill-line-left~
|
||||
&Ctrl-V= $edit:insert-raw~
|
||||
&Ctrl-W= $edit:kill-word-left~
|
||||
])
|
||||
|
||||
edit:command:binding = (edit:binding-table [
|
||||
&Default= $edit:command:default~
|
||||
&'$'= $edit:move-dot-eol~
|
||||
&0= $edit:move-dot-sol~
|
||||
&D= $edit:kill-line-right~
|
||||
&b= $edit:move-dot-left-word~
|
||||
&h= $edit:move-dot-left~
|
||||
&i= $edit:insert:start~
|
||||
&j= $edit:move-dot-down~
|
||||
&k= $edit:move-dot-up~
|
||||
&l= $edit:move-dot-right~
|
||||
&w= $edit:move-dot-right-word~
|
||||
&x= $edit:kill-rune-right~
|
||||
])
|
||||
|
||||
edit:history:binding = (edit:binding-table [
|
||||
&Default= $edit:history:default~
|
||||
&Up= $edit:history:up~
|
||||
&Down= $edit:history:down-or-quit~
|
||||
&Ctrl-R= $edit:history:switch-to-histlist~
|
||||
&'Ctrl-['= $edit:insert:start~
|
||||
])
|
||||
|
||||
edit:completion:binding = (edit:binding-table [
|
||||
&Default= $edit:completion:default~
|
||||
&Up= $edit:completion:up~
|
||||
&Down= $edit:completion:down~
|
||||
&Right= $edit:completion:right~
|
||||
&Left= $edit:completion:left~
|
||||
&Tab= $edit:completion:down-cycle~
|
||||
&Enter= $edit:completion:accept~
|
||||
&Shift-Tab= $edit:completion:up-cycle~
|
||||
&Ctrl-F= $edit:completion:trigger-filter~
|
||||
&'Ctrl-['= $edit:insert:start~
|
||||
])
|
||||
|
||||
edit:listing:binding = (edit:binding-table [
|
||||
&Default= $edit:listing:default~
|
||||
&Up= $edit:listing:up~
|
||||
&Down= $edit:listing:down~
|
||||
&PageUp= $edit:listing:page-up~
|
||||
&PageDown= $edit:listing:page-down~
|
||||
&Tab= $edit:listing:down-cycle~
|
||||
&Enter= $edit:listing:accept-close~
|
||||
&Backspace= $edit:listing:backspace~
|
||||
&Shift-Tab= $edit:listing:up-cycle~
|
||||
&Alt-Enter= $edit:listing:accept~
|
||||
&'Ctrl-['= $edit:insert:start~
|
||||
])
|
||||
|
||||
edit:histlist:binding = (edit:binding-table [
|
||||
&Ctrl-D= $edit:histlist:toggle-dedup~
|
||||
&Ctrl-G= $edit:histlist:toggle-case-sensitivity~
|
||||
])
|
||||
|
||||
edit:location:binding = (edit:binding-table [&])
|
||||
|
||||
edit:lastcmd:binding = (edit:binding-table [
|
||||
&Default= $edit:lastcmd:alt-default~
|
||||
])
|
||||
|
||||
edit:navigation:binding = (edit:binding-table [
|
||||
&Default= $edit:navigation:default~
|
||||
&Up= $edit:navigation:up~
|
||||
&Down= $edit:navigation:down~
|
||||
&Right= $edit:navigation:right~
|
||||
&Left= $edit:navigation:left~
|
||||
&PageUp= $edit:navigation:page-up~
|
||||
&PageDown= $edit:navigation:page-down~
|
||||
&Enter= $edit:navigation:insert-selected-and-quit~
|
||||
&Alt-Up= $edit:navigation:file-preview-up~
|
||||
&Alt-Down= $edit:navigation:file-preview-down~
|
||||
&Alt-Enter= $edit:navigation:insert-selected~
|
||||
&Ctrl-F= $edit:navigation:trigger-filter~
|
||||
&Ctrl-H= $edit:navigation:trigger-shown-hidden~
|
||||
&'Ctrl-['= $edit:insert:start~
|
||||
])
|
||||
|
||||
edit:narrow:binding = (edit:binding-table [&])
|
||||
}
|
||||
`
|
|
@ -4,6 +4,7 @@ package bundled
|
|||
// Get returns a map of bundled modules.
|
||||
func Get() map[string]string {
|
||||
return map[string]string{
|
||||
"binding": bindingElv,
|
||||
"epm": epmElv,
|
||||
"narrow": narrowElv,
|
||||
"readline-binding": readlineBindingElv,
|
||||
|
|
Loading…
Reference in New Issue
Block a user