mirror of
https://github.com/junegunn/fzf.git
synced 2025-05-19 12:50:22 -07:00
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
This commit is contained in:
parent
ba6d1b8772
commit
31fd207ba2
@ -768,6 +768,12 @@ e.g.
|
|||||||
\fBfzf \-\-multi \-\-preview='head \-10 {+}'
|
\fBfzf \-\-multi \-\-preview='head \-10 {+}'
|
||||||
git log \-\-oneline | fzf \-\-multi \-\-preview 'git show {+1}'\fR
|
git log \-\-oneline | fzf \-\-multi \-\-preview 'git show {+1}'\fR
|
||||||
|
|
||||||
|
Each expression expands to a quoted string, so that it's safe to pass it as an
|
||||||
|
argument to an external command. So you should not manually add quotes around
|
||||||
|
the curly braces. But if you don't want this behavior, you can put
|
||||||
|
\fBr\fR flag (raw) in the expression (e.g. \fB{r}\fR, \fB{r1}\fR, etc).
|
||||||
|
Use it with caution as unquoted output can lead to broken commands.
|
||||||
|
|
||||||
When using a field index expression, leading and trailing whitespace is stripped
|
When using a field index expression, leading and trailing whitespace is stripped
|
||||||
from the replacement string. To preserve the whitespace, use the \fBs\fR flag.
|
from the replacement string. To preserve the whitespace, use the \fBs\fR flag.
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ As such it is not useful for validation, but rather to generate test
|
|||||||
cases for example.
|
cases for example.
|
||||||
|
|
||||||
\\?(?: # escaped type
|
\\?(?: # escaped type
|
||||||
{\+?s?f?RANGE(?:,RANGE)*} # token type
|
{\+?s?f?r?RANGE(?:,RANGE)*} # token type
|
||||||
{q[:s?RANGE]} # query type
|
{q[:s?RANGE]} # query type
|
||||||
|{\+?n?f?} # item type (notice no mandatory element inside brackets)
|
|{\+?n?f?} # item type (notice no mandatory element inside brackets)
|
||||||
)
|
)
|
||||||
@ -65,7 +65,7 @@ const maxFocusEvents = 10000
|
|||||||
const blockDuration = 1 * time.Second
|
const blockDuration = 1 * time.Second
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
placeholder = regexp.MustCompile(`\\?(?:{[+sf]*[0-9,-.]*}|{q(?::s?[0-9,-.]+)?}|{fzf:(?:query|action|prompt)}|{\+?f?nf?})`)
|
placeholder = regexp.MustCompile(`\\?(?:{[+sfr]*[0-9,-.]*}|{q(?::s?[0-9,-.]+)?}|{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/+-]`)
|
||||||
@ -628,6 +628,7 @@ type placeholderFlags struct {
|
|||||||
number bool
|
number bool
|
||||||
forceUpdate bool
|
forceUpdate bool
|
||||||
file bool
|
file bool
|
||||||
|
raw bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type searchRequest struct {
|
type searchRequest struct {
|
||||||
@ -3782,6 +3783,8 @@ func parsePlaceholder(match string) (bool, string, placeholderFlags) {
|
|||||||
flags.number = true
|
flags.number = true
|
||||||
case 'f':
|
case 'f':
|
||||||
flags.file = true
|
flags.file = true
|
||||||
|
case 'r':
|
||||||
|
flags.raw = true
|
||||||
case 'q':
|
case 'q':
|
||||||
flags.forceUpdate = true
|
flags.forceUpdate = true
|
||||||
trimmed += string(char)
|
trimmed += string(char)
|
||||||
@ -3933,7 +3936,7 @@ func replacePlaceholder(params replacePlaceholderParams) (string, []string) {
|
|||||||
return "''"
|
return "''"
|
||||||
}
|
}
|
||||||
return strconv.Itoa(int(n))
|
return strconv.Itoa(int(n))
|
||||||
case flags.file:
|
case flags.file || flags.raw:
|
||||||
return item.AsString(params.stripAnsi)
|
return item.AsString(params.stripAnsi)
|
||||||
default:
|
default:
|
||||||
return params.executor.QuoteEntry(item.AsString(params.stripAnsi))
|
return params.executor.QuoteEntry(item.AsString(params.stripAnsi))
|
||||||
@ -3975,7 +3978,7 @@ func replacePlaceholder(params replacePlaceholderParams) (string, []string) {
|
|||||||
if !flags.preserveSpace {
|
if !flags.preserveSpace {
|
||||||
str = strings.TrimSpace(str)
|
str = strings.TrimSpace(str)
|
||||||
}
|
}
|
||||||
if !flags.file {
|
if !flags.file && !flags.raw {
|
||||||
str = params.executor.QuoteEntry(str)
|
str = params.executor.QuoteEntry(str)
|
||||||
}
|
}
|
||||||
return str
|
return str
|
||||||
|
@ -75,6 +75,14 @@ func TestReplacePlaceholder(t *testing.T) {
|
|||||||
result = replacePlaceholderTest("echo {}", true, Delimiter{}, printsep, false, "query", items1)
|
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}}")
|
||||||
|
|
||||||
|
// {r}, strip ansi
|
||||||
|
result = replacePlaceholderTest("echo {r}", true, Delimiter{}, printsep, false, "query", items1)
|
||||||
|
checkFormat("echo foo'bar baz")
|
||||||
|
|
||||||
|
// {r..}, strip ansi
|
||||||
|
result = replacePlaceholderTest("echo {r..}", true, Delimiter{}, printsep, false, "query", items1)
|
||||||
|
checkFormat("echo foo'bar baz")
|
||||||
|
|
||||||
// {}, with multiple items
|
// {}, with multiple items
|
||||||
result = replacePlaceholderTest("echo {}", true, Delimiter{}, printsep, false, "query", items2)
|
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}}")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user