feat(config): ui width, auto exec, selection and navigation configs (#80)

closes #67

So I made an auto-exec confg `auto-exec = true`
(e32c0ba6ed69f3c764353e58b8fbacf160f37d5a) which means:
- If you want your command in the prompt to be executed right away, you
can set this = false (for example, you are typing `nvim ~/.conf` but
IRIS is suggesting `nvim ~/.config`, it will ignore the suggestion and
exec what you are typing, this is current default behavior)
- If you want to auto execute full command which is being suggested, you
can set this = true (this is the opposite of above, when you are typing
`nvim ~/.conf` but IRIS is suggesting `nvim ~/.config`, it will auto
exec `nvim ~/.config` instead, but sometime you want to exec what you
are typing instead of the suggestion right?, just press esc or shift tab
to hide the menu and it will)

---

Select keybinding to replace tab
(0dc01cba8c610e8d6fd8c50f6a71bdcc061a098f)
`select = "ctrl+y"`

Some users may love nvim keybinding or emacs, so I bring navigation
keybinding to be configurable (0dc01cba8c610e8d6fd8c50f6a71bdcc061a098f)
```
navigate-up = "ctrl+k"
navigate-down = "ctrl+j"
```
---

I also added a option for UI width
(dfa3b810a7be406fe4652b3886020f37bb166811)
`max-width = 80`
- If you configure `max-width` to be larger than the actual width of the
current terminal, Iris will automatically "compress" the window to match
the terminal's width (meaning it will never overflow and break the
interface)
- If you configure `max-width` too small (e.g 10), the interface will
have cramped text, making it look very bad. So, I've set a minimum safe
min limit of 40. If the configured value is smaller than this, Iris will
automatically use 40

Small note: If you set `max-width = 0` (or leave it blank), it will
automatically use Iris's default standard size of 76. SO you can
confidently customize it without fear of breaking the UI (I hope so
lmao)

---

Added a fallback to ensure Iris never crashes or loses shortcuts if the
user accidentally deletes keybinding configuration lines or
intentionally assigns empty strings " "
(f682c9bf623f3ed46ad0763221145604dbd91b07)

Fix typo `toggle_mode` to `toggle-mode`
(b39be6673e552735fa65a6c9807510c83b4d9cdd)

if you have a better config design, please tell me, I always listen to
your idea
This commit is contained in:
VERSE
2026-07-31 10:49:10 +07:00
committed by GitHub
parent 9f43fcb352
commit a885c7462a
7 changed files with 303 additions and 226 deletions
+24 -2
View File
@@ -39,6 +39,7 @@ type CoreConfig struct {
Mode string `toml:"mode"`
Debug bool `toml:"debug"`
ExpandAlias bool `toml:"expand-alias"`
AutoExecute bool `toml:"auto-execute"`
}
type UIConfig struct {
@@ -47,6 +48,7 @@ type UIConfig struct {
ShowHiddenFiles bool `toml:"hidden-files"`
MaxSuggestions int `toml:"max-suggestions"`
MaxHeight int `toml:"max-height"`
MaxWidth int `toml:"max-width"`
NerdFonts bool `toml:"nerd-fonts"`
}
@@ -62,8 +64,11 @@ type UpdaterConfig struct {
}
type KeybindingsConfig struct {
ToggleMode string `toml:"toggle-mode"`
ToggleMenu string `toml:"toggle-menu"`
ToggleMode string `toml:"toggle-mode"`
ToggleMenu string `toml:"toggle-menu"`
SelectSuggestion string `toml:"select"`
NavigateUp string `toml:"navigate-up"`
NavigateDown string `toml:"navigate-down"`
}
type SuggestOnEmptyConfig struct {
@@ -186,6 +191,23 @@ func Load() (*Config, error) {
applyEnv(cfg)
// fallback for empty keybindings
if cfg.Keybindings.ToggleMode == "" {
cfg.Keybindings.ToggleMode = "ctrl+r"
}
if cfg.Keybindings.ToggleMenu == "" {
cfg.Keybindings.ToggleMenu = "shift+tab"
}
if cfg.Keybindings.SelectSuggestion == "" {
cfg.Keybindings.SelectSuggestion = "tab"
}
if cfg.Keybindings.NavigateUp == "" {
cfg.Keybindings.NavigateUp = "up"
}
if cfg.Keybindings.NavigateDown == "" {
cfg.Keybindings.NavigateDown = "down"
}
if err := validate(cfg); err != nil {
return cfg, fmt.Errorf("config: invalid value: %w", err)
}
+7 -2
View File
@@ -11,6 +11,7 @@ func DefaultConfig() *Config {
Mode: "last",
Debug: false,
ExpandAlias: true,
AutoExecute: false,
},
UI: UIConfig{
Style: "modern",
@@ -18,6 +19,7 @@ func DefaultConfig() *Config {
ShowHiddenFiles: false,
MaxSuggestions: 100,
MaxHeight: 15,
MaxWidth: 0, // 0 means no limit, fallback to terminal width
NerdFonts: true,
},
Git: GitConfig{
@@ -42,8 +44,11 @@ func DefaultConfig() *Config {
},
},
Keybindings: KeybindingsConfig{
ToggleMode: "ctrl+r",
ToggleMenu: "shift+tab",
ToggleMode: "ctrl+r",
ToggleMenu: "shift+tab",
SelectSuggestion: "tab",
NavigateUp: "up",
NavigateDown: "down",
},
}
}
+15 -1
View File
@@ -13,6 +13,8 @@ func MatchKey(input []byte, expected string) (matched bool, consumed int) {
}
expected = strings.ToLower(strings.TrimSpace(expected))
expected = strings.TrimPrefix(expected, "<")
expected = strings.TrimSuffix(expected, ">")
if strings.HasPrefix(expected, "ctrl+") && len(expected) == 6 {
char := expected[5]
@@ -38,12 +40,24 @@ func MatchKey(input []byte, expected string) (matched bool, consumed int) {
if len(input) >= 3 && input[0] == 0x1b && input[1] == '[' && input[2] == 'Z' {
return true, 3
}
case "up":
if len(input) >= 3 && input[0] == 0x1b && (input[1] == '[' || input[1] == 'O') && input[2] == 'A' {
return true, 3
}
case "down":
if len(input) >= 3 && input[0] == 0x1b && (input[1] == '[' || input[1] == 'O') && input[2] == 'B' {
return true, 3
}
case "right":
// typically \033[C or \033OC
if len(input) >= 3 && input[0] == 0x1b && (input[1] == '[' || input[1] == 'O') && input[2] == 'C' {
return true, 3
}
case "enter":
case "left":
if len(input) >= 3 && input[0] == 0x1b && (input[1] == '[' || input[1] == 'O') && input[2] == 'D' {
return true, 3
}
case "enter", "cr", "return":
if input[0] == 0x0d || input[0] == 0x0a {
return true, 1
}