diff options
| author | Junegunn Choi <junegunn.c@gmail.com> | 2015-11-09 01:42:01 +0900 |
|---|---|---|
| committer | Junegunn Choi <junegunn.c@gmail.com> | 2015-11-09 23:58:19 +0900 |
| commit | a89d8995c3a4544851ae3a40b8fb1f1c16f9535e (patch) | |
| tree | 25476566395e829d77b458078743b535d8ebe5b0 /src | |
| parent | dbc854d5f470d6a995401b3e6386687e7663cddd (diff) | |
| download | fzf-a89d8995c3a4544851ae3a40b8fb1f1c16f9535e.tar.gz | |
Add execute-multi action
Close #413
Diffstat (limited to 'src')
| -rw-r--r-- | src/options.go | 32 | ||||
| -rw-r--r-- | src/terminal.go | 37 |
2 files changed, 52 insertions, 17 deletions
diff --git a/src/options.go b/src/options.go index 42b27f34..d1f82014 100644 --- a/src/options.go +++ b/src/options.go @@ -466,10 +466,13 @@ func parseKeymap(keymap map[int]actionType, execmap map[int]string, toggleSort b // Backreferences are not supported. // "~!@#$%^&*;/|".each_char.map { |c| Regexp.escape(c) }.map { |c| "#{c}[^#{c}]*#{c}" }.join('|') executeRegexp = regexp.MustCompile( - "(?s):execute:.*|:execute(\\([^)]*\\)|\\[[^\\]]*\\]|~[^~]*~|![^!]*!|@[^@]*@|\\#[^\\#]*\\#|\\$[^\\$]*\\$|%[^%]*%|\\^[^\\^]*\\^|&[^&]*&|\\*[^\\*]*\\*|;[^;]*;|/[^/]*/|\\|[^\\|]*\\|)") + "(?s):execute(-multi)?:.*|:execute(-multi)?(\\([^)]*\\)|\\[[^\\]]*\\]|~[^~]*~|![^!]*!|@[^@]*@|\\#[^\\#]*\\#|\\$[^\\$]*\\$|%[^%]*%|\\^[^\\^]*\\^|&[^&]*&|\\*[^\\*]*\\*|;[^;]*;|/[^/]*/|\\|[^\\|]*\\|)") } masked := executeRegexp.ReplaceAllStringFunc(str, func(src string) string { - return ":execute(" + strings.Repeat(" ", len(src)-10) + ")" + if strings.HasPrefix(src, ":execute-multi") { + return ":execute-multi(" + strings.Repeat(" ", len(src)-len(":execute-multi()")) + ")" + } + return ":execute(" + strings.Repeat(" ", len(src)-len(":execute()")) + ")" }) masked = strings.Replace(masked, "::", string([]rune{escapedColon, ':'}), -1) masked = strings.Replace(masked, ",:", string([]rune{escapedComma, ':'}), -1) @@ -565,11 +568,18 @@ func parseKeymap(keymap map[int]actionType, execmap map[int]string, toggleSort b toggleSort = true default: if isExecuteAction(actLower) { - keymap[key] = actExecute - if act[7] == ':' { - execmap[key] = act[8:] + var offset int + if strings.HasPrefix(actLower, "execute-multi") { + keymap[key] = actExecuteMulti + offset = len("execute-multi") + } else { + keymap[key] = actExecute + offset = len("execute") + } + if act[offset] == ':' { + execmap[key] = act[offset+1:] } else { - execmap[key] = act[8 : len(act)-1] + execmap[key] = act[offset+1 : len(act)-1] } } else { errorExit("unknown action: " + act) @@ -580,10 +590,16 @@ func parseKeymap(keymap map[int]actionType, execmap map[int]string, toggleSort b } func isExecuteAction(str string) bool { - if !strings.HasPrefix(str, "execute") || len(str) < 9 { + if !strings.HasPrefix(str, "execute") || len(str) < len("execute()") { return false } - b := str[7] + b := str[len("execute")] + if strings.HasPrefix(str, "execute-multi") { + if len(str) < len("execute-multi()") { + return false + } + b = str[len("execute-multi")] + } e := str[len(str)-1] if b == ':' || b == '(' && e == ')' || b == '[' && e == ']' || b == e && strings.ContainsAny(string(b), "~!@#$%^&*;/|") { diff --git a/src/terminal.go b/src/terminal.go index eb82bd85..764459ff 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -132,6 +132,7 @@ const ( actPreviousHistory actNextHistory actExecute + actExecuteMulti ) func defaultKeymap() map[int]actionType { @@ -305,18 +306,22 @@ func (t *Terminal) output() bool { found = true } } else { - sels := make([]selectedItem, 0, len(t.selected)) - for _, sel := range t.selected { - sels = append(sels, sel) - } - sort.Sort(byTimeOrder(sels)) - for _, sel := range sels { + for _, sel := range t.sortSelected() { fmt.Println(*sel.text) } } return found } +func (t *Terminal) sortSelected() []selectedItem { + sels := make([]selectedItem, 0, len(t.selected)) + for _, sel := range t.selected { + sels = append(sels, sel) + } + sort.Sort(byTimeOrder(sels)) + return sels +} + func runeWidth(r rune, prefixWidth int) int { if r == '\t' { return 8 - prefixWidth%8 @@ -698,8 +703,12 @@ func keyMatch(key int, event C.Event) bool { return event.Type == key || event.Type == C.Rune && int(event.Char) == key-C.AltZ } -func executeCommand(template string, current string) { - command := strings.Replace(template, "{}", fmt.Sprintf("%q", current), -1) +func quoteEntry(entry string) string { + return fmt.Sprintf("%q", entry) +} + +func executeCommand(template string, replacement string) { + command := strings.Replace(template, "{}", replacement, -1) cmd := exec.Command("sh", "-c", command) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout @@ -858,7 +867,17 @@ func (t *Terminal) Loop() { case actExecute: if t.cy >= 0 && t.cy < t.merger.Length() { item := t.merger.Get(t.cy) - executeCommand(t.execmap[mapkey], item.AsString(t.ansi)) + executeCommand(t.execmap[mapkey], quoteEntry(item.AsString(t.ansi))) + } + case actExecuteMulti: + if len(t.selected) > 0 { + sels := make([]string, len(t.selected)) + for i, sel := range t.sortSelected() { + sels[i] = quoteEntry(*sel.text) + } + executeCommand(t.execmap[mapkey], strings.Join(sels, " ")) + } else { + return doAction(actExecute, mapkey) } case actInvalid: t.mutex.Unlock() |
