mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-09 11:53:47 -05:00
Compare commits
11 Commits
dependabot
...
devel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2773d5bc3 | ||
|
|
5e2d96d5e6 | ||
|
|
e659b46ff5 | ||
|
|
991c36453c | ||
|
|
4d563c6dfa | ||
|
|
5cb695744f | ||
|
|
c1b259c042 | ||
|
|
1a0371e2c7 | ||
|
|
aa259fdc19 | ||
|
|
b852dc8a56 | ||
|
|
a0cabe021d |
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,6 +1,30 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
0.67.0
|
||||
------
|
||||
- Added `--freeze-left=N` option to keep the leftmost N columns visible.
|
||||
```sh
|
||||
# Keeps the file name column fixed and always visible
|
||||
git grep --line-number --color=always -- '' |
|
||||
fzf --ansi --delimiter : --freeze-left 1
|
||||
|
||||
# Used with --keep-right
|
||||
git grep --line-number --color=always -- '' |
|
||||
fzf --ansi --delimiter : --freeze-left 1 --keep-right
|
||||
```
|
||||
- Also added `--freeze-right=N` option to keep the rightmost N columns visible.
|
||||
```sh
|
||||
fd | fzf --freeze-right 1 --delimiter /
|
||||
fd | fzf --freeze-left 1 --freeze-right 1 --delimiter /
|
||||
```
|
||||
|
||||
0.66.1
|
||||
------
|
||||
- Bug fixes
|
||||
- Fixed a bug preventing 'ctrl-h' from being bound to an action (#4556)
|
||||
- Fixed `--no-color` / `NO_COLOR` theme (#4561)
|
||||
|
||||
0.66.0
|
||||
------
|
||||
|
||||
@@ -35,10 +59,10 @@ This version introduces many new features centered around the new "raw" mode.
|
||||
|
||||
This version introduces a new "raw" mode (named so because it shows the list
|
||||
"unfiltered"). In raw mode, non-matching items stay in their original positions,
|
||||
but appear dimmed. This allows you see surrounding items of a match and better
|
||||
understand the context of it. You can enable raw mode by default with `--raw`,
|
||||
but it's often more useful when toggled dynamically with the `toggle-raw`
|
||||
action.
|
||||
but appear dimmed. This allows you to see the surrounding items of a match and
|
||||
better understand the context of it. You can enable raw mode by default with
|
||||
`--raw`, but it's often more useful when toggled dynamically with the
|
||||
`toggle-raw` action.
|
||||
|
||||
```sh
|
||||
tree | fzf --reverse --bind alt-r:toggle-raw
|
||||
|
||||
2
install
2
install
@@ -2,7 +2,7 @@
|
||||
|
||||
set -u
|
||||
|
||||
version=0.66.0
|
||||
version=0.66.1
|
||||
auto_completion=
|
||||
key_bindings=
|
||||
update_config=2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$version="0.66.0"
|
||||
$version="0.66.1"
|
||||
|
||||
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
..
|
||||
.TH fzf\-tmux 1 "Oct 2025" "fzf 0.66.0" "fzf\-tmux - open fzf in tmux split pane"
|
||||
.TH fzf\-tmux 1 "Oct 2025" "fzf 0.66.1" "fzf\-tmux - open fzf in tmux split pane"
|
||||
|
||||
.SH NAME
|
||||
fzf\-tmux - open fzf in tmux split pane
|
||||
|
||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
..
|
||||
.TH fzf 1 "Oct 2025" "fzf 0.66.0" "fzf - a command-line fuzzy finder"
|
||||
.TH fzf 1 "Oct 2025" "fzf 0.66.1" "fzf - a command-line fuzzy finder"
|
||||
|
||||
.SH NAME
|
||||
fzf - a command-line fuzzy finder
|
||||
@@ -629,9 +629,16 @@ Render empty lines between each item
|
||||
The given string will be repeated to draw a horizontal line on each gap
|
||||
(default: '┈' or '\-' depending on \fB\-\-no\-unicode\fR).
|
||||
.TP
|
||||
.BI "\-\-freeze\-left=" "N"
|
||||
Number of fields to freeze on the left.
|
||||
.TP
|
||||
.BI "\-\-freeze\-right=" "N"
|
||||
Number of fields to freeze on the right.
|
||||
.TP
|
||||
.B "\-\-keep\-right"
|
||||
Keep the right end of the line visible when it's too long. Effective only when
|
||||
the query string is empty.
|
||||
the query string is empty. Use \fB\-\-freeze\-right=1\fR instead if you want
|
||||
the last field to be always visible even with a non-empty query.
|
||||
.TP
|
||||
.BI "\-\-scroll\-off=" "LINES"
|
||||
Number of screen lines to keep above or below when scrolling to the top or to
|
||||
@@ -651,6 +658,9 @@ Label characters for \fBjump\fR mode.
|
||||
.BI "\-\-gutter=" "CHAR"
|
||||
Character used for the gutter column (default: '▌' unless \fB\-\-no\-unicode\fR is given)
|
||||
.TP
|
||||
.BI "\-\-gutter\-raw=" "CHAR"
|
||||
Character used for the gutter column in raw mode (default: '▖' unless \fB\-\-no\-unicode\fR is given)
|
||||
.TP
|
||||
.BI "\-\-pointer=" "STR"
|
||||
Pointer to the current line (default: '▌' or '>' depending on \fB\-\-no\-unicode\fR)
|
||||
.TP
|
||||
|
||||
@@ -26,7 +26,10 @@ __fzf_exec_awk() {
|
||||
# version >= 1.3.4
|
||||
local n x y z d
|
||||
IFS=' .' read -r n x y z d <<< $(command mawk -W version 2> /dev/null)
|
||||
[[ $n == mawk ]] && ((d >= 20230302 && (x * 1000 + y) * 1000 + z >= 1003004)) && __fzf_awk=mawk
|
||||
[[ $n == mawk ]] &&
|
||||
(((x * 1000 + y) * 1000 + z >= 1003004)) 2> /dev/null &&
|
||||
((d >= 20230302)) 2> /dev/null &&
|
||||
__fzf_awk=mawk
|
||||
fi
|
||||
fi
|
||||
# Note: macOS awk has a quirk that it stops processing at all when it sees
|
||||
|
||||
@@ -51,7 +51,10 @@ __fzf_exec_awk() {
|
||||
elif command -v mawk > /dev/null 2>&1; then
|
||||
local n x y z d
|
||||
IFS=' .' read -r n x y z d <<< $(command mawk -W version 2> /dev/null)
|
||||
[[ $n == mawk ]] && ((d >= 20230302 && (x * 1000 + y) * 1000 + z >= 1003004)) && __fzf_awk=mawk
|
||||
[[ $n == mawk ]] &&
|
||||
(((x * 1000 + y) * 1000 + z >= 1003004)) 2> /dev/null &&
|
||||
((d >= 20230302)) 2> /dev/null &&
|
||||
__fzf_awk=mawk
|
||||
fi
|
||||
fi
|
||||
LC_ALL=C exec "$__fzf_awk" "$@"
|
||||
|
||||
@@ -115,7 +115,10 @@ __fzf_exec_awk() {
|
||||
elif command -v mawk > /dev/null 2>&1; then
|
||||
local n x y z d
|
||||
IFS=' .' read -r n x y z d <<< $(command mawk -W version 2> /dev/null)
|
||||
[[ $n == mawk ]] && ((d >= 20230302 && (x * 1000 + y) * 1000 + z >= 1003004)) && __fzf_awk=mawk
|
||||
[[ $n == mawk ]] &&
|
||||
(((x * 1000 + y) * 1000 + z >= 1003004)) 2> /dev/null &&
|
||||
((d >= 20230302)) 2> /dev/null &&
|
||||
__fzf_awk=mawk
|
||||
fi
|
||||
fi
|
||||
LC_ALL=C exec "$__fzf_awk" "$@"
|
||||
|
||||
@@ -38,7 +38,10 @@ __fzf_exec_awk() {
|
||||
elif command -v mawk > /dev/null 2>&1; then
|
||||
local n x y z d
|
||||
IFS=' .' read -r n x y z d <<< $(command mawk -W version 2> /dev/null)
|
||||
[[ $n == mawk ]] && ((d >= 20230302 && (x * 1000 + y) * 1000 + z >= 1003004)) && __fzf_awk=mawk
|
||||
[[ $n == mawk ]] &&
|
||||
(((x * 1000 + y) * 1000 + z >= 1003004)) 2> /dev/null &&
|
||||
((d >= 20230302)) 2> /dev/null &&
|
||||
__fzf_awk=mawk
|
||||
fi
|
||||
fi
|
||||
LC_ALL=C exec "$__fzf_awk" "$@"
|
||||
|
||||
@@ -58,7 +58,10 @@ __fzf_exec_awk() {
|
||||
elif command -v mawk > /dev/null 2>&1; then
|
||||
local n x y z d
|
||||
IFS=' .' read -r n x y z d <<< $(command mawk -W version 2> /dev/null)
|
||||
[[ $n == mawk ]] && ((d >= 20230302 && (x * 1000 + y) * 1000 + z >= 1003004)) && __fzf_awk=mawk
|
||||
[[ $n == mawk ]] &&
|
||||
(((x * 1000 + y) * 1000 + z >= 1003004)) 2> /dev/null &&
|
||||
((d >= 20230302)) 2> /dev/null &&
|
||||
__fzf_awk=mawk
|
||||
fi
|
||||
fi
|
||||
LC_ALL=C exec "$__fzf_awk" "$@"
|
||||
|
||||
@@ -104,6 +104,8 @@ Usage: fzf [options]
|
||||
--gap[=N] Render empty lines between each item
|
||||
--gap-line[=STR] Draw horizontal line on each gap using the string
|
||||
(default: '┈' or '-')
|
||||
--freeze-left=N Number of fields to freeze on the left
|
||||
--freeze-right=N Number of fields to freeze on the right
|
||||
--keep-right Keep the right end of the line visible on overflow
|
||||
--scroll-off=LINES Number of screen lines to keep above or below when
|
||||
scrolling to the top or to the bottom (default: 0)
|
||||
@@ -562,6 +564,8 @@ type Options struct {
|
||||
Case Case
|
||||
Normalize bool
|
||||
Nth []Range
|
||||
FreezeLeft int
|
||||
FreezeRight int
|
||||
WithNth func(Delimiter) func([]Token, int32) string
|
||||
AcceptNth func(Delimiter) func([]Token, int32) string
|
||||
Delimiter Delimiter
|
||||
@@ -673,9 +677,10 @@ func defaultPreviewOpts(command string) previewOpts {
|
||||
}
|
||||
|
||||
func defaultOptions() *Options {
|
||||
var theme *tui.ColorTheme
|
||||
var theme, baseTheme *tui.ColorTheme
|
||||
if os.Getenv("NO_COLOR") != "" {
|
||||
theme = tui.NoColorTheme
|
||||
baseTheme = tui.NoColorTheme
|
||||
} else {
|
||||
theme = tui.EmptyTheme
|
||||
}
|
||||
@@ -703,6 +708,7 @@ func defaultOptions() *Options {
|
||||
Ansi: false,
|
||||
Mouse: true,
|
||||
Theme: theme,
|
||||
BaseTheme: baseTheme,
|
||||
Black: false,
|
||||
Bold: true,
|
||||
MinHeight: -10,
|
||||
@@ -2693,6 +2699,14 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
||||
if opts.Nth, err = splitNth(str); err != nil {
|
||||
return err
|
||||
}
|
||||
case "--freeze-left":
|
||||
if opts.FreezeLeft, err = nextInt("number of fields required"); err != nil {
|
||||
return err
|
||||
}
|
||||
case "--freeze-right":
|
||||
if opts.FreezeRight, err = nextInt("number of fields required"); err != nil {
|
||||
return err
|
||||
}
|
||||
case "--with-nth":
|
||||
str, err := nextString("nth expression required")
|
||||
if err != nil {
|
||||
@@ -3336,6 +3350,10 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
||||
return errors.New("empty jump labels")
|
||||
}
|
||||
|
||||
if opts.FreezeLeft < 0 || opts.FreezeRight < 0 {
|
||||
return errors.New("number of fields to freeze must be a non-negative integer")
|
||||
}
|
||||
|
||||
if validateJumpLabels {
|
||||
for _, r := range opts.JumpLabels {
|
||||
if r < 32 || r > 126 {
|
||||
|
||||
200
src/terminal.go
200
src/terminal.go
@@ -331,6 +331,8 @@ type Terminal struct {
|
||||
scrollbar string
|
||||
previewScrollbar string
|
||||
ansi bool
|
||||
freezeLeft int
|
||||
freezeRight int
|
||||
nthAttr tui.Attr
|
||||
nth []Range
|
||||
nthCurrent []Range
|
||||
@@ -800,7 +802,6 @@ func defaultKeymap() map[tui.Event][]*action {
|
||||
add(tui.CtrlD, actDeleteCharEof)
|
||||
add(tui.CtrlE, actEndOfLine)
|
||||
add(tui.CtrlF, actForwardChar)
|
||||
add(tui.CtrlH, actBackwardDeleteChar)
|
||||
add(tui.Backspace, actBackwardDeleteChar)
|
||||
add(tui.CtrlBackspace, actBackwardDeleteChar)
|
||||
add(tui.Tab, actToggleDown)
|
||||
@@ -1051,6 +1052,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
||||
footer: opts.Footer,
|
||||
header0: opts.Header,
|
||||
ansi: opts.Ansi,
|
||||
freezeLeft: opts.FreezeLeft,
|
||||
freezeRight: opts.FreezeRight,
|
||||
nthAttr: opts.Theme.Nth.Attr,
|
||||
nth: opts.Nth,
|
||||
nthCurrent: opts.Nth,
|
||||
@@ -2982,6 +2985,11 @@ func (t *Terminal) printInfoImpl() {
|
||||
} else {
|
||||
outputPrinter(t.window, maxWidth)
|
||||
}
|
||||
if t.infoStyle == infoInline && outputLen < maxWidth-1 && t.reading {
|
||||
t.window.Print(" ")
|
||||
printSpinner()
|
||||
outputLen += 2
|
||||
}
|
||||
|
||||
if t.infoStyle == infoInlineRight {
|
||||
if t.separatorLen > 0 {
|
||||
@@ -3521,6 +3529,33 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
||||
}
|
||||
allOffsets := result.colorOffsets(charOffsets, nthOffsets, t.theme, colBase, colMatch, t.nthAttr, hidden)
|
||||
|
||||
// Determine split offset for horizontal scrolling with freeze
|
||||
splitOffset1 := -1
|
||||
splitOffset2 := -1
|
||||
if t.hscroll && !t.wrap {
|
||||
var tokens []Token
|
||||
if t.freezeLeft > 0 || t.freezeRight > 0 {
|
||||
tokens = Tokenize(item.text.ToString(), t.delimiter)
|
||||
}
|
||||
// 0 1 2| 3| 4 5
|
||||
// ----- ---
|
||||
if t.freezeLeft > 0 {
|
||||
if len(tokens) > 0 {
|
||||
token := tokens[util.Min(t.freezeLeft, len(tokens))-1]
|
||||
splitOffset1 = int(token.prefixLength) + token.text.Length() - token.text.TrailingWhitespaces()
|
||||
}
|
||||
}
|
||||
if t.freezeRight > 0 {
|
||||
index := len(tokens) - t.freezeRight - 1
|
||||
if index == t.freezeLeft-1 {
|
||||
splitOffset2 = 0
|
||||
} else if index >= t.freezeLeft {
|
||||
token := tokens[index]
|
||||
splitOffset2 = int(token.prefixLength) + token.text.Length()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxLines := 1
|
||||
if t.canSpanMultiLines() {
|
||||
maxLines = maxLineNum - lineNum + 1
|
||||
@@ -3590,16 +3625,24 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
||||
break
|
||||
}
|
||||
}
|
||||
splitOffsetLeft := 0
|
||||
if splitOffset1 >= 0 && splitOffset1 > from && splitOffset1 < from+len(line) {
|
||||
splitOffsetLeft = splitOffset1 - from
|
||||
}
|
||||
splitOffsetRight := -1
|
||||
if splitOffset2 >= 0 && splitOffset2 >= from && splitOffset2 < from+len(line) {
|
||||
splitOffsetRight = splitOffset2 - from
|
||||
}
|
||||
from += len(line)
|
||||
if lineOffset < skipLines {
|
||||
continue
|
||||
}
|
||||
actualLineOffset := lineOffset - skipLines
|
||||
|
||||
var maxe int
|
||||
var maxEnd int
|
||||
for _, offset := range offsets {
|
||||
if offset.match {
|
||||
maxe = util.Max(maxe, int(offset.offset[1]))
|
||||
maxEnd = util.Max(maxEnd, int(offset.offset[1]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3663,69 +3706,112 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
||||
wrapped = true
|
||||
}
|
||||
|
||||
displayWidth = t.displayWidthWithLimit(line, 0, maxWidth)
|
||||
if !t.wrap && displayWidth > maxWidth {
|
||||
ellipsis, ellipsisWidth := util.Truncate(t.ellipsis, maxWidth/2)
|
||||
maxe = util.Constrain(maxe+util.Min(maxWidth/2-ellipsisWidth, t.hscrollOff), 0, len(line))
|
||||
transformOffsets := func(diff int32, rightTrim bool) {
|
||||
for idx, offset := range offsets {
|
||||
b, e := offset.offset[0], offset.offset[1]
|
||||
el := int32(len(ellipsis))
|
||||
b += el - diff
|
||||
e += el - diff
|
||||
b = util.Max32(b, el)
|
||||
if rightTrim {
|
||||
e = util.Min32(e, int32(maxWidth-ellipsisWidth))
|
||||
}
|
||||
offsets[idx].offset[0] = b
|
||||
offsets[idx].offset[1] = util.Max32(b, e)
|
||||
}
|
||||
frozenLeft := line[:splitOffsetLeft]
|
||||
middle := line[splitOffsetLeft:]
|
||||
frozenRight := []rune{}
|
||||
if splitOffsetRight >= splitOffsetLeft {
|
||||
middle = line[splitOffsetLeft:splitOffsetRight]
|
||||
frozenRight = line[splitOffsetRight:]
|
||||
}
|
||||
displayWidthSum := 0
|
||||
todo := [3]func(){}
|
||||
for fidx, runes := range [][]rune{frozenLeft, frozenRight, middle} {
|
||||
if len(runes) == 0 {
|
||||
continue
|
||||
}
|
||||
if t.hscroll {
|
||||
if t.keepRight && pos == nil {
|
||||
trimmed, diff := t.trimLeft(line, maxWidth, ellipsisWidth)
|
||||
transformOffsets(diff, false)
|
||||
line = append(ellipsis, trimmed...)
|
||||
} else if !t.overflow(line[:maxe], maxWidth-ellipsisWidth) {
|
||||
// Stri..
|
||||
line, _ = t.trimRight(line, maxWidth-ellipsisWidth)
|
||||
line = append(line, ellipsis...)
|
||||
} else {
|
||||
// Stri..
|
||||
rightTrim := false
|
||||
if t.overflow(line[maxe:], ellipsisWidth) {
|
||||
line = append(line[:maxe], ellipsis...)
|
||||
rightTrim = true
|
||||
shift := 0
|
||||
maxe := maxEnd
|
||||
offs := make([]colorOffset, len(offsets))
|
||||
for idx := range offsets {
|
||||
offs[idx] = offsets[idx]
|
||||
if fidx == 1 && splitOffsetRight > 0 {
|
||||
shift = splitOffsetRight
|
||||
} else if fidx == 2 && splitOffsetLeft > 0 {
|
||||
shift = splitOffsetLeft
|
||||
}
|
||||
offs[idx].offset[0] -= int32(shift)
|
||||
offs[idx].offset[1] -= int32(shift)
|
||||
}
|
||||
maxe -= shift
|
||||
displayWidth = t.displayWidthWithLimit(runes, 0, maxWidth)
|
||||
if !t.wrap && displayWidth > maxWidth {
|
||||
ellipsis, ellipsisWidth := util.Truncate(t.ellipsis, maxWidth/2)
|
||||
maxe = util.Constrain(maxe+util.Min(maxWidth/2-ellipsisWidth, t.hscrollOff), 0, len(runes))
|
||||
transformOffsets := func(diff int32, rightTrim bool) {
|
||||
for idx, offset := range offs {
|
||||
b, e := offset.offset[0], offset.offset[1]
|
||||
el := int32(len(ellipsis))
|
||||
b += el - diff
|
||||
e += el - diff
|
||||
b = util.Max32(b, el)
|
||||
if rightTrim {
|
||||
e = util.Min32(e, int32(maxWidth-ellipsisWidth))
|
||||
}
|
||||
offs[idx].offset[0] = b
|
||||
offs[idx].offset[1] = util.Max32(b, e)
|
||||
}
|
||||
// ..ri..
|
||||
var diff int32
|
||||
line, diff = t.trimLeft(line, maxWidth, ellipsisWidth)
|
||||
}
|
||||
if t.hscroll {
|
||||
if fidx == 1 || fidx == 2 && t.keepRight && pos == nil {
|
||||
trimmed, diff := t.trimLeft(runes, maxWidth, ellipsisWidth)
|
||||
transformOffsets(diff, false)
|
||||
runes = append(ellipsis, trimmed...)
|
||||
} else if fidx == 0 || !t.overflow(runes[:maxe], maxWidth-ellipsisWidth) {
|
||||
// Stri..
|
||||
runes, _ = t.trimRight(runes, maxWidth-ellipsisWidth)
|
||||
runes = append(runes, ellipsis...)
|
||||
} else {
|
||||
// Stri..
|
||||
rightTrim := false
|
||||
if t.overflow(runes[maxe:], ellipsisWidth) {
|
||||
runes = append(runes[:maxe], ellipsis...)
|
||||
rightTrim = true
|
||||
}
|
||||
// ..ri..
|
||||
var diff int32
|
||||
runes, diff = t.trimLeft(runes, maxWidth, ellipsisWidth)
|
||||
|
||||
// Transform offsets
|
||||
transformOffsets(diff, rightTrim)
|
||||
line = append(ellipsis, line...)
|
||||
// Transform offsets
|
||||
transformOffsets(diff, rightTrim)
|
||||
runes = append(ellipsis, runes...)
|
||||
}
|
||||
} else {
|
||||
runes, _ = t.trimRight(runes, maxWidth-ellipsisWidth)
|
||||
runes = append(runes, ellipsis...)
|
||||
|
||||
for idx, offset := range offs {
|
||||
offs[idx].offset[0] = util.Min32(offset.offset[0], int32(maxWidth-len(ellipsis)))
|
||||
offs[idx].offset[1] = util.Min32(offset.offset[1], int32(maxWidth))
|
||||
}
|
||||
}
|
||||
displayWidth = t.displayWidthWithLimit(runes, 0, displayWidth)
|
||||
}
|
||||
displayWidthSum += displayWidth
|
||||
|
||||
if maxWidth > 0 {
|
||||
color := colBase
|
||||
if hidden {
|
||||
color = color.WithFg(t.theme.Nomatch)
|
||||
}
|
||||
todo[fidx] = func() {
|
||||
t.printColoredString(t.window, runes, offs, color)
|
||||
}
|
||||
} else {
|
||||
line, _ = t.trimRight(line, maxWidth-ellipsisWidth)
|
||||
line = append(line, ellipsis...)
|
||||
|
||||
for idx, offset := range offsets {
|
||||
offsets[idx].offset[0] = util.Min32(offset.offset[0], int32(maxWidth-len(ellipsis)))
|
||||
offsets[idx].offset[1] = util.Min32(offset.offset[1], int32(maxWidth))
|
||||
}
|
||||
break
|
||||
}
|
||||
displayWidth = t.displayWidthWithLimit(line, 0, displayWidth)
|
||||
maxWidth -= displayWidth
|
||||
}
|
||||
|
||||
if maxWidth > 0 {
|
||||
color := colBase
|
||||
if hidden {
|
||||
color = color.WithFg(t.theme.Nomatch)
|
||||
}
|
||||
t.printColoredString(t.window, line, offsets, color)
|
||||
if todo[0] != nil {
|
||||
todo[0]()
|
||||
}
|
||||
if todo[2] != nil {
|
||||
todo[2]()
|
||||
}
|
||||
if todo[1] != nil {
|
||||
todo[1]()
|
||||
}
|
||||
if postTask != nil {
|
||||
postTask(actualLineNum, displayWidth, wasWrapped, forceRedraw, lbg)
|
||||
postTask(actualLineNum, displayWidthSum, wasWrapped, forceRedraw, lbg)
|
||||
} else {
|
||||
t.markOtherLine(actualLineNum)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func _() {
|
||||
_ = x[CtrlE-5]
|
||||
_ = x[CtrlF-6]
|
||||
_ = x[CtrlG-7]
|
||||
_ = x[CtrlH-8]
|
||||
_ = x[CtrlBackspace-8]
|
||||
_ = x[Tab-9]
|
||||
_ = x[CtrlJ-10]
|
||||
_ = x[CtrlK-11]
|
||||
@@ -99,75 +99,74 @@ func _() {
|
||||
_ = x[CtrlRight-88]
|
||||
_ = x[CtrlHome-89]
|
||||
_ = x[CtrlEnd-90]
|
||||
_ = x[CtrlBackspace-91]
|
||||
_ = x[CtrlDelete-92]
|
||||
_ = x[CtrlPageUp-93]
|
||||
_ = x[CtrlPageDown-94]
|
||||
_ = x[Alt-95]
|
||||
_ = x[CtrlAlt-96]
|
||||
_ = x[CtrlAltUp-97]
|
||||
_ = x[CtrlAltDown-98]
|
||||
_ = x[CtrlAltLeft-99]
|
||||
_ = x[CtrlAltRight-100]
|
||||
_ = x[CtrlAltHome-101]
|
||||
_ = x[CtrlAltEnd-102]
|
||||
_ = x[CtrlAltBackspace-103]
|
||||
_ = x[CtrlAltDelete-104]
|
||||
_ = x[CtrlAltPageUp-105]
|
||||
_ = x[CtrlAltPageDown-106]
|
||||
_ = x[CtrlShiftUp-107]
|
||||
_ = x[CtrlShiftDown-108]
|
||||
_ = x[CtrlShiftLeft-109]
|
||||
_ = x[CtrlShiftRight-110]
|
||||
_ = x[CtrlShiftHome-111]
|
||||
_ = x[CtrlShiftEnd-112]
|
||||
_ = x[CtrlShiftDelete-113]
|
||||
_ = x[CtrlShiftPageUp-114]
|
||||
_ = x[CtrlShiftPageDown-115]
|
||||
_ = x[CtrlAltShiftUp-116]
|
||||
_ = x[CtrlAltShiftDown-117]
|
||||
_ = x[CtrlAltShiftLeft-118]
|
||||
_ = x[CtrlAltShiftRight-119]
|
||||
_ = x[CtrlAltShiftHome-120]
|
||||
_ = x[CtrlAltShiftEnd-121]
|
||||
_ = x[CtrlAltShiftDelete-122]
|
||||
_ = x[CtrlAltShiftPageUp-123]
|
||||
_ = x[CtrlAltShiftPageDown-124]
|
||||
_ = x[Invalid-125]
|
||||
_ = x[Fatal-126]
|
||||
_ = x[BracketedPasteBegin-127]
|
||||
_ = x[BracketedPasteEnd-128]
|
||||
_ = x[Mouse-129]
|
||||
_ = x[DoubleClick-130]
|
||||
_ = x[LeftClick-131]
|
||||
_ = x[RightClick-132]
|
||||
_ = x[SLeftClick-133]
|
||||
_ = x[SRightClick-134]
|
||||
_ = x[ScrollUp-135]
|
||||
_ = x[ScrollDown-136]
|
||||
_ = x[SScrollUp-137]
|
||||
_ = x[SScrollDown-138]
|
||||
_ = x[PreviewScrollUp-139]
|
||||
_ = x[PreviewScrollDown-140]
|
||||
_ = x[Resize-141]
|
||||
_ = x[Change-142]
|
||||
_ = x[BackwardEOF-143]
|
||||
_ = x[Start-144]
|
||||
_ = x[Load-145]
|
||||
_ = x[Focus-146]
|
||||
_ = x[One-147]
|
||||
_ = x[Zero-148]
|
||||
_ = x[Result-149]
|
||||
_ = x[Jump-150]
|
||||
_ = x[JumpCancel-151]
|
||||
_ = x[ClickHeader-152]
|
||||
_ = x[ClickFooter-153]
|
||||
_ = x[Multi-154]
|
||||
_ = x[CtrlDelete-91]
|
||||
_ = x[CtrlPageUp-92]
|
||||
_ = x[CtrlPageDown-93]
|
||||
_ = x[Alt-94]
|
||||
_ = x[CtrlAlt-95]
|
||||
_ = x[CtrlAltUp-96]
|
||||
_ = x[CtrlAltDown-97]
|
||||
_ = x[CtrlAltLeft-98]
|
||||
_ = x[CtrlAltRight-99]
|
||||
_ = x[CtrlAltHome-100]
|
||||
_ = x[CtrlAltEnd-101]
|
||||
_ = x[CtrlAltBackspace-102]
|
||||
_ = x[CtrlAltDelete-103]
|
||||
_ = x[CtrlAltPageUp-104]
|
||||
_ = x[CtrlAltPageDown-105]
|
||||
_ = x[CtrlShiftUp-106]
|
||||
_ = x[CtrlShiftDown-107]
|
||||
_ = x[CtrlShiftLeft-108]
|
||||
_ = x[CtrlShiftRight-109]
|
||||
_ = x[CtrlShiftHome-110]
|
||||
_ = x[CtrlShiftEnd-111]
|
||||
_ = x[CtrlShiftDelete-112]
|
||||
_ = x[CtrlShiftPageUp-113]
|
||||
_ = x[CtrlShiftPageDown-114]
|
||||
_ = x[CtrlAltShiftUp-115]
|
||||
_ = x[CtrlAltShiftDown-116]
|
||||
_ = x[CtrlAltShiftLeft-117]
|
||||
_ = x[CtrlAltShiftRight-118]
|
||||
_ = x[CtrlAltShiftHome-119]
|
||||
_ = x[CtrlAltShiftEnd-120]
|
||||
_ = x[CtrlAltShiftDelete-121]
|
||||
_ = x[CtrlAltShiftPageUp-122]
|
||||
_ = x[CtrlAltShiftPageDown-123]
|
||||
_ = x[Invalid-124]
|
||||
_ = x[Fatal-125]
|
||||
_ = x[BracketedPasteBegin-126]
|
||||
_ = x[BracketedPasteEnd-127]
|
||||
_ = x[Mouse-128]
|
||||
_ = x[DoubleClick-129]
|
||||
_ = x[LeftClick-130]
|
||||
_ = x[RightClick-131]
|
||||
_ = x[SLeftClick-132]
|
||||
_ = x[SRightClick-133]
|
||||
_ = x[ScrollUp-134]
|
||||
_ = x[ScrollDown-135]
|
||||
_ = x[SScrollUp-136]
|
||||
_ = x[SScrollDown-137]
|
||||
_ = x[PreviewScrollUp-138]
|
||||
_ = x[PreviewScrollDown-139]
|
||||
_ = x[Resize-140]
|
||||
_ = x[Change-141]
|
||||
_ = x[BackwardEOF-142]
|
||||
_ = x[Start-143]
|
||||
_ = x[Load-144]
|
||||
_ = x[Focus-145]
|
||||
_ = x[One-146]
|
||||
_ = x[Zero-147]
|
||||
_ = x[Result-148]
|
||||
_ = x[Jump-149]
|
||||
_ = x[JumpCancel-150]
|
||||
_ = x[ClickHeader-151]
|
||||
_ = x[ClickFooter-152]
|
||||
_ = x[Multi-153]
|
||||
}
|
||||
|
||||
const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteShiftHomeShiftEndShiftPageUpShiftPageDownF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltDeleteAltHomeAltEndAltPageUpAltPageDownAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltShiftDeleteAltShiftHomeAltShiftEndAltShiftPageUpAltShiftPageDownCtrlUpCtrlDownCtrlLeftCtrlRightCtrlHomeCtrlEndCtrlBackspaceCtrlDeleteCtrlPageUpCtrlPageDownAltCtrlAltCtrlAltUpCtrlAltDownCtrlAltLeftCtrlAltRightCtrlAltHomeCtrlAltEndCtrlAltBackspaceCtrlAltDeleteCtrlAltPageUpCtrlAltPageDownCtrlShiftUpCtrlShiftDownCtrlShiftLeftCtrlShiftRightCtrlShiftHomeCtrlShiftEndCtrlShiftDeleteCtrlShiftPageUpCtrlShiftPageDownCtrlAltShiftUpCtrlAltShiftDownCtrlAltShiftLeftCtrlAltShiftRightCtrlAltShiftHomeCtrlAltShiftEndCtrlAltShiftDeleteCtrlAltShiftPageUpCtrlAltShiftPageDownInvalidFatalBracketedPasteBeginBracketedPasteEndMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeaderClickFooterMulti"
|
||||
const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlBackspaceTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteShiftHomeShiftEndShiftPageUpShiftPageDownF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltDeleteAltHomeAltEndAltPageUpAltPageDownAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltShiftDeleteAltShiftHomeAltShiftEndAltShiftPageUpAltShiftPageDownCtrlUpCtrlDownCtrlLeftCtrlRightCtrlHomeCtrlEndCtrlDeleteCtrlPageUpCtrlPageDownAltCtrlAltCtrlAltUpCtrlAltDownCtrlAltLeftCtrlAltRightCtrlAltHomeCtrlAltEndCtrlAltBackspaceCtrlAltDeleteCtrlAltPageUpCtrlAltPageDownCtrlShiftUpCtrlShiftDownCtrlShiftLeftCtrlShiftRightCtrlShiftHomeCtrlShiftEndCtrlShiftDeleteCtrlShiftPageUpCtrlShiftPageDownCtrlAltShiftUpCtrlAltShiftDownCtrlAltShiftLeftCtrlAltShiftRightCtrlAltShiftHomeCtrlAltShiftEndCtrlAltShiftDeleteCtrlAltShiftPageUpCtrlAltShiftPageDownInvalidFatalBracketedPasteBeginBracketedPasteEndMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeaderClickFooterMulti"
|
||||
|
||||
var _EventType_index = [...]uint16{0, 4, 9, 14, 19, 24, 29, 34, 39, 44, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97, 102, 107, 112, 117, 122, 127, 132, 135, 144, 157, 173, 182, 191, 199, 208, 214, 220, 228, 230, 234, 238, 243, 247, 250, 256, 263, 272, 281, 291, 302, 311, 319, 330, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 364, 367, 370, 382, 387, 394, 401, 409, 418, 425, 431, 440, 451, 461, 473, 485, 498, 512, 524, 535, 549, 565, 571, 579, 587, 596, 604, 611, 624, 634, 644, 656, 659, 666, 675, 686, 697, 709, 720, 730, 746, 759, 772, 787, 798, 811, 824, 838, 851, 863, 878, 893, 910, 924, 940, 956, 973, 989, 1004, 1022, 1040, 1060, 1067, 1072, 1091, 1108, 1113, 1124, 1133, 1143, 1153, 1164, 1172, 1182, 1191, 1202, 1217, 1234, 1240, 1246, 1257, 1262, 1266, 1271, 1274, 1278, 1284, 1288, 1298, 1309, 1320, 1325}
|
||||
var _EventType_index = [...]uint16{0, 4, 9, 14, 19, 24, 29, 34, 39, 52, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 143, 152, 165, 181, 190, 199, 207, 216, 222, 228, 236, 238, 242, 246, 251, 255, 258, 264, 271, 280, 289, 299, 310, 319, 327, 338, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 372, 375, 378, 390, 395, 402, 409, 417, 426, 433, 439, 448, 459, 469, 481, 493, 506, 520, 532, 543, 557, 573, 579, 587, 595, 604, 612, 619, 629, 639, 651, 654, 661, 670, 681, 692, 704, 715, 725, 741, 754, 767, 782, 793, 806, 819, 833, 846, 858, 873, 888, 905, 919, 935, 951, 968, 984, 999, 1017, 1035, 1055, 1062, 1067, 1086, 1103, 1108, 1119, 1128, 1138, 1148, 1159, 1167, 1177, 1186, 1197, 1212, 1229, 1235, 1241, 1252, 1257, 1261, 1266, 1269, 1273, 1279, 1283, 1293, 1304, 1315, 1320}
|
||||
|
||||
func (i EventType) String() string {
|
||||
if i < 0 || i >= EventType(len(_EventType_index)-1) {
|
||||
|
||||
@@ -371,12 +371,10 @@ func (r *FullscreenRenderer) GetChar() Event {
|
||||
}
|
||||
case rune(tcell.KeyCtrlH):
|
||||
switch {
|
||||
case ctrl:
|
||||
return keyfn('h')
|
||||
case alt:
|
||||
return Event{AltBackspace, 0, nil}
|
||||
case none, shift:
|
||||
return Event{Backspace, 0, nil}
|
||||
case ctrl, none, shift:
|
||||
return keyfn('h')
|
||||
}
|
||||
}
|
||||
case tcell.KeyCtrlI:
|
||||
|
||||
@@ -110,21 +110,21 @@ func TestGetCharEventKey(t *testing.T) {
|
||||
{giveKey{tcell.KeyDelete, 0, tcell.ModAlt}, wantKey{AltDelete, 0, nil}},
|
||||
{giveKey{tcell.KeyBackspace, 0, tcell.ModCtrl}, wantKey{CtrlBackspace, 0, nil}},
|
||||
{giveKey{tcell.KeyBackspace, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltBackspace, 0, nil}},
|
||||
{giveKey{tcell.KeyBackspace, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
|
||||
{giveKey{tcell.KeyBS, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModNone}, wantKey{Backspace, 0, nil}}, // actual "Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // actual "Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyDEL, rune(tcell.KeyDEL), tcell.ModCtrl}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift}, wantKey{Backspace, 0, nil}}, // actual "Shift+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltBackspace, 0, nil}}, // actual "Ctrl+Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+Shift+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift | tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // actual "Shift+Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{CtrlAltBackspace, 0, nil}}, // actual "Ctrl+Shift+Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl}, wantKey{CtrlH, 0, nil}}, // actual "Ctrl+H" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAlt, 'h', nil}}, // fabricated "Ctrl+Alt+H" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlH, 0, nil}}, // actual "Ctrl+Shift+H" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{CtrlAlt, 'h', nil}}, // fabricated "Ctrl+Shift+Alt+H" keystroke
|
||||
{giveKey{tcell.KeyBackspace, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
|
||||
{giveKey{tcell.KeyBS, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModNone}, wantKey{CtrlBackspace, 0, nil}}, // actual "Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // actual "Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyDEL, rune(tcell.KeyDEL), tcell.ModCtrl}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift}, wantKey{CtrlBackspace, 0, nil}}, // actual "Shift+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltBackspace, 0, nil}}, // actual "Ctrl+Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+Shift+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift | tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // actual "Shift+Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{CtrlAltBackspace, 0, nil}}, // actual "Ctrl+Shift+Alt+Backspace" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+H" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // fabricated "Ctrl+Alt+H" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+Shift+H" keystroke
|
||||
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{AltBackspace, 0, nil}}, // fabricated "Ctrl+Shift+Alt+H" keystroke
|
||||
|
||||
// section 4: (Alt+Shift)+Key(Up|Down|Left|Right)
|
||||
{giveKey{tcell.KeyUp, 0, tcell.ModNone}, wantKey{Up, 0, nil}},
|
||||
|
||||
@@ -43,7 +43,7 @@ const (
|
||||
CtrlE
|
||||
CtrlF
|
||||
CtrlG
|
||||
CtrlH
|
||||
CtrlBackspace
|
||||
Tab
|
||||
CtrlJ
|
||||
CtrlK
|
||||
@@ -137,7 +137,6 @@ const (
|
||||
CtrlRight
|
||||
CtrlHome
|
||||
CtrlEnd
|
||||
CtrlBackspace
|
||||
CtrlDelete
|
||||
CtrlPageUp
|
||||
CtrlPageDown
|
||||
@@ -296,8 +295,9 @@ func (a ColorAttr) IsColorDefined() bool {
|
||||
}
|
||||
|
||||
func (a ColorAttr) IsAttrDefined() bool {
|
||||
return a.Attr != AttrUndefined
|
||||
return a.Attr&^BoldForce != AttrUndefined
|
||||
}
|
||||
|
||||
func (a ColorAttr) IsUndefined() bool {
|
||||
return !a.IsColorDefined() && !a.IsAttrDefined()
|
||||
}
|
||||
@@ -1157,12 +1157,12 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, boldify bool, forceBlac
|
||||
// e.g. fzf --delimiter / --nth -1 --color fg:dim,nth:regular
|
||||
current := theme.Current
|
||||
if !baseTheme.Colored && current.IsUndefined() {
|
||||
current.Attr = Reverse
|
||||
current.Attr |= Reverse
|
||||
}
|
||||
theme.Current = theme.Fg.Merge(o(baseTheme.Current, current))
|
||||
currentMatch := theme.CurrentMatch
|
||||
if !baseTheme.Colored && currentMatch.IsUndefined() {
|
||||
currentMatch.Attr = Reverse | Underline
|
||||
currentMatch.Attr |= Reverse | Underline
|
||||
}
|
||||
theme.CurrentMatch = o(baseTheme.CurrentMatch, currentMatch)
|
||||
theme.Spinner = o(baseTheme.Spinner, theme.Spinner)
|
||||
|
||||
@@ -1190,6 +1190,26 @@ class TestCore < TestInteractive
|
||||
tmux.until { |lines| assert lines.any_include?('9999␊10000') }
|
||||
end
|
||||
|
||||
def test_freeze_left_keep_right
|
||||
tmux.send_keys %[seq 10000 | #{FZF} --read0 --delimiter "\n" --freeze-left 3 --keep-right --ellipsis XX --no-multi-line --bind space:toggle-multi-line], :Enter
|
||||
tmux.until { |lines| assert_match(/^> 1␊2␊3XX.*10000␊$/, lines[-3]) }
|
||||
tmux.send_keys '5'
|
||||
tmux.until { |lines| assert_match(/^> 1␊2␊3␊4␊5␊.*XX$/, lines[-3]) }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert lines.any_include?('> 1') }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert lines.any_include?('1␊2␊3␊4␊5␊') }
|
||||
end
|
||||
|
||||
def test_freeze_right
|
||||
tmux.send_keys %[seq 10000 | tr "\n" ' ' | #{FZF} --freeze-left 3 --freeze-right 3 --ellipsis XX], :Enter
|
||||
tmux.until { |lines| assert_match(/XX9998 9999 10000$/, lines[-3]) }
|
||||
tmux.send_keys "'1000"
|
||||
tmux.until { |lines| assert_match(/^> 1 2 3XX.*XX9998 9999 10000$/,lines[-3]) }
|
||||
tmux.send_keys :Space
|
||||
tmux.until { |lines| assert lines.any_include?('> 1') }
|
||||
end
|
||||
|
||||
def test_backward_eof
|
||||
tmux.send_keys "echo foo | #{FZF} --bind 'backward-eof:reload(seq 100)'", :Enter
|
||||
tmux.until { |lines| lines.item_count == 1 && lines.match_count == 1 }
|
||||
|
||||
Reference in New Issue
Block a user