diff --git a/api.go b/api.go index 9c3181e..dfd413b 100644 --- a/api.go +++ b/api.go @@ -35,7 +35,7 @@ var exports = map[string]util.LuaExport{ "hinter": {hlhinter, 1, false}, "multiprompt": {hlmultiprompt, 1, false}, "prependPath": {hlprependPath, 1, false}, - "prompt": {hlprompt, 1, false}, + "prompt": {hlprompt, 1, true}, "inputMode": {hlinputMode, 1, false}, "interval": {hlinterval, 2, false}, "read": {hlread, 1, false}, @@ -305,7 +305,7 @@ func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { } /* -prompt(str) +prompt(str, typ?) Changes the shell prompt to `str` There are a few verbs that can be used in the prompt text. These will be formatted and replaced with the appropriate values. @@ -313,17 +313,34 @@ These will be formatted and replaced with the appropriate values. `%u` - Name of current user `%h` - Hostname of device --- @param str string +--- @param typ string Type of prompt, being left or right. Left by default. */ func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { - var prompt string err := c.Check1Arg() - if err == nil { - prompt, err = c.StringArg(0) - } if err != nil { return nil, err } - lr.SetPrompt(fmtPrompt(prompt)) + p, err := c.StringArg(0) + if err != nil { + return nil, err + } + typ := "left" + if len(c.Etc()) != 0 { + ltyp := c.Etc()[0] + var ok bool + typ, ok = ltyp.TryString() + if !ok { + return nil, errors.New("bad argument to run (expected string, got " + ltyp.TypeName() + ")") + } + } + + switch typ { + case "left": + prompt = p + lr.SetPrompt(fmtPrompt(prompt)) + case "right": lr.SetRightPrompt(fmtPrompt(p)) + default: return nil, errors.New("expected prompt type to be right or left, got " + typ) + } return c.Next(), nil } diff --git a/readline/instance.go b/readline/instance.go index 2530071..ec6b861 100644 --- a/readline/instance.go +++ b/readline/instance.go @@ -30,11 +30,13 @@ type Instance struct { Multiline bool // If set to true, the shell will have a two-line prompt. MultilinePrompt string // If multiline is true, this is the content of the 2nd line. - mainPrompt string // If multiline true, the full prompt string / If false, the 1st line of the prompt - realPrompt []rune // The prompt that is actually on the same line as the beginning of the input line. - defaultPrompt []rune - promptLen int - stillOnRefresh bool // True if some logs have printed asynchronously since last loop. Check refresh prompt funcs + mainPrompt string // If multiline true, the full prompt string / If false, the 1st line of the prompt + rightPrompt string + rightPromptLen int + realPrompt []rune // The prompt that is actually on the same line as the beginning of the input line. + defaultPrompt []rune + promptLen int + stillOnRefresh bool // True if some logs have printed asynchronously since last loop. Check refresh prompt funcs // // Input Line --------------------------------------------------------------------------------- diff --git a/readline/prompt.go b/readline/prompt.go index 81738ac..699abec 100644 --- a/readline/prompt.go +++ b/readline/prompt.go @@ -14,6 +14,12 @@ func (rl *Instance) SetPrompt(s string) { rl.computePrompt() } +// SetRightPrompt sets the right prompt. +func (rl *Instance) SetRightPrompt(s string) { + rl.rightPrompt = s + " " + rl.computePrompt() +} + // RefreshPromptLog - A simple function to print a string message (a log, or more broadly, // an asynchronous event) without bothering the user, and by "pushing" the prompt below the message. func (rl *Instance) RefreshPromptLog(log string) (err error) { @@ -185,6 +191,7 @@ func (rl *Instance) computePrompt() (prompt []rune) { // Strip color escapes rl.promptLen = getRealLength(string(rl.realPrompt)) + rl.rightPromptLen = getRealLength(string(rl.rightPrompt)) return } @@ -205,3 +212,11 @@ func getRealLength(s string) (l int) { stripped := ansi.Strip(s) return uniseg.GraphemeClusterCount(stripped) } + +func (rl *Instance) echoRightPrompt() { + if rl.fullX < GetTermWidth() - rl.rightPromptLen - 1 { + moveCursorForwards(GetTermWidth()) + moveCursorBackwards(rl.rightPromptLen) + print(rl.rightPrompt) + } +} diff --git a/readline/readline.go b/readline/readline.go index 939b288..129d5c7 100644 --- a/readline/readline.go +++ b/readline/readline.go @@ -564,6 +564,8 @@ func (rl *Instance) editorInput(r []rune) { rl.writeHintText() } + rl.echoRightPrompt() + if len(rl.multisplit) == 0 { rl.syntaxCompletion() } diff --git a/readline/update.go b/readline/update.go index 979dbc9..40ff067 100644 --- a/readline/update.go +++ b/readline/update.go @@ -121,6 +121,8 @@ func (rl *Instance) renderHelpers() { rl.writeHintText() } + rl.echoRightPrompt() + // Go at beginning of first line after input remainder moveCursorDown(rl.fullY - rl.posY) moveCursorBackwards(GetTermWidth()) diff --git a/rl.go b/rl.go index 08efcc7..8975877 100644 --- a/rl.go +++ b/rl.go @@ -281,6 +281,13 @@ func (lr *lineReader) SetPrompt(p string) { } } +func (lr *lineReader) SetRightPrompt(p string) { + lr.rl.SetRightPrompt(p) + if initialized && !running { + lr.rl.RefreshPromptInPlace("") + } +} + func (lr *lineReader) AddHistory(cmd string) { fileHist.Write(cmd) }