Add 'f' flag for placeholder expression (#1733)

If present the contents of the selection will be placed in a temporary file,
and the filename will be placed into the string instead.
This commit is contained in:
Simon Fraser
2019-10-27 14:50:12 +00:00
committed by Junegunn Choi
parent 0c6c76e081
commit 391669a451
4 changed files with 84 additions and 29 deletions

View File

@@ -5,6 +5,7 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/signal"
"regexp"
@@ -22,9 +23,11 @@ import (
// import "github.com/pkg/profile"
var placeholder *regexp.Regexp
var activeTempFiles []string
func init() {
placeholder = regexp.MustCompile("\\\\?(?:{[+s]*[0-9,-.]*}|{q}|{\\+?n})")
placeholder = regexp.MustCompile("\\\\?(?:{[+sf]*[0-9,-.]*}|{q}|{\\+?f?nf?})")
activeTempFiles = []string{}
}
type jumpMode int
@@ -103,6 +106,7 @@ type Terminal struct {
jumping jumpMode
jumpLabels string
printer func(string)
printsep string
merger *Merger
selected map[int32]selectedItem
version int64
@@ -231,6 +235,7 @@ type placeholderFlags struct {
preserveSpace bool
number bool
query bool
file bool
}
func toActions(types ...actionType) []action {
@@ -407,6 +412,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
jumping: jumpDisabled,
jumpLabels: opts.JumpLabels,
printer: opts.Printer,
printsep: opts.PrintSep,
merger: EmptyMerger,
selected: make(map[int32]selectedItem),
reqBox: util.NewEventBox(),
@@ -1207,6 +1213,9 @@ func parsePlaceholder(match string) (bool, string, placeholderFlags) {
case 'n':
flags.number = true
skipChars++
case 'f':
flags.file = true
skipChars++
case 'q':
flags.query = true
default:
@@ -1232,7 +1241,27 @@ func hasPreviewFlags(template string) (plus bool, query bool) {
return
}
func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, forcePlus bool, query string, allItems []*Item) string {
func writeTemporaryFile(data []string, printSep string) string {
f, err := ioutil.TempFile("", "fzf-preview-*")
if err != nil {
errorExit("Unable to create temporary file")
}
defer f.Close()
f.WriteString(strings.Join(data, printSep))
f.WriteString(printSep)
activeTempFiles = append(activeTempFiles, f.Name())
return f.Name()
}
func cleanTemporaryFiles() {
for _, filename := range activeTempFiles {
os.Remove(filename)
}
activeTempFiles = []string{}
}
func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, printsep string, forcePlus bool, query string, allItems []*Item) string {
current := allItems[:1]
selected := allItems[1:]
if current[0] == nil {
@@ -1269,10 +1298,15 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, fo
} else {
replacements[idx] = strconv.Itoa(n)
}
} else if flags.file {
replacements[idx] = item.AsString(stripAnsi)
} else {
replacements[idx] = quoteEntry(item.AsString(stripAnsi))
}
}
if flags.file {
return writeTemporaryFile(replacements, printsep)
}
return strings.Join(replacements, " ")
}
@@ -1302,7 +1336,13 @@ func replacePlaceholder(template string, stripAnsi bool, delimiter Delimiter, fo
if !flags.preserveSpace {
str = strings.TrimSpace(str)
}
replacements[idx] = quoteEntry(str)
if !flags.file {
str = quoteEntry(str)
}
replacements[idx] = str
}
if flags.file {
return writeTemporaryFile(replacements, printsep)
}
return strings.Join(replacements, " ")
})
@@ -1319,7 +1359,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
if !valid {
return
}
command := replacePlaceholder(template, t.ansi, t.delimiter, forcePlus, string(t.input), list)
command := replacePlaceholder(template, t.ansi, t.delimiter, t.printsep, forcePlus, string(t.input), list)
cmd := util.ExecCommand(command, false)
if !background {
cmd.Stdin = os.Stdin
@@ -1335,6 +1375,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
cmd.Run()
t.tui.Resume(false)
}
cleanTemporaryFiles()
}
func (t *Terminal) hasPreviewer() bool {
@@ -1492,7 +1533,7 @@ func (t *Terminal) Loop() {
// We don't display preview window if no match
if request[0] != nil {
command := replacePlaceholder(t.preview.command,
t.ansi, t.delimiter, false, string(t.input), request)
t.ansi, t.delimiter, t.printsep, false, string(t.input), request)
cmd := util.ExecCommand(command, true)
if t.pwindow != nil {
env := os.Environ()
@@ -1534,6 +1575,7 @@ func (t *Terminal) Loop() {
if out.Len() > 0 || !<-updateChan {
t.reqBox.Set(reqPreviewDisplay, out.String())
}
cleanTemporaryFiles()
} else {
t.reqBox.Set(reqPreviewDisplay, "")
}