mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-14 06:13:47 -05:00
229
src/terminal.go
229
src/terminal.go
@@ -164,6 +164,7 @@ type eachLine struct {
|
||||
}
|
||||
|
||||
type itemLine struct {
|
||||
valid bool
|
||||
firstLine int
|
||||
numLines int
|
||||
cy int
|
||||
@@ -179,11 +180,15 @@ type itemLine struct {
|
||||
}
|
||||
|
||||
func (t *Terminal) markEmptyLine(line int) {
|
||||
t.prevLines[line] = itemLine{firstLine: line, empty: true}
|
||||
if t.window != t.inputWindow {
|
||||
t.prevLines[line] = itemLine{valid: true, firstLine: line, empty: true}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Terminal) markOtherLine(line int) {
|
||||
t.prevLines[line] = itemLine{firstLine: line, other: true}
|
||||
if t.window != t.inputWindow {
|
||||
t.prevLines[line] = itemLine{valid: true, firstLine: line, other: true}
|
||||
}
|
||||
}
|
||||
|
||||
type fitpad struct {
|
||||
@@ -241,6 +246,9 @@ type Terminal struct {
|
||||
previewLabel labelPrinter
|
||||
previewLabelLen int
|
||||
previewLabelOpts labelOpts
|
||||
inputLabel labelPrinter
|
||||
inputLabelLen int
|
||||
inputLabelOpts labelOpts
|
||||
pointer string
|
||||
pointerLen int
|
||||
pointerEmpty string
|
||||
@@ -298,6 +306,7 @@ type Terminal struct {
|
||||
listenUnsafe bool
|
||||
borderShape tui.BorderShape
|
||||
listBorderShape tui.BorderShape
|
||||
inputBorderShape tui.BorderShape
|
||||
listLabel labelPrinter
|
||||
listLabelLen int
|
||||
listLabelOpts labelOpts
|
||||
@@ -306,6 +315,8 @@ type Terminal struct {
|
||||
paused bool
|
||||
border tui.Window
|
||||
window tui.Window
|
||||
inputWindow tui.Window
|
||||
inputBorder tui.Window
|
||||
wborder tui.Window
|
||||
pborder tui.Window
|
||||
pwindow tui.Window
|
||||
@@ -394,6 +405,7 @@ const (
|
||||
reqReinit
|
||||
reqFullRedraw
|
||||
reqResize
|
||||
reqRedrawInputLabel
|
||||
reqRedrawListLabel
|
||||
reqRedrawBorderLabel
|
||||
reqRedrawPreviewLabel
|
||||
@@ -436,6 +448,7 @@ const (
|
||||
actCancel
|
||||
actChangeBorderLabel
|
||||
actChangeListLabel
|
||||
actChangeInputLabel
|
||||
actChangeHeader
|
||||
actChangeMulti
|
||||
actChangePreviewLabel
|
||||
@@ -497,6 +510,7 @@ const (
|
||||
actTransform
|
||||
actTransformBorderLabel
|
||||
actTransformListLabel
|
||||
actTransformInputLabel
|
||||
actTransformHeader
|
||||
actTransformPreviewLabel
|
||||
actTransformPrompt
|
||||
@@ -832,6 +846,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
||||
listenUnsafe: opts.Unsafe,
|
||||
borderShape: opts.BorderShape,
|
||||
listBorderShape: opts.ListBorderShape,
|
||||
inputBorderShape: opts.InputBorderShape,
|
||||
borderWidth: 1,
|
||||
listLabel: nil,
|
||||
listLabelOpts: opts.ListLabel,
|
||||
@@ -839,6 +854,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
||||
borderLabelOpts: opts.BorderLabel,
|
||||
previewLabel: nil,
|
||||
previewLabelOpts: opts.PreviewLabel,
|
||||
inputLabel: nil,
|
||||
inputLabelOpts: opts.InputLabel,
|
||||
cleanExit: opts.ClearOnExit,
|
||||
executor: executor,
|
||||
paused: opts.Phony,
|
||||
@@ -902,7 +919,10 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
||||
t.listLabel, t.listLabelLen = t.ansiLabelPrinter(opts.ListLabel.label, &tui.ColListLabel, false)
|
||||
t.borderLabel, t.borderLabelLen = t.ansiLabelPrinter(opts.BorderLabel.label, &tui.ColBorderLabel, false)
|
||||
t.previewLabel, t.previewLabelLen = t.ansiLabelPrinter(opts.PreviewLabel.label, &tui.ColPreviewLabel, false)
|
||||
if opts.Separator == nil || len(*opts.Separator) > 0 {
|
||||
t.inputLabel, t.inputLabelLen = t.ansiLabelPrinter(opts.InputLabel.label, &tui.ColInputLabel, false)
|
||||
|
||||
// Disable separator by default if input border is set
|
||||
if opts.Separator == nil && !t.inputBorderShape.Visible() || opts.Separator != nil && len(*opts.Separator) > 0 {
|
||||
bar := "─"
|
||||
if opts.Separator != nil {
|
||||
bar = *opts.Separator
|
||||
@@ -1120,6 +1140,17 @@ func (t *Terminal) ansiLabelPrinter(str string, color *tui.ColorPair, fill bool)
|
||||
return printFn, length
|
||||
}
|
||||
|
||||
// Temporarily switch 'window' so that we can use the existing windows with
|
||||
// a different window
|
||||
func (t *Terminal) withInputWindow(f func()) {
|
||||
prevWindow := t.window
|
||||
if t.inputWindow != nil {
|
||||
t.window = t.inputWindow
|
||||
}
|
||||
f()
|
||||
t.window = prevWindow
|
||||
}
|
||||
|
||||
func (t *Terminal) parsePrompt(prompt string) (func(), int) {
|
||||
var state *ansiState
|
||||
prompt = firstLine(prompt)
|
||||
@@ -1145,11 +1176,13 @@ func (t *Terminal) parsePrompt(prompt string) (func(), int) {
|
||||
}
|
||||
}
|
||||
output := func() {
|
||||
line := t.promptLine()
|
||||
wrap := t.wrap
|
||||
t.wrap = false
|
||||
t.printHighlighted(
|
||||
Result{item: item}, tui.ColPrompt, tui.ColPrompt, false, false, line, line, true, nil, nil)
|
||||
t.withInputWindow(func() {
|
||||
line := t.promptLine()
|
||||
t.printHighlighted(
|
||||
Result{item: item}, tui.ColPrompt, tui.ColPrompt, false, false, line, line, true, nil, nil)
|
||||
})
|
||||
t.wrap = wrap
|
||||
}
|
||||
_, promptLen := t.processTabs([]rune(trimmed), 0)
|
||||
@@ -1566,6 +1599,12 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
if t.wborder != nil {
|
||||
t.wborder = nil
|
||||
}
|
||||
if t.inputWindow != nil {
|
||||
t.inputWindow = nil
|
||||
}
|
||||
if t.inputBorder != nil {
|
||||
t.inputBorder = nil
|
||||
}
|
||||
if t.pborder != nil {
|
||||
t.pborder = nil
|
||||
}
|
||||
@@ -1605,6 +1644,27 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
width -= paddingInt[1] + paddingInt[3]
|
||||
height -= paddingInt[0] + paddingInt[2]
|
||||
|
||||
// Adjust position and size of the list window if input border is set
|
||||
inputWindowHeight := 0
|
||||
inputBorderHeight := 0
|
||||
shift := 0
|
||||
shrink := 0
|
||||
hasInputWindow := t.inputBorderShape.Visible()
|
||||
if hasInputWindow {
|
||||
inputWindowHeight = 2
|
||||
if t.noSeparatorLine() {
|
||||
inputWindowHeight--
|
||||
}
|
||||
inputBorderHeight = borderLines(t.inputBorderShape) + inputWindowHeight
|
||||
if t.layout == layoutReverse {
|
||||
shift = inputBorderHeight
|
||||
shrink = inputBorderHeight
|
||||
} else {
|
||||
shift = 0
|
||||
shrink = inputBorderHeight
|
||||
}
|
||||
}
|
||||
|
||||
hasListBorder := t.listBorderShape.Visible()
|
||||
innerWidth := width
|
||||
innerHeight := height
|
||||
@@ -1612,7 +1672,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
innerBorderFn := func(top int, left int, width int, height int) {
|
||||
if hasListBorder {
|
||||
t.wborder = t.tui.NewWindow(
|
||||
top, left, width, height, tui.WindowList, tui.MakeBorderStyle(t.listBorderShape, t.unicode), false)
|
||||
top+shift, left, width, height-shrink, tui.WindowList, tui.MakeBorderStyle(t.listBorderShape, t.unicode), false)
|
||||
}
|
||||
}
|
||||
if hasListBorder {
|
||||
@@ -1697,12 +1757,12 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
if previewOpts.position == posUp {
|
||||
innerBorderFn(marginInt[0]+pheight, marginInt[3], width, height-pheight)
|
||||
t.window = t.tui.NewWindow(
|
||||
innerMarginInt[0]+pheight, innerMarginInt[3], innerWidth, innerHeight-pheight, tui.WindowList, noBorder, true)
|
||||
innerMarginInt[0]+pheight+shift, innerMarginInt[3], innerWidth, innerHeight-pheight-shrink, tui.WindowList, noBorder, true)
|
||||
createPreviewWindow(marginInt[0], marginInt[3], width, pheight)
|
||||
} else {
|
||||
innerBorderFn(marginInt[0], marginInt[3], width, height-pheight)
|
||||
t.window = t.tui.NewWindow(
|
||||
innerMarginInt[0], innerMarginInt[3], innerWidth, innerHeight-pheight, tui.WindowList, noBorder, true)
|
||||
innerMarginInt[0]+shift, innerMarginInt[3], innerWidth, innerHeight-pheight-shrink, tui.WindowList, noBorder, true)
|
||||
createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight)
|
||||
}
|
||||
case posLeft, posRight:
|
||||
@@ -1741,7 +1801,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
m = 1
|
||||
}
|
||||
t.window = t.tui.NewWindow(
|
||||
innerMarginInt[0], innerMarginInt[3]+pwidth+m, innerWidth-pwidth-m, innerHeight, tui.WindowList, noBorder, true)
|
||||
innerMarginInt[0]+shift, innerMarginInt[3]+pwidth+m, innerWidth-pwidth-m, innerHeight-shrink, tui.WindowList, noBorder, true)
|
||||
|
||||
// Clear characters on the margin
|
||||
// fzf --bind 'space:preview(seq 100)' --preview-window left,1
|
||||
@@ -1763,7 +1823,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
}
|
||||
innerBorderFn(marginInt[0], marginInt[3], width-pwidth, height)
|
||||
t.window = t.tui.NewWindow(
|
||||
innerMarginInt[0], innerMarginInt[3], innerWidth-pwidth, innerHeight, tui.WindowList, noBorder, true)
|
||||
innerMarginInt[0]+shift, innerMarginInt[3], innerWidth-pwidth, innerHeight-shrink, tui.WindowList, noBorder, true)
|
||||
x := marginInt[3] + width - pwidth
|
||||
createPreviewWindow(marginInt[0], x, pwidth, height)
|
||||
}
|
||||
@@ -1801,16 +1861,56 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
}
|
||||
innerBorderFn(marginInt[0], marginInt[3], width, height)
|
||||
t.window = t.tui.NewWindow(
|
||||
innerMarginInt[0],
|
||||
innerMarginInt[0]+shift,
|
||||
innerMarginInt[3],
|
||||
innerWidth,
|
||||
innerHeight, tui.WindowList, noBorder, true)
|
||||
innerHeight-shrink, tui.WindowList, noBorder, true)
|
||||
}
|
||||
|
||||
// Set up input border
|
||||
if hasInputWindow {
|
||||
w := t.wborder
|
||||
if t.wborder == nil {
|
||||
w = t.window
|
||||
}
|
||||
if t.layout == layoutReverse {
|
||||
t.inputBorder = t.tui.NewWindow(
|
||||
w.Top()-shrink,
|
||||
w.Left(),
|
||||
w.Width(),
|
||||
util.Min(shrink, screenHeight), tui.WindowInput, tui.MakeBorderStyle(t.inputBorderShape, t.unicode), true)
|
||||
} else {
|
||||
t.inputBorder = t.tui.NewWindow(
|
||||
w.Top()+w.Height(),
|
||||
w.Left(),
|
||||
w.Width(),
|
||||
util.Min(shrink, screenHeight), tui.WindowInput, tui.MakeBorderStyle(t.inputBorderShape, t.unicode), true)
|
||||
}
|
||||
top := t.inputBorder.Top()
|
||||
left := t.inputBorder.Left()
|
||||
if t.inputBorderShape.HasTop() {
|
||||
top++
|
||||
}
|
||||
if t.inputBorderShape.HasLeft() {
|
||||
left += t.borderWidth + 1
|
||||
}
|
||||
width := t.inputBorder.Width() - borderColumns(t.inputBorderShape, t.borderWidth)
|
||||
if t.inputBorderShape.HasRight() {
|
||||
width++
|
||||
}
|
||||
t.inputWindow = t.tui.NewWindow(
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
t.inputBorder.Height()-borderLines(t.inputBorderShape),
|
||||
tui.WindowInput, noBorder, true)
|
||||
}
|
||||
|
||||
// Print border label
|
||||
t.printLabel(t.wborder, t.listLabel, t.listLabelOpts, t.listLabelLen, t.listBorderShape, false)
|
||||
t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, false)
|
||||
t.printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.activePreviewOpts.border, false)
|
||||
t.printLabel(t.inputBorder, t.inputLabel, t.inputLabelOpts, t.inputLabelLen, t.inputBorderShape, false)
|
||||
}
|
||||
|
||||
func (t *Terminal) printLabel(window tui.Window, render labelPrinter, opts labelOpts, length int, borderShape tui.BorderShape, redrawBorder bool) {
|
||||
@@ -1874,7 +1974,11 @@ func (t *Terminal) truncateQuery() {
|
||||
}
|
||||
|
||||
func (t *Terminal) updatePromptOffset() ([]rune, []rune) {
|
||||
maxWidth := util.Max(1, t.window.Width()-t.promptLen-1)
|
||||
w := t.window
|
||||
if t.inputWindow != nil {
|
||||
w = t.inputWindow
|
||||
}
|
||||
maxWidth := util.Max(1, w.Width()-t.promptLen-1)
|
||||
|
||||
_, overflow := t.trimLeft(t.input[:t.cx], maxWidth)
|
||||
minOffset := int(overflow)
|
||||
@@ -1889,6 +1993,9 @@ func (t *Terminal) updatePromptOffset() ([]rune, []rune) {
|
||||
}
|
||||
|
||||
func (t *Terminal) promptLine() int {
|
||||
if t.inputWindow != nil {
|
||||
return 0
|
||||
}
|
||||
if t.headerFirst {
|
||||
max := t.window.Height() - 1
|
||||
if max <= 0 { // Extremely short terminal
|
||||
@@ -1903,10 +2010,25 @@ func (t *Terminal) promptLine() int {
|
||||
}
|
||||
|
||||
func (t *Terminal) placeCursor() {
|
||||
if t.inputWindow != nil {
|
||||
y := t.inputWindow.Height() - 1
|
||||
if t.layout == layoutReverse {
|
||||
y = 0
|
||||
}
|
||||
t.inputWindow.Move(y, t.promptLen+t.queryLen[0])
|
||||
return
|
||||
}
|
||||
t.move(t.promptLine(), t.promptLen+t.queryLen[0], false)
|
||||
}
|
||||
|
||||
func (t *Terminal) printPrompt() {
|
||||
w := t.window
|
||||
if t.inputWindow != nil {
|
||||
w = t.inputWindow
|
||||
}
|
||||
if w.Height() == 0 {
|
||||
return
|
||||
}
|
||||
t.prompt()
|
||||
|
||||
before, after := t.updatePromptOffset()
|
||||
@@ -1914,8 +2036,8 @@ func (t *Terminal) printPrompt() {
|
||||
if t.paused {
|
||||
color = tui.ColDisabled
|
||||
}
|
||||
t.window.CPrint(color, string(before))
|
||||
t.window.CPrint(color, string(after))
|
||||
w.CPrint(color, string(before))
|
||||
w.CPrint(color, string(after))
|
||||
}
|
||||
|
||||
func (t *Terminal) trimMessage(message string, maxWidth int) string {
|
||||
@@ -1927,6 +2049,12 @@ func (t *Terminal) trimMessage(message string, maxWidth int) string {
|
||||
}
|
||||
|
||||
func (t *Terminal) printInfo() {
|
||||
t.withInputWindow(func() {
|
||||
t.printInfoImpl()
|
||||
})
|
||||
}
|
||||
|
||||
func (t *Terminal) printInfoImpl() {
|
||||
if t.window.Width() <= 1 {
|
||||
return
|
||||
}
|
||||
@@ -2124,7 +2252,7 @@ func (t *Terminal) printHeader() {
|
||||
return
|
||||
}
|
||||
max := t.window.Height()
|
||||
if t.headerFirst {
|
||||
if t.inputWindow == nil && t.headerFirst {
|
||||
max--
|
||||
if !t.noSeparatorLine() {
|
||||
max--
|
||||
@@ -2144,7 +2272,7 @@ func (t *Terminal) printHeader() {
|
||||
if needReverse && idx < len(t.header0) {
|
||||
line = len(t.header0) - idx - 1
|
||||
}
|
||||
if !t.headerFirst {
|
||||
if t.inputWindow == nil && !t.headerFirst {
|
||||
line++
|
||||
if !t.noSeparatorLine() {
|
||||
line++
|
||||
@@ -2189,10 +2317,7 @@ func (t *Terminal) printList() {
|
||||
count := t.merger.Length() - t.offset
|
||||
|
||||
// Start line
|
||||
startLine := 2 + t.visibleHeaderLines()
|
||||
if t.noSeparatorLine() {
|
||||
startLine--
|
||||
}
|
||||
startLine := t.promptLines() + t.visibleHeaderLines()
|
||||
maxy += startLine
|
||||
|
||||
barRange := [2]int{startLine + barStart, startLine + barStart + barLength}
|
||||
@@ -2233,10 +2358,10 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
||||
|
||||
// Avoid unnecessary redraw
|
||||
numLines, _ := t.numItemLines(item, maxLine-line+1)
|
||||
newLine := itemLine{firstLine: line, numLines: numLines, cy: index + t.offset, current: current, selected: selected, label: label,
|
||||
newLine := itemLine{valid: true, firstLine: line, numLines: numLines, cy: index + t.offset, current: current, selected: selected, label: label,
|
||||
result: result, queryLen: len(t.input), width: 0, hasBar: line >= barRange[0] && line < barRange[1]}
|
||||
prevLine := t.prevLines[line]
|
||||
forceRedraw := prevLine.other || prevLine.firstLine != newLine.firstLine
|
||||
forceRedraw := !prevLine.valid || prevLine.other || prevLine.firstLine != newLine.firstLine
|
||||
printBar := func(lineNum int, forceRedraw bool) bool {
|
||||
return t.printBar(lineNum, forceRedraw, barRange)
|
||||
}
|
||||
@@ -3962,6 +4087,8 @@ func (t *Terminal) Loop() error {
|
||||
if t.hasPreviewer() {
|
||||
t.previewBox.Set(reqPreviewReady, nil)
|
||||
}
|
||||
case reqRedrawInputLabel:
|
||||
t.printLabel(t.inputBorder, t.inputLabel, t.inputLabelOpts, t.inputLabelLen, t.inputBorderShape, true)
|
||||
case reqRedrawListLabel:
|
||||
t.printLabel(t.wborder, t.listLabel, t.listLabelOpts, t.listLabelLen, t.listBorderShape, true)
|
||||
case reqRedrawBorderLabel:
|
||||
@@ -4345,6 +4472,12 @@ func (t *Terminal) Loop() error {
|
||||
} else {
|
||||
req(reqHeader)
|
||||
}
|
||||
case actChangeInputLabel:
|
||||
t.inputLabelOpts.label = a.a
|
||||
if t.inputBorder != nil {
|
||||
t.inputLabel, t.inputLabelLen = t.ansiLabelPrinter(a.a, &tui.ColInputLabel, false)
|
||||
req(reqRedrawInputLabel)
|
||||
}
|
||||
case actChangeListLabel:
|
||||
t.listLabelOpts.label = a.a
|
||||
if t.wborder != nil {
|
||||
@@ -4368,6 +4501,13 @@ func (t *Terminal) Loop() error {
|
||||
if actions, err := parseSingleActionList(strings.Trim(body, "\r\n")); err == nil {
|
||||
return doActions(actions)
|
||||
}
|
||||
case actTransformInputLabel:
|
||||
label := t.executeCommand(a.a, false, true, true, true, "")
|
||||
t.inputLabelOpts.label = label
|
||||
if t.inputBorder != nil {
|
||||
t.inputLabel, t.inputLabelLen = t.ansiLabelPrinter(label, &tui.ColInputLabel, false)
|
||||
req(reqRedrawInputLabel)
|
||||
}
|
||||
case actTransformListLabel:
|
||||
label := t.executeCommand(a.a, false, true, true, true, "")
|
||||
t.listLabelOpts.label = label
|
||||
@@ -4927,6 +5067,21 @@ func (t *Terminal) Loop() error {
|
||||
break
|
||||
}
|
||||
|
||||
// Inside the input window
|
||||
if t.inputWindow != nil && t.inputWindow.Enclose(my, mx) {
|
||||
mx -= t.inputWindow.Left()
|
||||
my -= t.inputWindow.Top()
|
||||
y := t.inputWindow.Height() - 1
|
||||
if t.layout == layoutReverse {
|
||||
y = 0
|
||||
}
|
||||
mxCons := util.Constrain(mx-t.promptLen, 0, len(t.input))
|
||||
if my == y && mxCons >= 0 {
|
||||
t.cx = mxCons + t.xoffset
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// Ignored
|
||||
if !t.window.Enclose(my, mx) && !barDragging {
|
||||
break
|
||||
@@ -4935,10 +5090,7 @@ func (t *Terminal) Loop() error {
|
||||
// Translate coordinates
|
||||
mx -= t.window.Left()
|
||||
my -= t.window.Top()
|
||||
min := 2 + t.visibleHeaderLines()
|
||||
if t.noSeparatorLine() {
|
||||
min--
|
||||
}
|
||||
min := t.promptLines() + t.visibleHeaderLines()
|
||||
h := t.window.Height()
|
||||
switch t.layout {
|
||||
case layoutDefault:
|
||||
@@ -4990,7 +5142,7 @@ func (t *Terminal) Loop() error {
|
||||
|
||||
if me.Down {
|
||||
mxCons := util.Constrain(mx-t.promptLen, 0, len(t.input))
|
||||
if my == t.promptLine() && mxCons >= 0 {
|
||||
if t.inputWindow == nil && my == t.promptLine() && mxCons >= 0 {
|
||||
// Prompt
|
||||
t.cx = mxCons + t.xoffset
|
||||
} else if my >= min {
|
||||
@@ -5011,7 +5163,7 @@ func (t *Terminal) Loop() error {
|
||||
// Header
|
||||
numLines := t.visibleHeaderLines()
|
||||
lineOffset := 0
|
||||
if !t.headerFirst {
|
||||
if t.inputWindow == nil && !t.headerFirst {
|
||||
// offset for info line
|
||||
if t.noSeparatorLine() {
|
||||
lineOffset = 1
|
||||
@@ -5339,11 +5491,20 @@ func (t *Terminal) vset(o int) bool {
|
||||
return t.cy == o
|
||||
}
|
||||
|
||||
func (t *Terminal) maxItems() int {
|
||||
max := t.window.Height() - 2 - t.visibleHeaderLines()
|
||||
if t.noSeparatorLine() {
|
||||
max++
|
||||
// Number of prompt lines in the list window
|
||||
func (t *Terminal) promptLines() int {
|
||||
if t.inputWindow != nil {
|
||||
return 0
|
||||
}
|
||||
if t.noSeparatorLine() {
|
||||
return 1
|
||||
}
|
||||
return 2
|
||||
}
|
||||
|
||||
// Number of item lines in the list window
|
||||
func (t *Terminal) maxItems() int {
|
||||
max := t.window.Height() - t.visibleHeaderLines() - t.promptLines()
|
||||
return util.Max(max, 0)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user