mirror of https://github.com/Llewellynvdm/fzf.git
parent
f0fbed6007
commit
5d360180af
|
@ -17,8 +17,9 @@ CHANGELOG
|
||||||
--bind 'focus:transform:[[ -n {} ]] && exit; [[ {fzf:action} =~ up$ ]] && echo up || echo down'
|
--bind 'focus:transform:[[ -n {} ]] && exit; [[ {fzf:action} =~ up$ ]] && echo up || echo down'
|
||||||
```
|
```
|
||||||
- Added placeholder expressions
|
- Added placeholder expressions
|
||||||
- `{fzf:action}` - the name of the last action performed
|
- `{fzf:action}` - The name of the last action performed
|
||||||
- `{fzf:query}` - synonym for `{q}`
|
- `{fzf:prompt}` - Prompt string (including ANSI color codes)
|
||||||
|
- `{fzf:query}` - Synonym for `{q}`
|
||||||
- Added support for negative height
|
- Added support for negative height
|
||||||
```sh
|
```sh
|
||||||
# Terminal height minus 1, so you can still see the command line
|
# Terminal height minus 1, so you can still see the command line
|
||||||
|
|
|
@ -593,6 +593,7 @@ Also,
|
||||||
Use \fB{+n}\fR if you want all index numbers when multiple lines are selected.
|
Use \fB{+n}\fR if you want all index numbers when multiple lines are selected.
|
||||||
.br
|
.br
|
||||||
* \fB{fzf:action}\fR is replaced to to the name of the last action performed
|
* \fB{fzf:action}\fR is replaced to to the name of the last action performed
|
||||||
|
* \fB{fzf:prompt}\fR is replaced to to the prompt string
|
||||||
|
|
||||||
Note that you can escape a placeholder pattern by prepending a backslash.
|
Note that you can escape a placeholder pattern by prepending a backslash.
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ var actionTypeRegex *regexp.Regexp
|
||||||
const clearCode string = "\x1b[2J"
|
const clearCode string = "\x1b[2J"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
placeholder = regexp.MustCompile(`\\?(?:{[+sf]*[0-9,-.]*}|{q}|{fzf:(?:query|action)}|{\+?f?nf?})`)
|
placeholder = regexp.MustCompile(`\\?(?:{[+sf]*[0-9,-.]*}|{q}|{fzf:(?:query|action|prompt)}|{\+?f?nf?})`)
|
||||||
whiteSuffix = regexp.MustCompile(`\s*$`)
|
whiteSuffix = regexp.MustCompile(`\s*$`)
|
||||||
offsetComponentRegex = regexp.MustCompile(`([+-][0-9]+)|(-?/[1-9][0-9]*)`)
|
offsetComponentRegex = regexp.MustCompile(`([+-][0-9]+)|(-?/[1-9][0-9]*)`)
|
||||||
offsetTrimCharsRegex = regexp.MustCompile(`[^0-9/+-]`)
|
offsetTrimCharsRegex = regexp.MustCompile(`[^0-9/+-]`)
|
||||||
|
@ -183,6 +183,7 @@ type Terminal struct {
|
||||||
separator labelPrinter
|
separator labelPrinter
|
||||||
separatorLen int
|
separatorLen int
|
||||||
spinner []string
|
spinner []string
|
||||||
|
promptString string
|
||||||
prompt func()
|
prompt func()
|
||||||
promptLen int
|
promptLen int
|
||||||
borderLabel labelPrinter
|
borderLabel labelPrinter
|
||||||
|
@ -670,6 +671,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
||||||
infoSep: opts.InfoSep,
|
infoSep: opts.InfoSep,
|
||||||
separator: nil,
|
separator: nil,
|
||||||
spinner: makeSpinner(opts.Unicode),
|
spinner: makeSpinner(opts.Unicode),
|
||||||
|
promptString: opts.Prompt,
|
||||||
queryLen: [2]int{0, 0},
|
queryLen: [2]int{0, 0},
|
||||||
layout: opts.Layout,
|
layout: opts.Layout,
|
||||||
fullscreen: fullscreen,
|
fullscreen: fullscreen,
|
||||||
|
@ -2354,7 +2356,7 @@ func parsePlaceholder(match string) (bool, string, placeholderFlags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(match, "{fzf:") {
|
if strings.HasPrefix(match, "{fzf:") {
|
||||||
// Both {fzf:query} and {fzf:action} are not determined by the current item
|
// {fzf:*} are not determined by the current item
|
||||||
flags.forceUpdate = true
|
flags.forceUpdate = true
|
||||||
return false, match, flags
|
return false, match, flags
|
||||||
}
|
}
|
||||||
|
@ -2421,9 +2423,30 @@ func cleanTemporaryFiles() {
|
||||||
activeTempFiles = []string{}
|
activeTempFiles = []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type replacePlaceholderParams struct {
|
||||||
|
template string
|
||||||
|
stripAnsi bool
|
||||||
|
delimiter Delimiter
|
||||||
|
printsep string
|
||||||
|
forcePlus bool
|
||||||
|
query string
|
||||||
|
allItems []*Item
|
||||||
|
lastAction actionType
|
||||||
|
prompt string
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Terminal) replacePlaceholder(template string, forcePlus bool, input string, list []*Item) string {
|
func (t *Terminal) replacePlaceholder(template string, forcePlus bool, input string, list []*Item) string {
|
||||||
return replacePlaceholder(
|
return replacePlaceholder(replacePlaceholderParams{
|
||||||
template, t.ansi, t.delimiter, t.printsep, forcePlus, input, list, t.lastAction)
|
template: template,
|
||||||
|
stripAnsi: t.ansi,
|
||||||
|
delimiter: t.delimiter,
|
||||||
|
printsep: t.printsep,
|
||||||
|
forcePlus: forcePlus,
|
||||||
|
query: input,
|
||||||
|
allItems: list,
|
||||||
|
lastAction: t.lastAction,
|
||||||
|
prompt: t.promptString,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) evaluateScrollOffset() int {
|
func (t *Terminal) evaluateScrollOffset() int {
|
||||||
|
@ -2461,9 +2484,9 @@ func (t *Terminal) evaluateScrollOffset() int {
|
||||||
return util.Max(0, base)
|
return util.Max(0, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, printsep string, forcePlus bool, query string, allItems []*Item, lastAction actionType) string {
|
func replacePlaceholder(params replacePlaceholderParams) string {
|
||||||
current := allItems[:1]
|
current := params.allItems[:1]
|
||||||
selected := allItems[1:]
|
selected := params.allItems[1:]
|
||||||
if current[0] == nil {
|
if current[0] == nil {
|
||||||
current = []*Item{}
|
current = []*Item{}
|
||||||
}
|
}
|
||||||
|
@ -2472,7 +2495,7 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, pr
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace placeholders one by one
|
// replace placeholders one by one
|
||||||
return placeholder.ReplaceAllStringFunc(template, func(match string) string {
|
return placeholder.ReplaceAllStringFunc(params.template, func(match string) string {
|
||||||
escaped, match, flags := parsePlaceholder(match)
|
escaped, match, flags := parsePlaceholder(match)
|
||||||
|
|
||||||
// this function implements the effects a placeholder has on items
|
// this function implements the effects a placeholder has on items
|
||||||
|
@ -2482,17 +2505,8 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, pr
|
||||||
switch {
|
switch {
|
||||||
case escaped:
|
case escaped:
|
||||||
return match
|
return match
|
||||||
case match == "{fzf:action}":
|
|
||||||
name := ""
|
|
||||||
for i, r := range lastAction.String()[3:] {
|
|
||||||
if i > 0 && r >= 'A' && r <= 'Z' {
|
|
||||||
name += "-"
|
|
||||||
}
|
|
||||||
name += string(r)
|
|
||||||
}
|
|
||||||
return strings.ToLower(name)
|
|
||||||
case match == "{q}" || match == "{fzf:query}":
|
case match == "{q}" || match == "{fzf:query}":
|
||||||
return quoteEntry(query)
|
return quoteEntry(params.query)
|
||||||
case match == "{}":
|
case match == "{}":
|
||||||
replace = func(item *Item) string {
|
replace = func(item *Item) string {
|
||||||
switch {
|
switch {
|
||||||
|
@ -2503,11 +2517,22 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, pr
|
||||||
}
|
}
|
||||||
return strconv.Itoa(n)
|
return strconv.Itoa(n)
|
||||||
case flags.file:
|
case flags.file:
|
||||||
return item.AsString(stripAnsi)
|
return item.AsString(params.stripAnsi)
|
||||||
default:
|
default:
|
||||||
return quoteEntry(item.AsString(stripAnsi))
|
return quoteEntry(item.AsString(params.stripAnsi))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case match == "{fzf:action}":
|
||||||
|
name := ""
|
||||||
|
for i, r := range params.lastAction.String()[3:] {
|
||||||
|
if i > 0 && r >= 'A' && r <= 'Z' {
|
||||||
|
name += "-"
|
||||||
|
}
|
||||||
|
name += string(r)
|
||||||
|
}
|
||||||
|
return strings.ToLower(name)
|
||||||
|
case match == "{fzf:prompt}":
|
||||||
|
return quoteEntry(params.prompt)
|
||||||
default:
|
default:
|
||||||
// token type and also failover (below)
|
// token type and also failover (below)
|
||||||
rangeExpressions := strings.Split(match[1:len(match)-1], ",")
|
rangeExpressions := strings.Split(match[1:len(match)-1], ",")
|
||||||
|
@ -2522,15 +2547,15 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, pr
|
||||||
}
|
}
|
||||||
|
|
||||||
replace = func(item *Item) string {
|
replace = func(item *Item) string {
|
||||||
tokens := Tokenize(item.AsString(stripAnsi), delimiter)
|
tokens := Tokenize(item.AsString(params.stripAnsi), params.delimiter)
|
||||||
trans := Transform(tokens, ranges)
|
trans := Transform(tokens, ranges)
|
||||||
str := joinTokens(trans)
|
str := joinTokens(trans)
|
||||||
|
|
||||||
// trim the last delimiter
|
// trim the last delimiter
|
||||||
if delimiter.str != nil {
|
if params.delimiter.str != nil {
|
||||||
str = strings.TrimSuffix(str, *delimiter.str)
|
str = strings.TrimSuffix(str, *params.delimiter.str)
|
||||||
} else if delimiter.regex != nil {
|
} else if params.delimiter.regex != nil {
|
||||||
delims := delimiter.regex.FindAllStringIndex(str, -1)
|
delims := params.delimiter.regex.FindAllStringIndex(str, -1)
|
||||||
// make sure the delimiter is at the very end of the string
|
// make sure the delimiter is at the very end of the string
|
||||||
if len(delims) > 0 && delims[len(delims)-1][1] == len(str) {
|
if len(delims) > 0 && delims[len(delims)-1][1] == len(str) {
|
||||||
str = str[:delims[len(delims)-1][0]]
|
str = str[:delims[len(delims)-1][0]]
|
||||||
|
@ -2550,7 +2575,7 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, pr
|
||||||
// apply 'replace' function over proper set of items and return result
|
// apply 'replace' function over proper set of items and return result
|
||||||
|
|
||||||
items := current
|
items := current
|
||||||
if flags.plus || forcePlus {
|
if flags.plus || params.forcePlus {
|
||||||
items = selected
|
items = selected
|
||||||
}
|
}
|
||||||
replacements := make([]string, len(items))
|
replacements := make([]string, len(items))
|
||||||
|
@ -2560,7 +2585,7 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, pr
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.file {
|
if flags.file {
|
||||||
return writeTemporaryFile(replacements, printsep)
|
return writeTemporaryFile(replacements, params.printsep)
|
||||||
}
|
}
|
||||||
return strings.Join(replacements, " ")
|
return strings.Join(replacements, " ")
|
||||||
})
|
})
|
||||||
|
@ -3302,6 +3327,7 @@ func (t *Terminal) Loop() {
|
||||||
}
|
}
|
||||||
case actTransformPrompt:
|
case actTransformPrompt:
|
||||||
prompt := t.executeCommand(a.a, false, true, true, true)
|
prompt := t.executeCommand(a.a, false, true, true, true)
|
||||||
|
t.promptString = prompt
|
||||||
t.prompt, t.promptLen = t.parsePrompt(prompt)
|
t.prompt, t.promptLen = t.parsePrompt(prompt)
|
||||||
req(reqPrompt)
|
req(reqPrompt)
|
||||||
case actTransformQuery:
|
case actTransformQuery:
|
||||||
|
@ -3395,6 +3421,7 @@ func (t *Terminal) Loop() {
|
||||||
req(reqRedrawPreviewLabel)
|
req(reqRedrawPreviewLabel)
|
||||||
}
|
}
|
||||||
case actChangePrompt:
|
case actChangePrompt:
|
||||||
|
t.promptString = a.a
|
||||||
t.prompt, t.promptLen = t.parsePrompt(a.a)
|
t.prompt, t.promptLen = t.parsePrompt(a.a)
|
||||||
req(reqPrompt)
|
req(reqPrompt)
|
||||||
case actPreview:
|
case actPreview:
|
||||||
|
|
|
@ -12,6 +12,20 @@ import (
|
||||||
"github.com/junegunn/fzf/src/util"
|
"github.com/junegunn/fzf/src/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func replacePlaceholderTest(template string, stripAnsi bool, delimiter Delimiter, printsep string, forcePlus bool, query string, allItems []*Item) string {
|
||||||
|
return replacePlaceholder(replacePlaceholderParams{
|
||||||
|
template: template,
|
||||||
|
stripAnsi: stripAnsi,
|
||||||
|
delimiter: delimiter,
|
||||||
|
printsep: printsep,
|
||||||
|
forcePlus: forcePlus,
|
||||||
|
query: query,
|
||||||
|
allItems: allItems,
|
||||||
|
lastAction: actBackwardDeleteCharEof,
|
||||||
|
prompt: "prompt",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestReplacePlaceholder(t *testing.T) {
|
func TestReplacePlaceholder(t *testing.T) {
|
||||||
item1 := newItem(" foo'bar \x1b[31mbaz\x1b[m")
|
item1 := newItem(" foo'bar \x1b[31mbaz\x1b[m")
|
||||||
items1 := []*Item{item1, item1}
|
items1 := []*Item{item1, item1}
|
||||||
|
@ -52,90 +66,90 @@ func TestReplacePlaceholder(t *testing.T) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// {}, preserve ansi
|
// {}, preserve ansi
|
||||||
result = replacePlaceholder("echo {}", false, Delimiter{}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {}", false, Delimiter{}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.I}}bar \x1b[31mbaz\x1b[m{{.O}}")
|
checkFormat("echo {{.O}} foo{{.I}}bar \x1b[31mbaz\x1b[m{{.O}}")
|
||||||
|
|
||||||
// {}, strip ansi
|
// {}, strip ansi
|
||||||
result = replacePlaceholder("echo {}", true, Delimiter{}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {}", true, Delimiter{}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}")
|
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}")
|
||||||
|
|
||||||
// {}, with multiple items
|
// {}, with multiple items
|
||||||
result = replacePlaceholder("echo {}", true, Delimiter{}, printsep, false, "query", items2, actIgnore)
|
result = replacePlaceholderTest("echo {}", true, Delimiter{}, printsep, false, "query", items2)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}}")
|
||||||
|
|
||||||
// {..}, strip leading whitespaces, preserve ansi
|
// {..}, strip leading whitespaces, preserve ansi
|
||||||
result = replacePlaceholder("echo {..}", false, Delimiter{}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {..}", false, Delimiter{}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar \x1b[31mbaz\x1b[m{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar \x1b[31mbaz\x1b[m{{.O}}")
|
||||||
|
|
||||||
// {..}, strip leading whitespaces, strip ansi
|
// {..}, strip leading whitespaces, strip ansi
|
||||||
result = replacePlaceholder("echo {..}", true, Delimiter{}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {..}", true, Delimiter{}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}}")
|
||||||
|
|
||||||
// {q}
|
// {q}
|
||||||
result = replacePlaceholder("echo {} {q}", true, Delimiter{}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {} {q}", true, Delimiter{}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}} {{.O}}query{{.O}}")
|
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}} {{.O}}query{{.O}}")
|
||||||
|
|
||||||
// {q}, multiple items
|
// {q}, multiple items
|
||||||
result = replacePlaceholder("echo {+}{q}{+}", true, Delimiter{}, printsep, false, "query 'string'", items2, actIgnore)
|
result = replacePlaceholderTest("echo {+}{q}{+}", true, Delimiter{}, printsep, false, "query 'string'", items2)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}{{.O}}query {{.I}}string{{.I}}{{.O}}{{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}{{.O}}query {{.I}}string{{.I}}{{.O}}{{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {}{q}{}", true, Delimiter{}, printsep, false, "query 'string'", items2, actIgnore)
|
result = replacePlaceholderTest("echo {}{q}{}", true, Delimiter{}, printsep, false, "query 'string'", items2)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}}{{.O}}query {{.I}}string{{.I}}{{.O}}{{.O}}foo{{.I}}bar baz{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}}{{.O}}query {{.I}}string{{.I}}{{.O}}{{.O}}foo{{.I}}bar baz{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {1}/{2}/{2,1}/{-1}/{-2}/{}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}", true, Delimiter{}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {1}/{2}/{2,1}/{-1}/{-2}/{}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}", true, Delimiter{}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}}/{{.O}}baz{{.O}}/{{.O}}bazfoo{{.I}}bar{{.O}}/{{.O}}baz{{.O}}/{{.O}}foo{{.I}}bar{{.O}}/{{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}}/{{.O}}baz{{.O}}/{{.O}}bazfoo{{.I}}bar{{.O}}/{{.O}}baz{{.O}}/{{.O}}foo{{.I}}bar{{.O}}/{{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {1}/{2}/{-1}/{-2}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}", true, Delimiter{}, printsep, false, "query", items2, actIgnore)
|
result = replacePlaceholderTest("echo {1}/{2}/{-1}/{-2}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}", true, Delimiter{}, printsep, false, "query", items2)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}}/{{.O}}baz{{.O}}/{{.O}}baz{{.O}}/{{.O}}foo{{.I}}bar{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}}/{{.O}}baz{{.O}}/{{.O}}baz{{.O}}/{{.O}}foo{{.I}}bar{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {+1}/{+2}/{+-1}/{+-2}/{+..}/{n.t}/\\{}/\\{1}/\\{q}/{+3}", true, Delimiter{}, printsep, false, "query", items2, actIgnore)
|
result = replacePlaceholderTest("echo {+1}/{+2}/{+-1}/{+-2}/{+..}/{n.t}/\\{}/\\{1}/\\{q}/{+3}", true, Delimiter{}, printsep, false, "query", items2)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}} {{.O}}{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}} {{.O}}{{.O}}")
|
||||||
|
|
||||||
// forcePlus
|
// forcePlus
|
||||||
result = replacePlaceholder("echo {1}/{2}/{-1}/{-2}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}", true, Delimiter{}, printsep, true, "query", items2, actIgnore)
|
result = replacePlaceholderTest("echo {1}/{2}/{-1}/{-2}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}", true, Delimiter{}, printsep, true, "query", items2)
|
||||||
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}} {{.O}}{{.O}}")
|
checkFormat("echo {{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}baz{{.O}} {{.O}}BAZ{{.O}}/{{.O}}foo{{.I}}bar{{.O}} {{.O}}FOO{{.I}}BAR{{.O}}/{{.O}}foo{{.I}}bar baz{{.O}} {{.O}}FOO{{.I}}BAR BAZ{{.O}}/{n.t}/{}/{1}/{q}/{{.O}}{{.O}} {{.O}}{{.O}}")
|
||||||
|
|
||||||
// Whitespace preserving flag with "'" delimiter
|
// Whitespace preserving flag with "'" delimiter
|
||||||
result = replacePlaceholder("echo {s1}", true, Delimiter{str: &delim}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {s1}", true, Delimiter{str: &delim}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.O}}")
|
checkFormat("echo {{.O}} foo{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {s2}", true, Delimiter{str: &delim}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {s2}", true, Delimiter{str: &delim}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}}bar baz{{.O}}")
|
checkFormat("echo {{.O}}bar baz{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {s}", true, Delimiter{str: &delim}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {s}", true, Delimiter{str: &delim}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}")
|
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {s..}", true, Delimiter{str: &delim}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {s..}", true, Delimiter{str: &delim}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}")
|
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}")
|
||||||
|
|
||||||
// Whitespace preserving flag with regex delimiter
|
// Whitespace preserving flag with regex delimiter
|
||||||
regex = regexp.MustCompile(`\w+`)
|
regex = regexp.MustCompile(`\w+`)
|
||||||
|
|
||||||
result = replacePlaceholder("echo {s1}", true, Delimiter{regex: regex}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {s1}", true, Delimiter{regex: regex}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} {{.O}}")
|
checkFormat("echo {{.O}} {{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {s2}", true, Delimiter{regex: regex}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {s2}", true, Delimiter{regex: regex}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}}{{.I}}{{.O}}")
|
checkFormat("echo {{.O}}{{.I}}{{.O}}")
|
||||||
|
|
||||||
result = replacePlaceholder("echo {s3}", true, Delimiter{regex: regex}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {s3}", true, Delimiter{regex: regex}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} {{.O}}")
|
checkFormat("echo {{.O}} {{.O}}")
|
||||||
|
|
||||||
// No match
|
// No match
|
||||||
result = replacePlaceholder("echo {}/{+}", true, Delimiter{}, printsep, false, "query", []*Item{nil, nil}, actIgnore)
|
result = replacePlaceholderTest("echo {}/{+}", true, Delimiter{}, printsep, false, "query", []*Item{nil, nil})
|
||||||
check("echo /")
|
check("echo /")
|
||||||
|
|
||||||
// No match, but with selections
|
// No match, but with selections
|
||||||
result = replacePlaceholder("echo {}/{+}", true, Delimiter{}, printsep, false, "query", []*Item{nil, item1}, actIgnore)
|
result = replacePlaceholderTest("echo {}/{+}", true, Delimiter{}, printsep, false, "query", []*Item{nil, item1})
|
||||||
checkFormat("echo /{{.O}} foo{{.I}}bar baz{{.O}}")
|
checkFormat("echo /{{.O}} foo{{.I}}bar baz{{.O}}")
|
||||||
|
|
||||||
// String delimiter
|
// String delimiter
|
||||||
result = replacePlaceholder("echo {}/{1}/{2}", true, Delimiter{str: &delim}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {}/{1}/{2}", true, Delimiter{str: &delim}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}foo{{.O}}/{{.O}}bar baz{{.O}}")
|
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}foo{{.O}}/{{.O}}bar baz{{.O}}")
|
||||||
|
|
||||||
// Regex delimiter
|
// Regex delimiter
|
||||||
regex = regexp.MustCompile("[oa]+")
|
regex = regexp.MustCompile("[oa]+")
|
||||||
// foo'bar baz
|
// foo'bar baz
|
||||||
result = replacePlaceholder("echo {}/{1}/{3}/{2..3}", true, Delimiter{regex: regex}, printsep, false, "query", items1, actIgnore)
|
result = replacePlaceholderTest("echo {}/{1}/{3}/{2..3}", true, Delimiter{regex: regex}, printsep, false, "query", items1)
|
||||||
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}f{{.O}}/{{.O}}r b{{.O}}/{{.O}}{{.I}}bar b{{.O}}")
|
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}f{{.O}}/{{.O}}r b{{.O}}/{{.O}}{{.I}}bar b{{.O}}")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -155,7 +169,6 @@ func TestReplacePlaceholder(t *testing.T) {
|
||||||
newItem("7a 7b 7c 7d 7e 7f"),
|
newItem("7a 7b 7c 7d 7e 7f"),
|
||||||
}
|
}
|
||||||
stripAnsi := false
|
stripAnsi := false
|
||||||
printsep = "\n"
|
|
||||||
forcePlus := false
|
forcePlus := false
|
||||||
query := "sample query"
|
query := "sample query"
|
||||||
|
|
||||||
|
@ -199,7 +212,7 @@ func TestReplacePlaceholder(t *testing.T) {
|
||||||
// while the double q is invalid, it is useful here for testing purposes
|
// while the double q is invalid, it is useful here for testing purposes
|
||||||
templateToOutput[`{q}`] = "{{.O}}" + query + "{{.O}}"
|
templateToOutput[`{q}`] = "{{.O}}" + query + "{{.O}}"
|
||||||
templateToOutput[`{fzf:query}`] = "{{.O}}" + query + "{{.O}}"
|
templateToOutput[`{fzf:query}`] = "{{.O}}" + query + "{{.O}}"
|
||||||
templateToOutput[`{fzf:action}`] = "backward-delete-char-eof"
|
templateToOutput[`{fzf:action} {fzf:prompt}`] = "backward-delete-char-eof 'prompt'"
|
||||||
|
|
||||||
// IV. escaping placeholder
|
// IV. escaping placeholder
|
||||||
templateToOutput[`\{}`] = `{}`
|
templateToOutput[`\{}`] = `{}`
|
||||||
|
@ -210,11 +223,11 @@ func TestReplacePlaceholder(t *testing.T) {
|
||||||
templateToOutput[`{++}`] = templateToOutput[`{+}`]
|
templateToOutput[`{++}`] = templateToOutput[`{+}`]
|
||||||
|
|
||||||
for giveTemplate, wantOutput := range templateToOutput {
|
for giveTemplate, wantOutput := range templateToOutput {
|
||||||
result = replacePlaceholder(giveTemplate, stripAnsi, Delimiter{}, printsep, forcePlus, query, items3, actBackwardDeleteCharEof)
|
result = replacePlaceholderTest(giveTemplate, stripAnsi, Delimiter{}, printsep, forcePlus, query, items3)
|
||||||
checkFormat(wantOutput)
|
checkFormat(wantOutput)
|
||||||
}
|
}
|
||||||
for giveTemplate, wantOutput := range templateToFile {
|
for giveTemplate, wantOutput := range templateToFile {
|
||||||
path := replacePlaceholder(giveTemplate, stripAnsi, Delimiter{}, printsep, forcePlus, query, items3, actIgnore)
|
path := replacePlaceholderTest(giveTemplate, stripAnsi, Delimiter{}, printsep, forcePlus, query, items3)
|
||||||
|
|
||||||
data, err := readFile(path)
|
data, err := readFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -568,10 +581,10 @@ func testCommands(t *testing.T, tests []testCase) {
|
||||||
|
|
||||||
// evaluate the test cases
|
// evaluate the test cases
|
||||||
for idx, test := range tests {
|
for idx, test := range tests {
|
||||||
gotOutput := replacePlaceholder(
|
gotOutput := replacePlaceholderTest(
|
||||||
test.give.template, stripAnsi, delimiter, printsep, forcePlus,
|
test.give.template, stripAnsi, delimiter, printsep, forcePlus,
|
||||||
test.give.query,
|
test.give.query,
|
||||||
test.give.allItems, actIgnore)
|
test.give.allItems)
|
||||||
switch {
|
switch {
|
||||||
case test.want.output != "":
|
case test.want.output != "":
|
||||||
if gotOutput != test.want.output {
|
if gotOutput != test.want.output {
|
||||||
|
|
Loading…
Reference in New Issue