diff options
author | Junegunn Choi <junegunn.c@gmail.com> | 2022-12-23 03:28:16 +0900 |
---|---|---|
committer | Junegunn Choi <junegunn.c@gmail.com> | 2022-12-23 03:28:16 +0900 |
commit | 73162a4bc3403e3532afa8a95008a3b4a00d554a (patch) | |
tree | ca5222c63531f3478b07a216d237f850237d778c /src/options.go | |
parent | 1a9761736ed2190aa7536d4b6754f617f46cfd9c (diff) |
Rewrite bind spec parser
Diffstat (limited to 'src/options.go')
-rw-r--r-- | src/options.go | 64 |
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 |