change-nth: empty value restores default --nth

- Same rule as change-with-nth and transform-with-nth
    - Empty: default
    - '..': all fields
    - Non-empty invalid: ignored
- Previously, change-nth() and empty transform-nth output searched
  all fields, and transform-nth could not restore default
- Partly reverts af0014ab. Use change-nth(..) to unset default
This commit is contained in:
Junegunn Choi committed 2026-10-21 08:29:43 +09:00
1 parent c943963281
commit d3d6e40962
4 files changed
+48 -14

No files matched your search

+3 -1
View File
@@ -9,7 +9,9 @@ CHANGELOG
- Only `change-nth` and `change-with-nth` rotate through `|`-separated values
- Fixed the bound command being replaced with the output. e.g. With `transform-nth(echo '1|2')`, the next key press ran `2|1` as a shell command.
- A `--with-nth` template in the output can now contain `|`. e.g. `{2}|{1}` was cut to `{2}`.
- An invalid value for `change-nth` and `transform-nth` no longer restores the default `--nth`. It is ignored, as with `change-with-nth` and `transform-with-nth`.
- `change-nth` and `transform-nth` now handle empty and invalid values the same way as `change-with-nth` and `transform-with-nth`
- An empty value restores the default `--nth`. Previously, `change-nth()` and an empty `transform-nth` output searched all fields. Use `change-nth(..)` for that.
- A non-empty invalid value is ignored. Previously, it restored the default `--nth`.
- `change-nth` and `change-with-nth` now apply the value after the current one in the `|`-separated list
- A value equal to the current one is skipped, e.g. the first value when it is the initial `--nth`
- Invalid values in the list are skipped
+26 -4
View File
@@ -2060,8 +2060,8 @@ A key or an event can be bound to one or more of the following actions.
\fBchange\-list\-label(...)\fR (change \fB\-\-list\-label\fR to the given string)
\fBchange\-multi\fR (enable multi-select mode with no limit)
\fBchange\-multi(...)\fR (enable multi-select mode with a limit or disable it with 0)
\fBchange\-nth(...)\fR (change \fB\-\-nth\fR option; rotate through the multiple options separated by '|', starting from the one after the current option)
\fBchange\-with\-nth(...)\fR (change \fB\-\-with\-nth\fR option; rotate through the multiple options separated by '|', starting from the one after the current option)
\fBchange\-nth(...)\fR (change \fB\-\-nth\fR option; see CHANGE NTH AND WITH\-NTH)
\fBchange\-with\-nth(...)\fR (change \fB\-\-with\-nth\fR option; see CHANGE NTH AND WITH\-NTH)
\fBchange\-pointer(...)\fR (change \fB\-\-pointer\fR option)
\fBchange\-preview(...)\fR (change \fB\-\-preview\fR option)
\fBchange\-preview\-label(...)\fR (change \fB\-\-preview\-label\fR to the given string)
@@ -2166,8 +2166,8 @@ A key or an event can be bound to one or more of the following actions.
\fBtransform\-header\-label(...)\fR (transform header label using an external command)
\fBtransform\-input\-label(...)\fR (transform input label using an external command)
\fBtransform\-list\-label(...)\fR (transform list label using an external command)
\fBtransform\-nth(...)\fR (transform nth using an external command; no rotation, output is used as a whole)
\fBtransform\-with\-nth(...)\fR (transform with-nth using an external command; no rotation, output is used as a whole)
\fBtransform\-nth(...)\fR (transform nth using an external command; see CHANGE NTH AND WITH\-NTH)
\fBtransform\-with\-nth(...)\fR (transform with-nth using an external command; see CHANGE NTH AND WITH\-NTH)
\fBtransform\-pointer(...)\fR (transform pointer using an external command)
\fBtransform\-preview\-label(...)\fR (transform preview label using an external command)
\fBtransform\-prompt(...)\fR (transform prompt string using an external command)
@@ -2405,6 +2405,28 @@ e.g.
# This is equivalent to toggle\-preview action
fzf \-\-preview 'cat {}' \-\-bind 'ctrl\-/:change\-preview\-window(hidden|)'
.SS CHANGE NTH AND WITH\-NTH
\fBchange\-nth\fR and \fBchange\-with\-nth\fR actions change \fB\-\-nth\fR and
\fB\-\-with\-nth\fR options. You can specify multiple values separated by '|'
characters. Each time the action runs, fzf applies the value after the current
one in the list, skipping the values equal to the current one.
\fBtransform\-nth\fR and \fBtransform\-with\-nth\fR actions (and their
\fBbg\-\fR variants) take the output of the command as a single value. The
following rules apply to all of these actions.
* An empty value restores the default given by the option
* \fB..\fR selects all fields
* A non\-empty invalid value is ignored
e.g.
# All fields, then fields 1, 2, and 3
fzf \-\-bind 'ctrl\-/:change\-nth(..|1|2|3)'
# An empty string in the list is interpreted as the default
fzf \-\-nth 1 \-\-bind 'ctrl\-/:change\-nth(2|)'
.SH AUTHOR
Junegunn Choi (\fIjunegunn.c@gmail.com\fR)
+5 -8
View File
@@ -7341,18 +7341,15 @@ func (t *Terminal) Loop() error {
req(reqList, reqInfo)
case actChangeNth, actTransformNth, actBgTransformNth:
capture(true, func(expr string) {
empty := len(expr) == 0
// Empty value means all fields if it is the whole
// expression, otherwise the default --nth
resolve := func(value string) ([]Range, bool) {
if nth, err := splitNth(value); err == nil || empty {
return nth, true
} else if len(value) == 0 {
// Empty value restores the default --nth
if len(value) == 0 {
return t.nth, true
}
return nil, false
nth, err := splitNth(value)
return nth, err == nil
}
// Empty or a single '..' means all fields
// Empty range list or a single '..' means all fields
allFields := func(nth []Range) bool {
return len(nth) == 0 || len(nth) == 1 && nth[0].IsFull()
}
+14 -1
View File
@@ -3033,7 +3033,7 @@ class TestCore < TestInteractive
end
def test_change_nth_unset_default
tmux.send_keys %(echo foo bar | #{FZF} --nth 2 --query fb --bind space:change-nth:), :Enter
tmux.send_keys %(echo foo bar | #{FZF} --nth 2 --query fb --bind space:change-nth:..), :Enter
tmux.until do
assert_equal 1, it.item_count
assert_equal 0, it.match_count
@@ -3047,6 +3047,19 @@ class TestCore < TestInteractive
end
end
def test_change_nth_empty_restores_default
tmux.send_keys %(echo foo bar | #{FZF} --nth 2 --query fb --bind 'a:change-nth(..),space:change-nth(),b:transform-nth(true)'), :Enter
tmux.until { |lines| assert_equal 0, lines.match_count }
tmux.send_keys :a
tmux.until { |lines| assert_equal 1, lines.match_count }
tmux.send_keys :Space
tmux.until { |lines| assert_equal 0, lines.match_count }
tmux.send_keys :a
tmux.until { |lines| assert_equal 1, lines.match_count }
tmux.send_keys :b
tmux.until { |lines| assert_equal 0, lines.match_count }
end
def test_change_header_lines
tmux.send_keys %(seq 10 | #{FZF} --header-lines 3 --bind 'space:change-header-lines(5),enter:transform-header-lines(echo 1)'), :Enter
tmux.until do |lines|