This commit is contained in:
spaghetti-coder 2025-12-16 20:55:09 +01:00 committed by GitHub
commit 429c14cd60
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 16 deletions

View File

@ -25,11 +25,15 @@ const CommandSuggestions = observer(({ editorRef, editorActions, commands }: Com
onAutocomplete: (cmd, word, index, actions) => {
// Replace the trigger word with the command output
actions.removeText(index, word.length);
const initialPosition = actions.getCursorPosition();
actions.insertText(cmd.run());
// Position cursor if command specifies an offset
if (cmd.cursorOffset) {
actions.setCursorPosition(actions.getCursorPosition() + cmd.cursorOffset);
}
const offset = cmd.cursorRange?.[0];
if (typeof offset === "undefined") return;
const cursorPosition = initialPosition + offset;
const length = cmd.cursorRange?.[1] || 0;
actions.setCursorPosition(cursorPosition, cursorPosition + length);
},
});

View File

@ -42,7 +42,10 @@ export function SuggestionsPopup<T>({
<div
key={getItemKey(item, i)}
ref={i === selectedIndex ? selectedItemRef : null}
onMouseDown={() => onItemSelect(item)}
onMouseDown={(e) => {
onItemSelect(item);
e.preventDefault();
}}
className={cn(
"rounded p-1 px-2 w-full text-sm cursor-pointer transition-colors select-none",
"hover:bg-accent hover:text-accent-foreground",

View File

@ -1,28 +1,47 @@
export interface Command {
name: string;
run: () => string;
cursorOffset?: number;
// Ex.:
// [4] == [4, 0] - cursor offset is 4 chars from initial position
// [7, 2] - cursor offset is 7 chars and 2 next chars selected
// If omitted, cursor stays in the end of the inserted string
cursorRange?: number[];
}
export const editorCommands: Command[] = [
{
name: "todo",
run: () => "- [ ] ",
cursorOffset: 6, // Places cursor after "- [ ] " to start typing task
name: "code",
run: () => "```js\n\n```", // JS by default as most popular (at least on github)
cursorRange: [3, 2],
},
{
name: "code",
run: () => "```\n\n```",
cursorOffset: 4, // Places cursor on empty line between code fences
// Template from github, but with summary initially selected for better UX
name: "details",
run: () => "<details><summary>Details</summary>\n\n\n</details>",
cursorRange: [18, 7],
},
{
name: "image",
run: () => "![alt text]()", // No need in URL placeholder
cursorRange: [2, 8],
},
{
name: "link",
run: () => "[text](url)",
cursorOffset: 1, // Places cursor after "[" to type link text
run: () => "[text]()",
cursorRange: [1, 4],
},
{
name: "table",
run: () => "| Header | Header |\n| ------ | ------ |\n| Cell | Cell |",
cursorOffset: 1, // Places cursor after first "|" to edit first header
run: () => "| Column1 | Column2 |\n| ------ | ------ |\n| Cell1 | Cell2 |",
cursorRange: [2, 7],
},
{
name: "todo",
run: () => "- [ ] ",
},
{
name: "youtube",
run: () => "[![alt text](https://img.youtube.com/vi/VIDEO_ID/0.jpg)](https://www.youtube.com/watch?v=VIDEO_ID)",
cursorRange: [3, 8],
},
];