Allow search query longer than the screen width

By implementing horizontal scrolling of the prompt line.
Maximum length is hard-coded to 300-chars.

Close #1312
Fix #1225
This commit is contained in:
Junegunn Choi
2018-06-25 19:07:12 +09:00
parent f0fe79dd3b
commit 0edbcbdf19
2 changed files with 39 additions and 17 deletions

View File

@@ -22,9 +22,10 @@ const (
readerPollIntervalMax = 50 * time.Millisecond readerPollIntervalMax = 50 * time.Millisecond
// Terminal // Terminal
initialDelay = 20 * time.Millisecond initialDelay = 20 * time.Millisecond
initialDelayTac = 100 * time.Millisecond initialDelayTac = 100 * time.Millisecond
spinnerDuration = 200 * time.Millisecond spinnerDuration = 200 * time.Millisecond
maxPatternLength = 300
// Matcher // Matcher
numPartitionsMultiplier = 8 numPartitionsMultiplier = 8

View File

@@ -59,6 +59,7 @@ type Terminal struct {
inlineInfo bool inlineInfo bool
prompt string prompt string
promptLen int promptLen int
queryLen [2]int
layout layoutType layout layoutType
fullscreen bool fullscreen bool
hscroll bool hscroll bool
@@ -68,6 +69,7 @@ type Terminal struct {
cx int cx int
cy int cy int
offset int offset int
xoffset int
yanked []rune yanked []rune
input []rune input []rune
multi bool multi bool
@@ -364,6 +366,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
t := Terminal{ t := Terminal{
initDelay: delay, initDelay: delay,
inlineInfo: opts.InlineInfo, inlineInfo: opts.InlineInfo,
queryLen: [2]int{0, 0},
layout: opts.Layout, layout: opts.Layout,
fullscreen: fullscreen, fullscreen: fullscreen,
hscroll: opts.Hscroll, hscroll: opts.Hscroll,
@@ -373,6 +376,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
cx: len(input), cx: len(input),
cy: 0, cy: 0,
offset: 0, offset: 0,
xoffset: 0,
yanked: []rune{}, yanked: []rune{},
input: input, input: input,
multi: opts.Multi, multi: opts.Multi,
@@ -640,7 +644,6 @@ func (t *Terminal) resizeWindows() {
for i := 0; i < t.window.Height(); i++ { for i := 0; i < t.window.Height(); i++ {
t.window.MoveAndClear(i, 0) t.window.MoveAndClear(i, 0)
} }
t.truncateQuery()
} }
func (t *Terminal) move(y int, x int, clear bool) { func (t *Terminal) move(y int, x int, clear bool) {
@@ -668,20 +671,44 @@ func (t *Terminal) move(y int, x int, clear bool) {
} }
} }
func (t *Terminal) truncateQuery() {
t.input, _ = t.trimRight(t.input, maxPatternLength)
t.cx = util.Constrain(t.cx, 0, len(t.input))
}
func (t *Terminal) updatePromptOffset() ([]rune, []rune) {
maxWidth := util.Max(1, t.window.Width()-t.promptLen-1)
_, overflow := t.trimLeft(t.input[:t.cx], maxWidth)
minOffset := int(overflow)
maxOffset := util.Min(util.Min(len(t.input), minOffset+maxWidth), t.cx)
t.xoffset = util.Constrain(t.xoffset, minOffset, maxOffset)
before, _ := t.trimLeft(t.input[t.xoffset:t.cx], maxWidth)
beforeLen := t.displayWidth(before)
after, _ := t.trimRight(t.input[t.cx:], maxWidth-beforeLen)
afterLen := t.displayWidth(after)
t.queryLen = [2]int{beforeLen, afterLen}
return before, after
}
func (t *Terminal) placeCursor() { func (t *Terminal) placeCursor() {
t.move(0, t.promptLen+t.displayWidth(t.input[:t.cx]), false) t.move(0, t.promptLen+t.queryLen[0], false)
} }
func (t *Terminal) printPrompt() { func (t *Terminal) printPrompt() {
t.move(0, 0, true) t.move(0, 0, true)
t.window.CPrint(tui.ColPrompt, t.strong, t.prompt) t.window.CPrint(tui.ColPrompt, t.strong, t.prompt)
t.window.CPrint(tui.ColNormal, t.strong, string(t.input))
before, after := t.updatePromptOffset()
t.window.CPrint(tui.ColNormal, t.strong, string(before))
t.window.CPrint(tui.ColNormal, t.strong, string(after))
} }
func (t *Terminal) printInfo() { func (t *Terminal) printInfo() {
pos := 0 pos := 0
if t.inlineInfo { if t.inlineInfo {
pos = t.promptLen + t.displayWidth(t.input) + 1 pos = t.promptLen + t.queryLen[0] + t.queryLen[1] + 1
if pos+len(" < ") > t.window.Width() { if pos+len(" < ") > t.window.Width() {
return return
} }
@@ -1334,12 +1361,6 @@ func (t *Terminal) buildPlusList(template string, forcePlus bool) (bool, []*Item
return true, sels return true, sels
} }
func (t *Terminal) truncateQuery() {
maxPatternLength := util.Max(1, t.window.Width()-t.promptLen-1)
t.input, _ = t.trimRight(t.input, maxPatternLength)
t.cx = util.Constrain(t.cx, 0, len(t.input))
}
func (t *Terminal) selectItem(item *Item) { func (t *Terminal) selectItem(item *Item) {
t.selected[item.Index()] = selectedItem{time.Now(), item} t.selected[item.Index()] = selectedItem{time.Now(), item}
t.version++ t.version++
@@ -1392,10 +1413,10 @@ func (t *Terminal) Loop() {
t.initFunc() t.initFunc()
t.resizeWindows() t.resizeWindows()
t.printPrompt() t.printPrompt()
t.placeCursor()
t.refresh()
t.printInfo() t.printInfo()
t.printHeader() t.printHeader()
t.placeCursor()
t.refresh()
t.mutex.Unlock() t.mutex.Unlock()
go func() { go func() {
timer := time.NewTimer(t.initDelay) timer := time.NewTimer(t.initDelay)
@@ -1529,9 +1550,9 @@ func (t *Terminal) Loop() {
} }
} }
t.placeCursor() t.placeCursor()
t.refresh()
t.mutex.Unlock() t.mutex.Unlock()
}) })
t.refresh()
} }
}() }()
@@ -1852,7 +1873,7 @@ func (t *Terminal) Loop() {
} else if me.Down { } else if me.Down {
if my == 0 && mx >= 0 { if my == 0 && mx >= 0 {
// Prompt // Prompt
t.cx = mx t.cx = mx + t.xoffset
} else if my >= min { } else if my >= min {
// List // List
if t.vset(t.offset+my-min) && t.multi && me.Mod { if t.vset(t.offset+my-min) && t.multi && me.Mod {