mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2025-01-15 11:46:58 +00:00
Merge 6f943112a9
into a30181e240
This commit is contained in:
commit
d7da1e75ba
14
CHANGELOG.md
14
CHANGELOG.md
@ -6,7 +6,15 @@ CHANGELOG
|
|||||||
|
|
||||||
This version introduces three new border types, `--list-border`, `--input-border`, and `--header-border`, offering much greater flexibility for customizing the user interface.
|
This version introduces three new border types, `--list-border`, `--input-border`, and `--header-border`, offering much greater flexibility for customizing the user interface.
|
||||||
|
|
||||||
Also, fzf now offers three "style presets" for easier customization, which can be activated using the `--style=[default|minimal|full]` option.
|
<img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-4-borders.png" />
|
||||||
|
|
||||||
|
Also, fzf now offers "style presets" for quick customization, which can be activated using the `--style` option.
|
||||||
|
|
||||||
|
| Preset | Screenshot |
|
||||||
|
| :--- | :--- |
|
||||||
|
| `default` | <img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-style-default.png"/> |
|
||||||
|
| `full` | <img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-style-full.png"/> |
|
||||||
|
| `minimal` | <img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-style-minimal.png"/> |
|
||||||
|
|
||||||
- Style presets (#4160)
|
- Style presets (#4160)
|
||||||
- `--style=full`
|
- `--style=full`
|
||||||
@ -59,6 +67,10 @@ Also, fzf now offers three "style presets" for easier customization, which can b
|
|||||||
```
|
```
|
||||||
- Added `toggle-multi-line` action
|
- Added `toggle-multi-line` action
|
||||||
- Added `toggle-hscroll` action
|
- Added `toggle-hscroll` action
|
||||||
|
- A single-character delimiter is now treated as a plain string delimiter rather than a regular expression delimiter, even if it's a regular expression meta-character.
|
||||||
|
- This means you can just write `--delimiter '|'` instead of escaping it as `--delimiter '\|'`
|
||||||
|
- Bug fixes
|
||||||
|
- Bug fixes in fish scripts (thanks to @bitraid)
|
||||||
|
|
||||||
0.57.0
|
0.57.0
|
||||||
------
|
------
|
||||||
|
@ -9,11 +9,23 @@
|
|||||||
# - https://iterm2.com/utilities/imgcat
|
# - https://iterm2.com/utilities/imgcat
|
||||||
|
|
||||||
if [[ $# -ne 1 ]]; then
|
if [[ $# -ne 1 ]]; then
|
||||||
>&2 echo "usage: $0 FILENAME"
|
>&2 echo "usage: $0 FILENAME[:LINENO][:IGNORED]"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
file=${1/#\~\//$HOME/}
|
file=${1/#\~\//$HOME/}
|
||||||
|
|
||||||
|
center=0
|
||||||
|
if [[ ! -r $file ]]; then
|
||||||
|
if [[ $file =~ ^(.+):([0-9]+)\ *$ ]] && [[ -r ${BASH_REMATCH[1]} ]]; then
|
||||||
|
file=${BASH_REMATCH[1]}
|
||||||
|
center=${BASH_REMATCH[2]}
|
||||||
|
elif [[ $file =~ ^(.+):([0-9]+):[0-9]+\ *$ ]] && [[ -r ${BASH_REMATCH[1]} ]]; then
|
||||||
|
file=${BASH_REMATCH[1]}
|
||||||
|
center=${BASH_REMATCH[2]}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
type=$(file --brief --dereference --mime -- "$file")
|
type=$(file --brief --dereference --mime -- "$file")
|
||||||
|
|
||||||
if [[ ! $type =~ image/ ]]; then
|
if [[ ! $type =~ image/ ]]; then
|
||||||
@ -32,7 +44,7 @@ if [[ ! $type =~ image/ ]]; then
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${batname} --style="${BAT_STYLE:-numbers}" --color=always --pager=never -- "$file"
|
${batname} --style="${BAT_STYLE:-numbers}" --color=always --pager=never --highlight-line="${center:-0}" -- "$file"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -73,11 +73,10 @@ function fzf_key_bindings
|
|||||||
builtin history -z --reverse | command perl -0 -pe 's/^/$.\t/g; s/\n/\n\t/gm' | eval (__fzfcmd) --tac --read0 --print0 -q '(commandline)' | string replace -r '^\d*\t' '' | read -lz result
|
builtin history -z --reverse | command perl -0 -pe 's/^/$.\t/g; s/\n/\n\t/gm' | eval (__fzfcmd) --tac --read0 --print0 -q '(commandline)' | string replace -r '^\d*\t' '' | read -lz result
|
||||||
and commandline -- $result
|
and commandline -- $result
|
||||||
else
|
else
|
||||||
set -l line 0
|
set -l h (builtin history -z | string split0)
|
||||||
for i in (builtin history -z --reverse | string split0)
|
for i in (seq (count $h) -1 1)
|
||||||
set line (math $line + 1)
|
string join0 -- $i\t(string replace -a -- \n \n\t $h[$i] | string collect)
|
||||||
string escape -n -- $line\t$i
|
end | eval (__fzfcmd) --read0 --print0 -q '(commandline)' | string replace -r '^\d*\t' '' | read -lz result
|
||||||
end | string join0 | string replace -a '\n' '\n\t' | string unescape -n | eval (__fzfcmd) --tac --read0 --print0 -q '(commandline)' | string replace -r '^\d*\t' '' | read -lz result
|
|
||||||
and commandline -- $result
|
and commandline -- $result
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -133,14 +132,12 @@ function fzf_key_bindings
|
|||||||
bind \ec fzf-cd-widget
|
bind \ec fzf-cd-widget
|
||||||
end
|
end
|
||||||
|
|
||||||
if bind -M insert &> /dev/null
|
bind -M insert \cr fzf-history-widget
|
||||||
bind -M insert \cr fzf-history-widget
|
if not set -q FZF_CTRL_T_COMMAND; or test -n "$FZF_CTRL_T_COMMAND"
|
||||||
if not set -q FZF_CTRL_T_COMMAND; or test -n "$FZF_CTRL_T_COMMAND"
|
bind -M insert \ct fzf-file-widget
|
||||||
bind -M insert \ct fzf-file-widget
|
end
|
||||||
end
|
if not set -q FZF_ALT_C_COMMAND; or test -n "$FZF_ALT_C_COMMAND"
|
||||||
if not set -q FZF_ALT_C_COMMAND; or test -n "$FZF_ALT_C_COMMAND"
|
bind -M insert \ec fzf-cd-widget
|
||||||
bind -M insert \ec fzf-cd-widget
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath, fzf query, and optional -option= prefix'
|
function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath, fzf query, and optional -option= prefix'
|
||||||
|
50
src/ansi.go
50
src/ansi.go
@ -98,11 +98,11 @@ func isPrint(c uint8) bool {
|
|||||||
return '\x20' <= c && c <= '\x7e'
|
return '\x20' <= c && c <= '\x7e'
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchOperatingSystemCommand(s string) int {
|
func matchOperatingSystemCommand(s string, start int) int {
|
||||||
// `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)`
|
// `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)`
|
||||||
// ^ match starting here
|
// ^ match starting here after the first printable character
|
||||||
//
|
//
|
||||||
i := 5 // prefix matched in nextAnsiEscapeSequence()
|
i := start // prefix matched in nextAnsiEscapeSequence()
|
||||||
for ; i < len(s) && isPrint(s[i]); i++ {
|
for ; i < len(s) && isPrint(s[i]); i++ {
|
||||||
}
|
}
|
||||||
if i < len(s) {
|
if i < len(s) {
|
||||||
@ -156,7 +156,7 @@ func isCtrlSeqStart(c uint8) bool {
|
|||||||
// nextAnsiEscapeSequence returns the ANSI escape sequence and is equivalent to
|
// nextAnsiEscapeSequence returns the ANSI escape sequence and is equivalent to
|
||||||
// calling FindStringIndex() on the below regex (which was originally used):
|
// calling FindStringIndex() on the below regex (which was originally used):
|
||||||
//
|
//
|
||||||
// "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
|
// "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
|
||||||
func nextAnsiEscapeSequence(s string) (int, int) {
|
func nextAnsiEscapeSequence(s string) (int, int) {
|
||||||
// fast check for ANSI escape sequences
|
// fast check for ANSI escape sequences
|
||||||
i := 0
|
i := 0
|
||||||
@ -191,12 +191,20 @@ Loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// match: `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)`
|
// match: `\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)`
|
||||||
if i+5 < len(s) && s[i+1] == ']' && isNumeric(s[i+2]) &&
|
if i+5 < len(s) && s[i+1] == ']' {
|
||||||
(s[i+3] == ';' || s[i+3] == ':') && isPrint(s[i+4]) {
|
j := 2
|
||||||
|
// \x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)
|
||||||
|
// ------
|
||||||
|
for ; i+j < len(s) && isNumeric(s[i+j]); j++ {
|
||||||
|
}
|
||||||
|
|
||||||
if j := matchOperatingSystemCommand(s[i:]); j != -1 {
|
// \x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)
|
||||||
return i, i + j
|
// ---------------
|
||||||
|
if j > 2 && i+j+1 < len(s) && (s[i+j] == ';' || s[i+j] == ':') && isPrint(s[i+j+1]) {
|
||||||
|
if k := matchOperatingSystemCommand(s[i:], j+2); k != -1 {
|
||||||
|
return i, i + k
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,20 +318,15 @@ func extractColor(str string, state *ansiState, proc func(string, *ansiState) bo
|
|||||||
return trimmed, nil, state
|
return trimmed, nil, state
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAnsiCode(s string, delimiter byte) (int, byte, string) {
|
func parseAnsiCode(s string) (int, string) {
|
||||||
var remaining string
|
var remaining string
|
||||||
var i int
|
var i int
|
||||||
if delimiter == 0 {
|
// Faster than strings.IndexAny(";:")
|
||||||
// Faster than strings.IndexAny(";:")
|
i = strings.IndexByte(s, ';')
|
||||||
i = strings.IndexByte(s, ';')
|
if i < 0 {
|
||||||
if i < 0 {
|
i = strings.IndexByte(s, ':')
|
||||||
i = strings.IndexByte(s, ':')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i = strings.IndexByte(s, delimiter)
|
|
||||||
}
|
}
|
||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
delimiter = s[i]
|
|
||||||
remaining = s[i+1:]
|
remaining = s[i+1:]
|
||||||
s = s[:i]
|
s = s[:i]
|
||||||
}
|
}
|
||||||
@ -335,14 +338,14 @@ func parseAnsiCode(s string, delimiter byte) (int, byte, string) {
|
|||||||
for _, ch := range stringBytes(s) {
|
for _, ch := range stringBytes(s) {
|
||||||
ch -= '0'
|
ch -= '0'
|
||||||
if ch > 9 {
|
if ch > 9 {
|
||||||
return -1, delimiter, remaining
|
return -1, remaining
|
||||||
}
|
}
|
||||||
code = code*10 + int(ch)
|
code = code*10 + int(ch)
|
||||||
}
|
}
|
||||||
return code, delimiter, remaining
|
return code, remaining
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1, delimiter, remaining
|
return -1, remaining
|
||||||
}
|
}
|
||||||
|
|
||||||
func interpretCode(ansiCode string, prevState *ansiState) ansiState {
|
func interpretCode(ansiCode string, prevState *ansiState) ansiState {
|
||||||
@ -378,11 +381,10 @@ func interpretCode(ansiCode string, prevState *ansiState) ansiState {
|
|||||||
state256 := 0
|
state256 := 0
|
||||||
ptr := &state.fg
|
ptr := &state.fg
|
||||||
|
|
||||||
var delimiter byte
|
|
||||||
count := 0
|
count := 0
|
||||||
for len(ansiCode) != 0 {
|
for len(ansiCode) != 0 {
|
||||||
var num int
|
var num int
|
||||||
if num, delimiter, ansiCode = parseAnsiCode(ansiCode, delimiter); num != -1 {
|
if num, ansiCode = parseAnsiCode(ansiCode); num != -1 {
|
||||||
count++
|
count++
|
||||||
switch state256 {
|
switch state256 {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -335,6 +335,28 @@ func TestExtractColor(t *testing.T) {
|
|||||||
assert((*offsets)[0], 0, 6, 2, -1, true)
|
assert((*offsets)[0], 0, 6, 2, -1, true)
|
||||||
assert((*offsets)[1], 6, 11, 200, 100, false)
|
assert((*offsets)[1], 6, 11, 200, 100, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
state = nil
|
||||||
|
var color24 tui.Color = (1 << 24) + (180 << 16) + (190 << 8) + 254
|
||||||
|
src = "\x1b[1mhello \x1b[22;1;38:2:180:190:254mworld"
|
||||||
|
check(func(offsets *[]ansiOffset, state *ansiState) {
|
||||||
|
if len(*offsets) != 2 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if state.fg != color24 || state.attr != 1 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
assert((*offsets)[0], 0, 6, -1, -1, true)
|
||||||
|
assert((*offsets)[1], 6, 11, color24, -1, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
src = "\x1b]133;A\x1b\\hello \x1b]133;C\x1b\\world"
|
||||||
|
check(func(offsets *[]ansiOffset, state *ansiState) {
|
||||||
|
if len(*offsets) != 1 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
assert((*offsets)[0], 0, 11, color24, -1, true)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnsiCodeStringConversion(t *testing.T) {
|
func TestAnsiCodeStringConversion(t *testing.T) {
|
||||||
@ -381,7 +403,7 @@ func TestParseAnsiCode(t *testing.T) {
|
|||||||
{"-2", "", -1},
|
{"-2", "", -1},
|
||||||
}
|
}
|
||||||
for _, x := range tests {
|
for _, x := range tests {
|
||||||
n, _, s := parseAnsiCode(x.In, 0)
|
n, s := parseAnsiCode(x.In)
|
||||||
if n != x.N || s != x.Exp {
|
if n != x.N || s != x.Exp {
|
||||||
t.Fatalf("%q: got: (%d %q) want: (%d %q)", x.In, n, s, x.N, x.Exp)
|
t.Fatalf("%q: got: (%d %q) want: (%d %q)", x.In, n, s, x.N, x.Exp)
|
||||||
}
|
}
|
||||||
|
557
src/options.go
557
src/options.go
@ -332,8 +332,21 @@ func (o *previewOpts) Toggle() {
|
|||||||
o.hidden = !o.hidden
|
o.hidden = !o.hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *previewOpts) HasBorderRight() bool {
|
func (o *previewOpts) Border() tui.BorderShape {
|
||||||
return o.border.HasRight() || o.border == tui.BorderLine && o.position == posLeft
|
shape := o.border
|
||||||
|
if shape == tui.BorderLine {
|
||||||
|
switch o.position {
|
||||||
|
case posUp:
|
||||||
|
shape = tui.BorderBottom
|
||||||
|
case posDown:
|
||||||
|
shape = tui.BorderTop
|
||||||
|
case posLeft:
|
||||||
|
shape = tui.BorderRight
|
||||||
|
case posRight:
|
||||||
|
shape = tui.BorderLeft
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return shape
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultTmuxOptions(index int) *tmuxOptions {
|
func defaultTmuxOptions(index int) *tmuxOptions {
|
||||||
@ -700,54 +713,11 @@ func defaultOptions() *Options {
|
|||||||
Version: false}
|
Version: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
func optString(arg string, prefixes ...string) (bool, string) {
|
|
||||||
for _, prefix := range prefixes {
|
|
||||||
if strings.HasPrefix(arg, prefix) {
|
|
||||||
return true, arg[len(prefix):]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func nextString(args []string, i *int, message string) (string, error) {
|
|
||||||
if len(args) > *i+1 {
|
|
||||||
*i++
|
|
||||||
} else {
|
|
||||||
return "", errors.New(message)
|
|
||||||
}
|
|
||||||
return args[*i], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func optionalNextString(args []string, i *int) (bool, string) {
|
|
||||||
if len(args) > *i+1 && !strings.HasPrefix(args[*i+1], "-") && !strings.HasPrefix(args[*i+1], "+") {
|
|
||||||
*i++
|
|
||||||
return true, args[*i]
|
|
||||||
}
|
|
||||||
return false, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func isDir(path string) bool {
|
func isDir(path string) bool {
|
||||||
stat, err := os.Stat(path)
|
stat, err := os.Stat(path)
|
||||||
return err == nil && stat.IsDir()
|
return err == nil && stat.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
func nextDirs(args []string, i *int) ([]string, error) {
|
|
||||||
dirs := []string{}
|
|
||||||
for *i < len(args)-1 {
|
|
||||||
arg := args[*i+1]
|
|
||||||
if isDir(arg) {
|
|
||||||
dirs = append(dirs, arg)
|
|
||||||
*i++
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(dirs) == 0 {
|
|
||||||
return nil, errors.New("no directory specified")
|
|
||||||
}
|
|
||||||
return dirs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func atoi(str string) (int, error) {
|
func atoi(str string) (int, error) {
|
||||||
num, err := strconv.Atoi(str)
|
num, err := strconv.Atoi(str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -764,33 +734,6 @@ func atof(str string) (float64, error) {
|
|||||||
return num, nil
|
return num, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func nextInt(args []string, i *int, message string) (int, error) {
|
|
||||||
if len(args) > *i+1 {
|
|
||||||
*i++
|
|
||||||
} else {
|
|
||||||
return 0, errors.New(message)
|
|
||||||
}
|
|
||||||
n, err := atoi(args[*i])
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.New(message)
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func optionalNumeric(args []string, i *int, defaultValue int) (int, error) {
|
|
||||||
if len(args) > *i+1 {
|
|
||||||
if strings.IndexAny(args[*i+1], "0123456789") == 0 {
|
|
||||||
*i++
|
|
||||||
n, err := atoi(args[*i])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return defaultValue, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func splitNth(str string) ([]Range, error) {
|
func splitNth(str string) ([]Range, error) {
|
||||||
if match, _ := regexp.MatchString("^[0-9,-.]+$", str); !match {
|
if match, _ := regexp.MatchString("^[0-9,-.]+$", str); !match {
|
||||||
return nil, errors.New("invalid format: " + str)
|
return nil, errors.New("invalid format: " + str)
|
||||||
@ -812,18 +755,23 @@ func delimiterRegexp(str string) Delimiter {
|
|||||||
// Special handling of \t
|
// Special handling of \t
|
||||||
str = strings.ReplaceAll(str, "\\t", "\t")
|
str = strings.ReplaceAll(str, "\\t", "\t")
|
||||||
|
|
||||||
// 1. Pattern does not contain any special character
|
// 1. Pattern is a single character
|
||||||
|
if len([]rune(str)) == 1 {
|
||||||
|
return Delimiter{str: &str}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Pattern does not contain any special character
|
||||||
if regexp.QuoteMeta(str) == str {
|
if regexp.QuoteMeta(str) == str {
|
||||||
return Delimiter{str: &str}
|
return Delimiter{str: &str}
|
||||||
}
|
}
|
||||||
|
|
||||||
rx, e := regexp.Compile(str)
|
rx, e := regexp.Compile(str)
|
||||||
// 2. Pattern is not a valid regular expression
|
// 3. Pattern is not a valid regular expression
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return Delimiter{str: &str}
|
return Delimiter{str: &str}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Pattern as regular expression. Slow.
|
// 4. Pattern as regular expression. Slow.
|
||||||
return Delimiter{regex: rx}
|
return Delimiter{regex: rx}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2077,6 +2025,13 @@ func parseMarkerMultiLine(str string) (*[3]string, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func optString(arg string, prefix string) (bool, string) {
|
||||||
|
if strings.HasPrefix(arg, prefix) {
|
||||||
|
return true, arg[len(prefix):]
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
func parseOptions(index *int, opts *Options, allArgs []string) error {
|
func parseOptions(index *int, opts *Options, allArgs []string) error {
|
||||||
var err error
|
var err error
|
||||||
var historyMax int
|
var historyMax int
|
||||||
@ -2113,10 +2068,101 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
opts.Version = false
|
opts.Version = false
|
||||||
opts.Man = false
|
opts.Man = false
|
||||||
}
|
}
|
||||||
|
|
||||||
startIndex := *index
|
startIndex := *index
|
||||||
for i := 0; i < len(allArgs); i++ {
|
|
||||||
|
var i int
|
||||||
|
var val *string = nil
|
||||||
|
nextString := func(message string) (string, error) {
|
||||||
|
defer func() { val = nil }()
|
||||||
|
if val != nil {
|
||||||
|
return *val, nil
|
||||||
|
}
|
||||||
|
if len(allArgs) > i+1 {
|
||||||
|
i++
|
||||||
|
} else {
|
||||||
|
return "", errors.New(message)
|
||||||
|
}
|
||||||
|
return allArgs[i], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
optionalNextString := func() (bool, string) {
|
||||||
|
defer func() { val = nil }()
|
||||||
|
if val != nil {
|
||||||
|
return true, *val
|
||||||
|
}
|
||||||
|
if len(allArgs) > i+1 && !strings.HasPrefix(allArgs[i+1], "-") && !strings.HasPrefix(allArgs[i+1], "+") {
|
||||||
|
i++
|
||||||
|
return true, allArgs[i]
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
nextDirs := func() ([]string, error) {
|
||||||
|
defer func() { val = nil }()
|
||||||
|
dirs := []string{}
|
||||||
|
if val != nil {
|
||||||
|
dirs = append(dirs, *val)
|
||||||
|
}
|
||||||
|
for i < len(allArgs)-1 {
|
||||||
|
arg := allArgs[i+1]
|
||||||
|
if isDir(arg) {
|
||||||
|
dirs = append(dirs, arg)
|
||||||
|
i++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(dirs) == 0 {
|
||||||
|
return nil, errors.New("no directory specified")
|
||||||
|
}
|
||||||
|
return dirs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nextInt := func(message string) (int, error) {
|
||||||
|
defer func() { val = nil }()
|
||||||
|
var str string
|
||||||
|
if val != nil {
|
||||||
|
str = *val
|
||||||
|
} else if len(allArgs) > i+1 {
|
||||||
|
i++
|
||||||
|
str = allArgs[i]
|
||||||
|
} else {
|
||||||
|
return 0, errors.New(message)
|
||||||
|
}
|
||||||
|
n, err := atoi(str)
|
||||||
|
if err != nil {
|
||||||
|
return 0, errors.New(message)
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
optionalNumeric := func(defaultValue int) (int, error) {
|
||||||
|
defer func() { val = nil }()
|
||||||
|
var str string
|
||||||
|
if val != nil {
|
||||||
|
str = *val
|
||||||
|
} else if len(allArgs) > i+1 && strings.IndexAny(allArgs[i+1], "0123456789") == 0 {
|
||||||
|
i++
|
||||||
|
str = allArgs[i]
|
||||||
|
} else {
|
||||||
|
return defaultValue, nil
|
||||||
|
}
|
||||||
|
n, err := atoi(str)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for ; i < len(allArgs); i++ {
|
||||||
arg := allArgs[i]
|
arg := allArgs[i]
|
||||||
index := i + startIndex
|
index := i + startIndex
|
||||||
|
if strings.HasPrefix(arg, "--") && strings.IndexRune(arg, '=') > 0 {
|
||||||
|
tokens := strings.SplitN(arg, "=", 2)
|
||||||
|
arg = tokens[0]
|
||||||
|
val = &tokens[1]
|
||||||
|
}
|
||||||
switch arg {
|
switch arg {
|
||||||
case "--man":
|
case "--man":
|
||||||
clearExitingOpts()
|
clearExitingOpts()
|
||||||
@ -2139,7 +2185,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-winpty":
|
case "--no-winpty":
|
||||||
opts.NoWinpty = true
|
opts.NoWinpty = true
|
||||||
case "--tmux":
|
case "--tmux":
|
||||||
given, str := optionalNextString(allArgs, &i)
|
given, str := optionalNextString()
|
||||||
if given {
|
if given {
|
||||||
if opts.Tmux, err = parseTmuxOptions(str, index); err != nil {
|
if opts.Tmux, err = parseTmuxOptions(str, index); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -2156,7 +2202,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-force-tty-in":
|
case "--no-force-tty-in":
|
||||||
opts.ForceTtyIn = false
|
opts.ForceTtyIn = false
|
||||||
case "--proxy-script":
|
case "--proxy-script":
|
||||||
if opts.ProxyScript, err = nextString(allArgs, &i, ""); err != nil {
|
if opts.ProxyScript, err = nextString(""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "-x", "--extended":
|
case "-x", "--extended":
|
||||||
@ -2172,11 +2218,11 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "+e", "--no-exact":
|
case "+e", "--no-exact":
|
||||||
opts.Fuzzy = true
|
opts.Fuzzy = true
|
||||||
case "-q", "--query":
|
case "-q", "--query":
|
||||||
if opts.Query, err = nextString(allArgs, &i, "query string required"); err != nil {
|
if opts.Query, err = nextString("query string required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "-f", "--filter":
|
case "-f", "--filter":
|
||||||
filter, err := nextString(allArgs, &i, "query string required")
|
filter, err := nextString("query string required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2186,7 +2232,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-literal":
|
case "--no-literal":
|
||||||
opts.Normalize = true
|
opts.Normalize = true
|
||||||
case "--algo":
|
case "--algo":
|
||||||
str, err := nextString(allArgs, &i, "algorithm required (v1|v2)")
|
str, err := nextString("algorithm required (v1|v2)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2194,13 +2240,13 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--scheme":
|
case "--scheme":
|
||||||
str, err := nextString(allArgs, &i, "scoring scheme required (default|path|history)")
|
str, err := nextString("scoring scheme required (default|path|history)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
opts.Scheme = strings.ToLower(str)
|
opts.Scheme = strings.ToLower(str)
|
||||||
case "--expect":
|
case "--expect":
|
||||||
str, err := nextString(allArgs, &i, "key names required")
|
str, err := nextString("key names required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2218,7 +2264,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--disabled", "--phony":
|
case "--disabled", "--phony":
|
||||||
opts.Phony = true
|
opts.Phony = true
|
||||||
case "--tiebreak":
|
case "--tiebreak":
|
||||||
str, err := nextString(allArgs, &i, "sort criterion required")
|
str, err := nextString("sort criterion required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2226,7 +2272,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--bind":
|
case "--bind":
|
||||||
str, err := nextString(allArgs, &i, "bind expression required")
|
str, err := nextString("bind expression required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2234,7 +2280,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--color":
|
case "--color":
|
||||||
_, spec := optionalNextString(allArgs, &i)
|
_, spec := optionalNextString()
|
||||||
if len(spec) == 0 {
|
if len(spec) == 0 {
|
||||||
opts.Theme = tui.EmptyTheme()
|
opts.Theme = tui.EmptyTheme()
|
||||||
} else {
|
} else {
|
||||||
@ -2243,7 +2289,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "--toggle-sort":
|
case "--toggle-sort":
|
||||||
str, err := nextString(allArgs, &i, "key name required")
|
str, err := nextString("key name required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2251,13 +2297,13 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "-d", "--delimiter":
|
case "-d", "--delimiter":
|
||||||
str, err := nextString(allArgs, &i, "delimiter required")
|
str, err := nextString("delimiter required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
opts.Delimiter = delimiterRegexp(str)
|
opts.Delimiter = delimiterRegexp(str)
|
||||||
case "-n", "--nth":
|
case "-n", "--nth":
|
||||||
str, err := nextString(allArgs, &i, "nth expression required")
|
str, err := nextString("nth expression required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2265,7 +2311,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--with-nth":
|
case "--with-nth":
|
||||||
str, err := nextString(allArgs, &i, "nth expression required")
|
str, err := nextString("nth expression required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2273,7 +2319,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "-s", "--sort":
|
case "-s", "--sort":
|
||||||
if opts.Sort, err = optionalNumeric(allArgs, &i, 1); err != nil {
|
if opts.Sort, err = optionalNumeric(1); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "+s", "--no-sort":
|
case "+s", "--no-sort":
|
||||||
@ -2287,7 +2333,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-tac":
|
case "--no-tac":
|
||||||
opts.Tac = false
|
opts.Tac = false
|
||||||
case "--tail":
|
case "--tail":
|
||||||
if opts.Tail, err = nextInt(allArgs, &i, "number of items to keep required"); err != nil {
|
if opts.Tail, err = nextInt("number of items to keep required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if opts.Tail <= 0 {
|
if opts.Tail <= 0 {
|
||||||
@ -2302,7 +2348,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "+i", "--no-ignore-case":
|
case "+i", "--no-ignore-case":
|
||||||
opts.Case = CaseRespect
|
opts.Case = CaseRespect
|
||||||
case "-m", "--multi":
|
case "-m", "--multi":
|
||||||
if opts.Multi, err = optionalNumeric(allArgs, &i, maxMulti); err != nil {
|
if opts.Multi, err = optionalNumeric(maxMulti); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "+m", "--no-multi":
|
case "+m", "--no-multi":
|
||||||
@ -2326,7 +2372,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-bold":
|
case "--no-bold":
|
||||||
opts.Bold = false
|
opts.Bold = false
|
||||||
case "--layout":
|
case "--layout":
|
||||||
str, err := nextString(allArgs, &i, "layout required (default / reverse / reverse-list)")
|
str, err := nextString("layout required (default / reverse / reverse-list)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2350,7 +2396,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-wrap":
|
case "--no-wrap":
|
||||||
opts.Wrap = false
|
opts.Wrap = false
|
||||||
case "--wrap-sign":
|
case "--wrap-sign":
|
||||||
str, err := nextString(allArgs, &i, "wrap sign required")
|
str, err := nextString("wrap sign required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2368,11 +2414,11 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-hscroll":
|
case "--no-hscroll":
|
||||||
opts.Hscroll = false
|
opts.Hscroll = false
|
||||||
case "--hscroll-off":
|
case "--hscroll-off":
|
||||||
if opts.HscrollOff, err = nextInt(allArgs, &i, "hscroll offset required"); err != nil {
|
if opts.HscrollOff, err = nextInt("hscroll offset required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--scroll-off":
|
case "--scroll-off":
|
||||||
if opts.ScrollOff, err = nextInt(allArgs, &i, "scroll offset required"); err != nil {
|
if opts.ScrollOff, err = nextInt("scroll offset required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--filepath-word":
|
case "--filepath-word":
|
||||||
@ -2380,7 +2426,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-filepath-word":
|
case "--no-filepath-word":
|
||||||
opts.FileWord = false
|
opts.FileWord = false
|
||||||
case "--info":
|
case "--info":
|
||||||
str, err := nextString(allArgs, &i, "info style required")
|
str, err := nextString("info style required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2388,7 +2434,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--info-command":
|
case "--info-command":
|
||||||
if opts.InfoCommand, err = nextString(allArgs, &i, "info command required"); err != nil {
|
if opts.InfoCommand, err = nextString("info command required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--no-info-command":
|
case "--no-info-command":
|
||||||
@ -2401,7 +2447,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-inline-info":
|
case "--no-inline-info":
|
||||||
opts.InfoStyle = infoDefault
|
opts.InfoStyle = infoDefault
|
||||||
case "--separator":
|
case "--separator":
|
||||||
separator, err := nextString(allArgs, &i, "separator character required")
|
separator, err := nextString("separator character required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2410,7 +2456,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
nosep := ""
|
nosep := ""
|
||||||
opts.Separator = &nosep
|
opts.Separator = &nosep
|
||||||
case "--scrollbar":
|
case "--scrollbar":
|
||||||
given, bar := optionalNextString(allArgs, &i)
|
given, bar := optionalNextString()
|
||||||
if given {
|
if given {
|
||||||
opts.Scrollbar = &bar
|
opts.Scrollbar = &bar
|
||||||
} else {
|
} else {
|
||||||
@ -2420,7 +2466,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
noBar := ""
|
noBar := ""
|
||||||
opts.Scrollbar = &noBar
|
opts.Scrollbar = &noBar
|
||||||
case "--jump-labels":
|
case "--jump-labels":
|
||||||
if opts.JumpLabels, err = nextString(allArgs, &i, "label characters required"); err != nil {
|
if opts.JumpLabels, err = nextString("label characters required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
validateJumpLabels = true
|
validateJumpLabels = true
|
||||||
@ -2447,26 +2493,26 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-print-query":
|
case "--no-print-query":
|
||||||
opts.PrintQuery = false
|
opts.PrintQuery = false
|
||||||
case "--prompt":
|
case "--prompt":
|
||||||
opts.Prompt, err = nextString(allArgs, &i, "prompt string required")
|
opts.Prompt, err = nextString("prompt string required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--pointer":
|
case "--pointer":
|
||||||
str, err := nextString(allArgs, &i, "pointer sign required")
|
str, err := nextString("pointer sign required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
str = firstLine(str)
|
str = firstLine(str)
|
||||||
opts.Pointer = &str
|
opts.Pointer = &str
|
||||||
case "--marker":
|
case "--marker":
|
||||||
str, err := nextString(allArgs, &i, "marker sign required")
|
str, err := nextString("marker sign required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
str = firstLine(str)
|
str = firstLine(str)
|
||||||
opts.Marker = &str
|
opts.Marker = &str
|
||||||
case "--marker-multi-line":
|
case "--marker-multi-line":
|
||||||
str, err := nextString(allArgs, &i, "marker sign for multi-line entries required")
|
str, err := nextString("marker sign for multi-line entries required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2480,7 +2526,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-history":
|
case "--no-history":
|
||||||
opts.History = nil
|
opts.History = nil
|
||||||
case "--history":
|
case "--history":
|
||||||
str, err := nextString(allArgs, &i, "history file path required")
|
str, err := nextString("history file path required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2488,7 +2534,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--history-size":
|
case "--history-size":
|
||||||
n, err := nextInt(allArgs, &i, "history max size required")
|
n, err := nextInt("history max size required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2500,13 +2546,13 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-header-lines":
|
case "--no-header-lines":
|
||||||
opts.HeaderLines = 0
|
opts.HeaderLines = 0
|
||||||
case "--header":
|
case "--header":
|
||||||
str, err := nextString(allArgs, &i, "header string required")
|
str, err := nextString("header string required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
opts.Header = strLines(str)
|
opts.Header = strLines(str)
|
||||||
case "--header-lines":
|
case "--header-lines":
|
||||||
if opts.HeaderLines, err = nextInt(allArgs, &i, "number of header lines required"); err != nil {
|
if opts.HeaderLines, err = nextInt("number of header lines required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--header-first":
|
case "--header-first":
|
||||||
@ -2514,26 +2560,26 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-header-first":
|
case "--no-header-first":
|
||||||
opts.HeaderFirst = false
|
opts.HeaderFirst = false
|
||||||
case "--gap":
|
case "--gap":
|
||||||
if opts.Gap, err = optionalNumeric(allArgs, &i, 1); err != nil {
|
if opts.Gap, err = optionalNumeric(1); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--no-gap":
|
case "--no-gap":
|
||||||
opts.Gap = 0
|
opts.Gap = 0
|
||||||
case "--ellipsis":
|
case "--ellipsis":
|
||||||
str, err := nextString(allArgs, &i, "ellipsis string required")
|
str, err := nextString("ellipsis string required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
str = firstLine(str)
|
str = firstLine(str)
|
||||||
opts.Ellipsis = &str
|
opts.Ellipsis = &str
|
||||||
case "--preview":
|
case "--preview":
|
||||||
if opts.Preview.command, err = nextString(allArgs, &i, "preview command required"); err != nil {
|
if opts.Preview.command, err = nextString("preview command required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--no-preview":
|
case "--no-preview":
|
||||||
opts.Preview.command = ""
|
opts.Preview.command = ""
|
||||||
case "--preview-window":
|
case "--preview-window":
|
||||||
str, err := nextString(allArgs, &i, "preview window layout required: [up|down|left|right][,SIZE[%]][,border-STYLE][,wrap][,cycle][,hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default]")
|
str, err := nextString("preview window layout required: [up|down|left|right][,SIZE[%]][,border-STYLE][,wrap][,cycle][,hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default]")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2543,12 +2589,12 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-preview-border":
|
case "--no-preview-border":
|
||||||
opts.Preview.border = tui.BorderNone
|
opts.Preview.border = tui.BorderNone
|
||||||
case "--preview-border":
|
case "--preview-border":
|
||||||
hasArg, arg := optionalNextString(allArgs, &i)
|
hasArg, arg := optionalNextString()
|
||||||
if opts.Preview.border, err = parseBorder(arg, !hasArg, true); err != nil {
|
if opts.Preview.border, err = parseBorder(arg, !hasArg, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--height":
|
case "--height":
|
||||||
str, err := nextString(allArgs, &i, "height required: [~]HEIGHT[%]")
|
str, err := nextString("height required: [~]HEIGHT[%]")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2556,7 +2602,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--min-height":
|
case "--min-height":
|
||||||
if opts.MinHeight, err = nextInt(allArgs, &i, "height required: HEIGHT"); err != nil {
|
if opts.MinHeight, err = nextInt("height required: HEIGHT"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--no-height":
|
case "--no-height":
|
||||||
@ -2568,12 +2614,12 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-border":
|
case "--no-border":
|
||||||
opts.BorderShape = tui.BorderNone
|
opts.BorderShape = tui.BorderNone
|
||||||
case "--border":
|
case "--border":
|
||||||
hasArg, arg := optionalNextString(allArgs, &i)
|
hasArg, arg := optionalNextString()
|
||||||
if opts.BorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
if opts.BorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--list-border":
|
case "--list-border":
|
||||||
hasArg, arg := optionalNextString(allArgs, &i)
|
hasArg, arg := optionalNextString()
|
||||||
if opts.ListBorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
if opts.ListBorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2582,12 +2628,12 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-list-label":
|
case "--no-list-label":
|
||||||
opts.ListLabel.label = ""
|
opts.ListLabel.label = ""
|
||||||
case "--list-label":
|
case "--list-label":
|
||||||
opts.ListLabel.label, err = nextString(allArgs, &i, "label required")
|
opts.ListLabel.label, err = nextString("label required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--list-label-pos":
|
case "--list-label-pos":
|
||||||
pos, err := nextString(allArgs, &i, "label position required (positive or negative integer or 'center')")
|
pos, err := nextString("label position required (positive or negative integer or 'center')")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2597,18 +2643,18 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-header-border":
|
case "--no-header-border":
|
||||||
opts.HeaderBorderShape = tui.BorderNone
|
opts.HeaderBorderShape = tui.BorderNone
|
||||||
case "--header-border":
|
case "--header-border":
|
||||||
hasArg, arg := optionalNextString(allArgs, &i)
|
hasArg, arg := optionalNextString()
|
||||||
if opts.HeaderBorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
if opts.HeaderBorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--no-header-label":
|
case "--no-header-label":
|
||||||
opts.HeaderLabel.label = ""
|
opts.HeaderLabel.label = ""
|
||||||
case "--header-label":
|
case "--header-label":
|
||||||
if opts.HeaderLabel.label, err = nextString(allArgs, &i, "header label required"); err != nil {
|
if opts.HeaderLabel.label, err = nextString("header label required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--header-label-pos":
|
case "--header-label-pos":
|
||||||
pos, err := nextString(allArgs, &i, "header label position required (positive or negative integer or 'center')")
|
pos, err := nextString("header label position required (positive or negative integer or 'center')")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2618,18 +2664,18 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-input-border":
|
case "--no-input-border":
|
||||||
opts.InputBorderShape = tui.BorderNone
|
opts.InputBorderShape = tui.BorderNone
|
||||||
case "--input-border":
|
case "--input-border":
|
||||||
hasArg, arg := optionalNextString(allArgs, &i)
|
hasArg, arg := optionalNextString()
|
||||||
if opts.InputBorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
if opts.InputBorderShape, err = parseBorder(arg, !hasArg, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--no-input-label":
|
case "--no-input-label":
|
||||||
opts.InputLabel.label = ""
|
opts.InputLabel.label = ""
|
||||||
case "--input-label":
|
case "--input-label":
|
||||||
if opts.InputLabel.label, err = nextString(allArgs, &i, "input label required"); err != nil {
|
if opts.InputLabel.label, err = nextString("input label required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--input-label-pos":
|
case "--input-label-pos":
|
||||||
pos, err := nextString(allArgs, &i, "input label position required (positive or negative integer or 'center')")
|
pos, err := nextString("input label position required (positive or negative integer or 'center')")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2639,12 +2685,12 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-border-label":
|
case "--no-border-label":
|
||||||
opts.BorderLabel.label = ""
|
opts.BorderLabel.label = ""
|
||||||
case "--border-label":
|
case "--border-label":
|
||||||
opts.BorderLabel.label, err = nextString(allArgs, &i, "label required")
|
opts.BorderLabel.label, err = nextString("label required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--border-label-pos":
|
case "--border-label-pos":
|
||||||
pos, err := nextString(allArgs, &i, "label position required (positive or negative integer or 'center')")
|
pos, err := nextString("label position required (positive or negative integer or 'center')")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2654,11 +2700,11 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-preview-label":
|
case "--no-preview-label":
|
||||||
opts.PreviewLabel.label = ""
|
opts.PreviewLabel.label = ""
|
||||||
case "--preview-label":
|
case "--preview-label":
|
||||||
if opts.PreviewLabel.label, err = nextString(allArgs, &i, "preview label required"); err != nil {
|
if opts.PreviewLabel.label, err = nextString("preview label required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--preview-label-pos":
|
case "--preview-label-pos":
|
||||||
pos, err := nextString(allArgs, &i, "preview label position required (positive or negative integer or 'center')")
|
pos, err := nextString("preview label position required (positive or negative integer or 'center')")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2666,7 +2712,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--style":
|
case "--style":
|
||||||
preset, err := nextString(allArgs, &i, "preset name required: [default|minimal|full]")
|
preset, err := nextString("preset name required: [default|minimal|full]")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2682,7 +2728,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-ambidouble":
|
case "--no-ambidouble":
|
||||||
opts.Ambidouble = false
|
opts.Ambidouble = false
|
||||||
case "--margin":
|
case "--margin":
|
||||||
str, err := nextString(allArgs, &i, "margin required (TRBL / TB,RL / T,RL,B / T,R,B,L)")
|
str, err := nextString("margin required (TRBL / TB,RL / T,RL,B / T,R,B,L)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2690,7 +2736,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--padding":
|
case "--padding":
|
||||||
str, err := nextString(allArgs, &i, "padding required (TRBL / TB,RL / T,RL,B / T,R,B,L)")
|
str, err := nextString("padding required (TRBL / TB,RL / T,RL,B / T,R,B,L)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2698,15 +2744,15 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--tabstop":
|
case "--tabstop":
|
||||||
if opts.Tabstop, err = nextInt(allArgs, &i, "tab stop required"); err != nil {
|
if opts.Tabstop, err = nextInt("tab stop required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--with-shell":
|
case "--with-shell":
|
||||||
if opts.WithShell, err = nextString(allArgs, &i, "shell command and flags required"); err != nil {
|
if opts.WithShell, err = nextString("shell command and flags required"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--listen", "--listen-unsafe":
|
case "--listen", "--listen-unsafe":
|
||||||
given, str := optionalNextString(allArgs, &i)
|
given, str := optionalNextString()
|
||||||
addr := defaultListenAddr
|
addr := defaultListenAddr
|
||||||
if given {
|
if given {
|
||||||
var err error
|
var err error
|
||||||
@ -2725,7 +2771,7 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
case "--no-clear":
|
case "--no-clear":
|
||||||
opts.ClearOnExit = false
|
opts.ClearOnExit = false
|
||||||
case "--walker":
|
case "--walker":
|
||||||
str, err := nextString(allArgs, &i, "walker options required [file][,dir][,follow][,hidden]")
|
str, err := nextString("walker options required [file][,dir][,follow][,hidden]")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2733,261 +2779,58 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--walker-root":
|
case "--walker-root":
|
||||||
if opts.WalkerRoot, err = nextDirs(allArgs, &i); err != nil {
|
if opts.WalkerRoot, err = nextDirs(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--walker-skip":
|
case "--walker-skip":
|
||||||
str, err := nextString(allArgs, &i, "directory names to ignore required")
|
str, err := nextString("directory names to ignore required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
opts.WalkerSkip = filterNonEmpty(strings.Split(str, ","))
|
opts.WalkerSkip = filterNonEmpty(strings.Split(str, ","))
|
||||||
case "--profile-cpu":
|
case "--profile-cpu":
|
||||||
if opts.CPUProfile, err = nextString(allArgs, &i, "file path required: cpu"); err != nil {
|
if opts.CPUProfile, err = nextString("file path required: cpu"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--profile-mem":
|
case "--profile-mem":
|
||||||
if opts.MEMProfile, err = nextString(allArgs, &i, "file path required: mem"); err != nil {
|
if opts.MEMProfile, err = nextString("file path required: mem"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--profile-block":
|
case "--profile-block":
|
||||||
if opts.BlockProfile, err = nextString(allArgs, &i, "file path required: block"); err != nil {
|
if opts.BlockProfile, err = nextString("file path required: block"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--profile-mutex":
|
case "--profile-mutex":
|
||||||
if opts.MutexProfile, err = nextString(allArgs, &i, "file path required: mutex"); err != nil {
|
if opts.MutexProfile, err = nextString("file path required: mutex"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "--":
|
case "--":
|
||||||
// Ignored
|
// Ignored
|
||||||
default:
|
default:
|
||||||
if match, value := optString(arg, "--algo="); match {
|
if match, value := optString(arg, "-q"); match {
|
||||||
if opts.FuzzyAlgo, err = parseAlgo(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--tmux="); match {
|
|
||||||
if opts.Tmux, err = parseTmuxOptions(value, index); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--style="); match {
|
|
||||||
if err := applyPreset(opts, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--scheme="); match {
|
|
||||||
opts.Scheme = strings.ToLower(value)
|
|
||||||
} else if match, value := optString(arg, "-q", "--query="); match {
|
|
||||||
opts.Query = value
|
opts.Query = value
|
||||||
} else if match, value := optString(arg, "-f", "--filter="); match {
|
} else if match, value := optString(arg, "-f"); match {
|
||||||
opts.Filter = &value
|
opts.Filter = &value
|
||||||
} else if match, value := optString(arg, "-d", "--delimiter="); match {
|
} else if match, value := optString(arg, "-d"); match {
|
||||||
opts.Delimiter = delimiterRegexp(value)
|
opts.Delimiter = delimiterRegexp(value)
|
||||||
} else if match, value := optString(arg, "--border="); match {
|
} else if match, value := optString(arg, "-n"); match {
|
||||||
if opts.BorderShape, err = parseBorder(value, false, false); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--preview-border="); match {
|
|
||||||
if opts.Preview.border, err = parseBorder(value, false, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--list-border="); match {
|
|
||||||
if opts.ListBorderShape, err = parseBorder(value, false, false); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--list-label="); match {
|
|
||||||
opts.ListLabel.label = value
|
|
||||||
} else if match, value := optString(arg, "--list-label-pos="); match {
|
|
||||||
if err := parseLabelPosition(&opts.ListLabel, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--input-border="); match {
|
|
||||||
if opts.InputBorderShape, err = parseBorder(value, false, false); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--input-label="); match {
|
|
||||||
opts.InputLabel.label = value
|
|
||||||
} else if match, value := optString(arg, "--input-label-pos="); match {
|
|
||||||
if err := parseLabelPosition(&opts.InputLabel, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--border-label="); match {
|
|
||||||
opts.BorderLabel.label = value
|
|
||||||
} else if match, value := optString(arg, "--border-label-pos="); match {
|
|
||||||
if err := parseLabelPosition(&opts.BorderLabel, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--preview-label="); match {
|
|
||||||
opts.PreviewLabel.label = value
|
|
||||||
} else if match, value := optString(arg, "--preview-label-pos="); match {
|
|
||||||
if err := parseLabelPosition(&opts.PreviewLabel, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--wrap-sign="); match {
|
|
||||||
opts.WrapSign = &value
|
|
||||||
} else if match, value := optString(arg, "--prompt="); match {
|
|
||||||
opts.Prompt = value
|
|
||||||
} else if match, value := optString(arg, "--pointer="); match {
|
|
||||||
str := firstLine(value)
|
|
||||||
opts.Pointer = &str
|
|
||||||
} else if match, value := optString(arg, "--marker="); match {
|
|
||||||
str := firstLine(value)
|
|
||||||
opts.Marker = &str
|
|
||||||
} else if match, value := optString(arg, "--marker-multi-line="); match {
|
|
||||||
if opts.MarkerMulti, err = parseMarkerMultiLine(firstLine(value)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "-n", "--nth="); match {
|
|
||||||
if opts.Nth, err = splitNth(value); err != nil {
|
if opts.Nth, err = splitNth(value); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if match, value := optString(arg, "--with-nth="); match {
|
} else if match, _ := optString(arg, "-s"); match {
|
||||||
if opts.WithNth, err = splitNth(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, _ := optString(arg, "-s", "--sort="); match {
|
|
||||||
opts.Sort = 1 // Don't care
|
opts.Sort = 1 // Don't care
|
||||||
} else if match, value := optString(arg, "-m", "--multi="); match {
|
} else if match, value := optString(arg, "-m"); match {
|
||||||
if opts.Multi, err = atoi(value); err != nil {
|
if opts.Multi, err = atoi(value); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if match, value := optString(arg, "--height="); match {
|
|
||||||
if opts.Height, err = parseHeight(value, index); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--min-height="); match {
|
|
||||||
if opts.MinHeight, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--layout="); match {
|
|
||||||
if opts.Layout, err = parseLayout(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--info="); match {
|
|
||||||
if opts.InfoStyle, opts.InfoPrefix, err = parseInfoStyle(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--info-command="); match {
|
|
||||||
opts.InfoCommand = value
|
|
||||||
} else if match, value := optString(arg, "--separator="); match {
|
|
||||||
opts.Separator = &value
|
|
||||||
} else if match, value := optString(arg, "--scrollbar="); match {
|
|
||||||
opts.Scrollbar = &value
|
|
||||||
} else if match, value := optString(arg, "--toggle-sort="); match {
|
|
||||||
if err := parseToggleSort(opts.Keymap, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--expect="); match {
|
|
||||||
chords, err := parseKeyChords(value, "key names required")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for k, v := range chords {
|
|
||||||
opts.Expect[k] = v
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--tiebreak="); match {
|
|
||||||
if opts.Criteria, err = parseTiebreak(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--color="); match {
|
|
||||||
if opts.Theme, err = parseTheme(opts.Theme, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--bind="); match {
|
|
||||||
if err := parseKeymap(opts.Keymap, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--history="); match {
|
|
||||||
if err := setHistory(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--history-size="); match {
|
|
||||||
n, err := atoi(value)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := setHistoryMax(n); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--header="); match {
|
|
||||||
opts.Header = strLines(value)
|
|
||||||
} else if match, value := optString(arg, "--header-lines="); match {
|
|
||||||
if opts.HeaderLines, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--gap="); match {
|
|
||||||
if opts.Gap, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--ellipsis="); match {
|
|
||||||
str := firstLine(value)
|
|
||||||
opts.Ellipsis = &str
|
|
||||||
} else if match, value := optString(arg, "--preview="); match {
|
|
||||||
opts.Preview.command = value
|
|
||||||
} else if match, value := optString(arg, "--preview-window="); match {
|
|
||||||
if err := parsePreviewWindow(&opts.Preview, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--margin="); match {
|
|
||||||
if opts.Margin, err = parseMargin("margin", value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--padding="); match {
|
|
||||||
if opts.Padding, err = parseMargin("padding", value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--tabstop="); match {
|
|
||||||
if opts.Tabstop, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--with-shell="); match {
|
|
||||||
opts.WithShell = value
|
|
||||||
} else if match, value := optString(arg, "--listen="); match {
|
|
||||||
addr, err := parseListenAddress(value)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
opts.ListenAddr = &addr
|
|
||||||
opts.Unsafe = false
|
|
||||||
} else if match, value := optString(arg, "--listen-unsafe="); match {
|
|
||||||
addr, err := parseListenAddress(value)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
opts.ListenAddr = &addr
|
|
||||||
opts.Unsafe = true
|
|
||||||
} else if match, value := optString(arg, "--walker="); match {
|
|
||||||
if opts.WalkerOpts, err = parseWalkerOpts(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--walker-root="); match {
|
|
||||||
if !isDir(value) {
|
|
||||||
return errors.New("not a directory: " + value)
|
|
||||||
}
|
|
||||||
dirs, _ := nextDirs(allArgs, &i)
|
|
||||||
opts.WalkerRoot = append([]string{value}, dirs...)
|
|
||||||
} else if match, value := optString(arg, "--walker-skip="); match {
|
|
||||||
opts.WalkerSkip = filterNonEmpty(strings.Split(value, ","))
|
|
||||||
} else if match, value := optString(arg, "--hscroll-off="); match {
|
|
||||||
if opts.HscrollOff, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--scroll-off="); match {
|
|
||||||
if opts.ScrollOff, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--jump-labels="); match {
|
|
||||||
opts.JumpLabels = value
|
|
||||||
validateJumpLabels = true
|
|
||||||
} else if match, value := optString(arg, "--tail="); match {
|
|
||||||
if opts.Tail, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if opts.Tail <= 0 {
|
|
||||||
return errors.New("number of items to keep must be a positive integer")
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return errors.New("unknown option: " + arg)
|
return errors.New("unknown option: " + arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if val != nil {
|
||||||
|
return errors.New("unexpected value for " + arg + ": " + *val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*index += len(allArgs)
|
*index += len(allArgs)
|
||||||
|
|
||||||
|
@ -9,9 +9,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestDelimiterRegex(t *testing.T) {
|
func TestDelimiterRegex(t *testing.T) {
|
||||||
// Valid regex
|
// Valid regex, but a single character -> string
|
||||||
delim := delimiterRegexp(".")
|
delim := delimiterRegexp(".")
|
||||||
if delim.regex == nil || delim.str != nil {
|
if delim.regex != nil || *delim.str != "." {
|
||||||
|
t.Error(delim)
|
||||||
|
}
|
||||||
|
delim = delimiterRegexp("|")
|
||||||
|
if delim.regex != nil || *delim.str != "|" {
|
||||||
t.Error(delim)
|
t.Error(delim)
|
||||||
}
|
}
|
||||||
// Broken regex -> string
|
// Broken regex -> string
|
||||||
|
101
src/terminal.go
101
src/terminal.go
@ -782,7 +782,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
// Minimum height required to render fzf excluding margin and padding
|
// Minimum height required to render fzf excluding margin and padding
|
||||||
effectiveMinHeight := minHeight
|
effectiveMinHeight := minHeight
|
||||||
if previewBox != nil && opts.Preview.aboveOrBelow() {
|
if previewBox != nil && opts.Preview.aboveOrBelow() {
|
||||||
effectiveMinHeight += 1 + borderLines(opts.Preview.border)
|
effectiveMinHeight += 1 + borderLines(opts.Preview.Border())
|
||||||
}
|
}
|
||||||
if noSeparatorLine(opts.InfoStyle, opts.Separator == nil || uniseg.StringWidth(*opts.Separator) > 0) {
|
if noSeparatorLine(opts.InfoStyle, opts.Separator == nil || uniseg.StringWidth(*opts.Separator) > 0) {
|
||||||
effectiveMinHeight--
|
effectiveMinHeight--
|
||||||
@ -1012,6 +1012,14 @@ func (t *Terminal) deferActivation() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) environ() []string {
|
func (t *Terminal) environ() []string {
|
||||||
|
return t.environImpl(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Terminal) environForPreview() []string {
|
||||||
|
return t.environImpl(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Terminal) environImpl(forPreview bool) []string {
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
if t.listenPort != nil {
|
if t.listenPort != nil {
|
||||||
env = append(env, fmt.Sprintf("FZF_PORT=%d", *t.listenPort))
|
env = append(env, fmt.Sprintf("FZF_PORT=%d", *t.listenPort))
|
||||||
@ -1037,9 +1045,11 @@ func (t *Terminal) environ() []string {
|
|||||||
if pwindowSize.Lines > 0 {
|
if pwindowSize.Lines > 0 {
|
||||||
lines := fmt.Sprintf("LINES=%d", pwindowSize.Lines)
|
lines := fmt.Sprintf("LINES=%d", pwindowSize.Lines)
|
||||||
columns := fmt.Sprintf("COLUMNS=%d", pwindowSize.Columns)
|
columns := fmt.Sprintf("COLUMNS=%d", pwindowSize.Columns)
|
||||||
env = append(env, lines)
|
if forPreview {
|
||||||
|
env = append(env, lines)
|
||||||
|
env = append(env, columns)
|
||||||
|
}
|
||||||
env = append(env, "FZF_PREVIEW_"+lines)
|
env = append(env, "FZF_PREVIEW_"+lines)
|
||||||
env = append(env, columns)
|
|
||||||
env = append(env, "FZF_PREVIEW_"+columns)
|
env = append(env, "FZF_PREVIEW_"+columns)
|
||||||
env = append(env, fmt.Sprintf("FZF_PREVIEW_TOP=%d", t.tui.Top()+t.pwindow.Top()))
|
env = append(env, fmt.Sprintf("FZF_PREVIEW_TOP=%d", t.tui.Top()+t.pwindow.Top()))
|
||||||
env = append(env, fmt.Sprintf("FZF_PREVIEW_LEFT=%d", t.pwindow.Left()))
|
env = append(env, fmt.Sprintf("FZF_PREVIEW_LEFT=%d", t.pwindow.Left()))
|
||||||
@ -1093,6 +1103,9 @@ func (t *Terminal) extraLines() int {
|
|||||||
if t.listBorderShape.Visible() {
|
if t.listBorderShape.Visible() {
|
||||||
extra += borderLines(t.listBorderShape)
|
extra += borderLines(t.listBorderShape)
|
||||||
}
|
}
|
||||||
|
if t.headerBorderShape.Visible() {
|
||||||
|
extra += borderLines(t.headerBorderShape)
|
||||||
|
}
|
||||||
if !t.noSeparatorLine() {
|
if !t.noSeparatorLine() {
|
||||||
extra++
|
extra++
|
||||||
}
|
}
|
||||||
@ -1508,12 +1521,12 @@ func calculateSize(base int, size sizeSpec, occupied int, minSize int) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) minPreviewSize(opts *previewOpts) (int, int) {
|
func (t *Terminal) minPreviewSize(opts *previewOpts) (int, int) {
|
||||||
minPreviewWidth := 1 + borderColumns(opts.border, t.borderWidth)
|
minPreviewWidth := 1 + borderColumns(opts.Border(), t.borderWidth)
|
||||||
minPreviewHeight := 1 + borderLines(opts.border)
|
minPreviewHeight := 1 + borderLines(opts.Border())
|
||||||
|
|
||||||
switch opts.position {
|
switch opts.position {
|
||||||
case posLeft, posRight:
|
case posLeft, posRight:
|
||||||
if len(t.scrollbar) > 0 && !opts.HasBorderRight() {
|
if len(t.scrollbar) > 0 && !opts.Border().HasRight() {
|
||||||
// Need a column to show scrollbar
|
// Need a column to show scrollbar
|
||||||
minPreviewWidth++
|
minPreviewWidth++
|
||||||
}
|
}
|
||||||
@ -1743,11 +1756,14 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
t.areaLines = height
|
t.areaLines = height
|
||||||
t.areaColumns = width
|
t.areaColumns = width
|
||||||
|
|
||||||
|
// If none of the inner borders has the right side, but the outer border does, increase the list width by 1 column
|
||||||
|
listStickToRight := t.borderShape.HasRight() && !t.listBorderShape.HasRight() && !t.inputBorderShape.HasRight() &&
|
||||||
|
(!t.headerVisible || !t.headerBorderShape.HasRight() || t.visibleHeaderLines() == 0)
|
||||||
|
|
||||||
// Set up preview window
|
// Set up preview window
|
||||||
noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode)
|
noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode)
|
||||||
if forcePreview || t.needPreviewWindow() {
|
if forcePreview || t.needPreviewWindow() {
|
||||||
var resizePreviewWindows func(previewOpts *previewOpts)
|
var resizePreviewWindows func(previewOpts *previewOpts)
|
||||||
stickToRight := false
|
|
||||||
resizePreviewWindows = func(previewOpts *previewOpts) {
|
resizePreviewWindows = func(previewOpts *previewOpts) {
|
||||||
t.activePreviewOpts = previewOpts
|
t.activePreviewOpts = previewOpts
|
||||||
if previewOpts.size.size == 0 {
|
if previewOpts.size.size == 0 {
|
||||||
@ -1757,19 +1773,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
createPreviewWindow := func(y int, x int, w int, h int) {
|
createPreviewWindow := func(y int, x int, w int, h int) {
|
||||||
pwidth := w
|
pwidth := w
|
||||||
pheight := h
|
pheight := h
|
||||||
shape := previewOpts.border
|
shape := previewOpts.Border()
|
||||||
if shape == tui.BorderLine {
|
|
||||||
switch previewOpts.position {
|
|
||||||
case posUp:
|
|
||||||
shape = tui.BorderBottom
|
|
||||||
case posDown:
|
|
||||||
shape = tui.BorderTop
|
|
||||||
case posLeft:
|
|
||||||
shape = tui.BorderRight
|
|
||||||
case posRight:
|
|
||||||
shape = tui.BorderLeft
|
|
||||||
}
|
|
||||||
}
|
|
||||||
previewBorder := tui.MakeBorderStyle(shape, t.unicode)
|
previewBorder := tui.MakeBorderStyle(shape, t.unicode)
|
||||||
t.pborder = t.tui.NewWindow(y, x, w, h, tui.WindowPreview, previewBorder, false)
|
t.pborder = t.tui.NewWindow(y, x, w, h, tui.WindowPreview, previewBorder, false)
|
||||||
pwidth -= borderColumns(shape, bw)
|
pwidth -= borderColumns(shape, bw)
|
||||||
@ -1813,11 +1817,9 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
if previewOpts.hidden {
|
if previewOpts.hidden {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// If none of the inner borders has the right side, but the outer border does, increase the width by 1 column
|
|
||||||
stickToRight = t.borderShape.HasRight() &&
|
listStickToRight = listStickToRight && !previewOpts.Border().HasRight()
|
||||||
!previewOpts.HasBorderRight() && !t.listBorderShape.HasRight() && !t.inputBorderShape.HasRight() &&
|
if listStickToRight {
|
||||||
(!t.headerVisible || !t.headerBorderShape.HasRight() || t.visibleHeaderLines() == 0)
|
|
||||||
if stickToRight {
|
|
||||||
innerWidth++
|
innerWidth++
|
||||||
width++
|
width++
|
||||||
}
|
}
|
||||||
@ -1890,9 +1892,12 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
innerBorderFn(marginInt[0], marginInt[3]+pwidth, width-pwidth, height)
|
innerBorderFn(marginInt[0], marginInt[3]+pwidth, width-pwidth, height)
|
||||||
createPreviewWindow(marginInt[0], marginInt[3], pwidth, height)
|
createPreviewWindow(marginInt[0], marginInt[3], pwidth, height)
|
||||||
} else {
|
} else {
|
||||||
// NOTE: fzf --preview 'cat {}' --preview-window border-left --border
|
// NOTE: Relaxed condition for the following cases
|
||||||
stickToRight = !previewOpts.HasBorderRight() && t.borderShape.HasRight()
|
// fzf --preview 'seq 500' --preview-window border-left --border
|
||||||
if stickToRight {
|
// fzf --preview 'seq 500' --preview-window border-left --border --list-border
|
||||||
|
// fzf --preview 'seq 500' --preview-window border-left --border --input-border
|
||||||
|
listStickToRight = t.borderShape.HasRight() && !previewOpts.Border().HasRight()
|
||||||
|
if listStickToRight {
|
||||||
innerWidth++
|
innerWidth++
|
||||||
width++
|
width++
|
||||||
}
|
}
|
||||||
@ -1906,7 +1911,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
}
|
}
|
||||||
resizePreviewWindows(&t.previewOpts)
|
resizePreviewWindows(&t.previewOpts)
|
||||||
|
|
||||||
if t.borderShape.HasRight() && !stickToRight {
|
if t.borderShape.HasRight() && !listStickToRight {
|
||||||
// Need to clear the extra margin between the borders
|
// Need to clear the extra margin between the borders
|
||||||
// fzf --preview 'seq 1000' --preview-window border-left --bind space:change-preview-window:border-rounded --border vertical
|
// fzf --preview 'seq 1000' --preview-window border-left --bind space:change-preview-window:border-rounded --border vertical
|
||||||
// fzf --preview 'seq 1000' --preview-window up,hidden --bind space:toggle-preview --border vertical
|
// fzf --preview 'seq 1000' --preview-window up,hidden --bind space:toggle-preview --border vertical
|
||||||
@ -1929,7 +1934,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
|
|
||||||
// Without preview window
|
// Without preview window
|
||||||
if t.window == nil {
|
if t.window == nil {
|
||||||
if t.borderShape.HasRight() && !hasListBorder {
|
if listStickToRight {
|
||||||
// Put scrollbar closer to the right border for consistent look
|
// Put scrollbar closer to the right border for consistent look
|
||||||
innerWidth++
|
innerWidth++
|
||||||
width++
|
width++
|
||||||
@ -2014,9 +2019,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
|
|||||||
// Print border label
|
// Print border label
|
||||||
t.printLabel(t.wborder, t.listLabel, t.listLabelOpts, t.listLabelLen, t.listBorderShape, false)
|
t.printLabel(t.wborder, t.listLabel, t.listLabelOpts, t.listLabelLen, t.listBorderShape, false)
|
||||||
t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, false)
|
t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, false)
|
||||||
if t.pborder != nil && t.pwindow.Height() != t.pborder.Height() { // To address --preview-border=line with different positions
|
t.printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.activePreviewOpts.Border(), false)
|
||||||
t.printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.activePreviewOpts.border, false)
|
|
||||||
}
|
|
||||||
t.printLabel(t.inputBorder, t.inputLabel, t.inputLabelOpts, t.inputLabelLen, t.inputBorderShape, false)
|
t.printLabel(t.inputBorder, t.inputLabel, t.inputLabelOpts, t.inputLabelLen, t.inputBorderShape, false)
|
||||||
t.printLabel(t.headerBorder, t.headerLabel, t.headerLabelOpts, t.headerLabelLen, t.headerBorderShape, false)
|
t.printLabel(t.headerBorder, t.headerLabel, t.headerLabelOpts, t.headerLabelLen, t.headerBorderShape, false)
|
||||||
}
|
}
|
||||||
@ -2031,7 +2034,7 @@ func (t *Terminal) printLabel(window tui.Window, render labelPrinter, opts label
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch borderShape {
|
switch borderShape {
|
||||||
case tui.BorderHorizontal, tui.BorderTop, tui.BorderBottom, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderThinBlock, tui.BorderDouble, tui.BorderLine:
|
case tui.BorderHorizontal, tui.BorderTop, tui.BorderBottom, tui.BorderRounded, tui.BorderSharp, tui.BorderBold, tui.BorderBlock, tui.BorderThinBlock, tui.BorderDouble:
|
||||||
if redrawBorder {
|
if redrawBorder {
|
||||||
window.DrawHBorder()
|
window.DrawHBorder()
|
||||||
}
|
}
|
||||||
@ -2388,9 +2391,19 @@ func (t *Terminal) printHeaderImpl() {
|
|||||||
}
|
}
|
||||||
// Wrapping is not supported for header
|
// Wrapping is not supported for header
|
||||||
wrap := t.wrap
|
wrap := t.wrap
|
||||||
|
|
||||||
|
// Align header with the list
|
||||||
|
// fzf --header-lines 3 --style full --no-list-border
|
||||||
|
// fzf --header-lines 3 --style full --no-header-border
|
||||||
|
// fzf --header-lines 3 --style full --no-header-border --no-input-border
|
||||||
indentSize := t.pointerLen + t.markerLen
|
indentSize := t.pointerLen + t.markerLen
|
||||||
if t.headerBorderShape.HasLeft() && !t.listBorderShape.HasLeft() {
|
if t.headerWindow != nil {
|
||||||
indentSize = util.Max(0, indentSize-(1+t.borderWidth))
|
if t.listBorderShape.HasLeft() {
|
||||||
|
indentSize += 1 + t.borderWidth
|
||||||
|
}
|
||||||
|
if t.headerBorderShape.HasLeft() {
|
||||||
|
indentSize -= 1 + t.borderWidth
|
||||||
|
}
|
||||||
}
|
}
|
||||||
indent := strings.Repeat(" ", indentSize)
|
indent := strings.Repeat(" ", indentSize)
|
||||||
t.wrap = false
|
t.wrap = false
|
||||||
@ -3214,11 +3227,11 @@ func (t *Terminal) renderPreviewScrollbar(yoff int, barLength int, barStart int)
|
|||||||
t.previewer.xw = xw
|
t.previewer.xw = xw
|
||||||
}
|
}
|
||||||
xshift := -1 - t.borderWidth
|
xshift := -1 - t.borderWidth
|
||||||
if !t.activePreviewOpts.HasBorderRight() {
|
if !t.activePreviewOpts.Border().HasRight() {
|
||||||
xshift = -1
|
xshift = -1
|
||||||
}
|
}
|
||||||
yshift := 1
|
yshift := 1
|
||||||
if !t.activePreviewOpts.border.HasTop() {
|
if !t.activePreviewOpts.Border().HasTop() {
|
||||||
yshift = 0
|
yshift = 0
|
||||||
}
|
}
|
||||||
for i := yoff; i < height; i++ {
|
for i := yoff; i < height; i++ {
|
||||||
@ -3880,13 +3893,13 @@ func (t *Terminal) Loop() error {
|
|||||||
if t.activePreviewOpts.aboveOrBelow() {
|
if t.activePreviewOpts.aboveOrBelow() {
|
||||||
if t.activePreviewOpts.size.percent {
|
if t.activePreviewOpts.size.percent {
|
||||||
newContentHeight := int(float64(contentHeight) * 100. / (100. - t.activePreviewOpts.size.size))
|
newContentHeight := int(float64(contentHeight) * 100. / (100. - t.activePreviewOpts.size.size))
|
||||||
contentHeight = util.Max(contentHeight+1+borderLines(t.activePreviewOpts.border), newContentHeight)
|
contentHeight = util.Max(contentHeight+1+borderLines(t.activePreviewOpts.Border()), newContentHeight)
|
||||||
} else {
|
} else {
|
||||||
contentHeight += int(t.activePreviewOpts.size.size) + borderLines(t.activePreviewOpts.border)
|
contentHeight += int(t.activePreviewOpts.size.size) + borderLines(t.activePreviewOpts.Border())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Minimum height if preview window can appear
|
// Minimum height if preview window can appear
|
||||||
contentHeight = util.Max(contentHeight, 1+borderLines(t.activePreviewOpts.border))
|
contentHeight = util.Max(contentHeight, 1+borderLines(t.activePreviewOpts.Border()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return util.Min(termHeight, contentHeight+pad)
|
return util.Min(termHeight, contentHeight+pad)
|
||||||
@ -4129,7 +4142,7 @@ func (t *Terminal) Loop() error {
|
|||||||
if len(command) > 0 && t.canPreview() {
|
if len(command) > 0 && t.canPreview() {
|
||||||
_, list := t.buildPlusList(command, false)
|
_, list := t.buildPlusList(command, false)
|
||||||
t.cancelPreview()
|
t.cancelPreview()
|
||||||
t.previewBox.Set(reqPreviewEnqueue, previewRequest{command, t.evaluateScrollOffset(), list, t.environ()})
|
t.previewBox.Set(reqPreviewEnqueue, previewRequest{command, t.evaluateScrollOffset(), list, t.environForPreview()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4240,7 +4253,7 @@ func (t *Terminal) Loop() error {
|
|||||||
case reqRedrawBorderLabel:
|
case reqRedrawBorderLabel:
|
||||||
t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, true)
|
t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, true)
|
||||||
case reqRedrawPreviewLabel:
|
case reqRedrawPreviewLabel:
|
||||||
t.printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.activePreviewOpts.border, true)
|
t.printLabel(t.pborder, t.previewLabel, t.previewLabelOpts, t.previewLabelLen, t.activePreviewOpts.Border(), true)
|
||||||
case reqReinit:
|
case reqReinit:
|
||||||
t.tui.Resume(t.fullscreen, true)
|
t.tui.Resume(t.fullscreen, true)
|
||||||
t.fullRedraw()
|
t.fullRedraw()
|
||||||
@ -4521,7 +4534,7 @@ func (t *Terminal) Loop() error {
|
|||||||
if valid {
|
if valid {
|
||||||
t.cancelPreview()
|
t.cancelPreview()
|
||||||
t.previewBox.Set(reqPreviewEnqueue,
|
t.previewBox.Set(reqPreviewEnqueue,
|
||||||
previewRequest{t.previewOpts.command, t.evaluateScrollOffset(), list, t.environ()})
|
previewRequest{t.previewOpts.command, t.evaluateScrollOffset(), list, t.environForPreview()})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Discard the preview content so that it won't accidentally appear
|
// Discard the preview content so that it won't accidentally appear
|
||||||
|
@ -897,6 +897,10 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
|
|||||||
theme.Border = o(baseTheme.Border, theme.Border)
|
theme.Border = o(baseTheme.Border, theme.Border)
|
||||||
theme.BorderLabel = o(baseTheme.BorderLabel, theme.BorderLabel)
|
theme.BorderLabel = o(baseTheme.BorderLabel, theme.BorderLabel)
|
||||||
|
|
||||||
|
undefined := NewColorAttr()
|
||||||
|
scrollbarDefined := theme.Scrollbar != undefined
|
||||||
|
previewBorderDefined := theme.PreviewBorder != undefined
|
||||||
|
|
||||||
// These colors are not defined in the base themes
|
// These colors are not defined in the base themes
|
||||||
theme.ListFg = o(theme.Fg, theme.ListFg)
|
theme.ListFg = o(theme.Fg, theme.ListFg)
|
||||||
theme.ListBg = o(theme.Bg, theme.ListBg)
|
theme.ListBg = o(theme.Bg, theme.ListBg)
|
||||||
@ -913,7 +917,17 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
|
|||||||
theme.ListBorder = o(theme.Border, theme.ListBorder)
|
theme.ListBorder = o(theme.Border, theme.ListBorder)
|
||||||
theme.Separator = o(theme.ListBorder, theme.Separator)
|
theme.Separator = o(theme.ListBorder, theme.Separator)
|
||||||
theme.Scrollbar = o(theme.ListBorder, theme.Scrollbar)
|
theme.Scrollbar = o(theme.ListBorder, theme.Scrollbar)
|
||||||
theme.PreviewScrollbar = o(theme.PreviewBorder, theme.PreviewScrollbar)
|
/*
|
||||||
|
--color list-border:green
|
||||||
|
--color scrollbar:red
|
||||||
|
--color scrollbar:red,list-border:green
|
||||||
|
--color scrollbar:red,preview-border:green
|
||||||
|
*/
|
||||||
|
if scrollbarDefined && !previewBorderDefined {
|
||||||
|
theme.PreviewScrollbar = o(theme.Scrollbar, theme.PreviewScrollbar)
|
||||||
|
} else {
|
||||||
|
theme.PreviewScrollbar = o(theme.PreviewBorder, theme.PreviewScrollbar)
|
||||||
|
}
|
||||||
if hasInputWindow {
|
if hasInputWindow {
|
||||||
theme.InputBg = o(theme.Bg, theme.InputBg)
|
theme.InputBg = o(theme.Bg, theme.InputBg)
|
||||||
} else {
|
} else {
|
||||||
|
@ -3513,9 +3513,9 @@ class TestGoFZF < TestBase
|
|||||||
│ ║ 11
|
│ ║ 11
|
||||||
│ ║ > 10
|
│ ║ > 10
|
||||||
│ ╚LIST══════
|
│ ╚LIST══════
|
||||||
│ 3
|
│ 3
|
||||||
│ 2
|
│ 2
|
||||||
│ 1
|
│ 1
|
||||||
│ ┏INPUT━━━━━
|
│ ┏INPUT━━━━━
|
||||||
│ ┃ 19/97
|
│ ┃ 19/97
|
||||||
│ ┃ > 1
|
│ ┃ > 1
|
||||||
@ -3529,9 +3529,9 @@ class TestGoFZF < TestBase
|
|||||||
│ ║ 11
|
│ ║ 11
|
||||||
│ ║ > 10
|
│ ║ > 10
|
||||||
│ ╚ list ════
|
│ ╚ list ════
|
||||||
│ 3
|
│ 3
|
||||||
│ 2
|
│ 2
|
||||||
│ 1
|
│ 1
|
||||||
│ ┏ input ━━━
|
│ ┏ input ━━━
|
||||||
│ ┃ 19/97
|
│ ┃ 19/97
|
||||||
│ ┃ > 1
|
│ ┃ > 1
|
||||||
@ -3556,9 +3556,9 @@ class TestGoFZF < TestBase
|
|||||||
│ ┃ 19/97
|
│ ┃ 19/97
|
||||||
│ ┃ > 1
|
│ ┃ > 1
|
||||||
│ ┗━━━━━━━━━━
|
│ ┗━━━━━━━━━━
|
||||||
│ 3
|
│ 3
|
||||||
│ 2
|
│ 2
|
||||||
│ 1
|
│ 1
|
||||||
│
|
│
|
||||||
╰──────────────
|
╰──────────────
|
||||||
BLOCK
|
BLOCK
|
||||||
@ -3572,9 +3572,9 @@ class TestGoFZF < TestBase
|
|||||||
│ ┃ 19/97
|
│ ┃ 19/97
|
||||||
│ ┃ > 1
|
│ ┃ > 1
|
||||||
│ ┗━━━━━━━━━━
|
│ ┗━━━━━━━━━━
|
||||||
│ 3
|
│ 3
|
||||||
│ 2
|
│ 2
|
||||||
│ 1
|
│ 1
|
||||||
│
|
│
|
||||||
╰──────────────
|
╰──────────────
|
||||||
BLOCK
|
BLOCK
|
||||||
@ -3702,6 +3702,22 @@ class TestGoFZF < TestBase
|
|||||||
BLOCK
|
BLOCK
|
||||||
tmux.until { assert_block(block, _1) }
|
tmux.until { assert_block(block, _1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_style_full_adaptive_height
|
||||||
|
tmux.send_keys %(seq 1| #{FZF} --style=full --height=~100% --header-lines=1 --info=default), :Enter
|
||||||
|
block = <<~BLOCK
|
||||||
|
╭────────
|
||||||
|
╰────────
|
||||||
|
╭────────
|
||||||
|
│ 1
|
||||||
|
╰────────
|
||||||
|
╭────────
|
||||||
|
│ 0/0
|
||||||
|
│ >
|
||||||
|
╰────────
|
||||||
|
BLOCK
|
||||||
|
tmux.until { assert_block(block, _1) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module TestShell
|
module TestShell
|
||||||
|
Loading…
Reference in New Issue
Block a user