mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-16 04:48:27 +08:00
d802ed3a70
There are just a handful of NewNs() uses and more than twenty Ns{} uses. NewNS() doesn't, and probably never will, do anything that can't done by the Ns{} syntax so we can simplify the code and improve consistency by removing it.
105 lines
2.7 KiB
Go
105 lines
2.7 KiB
Go
// Package edit implements the line editor for Elvish.
|
|
//
|
|
// The line editor is based on the cli package, which implements a general,
|
|
// Elvish-agnostic line editor, and multiple "addon" packages. This package
|
|
// glues them together and provides Elvish bindings for them.
|
|
package edit
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/elves/elvish/pkg/cli"
|
|
"github.com/elves/elvish/pkg/cli/histutil"
|
|
"github.com/elves/elvish/pkg/eval"
|
|
"github.com/elves/elvish/pkg/parse"
|
|
"github.com/elves/elvish/pkg/store"
|
|
)
|
|
|
|
// Editor is the interface line editor for Elvish.
|
|
type Editor struct {
|
|
app cli.App
|
|
ns eval.Ns
|
|
}
|
|
|
|
// NewEditor creates a new editor from input and output terminal files.
|
|
func NewEditor(tty cli.TTY, ev *eval.Evaler, st store.Store) *Editor {
|
|
ns := eval.Ns{}
|
|
appSpec := cli.AppSpec{TTY: tty}
|
|
|
|
fuser, err := histutil.NewFuser(st)
|
|
if err != nil {
|
|
// TODO(xiaq): Report the error.
|
|
}
|
|
|
|
if fuser != nil {
|
|
appSpec.AfterReadline = []func(string){func(code string) {
|
|
if code != "" && !strings.HasPrefix(code, " ") {
|
|
fuser.AddCmd(code)
|
|
}
|
|
// TODO(xiaq): Handle the error.
|
|
}}
|
|
}
|
|
|
|
// Make a variable for the app first. This is to work around the
|
|
// bootstrapping of initPrompts, which expects a notifier.
|
|
var app cli.App
|
|
initHighlighter(&appSpec, ev)
|
|
initConfigAPI(&appSpec, ev, ns)
|
|
initInsertAPI(&appSpec, appNotifier{&app}, ev, ns)
|
|
initPrompts(&appSpec, appNotifier{&app}, ev, ns)
|
|
app = cli.NewApp(appSpec)
|
|
|
|
initCommandAPI(app, ev, ns)
|
|
initListings(app, ev, ns, st, fuser)
|
|
initNavigation(app, ev, ns)
|
|
initCompletion(app, ev, ns)
|
|
initHistWalk(app, ev, ns, fuser)
|
|
initInstant(app, ev, ns)
|
|
initMinibuf(app, ev, ns)
|
|
|
|
initBufferBuiltins(app, ns)
|
|
initTTYBuiltins(app, tty, ns)
|
|
initMiscBuiltins(app, ns)
|
|
initStateAPI(app, ns)
|
|
initStoreAPI(app, ns, fuser)
|
|
evalDefaultBinding(ev, ns)
|
|
|
|
return &Editor{app, ns}
|
|
}
|
|
|
|
func evalDefaultBinding(ev *eval.Evaler, ns eval.Ns) {
|
|
// TODO(xiaq): The evaler API should accodomate the use case of evaluating a
|
|
// piece of code in an alternative global namespace.
|
|
|
|
n, err := parse.AsChunk("[default bindings]", defaultBindingsElv)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
src := eval.NewInternalElvishSource(
|
|
true, "[default bindings]", defaultBindingsElv)
|
|
op, err := ev.CompileWithGlobal(n, src, ns)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// TODO(xiaq): Use stdPorts when it is possible to do so.
|
|
fm := eval.NewTopFrame(ev, src, []*eval.Port{
|
|
{File: os.Stdin}, {File: os.Stdout}, {File: os.Stderr},
|
|
})
|
|
fm.SetLocal(ns)
|
|
err = fm.Eval(op)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// ReadCode reads input from the user.
|
|
func (ed *Editor) ReadCode() (string, error) {
|
|
return ed.app.ReadCode()
|
|
}
|
|
|
|
// Ns returns a namespace for manipulating the editor from Elvish code.
|
|
func (ed *Editor) Ns() eval.Ns {
|
|
return ed.ns
|
|
}
|