chore: generate
This commit is contained in:
parent
c0a258b22a
commit
82a3270cf2
5 changed files with 60 additions and 69 deletions
|
|
@ -1,11 +1,7 @@
|
||||||
import { createStore, type SetStoreFunction, type Store } from "solid-js/store"
|
import { createStore, type SetStoreFunction, type Store } from "solid-js/store"
|
||||||
import type { Prompt } from "@/context/prompt"
|
import type { Prompt } from "@/context/prompt"
|
||||||
import { Persist, persisted } from "@/utils/persist"
|
import { Persist, persisted } from "@/utils/persist"
|
||||||
import {
|
import { prependHistoryEntry, type PromptHistoryComment, type PromptHistoryStoredEntry } from "./history"
|
||||||
prependHistoryEntry,
|
|
||||||
type PromptHistoryComment,
|
|
||||||
type PromptHistoryStoredEntry,
|
|
||||||
} from "./history"
|
|
||||||
|
|
||||||
export type PromptInputHistory = {
|
export type PromptInputHistory = {
|
||||||
entries: (mode: "normal" | "shell") => PromptHistoryStoredEntry[]
|
entries: (mode: "normal" | "shell") => PromptHistoryStoredEntry[]
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,15 @@ export type PromptInputV2AttachmentConfig = {
|
||||||
getPathForFile?: (file: File) => string
|
getPathForFile?: (file: File) => string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createPromptInputV2Attachments(input: PromptInputV2AttachmentConfig & {
|
export function createPromptInputV2Attachments(
|
||||||
capture: () => PromptTarget
|
input: PromptInputV2AttachmentConfig & {
|
||||||
editor: () => HTMLElement | undefined
|
capture: () => PromptTarget
|
||||||
focusEditor: () => void
|
editor: () => HTMLElement | undefined
|
||||||
addPart: (part: PromptInputV2Prompt[number]) => boolean
|
focusEditor: () => void
|
||||||
setDraggingType: (type: "image" | "@mention" | null) => void
|
addPart: (part: PromptInputV2Prompt[number]) => boolean
|
||||||
}) {
|
setDraggingType: (type: "image" | "@mention" | null) => void
|
||||||
|
},
|
||||||
|
) {
|
||||||
const capture = () => {
|
const capture = () => {
|
||||||
const prompt = input.capture()
|
const prompt = input.capture()
|
||||||
const editor = input.editor()
|
const editor = input.editor()
|
||||||
|
|
@ -113,13 +115,10 @@ export function createPromptInputV2Attachments(input: PromptInputV2AttachmentCon
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
const addAttachments = async (files: File[], toast = true, target = capture()) => {
|
const addAttachments = async (files: File[], toast = true, target = capture()) => {
|
||||||
const found = await files.reduce(
|
const found = await files.reduce(async (result, file) => {
|
||||||
async (result, file) => {
|
const previous = await result
|
||||||
const previous = await result
|
return (await add(file, false, target)) || previous
|
||||||
return (await add(file, false, target)) || previous
|
}, Promise.resolve(false))
|
||||||
},
|
|
||||||
Promise.resolve(false),
|
|
||||||
)
|
|
||||||
if (!found && files.length > 0 && toast) input.warn()
|
if (!found && files.length > 0 && toast) input.warn()
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,11 @@ describe("prompt input v2 interaction machine", () => {
|
||||||
{ type: "commands.open" },
|
{ type: "commands.open" },
|
||||||
persisted("existing text"),
|
persisted("existing text"),
|
||||||
)
|
)
|
||||||
const selected = transitionPromptInputV2(open.state, { type: "popover.select", item: command }, persisted("existing text"))
|
const selected = transitionPromptInputV2(
|
||||||
|
open.state,
|
||||||
|
{ type: "popover.select", item: command },
|
||||||
|
persisted("existing text"),
|
||||||
|
)
|
||||||
|
|
||||||
expect(selected.commands).toContainEqual({ type: "draft.setText", value: "/review existing text" })
|
expect(selected.commands).toContainEqual({ type: "draft.setText", value: "/review existing text" })
|
||||||
expect(selected.state.popover).toEqual({ type: "closed" })
|
expect(selected.state.popover).toEqual({ type: "closed" })
|
||||||
|
|
|
||||||
|
|
@ -91,25 +91,19 @@ function inputChanged(state: PromptInputV2InteractionState, value: string, persi
|
||||||
const context = value.match(/(?:^|\s)@([^\s@]*)$/)
|
const context = value.match(/(?:^|\s)@([^\s@]*)$/)
|
||||||
if (context) {
|
if (context) {
|
||||||
const query = context[1] ?? ""
|
const query = context[1] ?? ""
|
||||||
return changed(
|
return changed({ ...state, popover: { type: "context", query }, focus: "editor" }, [
|
||||||
{ ...state, popover: { type: "context", query }, focus: "editor" },
|
...setText,
|
||||||
[
|
{ type: "popover.filter", popover: "context", query },
|
||||||
...setText,
|
])
|
||||||
{ type: "popover.filter", popover: "context", query },
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const command = value.match(/^\/([^\s/]*)$/)
|
const command = value.match(/^\/([^\s/]*)$/)
|
||||||
if (command) {
|
if (command) {
|
||||||
const query = command[1] ?? ""
|
const query = command[1] ?? ""
|
||||||
return changed(
|
return changed({ ...state, popover: { type: "command-inline", query }, focus: "editor" }, [
|
||||||
{ ...state, popover: { type: "command-inline", query }, focus: "editor" },
|
...setText,
|
||||||
[
|
{ type: "popover.filter", popover: "command", query },
|
||||||
...setText,
|
])
|
||||||
{ type: "popover.filter", popover: "command", query },
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed(
|
return changed(
|
||||||
|
|
@ -123,45 +117,35 @@ function openCommands(
|
||||||
persisted: PromptInputV2PersistedState,
|
persisted: PromptInputV2PersistedState,
|
||||||
): PromptInputV2Transition {
|
): PromptInputV2Transition {
|
||||||
if (!populated(persisted)) {
|
if (!populated(persisted)) {
|
||||||
return changed(
|
return changed({ ...state, popover: { type: "command-inline", query: "" }, focus: "editor" }, [
|
||||||
{ ...state, popover: { type: "command-inline", query: "" }, focus: "editor" },
|
{ type: "draft.setText", value: promptText(persisted) + "/" },
|
||||||
[
|
|
||||||
{ type: "draft.setText", value: promptText(persisted) + "/" },
|
|
||||||
{ type: "popover.filter", popover: "command", query: "" },
|
|
||||||
{ type: "focus.editor" },
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return changed(
|
|
||||||
{ ...state, popover: { type: "command-menu", query: "" }, focus: "command-search" },
|
|
||||||
[
|
|
||||||
{ type: "popover.filter", popover: "command", query: "" },
|
{ type: "popover.filter", popover: "command", query: "" },
|
||||||
{ type: "focus.command-search" },
|
{ type: "focus.editor" },
|
||||||
],
|
])
|
||||||
)
|
}
|
||||||
|
return changed({ ...state, popover: { type: "command-menu", query: "" }, focus: "command-search" }, [
|
||||||
|
{ type: "popover.filter", popover: "command", query: "" },
|
||||||
|
{ type: "focus.command-search" },
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
function openContext(
|
function openContext(
|
||||||
state: PromptInputV2InteractionState,
|
state: PromptInputV2InteractionState,
|
||||||
persisted: PromptInputV2PersistedState,
|
persisted: PromptInputV2PersistedState,
|
||||||
): PromptInputV2Transition {
|
): PromptInputV2Transition {
|
||||||
return changed(
|
return changed({ ...state, popover: { type: "context", query: "" }, focus: "editor" }, [
|
||||||
{ ...state, popover: { type: "context", query: "" }, focus: "editor" },
|
{ type: "draft.setText", value: promptText(persisted) + "@" },
|
||||||
[
|
{ type: "popover.filter", popover: "context", query: "" },
|
||||||
{ type: "draft.setText", value: promptText(persisted) + "@" },
|
{ type: "focus.editor" },
|
||||||
{ type: "popover.filter", popover: "context", query: "" },
|
])
|
||||||
{ type: "focus.editor" },
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryChanged(state: PromptInputV2InteractionState, query: string): PromptInputV2Transition {
|
function queryChanged(state: PromptInputV2InteractionState, query: string): PromptInputV2Transition {
|
||||||
if (state.popover.type === "closed") return unchanged(state)
|
if (state.popover.type === "closed") return unchanged(state)
|
||||||
const popover = state.popover.type === "context" ? "context" : "command"
|
const popover = state.popover.type === "context" ? "context" : "command"
|
||||||
return changed(
|
return changed({ ...state, popover: { ...state.popover, query, activeID: undefined } }, [
|
||||||
{ ...state, popover: { ...state.popover, query, activeID: undefined } },
|
{ type: "popover.filter", popover, query },
|
||||||
[{ type: "popover.filter", popover, query }],
|
])
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resultsChanged(state: PromptInputV2InteractionState, ids: string[]): PromptInputV2Transition {
|
function resultsChanged(state: PromptInputV2InteractionState, ids: string[]): PromptInputV2Transition {
|
||||||
|
|
@ -215,20 +199,26 @@ function keyDown(
|
||||||
return unchanged(state)
|
return unchanged(state)
|
||||||
}
|
}
|
||||||
if (event.key === "Escape") {
|
if (event.key === "Escape") {
|
||||||
return changed(
|
return changed({ ...state, popover: { type: "closed" }, focus: "editor" }, [{ type: "focus.editor" }], true)
|
||||||
{ ...state, popover: { type: "closed" }, focus: "editor" },
|
|
||||||
[{ type: "focus.editor" }],
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (event.key === "Tab" || (event.key === "Enter" && !event.composing)) {
|
if (event.key === "Tab" || (event.key === "Enter" && !event.composing)) {
|
||||||
if (!state.popover.activeID) return unchanged(state, true)
|
if (!state.popover.activeID) return unchanged(state, true)
|
||||||
return unchanged(state, true, [{ type: "suggestion.select", id: state.popover.activeID }])
|
return unchanged(state, true, [{ type: "suggestion.select", id: state.popover.activeID }])
|
||||||
}
|
}
|
||||||
const direction = event.key === "ArrowDown" || (event.ctrl && event.key === "n") ? 1 : event.key === "ArrowUp" || (event.ctrl && event.key === "p") ? -1 : 0
|
const direction =
|
||||||
|
event.key === "ArrowDown" || (event.ctrl && event.key === "n")
|
||||||
|
? 1
|
||||||
|
: event.key === "ArrowUp" || (event.ctrl && event.key === "p")
|
||||||
|
? -1
|
||||||
|
: 0
|
||||||
if (!direction || event.ids.length === 0) return unchanged(state)
|
if (!direction || event.ids.length === 0) return unchanged(state)
|
||||||
const current = state.popover.activeID ? event.ids.indexOf(state.popover.activeID) : -1
|
const current = state.popover.activeID ? event.ids.indexOf(state.popover.activeID) : -1
|
||||||
const index = current < 0 ? (direction === 1 ? 0 : event.ids.length - 1) : (current + direction + event.ids.length) % event.ids.length
|
const index =
|
||||||
|
current < 0
|
||||||
|
? direction === 1
|
||||||
|
? 0
|
||||||
|
: event.ids.length - 1
|
||||||
|
: (current + direction + event.ids.length) % event.ids.length
|
||||||
return changed({ ...state, popover: { ...state.popover, activeID: event.ids[index] } }, [], true)
|
return changed({ ...state, popover: { ...state.popover, activeID: event.ids[index] } }, [], true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,9 @@ export function createPromptInputV2Store(input: PromptInputV2StoreInput) {
|
||||||
setStore()("context", "items", (items) => items.filter((item) => item.key !== key))
|
setStore()("context", "items", (items) => items.filter((item) => item.key !== key))
|
||||||
},
|
},
|
||||||
addMention(mention: PromptInputV2FilePart | PromptInputV2AgentPart) {
|
addMention(mention: PromptInputV2FilePart | PromptInputV2AgentPart) {
|
||||||
const text = store().prompt.map((part) => ("content" in part ? part.content : "")).join("")
|
const text = store()
|
||||||
|
.prompt.map((part) => ("content" in part ? part.content : ""))
|
||||||
|
.join("")
|
||||||
const end = store().cursor ?? text.length
|
const end = store().cursor ?? text.length
|
||||||
const start = text.slice(0, end).lastIndexOf("@")
|
const start = text.slice(0, end).lastIndexOf("@")
|
||||||
setStore()("prompt", insertMention(store().prompt, start < 0 ? end : start, end, mention))
|
setStore()("prompt", insertMention(store().prompt, start < 0 ? end : start, end, mention))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue