Skip to content

Commit

Permalink
feat: allow customization of search bar key bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
kencx committed Jun 3, 2023
1 parent bb7d8d3 commit 52851ca
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 149 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ See [config](examples/config/README.md) for all configuration options.
- [x] Ability to customize keyb hotkeys
- [x] `a, add` subcommand to quickly add a single hotkey entry from the CLI
- [ ] Export to additional file formats (`json, toml, conf/ini` etc.)
- [ ] Allow customization of search bar key bindings
- [ ] Support multiple keyb files or directories

## Contributing

Expand Down
208 changes: 113 additions & 95 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,89 +51,107 @@ type Color struct {
}

type Keys struct {
Quit string
Up string
Down string
UpFocus string `yaml:"up_focus"`
DownFocus string `yaml:"down_focus"`
HalfUp string `yaml:"half_up"`
HalfDown string `yaml:"half_down"`
FullUp string `yaml:"full_up"`
FullDown string `yaml:"full_bottom"`
GoToFirstLine string `yaml:"first_line"`
GoToLastLine string `yaml:"last_line"`
GoToTop string `yaml:"top"`
GoToMiddle string `yaml:"middle"`
GoToBottom string `yaml:"bottom"`
Search string
ClearSearch string `yaml:"clear_search"`
Normal string
Quit string
Up string
Down string
UpFocus string `yaml:"up_focus"`
DownFocus string `yaml:"down_focus"`
HalfUp string `yaml:"half_up"`
HalfDown string `yaml:"half_down"`
FullUp string `yaml:"full_up"`
FullDown string `yaml:"full_bottom"`
GoToFirstLine string `yaml:"first_line"`
GoToLastLine string `yaml:"last_line"`
GoToTop string `yaml:"top"`
GoToMiddle string `yaml:"middle"`
GoToBottom string `yaml:"bottom"`
Search string
ClearSearch string `yaml:"clear_search"`
Normal string
CursorWordForward string `yaml:"cursor_word_forward"`
CursorWordBackward string `yaml:"cursor_word_backward"`
CursorDeleteWordBackward string `yaml:"cursor_delete_word_backward"`
CursorDeleteWordForward string `yaml:"cursor_delete_word_forward"`
CursorDeleteAfterCursor string `yaml:"cursor_delete_after_cursor"`
CursorDeleteBeforeCursor string `yaml:"cursor_delete_before_cursor"`
CursorLineStart string `yaml:"cursor_line_start"`
CursorLineEnd string `yaml:"cursor_line_end"`
CursorPaste string `yaml:"cursor_paste"`
}

var DefaultConfig = &Config{
Settings: Settings{
Debug: false,
Reverse: false,
Mouse: true,
SearchMode: false,
SortKeys: false,
Title: "",
Prompt: "keys > ",
PromptLocation: "top",
Placeholder: "...",
PrefixSep: ";",
SepWidth: 4,
Margin: 0,
Padding: 1,
BorderStyle: "hidden",
},
Color: Color{
FilterFg: "#FFA066",
},
Keys: Keys{
Quit: "q, ctrl+c",
Up: "k, up",
Down: "j, down",
UpFocus: "ctrl+k",
DownFocus: "ctrl+j",
HalfUp: "ctrl+u",
HalfDown: "ctrl+d",
FullUp: "ctrl+b",
FullDown: "ctrl+f",
GoToFirstLine: "g",
GoToLastLine: "G",
GoToTop: "H",
GoToMiddle: "M",
GoToBottom: "L",
Search: "/",
ClearSearch: "alt+d",
Normal: "esc",
},
}
Settings: Settings{
Debug: false,
Reverse: false,
Mouse: true,
SearchMode: false,
SortKeys: false,
Title: "",
Prompt: "keys > ",
PromptLocation: "top",
Placeholder: "...",
PrefixSep: ";",
SepWidth: 4,
Margin: 0,
Padding: 1,
BorderStyle: "hidden",
},
Color: Color{
FilterFg: "#FFA066",
},
Keys: Keys{
Quit: "q, ctrl+c",
Up: "k, up",
Down: "j, down",
UpFocus: "ctrl+k",
DownFocus: "ctrl+j",
HalfUp: "ctrl+u",
HalfDown: "ctrl+d",
FullUp: "ctrl+b",
FullDown: "ctrl+f",
GoToFirstLine: "g",
GoToLastLine: "G",
GoToTop: "H",
GoToMiddle: "M",
GoToBottom: "L",
Search: "/",
ClearSearch: "alt+d",
Normal: "esc",
CursorWordForward: "alt+right, alt+f",
CursorWordBackward: "alt+left, alt+b",
CursorDeleteWordBackward: "alt+backspace",
CursorDeleteWordForward: "alt+delete",
CursorDeleteAfterCursor: "alt+k",
CursorDeleteBeforeCursor: "alt+u",
CursorLineStart: "home, ctrl+a",
CursorLineEnd: "end, ctrl+e",
CursorPaste: "ctrl+v",
},
}

