2016-10-03 05:16:10 +00:00
package fzf
import (
2021-09-24 00:45:06 +00:00
"bytes"
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
"io"
"os"
2016-10-03 05:16:10 +00:00
"regexp"
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
"strings"
2016-10-03 05:16:10 +00:00
"testing"
2021-09-24 00:45:06 +00:00
"text/template"
2016-10-03 05:16:10 +00:00
"github.com/junegunn/fzf/src/util"
)
func TestReplacePlaceholder ( t * testing . T ) {
2017-01-27 08:46:56 +00:00
item1 := newItem ( " foo'bar \x1b[31mbaz\x1b[m" )
items1 := [ ] * Item { item1 , item1 }
2016-10-03 05:16:10 +00:00
items2 := [ ] * Item {
2017-01-27 08:46:56 +00:00
newItem ( "foo'bar \x1b[31mbaz\x1b[m" ) ,
2016-10-03 05:16:10 +00:00
newItem ( "foo'bar \x1b[31mbaz\x1b[m" ) ,
newItem ( "FOO'BAR \x1b[31mBAZ\x1b[m" ) }
2018-03-30 02:47:46 +00:00
delim := "'"
var regex * regexp . Regexp
2016-10-03 05:16:10 +00:00
var result string
check := func ( expected string ) {
if result != expected {
t . Errorf ( "expected: %s, actual: %s" , expected , result )
}
}
2021-09-24 00:45:06 +00:00
// helper function that converts template format into string and carries out the check()
checkFormat := func ( format string ) {
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
type quotes struct { O , I , S string } // outer, inner quotes, print separator
unixStyle := quotes { ` ' ` , ` '\'' ` , "\n" }
windowsStyle := quotes { ` ^" ` , ` ' ` , "\n" }
2021-09-24 00:45:06 +00:00
var effectiveStyle quotes
if util . IsWindows ( ) {
effectiveStyle = windowsStyle
} else {
effectiveStyle = unixStyle
}
expected := templateToString ( format , effectiveStyle )
check ( expected )
}
2019-10-27 14:50:12 +00:00
printsep := "\n"
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
/ *
Test multiple placeholders and the function parameters .
* /
2016-10-03 05:16:10 +00:00
// {}, preserve ansi
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}" , false , Delimiter { } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.I}}bar \x1b[31mbaz\x1b[m{{.O}}" )
2016-10-03 05:16:10 +00:00
// {}, strip ansi
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}" , true , Delimiter { } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.I}}bar baz{{.O}}" )
2016-10-03 05:16:10 +00:00
// {}, with multiple items
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}" , true , Delimiter { } , printsep , false , "query" , items2 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}}foo{{.I}}bar baz{{.O}}" )
2016-10-03 05:16:10 +00:00
// {..}, strip leading whitespaces, preserve ansi
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {..}" , false , Delimiter { } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}}foo{{.I}}bar \x1b[31mbaz\x1b[m{{.O}}" )
2016-10-03 05:16:10 +00:00
// {..}, strip leading whitespaces, strip ansi
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {..}" , true , Delimiter { } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}}foo{{.I}}bar baz{{.O}}" )
2016-10-03 05:16:10 +00:00
// {q}
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {} {q}" , true , Delimiter { } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.I}}bar baz{{.O}} {{.O}}query{{.O}}" )
2016-10-03 05:16:10 +00:00
// {q}, multiple items
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {+}{q}{+}" , true , Delimiter { } , printsep , false , "query 'string'" , items2 )
2021-09-24 00:45:06 +00:00
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}}" )
2016-10-03 05:16:10 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}{q}{}" , true , Delimiter { } , printsep , false , "query 'string'" , items2 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}}foo{{.I}}bar baz{{.O}}{{.O}}query {{.I}}string{{.I}}{{.O}}{{.O}}foo{{.I}}bar baz{{.O}}" )
2017-01-27 08:46:56 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {1}/{2}/{2,1}/{-1}/{-2}/{}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}" , true , Delimiter { } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
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}}" )
2016-10-03 05:16:10 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {1}/{2}/{-1}/{-2}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}" , true , Delimiter { } , printsep , false , "query" , items2 )
2021-09-24 00:45:06 +00:00
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}}" )
2017-01-27 08:46:56 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {+1}/{+2}/{+-1}/{+-2}/{+..}/{n.t}/\\{}/\\{1}/\\{q}/{+3}" , true , Delimiter { } , printsep , false , "query" , items2 )
2021-09-24 00:45:06 +00:00
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}}" )
2016-10-03 05:16:10 +00:00
2017-01-27 08:46:56 +00:00
// forcePlus
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {1}/{2}/{-1}/{-2}/{..}/{n.t}/\\{}/\\{1}/\\{q}/{3}" , true , Delimiter { } , printsep , true , "query" , items2 )
2021-09-24 00:45:06 +00:00
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}}" )
2017-01-27 08:46:56 +00:00
2018-03-30 02:47:46 +00:00
// Whitespace preserving flag with "'" delimiter
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {s1}" , true , Delimiter { str : & delim } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.O}}" )
2018-03-30 02:47:46 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {s2}" , true , Delimiter { str : & delim } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}}bar baz{{.O}}" )
2018-03-30 02:47:46 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {s}" , true , Delimiter { str : & delim } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.I}}bar baz{{.O}}" )
2018-03-30 02:47:46 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {s..}" , true , Delimiter { str : & delim } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.I}}bar baz{{.O}}" )
2018-03-30 02:47:46 +00:00
// Whitespace preserving flag with regex delimiter
Improvements to code quality and readability (#1737)
* Remove 1 unused field and 3 unused functions
unused elements fount by running
golangci-lint run --disable-all --enable unused
src/result.go:19:2: field `index` is unused (unused)
index int32
^
src/tui/light.go:716:23: func `(*LightWindow).stderr` is unused (unused)
func (w *LightWindow) stderr(str string) {
^
src/terminal.go:1015:6: func `numLinesMax` is unused (unused)
func numLinesMax(str string, max int) int {
^
src/tui/tui.go:167:20: func `ColorPair.is24` is unused (unused)
func (p ColorPair) is24() bool {
^
* Address warnings from "gosimple" linter
src/options.go:389:83: S1003: should use strings.Contains(str, ",,,") instead (gosimple)
if str == "," || strings.HasPrefix(str, ",,") || strings.HasSuffix(str, ",,") || strings.Index(str, ",,,") >= 0 {
^
src/options.go:630:18: S1007: should use raw string (`...`) with regexp.MustCompile to avoid having to escape twice (gosimple)
executeRegexp = regexp.MustCompile(
^
src/terminal.go:29:16: S1007: should use raw string (`...`) with regexp.MustCompile to avoid having to escape twice (gosimple)
placeholder = regexp.MustCompile("\\\\?(?:{[+sf]*[0-9,-.]*}|{q}|{\\+?f?nf?})")
^
src/terminal_test.go:92:10: S1007: should use raw string (`...`) with regexp.MustCompile to avoid having to escape twice (gosimple)
regex = regexp.MustCompile("\\w+")
^
* Address warnings from "staticcheck" linter
src/algo/algo.go:374:2: SA4006: this value of `offset32` is never used (staticcheck)
offset32, T := alloc32(offset32, slab, N)
^
src/algo/algo.go:456:2: SA4006: this value of `offset16` is never used (staticcheck)
offset16, C := alloc16(offset16, slab, width*M)
^
src/tui/tui.go:119:2: SA9004: only the first constant in this group has an explicit type (staticcheck)
colUndefined Color = -2
^
2019-11-05 00:46:51 +00:00
regex = regexp . MustCompile ( ` \w+ ` )
2018-03-30 02:47:46 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {s1}" , true , Delimiter { regex : regex } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} {{.O}}" )
2018-03-30 02:47:46 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {s2}" , true , Delimiter { regex : regex } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}}{{.I}}{{.O}}" )
2018-03-30 02:47:46 +00:00
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {s3}" , true , Delimiter { regex : regex } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} {{.O}}" )
2018-03-30 02:47:46 +00:00
2017-01-27 08:46:56 +00:00
// No match
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}/{+}" , true , Delimiter { } , printsep , false , "query" , [ ] * Item { nil , nil } )
2017-01-27 08:46:56 +00:00
check ( "echo /" )
// No match, but with selections
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}/{+}" , true , Delimiter { } , printsep , false , "query" , [ ] * Item { nil , item1 } )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo /{{.O}} foo{{.I}}bar baz{{.O}}" )
2017-01-27 08:46:56 +00:00
2016-10-03 05:16:10 +00:00
// String delimiter
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}/{1}/{2}" , true , Delimiter { str : & delim } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}foo{{.O}}/{{.O}}bar baz{{.O}}" )
2016-10-03 05:16:10 +00:00
// Regex delimiter
2018-03-30 02:47:46 +00:00
regex = regexp . MustCompile ( "[oa]+" )
2016-10-03 05:16:10 +00:00
// foo'bar baz
2019-10-27 14:50:12 +00:00
result = replacePlaceholder ( "echo {}/{1}/{3}/{2..3}" , true , Delimiter { regex : regex } , printsep , false , "query" , items1 )
2021-09-24 00:45:06 +00:00
checkFormat ( "echo {{.O}} foo{{.I}}bar baz{{.O}}/{{.O}}f{{.O}}/{{.O}}r b{{.O}}/{{.O}}{{.I}}bar b{{.O}}" )
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
/ *
Test single placeholders , but focus on the placeholders ' parameters ( e . g . flags ) .
see : TestParsePlaceholder
* /
items3 := [ ] * Item {
// single line
newItem ( "1a 1b 1c 1d 1e 1f" ) ,
// multi line
newItem ( "1a 1b 1c 1d 1e 1f" ) ,
newItem ( "2a 2b 2c 2d 2e 2f" ) ,
newItem ( "3a 3b 3c 3d 3e 3f" ) ,
newItem ( "4a 4b 4c 4d 4e 4f" ) ,
newItem ( "5a 5b 5c 5d 5e 5f" ) ,
newItem ( "6a 6b 6c 6d 6e 6f" ) ,
newItem ( "7a 7b 7c 7d 7e 7f" ) ,
}
stripAnsi := false
printsep = "\n"
forcePlus := false
query := "sample query"
templateToOutput := make ( map [ string ] string )
templateToFile := make ( map [ string ] string ) // same as above, but the file contents will be matched
// I. item type placeholder
templateToOutput [ ` { } ` ] = ` {{ .O }} 1a 1b 1c 1d 1e 1f {{ .O }} `
templateToOutput [ ` { +} ` ] = ` {{ .O }} 1a 1b 1c 1d 1e 1f {{ .O }} {{ .O }} 2a 2b 2c 2d 2e 2f {{ .O }} {{ .O }} 3a 3b 3c 3d 3e 3f {{ .O }} {{ .O }} 4a 4b 4c 4d 4e 4f {{ .O }} {{ .O }} 5a 5b 5c 5d 5e 5f {{ .O }} {{ .O }} 6a 6b 6c 6d 6e 6f {{ .O }} {{ .O }} 7a 7b 7c 7d 7e 7f {{ .O }} `
templateToOutput [ ` { n} ` ] = ` 0 `
templateToOutput [ ` { +n} ` ] = ` 0 0 0 0 0 0 0 `
templateToFile [ ` { f} ` ] = ` 1a 1b 1c 1d 1e 1f {{ .S }} `
templateToFile [ ` { +f} ` ] = ` 1a 1b 1c 1d 1e 1f {{ .S }} 2a 2b 2c 2d 2e 2f {{ .S }} 3a 3b 3c 3d 3e 3f {{ .S }} 4a 4b 4c 4d 4e 4f {{ .S }} 5a 5b 5c 5d 5e 5f {{ .S }} 6a 6b 6c 6d 6e 6f {{ .S }} 7a 7b 7c 7d 7e 7f {{ .S }} `
templateToFile [ ` { nf} ` ] = ` 0 {{ .S }} `
templateToFile [ ` { +nf} ` ] = ` 0 {{ .S }} 0 {{ .S }} 0 {{ .S }} 0 {{ .S }} 0 {{ .S }} 0 {{ .S }} 0 {{ .S }} `
// II. token type placeholders
templateToOutput [ ` { ..} ` ] = templateToOutput [ ` { } ` ]
templateToOutput [ ` { 1..} ` ] = templateToOutput [ ` { } ` ]
templateToOutput [ ` { ..2} ` ] = ` {{ .O }} 1a 1b {{ .O }} `
templateToOutput [ ` { 1..2} ` ] = templateToOutput [ ` { ..2} ` ]
templateToOutput [ ` { -2..-1} ` ] = ` {{ .O }} 1e 1f {{ .O }} `
// shorthand for x..x range
templateToOutput [ ` { 1} ` ] = ` {{ .O }} 1a {{ .O }} `
templateToOutput [ ` { 1..1} ` ] = templateToOutput [ ` { 1} ` ]
templateToOutput [ ` { -6} ` ] = templateToOutput [ ` { 1} ` ]
// multiple ranges
templateToOutput [ ` { 1,2} ` ] = templateToOutput [ ` { 1..2} ` ]
templateToOutput [ ` { 1,2,4} ` ] = ` {{ .O }} 1a 1b 1d {{ .O }} `
templateToOutput [ ` { 1,2..4} ` ] = ` {{ .O }} 1a 1b 1c 1d {{ .O }} `
templateToOutput [ ` { 1..2,-4..-3} ` ] = ` {{ .O }} 1a 1b 1c 1d {{ .O }} `
// flags
templateToOutput [ ` { +1} ` ] = ` {{ .O }} 1a {{ .O }} {{ .O }} 2a {{ .O }} {{ .O }} 3a {{ .O }} {{ .O }} 4a {{ .O }} {{ .O }} 5a {{ .O }} {{ .O }} 6a {{ .O }} {{ .O }} 7a {{ .O }} `
templateToOutput [ ` { +-1} ` ] = ` {{ .O }} 1f {{ .O }} {{ .O }} 2f {{ .O }} {{ .O }} 3f {{ .O }} {{ .O }} 4f {{ .O }} {{ .O }} 5f {{ .O }} {{ .O }} 6f {{ .O }} {{ .O }} 7f {{ .O }} `
templateToOutput [ ` { s1} ` ] = ` {{ .O }} 1a {{ .O }} `
templateToFile [ ` { f1} ` ] = ` 1a {{ .S }} `
templateToOutput [ ` { +s1..2} ` ] = ` {{ .O }} 1a 1b {{ .O }} {{ .O }} 2a 2b {{ .O }} {{ .O }} 3a 3b {{ .O }} {{ .O }} 4a 4b {{ .O }} {{ .O }} 5a 5b {{ .O }} {{ .O }} 6a 6b {{ .O }} {{ .O }} 7a 7b {{ .O }} `
templateToFile [ ` { +sf1..2} ` ] = ` 1a 1b {{ .S }} 2a 2b {{ .S }} 3a 3b {{ .S }} 4a 4b {{ .S }} 5a 5b {{ .S }} 6a 6b {{ .S }} 7a 7b {{ .S }} `
// III. query type placeholder
// query flag is not removed after parsing, so it gets doubled
// while the double q is invalid, it is useful here for testing purposes
templateToOutput [ ` { q} ` ] = "{{.O}}" + query + "{{.O}}"
// IV. escaping placeholder
templateToOutput [ ` \ { } ` ] = ` { } `
templateToOutput [ ` \ { ++} ` ] = ` { ++} `
templateToOutput [ ` { ++} ` ] = templateToOutput [ ` { +} ` ]
for giveTemplate , wantOutput := range templateToOutput {
result = replacePlaceholder ( giveTemplate , stripAnsi , Delimiter { } , printsep , forcePlus , query , items3 )
checkFormat ( wantOutput )
}
for giveTemplate , wantOutput := range templateToFile {
path := replacePlaceholder ( giveTemplate , stripAnsi , Delimiter { } , printsep , forcePlus , query , items3 )
data , err := readFile ( path )
if err != nil {
t . Errorf ( "Cannot read the content of the temp file %s." , path )
}
result = string ( data )
checkFormat ( wantOutput )
}
2016-10-03 05:16:10 +00:00
}
2017-10-02 15:36:19 +00:00
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
func TestQuoteEntry ( t * testing . T ) {
type quotes struct { E , O , SQ , DQ , BS string } // standalone escape, outer, single and double quotes, backslash
unixStyle := quotes { ` ` , ` ' ` , ` '\'' ` , ` " ` , ` \ ` }
windowsStyle := quotes { ` ^ ` , ` ^" ` , ` ' ` , ` \^" ` , ` \\ ` }
var effectiveStyle quotes
if util . IsWindows ( ) {
effectiveStyle = windowsStyle
} else {
effectiveStyle = unixStyle
}
2017-10-02 15:36:19 +00:00
tests := map [ string ] string {
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
` ' ` : ` {{ .O }} {{ .SQ }} {{ .O }} ` ,
` " ` : ` {{ .O }} {{ .DQ }} {{ .O }} ` ,
` \ ` : ` {{ .O }} {{ .BS }} {{ .O }} ` ,
` \" ` : ` {{ .O }} {{ .BS }} {{ .DQ }} {{ .O }} ` ,
` "\\\" ` : ` {{ .O }} {{ .DQ }} {{ .BS }} {{ .BS }} {{ .BS }} {{ .DQ }} {{ .O }} ` ,
` $ ` : ` {{ .O }} $ {{ .O }} ` ,
` $HOME ` : ` {{ .O }} $HOME {{ .O }} ` ,
` '$HOME' ` : ` {{ .O }} {{ .SQ }} $HOME {{ .SQ }} {{ .O }} ` ,
` & ` : ` {{ .O }} {{ .E }} & {{ .O }} ` ,
` | ` : ` {{ .O }} {{ .E }} | {{ .O }} ` ,
` < ` : ` {{ .O }} {{ .E }} < {{ .O }} ` ,
` > ` : ` {{ .O }} {{ .E }} > {{ .O }} ` ,
` ( ` : ` {{ .O }} {{ .E }} ( {{ .O }} ` ,
` ) ` : ` {{ .O }} {{ .E }} ) {{ .O }} ` ,
` @ ` : ` {{ .O }} {{ .E }} @ {{ .O }} ` ,
` ^ ` : ` {{ .O }} {{ .E }} ^ {{ .O }} ` ,
` % ` : ` {{ .O }} {{ .E }} % {{ .O }} ` ,
` ! ` : ` {{ .O }} {{ .E }} ! {{ .O }} ` ,
` %USERPROFILE% ` : ` {{ .O }} {{ .E }} %USERPROFILE {{ .E }} % {{ .O }} ` ,
` C:\Program Files (x86)\ ` : ` {{ .O }} C: {{ .BS }} Program Files {{ .E }} (x86 {{ .E }} ) {{ .BS }} {{ .O }} ` ,
` "C:\Program Files" ` : ` {{ .O }} {{ .DQ }} C: {{ .BS }} Program Files {{ .DQ }} {{ .O }} ` ,
2017-10-02 15:36:19 +00:00
}
for input , expected := range tests {
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
escaped := quoteEntry ( input )
expected = templateToString ( expected , effectiveStyle )
2017-10-02 15:36:19 +00:00
if escaped != expected {
t . Errorf ( "Input: %s, expected: %s, actual %s" , input , expected , escaped )
}
}
}
2021-09-24 00:45:06 +00:00
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
// purpose of this test is to demonstrate some shortcomings of fzf's templating system on Unix
func TestUnixCommands ( t * testing . T ) {
if util . IsWindows ( ) {
t . SkipNow ( )
}
tests := [ ] testCase {
// reference: give{template, query, items}, want{output OR match}
// 1) working examples
// paths that does not have to evaluated will work fine, when quoted
{ give { ` grep foo { } ` , ` ` , newItems ( ` test ` ) } , want { output : ` grep foo 'test' ` } } ,
{ give { ` grep foo { } ` , ` ` , newItems ( ` /home/user/test ` ) } , want { output : ` grep foo '/home/user/test' ` } } ,
{ give { ` grep foo { } ` , ` ` , newItems ( ` ./test ` ) } , want { output : ` grep foo './test' ` } } ,
// only placeholders are escaped as data, this will lookup tilde character in a test file in your home directory
// quoting the tilde is required (to be treated as string)
{ give { ` grep { } ~/test ` , ` ` , newItems ( ` ~ ` ) } , want { output : ` grep '~' ~/test ` } } ,
// 2) problematic examples
2021-10-27 19:47:01 +00:00
// (not necessarily unexpected)
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
// paths that need to expand some part of it won't work (special characters and variables)
{ give { ` cat { } ` , ` ` , newItems ( ` ~/test ` ) } , want { output : ` cat '~/test' ` } } ,
{ give { ` cat { } ` , ` ` , newItems ( ` $HOME/test ` ) } , want { output : ` cat '$HOME/test' ` } } ,
}
testCommands ( t , tests )
}
// purpose of this test is to demonstrate some shortcomings of fzf's templating system on Windows
func TestWindowsCommands ( t * testing . T ) {
if ! util . IsWindows ( ) {
t . SkipNow ( )
}
tests := [ ] testCase {
// reference: give{template, query, items}, want{output OR match}
// 1) working examples
// example of redundantly escaped backslash in the output, besides looking bit ugly, it won't cause any issue
{ give { ` type { } ` , ` ` , newItems ( ` C:\test.txt ` ) } , want { output : ` type ^"C:\\test.txt^" ` } } ,
{ give { ` rg -- "package" { } ` , ` ` , newItems ( ` .\test.go ` ) } , want { output : ` rg -- "package" ^".\\test.go^" ` } } ,
// example of mandatorily escaped backslash in the output, otherwise `rg -- "C:\test.txt"` is matching for tabulator
{ give { ` rg -- { } ` , ` ` , newItems ( ` C:\test.txt ` ) } , want { output : ` rg -- ^"C:\\test.txt^" ` } } ,
// example of mandatorily escaped double quote in the output, otherwise `rg -- ""C:\\test.txt""` is not matching for the double quotes around the path
{ give { ` rg -- { } ` , ` ` , newItems ( ` "C:\test.txt" ` ) } , want { output : ` rg -- ^"\^"C:\\test.txt\^"^" ` } } ,
// 2) problematic examples
2021-10-27 19:47:01 +00:00
// (not necessarily unexpected)
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
// notepad++'s parser can't handle `-n"12"` generate by fzf, expects `-n12`
{ give { ` notepad++ -n { 1} { 2} ` , ` ` , newItems ( ` 12 C:\Work\Test Folder\File.txt ` ) } , want { output : ` notepad++ -n^"12^" ^"C:\\Work\\Test Folder\\File.txt^" ` } } ,
// cat is parsing `\"` as a part of the file path, double quote is illegal character for paths on Windows
// cat: "C:\\test.txt: Invalid argument
{ give { ` cat { } ` , ` ` , newItems ( ` "C:\test.txt" ` ) } , want { output : ` cat ^"\^"C:\\test.txt\^"^" ` } } ,
// cat: "C:\\test.txt": Invalid argument
{ give { ` cmd /c { } ` , ` ` , newItems ( ` cat "C:\test.txt" ` ) } , want { output : ` cmd /c ^"cat \^"C:\\test.txt\^"^" ` } } ,
// the "file" flag in the pattern won't create *.bat or *.cmd file so the command in the output tries to edit the file, instead of executing it
// the temp file contains: `cat "C:\test.txt"`
2021-10-27 19:47:01 +00:00
// TODO this should actually work
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
{ give { ` cmd /c { f} ` , ` ` , newItems ( ` cat "C:\test.txt" ` ) } , want { match : ` ^cmd /c .*\fzf-preview-[0-9] { 9}$ ` } } ,
}
testCommands ( t , tests )
}
2021-10-27 19:47:01 +00:00
// purpose of this test is to demonstrate some shortcomings of fzf's templating system on Windows in Powershell
func TestPowershellCommands ( t * testing . T ) {
if ! util . IsWindows ( ) {
t . SkipNow ( )
}
tests := [ ] testCase {
// reference: give{template, query, items}, want{output OR match}
2021-11-01 19:59:57 +00:00
/ *
You can read each line in the following table as a pipeline that
consist of series of parsers that act upon your input ( col . 1 ) and
each cell represents the output value .
For example :
- exec . Command ( "program.exe" , ` \'' ` )
- goes to win32 api which will process it transparently as it contains no special characters , see [ CommandLineToArgvW ] [ ] .
- powershell command will receive it as is , that is two arguments : a literal backslash and empty string in single quotes
- native command run via / from powershell will receive only one argument : a literal backslash . Because extra parsing rules apply , see [ NativeCallsFromPowershell ] [ ] .
- some ¹ apps have internal parser , that requires one more level of escaping ( yes , this is completely application - specific , but see terminal_test . go # TestWindowsCommands )
Character ⁰ CommandLineToArgvW Powershell commands Native commands from Powershell Apps requiring escapes ¹ | Being tested below
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - -- -- -- -- -- -- -- -- -- -- -- -- -- | -- -- -- -- -- -- -- -- --
" empty string ² missing argument error ... ... |
\ " literal " unbalanced quote error ... ... |
'\"' literal '"' literal " empty string empty string ( match all ) | yes
' \ \ \ "' literal '\"' literal \" literal " literal " |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - -- -- -- -- -- -- -- -- -- -- -- -- -- | -- -- -- -- -- -- -- -- --
\ transparent transparent transparent regex error |
' \ ' transparent literal \ literal \ regex error | yes
\ \ transparent transparent transparent literal \ |
'\\' transparent literal \ \ literal \ \ literal \ |
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - -- -- -- -- -- -- -- -- -- -- -- -- -- | -- -- -- -- -- -- -- -- --
' transparent unbalanced quote error ... ... |
\ ' transparent literal \ and unb . quote error ... ... |
\ ' ' transparent literal \ and empty string literal \ regex error | no , but given as example above
''' transparent unbalanced quote error ... ... |
''' ' transparent literal ' literal ' literal ' | yes
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - -- -- -- -- -- -- -- -- -- -- -- -- -- | -- -- -- -- -- -- -- -- --
⁰ : charatecter or characters 'x' as an argument to a program in go ' s call : exec . Command ( "program.exe" , ` x ` )
¹ : native commands like grep , git grep , ripgrep
² : interpreted as a grouping quote , affects argument parser and gets removed from the result
[ CommandLineToArgvW ] : https : //docs.microsoft.com/en-gb/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw#remarks
[ NativeCallsFromPowershell ] : https : //docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing?view=powershell-7.1#passing-arguments-that-contain-quote-characters
* /
2021-10-27 19:47:01 +00:00
// 1) working examples
{ give { ` Get-Content { } ` , ` ` , newItems ( ` C:\test.txt ` ) } , want { output : ` Get-Content 'C:\test.txt' ` } } ,
{ give { ` rg -- "package" { } ` , ` ` , newItems ( ` .\test.go ` ) } , want { output : ` rg -- "package" '.\test.go' ` } } ,
// example of escaping single quotes
{ give { ` rg -- { } ` , ` ` , newItems ( ` 'foobar' ` ) } , want { output : ` rg -- '''foobar''' ` } } ,
// chaining powershells
{ give { ` powershell -NoProfile -Command { } ` , ` ` , newItems ( ` cat "C:\test.txt" ` ) } , want { output : ` powershell -NoProfile -Command 'cat \"C:\test.txt\"' ` } } ,
// 2) problematic examples
// (not necessarily unexpected)
// looking for a path string will only work with escaped backslashes
{ give { ` rg -- { } ` , ` ` , newItems ( ` C:\test.txt ` ) } , want { output : ` rg -- 'C:\test.txt' ` } } ,
// looking for a literal double quote will only work with triple escaped double quotes
{ give { ` rg -- { } ` , ` ` , newItems ( ` "C:\test.txt" ` ) } , want { output : ` rg -- '\"C:\test.txt\"' ` } } ,
// Get-Content (i.e. cat alias) is parsing `"` as a part of the file path, returns an error:
// Get-Content : Cannot find drive. A drive with the name '"C:' does not exist.
{ give { ` cat { } ` , ` ` , newItems ( ` "C:\test.txt" ` ) } , want { output : ` cat '\"C:\test.txt\"' ` } } ,
// the "file" flag in the pattern won't create *.ps1 file so the powershell will offload this "unknown" filetype
// to explorer, which will prompt user to pick editing program for the fzf-preview file
// the temp file contains: `cat "C:\test.txt"`
// TODO this should actually work
{ give { ` powershell -NoProfile -Command { f} ` , ` ` , newItems ( ` cat "C:\test.txt" ` ) } , want { match : ` ^powershell -NoProfile -Command .*\fzf-preview-[0-9] { 9}$ ` } } ,
}
// to force powershell-style escaping we temporarily set environment variable that fzf honors
shellBackup := os . Getenv ( "SHELL" )
os . Setenv ( "SHELL" , "powershell" )
testCommands ( t , tests )
os . Setenv ( "SHELL" , shellBackup )
}
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
/ *
2022-08-12 13:11:15 +00:00
Test typical valid placeholders and parsing of them .
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
2022-08-12 13:11:15 +00:00
Also since the parser assumes the input is matched with ` placeholder ` regex ,
the regex is tested here as well .
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
* /
func TestParsePlaceholder ( t * testing . T ) {
// give, want pairs
templates := map [ string ] string {
// I. item type placeholder
` { } ` : ` { } ` ,
` { +} ` : ` { +} ` ,
` { n} ` : ` { n} ` ,
` { +n} ` : ` { +n} ` ,
` { f} ` : ` { f} ` ,
` { +nf} ` : ` { +nf} ` ,
// II. token type placeholders
` { ..} ` : ` { ..} ` ,
` { 1..} ` : ` { 1..} ` ,
` { ..2} ` : ` { ..2} ` ,
` { 1..2} ` : ` { 1..2} ` ,
` { -2..-1} ` : ` { -2..-1} ` ,
// shorthand for x..x range
` { 1} ` : ` { 1} ` ,
` { 1..1} ` : ` { 1..1} ` ,
` { -6} ` : ` { -6} ` ,
// multiple ranges
` { 1,2} ` : ` { 1,2} ` ,
` { 1,2,4} ` : ` { 1,2,4} ` ,
` { 1,2..4} ` : ` { 1,2..4} ` ,
` { 1..2,-4..-3} ` : ` { 1..2,-4..-3} ` ,
// flags
` { +1} ` : ` { +1} ` ,
` { +-1} ` : ` { +-1} ` ,
` { s1} ` : ` { s1} ` ,
` { f1} ` : ` { f1} ` ,
` { +s1..2} ` : ` { +s1..2} ` ,
` { +sf1..2} ` : ` { +sf1..2} ` ,
// III. query type placeholder
// query flag is not removed after parsing, so it gets doubled
// while the double q is invalid, it is useful here for testing purposes
` { q} ` : ` { qq} ` ,
// IV. escaping placeholder
` \ { } ` : ` { } ` ,
` \ { ++} ` : ` { ++} ` ,
` { ++} ` : ` { +} ` ,
}
for giveTemplate , wantTemplate := range templates {
if ! placeholder . MatchString ( giveTemplate ) {
t . Errorf ( ` given placeholder %s does not match placeholder regex, so attempt to parse it is unexpected ` , giveTemplate )
continue
}
_ , placeholderWithoutFlags , flags := parsePlaceholder ( giveTemplate )
gotTemplate := placeholderWithoutFlags [ : 1 ] + flags . encodePlaceholder ( ) + placeholderWithoutFlags [ 1 : ]
if gotTemplate != wantTemplate {
t . Errorf ( ` parsed placeholder "%s" into "%s", but want "%s" ` , giveTemplate , gotTemplate , wantTemplate )
}
}
}
/* utilities section */
// Item represents one line in fzf UI. Usually it is relative path to files and folders.
func newItem ( str string ) * Item {
bytes := [ ] byte ( str )
trimmed , _ , _ := extractColor ( str , nil , nil )
return & Item { origText : & bytes , text : util . ToChars ( [ ] byte ( trimmed ) ) }
}
// Functions tested in this file require array of items (allItems). The array needs
// to consist of at least two nils. This is helper function.
func newItems ( str ... string ) [ ] * Item {
result := make ( [ ] * Item , util . Max ( len ( str ) , 2 ) )
for i , s := range str {
result [ i ] = newItem ( s )
}
return result
}
// (for logging purposes)
func ( item * Item ) String ( ) string {
return item . AsString ( true )
}
2021-09-24 00:45:06 +00:00
// Helper function to parse, execute and convert "text/template" to string. Panics on error.
func templateToString ( format string , data interface { } ) string {
bb := & bytes . Buffer { }
err := template . Must ( template . New ( "" ) . Parse ( format ) ) . Execute ( bb , data )
if err != nil {
panic ( err )
}
return bb . String ( )
}
Add more tests of placeholder flags and simplify its logic (#2624)
* [tests] Test fzf's placeholders and escaping on practical commands
This tests some reasonable commands in fzf's templates (for commands,
previews, rebinds etc.), how are those commands escaped (backslashes,
double quotes), and documents if the output is executable in cmd.exe.
Both on Unix and Windows.
* [tests] Add testing of placeholder parsing and matching
Adds tests and bit of docs for the curly brackets placeholders in fzf's
template strings. Also tests the "placeholder" regex.
* [tests] Add more test cases of replacing placeholders focused on flags
Replacing placeholders in templates is already tested, this adds tests
that focus more on the parameters of placeholders - e.g. flags, token
ranges.
There is at least one test for each flag, not all combinations are
tested though.
* [refactoring] Split OS-specific function quoteEntry() to corresponding source file
This is minor refactoring, and also the function's test was made
crossplatform.
* [refactoring] Simplify replacePlaceholder function
Should be equivalent to the original, but has simpler structure.
2021-10-15 13:31:59 +00:00
// ad hoc types for test cases
type give struct {
template string
query string
allItems [ ] * Item
}
type want struct {
/ *
Unix :
The ` want.output ` string is supposed to be formatted for evaluation by
` sh -c command ` system call .
Windows :
The ` want.output ` string is supposed to be formatted for evaluation by
` cmd.exe /s /c "command" ` system call . The ` /s ` switch enables so called old
behaviour , which is more favourable for nesting ( possibly escaped )
special characters . This is the relevant section of ` help cmd ` :
... old behavior is to see if the first character is
a quote character and if so , strip the leading character and
remove the last quote character on the command line , preserving
any text after the last quote character .
* /
output string // literal output
match string // output is matched against this regex (when output is empty string)
}
type testCase struct {
give
want
}
func testCommands ( t * testing . T , tests [ ] testCase ) {
// common test parameters
delim := "\t"
delimiter := Delimiter { str : & delim }
printsep := ""
stripAnsi := false
forcePlus := false
// evaluate the test cases
for idx , test := range tests {
gotOutput := replacePlaceholder (
test . give . template , stripAnsi , delimiter , printsep , forcePlus ,
test . give . query ,
test . give . allItems )
switch {
case test . want . output != "" :
if gotOutput != test . want . output {
t . Errorf ( "tests[%v]:\ngave{\n\ttemplate: '%s',\n\tquery: '%s',\n\tallItems: %s}\nand got '%s',\nbut want '%s'" ,
idx ,
test . give . template , test . give . query , test . give . allItems ,
gotOutput , test . want . output )
}
case test . want . match != "" :
wantMatch := strings . ReplaceAll ( test . want . match , ` \ ` , ` \\ ` )
wantRegex := regexp . MustCompile ( wantMatch )
if ! wantRegex . MatchString ( gotOutput ) {
t . Errorf ( "tests[%v]:\ngave{\n\ttemplate: '%s',\n\tquery: '%s',\n\tallItems: %s}\nand got '%s',\nbut want '%s'" ,
idx ,
test . give . template , test . give . query , test . give . allItems ,
gotOutput , test . want . match )
}
default :
t . Errorf ( "tests[%v]: test case does not describe 'want' property" , idx )
}
}
}
// naive encoder of placeholder flags
func ( flags placeholderFlags ) encodePlaceholder ( ) string {
encoded := ""
if flags . plus {
encoded += "+"
}
if flags . preserveSpace {
encoded += "s"
}
if flags . number {
encoded += "n"
}
if flags . file {
encoded += "f"
}
if flags . query {
encoded += "q"
}
return encoded
}
// can be replaced with os.ReadFile() in go 1.16+
func readFile ( path string ) ( [ ] byte , error ) {
file , err := os . Open ( path )
if err != nil {
return nil , err
}
defer file . Close ( )
data := make ( [ ] byte , 0 , 128 )
for {
if len ( data ) >= cap ( data ) {
d := append ( data [ : cap ( data ) ] , 0 )
data = d [ : len ( data ) ]
}
n , err := file . Read ( data [ len ( data ) : cap ( data ) ] )
data = data [ : len ( data ) + n ]
if err != nil {
if err == io . EOF {
err = nil
}
return data , err
}
}
}