Custom key binding support (#238)

This commit is contained in:
Junegunn Choi
2015-05-20 21:25:15 +09:00
parent 15099eb13b
commit 1592bedbe8
6 changed files with 306 additions and 54 deletions

View File

@@ -51,6 +51,7 @@ const usage = `usage: fzf [options]
--print-query Print query as the first line
--expect=KEYS Comma-separated list of keys to complete fzf
--toggle-sort=KEY Key to toggle sort
--bind=KEYBINDS Custom key bindings. Refer to the man page.
--sync Synchronous search for multi-staged filtering
Environment variables
@@ -112,8 +113,9 @@ type Options struct {
Select1 bool
Exit0 bool
Filter *string
ToggleSort int
ToggleSort bool
Expect []int
Keymap map[int]actionType
PrintQuery bool
Sync bool
Version bool
@@ -149,8 +151,9 @@ func defaultOptions() *Options {
Select1: false,
Exit0: false,
Filter: nil,
ToggleSort: 0,
ToggleSort: false,
Expect: []int{},
Keymap: defaultKeymap(),
PrintQuery: false,
Sync: false,
Version: false}
@@ -290,12 +293,82 @@ func parseTheme(str string) *curses.ColorTheme {
return nil
}
func checkToggleSort(str string) int {
func parseKeymap(keymap map[int]actionType, toggleSort bool, str string) (map[int]actionType, bool) {
for _, pairStr := range strings.Split(str, ",") {
pair := strings.Split(pairStr, ":")
if len(pair) != 2 {
errorExit("invalid key binding: " + pairStr)
}
keys := parseKeyChords(pair[0], "key name required")
if len(keys) != 1 {
errorExit("invalid key binding: " + pairStr)
}
key := keys[0]
act := strings.ToLower(pair[1])
switch strings.ToLower(pair[1]) {
case "beginning-of-line":
keymap[key] = actBeginningOfLine
case "abort":
keymap[key] = actAbort
case "accept":
keymap[key] = actAccept
case "backward-char":
keymap[key] = actBackwardChar
case "backward-delete-char":
keymap[key] = actBackwardDeleteChar
case "backward-word":
keymap[key] = actBackwardWord
case "clear-screen":
keymap[key] = actClearScreen
case "delete-char":
keymap[key] = actDeleteChar
case "end-of-line":
keymap[key] = actEndOfLine
case "forward-char":
keymap[key] = actForwardChar
case "forward-word":
keymap[key] = actForwardWord
case "kill-line":
keymap[key] = actKillLine
case "kill-word":
keymap[key] = actKillWord
case "unix-line-discard", "line-discard":
keymap[key] = actUnixLineDiscard
case "unix-word-rubout", "word-rubout":
keymap[key] = actUnixWordRubout
case "yank":
keymap[key] = actYank
case "backward-kill-word":
keymap[key] = actBackwardKillWord
case "toggle-down":
keymap[key] = actToggleDown
case "toggle-up":
keymap[key] = actToggleUp
case "down":
keymap[key] = actDown
case "up":
keymap[key] = actUp
case "page-up":
keymap[key] = actPageUp
case "page-down":
keymap[key] = actPageDown
case "toggle-sort":
keymap[key] = actToggleSort
toggleSort = true
default:
errorExit("unknown action: " + act)
}
}
return keymap, toggleSort
}
func checkToggleSort(keymap map[int]actionType, str string) map[int]actionType {
keys := parseKeyChords(str, "key name required")
if len(keys) != 1 {
errorExit("multiple keys specified")
}
return keys[0]
keymap[keys[0]] = actToggleSort
return keymap
}
func parseOptions(opts *Options, allArgs []string) {
@@ -319,10 +392,13 @@ func parseOptions(opts *Options, allArgs []string) {
opts.Expect = parseKeyChords(nextString(allArgs, &i, "key names required"), "key names required")
case "--tiebreak":
opts.Tiebreak = parseTiebreak(nextString(allArgs, &i, "sort criterion required"))
case "--bind":
opts.Keymap, opts.ToggleSort = parseKeymap(opts.Keymap, opts.ToggleSort, nextString(allArgs, &i, "bind expression required"))
case "--color":
opts.Theme = parseTheme(nextString(allArgs, &i, "color scheme name required"))
case "--toggle-sort":
opts.ToggleSort = checkToggleSort(nextString(allArgs, &i, "key name required"))
opts.Keymap = checkToggleSort(opts.Keymap, nextString(allArgs, &i, "key name required"))
opts.ToggleSort = true
case "-d", "--delimiter":
opts.Delimiter = delimiterRegexp(nextString(allArgs, &i, "delimiter required"))
case "-n", "--nth":
@@ -409,13 +485,16 @@ func parseOptions(opts *Options, allArgs []string) {
} else if match, _ := optString(arg, "-s|--sort="); match {
opts.Sort = 1 // Don't care
} else if match, value := optString(arg, "--toggle-sort="); match {
opts.ToggleSort = checkToggleSort(value)
opts.Keymap = checkToggleSort(opts.Keymap, value)
opts.ToggleSort = true
} else if match, value := optString(arg, "--expect="); match {
opts.Expect = parseKeyChords(value, "key names required")
} else if match, value := optString(arg, "--tiebreak="); match {
opts.Tiebreak = parseTiebreak(value)
} else if match, value := optString(arg, "--color="); match {
opts.Theme = parseTheme(value)
} else if match, value := optString(arg, "--bind="); match {
opts.Keymap, opts.ToggleSort = parseKeymap(opts.Keymap, opts.ToggleSort, value)
} else {
errorExit("unknown option: " + arg)
}