Skip to content

Commit 31fd207

Browse files
committed
Add 'r' flag (raw) for unquoted output
By default, placeholder expressions are automatically quoted to ensure they are safely passed as arguments to external programs. The r flag ({r}, {r1}, etc.) disables this behavior, outputting the evaluated value without quotes. For example, echo 'foo bar' | fzf --preview 'echo {} {r}' The preview command becomes: echo 'foo bar' foo bar Since `{r}` expands to unquoted "foo bar", 'foo' and 'bar' are passed as separate arguments. **Use with caution** Unquoted output can lead to broken commands. echo "let's go" | fzf --preview 'echo {r}' Close #4330
1 parent ba6d1b8 commit 31fd207

File tree

3 files changed

+21
-4
lines changed

3 files changed

+21
-4
lines changed

man/man1/fzf.1

+6
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,12 @@ e.g.
768768
\fBfzf \-\-multi \-\-preview='head \-10 {+}'
769769
git log \-\-oneline | fzf \-\-multi \-\-preview 'git show {+1}'\fR
770770

771+
Each expression expands to a quoted string, so that it's safe to pass it as an
772+
argument to an external command. So you should not manually add quotes around
773+
the curly braces. But if you don't want this behavior, you can put
774+
\fBr\fR flag (raw) in the expression (e.g. \fB{r}\fR, \fB{r1}\fR, etc).
775+
Use it with caution as unquoted output can lead to broken commands.
776+
771777
When using a field index expression, leading and trailing whitespace is stripped
772778
from the replacement string. To preserve the whitespace, use the \fBs\fR flag.
773779

src/terminal.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ As such it is not useful for validation, but rather to generate test
3838
cases for example.
3939
4040
\\?(?: # escaped type
41-
{\+?s?f?RANGE(?:,RANGE)*} # token type
41+
{\+?s?f?r?RANGE(?:,RANGE)*} # token type
4242
{q[:s?RANGE]} # query type
4343
|{\+?n?f?} # item type (notice no mandatory element inside brackets)
4444
)
@@ -65,7 +65,7 @@ const maxFocusEvents = 10000
6565
const blockDuration = 1 * time.Second
6666

6767
func init() {
68-
placeholder = regexp.MustCompile(`\\?(?:{[+sf]*[0-9,-.]*}|{q(?::s?[0-9,-.]+)?}|{fzf:(?:query|action|prompt)}|{\+?f?nf?})`)
68+
placeholder = regexp.MustCompile(`\\?(?:{[+sfr]*[0-9,-.]*}|{q(?::s?[0-9,-.]+)?}|{fzf:(?:query|action|prompt)}|{\+?f?nf?})`)
6969
whiteSuffix = regexp.MustCompile(`\s*$`)
7070
offsetComponentRegex = regexp.MustCompile(`([+-][0-9]+)|(-?/[1-9][0-9]*)`)
7171
offsetTrimCharsRegex = regexp.MustCompile(`[^0-9/+-]`)
@@ -628,6 +628,7 @@ type placeholderFlags struct {
628628
number bool
629629
forceUpdate bool
630630
file bool
631+
raw bool
631632
}
632633

633634
type searchRequest struct {
@@ -3782,6 +3783,8 @@ func parsePlaceholder(match string) (bool, string, placeholderFlags) {
37823783
flags.number = true
37833784
case 'f':
37843785
flags.file = true
3786+
case 'r':
3787+
flags.raw = true
37853788
case 'q':
37863789
flags.forceUpdate = true
37873790
trimmed += string(char)
@@ -3933,7 +3936,7 @@ func replacePlaceholder(params replacePlaceholderParams) (string, []string) {
39333936
return "''"
39343937
}
39353938
return strconv.Itoa(int(n))
3936-
case flags.file:
3939+
case flags.file || flags.raw:
39373940
return item.AsString(params.stripAnsi)
39383941
default:
39393942
return params.executor.QuoteEntry(item.AsString(params.stripAnsi))
@@ -3975,7 +3978,7 @@ func replacePlaceholder(params replacePlaceholderParams) (string, []string) {
39753978
if !flags.preserveSpace {
39763979
str = strings.TrimSpace(str)
39773980
}
3978-
if !flags.file {
3981+
if !flags.file && !flags.raw {
39793982
str = params.executor.QuoteEntry(str)
39803983
}
39813984
return str

src/terminal_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ func TestReplacePlaceholder(t *testing.T) {
7575
result = replacePlaceholderTest("echo {}", true, Delimiter{}, printsep, false, "query", items1)
7676
checkFormat("echo {{.O}} foo{{.I}}bar baz{{.O}}")
7777

78+
// {r}, strip ansi
79+
result = replacePlaceholderTest("echo {r}", true, Delimiter{}, printsep, false, "query", items1)
80+
checkFormat("echo foo'bar baz")
81+
82+
// {r..}, strip ansi
83+
result = replacePlaceholderTest("echo {r..}", true, Delimiter{}, printsep, false, "query", items1)
84+
checkFormat("echo foo'bar baz")
85+
7886
// {}, with multiple items
7987
result = replacePlaceholderTest("echo {}", true, Delimiter{}, printsep, false, "query", items2)
8088
checkFormat("echo {{.O}}foo{{.I}}bar baz{{.O}}")

0 commit comments

Comments
 (0)