mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2025-01-24 15:48:27 +00:00
parent
c0435fdff4
commit
f83491274f
@ -1,7 +1,7 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
0.42.1
|
0.43.0
|
||||||
------
|
------
|
||||||
- `--listen` server can be secured by setting `$FZF_API_KEY` environment
|
- `--listen` server can be secured by setting `$FZF_API_KEY` environment
|
||||||
variable.
|
variable.
|
||||||
@ -14,6 +14,7 @@ CHANGELOG
|
|||||||
# Client
|
# Client
|
||||||
curl localhost:6266 -H "x-api-key: $FZF_API_KEY" -d 'change-query(yo)'
|
curl localhost:6266 -H "x-api-key: $FZF_API_KEY" -d 'change-query(yo)'
|
||||||
```
|
```
|
||||||
|
- Added `toggle-header` action
|
||||||
|
|
||||||
0.42.0
|
0.42.0
|
||||||
------
|
------
|
||||||
|
@ -1137,6 +1137,7 @@ A key or an event can be bound to one or more of the following actions.
|
|||||||
\fBtoggle\fR (\fIright-click\fR)
|
\fBtoggle\fR (\fIright-click\fR)
|
||||||
\fBtoggle-all\fR (toggle all matches)
|
\fBtoggle-all\fR (toggle all matches)
|
||||||
\fBtoggle+down\fR \fIctrl-i (tab)\fR
|
\fBtoggle+down\fR \fIctrl-i (tab)\fR
|
||||||
|
\fBtoggle-header\fR
|
||||||
\fBtoggle-in\fR (\fB--layout=reverse*\fR ? \fBtoggle+up\fR : \fBtoggle+down\fR)
|
\fBtoggle-in\fR (\fB--layout=reverse*\fR ? \fBtoggle+up\fR : \fBtoggle+down\fR)
|
||||||
\fBtoggle-out\fR (\fB--layout=reverse*\fR ? \fBtoggle+down\fR : \fBtoggle+up\fR)
|
\fBtoggle-out\fR (\fB--layout=reverse*\fR ? \fBtoggle+down\fR : \fBtoggle+up\fR)
|
||||||
\fBtoggle-preview\fR
|
\fBtoggle-preview\fR
|
||||||
|
@ -1115,6 +1115,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA
|
|||||||
appendAction(actToggleSearch)
|
appendAction(actToggleSearch)
|
||||||
case "toggle-track":
|
case "toggle-track":
|
||||||
appendAction(actToggleTrack)
|
appendAction(actToggleTrack)
|
||||||
|
case "toggle-header":
|
||||||
|
appendAction(actToggleHeader)
|
||||||
case "track":
|
case "track":
|
||||||
appendAction(actTrack)
|
appendAction(actTrack)
|
||||||
case "select":
|
case "select":
|
||||||
|
@ -125,6 +125,7 @@ type eachLine struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type itemLine struct {
|
type itemLine struct {
|
||||||
|
offset int
|
||||||
current bool
|
current bool
|
||||||
selected bool
|
selected bool
|
||||||
label string
|
label string
|
||||||
@ -192,6 +193,7 @@ type Terminal struct {
|
|||||||
printQuery bool
|
printQuery bool
|
||||||
history *History
|
history *History
|
||||||
cycle bool
|
cycle bool
|
||||||
|
headerVisible bool
|
||||||
headerFirst bool
|
headerFirst bool
|
||||||
headerLines int
|
headerLines int
|
||||||
header []string
|
header []string
|
||||||
@ -341,6 +343,7 @@ const (
|
|||||||
actToggleIn
|
actToggleIn
|
||||||
actToggleOut
|
actToggleOut
|
||||||
actToggleTrack
|
actToggleTrack
|
||||||
|
actToggleHeader
|
||||||
actTrack
|
actTrack
|
||||||
actDown
|
actDown
|
||||||
actUp
|
actUp
|
||||||
@ -628,6 +631,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
|||||||
cleanExit: opts.ClearOnExit,
|
cleanExit: opts.ClearOnExit,
|
||||||
paused: opts.Phony,
|
paused: opts.Phony,
|
||||||
cycle: opts.Cycle,
|
cycle: opts.Cycle,
|
||||||
|
headerVisible: true,
|
||||||
headerFirst: opts.HeaderFirst,
|
headerFirst: opts.HeaderFirst,
|
||||||
headerLines: opts.HeaderLines,
|
headerLines: opts.HeaderLines,
|
||||||
header: []string{},
|
header: []string{},
|
||||||
@ -734,9 +738,16 @@ func borderLines(shape tui.BorderShape) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Terminal) visibleHeaderLines() int {
|
||||||
|
if !t.headerVisible {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return len(t.header0) + t.headerLines
|
||||||
|
}
|
||||||
|
|
||||||
// Extra number of lines needed to display fzf
|
// Extra number of lines needed to display fzf
|
||||||
func (t *Terminal) extraLines() int {
|
func (t *Terminal) extraLines() int {
|
||||||
extra := len(t.header0) + t.headerLines + 1
|
extra := t.visibleHeaderLines() + 1
|
||||||
if !t.noInfoLine() {
|
if !t.noInfoLine() {
|
||||||
extra++
|
extra++
|
||||||
}
|
}
|
||||||
@ -1386,7 +1397,7 @@ func (t *Terminal) move(y int, x int, clear bool) {
|
|||||||
case layoutDefault:
|
case layoutDefault:
|
||||||
y = h - y - 1
|
y = h - y - 1
|
||||||
case layoutReverseList:
|
case layoutReverseList:
|
||||||
n := 2 + len(t.header0) + len(t.header)
|
n := 2 + t.visibleHeaderLines()
|
||||||
if t.noInfoLine() {
|
if t.noInfoLine() {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
@ -1430,7 +1441,7 @@ func (t *Terminal) promptLine() int {
|
|||||||
if !t.noInfoLine() {
|
if !t.noInfoLine() {
|
||||||
max--
|
max--
|
||||||
}
|
}
|
||||||
return util.Min(len(t.header0)+t.headerLines, max)
|
return util.Min(t.visibleHeaderLines(), max)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -1583,7 +1594,7 @@ func (t *Terminal) printInfo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) printHeader() {
|
func (t *Terminal) printHeader() {
|
||||||
if len(t.header0)+len(t.header) == 0 {
|
if t.visibleHeaderLines() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
max := t.window.Height()
|
max := t.window.Height()
|
||||||
@ -1611,7 +1622,8 @@ func (t *Terminal) printHeader() {
|
|||||||
text: util.ToChars([]byte(trimmed)),
|
text: util.ToChars([]byte(trimmed)),
|
||||||
colors: colors}
|
colors: colors}
|
||||||
|
|
||||||
t.move(line, 2, true)
|
t.move(line, 0, true)
|
||||||
|
t.window.Print(" ")
|
||||||
t.printHighlighted(Result{item: item},
|
t.printHighlighted(Result{item: item},
|
||||||
tui.ColHeader, tui.ColHeader, false, false)
|
tui.ColHeader, tui.ColHeader, false, false)
|
||||||
}
|
}
|
||||||
@ -1628,13 +1640,13 @@ func (t *Terminal) printList() {
|
|||||||
if t.layout == layoutDefault {
|
if t.layout == layoutDefault {
|
||||||
i = maxy - 1 - j
|
i = maxy - 1 - j
|
||||||
}
|
}
|
||||||
line := i + 2 + len(t.header0) + len(t.header)
|
line := i + 2 + t.visibleHeaderLines()
|
||||||
if t.noInfoLine() {
|
if t.noInfoLine() {
|
||||||
line--
|
line--
|
||||||
}
|
}
|
||||||
if i < count {
|
if i < count {
|
||||||
t.printItem(t.merger.Get(i+t.offset), line, i, i == t.cy-t.offset, i >= barStart && i < barStart+barLength)
|
t.printItem(t.merger.Get(i+t.offset), line, i, i == t.cy-t.offset, i >= barStart && i < barStart+barLength)
|
||||||
} else if t.prevLines[i] != emptyLine {
|
} else if t.prevLines[i] != emptyLine || t.prevLines[i].offset != line {
|
||||||
t.prevLines[i] = emptyLine
|
t.prevLines[i] = emptyLine
|
||||||
t.move(line, 0, true)
|
t.move(line, 0, true)
|
||||||
}
|
}
|
||||||
@ -1656,11 +1668,12 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool, bar b
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Avoid unnecessary redraw
|
// Avoid unnecessary redraw
|
||||||
newLine := itemLine{current: current, selected: selected, label: label,
|
newLine := itemLine{offset: line, current: current, selected: selected, label: label,
|
||||||
result: result, queryLen: len(t.input), width: 0, bar: bar}
|
result: result, queryLen: len(t.input), width: 0, bar: bar}
|
||||||
prevLine := t.prevLines[i]
|
prevLine := t.prevLines[i]
|
||||||
|
forceRedraw := prevLine.offset != newLine.offset
|
||||||
printBar := func() {
|
printBar := func() {
|
||||||
if len(t.scrollbar) > 0 && bar != prevLine.bar {
|
if len(t.scrollbar) > 0 && (bar != prevLine.bar || forceRedraw) {
|
||||||
t.prevLines[i].bar = bar
|
t.prevLines[i].bar = bar
|
||||||
t.move(line, t.window.Width()-1, true)
|
t.move(line, t.window.Width()-1, true)
|
||||||
if bar {
|
if bar {
|
||||||
@ -1669,7 +1682,8 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool, bar b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevLine.current == newLine.current &&
|
if !forceRedraw &&
|
||||||
|
prevLine.current == newLine.current &&
|
||||||
prevLine.selected == newLine.selected &&
|
prevLine.selected == newLine.selected &&
|
||||||
prevLine.label == newLine.label &&
|
prevLine.label == newLine.label &&
|
||||||
prevLine.queryLen == newLine.queryLen &&
|
prevLine.queryLen == newLine.queryLen &&
|
||||||
@ -1678,7 +1692,7 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool, bar b
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
t.move(line, 0, false)
|
t.move(line, 0, forceRedraw)
|
||||||
if current {
|
if current {
|
||||||
if len(label) == 0 {
|
if len(label) == 0 {
|
||||||
t.window.CPrint(tui.ColCurrentCursorEmpty, t.pointerEmpty)
|
t.window.CPrint(tui.ColCurrentCursorEmpty, t.pointerEmpty)
|
||||||
@ -3403,6 +3417,9 @@ func (t *Terminal) Loop() {
|
|||||||
t.track = trackEnabled
|
t.track = trackEnabled
|
||||||
}
|
}
|
||||||
req(reqInfo)
|
req(reqInfo)
|
||||||
|
case actToggleHeader:
|
||||||
|
t.headerVisible = !t.headerVisible
|
||||||
|
req(reqList, reqInfo, reqPrompt, reqHeader)
|
||||||
case actTrack:
|
case actTrack:
|
||||||
if t.track == trackDisabled {
|
if t.track == trackDisabled {
|
||||||
t.track = trackCurrent
|
t.track = trackCurrent
|
||||||
@ -3485,7 +3502,7 @@ func (t *Terminal) Loop() {
|
|||||||
// Translate coordinates
|
// Translate coordinates
|
||||||
mx -= t.window.Left()
|
mx -= t.window.Left()
|
||||||
my -= t.window.Top()
|
my -= t.window.Top()
|
||||||
min := 2 + len(t.header0) + len(t.header)
|
min := 2 + t.visibleHeaderLines()
|
||||||
if t.noInfoLine() {
|
if t.noInfoLine() {
|
||||||
min--
|
min--
|
||||||
}
|
}
|
||||||
@ -3757,7 +3774,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.header0) - len(t.header)
|
max := t.window.Height() - 2 - t.visibleHeaderLines()
|
||||||
if t.noInfoLine() {
|
if t.noInfoLine() {
|
||||||
max++
|
max++
|
||||||
}
|
}
|
||||||
|
@ -1213,6 +1213,39 @@ class TestGoFZF < TestBase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_toggle_header
|
||||||
|
tmux.send_keys "seq 4 | #{FZF} --header-lines 2 --header foo --bind space:toggle-header --header-first --height 10 --border", :Enter
|
||||||
|
before = <<~OUTPUT
|
||||||
|
╭───────
|
||||||
|
│
|
||||||
|
│ 4
|
||||||
|
│ > 3
|
||||||
|
│ 2/2
|
||||||
|
│ >
|
||||||
|
│ 2
|
||||||
|
│ 1
|
||||||
|
│ foo
|
||||||
|
╰───────
|
||||||
|
OUTPUT
|
||||||
|
tmux.until { assert_block(before, _1) }
|
||||||
|
tmux.send_keys :Space
|
||||||
|
after = <<~OUTPUT
|
||||||
|
╭───────
|
||||||
|
│
|
||||||
|
│
|
||||||
|
│
|
||||||
|
│
|
||||||
|
│ 4
|
||||||
|
│ > 3
|
||||||
|
│ 2/2
|
||||||
|
│ >
|
||||||
|
╰───────
|
||||||
|
OUTPUT
|
||||||
|
tmux.until { assert_block(after, _1) }
|
||||||
|
tmux.send_keys :Space
|
||||||
|
tmux.until { assert_block(before, _1) }
|
||||||
|
end
|
||||||
|
|
||||||
def test_cancel
|
def test_cancel
|
||||||
tmux.send_keys "seq 10 | #{fzf('--bind 2:cancel')}", :Enter
|
tmux.send_keys "seq 10 | #{fzf('--bind 2:cancel')}", :Enter
|
||||||
tmux.until { |lines| assert_equal ' 10/10', lines[-2] }
|
tmux.until { |lines| assert_equal ' 10/10', lines[-2] }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user