Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.gemini
4 changes: 2 additions & 2 deletions inputrc/inputrc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func buildOpts(t *testing.T, buf []byte) []Option {
lines := bytes.Split(bytes.TrimSpace(buf), []byte{'\n'})
var opts []Option

for i := 0; i < len(lines); i++ {
for i := range lines {
line := bytes.TrimSpace(lines[i])
// If the line is empty, keep going
if len(line) == 0 {
Expand Down Expand Up @@ -406,4 +406,4 @@ func readTestdata(name string) ([]byte, error) {
}

//go:embed testdata/*.inputrc
var testdata embed.FS
var testdata embed.FS
6 changes: 3 additions & 3 deletions inputrc/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,11 +507,11 @@ func findStringEnd(seq []rune, pos, end int) (int, bool) {
quote := seq[pos]

for pos++; pos < end; pos++ {
switch char = seq[pos]; {
case char == '\\':
switch char = seq[pos]; char {
case '\\':
pos++
continue
case char == quote:
case quote:
return pos + 1, true
}
}
Expand Down
10 changes: 5 additions & 5 deletions internal/core/cursor.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,12 @@ func (c *Cursor) LineMove(lines int) {
}

if lines < 0 {
for i := 0; i < -1*lines; i++ {
for i := 0; i < -lines; i++ {
c.moveLineUp()
c.CheckCommand()
}
} else {
for i := 0; i < lines; i++ {
for range lines {
c.moveLineDown()
c.CheckCommand()
}
Expand Down Expand Up @@ -287,7 +287,7 @@ func (c *Cursor) AtBeginningOfLine() bool {

newlines := c.line.newlines()

for line := 0; line < len(newlines); line++ {
for line := range newlines {
epos := newlines[line][0]
if epos == c.pos-1 {
return true
Expand All @@ -306,7 +306,7 @@ func (c *Cursor) AtEndOfLine() bool {

newlines := c.line.newlines()

for line := 0; line < len(newlines); line++ {
for line := range newlines {
epos := newlines[line][0]
if epos == c.pos+1 {
return true
Expand Down Expand Up @@ -394,7 +394,7 @@ func (c *Cursor) moveLineDown() {

newlines := c.line.newlines()

for line := 0; line < len(newlines); line++ {
for line := range newlines {
end := newlines[line][0]
if line < c.LinePos() {
begin = end
Expand Down
3 changes: 2 additions & 1 deletion internal/core/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"regexp"
"sync"

"github.com/rivo/uniseg"

"github.com/reeflective/readline/inputrc"
"github.com/reeflective/readline/internal/strutil"
"github.com/rivo/uniseg"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion internal/core/selection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,7 @@ func TestSelection_SelectKeyword(t *testing.T) {
var gotKbpos, gotKepos int
var gotMatch bool

for i := 0; i < test.args.cycles; i++ {
for range test.args.cycles {
gotKbpos, gotKepos, gotMatch = sel.SelectKeyword(test.args.bpos, test.args.epos, test.args.next)
}

Expand Down
100 changes: 0 additions & 100 deletions internal/display/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,42 +66,6 @@ func Init(e *Engine, highlighter func([]rune) string) {
e.highlighter = highlighter
}

// Refresh recomputes and redisplays the entire readline interface, except
// the first lines of the primary prompt when the latter is a multiline one.
func (e *Engine) Refresh() {
fmt.Print(term.HideCursor)

// Go back to the first column, and if the primary prompt
// was not printed yet, back up to the line's beginning row.
term.MoveCursorBackwards(term.GetWidth())

if !e.primaryPrinted {
term.MoveCursorUp(e.cursorRow)
}

// Print either all or the last line of the prompt.
e.prompt.LastPrint()

// Get all positions required for the redisplay to come:
// prompt end (thus indentation), cursor positions, etc.
e.computeCoordinates(true)

// Print the line, and any of the secondary and right prompts.
e.displayLine()
e.displayMultilinePrompts()

// Display hints and completions, go back
// to the start of the line, then to cursor.
helpersMoved := e.displayHelpers()
if helpersMoved {
e.cursorHintToLineStart()
e.lineStartToCursorPos()
} else {
e.lineEndToCursorPos()
}
fmt.Print(term.ShowCursor)
}

// PrintPrimaryPrompt redraws the primary prompt.
// There are relatively few cases where you want to use this.
// It is currently only used when using clear-screen commands.
Expand Down Expand Up @@ -274,70 +238,6 @@ func (e *Engine) displayLine() {
}
}

func (e *Engine) displayMultilinePrompts() {
// If we have more than one line, write the columns.
if e.line.Lines() > 1 {
term.MoveCursorUp(e.lineRows)
term.MoveCursorBackwards(term.GetWidth())
e.prompt.MultilineColumnPrint()
}

// Then if we have a line at all, rewrite the last column
// character with any secondary prompt available.
if e.line.Lines() > 0 {
term.MoveCursorBackwards(term.GetWidth())
e.prompt.SecondaryPrint()
term.MoveCursorBackwards(term.GetWidth())
term.MoveCursorForwards(e.lineCol)
}

// Then prompt the right-sided prompt if possible.
e.prompt.RightPrint(e.lineCol, true)
}

// displayHelpers renders the hint and completion sections.
// It assumes that the cursor is on the last line of input,
// and goes back to this same line after displaying this.
func (e *Engine) displayHelpers() bool {
// Recompute completions and hints if autocompletion is on.
e.completer.Autocomplete()

hintRows := ui.CoordinatesHint(e.hint)
compMatches := e.completer.Matches()
compSkip := e.completer.DisplaySkipped()

if e.hintRows == 0 && e.compRows == 0 && hintRows == 0 && (compMatches == 0 || compSkip) {
return false
}

fmt.Print(term.NewlineReturn)

prevHintRows := e.hintRows
prevCompRows := e.compRows

// Display hint and completions.
ui.DisplayHint(e.hint)
e.hintRows = ui.CoordinatesHint(e.hint)
if compMatches > 0 && !compSkip {
completion.Display(e.completer, e.AvailableHelperLines())
e.compRows = completion.Coordinates(e.completer)
} else {
e.completer.ResetUsedRows()
e.compRows = 0
}

if e.hintRows+e.compRows < prevHintRows+prevCompRows {
fmt.Print(term.ClearScreenBelow)
}

// Go back to the first line below the input line.
term.MoveCursorBackwards(term.GetWidth())
term.MoveCursorUp(e.compRows)
term.MoveCursorUp(e.hintRows)

return true
}

// lineEndToCursorPos moves the cursor from the end of the input line
// to the current cursor position.
func (e *Engine) lineEndToCursorPos() {
Expand Down
8 changes: 6 additions & 2 deletions internal/display/highlight.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ func (e *Engine) highlightLine(line []rune, selection core.Selection) string {
var highlighted string

// And apply highlighting before each rune.
var highlightedSb25 strings.Builder

for i, r := range line {
if highlight, found := colors[i]; found {
highlighted += string(highlight)
highlightedSb25.WriteString(string(highlight))
}

highlighted += string(r)
highlightedSb25.WriteRune(r)
}

highlighted += highlightedSb25.String()

// Finally, highlight comments using a regex.
comment := strings.Trim(e.opts.GetString("comment-begin"), "\"")
commentPattern := fmt.Sprintf(`(^|\s)%s.*`, comment)
Expand Down
Loading
Loading