Rewrite bind spec parser

pull/3097/head^2
Junegunn Choi 1 year ago
parent 1a9761736e
commit 73162a4bc3
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

@ -1049,6 +1049,8 @@ that case, you can use any of the following alternative notations to avoid
parse errors. parse errors.
\fBaction-name[...]\fR \fBaction-name[...]\fR
\fBaction-name{...}\fR
\fBaction-name<...>\fR
\fBaction-name~...~\fR \fBaction-name~...~\fR
\fBaction-name!...!\fR \fBaction-name!...!\fR
\fBaction-name@...@\fR \fBaction-name@...@\fR

@ -889,19 +889,58 @@ const (
) )
func init() { func init() {
// Backreferences are not supported.
// "~!@#$%^&*;/|".each_char.map { |c| Regexp.escape(c) }.map { |c| "#{c}[^#{c}]*#{c}" }.join('|')
executeRegexp = regexp.MustCompile( 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("[,:]+") splitRegexp = regexp.MustCompile("[,:]+")
actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+") actionNameRegexp = regexp.MustCompile("(?i)^[a-z-]+")
} }
func maskActionContents(action string) string { func maskActionContents(action string) string {
masked := executeRegexp.ReplaceAllStringFunc(action, func(src string) string { masked := ""
prefix := src[:1] + actionNameRegexp.FindString(src[1:]) Loop:
return prefix + "(" + strings.Repeat(" ", len(src)-len(prefix)-2) + ")" 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{escapedColon, ':'}), -1)
masked = strings.Replace(masked, ",:", string([]rune{escapedComma, ':'}), -1) masked = strings.Replace(masked, ",:", string([]rune{escapedComma, ':'}), -1)
masked = strings.Replace(masked, "+:", string([]rune{escapedPlus, ':'}), -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 { func isExecuteAction(str string) actionType {
matches := executeRegexp.FindAllStringSubmatch(":"+str, -1) masked := maskActionContents(":" + str)[1:]
if matches == nil || len(matches) != 1 || len(matches[0][0]) != len(str)+1 { if masked == str {
// Not masked
return actIgnore return actIgnore
} }
prefix := matches[0][1]
if len(prefix) == 0 { prefix := actionNameRegexp.FindString(str)
prefix = matches[0][2]
}
switch prefix { switch prefix {
case "reload": case "reload":
return actReload return actReload

Loading…
Cancel
Save