mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
Merge 38b567a2f1 into 83397ebde2
This commit is contained in:
commit
a56cab1ade
6 changed files with 74 additions and 1 deletions
|
|
@ -0,0 +1,37 @@
|
|||
import { createMemo } from "solid-js"
|
||||
import { DialogSelect } from "@tui/ui/dialog-select"
|
||||
import { useDialog } from "@tui/ui/dialog"
|
||||
import type { PromptInfo } from "./prompt/history"
|
||||
|
||||
export interface DialogHistorySearchProps {
|
||||
items: PromptInfo[]
|
||||
onSelect: (item: PromptInfo) => void
|
||||
}
|
||||
|
||||
export function DialogHistorySearch(props: DialogHistorySearchProps) {
|
||||
const dialog = useDialog()
|
||||
|
||||
const options = createMemo(() => {
|
||||
const seen = new Set<string>()
|
||||
return props.items
|
||||
.slice()
|
||||
.reverse()
|
||||
.filter((item) => {
|
||||
if (!item.input.trim().length) return false
|
||||
if (seen.has(item.input)) return false
|
||||
seen.add(item.input)
|
||||
return true
|
||||
})
|
||||
.map((item) => ({
|
||||
title: item.input,
|
||||
value: item,
|
||||
description: undefined,
|
||||
onSelect: () => {
|
||||
props.onSelect(item)
|
||||
dialog.clear()
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
||||
return <DialogSelect title="Search History" placeholder="Type to search..." options={options()} />
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ export type PromptInfo = {
|
|||
)[]
|
||||
}
|
||||
|
||||
const MAX_HISTORY_ENTRIES = 50
|
||||
const MAX_HISTORY_ENTRIES = 100
|
||||
|
||||
export const { use: usePromptHistory, provider: PromptHistoryProvider } = createSimpleContext({
|
||||
name: "PromptHistory",
|
||||
|
|
@ -61,6 +61,9 @@ export const { use: usePromptHistory, provider: PromptHistoryProvider } = create
|
|||
})
|
||||
|
||||
return {
|
||||
get items() {
|
||||
return store.history
|
||||
},
|
||||
move(direction: 1 | -1, input: string) {
|
||||
if (!store.history.length) return undefined
|
||||
const current = store.history.at(store.index)
|
||||
|
|
@ -103,6 +106,9 @@ export const { use: usePromptHistory, provider: PromptHistoryProvider } = create
|
|||
|
||||
appendFile(historyFile.name!, JSON.stringify(entry) + "\n").catch(() => {})
|
||||
},
|
||||
reset() {
|
||||
setStore("index", 0)
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import { useDialog } from "@tui/ui/dialog"
|
|||
import { DialogProvider as DialogProviderConnect } from "../dialog-provider"
|
||||
import { DialogAlert } from "../../ui/dialog-alert"
|
||||
import { useToast } from "../../ui/toast"
|
||||
import { DialogHistorySearch } from "../dialog-history-search"
|
||||
|
||||
export type PromptProps = {
|
||||
sessionID?: string
|
||||
|
|
@ -788,6 +789,25 @@ export function Prompt(props: PromptProps) {
|
|||
}
|
||||
if (store.mode === "normal") autocomplete.onKeyDown(e)
|
||||
if (!autocomplete.visible) {
|
||||
if (keybind.match("history_search", e)) {
|
||||
e.preventDefault()
|
||||
const historyItems = history.items
|
||||
dialog.replace(() => (
|
||||
<DialogHistorySearch
|
||||
items={historyItems}
|
||||
onSelect={(item) => {
|
||||
input.setText(item.input)
|
||||
setStore("prompt", item)
|
||||
setStore("mode", item.mode ?? "normal")
|
||||
restoreExtmarksFromParts(item.parts)
|
||||
input.cursorOffset = input.plainText.length
|
||||
history.reset()
|
||||
}}
|
||||
/>
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
(keybind.match("history_previous", e) && input.cursorOffset === 0) ||
|
||||
(keybind.match("history_next", e) && input.cursorOffset === input.plainText.length)
|
||||
|
|
|
|||
|
|
@ -561,6 +561,7 @@ export namespace Config {
|
|||
.describe("Delete word backward in input"),
|
||||
history_previous: z.string().optional().default("up").describe("Previous history item"),
|
||||
history_next: z.string().optional().default("down").describe("Next history item"),
|
||||
history_search: z.string().optional().default("ctrl+r").describe("Search history"),
|
||||
session_child_cycle: z.string().optional().default("<leader>right").describe("Next child session"),
|
||||
session_child_cycle_reverse: z.string().optional().default("<leader>left").describe("Previous child session"),
|
||||
session_parent: z.string().optional().default("<leader>up").describe("Go to parent session"),
|
||||
|
|
|
|||
|
|
@ -1114,6 +1114,10 @@ export type KeybindsConfig = {
|
|||
* Next history item
|
||||
*/
|
||||
history_next?: string
|
||||
/**
|
||||
* Search history
|
||||
*/
|
||||
history_search?: string
|
||||
/**
|
||||
* Next child session
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7623,6 +7623,11 @@
|
|||
"default": "down",
|
||||
"type": "string"
|
||||
},
|
||||
"history_search": {
|
||||
"description": "Search history",
|
||||
"default": "ctrl+r",
|
||||
"type": "string"
|
||||
},
|
||||
"session_child_cycle": {
|
||||
"description": "Next child session",
|
||||
"default": "<leader>right",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue