mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2024-12-23 03:19:01 +00:00
parent
168453da71
commit
d2fa470165
@ -39,6 +39,10 @@ CHANGELOG
|
|||||||
# usage: _fzf_setup_completion path|dir COMMANDS...
|
# usage: _fzf_setup_completion path|dir COMMANDS...
|
||||||
_fzf_setup_completion path git kubectl
|
_fzf_setup_completion path git kubectl
|
||||||
```
|
```
|
||||||
|
- Info line style can be changed by `--info=STYLE`
|
||||||
|
- `--info=default`
|
||||||
|
- `--info=inline` (same as old `--inline-info`)
|
||||||
|
- `--info=hidden`
|
||||||
- When you transform the input with `--with-nth`, the trailing white spaces
|
- When you transform the input with `--with-nth`, the trailing white spaces
|
||||||
are removed.
|
are removed.
|
||||||
- `ctrl-\`, `ctrl-]`, `ctrl-^`, and `ctrl-/` can now be used with `--bind`
|
- `ctrl-\`, `ctrl-]`, `ctrl-^`, and `ctrl-/` can now be used with `--bind`
|
||||||
|
@ -212,8 +212,21 @@ e.g.
|
|||||||
fzf --margin 1,5%\fR
|
fzf --margin 1,5%\fR
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.B "--inline-info"
|
.BI "--info=" "STYLE"
|
||||||
Display finder info inline with the query
|
Determines the display style of finder info.
|
||||||
|
|
||||||
|
.br
|
||||||
|
.BR default " Display on the next line to the prompt"
|
||||||
|
.br
|
||||||
|
.BR inline " Display on the same line"
|
||||||
|
.br
|
||||||
|
.BR hidden " Do not display finder info"
|
||||||
|
.br
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B "--no-info"
|
||||||
|
A synonym for \fB--info=hidden\fB
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "--prompt=" "STR"
|
.BI "--prompt=" "STR"
|
||||||
Input prompt (default: '> ')
|
Input prompt (default: '> ')
|
||||||
|
@ -57,7 +57,7 @@ const usage = `usage: fzf [options]
|
|||||||
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
|
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
|
||||||
--border Draw border above and below the finder
|
--border Draw border above and below the finder
|
||||||
--margin=MARGIN Screen margin (TRBL / TB,RL / T,RL,B / T,R,B,L)
|
--margin=MARGIN Screen margin (TRBL / TB,RL / T,RL,B / T,R,B,L)
|
||||||
--inline-info Display finder info inline with the query
|
--info=STYLE Finder info style [default|inline|hidden]
|
||||||
--prompt=STR Input prompt (default: '> ')
|
--prompt=STR Input prompt (default: '> ')
|
||||||
--header=STR String to print as header
|
--header=STR String to print as header
|
||||||
--header-lines=N The first N lines of the input are treated as header
|
--header-lines=N The first N lines of the input are treated as header
|
||||||
@ -142,6 +142,14 @@ const (
|
|||||||
layoutReverseList
|
layoutReverseList
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type infoStyle int
|
||||||
|
|
||||||
|
const (
|
||||||
|
infoDefault infoStyle = iota
|
||||||
|
infoInline
|
||||||
|
infoHidden
|
||||||
|
)
|
||||||
|
|
||||||
type previewOpts struct {
|
type previewOpts struct {
|
||||||
command string
|
command string
|
||||||
position windowPosition
|
position windowPosition
|
||||||
@ -177,7 +185,7 @@ type Options struct {
|
|||||||
Hscroll bool
|
Hscroll bool
|
||||||
HscrollOff int
|
HscrollOff int
|
||||||
FileWord bool
|
FileWord bool
|
||||||
InlineInfo bool
|
InfoStyle infoStyle
|
||||||
JumpLabels string
|
JumpLabels string
|
||||||
Prompt string
|
Prompt string
|
||||||
Query string
|
Query string
|
||||||
@ -230,7 +238,7 @@ func defaultOptions() *Options {
|
|||||||
Hscroll: true,
|
Hscroll: true,
|
||||||
HscrollOff: 10,
|
HscrollOff: 10,
|
||||||
FileWord: false,
|
FileWord: false,
|
||||||
InlineInfo: false,
|
InfoStyle: infoDefault,
|
||||||
JumpLabels: defaultJumpLabels,
|
JumpLabels: defaultJumpLabels,
|
||||||
Prompt: "> ",
|
Prompt: "> ",
|
||||||
Query: "",
|
Query: "",
|
||||||
@ -904,6 +912,20 @@ func parseLayout(str string) layoutType {
|
|||||||
return layoutDefault
|
return layoutDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseInfoStyle(str string) infoStyle {
|
||||||
|
switch str {
|
||||||
|
case "default":
|
||||||
|
return infoDefault
|
||||||
|
case "inline":
|
||||||
|
return infoInline
|
||||||
|
case "hidden":
|
||||||
|
return infoHidden
|
||||||
|
default:
|
||||||
|
errorExit("invalid info style (expected: default / inline / hidden)")
|
||||||
|
}
|
||||||
|
return infoDefault
|
||||||
|
}
|
||||||
|
|
||||||
func parsePreviewWindow(opts *previewOpts, input string) {
|
func parsePreviewWindow(opts *previewOpts, input string) {
|
||||||
// Default
|
// Default
|
||||||
opts.position = posRight
|
opts.position = posRight
|
||||||
@ -1109,10 +1131,15 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
opts.FileWord = true
|
opts.FileWord = true
|
||||||
case "--no-filepath-word":
|
case "--no-filepath-word":
|
||||||
opts.FileWord = false
|
opts.FileWord = false
|
||||||
|
case "--info":
|
||||||
|
opts.InfoStyle = parseInfoStyle(
|
||||||
|
nextString(allArgs, &i, "info style required"))
|
||||||
|
case "--no-info":
|
||||||
|
opts.InfoStyle = infoHidden
|
||||||
case "--inline-info":
|
case "--inline-info":
|
||||||
opts.InlineInfo = true
|
opts.InfoStyle = infoInline
|
||||||
case "--no-inline-info":
|
case "--no-inline-info":
|
||||||
opts.InlineInfo = false
|
opts.InfoStyle = infoDefault
|
||||||
case "--jump-labels":
|
case "--jump-labels":
|
||||||
opts.JumpLabels = nextString(allArgs, &i, "label characters required")
|
opts.JumpLabels = nextString(allArgs, &i, "label characters required")
|
||||||
validateJumpLabels = true
|
validateJumpLabels = true
|
||||||
@ -1220,6 +1247,8 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
opts.MinHeight = atoi(value)
|
opts.MinHeight = atoi(value)
|
||||||
} else if match, value := optString(arg, "--layout="); match {
|
} else if match, value := optString(arg, "--layout="); match {
|
||||||
opts.Layout = parseLayout(value)
|
opts.Layout = parseLayout(value)
|
||||||
|
} else if match, value := optString(arg, "--info="); match {
|
||||||
|
opts.InfoStyle = parseInfoStyle(value)
|
||||||
} else if match, value := optString(arg, "--toggle-sort="); match {
|
} else if match, value := optString(arg, "--toggle-sort="); match {
|
||||||
parseToggleSort(opts.Keymap, value)
|
parseToggleSort(opts.Keymap, value)
|
||||||
} else if match, value := optString(arg, "--expect="); match {
|
} else if match, value := optString(arg, "--expect="); match {
|
||||||
|
@ -60,7 +60,7 @@ var emptyLine = itemLine{}
|
|||||||
// Terminal represents terminal input/output
|
// Terminal represents terminal input/output
|
||||||
type Terminal struct {
|
type Terminal struct {
|
||||||
initDelay time.Duration
|
initDelay time.Duration
|
||||||
inlineInfo bool
|
infoStyle infoStyle
|
||||||
prompt string
|
prompt string
|
||||||
promptLen int
|
promptLen int
|
||||||
queryLen [2]int
|
queryLen [2]int
|
||||||
@ -361,7 +361,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
|||||||
if previewBox != nil && (opts.Preview.position == posUp || opts.Preview.position == posDown) {
|
if previewBox != nil && (opts.Preview.position == posUp || opts.Preview.position == posDown) {
|
||||||
effectiveMinHeight *= 2
|
effectiveMinHeight *= 2
|
||||||
}
|
}
|
||||||
if opts.InlineInfo {
|
if opts.InfoStyle != infoDefault {
|
||||||
effectiveMinHeight -= 1
|
effectiveMinHeight -= 1
|
||||||
}
|
}
|
||||||
if opts.Bordered {
|
if opts.Bordered {
|
||||||
@ -380,7 +380,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
|||||||
}
|
}
|
||||||
t := Terminal{
|
t := Terminal{
|
||||||
initDelay: delay,
|
initDelay: delay,
|
||||||
inlineInfo: opts.InlineInfo,
|
infoStyle: opts.InfoStyle,
|
||||||
queryLen: [2]int{0, 0},
|
queryLen: [2]int{0, 0},
|
||||||
layout: opts.Layout,
|
layout: opts.Layout,
|
||||||
fullscreen: fullscreen,
|
fullscreen: fullscreen,
|
||||||
@ -438,6 +438,10 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
|||||||
return &t
|
return &t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Terminal) noInfoLine() bool {
|
||||||
|
return t.infoStyle != infoDefault
|
||||||
|
}
|
||||||
|
|
||||||
// Input returns current query string
|
// Input returns current query string
|
||||||
func (t *Terminal) Input() []rune {
|
func (t *Terminal) Input() []rune {
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
@ -672,7 +676,7 @@ func (t *Terminal) move(y int, x int, clear bool) {
|
|||||||
y = h - y - 1
|
y = h - y - 1
|
||||||
case layoutReverseList:
|
case layoutReverseList:
|
||||||
n := 2 + len(t.header)
|
n := 2 + len(t.header)
|
||||||
if t.inlineInfo {
|
if t.noInfoLine() {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
if y < n {
|
if y < n {
|
||||||
@ -725,7 +729,17 @@ func (t *Terminal) printPrompt() {
|
|||||||
|
|
||||||
func (t *Terminal) printInfo() {
|
func (t *Terminal) printInfo() {
|
||||||
pos := 0
|
pos := 0
|
||||||
if t.inlineInfo {
|
switch t.infoStyle {
|
||||||
|
case infoDefault:
|
||||||
|
t.move(1, 0, true)
|
||||||
|
if t.reading {
|
||||||
|
duration := int64(spinnerDuration)
|
||||||
|
idx := (time.Now().UnixNano() % (duration * int64(len(_spinner)))) / duration
|
||||||
|
t.window.CPrint(tui.ColSpinner, t.strong, _spinner[idx])
|
||||||
|
}
|
||||||
|
t.move(1, 2, false)
|
||||||
|
pos = 2
|
||||||
|
case infoInline:
|
||||||
pos = t.promptLen + t.queryLen[0] + t.queryLen[1] + 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
|
||||||
@ -737,15 +751,8 @@ func (t *Terminal) printInfo() {
|
|||||||
t.window.CPrint(tui.ColPrompt, t.strong, " < ")
|
t.window.CPrint(tui.ColPrompt, t.strong, " < ")
|
||||||
}
|
}
|
||||||
pos += len(" < ")
|
pos += len(" < ")
|
||||||
} else {
|
case infoHidden:
|
||||||
t.move(1, 0, true)
|
return
|
||||||
if t.reading {
|
|
||||||
duration := int64(spinnerDuration)
|
|
||||||
idx := (time.Now().UnixNano() % (duration * int64(len(_spinner)))) / duration
|
|
||||||
t.window.CPrint(tui.ColSpinner, t.strong, _spinner[idx])
|
|
||||||
}
|
|
||||||
t.move(1, 2, false)
|
|
||||||
pos = 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
found := t.merger.Length()
|
found := t.merger.Length()
|
||||||
@ -787,7 +794,7 @@ func (t *Terminal) printHeader() {
|
|||||||
var state *ansiState
|
var state *ansiState
|
||||||
for idx, lineStr := range t.header {
|
for idx, lineStr := range t.header {
|
||||||
line := idx + 2
|
line := idx + 2
|
||||||
if t.inlineInfo {
|
if t.noInfoLine() {
|
||||||
line--
|
line--
|
||||||
}
|
}
|
||||||
if line >= max {
|
if line >= max {
|
||||||
@ -816,7 +823,7 @@ func (t *Terminal) printList() {
|
|||||||
i = maxy - 1 - j
|
i = maxy - 1 - j
|
||||||
}
|
}
|
||||||
line := i + 2 + len(t.header)
|
line := i + 2 + len(t.header)
|
||||||
if t.inlineInfo {
|
if t.noInfoLine() {
|
||||||
line--
|
line--
|
||||||
}
|
}
|
||||||
if i < count {
|
if i < count {
|
||||||
@ -1590,9 +1597,6 @@ func (t *Terminal) Loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit := func(getCode func() int) {
|
exit := func(getCode func() int) {
|
||||||
if !t.cleanExit && t.fullscreen && t.inlineInfo {
|
|
||||||
t.placeCursor()
|
|
||||||
}
|
|
||||||
t.tui.Close()
|
t.tui.Close()
|
||||||
code := getCode()
|
code := getCode()
|
||||||
if code <= exitNoMatch && t.history != nil {
|
if code <= exitNoMatch && t.history != nil {
|
||||||
@ -1613,7 +1617,7 @@ func (t *Terminal) Loop() {
|
|||||||
switch req {
|
switch req {
|
||||||
case reqPrompt:
|
case reqPrompt:
|
||||||
t.printPrompt()
|
t.printPrompt()
|
||||||
if t.inlineInfo {
|
if t.noInfoLine() {
|
||||||
t.printInfo()
|
t.printInfo()
|
||||||
}
|
}
|
||||||
case reqInfo:
|
case reqInfo:
|
||||||
@ -1995,7 +1999,7 @@ func (t *Terminal) Loop() {
|
|||||||
my -= t.window.Top()
|
my -= t.window.Top()
|
||||||
mx = util.Constrain(mx-t.promptLen, 0, len(t.input))
|
mx = util.Constrain(mx-t.promptLen, 0, len(t.input))
|
||||||
min := 2 + len(t.header)
|
min := 2 + len(t.header)
|
||||||
if t.inlineInfo {
|
if t.noInfoLine() {
|
||||||
min--
|
min--
|
||||||
}
|
}
|
||||||
h := t.window.Height()
|
h := t.window.Height()
|
||||||
@ -2151,7 +2155,7 @@ func (t *Terminal) vset(o int) bool {
|
|||||||
|
|
||||||
func (t *Terminal) maxItems() int {
|
func (t *Terminal) maxItems() int {
|
||||||
max := t.window.Height() - 2 - len(t.header)
|
max := t.window.Height() - 2 - len(t.header)
|
||||||
if t.inlineInfo {
|
if t.noInfoLine() {
|
||||||
max++
|
max++
|
||||||
}
|
}
|
||||||
return util.Max(max, 0)
|
return util.Max(max, 0)
|
||||||
|
@ -1516,6 +1516,11 @@ class TestGoFZF < TestBase
|
|||||||
tmux.until { |lines| lines[-1] == prompt }
|
tmux.until { |lines| lines[-1] == prompt }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_info_hidden
|
||||||
|
tmux.send_keys 'seq 10 | fzf --info=hidden', :Enter
|
||||||
|
tmux.until { |lines| lines[-2] == '> 1' }
|
||||||
|
end
|
||||||
|
|
||||||
def test_change_top
|
def test_change_top
|
||||||
tmux.send_keys %(seq 1000 | #{FZF} --bind change:top), :Enter
|
tmux.send_keys %(seq 1000 | #{FZF} --bind change:top), :Enter
|
||||||
tmux.until { |lines| lines.match_count == 1000 }
|
tmux.until { |lines| lines.match_count == 1000 }
|
||||||
|
Loading…
Reference in New Issue
Block a user