mirror of
https://github.com/fbarrca/obsidian-inlineAI.git
synced 2026-07-22 11:50:24 +00:00
Commands and prefix can be set through the settings
This commit is contained in:
parent
c84137da2e
commit
a3b709c2b2
4 changed files with 51 additions and 22 deletions
|
|
@ -17,12 +17,11 @@ export default class InlineAIChatPlugin extends Plugin {
|
|||
this.chatapi = new ChatApiManager(this.settings, this.app);
|
||||
|
||||
this.registerEditorExtension([
|
||||
FloatingTooltipExtension(this.chatapi),
|
||||
FloatingTooltipExtension(this.chatapi, this),
|
||||
generatedResponseState,
|
||||
currentSelectionState,
|
||||
buildSelectionHiglightState,
|
||||
diffExtension
|
||||
|
||||
]);
|
||||
|
||||
// Add command to show tooltip
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import { ChatApiManager } from "../api";
|
|||
|
||||
import { currentSelectionState, SelectionInfo } from "./SelectionState";
|
||||
import { slashCommandAutocompletion } from "./commands/source";
|
||||
import { slashCommands } from "./commands/commands";
|
||||
import InlineAIChatPlugin from "src/main";
|
||||
|
||||
|
||||
|
||||
|
|
@ -33,6 +33,7 @@ export const acceptTooltipEffect = StateEffect.define<null>();
|
|||
class FloatingWidget extends WidgetType {
|
||||
private chatApiManager: ChatApiManager;
|
||||
private selectionInfo: SelectionInfo | null;
|
||||
private plugin: InlineAIChatPlugin;
|
||||
|
||||
private outerEditorView: EditorView | null = null;
|
||||
|
||||
|
|
@ -48,10 +49,11 @@ class FloatingWidget extends WidgetType {
|
|||
private acceptButton!: HTMLButtonElement;
|
||||
private discardButton!: HTMLButtonElement;
|
||||
|
||||
constructor(chatApiManager: ChatApiManager, selectionInfo: SelectionInfo | null) {
|
||||
constructor(chatApiManager: ChatApiManager, selectionInfo: SelectionInfo | null, plugin:InlineAIChatPlugin) {
|
||||
super();
|
||||
this.chatApiManager = chatApiManager;
|
||||
this.selectionInfo = selectionInfo;
|
||||
this.plugin = plugin;
|
||||
|
||||
// Create main DOM structure using createEl
|
||||
this.dom = createEl("div", { cls: "cm-cursor-overlay", attr: { style: "user-select: none;" } });
|
||||
|
|
@ -152,8 +154,8 @@ class FloatingWidget extends WidgetType {
|
|||
]),
|
||||
// 3) Enable slash-command autocompletion
|
||||
slashCommandAutocompletion({
|
||||
prefix: ':',
|
||||
customCommands: slashCommands
|
||||
prefix: this.plugin.settings.commandPrefix,
|
||||
customCommands: this.plugin.settings.customCommands
|
||||
})
|
||||
],
|
||||
}),
|
||||
|
|
@ -297,14 +299,15 @@ class FloatingWidget extends WidgetType {
|
|||
*/
|
||||
function renderFloatingWidget(
|
||||
state: EditorState,
|
||||
chatApiManager: ChatApiManager
|
||||
chatApiManager: ChatApiManager,
|
||||
plugin:InlineAIChatPlugin
|
||||
): DecorationSet {
|
||||
const firstSelectedRange = state.selection.ranges.find((range) => !range.empty) ?? state.selection.main;
|
||||
|
||||
const selectionInfo = state.field(currentSelectionState, false) ?? null;
|
||||
|
||||
const deco = Decoration.widget({
|
||||
widget: new FloatingWidget(chatApiManager, selectionInfo),
|
||||
widget: new FloatingWidget(chatApiManager, selectionInfo, plugin),
|
||||
above: true,
|
||||
inline: true,
|
||||
side: -9999,
|
||||
|
|
@ -323,7 +326,7 @@ function renderFloatingWidget(
|
|||
* When the user dismisses the tooltip, it clears the decoration set.
|
||||
* Otherwise, it returns the existing decoration set.
|
||||
*/
|
||||
function FloatingTooltipState(chatApiManager: ChatApiManager) {
|
||||
function FloatingTooltipState(chatApiManager: ChatApiManager, plugin:InlineAIChatPlugin) {
|
||||
return StateField.define<DecorationSet>({
|
||||
create(state) {
|
||||
return Decoration.none;
|
||||
|
|
@ -331,7 +334,7 @@ function FloatingTooltipState(chatApiManager: ChatApiManager) {
|
|||
update(decorations, tr) {
|
||||
// Recompute if the user triggers the command
|
||||
if (tr.effects.some((e) => e.is(commandEffect))) {
|
||||
return renderFloatingWidget(tr.state, chatApiManager);
|
||||
return renderFloatingWidget(tr.state, chatApiManager, plugin);
|
||||
}
|
||||
// Or dismiss it
|
||||
if (tr.effects.some((e) => e.is(dismissTooltipEffect))) {
|
||||
|
|
@ -347,6 +350,6 @@ function FloatingTooltipState(chatApiManager: ChatApiManager) {
|
|||
/**
|
||||
* Extension enabling selection overlay widgets.
|
||||
*/
|
||||
export function FloatingTooltipExtension(chatApiManager: ChatApiManager) {
|
||||
return [FloatingTooltipState(chatApiManager)];
|
||||
export function FloatingTooltipExtension(chatApiManager: ChatApiManager, plugin:InlineAIChatPlugin) {
|
||||
return [FloatingTooltipState(chatApiManager, plugin)];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
import { autocompletion, CompletionContext } from "@codemirror/autocomplete"
|
||||
import { SlashCommand, slashCommands } from "./commands";
|
||||
/**
|
||||
*
|
||||
* Interface describing a slash command.
|
||||
*/
|
||||
export interface SlashCommand {
|
||||
keyword: string;
|
||||
prompt: string;
|
||||
}
|
||||
|
||||
|
||||
// Factory function that creates a completion source with custom parameters
|
||||
|
|
@ -8,10 +15,11 @@ function createSlashCommandSource(options: {
|
|||
customCommands: SlashCommand[]
|
||||
} = {
|
||||
prefix: '/',
|
||||
customCommands: slashCommands
|
||||
customCommands: []
|
||||
}) {
|
||||
const { prefix, customCommands } = options;
|
||||
console.log(prefix, customCommands)
|
||||
|
||||
return (context: CompletionContext) => {
|
||||
let word = context.matchBefore(new RegExp(`^\\${prefix}\\w*`))
|
||||
if (!word || (word.from == word.to && !context.explicit))
|
||||
|
|
@ -19,8 +27,9 @@ function createSlashCommandSource(options: {
|
|||
return {
|
||||
from: word.from+1,
|
||||
options: (customCommands).map(cmd => ({
|
||||
label: cmd.label,
|
||||
type: "text"
|
||||
label: cmd.keyword,
|
||||
type: "text",
|
||||
detail: cmd.prompt,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
@ -31,4 +40,4 @@ export function slashCommandAutocompletion(options: { prefix?: string, customCom
|
|||
return autocompletion({
|
||||
override: [createSlashCommandSource(options)]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { App, PluginSettingTab, Setting } from "obsidian";
|
||||
import MyPlugin from "./main";
|
||||
import { cursorPrompt, selectionPrompt } from "./default_prompts";
|
||||
import { SlashCommand } from "./modules/commands/source";
|
||||
|
||||
// Interface for the settings
|
||||
export interface InlineAISettings {
|
||||
|
|
@ -10,7 +11,8 @@ export interface InlineAISettings {
|
|||
customURL?: string; // Add a custom URL field
|
||||
selectionPrompt: string;
|
||||
cursorPrompt: string;
|
||||
customCommands: { name: string; prompt: string }[]; // Add custom commands array
|
||||
customCommands: SlashCommand[];
|
||||
commandPrefix: string; // Add command prefix setting
|
||||
}
|
||||
|
||||
// Default settings values
|
||||
|
|
@ -22,6 +24,7 @@ export const DEFAULT_SETTINGS: InlineAISettings = {
|
|||
selectionPrompt: selectionPrompt,
|
||||
cursorPrompt: cursorPrompt,
|
||||
customCommands: [], // Default is an empty array
|
||||
commandPrefix: "/" // Default command prefix
|
||||
};
|
||||
|
||||
// Settings tab class to display settings in Obsidian UI
|
||||
|
|
@ -113,6 +116,21 @@ export class InlineAISettingsTab extends PluginSettingTab {
|
|||
.setName("Advanced")
|
||||
.setHeading();
|
||||
|
||||
// Command Prefix setting
|
||||
new Setting(containerEl)
|
||||
.setName("Command Prefix")
|
||||
.setDesc("The prefix used to trigger custom commands (e.g., /, !, #)")
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("/")
|
||||
.setValue(this.plugin.settings.commandPrefix)
|
||||
.onChange(async (value) => {
|
||||
// Ensure the prefix is not empty
|
||||
this.plugin.settings.commandPrefix = value || "/";
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
);
|
||||
|
||||
// Selection Prompt setting
|
||||
new Setting(containerEl)
|
||||
.setName("Selection prompt")
|
||||
|
|
@ -157,14 +175,14 @@ export class InlineAISettingsTab extends PluginSettingTab {
|
|||
// Display existing commands
|
||||
this.plugin.settings.customCommands.forEach((command, index) => {
|
||||
const setting = new Setting(containerEl)
|
||||
.setName(`Command: ${command.name}`)
|
||||
.setName(`Command: ${command.keyword}`)
|
||||
.setDesc("Edit the command prompt.")
|
||||
.addText((text) =>
|
||||
text
|
||||
.setValue(command.name)
|
||||
.setValue(command.keyword)
|
||||
.setPlaceholder("Command name")
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.customCommands[index].name = value;
|
||||
this.plugin.settings.customCommands[index].keyword = value;
|
||||
await this.plugin.saveSettings();
|
||||
})
|
||||
)
|
||||
|
|
@ -196,7 +214,7 @@ export class InlineAISettingsTab extends PluginSettingTab {
|
|||
.setButtonText("Add Command")
|
||||
.setCta()
|
||||
.onClick(async () => {
|
||||
this.plugin.settings.customCommands.push({ name: "New Command", prompt: "" });
|
||||
this.plugin.settings.customCommands.push({ keyword: "new_command", prompt: "" });
|
||||
await this.plugin.saveSettings();
|
||||
this.display(); // Refresh the display
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue