feat: show preview command when using arrow keys

This commit is contained in:
verse91
2026-04-27 16:22:10 +07:00
parent 44ff34f378
commit 23e5b13f6d
2 changed files with 38 additions and 19 deletions
+2 -2
View File
@@ -66,7 +66,7 @@ func fixedWidth(s string, width int) string {
return s return s
} }
func (o *Overlay) RenderGhostText(buffer string) string { func (o *Overlay) RenderGhostText(buffer string, userNavigated bool) string {
o.mu.Lock() o.mu.Lock()
defer o.mu.Unlock() defer o.mu.Unlock()
@@ -77,7 +77,7 @@ func (o *Overlay) RenderGhostText(buffer string) string {
var s strings.Builder var s strings.Builder
ghostText := "" ghostText := ""
if buffer != "" { if !userNavigated && buffer != "" {
topCmd := o.Items[0].Cmd topCmd := o.Items[0].Cmd
if strings.HasPrefix(strings.ToLower(topCmd), strings.ToLower(buffer)) { if strings.HasPrefix(strings.ToLower(topCmd), strings.ToLower(buffer)) {
ghostText = topCmd[len(buffer):] ghostText = topCmd[len(buffer):]
+36 -17
View File
@@ -165,6 +165,7 @@ func runWrapper() {
}() }()
var disableGhostText atomic.Bool var disableGhostText atomic.Bool
var userNavigated bool
isExecuting := func() bool { isExecuting := func() bool {
pgrp, err := unix.IoctlGetInt(int(ptmx.Fd()), unix.TIOCGPGRP) pgrp, err := unix.IoctlGetInt(int(ptmx.Fd()), unix.TIOCGPGRP)
@@ -211,7 +212,7 @@ func runWrapper() {
overlay.UpdateItems(results) overlay.UpdateItems(results)
var rBuf strings.Builder var rBuf strings.Builder
if !disableGhostText.Load() { if !disableGhostText.Load() {
rBuf.WriteString(overlay.RenderGhostText(query)) rBuf.WriteString(overlay.RenderGhostText(query, false))
} }
rBuf.WriteString(overlay.Render()) rBuf.WriteString(overlay.Render())
os.Stdout.Write([]byte(rBuf.String())) os.Stdout.Write([]byte(rBuf.String()))
@@ -240,6 +241,7 @@ func runWrapper() {
bufCopy := naiveBuffer bufCopy := naiveBuffer
modeCopy := mode modeCopy := mode
navCopy := userNavigated
if bufCopy == "" { if bufCopy == "" {
os.Stdout.Write([]byte(overlay.ClearAndDisable())) os.Stdout.Write([]byte(overlay.ClearAndDisable()))
@@ -254,23 +256,32 @@ func runWrapper() {
return return
} }
debugLog("[Render] query: '%s', mode: %s", bufCopy, modeCopy)
results := mergeResults(bufCopy, modeCopy)
debugLog("[Render] results found: %d", len(results))
var b strings.Builder var b strings.Builder
if len(results) == 0 { if !navCopy {
b.WriteString(overlay.ClearAndDisable()) debugLog("[Render] query: '%s', mode: %s", bufCopy, modeCopy)
} else { results := mergeResults(bufCopy, modeCopy)
debugLog("[Render] results found: %d", len(results))
if len(results) == 0 {
b.WriteString(overlay.ClearAndDisable())
os.Stdout.Write([]byte(b.String()))
return
}
if overlay.Visible { if overlay.Visible {
b.WriteString(overlay.Clear()) b.WriteString(overlay.Clear())
} }
overlay.UpdateItems(results) overlay.UpdateItems(results)
if !disableGhostText.Load() { } else {
b.WriteString(overlay.RenderGhostText(bufCopy)) if overlay.Visible {
b.WriteString(overlay.Clear())
} }
b.WriteString(overlay.Render())
} }
if !disableGhostText.Load() {
b.WriteString(overlay.RenderGhostText(bufCopy, navCopy))
}
b.WriteString(overlay.Render())
os.Stdout.Write([]byte(b.String())) os.Stdout.Write([]byte(b.String()))
}) })
} }
@@ -317,6 +328,7 @@ func runWrapper() {
if overlay.Visible && (inputSlice[i+2] == 'A' || inputSlice[i+2] == 'B') { if overlay.Visible && (inputSlice[i+2] == 'A' || inputSlice[i+2] == 'B') {
intercepted = true intercepted = true
userNavigated = true
if inputSlice[i+2] == 'A' { // up arrow if inputSlice[i+2] == 'A' { // up arrow
overlay.Cursor-- overlay.Cursor--
if overlay.Cursor < 0 { if overlay.Cursor < 0 {
@@ -328,12 +340,13 @@ func runWrapper() {
overlay.Cursor = len(overlay.Items) - 1 overlay.Cursor = len(overlay.Items) - 1
} }
} }
var rBuf strings.Builder
if !disableGhostText.Load() { selected := overlay.Items[overlay.Cursor].Cmd
rBuf.WriteString(overlay.RenderGhostText(naiveBuffer)) ptmx.Write([]byte{0x15}) // ctrl+u to clear line
} ptmx.Write([]byte(selected))
rBuf.WriteString(overlay.Render()) naiveBuffer = selected
os.Stdout.Write([]byte(rBuf.String()))
shouldOverlayDraw = true
i += 2 i += 2
continue continue
} else if overlay.Visible && !disableGhostText.Load() && inputSlice[i+2] == 'C' { // right arrow } else if overlay.Visible && !disableGhostText.Load() && inputSlice[i+2] == 'C' { // right arrow
@@ -388,10 +401,12 @@ func runWrapper() {
} else if overlay.Visible && (b == 0x0d || b == 0x0a) { } else if overlay.Visible && (b == 0x0d || b == 0x0a) {
intercepted = true intercepted = true
os.Stdout.Write([]byte(overlay.ClearAndDisable())) os.Stdout.Write([]byte(overlay.ClearAndDisable()))
ptmx.Write([]byte{0x0d}) ptmx.Write([]byte{0x0d})
naiveBuffer = "" naiveBuffer = ""
disableGhostText.Store(false) disableGhostText.Store(false)
shouldOverlayDraw = false shouldOverlayDraw = false
userNavigated = false
continue continue
} else if b == 0x09 { // tab: select suggestions } else if b == 0x09 { // tab: select suggestions
intercepted = true intercepted = true
@@ -415,6 +430,7 @@ func runWrapper() {
shouldOverlayDraw = true // <- rerender after tab to choose, if you set to false, shouldOverlayDraw = true // <- rerender after tab to choose, if you set to false,
// when you press tab continuely, it will print all folder from menu suggestions // when you press tab continuely, it will print all folder from menu suggestions
// and make the cursor jump to next line // and make the cursor jump to next line
userNavigated = false
} }
continue continue
} }
@@ -428,6 +444,7 @@ func runWrapper() {
if len(naiveBuffer) > 0 { if len(naiveBuffer) > 0 {
naiveBuffer = naiveBuffer[:len(naiveBuffer)-1] naiveBuffer = naiveBuffer[:len(naiveBuffer)-1]
shouldOverlayDraw = true shouldOverlayDraw = true
userNavigated = false
} }
case 0x17: // ctrl+w: delete the last word in the buffer case 0x17: // ctrl+w: delete the last word in the buffer
trimBuf := strings.TrimRight(naiveBuffer, " ") trimBuf := strings.TrimRight(naiveBuffer, " ")
@@ -438,10 +455,12 @@ func runWrapper() {
naiveBuffer = "" naiveBuffer = ""
} }
shouldOverlayDraw = true shouldOverlayDraw = true
userNavigated = false
case '\r', '\n', 0x03, 0x15, 0x0C: // enter, ctrl+c, ctrl+u, ctrl+l: clear buffer on line reset case '\r', '\n', 0x03, 0x15, 0x0C: // enter, ctrl+c, ctrl+u, ctrl+l: clear buffer on line reset
naiveBuffer = "" naiveBuffer = ""
disableGhostText.Store(false) disableGhostText.Store(false)
os.Stdout.Write([]byte(overlay.ClearAndDisable())) os.Stdout.Write([]byte(overlay.ClearAndDisable()))
userNavigated = false
default: default:
// track normal printable characters in the buffer for matching // track normal printable characters in the buffer for matching
if b >= 32 && b <= 126 { if b >= 32 && b <= 126 {