func Parse(flagKPath, configPath string) (Apps, *Config, error) {
var (
config *Config
err error
)

switch configPath {
case "":
config, err = ReadDefaultConfigFile()
default:
config, err = ReadConfigFile(configPath)
}
if err != nil {
return nil, nil, err
}
var (
config *Config
err error
)

switch configPath {
case "":
config, err = ReadDefaultConfigFile()
default:
config, err = ReadConfigFile(configPath)
}
if err != nil {
return nil, nil, err
}

// priority: flag > file
var kPath string
if flagKPath != "" {
kPath = flagKPath
}

// If no keyb file present, create a default file and set it as kPath
// If no keyb file present, create a default file and set it as kPath
if kPath == "" {
kPath = config.KeybPath
if !pathExists(kPath) {
Expand All @@ -152,29 +170,29 @@ func Parse(flagKPath, configPath string) (Apps, *Config, error) {

// Read config file at default path if exist. Otherwise, return default config
func ReadDefaultConfigFile() (*Config, error) {
baseDir, err := getBaseDir()
if err != nil {
return nil, err
}
configDir, err := getConfigDir(baseDir)
if err != nil {
return nil, err
}

var config *Config
defaultConfigFilePath := filepath.Join(configDir, configFileName)
if !pathExists(defaultConfigFilePath) {
config, err = newDefaultConfig()
if err != nil {
return nil, err
}
} else {
config, err = ReadConfigFile(defaultConfigFilePath)
if err != nil {
return nil, err
}
}
return config, nil
baseDir, err := getBaseDir()
if err != nil {
return nil, err
}
configDir, err := getConfigDir(baseDir)
if err != nil {
return nil, err
}

var config *Config
defaultConfigFilePath := filepath.Join(configDir, configFileName)
if !pathExists(defaultConfigFilePath) {
config, err = newDefaultConfig()
if err != nil {
return nil, err
}
} else {
config, err = ReadConfigFile(defaultConfigFilePath)
if err != nil {
return nil, err
}
}
return config, nil
}

// Read given config file and merge with default config
Expand All @@ -201,7 +219,7 @@ func ReadConfigFile(path string) (*Config, error) {
}

func newDefaultConfig() (*Config, error) {
res := DefaultConfig
res := DefaultConfig

baseDir, err := getBaseDir()
if err != nil {
Expand Down
45 changes: 27 additions & 18 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

const (
testDirPath = "../testdata"
testDirPath = "../testdata"
testConfigDir = keybDirPath
)

Expand Down Expand Up @@ -71,23 +71,32 @@ func TestReadConfigFile(t *testing.T) {
FilterFg: "#FFA066",
},
Keys: Keys{
Quit: "q, ctrl+c",
Up: "k, up",
Down: "j, down",
UpFocus: "alt+k",
DownFocus: "alt+j",
HalfUp: "ctrl+u",
HalfDown: "ctrl+d",
FullUp: "ctrl+b",
FullDown: "ctrl+f",
GoToFirstLine: "g",
GoToLastLine: "G",
GoToTop: "H",
GoToMiddle: "M",
GoToBottom: "L",
Search: "/",
ClearSearch: "alt+d",
Normal: "esc",
Quit: "q, ctrl+c",
Up: "k, up",
Down: "j, down",
UpFocus: "alt+k",
DownFocus: "alt+j",
HalfUp: "ctrl+u",
HalfDown: "ctrl+d",
FullUp: "ctrl+b",
FullDown: "ctrl+f",
GoToFirstLine: "g",
GoToLastLine: "G",
GoToTop: "H",
GoToMiddle: "M",
GoToBottom: "L",
Search: "/",
ClearSearch: "alt+d",
Normal: "esc",
CursorWordForward: "alt+right, alt+f",
CursorWordBackward: "alt+left, alt+b",
CursorDeleteWordBackward: "alt+backspace",
CursorDeleteWordForward: "alt+delete",
CursorDeleteAfterCursor: "alt+k",
CursorDeleteBeforeCursor: "alt+u",
CursorLineStart: "home, ctrl+a",
CursorLineEnd: "end, ctrl+e",
CursorPaste: "ctrl+v",
},
}
got, err := ReadConfigFile(filepath.Join(testDirPath, "testConfig.yml"))
Expand Down
16 changes: 12 additions & 4 deletions examples/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,16 @@ Multiple keys may be set for a single binding, separated by commas.
| `normal` | <kbd>Esc</kbd> | Exit search mode |
| `quit` | <kbd>Ctrl + c, q</kbd> | Quit |

>The
>[default](https://github.com/charmbracelet/bubbles/blob/afd7868712d4a4f817829dc7e1868c337c5e5cff/textinput/textinput.go#L61)
>key bindings for the search bar have been reset temporarily. Customization of
>these key bindings are coming soon.
These hotkeys configure the cursor behaviour in the search bar only:

| Hotkey | Default | Description |
| ----------------------- | --------------------------- | ---------------- |
| `cursor_word_forward` | <kbd>alt+right, alt+f</kbd> | Move forward by word |
| `cursor_word_backward` | <kbd>alt+left, alt+b</kbd> | Move backward by word |
| `cursor_delete_word_backward` | <kbd>alt+backspace</kbd> | Delete word backward |
| `cursor_delete_word_forward` | <kbd>alt+delete</kbd> | Delete word forward |
| `cursor_delete_after_cursor` | <kbd>alt+k</kbd> | Delete after cursor |
| `cursor_delete_before_cursor` | <kbd>alt+u</kbd> | Delete before cursor |
| `cursor_line_start` | <kbd>home, ctrl+a</kbd> | Move cursor to start |
| `cursor_line_end` | <kbd>end, ctrl+e</kbd> | Move cursor to end |
| `cursor_paste` | <kbd>ctrl+v</kbd> | Paste into search bar|
9 changes: 9 additions & 0 deletions examples/config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,12 @@ keys:
search: /
clear_search: alt+d
normal: esc
cursor_word_forward: "alt+right, alt+f"
cursor_word_backward: "alt+left, alt+b"
cursor_delete_word_backward: "alt+backspace"
cursor_delete_word_forward: "alt+delete"
cursor_delete_after_cursor: "alt+k"
cursor_delete_before_cursor: "alt+u"
cursor_line_start: "home, ctrl+a"
cursor_line_end: "end, ctrl+e"
cursor_paste: "ctrl+v"
9 changes: 9 additions & 0 deletions testdata/testConfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,12 @@ keys:
search: /
clear_search: alt+d
normal: esc
cursor_word_forward: "alt+right, alt+f"
cursor_word_backward: "alt+left, alt+b"
cursor_delete_word_backward: "alt+backspace"
cursor_delete_word_forward: "alt+delete"
cursor_delete_after_cursor: "alt+k"
cursor_delete_before_cursor: "alt+u"
cursor_line_start: "home, ctrl+a"
cursor_line_end: "end, ctrl+e"
cursor_paste: "ctrl+v"
Loading

0 comments on commit 52851ca

Please sign in to comment.