feat: add right prompt (#140)

* feat: add right prompt (closes #111)

* chore: add comment for set right prompt function

* fix: add 1 space at the end of right prompt to fix character cut off

* docs: update doc for prompt function
pull/143/head
sammyette 2022-04-13 10:13:46 -04:00 committed by GitHub
parent 626b036b4b
commit 0a2046e985
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 12 deletions

29
api.go
View File

@ -35,7 +35,7 @@ var exports = map[string]util.LuaExport{
"hinter": {hlhinter, 1, false}, "hinter": {hlhinter, 1, false},
"multiprompt": {hlmultiprompt, 1, false}, "multiprompt": {hlmultiprompt, 1, false},
"prependPath": {hlprependPath, 1, false}, "prependPath": {hlprependPath, 1, false},
"prompt": {hlprompt, 1, false}, "prompt": {hlprompt, 1, true},
"inputMode": {hlinputMode, 1, false}, "inputMode": {hlinputMode, 1, false},
"interval": {hlinterval, 2, false}, "interval": {hlinterval, 2, false},
"read": {hlread, 1, 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` Changes the shell prompt to `str`
There are a few verbs that can be used in the prompt text. There are a few verbs that can be used in the prompt text.
These will be formatted and replaced with the appropriate values. 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 `%u` - Name of current user
`%h` - Hostname of device `%h` - Hostname of device
--- @param str string --- @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) { func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
var prompt string
err := c.Check1Arg() err := c.Check1Arg()
if err == nil {
prompt, err = c.StringArg(0)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
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)) 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 return c.Next(), nil
} }

View File

@ -31,6 +31,8 @@ type Instance struct {
MultilinePrompt string // If multiline is true, this is the content of the 2nd line. 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 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. realPrompt []rune // The prompt that is actually on the same line as the beginning of the input line.
defaultPrompt []rune defaultPrompt []rune
promptLen int promptLen int

View File

@ -14,6 +14,12 @@ func (rl *Instance) SetPrompt(s string) {
rl.computePrompt() 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, // 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. // an asynchronous event) without bothering the user, and by "pushing" the prompt below the message.
func (rl *Instance) RefreshPromptLog(log string) (err error) { func (rl *Instance) RefreshPromptLog(log string) (err error) {
@ -185,6 +191,7 @@ func (rl *Instance) computePrompt() (prompt []rune) {
// Strip color escapes // Strip color escapes
rl.promptLen = getRealLength(string(rl.realPrompt)) rl.promptLen = getRealLength(string(rl.realPrompt))
rl.rightPromptLen = getRealLength(string(rl.rightPrompt))
return return
} }
@ -205,3 +212,11 @@ func getRealLength(s string) (l int) {
stripped := ansi.Strip(s) stripped := ansi.Strip(s)
return uniseg.GraphemeClusterCount(stripped) return uniseg.GraphemeClusterCount(stripped)
} }
func (rl *Instance) echoRightPrompt() {
if rl.fullX < GetTermWidth() - rl.rightPromptLen - 1 {
moveCursorForwards(GetTermWidth())
moveCursorBackwards(rl.rightPromptLen)
print(rl.rightPrompt)
}
}

View File

@ -564,6 +564,8 @@ func (rl *Instance) editorInput(r []rune) {
rl.writeHintText() rl.writeHintText()
} }
rl.echoRightPrompt()
if len(rl.multisplit) == 0 { if len(rl.multisplit) == 0 {
rl.syntaxCompletion() rl.syntaxCompletion()
} }

View File

@ -121,6 +121,8 @@ func (rl *Instance) renderHelpers() {
rl.writeHintText() rl.writeHintText()
} }
rl.echoRightPrompt()
// Go at beginning of first line after input remainder // Go at beginning of first line after input remainder
moveCursorDown(rl.fullY - rl.posY) moveCursorDown(rl.fullY - rl.posY)
moveCursorBackwards(GetTermWidth()) moveCursorBackwards(GetTermWidth())

7
rl.go
View File

@ -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) { func (lr *lineReader) AddHistory(cmd string) {
fileHist.Write(cmd) fileHist.Write(cmd)
} }