feat(config): add some more config options (#64)

## Add
Make these things configurable
- Expand aliases
- Suggest hidden files (#59)
- Toggle menu and mode 

```
[ui]
hidden-files = true # or false

[core]
expand-alias = true # or false

[keybindings]
toggle-mode = "ctrl+r"
toggle-menu = "ctrl+space"
```

- Auto reload config on changes: now just changes config and save the
file, IRIS will auto detect and reload in silent
- Added all these in config on init and docs

## Fix
I tested on holding backspace and the ghost text keep glitching so I
fixed it, this is just a small fix
This commit is contained in:
VERSE
2026-07-29 20:43:46 +07:00
committed by GitHub
parent 69fb77910d
commit d6cfb9c909
9 changed files with 271 additions and 81 deletions
+78 -49
View File
@@ -247,6 +247,8 @@ func runWrapper() {
overlay := integration.NewOverlay()
// start background update check (async)
pendingUpdate = startBackgroundUpdateCheck()
updatePrinted := false
@@ -256,6 +258,12 @@ func runWrapper() {
shellPGID = spec.ShellPID
}
var isCommandActive atomic.Bool
var disableGhostText atomic.Bool
disableGhostText.Store(!config.Get().UI.GhostText)
config.AutoDetectConfigChange(func(cfg *config.Config) {
disableGhostText.Store(!cfg.UI.GhostText)
})
var renderOverlay func()
isExecuting := func() bool {
if isCommandActive.Load() {
return true
@@ -311,10 +319,6 @@ func runWrapper() {
}
}()
var disableGhostText atomic.Bool
disableGhostText.Store(!config.Get().UI.GhostText)
var renderOverlay func()
// listen for suggestion requests from shell scripts via the ipc pipe
go func() {
defer func() {
@@ -576,9 +580,9 @@ func runWrapper() {
}
if renderTimer != nil {
renderTimer.Stop()
return
}
renderTimer = time.AfterFunc(25*time.Millisecond, func() {
renderTimer = time.AfterFunc(20*time.Millisecond, func() {
renderMu.Lock()
renderTimer = nil
renderMu.Unlock()
@@ -614,6 +618,21 @@ func runWrapper() {
b := inputSlice[i]
intercepted := false
if matched, consumed := config.MatchKey(inputSlice[i:], config.Get().Keybindings.ToggleMenu); matched {
intercepted = true
suggestionsEnabled = !suggestionsEnabled
logger.Debugf("Intercepted ToggleMenu, suggestionsEnabled=%v", suggestionsEnabled)
if !suggestionsEnabled {
writeStdout([]byte(overlay.ClearAndDisable()))
} else {
shouldOverlayDraw = true
}
i += consumed - 1
continue
}
if b == '\033' {
// check for bracketed paste start/end
if i+5 < n && inputSlice[i+1] == '[' && inputSlice[i+2] == '2' && inputSlice[i+3] == '0' {
@@ -628,20 +647,6 @@ func runWrapper() {
}
// handle escape sequences like arrow keys and functional shortcuts
if i+2 < n && (inputSlice[i+1] == '[' || inputSlice[i+1] == 'O') {
// shift tab: hide/unhide menu dropdown
if inputSlice[i+1] == '[' && inputSlice[i+2] == 'Z' {
intercepted = true
suggestionsEnabled = !suggestionsEnabled
logger.Debugf("Intercepted Shift+Tab, suggestionsEnabled=%v", suggestionsEnabled)
if !suggestionsEnabled {
writeStdout([]byte(overlay.ClearAndDisable()))
} else {
shouldOverlayDraw = true
}
i += 2
continue
}
if overlay.IsVisible() && (inputSlice[i+2] == 'A' || inputSlice[i+2] == 'B') {
intercepted = true
userNavigated.Store(true)
@@ -722,24 +727,6 @@ func runWrapper() {
}
i += 2
continue
} else if !disableGhostText.Load() && inputSlice[i+2] == 'C' { // right arrow
bufferMu.Lock()
atEnd := (cursorOffset == 0)
ghostText := overlay.GetGhostText(naiveBuffer, atEnd)
bufferMu.Unlock()
if len(ghostText) > 0 {
intercepted = true
logger.Debugf("Intercepted Right Arrow (accepted ghost text: %q)", ghostText)
bufferMu.Lock()
naiveBuffer += ghostText
cursorOffset = 0
bufferMu.Unlock()
_, _ = ptmx.Write([]byte(ghostText))
shouldOverlayDraw = true
i += 2
continue
}
}
}
@@ -775,6 +762,29 @@ func runWrapper() {
i += 2
continue
}
bufferMu.Lock()
atEnd := (cursorOffset == 0)
ghostText := ""
if !disableGhostText.Load() {
ghostText = overlay.GetGhostText(naiveBuffer, atEnd)
}
bufferMu.Unlock()
if len(ghostText) > 0 {
intercepted = true
logger.Debugf("Intercepted Right Arrow (accepted ghost text: %q)", ghostText)
bufferMu.Lock()
naiveBuffer += ghostText
cursorOffset = 0
bufferMu.Unlock()
overlay.ClearGhostTextState()
_, _ = ptmx.Write([]byte(ghostText))
shouldOverlayDraw = true
i += 2
continue
}
bufferMu.Lock()
if naiveBuffer != "" || overlay.IsVisible() {
cursorOffset--
@@ -813,7 +823,8 @@ func runWrapper() {
continue
}
if b == 0x12 { // ctrl+r: toggle between command specs and command history
if matched, consumed := config.MatchKey(inputSlice[i:], config.Get().Keybindings.ToggleMode); matched { // ctrl+r: toggle between command specs and command history
i += consumed - 1
intercepted = true
activeModeMu.Lock()
if activeMode == "spec" {
@@ -869,12 +880,33 @@ func runWrapper() {
}
renderMu.Unlock()
if cmdToSubmit == "" {
bufferMu.Lock()
cmdToSubmit = naiveBuffer
bufferMu.Unlock()
}
if strings.TrimSpace(cmdToSubmit) == "iris reload" {
if newCfg, err := config.Load(); err == nil {
config.Init(newCfg)
disableGhostText.Store(!newCfg.UI.GhostText)
}
// Clear the shell line with Ctrl+U, then echo message, then Enter
msg := "echo -e '\\033[32m✓ Iris configuration reloaded successfully.\\033[0m'\r"
_, _ = ptmx.Write(append([]byte{0x15}, []byte(msg)...))
bufferMu.Lock()
naiveBuffer = ""
cursorOffset = 0
bufferMu.Unlock()
disableGhostText.Store(false)
shouldOverlayDraw = false
userNavigated.Store(false)
continue
}
isCommandActive.Store(true)
_, _ = ptmx.Write([]byte{b})
bufferMu.Lock()
if cmdToSubmit == "" {
cmdToSubmit = naiveBuffer
}
lastSubmittedCommand = strings.TrimSpace(cmdToSubmit)
naiveBuffer = ""
cursorOffset = 0
@@ -930,12 +962,8 @@ func runWrapper() {
bufferMu.Unlock()
_, _ = ptmx.Write(append([]byte{0x15}, selected...))
overlay.ResetCursor() // this prevents when you tab, it switches between suggestions non-stop
shouldOverlayDraw = true // <- rerender after tab to choose, if you set to false,
// when you press tab continually, it will print all folder from menu suggestions
// and make the cursor jump to next line
overlay.ResetCursor()
shouldOverlayDraw = true
userNavigated.Store(false)
}
continue
@@ -1034,8 +1062,9 @@ func runWrapper() {
// track normal printable characters in the buffer for matching
if b >= 32 && b <= 126 {
// expand alias on space, but only when typing manually (not pasting)
// and only if expand-alias configuration is enabled
bufferMu.Lock()
isSpaceAlias := !inBracketedPaste && b == ' ' && naiveBuffer != "" && !strings.Contains(naiveBuffer, " ")
isSpaceAlias := config.Get().Core.ExpandAlias && !inBracketedPaste && b == ' ' && naiveBuffer != "" && !strings.Contains(naiveBuffer, " ")
var target string
var ok bool
if isSpaceAlias {