From d64779f660dc0edb1ed14420c7bd446e9f83fb33 Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Sat, 14 Mar 2026 21:52:13 +1100 Subject: [PATCH] Add cmd-k to delete current line --- app.go | 22 +++++++++ frontend/index.html | 9 ++++ frontend/src/app.css | 46 +++++++++++++++++++ frontend/src/cmplugins.js | 22 +++++++++ frontend/src/controllers/prompt_controller.js | 42 +++++++++++++++++ frontend/src/main.js | 2 + frontend/src/services.js | 3 ++ frontend/wailsjs/go/main/App.d.ts | 4 ++ frontend/wailsjs/go/main/App.js | 8 ++++ models.go | 8 ++++ 10 files changed, 166 insertions(+) create mode 100644 frontend/src/controllers/prompt_controller.js diff --git a/app.go b/app.go index 672b391..a0d3a74 100644 --- a/app.go +++ b/app.go @@ -62,6 +62,28 @@ func (a *App) ListProcessors() (resp []ListProcessorsResponse) { return resp } +func (a *App) TriggerTextProcess(action string) { + runtime.EventsEmit(a.ctx, "request-text-process", RequestTextProcess{ + Action: action, + }) +} + +func (a *App) PromptUser(label string, resp func(string)) { + runtime.EventsOnce(a.ctx, "prompt-response", func(data ...interface{}) { + if len(data) == 0 { + return + } + ans, ok := data[0].(string) + if !ok { + return + } + resp(ans) + }) + runtime.EventsEmit(a.ctx, "prompt-request", PromptRequest{ + Label: label, + }) +} + func (a *App) ProcessText(req ProcessTextRequest) { filter, ok := TextFilters[req.Action] if !ok { diff --git a/frontend/index.html b/frontend/index.html index 4951b76..43a2da8 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -10,6 +10,15 @@
Cmd+P: open command palette. Shift+Cmd+P: rerun last command.
+ +
+ +
+ +
+
+
diff --git a/frontend/src/app.css b/frontend/src/app.css index c18533a..efc3d8f 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -27,6 +27,52 @@ font-size: 1.1em; } +dialog#prompt-dialog { + width: 450px; + max-width: 50%; + + position: absolute; + top: 0; + left: 50%; + transform: translate(-50%, -50%); + + padding: 0; + + /* Frosted glass effect */ + background: rgba(225, 225, 225, 0.38); + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + + /* Subtle grey border and rounded corners */ + border: 1px solid rgba(169, 169, 169, 0.3); + border-radius: 12px; + + /* Add subtle shadow for depth */ + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); +} + +dialog#prompt-dialog .dialog-body { + display: flex; + flex-direction: column; + padding: 10px; +} + +dialog#prompt-dialog .prompt-label { + font-size: 0.9em; + color: rgba(0, 0, 0, 0.6); + margin-bottom: 6px; +} + +dialog#prompt-dialog input { + width: 100%; + border: none; + text-decoration: none; + outline: none; + font-size: 1.3em; + background-color: transparent; + font-weight: normal; +} + dialog#command-dialog { width: 450px; height: 400px; diff --git a/frontend/src/cmplugins.js b/frontend/src/cmplugins.js index 7ee146f..b3b160e 100644 --- a/frontend/src/cmplugins.js +++ b/frontend/src/cmplugins.js @@ -43,6 +43,28 @@ export const commandPalette = keymap.of([{ let event = new CustomEvent('dq-rerunlastcommand'); window.dispatchEvent(event); + return true; + } +}, { + key: "Cmd-k", + run: (view) => { + const {state} = view; + const changes = []; + + for (let range of state.selection.ranges) { + const line = state.doc.lineAt(range.head); + changes.push({ + from: line.from, + to: line.to < state.doc.length ? line.to + 1 : line.to, + insert: "" + }); + } + + view.dispatch({ + changes: changes, + sequential: true + }); + return true; } }]); diff --git a/frontend/src/controllers/prompt_controller.js b/frontend/src/controllers/prompt_controller.js new file mode 100644 index 0000000..c8ff4e3 --- /dev/null +++ b/frontend/src/controllers/prompt_controller.js @@ -0,0 +1,42 @@ +import { Controller } from "@hotwired/stimulus" + +export class PromptController extends Controller { + static targets = [ + "label", + "input", + ]; + + connect() { + this._callback = null; + + window.runtime.EventsOn("prompt-request", (data) => { + this.prompt(data.label, (res) => { + window.runtime.EventsEmit("prompt-response", res); + }); + }); + } + + prompt(label, callback) { + this._callback = callback; + this.labelTarget.textContent = label; + this.inputTarget.value = ""; + this.element.showModal(); + this.inputTarget.focus(); + } + + submit(ev) { + ev.preventDefault(); + let value = this.inputTarget.value; + this.element.close(); + if (this._callback) { + this._callback(value); + this._callback = null; + } + } + + dismiss(ev) { + ev.preventDefault(); + this._callback = null; + this.element.close(); + } +} diff --git a/frontend/src/main.js b/frontend/src/main.js index 69357a5..b6da20d 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -11,6 +11,7 @@ import {indentWithTab} from "@codemirror/commands"; import {StatusController} from "./controllers/status_controller.js"; import {CommandsController} from "./controllers/commands_controller.js"; +import {PromptController} from "./controllers/prompt_controller.js"; @@ -28,6 +29,7 @@ const view = new EditorView({ window.Stimulus = Application.start() Stimulus.register("commands", CommandsController); +Stimulus.register("prompt", PromptController); Stimulus.register("status", StatusController); textProcessor.setCodeMirrorEditor(view); diff --git a/frontend/src/services.js b/frontend/src/services.js index bb9e368..c6d46b7 100644 --- a/frontend/src/services.js +++ b/frontend/src/services.js @@ -29,6 +29,9 @@ class TextProcessor { }); this._editor.dispatch({ changes: changes }); }); + window.runtime.EventsOn("request-text-process", (data) => { + this.runTextCommand(data.action); + }); } async runTextCommand(command) { diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 45cbb46..56c40cf 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -8,4 +8,8 @@ export function LoadCurrentBuffer():Promise; export function ProcessText(arg1:main.ProcessTextRequest):Promise; +export function PromptUser(arg1:string,arg2:any):Promise; + export function SaveCurrentBuffer(arg1:string):Promise; + +export function TriggerTextProcess(arg1:string):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index a6ec05f..144d9f3 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -14,6 +14,14 @@ export function ProcessText(arg1) { return window['go']['main']['App']['ProcessText'](arg1); } +export function PromptUser(arg1, arg2) { + return window['go']['main']['App']['PromptUser'](arg1, arg2); +} + export function SaveCurrentBuffer(arg1) { return window['go']['main']['App']['SaveCurrentBuffer'](arg1); } + +export function TriggerTextProcess(arg1) { + return window['go']['main']['App']['TriggerTextProcess'](arg1); +} diff --git a/models.go b/models.go index 3734a75..3b3721a 100644 --- a/models.go +++ b/models.go @@ -25,3 +25,11 @@ type SetStatusbarMessage struct { type ProcessTextResponse struct { Output []TextSpan `json:"output"` } + +type RequestTextProcess struct { + Action string `json:"action"` +} + +type PromptRequest struct { + Label string `json:"label"` +}