summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2015-11-09 01:42:01 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2015-11-09 23:58:19 +0900
commita89d8995c3a4544851ae3a40b8fb1f1c16f9535e (patch)
tree25476566395e829d77b458078743b535d8ebe5b0 /src
parentdbc854d5f470d6a995401b3e6386687e7663cddd (diff)
downloadfzf-a89d8995c3a4544851ae3a40b8fb1f1c16f9535e.tar.gz
Add execute-multi action
Close #413
Diffstat (limited to 'src')
-rw-r--r--src/options.go32
-rw-r--r--src/terminal.go37
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()