github.com/hoop33/elvish@v0.0.0-20160801152013-6d25485beab4/edit/prompt.go (about) 1 package edit 2 3 import ( 4 "bytes" 5 "errors" 6 "os" 7 "os/user" 8 9 "github.com/elves/elvish/eval" 10 "github.com/elves/elvish/util" 11 ) 12 13 var ErrPromptMustBeStringOrFunc = errors.New("prompt must be string or function") 14 15 // PromptVariable is a prompt function variable. It may be set to a String, a 16 // Fn, or a BuiltinPrompt. It provides $le:prompt and $le:rprompt. 17 type PromptVariable struct { 18 Prompt *Prompt 19 } 20 21 func (pv PromptVariable) Get() eval.Value { 22 // XXX Should return a proper eval.Fn 23 return eval.String("<prompt>") 24 } 25 26 func (pv PromptVariable) Set(v eval.Value) { 27 if s, ok := v.(eval.String); ok { 28 *pv.Prompt = BuiltinPrompt(func(*Editor) string { return string(s) }) 29 } else if c, ok := v.(eval.Fn); ok { 30 *pv.Prompt = FnAsPrompt{c} 31 } else { 32 throw(ErrPromptMustBeStringOrFunc) 33 } 34 } 35 36 // Prompt is the interface of prompt functions. 37 type Prompt interface { 38 Call(*Editor) string 39 } 40 41 // BuiltinPrompt is a trivial implementation of Prompt. 42 type BuiltinPrompt func(*Editor) string 43 44 func (bp BuiltinPrompt) Call(ed *Editor) string { 45 return bp(ed) 46 } 47 48 // FnAsPrompt adapts a eval.Fn to a Prompt. 49 type FnAsPrompt struct { 50 eval.Fn 51 } 52 53 func (c FnAsPrompt) Call(ed *Editor) string { 54 in, err := makeClosedStdin() 55 if err != nil { 56 return "" 57 } 58 ports := []*eval.Port{in, &eval.Port{File: os.Stdout}, &eval.Port{File: os.Stderr}} 59 60 // XXX There is no source to pass to NewTopEvalCtx. 61 ec := eval.NewTopEvalCtx(ed.evaler, "[editor prompt]", "", ports) 62 values, err := ec.PCaptureOutput(c.Fn, nil) 63 if err != nil { 64 ed.notify("prompt function error: %v", err) 65 return "" 66 } 67 var b bytes.Buffer 68 for _, v := range values { 69 b.WriteString(eval.ToString(v)) 70 } 71 return b.String() 72 } 73 74 func defaultPrompts() (Prompt, Prompt) { 75 // Make default prompts. 76 username := "???" 77 user, err := user.Current() 78 if err == nil { 79 username = user.Username 80 } 81 hostname, err := os.Hostname() 82 if err != nil { 83 hostname = "???" 84 } 85 rpromptStr := username + "@" + hostname 86 prompt := func(*Editor) string { 87 return util.Getwd() + "> " 88 } 89 rprompt := func(*Editor) string { 90 return rpromptStr 91 } 92 return BuiltinPrompt(prompt), BuiltinPrompt(rprompt) 93 }