mirror of https://github.com/Hilbis/Hilbish
feat: add inline hint text and change what were hints previously to info (closes #126)
parent
577f00dfef
commit
6ea25a22b3
14
api.go
14
api.go
|
@ -28,6 +28,7 @@ var exports = map[string]lua.LGFunction {
|
|||
"exec": hlexec,
|
||||
"runnerMode": hlrunnerMode,
|
||||
"goro": hlgoro,
|
||||
"hinter": hlhinter,
|
||||
"multiprompt": hlmlprompt,
|
||||
"prependPath": hlprependPath,
|
||||
"prompt": hlprompt,
|
||||
|
@ -503,3 +504,16 @@ func hlrunnerMode(L *lua.LState) int {
|
|||
|
||||
return 0
|
||||
}
|
||||
|
||||
// hinter(cb)
|
||||
// Sets the hinter function. This will be called on every key insert to determine
|
||||
// what text to use as an inline hint. The callback is passed 2 arguments:
|
||||
// the current line and the position. It is expected to return a string
|
||||
// which will be used for the hint.
|
||||
// --- @param cb function
|
||||
func hlhinter(L *lua.LState) int {
|
||||
hinterCb := L.CheckFunction(1)
|
||||
hinter = hinterCb
|
||||
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ type EventReturn struct {
|
|||
ForwardKey bool
|
||||
ClearHelpers bool
|
||||
CloseReadline bool
|
||||
HintText []rune
|
||||
InfoText []rune
|
||||
NewLine []rune
|
||||
NewPos int
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ import "regexp"
|
|||
|
||||
// SetHintText - a nasty function to force writing a new hint text. It does not update helpers, it just renders
|
||||
// them, so the hint will survive until the helpers (thus including the hint) will be updated/recomputed.
|
||||
/*
|
||||
func (rl *Instance) SetHintText(s string) {
|
||||
rl.hintText = []rune(s)
|
||||
rl.renderHelpers()
|
||||
}
|
||||
*/
|
||||
|
||||
func (rl *Instance) getHintText() {
|
||||
|
||||
|
@ -27,7 +29,7 @@ func (rl *Instance) getHintText() {
|
|||
// writeHintText - only writes the hint text and computes its offsets.
|
||||
func (rl *Instance) writeHintText() {
|
||||
if len(rl.hintText) == 0 {
|
||||
rl.hintY = 0
|
||||
//rl.hintY = 0
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -41,16 +43,16 @@ func (rl *Instance) writeHintText() {
|
|||
|
||||
wrapped, hintLen := WrapText(string(rl.hintText), width)
|
||||
offset += hintLen
|
||||
rl.hintY = offset
|
||||
// rl.hintY = offset
|
||||
|
||||
hintText := string(wrapped)
|
||||
|
||||
if len(hintText) > 0 {
|
||||
print("\r" + rl.HintFormatting + string(hintText) + seqReset)
|
||||
print(rl.HintFormatting + string(hintText) + seqReset)
|
||||
}
|
||||
}
|
||||
|
||||
func (rl *Instance) resetHintText() {
|
||||
rl.hintY = 0
|
||||
//rl.hintY = 0
|
||||
rl.hintText = []rune{}
|
||||
}
|
||||
|
|
|
@ -183,13 +183,13 @@ func (rl *Instance) completeHistory() (hist []*CompletionGroup) {
|
|||
return
|
||||
}
|
||||
history = rl.altHistory
|
||||
rl.histHint = []rune(rl.altHistName + ": ")
|
||||
rl.histInfo = []rune(rl.altHistName + ": ")
|
||||
} else {
|
||||
if rl.mainHistory == nil {
|
||||
return
|
||||
}
|
||||
history = rl.mainHistory
|
||||
rl.histHint = []rune(rl.mainHistName + ": ")
|
||||
rl.histInfo = []rune(rl.mainHistName + ": ")
|
||||
}
|
||||
|
||||
hist[0].init(rl)
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package readline
|
||||
|
||||
import "regexp"
|
||||
|
||||
// SetInfoText - a nasty function to force writing a new info text. It does not update helpers, it just renders
|
||||
// them, so the info will survive until the helpers (thus including the info) will be updated/recomputed.
|
||||
func (rl *Instance) SetInfoText(s string) {
|
||||
rl.infoText = []rune(s)
|
||||
rl.renderHelpers()
|
||||
}
|
||||
|
||||
func (rl *Instance) getInfoText() {
|
||||
|
||||
if !rl.modeAutoFind && !rl.modeTabFind {
|
||||
// Return if no infos provided by the user/engine
|
||||
if rl.InfoText == nil {
|
||||
rl.resetInfoText()
|
||||
return
|
||||
}
|
||||
// The info text also works with the virtual completion line system.
|
||||
// This way, the info is also refreshed depending on what we are pointing
|
||||
// at with our cursor.
|
||||
rl.infoText = rl.InfoText(rl.getCompletionLine())
|
||||
}
|
||||
}
|
||||
|
||||
// writeInfoText - only writes the info text and computes its offsets.
|
||||
func (rl *Instance) writeInfoText() {
|
||||
if len(rl.infoText) == 0 {
|
||||
rl.infoY = 0
|
||||
return
|
||||
}
|
||||
|
||||
width := GetTermWidth()
|
||||
|
||||
// Wraps the line, and counts the number of newlines in the string,
|
||||
// adjusting the offset as well.
|
||||
re := regexp.MustCompile(`\r?\n`)
|
||||
newlines := re.Split(string(rl.infoText), -1)
|
||||
offset := len(newlines)
|
||||
|
||||
wrapped, infoLen := WrapText(string(rl.infoText), width)
|
||||
offset += infoLen
|
||||
rl.infoY = offset
|
||||
|
||||
infoText := string(wrapped)
|
||||
|
||||
if len(infoText) > 0 {
|
||||
print("\r" + rl.InfoFormatting + string(infoText) + seqReset)
|
||||
}
|
||||
}
|
||||
|
||||
func (rl *Instance) resetInfoText() {
|
||||
rl.infoY = 0
|
||||
rl.infoText = []rune{}
|
||||
}
|
|
@ -110,7 +110,7 @@ type Instance struct {
|
|||
searchMode FindMode // Used for varying hints, and underlying functions called
|
||||
regexSearch *regexp.Regexp // Holds the current search regex match
|
||||
mainHist bool // Which history stdin do we want
|
||||
histHint []rune // We store a hist hint, for dual history sources
|
||||
histInfo []rune // We store a piece of hist info, for dual history sources
|
||||
|
||||
//
|
||||
// History -----------------------------------------------------------------------------------
|
||||
|
@ -134,19 +134,33 @@ type Instance struct {
|
|||
histNavIdx int // Used for quick history navigation.
|
||||
|
||||
//
|
||||
// Hints -------------------------------------------------------------------------------------
|
||||
// Info -------------------------------------------------------------------------------------
|
||||
|
||||
// HintText is a helper function which displays hint text the prompt.
|
||||
// HintText takes the line input from the promt and the cursor position.
|
||||
// InfoText is a helper function which displays infio text below the prompt.
|
||||
// InfoText takes the line input from the prompt and the cursor position.
|
||||
// It returns the info text to display.
|
||||
InfoText func([]rune, int) []rune
|
||||
|
||||
// InfoColor is any ANSI escape codes you wish to use for info formatting. By
|
||||
// default this will just be blue.
|
||||
InfoFormatting string
|
||||
|
||||
infoText []rune // The actual info text
|
||||
infoY int // Offset to info, if it spans multiple lines
|
||||
|
||||
//
|
||||
// Hints -----------------------------------------------------------------------------------
|
||||
|
||||
// HintText is a helper function which displays hint text right after the user's input.
|
||||
// It takes the line input and cursor position.
|
||||
// It returns the hint text to display.
|
||||
HintText func([]rune, int) []rune
|
||||
|
||||
// HintColor any ANSI escape codes you wish to use for hint formatting. By
|
||||
// default this will just be blue.
|
||||
// HintFormatting is just a string to use as the formatting for the hint. By default
|
||||
// this will be a grey color.
|
||||
HintFormatting string
|
||||
|
||||
hintText []rune // The actual hint text
|
||||
hintY int // Offset to hints, if it spans multiple lines
|
||||
hintText []rune
|
||||
|
||||
//
|
||||
// Vim Operatng Parameters -------------------------------------------------------------------
|
||||
|
@ -205,7 +219,8 @@ func NewInstance() *Instance {
|
|||
rl.HistoryAutoWrite = true
|
||||
|
||||
// Others
|
||||
rl.HintFormatting = seqFgBlue
|
||||
rl.InfoFormatting = seqFgBlue
|
||||
rl.HintFormatting = "\x1b[2m"
|
||||
rl.evtKeyPress = make(map[string]func(string, []rune, int) *EventReturn)
|
||||
rl.TempDirectory = os.TempDir()
|
||||
|
||||
|
|
|
@ -57,9 +57,9 @@ func (rl *Instance) echo() {
|
|||
|
||||
// Print the input line with optional syntax highlighting
|
||||
if rl.SyntaxHighlighter != nil {
|
||||
print(rl.SyntaxHighlighter(line) + " ")
|
||||
print(rl.SyntaxHighlighter(line))
|
||||
} else {
|
||||
print(string(line) + " ")
|
||||
print(string(line))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ func (rl *Instance) RefreshPromptLog(log string) (err error) {
|
|||
// We adjust cursor movement, depending on which mode we're currently in.
|
||||
if !rl.modeTabCompletion {
|
||||
rl.tcUsedY = 1
|
||||
// Account for the hint line
|
||||
// Account for the info line
|
||||
} else if rl.modeTabCompletion && rl.modeAutoFind {
|
||||
rl.tcUsedY = 0
|
||||
} else {
|
||||
|
@ -40,7 +40,7 @@ func (rl *Instance) RefreshPromptLog(log string) (err error) {
|
|||
moveCursorUp(1)
|
||||
}
|
||||
rl.stillOnRefresh = true
|
||||
moveCursorUp(rl.hintY + rl.tcUsedY)
|
||||
moveCursorUp(rl.infoY + rl.tcUsedY)
|
||||
moveCursorBackwards(GetTermWidth())
|
||||
print("\r\n" + seqClearScreenBelow)
|
||||
|
||||
|
@ -73,7 +73,7 @@ func (rl *Instance) RefreshPromptInPlace(prompt string) (err error) {
|
|||
// Prompt data intependent
|
||||
if !rl.modeTabCompletion {
|
||||
rl.tcUsedY = 1
|
||||
// Account for the hint line
|
||||
// Account for the info line
|
||||
} else if rl.modeTabCompletion && rl.modeAutoFind {
|
||||
rl.tcUsedY = 0
|
||||
} else {
|
||||
|
@ -91,7 +91,7 @@ func (rl *Instance) RefreshPromptInPlace(prompt string) (err error) {
|
|||
|
||||
// Clear the input line and everything below
|
||||
print(seqClearLine)
|
||||
moveCursorUp(rl.hintY + rl.tcUsedY)
|
||||
moveCursorUp(rl.infoY + rl.tcUsedY)
|
||||
moveCursorBackwards(GetTermWidth())
|
||||
print("\r\n" + seqClearScreenBelow)
|
||||
|
||||
|
@ -118,7 +118,7 @@ func (rl *Instance) RefreshPromptCustom(prompt string, offset int, clearLine boo
|
|||
// We adjust cursor movement, depending on which mode we're currently in.
|
||||
if !rl.modeTabCompletion {
|
||||
rl.tcUsedY = 1
|
||||
} else if rl.modeTabCompletion && rl.modeAutoFind { // Account for the hint line
|
||||
} else if rl.modeTabCompletion && rl.modeAutoFind { // Account for the info line
|
||||
rl.tcUsedY = 0
|
||||
} else {
|
||||
rl.tcUsedY = 1
|
||||
|
|
|
@ -40,10 +40,10 @@ func (rl *Instance) Readline() (string, error) {
|
|||
rl.posY = 0
|
||||
rl.tcPrefix = ""
|
||||
|
||||
// Completion && hints init
|
||||
rl.resetHintText()
|
||||
// Completion && infos init
|
||||
rl.resetInfoText()
|
||||
rl.resetTabCompletion()
|
||||
rl.getHintText()
|
||||
rl.getInfoText()
|
||||
|
||||
// History Init
|
||||
// We need this set to the last command, so that we can access it quickly
|
||||
|
@ -63,7 +63,7 @@ func (rl *Instance) Readline() (string, error) {
|
|||
return string(rl.line), nil
|
||||
}
|
||||
|
||||
// Finally, print any hints or completions
|
||||
// Finally, print any info or completions
|
||||
// if the TabCompletion engines so desires
|
||||
rl.renderHelpers()
|
||||
|
||||
|
@ -128,8 +128,8 @@ func (rl *Instance) Readline() (string, error) {
|
|||
rl.updateHelpers()
|
||||
}
|
||||
|
||||
if len(ret.HintText) > 0 {
|
||||
rl.hintText = ret.HintText
|
||||
if len(ret.InfoText) > 0 {
|
||||
rl.infoText = ret.InfoText
|
||||
rl.clearHelpers()
|
||||
rl.renderHelpers()
|
||||
}
|
||||
|
@ -174,8 +174,8 @@ func (rl *Instance) Readline() (string, error) {
|
|||
}
|
||||
print(seqClearScreenBelow)
|
||||
|
||||
rl.resetHintText()
|
||||
rl.getHintText()
|
||||
rl.resetInfoText()
|
||||
rl.getInfoText()
|
||||
rl.renderHelpers()
|
||||
|
||||
// Line Editing ------------------------------------------------------------------------------------
|
||||
|
@ -533,6 +533,7 @@ func (rl *Instance) editorInput(r []rune) {
|
|||
// We don't need it when inserting text.
|
||||
rl.histNavIdx = 0
|
||||
rl.insert(r)
|
||||
rl.writeHintText()
|
||||
}
|
||||
|
||||
if len(rl.multisplit) == 0 {
|
||||
|
@ -696,6 +697,7 @@ func (rl *Instance) escapeSeq(r []rune) {
|
|||
rl.updateHelpers()
|
||||
return
|
||||
case seqCtrlRightArrow:
|
||||
rl.insert(rl.hintText)
|
||||
rl.moveCursorByAdjust(rl.viJumpW(tokeniseLine))
|
||||
rl.updateHelpers()
|
||||
return
|
||||
|
|
|
@ -259,9 +259,9 @@ func (r *registers) resetRegister() {
|
|||
// The user can show registers completions and insert, no matter the cursor position.
|
||||
func (rl *Instance) completeRegisters() (groups []*CompletionGroup) {
|
||||
|
||||
// We set the hint exceptionally
|
||||
hint := BLUE + "-- registers --" + RESET
|
||||
rl.hintText = []rune(hint)
|
||||
// We set the info exceptionally
|
||||
info := BLUE + "-- registers --" + RESET
|
||||
rl.infoText = []rune(info)
|
||||
|
||||
// Make the groups
|
||||
anonRegs := &CompletionGroup{
|
||||
|
|
|
@ -93,16 +93,16 @@ func (rl *Instance) getTabSearchCompletion() {
|
|||
}
|
||||
rl.getCurrentGroup()
|
||||
|
||||
// Set the hint for this completion mode
|
||||
rl.hintText = append([]rune("Completion search: "), rl.tfLine...)
|
||||
// Set the info for this completion mode
|
||||
rl.infoText = append([]rune("Completion search: "), rl.tfLine...)
|
||||
|
||||
for _, g := range rl.tcGroups {
|
||||
g.updateTabFind(rl)
|
||||
}
|
||||
|
||||
// If total number of matches is zero, we directly change the hint, and return
|
||||
// If total number of matches is zero, we directly change the info, and return
|
||||
if comps, _, _ := rl.getCompletionCount(); comps == 0 {
|
||||
rl.hintText = append(rl.hintText, []rune(DIM+RED+" ! no matches (Ctrl-G/Esc to cancel)"+RESET)...)
|
||||
rl.infoText = append(rl.infoText, []rune(DIM+RED+" ! no matches (Ctrl-G/Esc to cancel)"+RESET)...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,25 +117,25 @@ func (rl *Instance) getHistorySearchCompletion() {
|
|||
rl.tcGroups = checkNilItems(rl.tcGroups) // Avoid nil maps in groups
|
||||
rl.getCurrentGroup() // Make sure there is a current group
|
||||
|
||||
// The history hint is already set, but overwrite it if we don't have completions
|
||||
// The history info is already set, but overwrite it if we don't have completions
|
||||
if len(rl.tcGroups[0].Suggestions) == 0 {
|
||||
rl.histHint = []rune(fmt.Sprintf("%s%s%s %s", DIM, RED,
|
||||
rl.histInfo = []rune(fmt.Sprintf("%s%s%s %s", DIM, RED,
|
||||
"No command history source, or empty (Ctrl-G/Esc to cancel)", RESET))
|
||||
rl.hintText = rl.histHint
|
||||
rl.infoText = rl.histInfo
|
||||
return
|
||||
}
|
||||
|
||||
// Set the hint line with everything
|
||||
rl.histHint = append([]rune("\033[38;5;183m"+string(rl.histHint)+RESET), rl.tfLine...)
|
||||
rl.histHint = append(rl.histHint, []rune(RESET)...)
|
||||
rl.hintText = rl.histHint
|
||||
// Set the info line with everything
|
||||
rl.histInfo = append([]rune("\033[38;5;183m"+string(rl.histInfo)+RESET), rl.tfLine...)
|
||||
rl.histInfo = append(rl.histInfo, []rune(RESET)...)
|
||||
rl.infoText = rl.histInfo
|
||||
|
||||
// Refresh filtered candidates
|
||||
rl.tcGroups[0].updateTabFind(rl)
|
||||
|
||||
// If no items matched history, add hint text that we failed to search
|
||||
// If no items matched history, add info text that we failed to search
|
||||
if len(rl.tcGroups[0].Suggestions) == 0 {
|
||||
rl.hintText = append(rl.histHint, []rune(DIM+RED+" ! no matches (Ctrl-G/Esc to cancel)"+RESET)...)
|
||||
rl.infoText = append(rl.histInfo, []rune(DIM+RED+" ! no matches (Ctrl-G/Esc to cancel)"+RESET)...)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -298,15 +298,15 @@ func (rl *Instance) cropCompletions(comps string) (cropped string, usedY int) {
|
|||
// Else we go on, but we have more comps than what allowed:
|
||||
// we will add a line to the end of the comps, giving the actualized
|
||||
// number of completions remaining and not printed
|
||||
var moreComps = func(cropped string, offset int) (hinted string, noHint bool) {
|
||||
var moreComps = func(cropped string, offset int) (infoed string, noInfo bool) {
|
||||
_, _, adjusted := rl.getCompletionCount()
|
||||
remain := adjusted - offset
|
||||
if remain == 0 {
|
||||
return cropped, true
|
||||
}
|
||||
hint := fmt.Sprintf(DIM+YELLOW+" %d more completions... (scroll down to show)"+RESET+"\n", remain)
|
||||
hinted = cropped + hint
|
||||
return hinted, false
|
||||
info := fmt.Sprintf(DIM+YELLOW+" %d more completions... (scroll down to show)"+RESET+"\n", remain)
|
||||
infoed = cropped + info
|
||||
return infoed, false
|
||||
}
|
||||
|
||||
// Get the current absolute candidate position (prev groups x suggestions + curGroup.tcPosY)
|
||||
|
@ -509,7 +509,7 @@ func (rl *Instance) hasOneCandidate() bool {
|
|||
// - The terminal lengh
|
||||
// we use this function to prompt for confirmation before printing comps.
|
||||
func (rl *Instance) promptCompletionConfirm(sentence string) {
|
||||
rl.hintText = []rune(sentence)
|
||||
rl.infoText = []rune(sentence)
|
||||
|
||||
rl.compConfirmWait = true
|
||||
rl.viUndoSkipAppend = true
|
||||
|
|
|
@ -33,7 +33,7 @@ func (rl *Instance) updateTabFind(r []rune) {
|
|||
var err error
|
||||
rl.regexSearch, err = regexp.Compile("(?i)" + string(rl.tfLine))
|
||||
if err != nil {
|
||||
rl.hintText = []rune(Red("Failed to match search regexp"))
|
||||
rl.infoText = []rune(Red("Failed to match search regexp"))
|
||||
}
|
||||
|
||||
// We update and print
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package readline
|
||||
|
||||
// updateHelpers is a key part of the whole refresh process:
|
||||
// it should coordinate reprinting the input line, any hints and completions
|
||||
// it should coordinate reprinting the input line, any Infos and completions
|
||||
// and manage to get back to the current (computed) cursor coordinates
|
||||
func (rl *Instance) updateHelpers() {
|
||||
|
||||
// Load all hints & completions before anything.
|
||||
// Thus overwrites anything having been dirtily added/forced/modified, like rl.SetHintText()
|
||||
// Load all Infos & completions before anything.
|
||||
// Thus overwrites anything having been dirtily added/forced/modified, like rl.SetInfoText()
|
||||
rl.getInfoText()
|
||||
rl.getHintText()
|
||||
if rl.modeTabCompletion {
|
||||
rl.getTabCompletion()
|
||||
|
@ -75,11 +76,11 @@ func (rl *Instance) resetHelpers() {
|
|||
rl.modeAutoFind = false
|
||||
|
||||
// Now reset all below-input helpers
|
||||
rl.resetHintText()
|
||||
rl.resetInfoText()
|
||||
rl.resetTabCompletion()
|
||||
}
|
||||
|
||||
// clearHelpers - Clears everything: prompt, input, hints & comps,
|
||||
// clearHelpers - Clears everything: prompt, input, Infos & comps,
|
||||
// and comes back at the prompt.
|
||||
func (rl *Instance) clearHelpers() {
|
||||
|
||||
|
@ -97,25 +98,40 @@ func (rl *Instance) clearHelpers() {
|
|||
moveCursorForwards(rl.posX)
|
||||
}
|
||||
|
||||
// renderHelpers - pritns all components (prompt, line, hints & comps)
|
||||
// renderHelpers - pritns all components (prompt, line, Infos & comps)
|
||||
// and replaces the cursor to its current position. This function never
|
||||
// computes or refreshes any value, except from inside the echo function.
|
||||
func (rl *Instance) renderHelpers() {
|
||||
|
||||
// Optional, because neutral on placement
|
||||
|
||||
// when the instance is in this state we want it to be "below" the user's
|
||||
// input for it to be aligned properly
|
||||
if !rl.compConfirmWait {
|
||||
rl.writeHintText()
|
||||
}
|
||||
rl.echo()
|
||||
if rl.modeTabCompletion {
|
||||
// in tab complete mode we want it to update
|
||||
// when something has been selected
|
||||
// (dynamic!!)
|
||||
rl.getHintText()
|
||||
rl.writeHintText()
|
||||
} else if !rl.compConfirmWait {
|
||||
// for the same reason above, do nothing here
|
||||
} else {
|
||||
rl.writeHintText()
|
||||
}
|
||||
|
||||
// Go at beginning of first line after input remainder
|
||||
moveCursorDown(rl.fullY - rl.posY)
|
||||
moveCursorBackwards(GetTermWidth())
|
||||
|
||||
// Print hints, check for any confirmation hint current.
|
||||
// (do not overwrite the confirmation question hint)
|
||||
// Print Infos, check for any confirmation Info current.
|
||||
// (do not overwrite the confirmation question Info)
|
||||
if !rl.compConfirmWait {
|
||||
if len(rl.hintText) > 0 {
|
||||
if len(rl.infoText) > 0 {
|
||||
print("\n")
|
||||
}
|
||||
rl.writeHintText()
|
||||
rl.writeInfoText()
|
||||
moveCursorBackwards(GetTermWidth())
|
||||
|
||||
// Print completions and go back to beginning of this line
|
||||
|
@ -126,17 +142,17 @@ func (rl *Instance) renderHelpers() {
|
|||
}
|
||||
|
||||
// If we are still waiting for the user to confirm too long completions
|
||||
// Immediately refresh the hints
|
||||
// Immediately refresh the Infos
|
||||
if rl.compConfirmWait {
|
||||
print("\n")
|
||||
rl.writeHintText()
|
||||
rl.getHintText()
|
||||
rl.writeInfoText()
|
||||
rl.getInfoText()
|
||||
moveCursorBackwards(GetTermWidth())
|
||||
}
|
||||
|
||||
// Anyway, compensate for hint printout
|
||||
if len(rl.hintText) > 0 {
|
||||
moveCursorUp(rl.hintY)
|
||||
// Anyway, compensate for Info printout
|
||||
if len(rl.infoText) > 0 {
|
||||
moveCursorUp(rl.infoY)
|
||||
} else if !rl.compConfirmWait {
|
||||
moveCursorUp(1)
|
||||
} else if rl.compConfirmWait {
|
||||
|
|
|
@ -399,22 +399,22 @@ func (rl *Instance) refreshVimStatus() {
|
|||
rl.updateHelpers()
|
||||
}
|
||||
|
||||
// viHintMessage - lmorg's way of showing Vim status is to overwrite the hint.
|
||||
// viInfoMessage - lmorg's way of showing Vim status is to overwrite the info.
|
||||
// Currently not used, as there is a possibility to show the current Vim mode in the prompt.
|
||||
func (rl *Instance) viHintMessage() {
|
||||
func (rl *Instance) viInfoMessage() {
|
||||
switch rl.modeViMode {
|
||||
case VimKeys:
|
||||
rl.hintText = []rune("-- VIM KEYS -- (press `i` to return to normal editing mode)")
|
||||
rl.infoText = []rune("-- VIM KEYS -- (press `i` to return to normal editing mode)")
|
||||
case VimInsert:
|
||||
rl.hintText = []rune("-- INSERT --")
|
||||
rl.infoText = []rune("-- INSERT --")
|
||||
case VimReplaceOnce:
|
||||
rl.hintText = []rune("-- REPLACE CHARACTER --")
|
||||
rl.infoText = []rune("-- REPLACE CHARACTER --")
|
||||
case VimReplaceMany:
|
||||
rl.hintText = []rune("-- REPLACE --")
|
||||
rl.infoText = []rune("-- REPLACE --")
|
||||
case VimDelete:
|
||||
rl.hintText = []rune("-- DELETE --")
|
||||
rl.infoText = []rune("-- DELETE --")
|
||||
default:
|
||||
rl.getHintText()
|
||||
rl.getInfoText()
|
||||
}
|
||||
|
||||
rl.clearHelpers()
|
||||
|
|
|
@ -33,7 +33,7 @@ func (rl *Instance) viDelete(r rune) {
|
|||
rl.saveBufToRegister(rl.line)
|
||||
rl.clearLine()
|
||||
rl.resetHelpers()
|
||||
rl.getHintText()
|
||||
rl.getInfoText()
|
||||
|
||||
case 'e':
|
||||
vii := rl.getViIterations()
|
||||
|
|
24
rl.go
24
rl.go
|
@ -13,6 +13,7 @@ type lineReader struct {
|
|||
rl *readline.Instance
|
||||
}
|
||||
var fileHist *fileHistory
|
||||
var hinter lua.LValue
|
||||
|
||||
// other gophers might hate this naming but this is local, shut up
|
||||
func newLineReader(prompt string, noHist bool) *lineReader {
|
||||
|
@ -44,6 +45,25 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
|||
}
|
||||
hooks.Em.Emit("hilbish.vimAction", actionStr, args)
|
||||
}
|
||||
rl.HintText = func(line []rune, pos int) []rune {
|
||||
err := l.CallByParam(lua.P{
|
||||
Fn: hinter,
|
||||
NRet: 1,
|
||||
Protect: true,
|
||||
}, lua.LString(string(line)), lua.LNumber(pos))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return []rune{}
|
||||
}
|
||||
|
||||
retVal := l.Get(-1)
|
||||
hintText := ""
|
||||
if luaStr, ok := retVal.(lua.LString); retVal != lua.LNil && ok {
|
||||
hintText = luaStr.String()
|
||||
}
|
||||
|
||||
return []rune(hintText)
|
||||
}
|
||||
rl.TabCompleter = func(line []rune, pos int, _ readline.DelayedTabContext) (string, []*readline.CompletionGroup) {
|
||||
ctx := string(line)
|
||||
var completions []string
|
||||
|
@ -253,7 +273,7 @@ func (lr *lineReader) luaGetHistory(L *lua.LState) int {
|
|||
cmd, _ := fileHist.GetLine(idx)
|
||||
L.Push(lua.LString(cmd))
|
||||
|
||||
return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
func (lr *lineReader) luaAllHistory(L *lua.LState) int {
|
||||
|
@ -267,7 +287,7 @@ func (lr *lineReader) luaAllHistory(L *lua.LState) int {
|
|||
|
||||
L.Push(tbl)
|
||||
|
||||
return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
func (lr *lineReader) luaClearHistory(l *lua.LState) int {
|
||||
|
|
Loading…
Reference in New Issue