mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-04 10:57:50 +08:00
Prompt can now be customized by modifying le:{,r}prompt.
This fixes #103.
This commit is contained in:
parent
9d7e5de667
commit
67e4b5df11
|
@ -29,6 +29,8 @@ type Editor struct {
|
||||||
store *store.Store
|
store *store.Store
|
||||||
evaler *eval.Evaler
|
evaler *eval.Evaler
|
||||||
cmdSeq int
|
cmdSeq int
|
||||||
|
ps1 Prompt
|
||||||
|
rps1 Prompt
|
||||||
editorState
|
editorState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +95,8 @@ func NewEditor(file *os.File, sigs chan os.Signal, ev *eval.Evaler, st *store.St
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prompt, rprompt := defaultPrompts()
|
||||||
|
|
||||||
ed := &Editor{
|
ed := &Editor{
|
||||||
file: file,
|
file: file,
|
||||||
writer: newWriter(file),
|
writer: newWriter(file),
|
||||||
|
@ -101,6 +105,8 @@ func NewEditor(file *os.File, sigs chan os.Signal, ev *eval.Evaler, st *store.St
|
||||||
store: st,
|
store: st,
|
||||||
evaler: ev,
|
evaler: ev,
|
||||||
cmdSeq: seq,
|
cmdSeq: seq,
|
||||||
|
ps1: prompt,
|
||||||
|
rps1: rprompt,
|
||||||
}
|
}
|
||||||
ev.AddModule("le", makeModule(ed))
|
ev.AddModule("le", makeModule(ed))
|
||||||
return ed
|
return ed
|
||||||
|
@ -282,7 +288,7 @@ func (ed *Editor) finishReadLine(addError func(error)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadLine reads a line interactively.
|
// ReadLine reads a line interactively.
|
||||||
func (ed *Editor) ReadLine(prompt, rprompt func() string) (lr LineRead) {
|
func (ed *Editor) ReadLine() (lr LineRead) {
|
||||||
ed.editorState = editorState{active: true}
|
ed.editorState = editorState{active: true}
|
||||||
isExternalCh := make(chan map[string]bool, 1)
|
isExternalCh := make(chan map[string]bool, 1)
|
||||||
go getIsExternal(ed.evaler, isExternalCh)
|
go getIsExternal(ed.evaler, isExternalCh)
|
||||||
|
@ -302,8 +308,8 @@ func (ed *Editor) ReadLine(prompt, rprompt func() string) (lr LineRead) {
|
||||||
|
|
||||||
MainLoop:
|
MainLoop:
|
||||||
for {
|
for {
|
||||||
ed.prompt = prompt()
|
ed.prompt = ed.ps1.Call(ed)
|
||||||
ed.rprompt = rprompt()
|
ed.rprompt = ed.rps1.Call(ed)
|
||||||
|
|
||||||
err := ed.refresh(false, true)
|
err := ed.refresh(false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -39,6 +39,9 @@ func makeModule(ed *Editor) eval.Namespace {
|
||||||
|
|
||||||
ns["binding"] = eval.NewRoVariable(binding)
|
ns["binding"] = eval.NewRoVariable(binding)
|
||||||
|
|
||||||
|
ns["prompt"] = PromptVariable{&ed.ps1}
|
||||||
|
ns["rprompt"] = PromptVariable{&ed.rps1}
|
||||||
|
|
||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,36 @@ package edit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
|
|
||||||
"github.com/elves/elvish/eval"
|
"github.com/elves/elvish/eval"
|
||||||
|
"github.com/elves/elvish/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrPromptMustBeStringOrFunc = errors.New("prompt must be string or function")
|
||||||
|
|
||||||
|
// PromptVariable implements $le:prompt and $le:rprompt.
|
||||||
|
type PromptVariable struct {
|
||||||
|
Prompt *Prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pv PromptVariable) Get() eval.Value {
|
||||||
|
// XXX Should return a proper eval.Caller
|
||||||
|
return eval.String("<prompt>")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pv PromptVariable) Set(v eval.Value) {
|
||||||
|
if s, ok := v.(eval.String); ok {
|
||||||
|
*pv.Prompt = BuiltinPrompt(func(*Editor) string { return string(s) })
|
||||||
|
} else if c, ok := v.(eval.Caller); ok {
|
||||||
|
*pv.Prompt = CallerPrompt{c}
|
||||||
|
} else {
|
||||||
|
throw(ErrPromptMustBeStringOrFunc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prompt is the interface of prompt functions.
|
// Prompt is the interface of prompt functions.
|
||||||
type Prompt interface {
|
type Prompt interface {
|
||||||
Call(*Editor) string
|
Call(*Editor) string
|
||||||
|
@ -29,7 +54,7 @@ func (c CallerPrompt) Call(ed *Editor) string {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
ports := []*eval.Port{in, nil, &eval.Port{File: os.Stderr}}
|
ports := []*eval.Port{in, &eval.Port{File: os.Stdout}, &eval.Port{File: os.Stderr}}
|
||||||
|
|
||||||
// XXX There is no source to pass to NewTopEvalCtx.
|
// XXX There is no source to pass to NewTopEvalCtx.
|
||||||
ec := eval.NewTopEvalCtx(ed.evaler, "[editor prompt]", "", ports)
|
ec := eval.NewTopEvalCtx(ed.evaler, "[editor prompt]", "", ports)
|
||||||
|
@ -44,3 +69,24 @@ func (c CallerPrompt) Call(ed *Editor) string {
|
||||||
}
|
}
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func defaultPrompts() (Prompt, Prompt) {
|
||||||
|
// Make default prompts.
|
||||||
|
username := "???"
|
||||||
|
user, err := user.Current()
|
||||||
|
if err == nil {
|
||||||
|
username = user.Username
|
||||||
|
}
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
hostname = "???"
|
||||||
|
}
|
||||||
|
rpromptStr := username + "@" + hostname
|
||||||
|
prompt := func(*Editor) string {
|
||||||
|
return util.Getwd() + "> "
|
||||||
|
}
|
||||||
|
rprompt := func(*Editor) string {
|
||||||
|
return rpromptStr
|
||||||
|
}
|
||||||
|
return BuiltinPrompt(prompt), BuiltinPrompt(rprompt)
|
||||||
|
}
|
||||||
|
|
21
run/run.go
21
run/run.go
|
@ -8,7 +8,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"os/user"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -127,27 +126,9 @@ func interact(ev *eval.Evaler, st *store.Store) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build prompt and rprompt.
|
|
||||||
username := "???"
|
|
||||||
user, err := user.Current()
|
|
||||||
if err == nil {
|
|
||||||
username = user.Username
|
|
||||||
}
|
|
||||||
hostname, err := os.Hostname()
|
|
||||||
if err != nil {
|
|
||||||
hostname = "???"
|
|
||||||
}
|
|
||||||
rpromptStr := username + "@" + hostname
|
|
||||||
prompt := func() string {
|
|
||||||
return util.Getwd() + "> "
|
|
||||||
}
|
|
||||||
rprompt := func() string {
|
|
||||||
return rpromptStr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build readLine function.
|
// Build readLine function.
|
||||||
readLine := func() edit.LineRead {
|
readLine := func() edit.LineRead {
|
||||||
return ed.ReadLine(prompt, rprompt)
|
return ed.ReadLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
cooldown := time.Second
|
cooldown := time.Second
|
||||||
|
|
Loading…
Reference in New Issue
Block a user