mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-18 00:03:39 -05:00
Add --no-input to hide the input section (#4210)
Close #2890 Close #1396 You can't type in queries in this mode, and the only way to trigger an fzf search is to use `search(...)` action. # Click header to trigger search fzf --header '[src] [test]' --no-input --layout reverse \ --header-border bottom --input-border \ --bind 'click-header:transform-search:echo ${FZF_CLICK_HEADER_WORD:1:-1}'
This commit is contained in:
@@ -127,6 +127,7 @@ Usage: fzf [options]
|
||||
(default: 0 or center)
|
||||
|
||||
INPUT SECTION
|
||||
--no-input Disable and hide the input section
|
||||
--prompt=STR Input prompt (default: '> ')
|
||||
--info=STYLE Finder info style
|
||||
[default|right|hidden|inline[-right][:PREFIX]]
|
||||
@@ -538,6 +539,7 @@ type Options struct {
|
||||
Scheme string
|
||||
Extended bool
|
||||
Phony bool
|
||||
Inputless bool
|
||||
Case Case
|
||||
Normalize bool
|
||||
Nth []Range
|
||||
@@ -659,6 +661,7 @@ func defaultOptions() *Options {
|
||||
Scheme: "", // Unknown
|
||||
Extended: true,
|
||||
Phony: false,
|
||||
Inputless: false,
|
||||
Case: CaseSmart,
|
||||
Normalize: true,
|
||||
Nth: make([]Range, 0),
|
||||
@@ -2315,6 +2318,8 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
||||
opts.Phony = false
|
||||
case "--disabled", "--phony":
|
||||
opts.Phony = true
|
||||
case "--no-input":
|
||||
opts.Inputless = true
|
||||
case "--tiebreak":
|
||||
str, err := nextString("sort criterion required")
|
||||
if err != nil {
|
||||
@@ -3064,6 +3069,9 @@ func noSeparatorLine(style infoStyle, separator bool) bool {
|
||||
}
|
||||
|
||||
func (opts *Options) noSeparatorLine() bool {
|
||||
if opts.Inputless {
|
||||
return true
|
||||
}
|
||||
sep := opts.Separator == nil && !opts.InputBorderShape.Visible() || opts.Separator != nil && len(*opts.Separator) > 0
|
||||
return noSeparatorLine(opts.InfoStyle, sep)
|
||||
}
|
||||
@@ -3235,7 +3243,13 @@ func postProcessOptions(opts *Options) error {
|
||||
|
||||
// Sets --min-height automatically
|
||||
if opts.Height.size > 0 && opts.Height.percent && opts.MinHeight < 0 {
|
||||
opts.MinHeight = -opts.MinHeight + 1 + borderLines(opts.BorderShape) + borderLines(opts.ListBorderShape) + borderLines(opts.InputBorderShape)
|
||||
opts.MinHeight = -opts.MinHeight + borderLines(opts.BorderShape) + borderLines(opts.ListBorderShape)
|
||||
if !opts.Inputless {
|
||||
opts.MinHeight += 1 + borderLines(opts.InputBorderShape)
|
||||
if !opts.noSeparatorLine() {
|
||||
opts.MinHeight++
|
||||
}
|
||||
}
|
||||
if len(opts.Header) > 0 {
|
||||
opts.MinHeight += borderLines(opts.HeaderBorderShape) + len(opts.Header)
|
||||
}
|
||||
@@ -3246,9 +3260,6 @@ func postProcessOptions(opts *Options) error {
|
||||
}
|
||||
opts.MinHeight += borderLines(borderShape) + opts.HeaderLines
|
||||
}
|
||||
if !opts.noSeparatorLine() {
|
||||
opts.MinHeight++
|
||||
}
|
||||
if len(opts.Preview.command) > 0 && (opts.Preview.position == posUp || opts.Preview.position == posDown) && opts.Preview.Visible() && opts.Preview.position == posUp {
|
||||
borderShape := opts.Preview.border
|
||||
if opts.Preview.border == tui.BorderLine {
|
||||
|
||||
@@ -324,6 +324,7 @@ type Terminal struct {
|
||||
cleanExit bool
|
||||
executor *util.Executor
|
||||
paused bool
|
||||
inputless bool
|
||||
border tui.Window
|
||||
window tui.Window
|
||||
inputWindow tui.Window
|
||||
@@ -810,6 +811,9 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if opts.Inputless {
|
||||
renderer.HideCursor()
|
||||
}
|
||||
wordRubout := "[^\\pL\\pN][\\pL\\pN]"
|
||||
wordNext := "[\\pL\\pN][^\\pL\\pN]|(.$)"
|
||||
if opts.FileWord {
|
||||
@@ -887,6 +891,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
||||
cleanExit: opts.ClearOnExit,
|
||||
executor: executor,
|
||||
paused: opts.Phony,
|
||||
inputless: opts.Inputless,
|
||||
cycle: opts.Cycle,
|
||||
highlightLine: opts.CursorLine,
|
||||
headerVisible: true,
|
||||
@@ -1124,9 +1129,15 @@ func (t *Terminal) visibleHeaderLinesInList() int {
|
||||
|
||||
// Extra number of lines needed to display fzf
|
||||
func (t *Terminal) extraLines() int {
|
||||
extra := 1
|
||||
if t.inputBorderShape.Visible() {
|
||||
extra += borderLines(t.inputBorderShape)
|
||||
extra := 0
|
||||
if !t.inputless {
|
||||
extra++
|
||||
if !t.noSeparatorLine() {
|
||||
extra++
|
||||
}
|
||||
if t.inputBorderShape.Visible() {
|
||||
extra += borderLines(t.inputBorderShape)
|
||||
}
|
||||
}
|
||||
if t.listBorderShape.Visible() {
|
||||
extra += borderLines(t.listBorderShape)
|
||||
@@ -1141,9 +1152,6 @@ func (t *Terminal) extraLines() int {
|
||||
}
|
||||
extra += t.headerLines
|
||||
}
|
||||
if !t.noSeparatorLine() {
|
||||
extra++
|
||||
}
|
||||
return extra
|
||||
}
|
||||
|
||||
@@ -1265,7 +1273,7 @@ func (t *Terminal) parsePrompt(prompt string) (func(), int) {
|
||||
}
|
||||
|
||||
func (t *Terminal) noSeparatorLine() bool {
|
||||
return noSeparatorLine(t.infoStyle, t.separatorLen > 0)
|
||||
return t.inputless || noSeparatorLine(t.infoStyle, t.separatorLen > 0)
|
||||
}
|
||||
|
||||
func getScrollbar(perLine int, total int, height int, offset int) (int, int) {
|
||||
@@ -1350,7 +1358,10 @@ func (t *Terminal) Input() (bool, []rune) {
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
paused := t.paused
|
||||
src := t.input
|
||||
var src []rune
|
||||
if !t.inputless {
|
||||
src = t.input
|
||||
}
|
||||
if t.inputOverride != nil {
|
||||
paused = false
|
||||
src = *t.inputOverride
|
||||
@@ -1635,8 +1646,11 @@ func (t *Terminal) adjustMarginAndPadding() (int, int, [4]int, [4]int) {
|
||||
|
||||
minAreaWidth := minWidth
|
||||
minAreaHeight := minHeight
|
||||
if t.inputless {
|
||||
minAreaHeight--
|
||||
}
|
||||
if t.noSeparatorLine() {
|
||||
minAreaHeight -= 1
|
||||
minAreaHeight--
|
||||
}
|
||||
if t.needPreviewWindow() {
|
||||
minPreviewWidth, minPreviewHeight := t.minPreviewSize(t.activePreviewOpts)
|
||||
@@ -1756,7 +1770,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
shrink := 0
|
||||
hasHeaderWindow := t.hasHeaderWindow()
|
||||
hasHeaderLinesWindow := t.hasHeaderLinesWindow()
|
||||
hasInputWindow := t.inputBorderShape.Visible() || hasHeaderWindow || hasHeaderLinesWindow
|
||||
hasInputWindow := !t.inputless && (t.inputBorderShape.Visible() || hasHeaderWindow || hasHeaderLinesWindow)
|
||||
if hasInputWindow {
|
||||
inputWindowHeight := 2
|
||||
if t.noSeparatorLine() {
|
||||
@@ -1873,6 +1887,9 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
||||
switch previewOpts.position {
|
||||
case posUp, posDown:
|
||||
minWindowHeight := minHeight
|
||||
if t.inputless {
|
||||
minWindowHeight--
|
||||
}
|
||||
if t.noSeparatorLine() {
|
||||
minWindowHeight--
|
||||
}
|
||||
@@ -2227,6 +2244,9 @@ func (t *Terminal) promptLine() int {
|
||||
}
|
||||
|
||||
func (t *Terminal) placeCursor() {
|
||||
if t.inputless {
|
||||
return
|
||||
}
|
||||
if t.inputWindow != nil {
|
||||
y := t.inputWindow.Height() - 1
|
||||
if t.layout == layoutReverse {
|
||||
@@ -2239,6 +2259,9 @@ func (t *Terminal) placeCursor() {
|
||||
}
|
||||
|
||||
func (t *Terminal) printPrompt() {
|
||||
if t.inputless {
|
||||
return
|
||||
}
|
||||
w := t.window
|
||||
if t.inputWindow != nil {
|
||||
w = t.inputWindow
|
||||
@@ -2266,6 +2289,9 @@ func (t *Terminal) trimMessage(message string, maxWidth int) string {
|
||||
}
|
||||
|
||||
func (t *Terminal) printInfo() {
|
||||
if t.inputless {
|
||||
return
|
||||
}
|
||||
t.withWindow(t.inputWindow, func() { t.printInfoImpl() })
|
||||
}
|
||||
|
||||
@@ -2509,7 +2535,7 @@ func (t *Terminal) headerIndent(borderShape tui.BorderShape) int {
|
||||
|
||||
func (t *Terminal) printHeaderImpl(window tui.Window, borderShape tui.BorderShape, lines1 []string, lines2 []string) {
|
||||
max := t.window.Height()
|
||||
if t.inputWindow == nil && window == nil && t.headerFirst {
|
||||
if !t.inputless && t.inputWindow == nil && window == nil && t.headerFirst {
|
||||
max--
|
||||
if !t.noSeparatorLine() {
|
||||
max--
|
||||
@@ -2539,7 +2565,7 @@ func (t *Terminal) printHeaderImpl(window tui.Window, borderShape tui.BorderShap
|
||||
if needReverse && idx < len(lines1) {
|
||||
line = len(lines1) - idx - 1
|
||||
}
|
||||
if t.inputWindow == nil && window == nil && !t.headerFirst {
|
||||
if !t.inputless && t.inputWindow == nil && window == nil && !t.headerFirst {
|
||||
line++
|
||||
if !t.noSeparatorLine() {
|
||||
line++
|
||||
@@ -5681,7 +5707,7 @@ func (t *Terminal) Loop() error {
|
||||
// Header
|
||||
numLines := t.visibleHeaderLinesInList()
|
||||
lineOffset := 0
|
||||
if t.inputWindow == nil && !t.headerFirst {
|
||||
if !t.inputless && t.inputWindow == nil && !t.headerFirst {
|
||||
// offset for info line
|
||||
if t.noSeparatorLine() {
|
||||
lineOffset = 1
|
||||
@@ -5829,7 +5855,13 @@ func (t *Terminal) Loop() error {
|
||||
} else if !doActions(actions) {
|
||||
continue
|
||||
}
|
||||
t.truncateQuery()
|
||||
if t.inputless {
|
||||
// Always just discard the change
|
||||
t.input = previousInput
|
||||
t.cx = len(t.input)
|
||||
} else {
|
||||
t.truncateQuery()
|
||||
}
|
||||
queryChanged = string(previousInput) != string(t.input)
|
||||
if queryChanged {
|
||||
t.inputOverride = nil
|
||||
@@ -6016,6 +6048,9 @@ func (t *Terminal) vset(o int) bool {
|
||||
|
||||
// Number of prompt lines in the list window
|
||||
func (t *Terminal) promptLines() int {
|
||||
if t.inputless {
|
||||
return 0
|
||||
}
|
||||
if t.inputWindow != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ func (r *FullscreenRenderer) Clear() {}
|
||||
func (r *FullscreenRenderer) NeedScrollbarRedraw() bool { return false }
|
||||
func (r *FullscreenRenderer) ShouldEmitResizeEvent() bool { return false }
|
||||
func (r *FullscreenRenderer) Bell() {}
|
||||
func (r *FullscreenRenderer) HideCursor() {}
|
||||
func (r *FullscreenRenderer) Refresh() {}
|
||||
func (r *FullscreenRenderer) Close() {}
|
||||
func (r *FullscreenRenderer) Size() TermSize { return TermSize{} }
|
||||
|
||||
@@ -77,7 +77,13 @@ func (r *LightRenderer) csi(code string) string {
|
||||
|
||||
func (r *LightRenderer) flush() {
|
||||
if r.queued.Len() > 0 {
|
||||
r.flushRaw("\x1b[?7l\x1b[?25l" + r.queued.String() + "\x1b[?25h\x1b[?7h")
|
||||
raw := "\x1b[?7l\x1b[?25l" + r.queued.String()
|
||||
if r.showCursor {
|
||||
raw += "\x1b[?25h\x1b[?7h"
|
||||
} else {
|
||||
raw += "\x1b[?7h"
|
||||
}
|
||||
r.flushRaw(raw)
|
||||
r.queued.Reset()
|
||||
}
|
||||
}
|
||||
@@ -110,6 +116,7 @@ type LightRenderer struct {
|
||||
y int
|
||||
x int
|
||||
maxHeightFunc func(int) int
|
||||
showCursor bool
|
||||
|
||||
// Windows only
|
||||
ttyinChannel chan byte
|
||||
@@ -152,7 +159,8 @@ func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse
|
||||
tabstop: tabstop,
|
||||
fullscreen: fullscreen,
|
||||
upOneLine: false,
|
||||
maxHeightFunc: maxHeightFunc}
|
||||
maxHeightFunc: maxHeightFunc,
|
||||
showCursor: true}
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
@@ -759,6 +767,9 @@ func (r *LightRenderer) Close() {
|
||||
} else if !r.fullscreen {
|
||||
r.csi("u")
|
||||
}
|
||||
if !r.showCursor {
|
||||
r.csi("?25h")
|
||||
}
|
||||
r.disableMouse()
|
||||
r.flush()
|
||||
r.closePlatform()
|
||||
@@ -1214,3 +1225,7 @@ func (w *LightWindow) Erase() {
|
||||
func (w *LightWindow) EraseMaybe() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *LightRenderer) HideCursor() {
|
||||
r.showCursor = false
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ type TcellWindow struct {
|
||||
borderStyle BorderStyle
|
||||
uri *string
|
||||
params *string
|
||||
showCursor bool
|
||||
}
|
||||
|
||||
func (w *TcellWindow) Top() int {
|
||||
@@ -72,7 +73,9 @@ func (w *TcellWindow) Height() int {
|
||||
|
||||
func (w *TcellWindow) Refresh() {
|
||||
if w.moveCursor {
|
||||
_screen.ShowCursor(w.left+w.lastX, w.top+w.lastY)
|
||||
if w.showCursor {
|
||||
_screen.ShowCursor(w.left+w.lastX, w.top+w.lastY)
|
||||
}
|
||||
w.moveCursor = false
|
||||
}
|
||||
w.lastX = 0
|
||||
@@ -104,6 +107,10 @@ func (r *FullscreenRenderer) Bell() {
|
||||
_screen.Beep()
|
||||
}
|
||||
|
||||
func (r *FullscreenRenderer) HideCursor() {
|
||||
r.showCursor = false
|
||||
}
|
||||
|
||||
func (r *FullscreenRenderer) PassThrough(str string) {
|
||||
// No-op
|
||||
// https://github.com/gdamore/tcell/pull/650#issuecomment-1806442846
|
||||
@@ -168,6 +175,9 @@ func (r *FullscreenRenderer) getScreen() (tcell.Screen, error) {
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
if !r.showCursor {
|
||||
s.HideCursor()
|
||||
}
|
||||
_screen = s
|
||||
}
|
||||
return _screen, nil
|
||||
@@ -590,7 +600,8 @@ func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int,
|
||||
width: width,
|
||||
height: height,
|
||||
normal: normal,
|
||||
borderStyle: borderStyle}
|
||||
borderStyle: borderStyle,
|
||||
showCursor: r.showCursor}
|
||||
w.Erase()
|
||||
return w
|
||||
}
|
||||
|
||||
@@ -615,6 +615,7 @@ type Renderer interface {
|
||||
NeedScrollbarRedraw() bool
|
||||
ShouldEmitResizeEvent() bool
|
||||
Bell()
|
||||
HideCursor()
|
||||
|
||||
GetChar() Event
|
||||
|
||||
@@ -662,6 +663,7 @@ type FullscreenRenderer struct {
|
||||
forceBlack bool
|
||||
prevDownTime time.Time
|
||||
clicks [][2]int
|
||||
showCursor bool
|
||||
}
|
||||
|
||||
func NewFullscreenRenderer(theme *ColorTheme, forceBlack bool, mouse bool) Renderer {
|
||||
@@ -670,7 +672,8 @@ func NewFullscreenRenderer(theme *ColorTheme, forceBlack bool, mouse bool) Rende
|
||||
mouse: mouse,
|
||||
forceBlack: forceBlack,
|
||||
prevDownTime: time.Unix(0, 0),
|
||||
clicks: [][2]int{}}
|
||||
clicks: [][2]int{},
|
||||
showCursor: true}
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user