summaryrefslogtreecommitdiffstats
path: root/src/options.go
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2022-12-23 03:28:16 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2022-12-23 03:28:16 +0900
commit73162a4bc3403e3532afa8a95008a3b4a00d554a (patch)
treeca5222c63531f3478b07a216d237f850237d778c /src/options.go
parent1a9761736ed2190aa7536d4b6754f617f46cfd9c (diff)
Rewrite bind spec parser
Diffstat (limited to 'src/options.go')
-rw-r--r--src/options.go64
1 files changed, 51 insertions, 13 deletions
diff --git a/src/options.go b/src/options.go
index 4c7774c9..6eafa545 100644
--- a/src/options.go
+++ b/src/options.go
@@ -889,19 +889,58 @@ const (
)
func init() {
- // Backreferences are not supported.
- // "~!@#$%^&*;/|".each_char.map { |c| Regexp.escape(c) }.map { |c| "#{c}[^#{c}]*#{c}" }.join('|')
executeRegexp = regexp.MustCompile(
- `(?si)[:+](execute(?:-multi|-silent)?|reload|preview|change-query|change-prompt|change-preview-window|change-preview|(?:re|un)bind):.+|[:+](execute(?:-multi|-silent)?|reload|preview|change-query|change-prompt|change-preview-window|change-preview|(?:re|un)bind)(\([^)]*\)|\[[^\]]*\]|~[^~]*~|![^!]*!|@[^@]*@|\#[^\#]*\#|\$[^\$]*\$|%[^%]*%|\^[^\^]*\^|&[^&]*&|\*[^\*]*\*|;[^;]*;|/[^/]*/|\|[^\|]*\|)`)
+ `(?si)[:+](execute(?:-multi|-silent)?|reload|preview|change-query|change-prompt|change-preview-window|change-preview|(?:re|un)bind)`)
splitRegexp = regexp.MustCompile("[,:]+")
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
}
func maskActionContents(action string) string {
- masked := executeRegexp.ReplaceAllStringFunc(action, func(src string) string {
- prefix := src[:1] + actionNameRegexp.FindString(src[1:])
- return prefix + "(" + strings.Repeat(" ", len(src)-len(prefix)-2) + ")"
- })
+ masked := ""
+Loop:
+ for len(action) > 0 {
+ loc := executeRegexp.FindStringIndex(action)
+ if loc == nil {
+ masked += action
+ break
+ }
+ masked += action[:loc[1]]
+ action = action[loc[1]:]
+ if len(action) == 0 {
+ break
+ }
+ cs := string(action[0])
+ ce := ")"
+ switch action[0] {
+ case ':':
+ masked += strings.Repeat(" ", len(action))
+ break Loop
+ case '(':
+ ce = ")"
+ case '{':
+ ce = "}"
+ case '[':
+ ce = "]"
+ case '<':
+ ce = ">"
+ case '~', '!', '@', '#', '$', '%', '^', '&', '*', ';', '/', '|':
+ ce = string(cs)
+ default:
+ continue
+ }
+ cs = regexp.QuoteMeta(cs)
+ ce = regexp.QuoteMeta(ce)
+
+ // @$ or @+
+ loc = regexp.MustCompile(fmt.Sprintf(`^%s.*?(%s[+,]|%s$)`, cs, ce, ce)).FindStringIndex(action)
+ if loc == nil {
+ masked += action
+ break
+ }
+ // Keep + or , at the end
+ masked += strings.Repeat(" ", loc[1]-1) + action[loc[1]-1:loc[1]]
+ action = action[loc[1]:]
+ }
masked = strings.Replace(masked, "::", string([]rune{escapedColon, ':'}), -1)
masked = strings.Replace(masked, ",:", string([]rune{escapedComma, ':'}), -1)
masked = strings.Replace(masked, "+:", string([]rune{escapedPlus, ':'}), -1)
@@ -1130,14 +1169,13 @@ func parseKeymap(keymap map[tui.Event][]*action, str string, exit func(string))
}
func isExecuteAction(str string) actionType {
- matches := executeRegexp.FindAllStringSubmatch(":"+str, -1)
- if matches == nil || len(matches) != 1 || len(matches[0][0]) != len(str)+1 {
+ masked := maskActionContents(":" + str)[1:]
+ if masked == str {
+ // Not masked
return actIgnore
}
- prefix := matches[0][1]
- if len(prefix) == 0 {
- prefix = matches[0][2]
- }
+
+ prefix := actionNameRegexp.FindString(str)
switch prefix {
case "reload":
return actReload