diff --git a/app.go b/app.go index af53038..fefa3b8 100644 --- a/app.go +++ b/app.go @@ -2,7 +2,10 @@ package main import ( "context" - "fmt" + "log" + + "github.com/wailsapp/wails/v2/pkg/runtime" + "lmika.dev/pkg/modash/moslice" ) // App struct @@ -22,6 +25,30 @@ func (a *App) startup(ctx context.Context) { } // Greet returns a greeting for the given name -func (a *App) Greet(name string) string { - return fmt.Sprintf("Hello %s, It's show time!", name) +func (a *App) ProcessText(req ProcessTextRequest) { + filter, ok := TextFilters[req.Action] + if !ok { + log.Printf("Unknown filter: [%s]", req.Action) + return + } + + resp, err := moslice.MapWithError(req.Input, func(span TextSpan) (TextSpan, error) { + outStr, err := filter(span.Text) + if err != nil { + return TextSpan{}, err + } + return TextSpan{ + Text: outStr, + Pos: span.Pos, + Len: span.Len, + }, nil + }) + if err != nil { + log.Printf("Error running filter: %s", err) + return + } + + runtime.EventsEmit(a.ctx, "process-text-response", ProcessTextResponse{ + Output: resp, + }) } diff --git a/frontend/index.html b/frontend/index.html index 2aee517..4860015 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -15,10 +15,8 @@ data-action="keyup.enter->commands#runCommand keydown.esc->commands#dismissDialog keyup->commands#handleKeyup"> diff --git a/frontend/src/app.css b/frontend/src/app.css index 4648b40..d73015f 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,5 +1,6 @@ .cm-editor { height: 100%; + font-size: 1.1em; } dialog#command-dialog { diff --git a/frontend/src/controllers/commands_controller.js b/frontend/src/controllers/commands_controller.js index b79cf9a..5a04574 100644 --- a/frontend/src/controllers/commands_controller.js +++ b/frontend/src/controllers/commands_controller.js @@ -1,6 +1,8 @@ import { Controller } from "@hotwired/stimulus" -export default class extends Controller { +import { textProcessor } from "../services.js"; + +export class CommandsController extends Controller { static targets = [ "commandInput", "commandSelect", @@ -30,7 +32,7 @@ export default class extends Controller { runCommand(ev) { ev.preventDefault(); - console.log("Do this: " + this.commandSelectTarget.value); + textProcessor.runTextCommand(this.commandSelectTarget.value); this.element.close(); } @@ -49,4 +51,4 @@ export default class extends Controller { this.commandSelectTarget.selectedIndex = 0; } } -} \ No newline at end of file +} diff --git a/frontend/src/main.js b/frontend/src/main.js index 332dbb0..6ca66d9 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -5,7 +5,8 @@ import {EditorView, basicSetup} from "codemirror"; import {keymap} from "@codemirror/view"; import { Application } from "@hotwired/stimulus"; -import CommandsController from "./controllers/commands_controller.js"; +import { textProcessor } from "./services.js"; +import {CommandsController} from "./controllers/commands_controller.js"; const view = new EditorView({ parent: document.querySelector("#app"), @@ -27,4 +28,6 @@ const view = new EditorView({ window.Stimulus = Application.start() Stimulus.register("commands", CommandsController); +textProcessor.setCodeMirrorEditor(view); + view.focus(); \ No newline at end of file diff --git a/frontend/src/services.js b/frontend/src/services.js new file mode 100644 index 0000000..60981c7 --- /dev/null +++ b/frontend/src/services.js @@ -0,0 +1,31 @@ +import {ProcessText} from "../wailsjs/go/main/App"; + +class TextProcessor { + setCodeMirrorEditor(editor) { + this._editor = editor; + window.runtime.EventsOn("process-text-response", (data) => { + const changes = data.output.map(span => ({ + from: span.pos, + to: span.pos + span.len, + insert: span.text, + })); + this._editor.dispatch({ changes: changes }); + }); + } + + runTextCommand(command) { + if (this._editor === undefined) { + return; + } + + ProcessText({ + action: command, + input: [ + {text: this._editor.state.doc.toString(), pos: 0, len: this._editor.state.doc.length} + ], + }); + } +} + + +export const textProcessor = new TextProcessor(); \ No newline at end of file diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 02a3bb9..a164699 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -1,4 +1,5 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +import {main} from '../models'; -export function Greet(arg1:string):Promise; +export function ProcessText(arg1:main.ProcessTextRequest):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index c71ae77..b8eff0c 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,6 +2,6 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -export function Greet(arg1) { - return window['go']['main']['App']['Greet'](arg1); +export function ProcessText(arg1) { + return window['go']['main']['App']['ProcessText'](arg1); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts new file mode 100755 index 0000000..0315b64 --- /dev/null +++ b/frontend/wailsjs/go/models.ts @@ -0,0 +1,53 @@ +export namespace main { + + export class TextSpan { + text: string; + pos: number; + len: number; + + static createFrom(source: any = {}) { + return new TextSpan(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.text = source["text"]; + this.pos = source["pos"]; + this.len = source["len"]; + } + } + export class ProcessTextRequest { + action: string; + input: TextSpan[]; + + static createFrom(source: any = {}) { + return new ProcessTextRequest(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.action = source["action"]; + this.input = this.convertValues(source["input"], TextSpan); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + +} + diff --git a/go.mod b/go.mod index 2cee520..9d0b5a4 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,13 @@ module dequoter -go 1.23 +go 1.23.3 -require github.com/wailsapp/wails/v2 v2.10.2 +toolchain go1.24.3 + +require ( + github.com/wailsapp/wails/v2 v2.10.2 + lmika.dev/pkg/modash v0.0.0-20250729120720-cdaa1c8abbe3 +) require ( github.com/bep/debounce v1.2.1 // indirect diff --git a/go.sum b/go.sum index b1e0229..ea6cc63 100644 --- a/go.sum +++ b/go.sum @@ -79,3 +79,5 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +lmika.dev/pkg/modash v0.0.0-20250729120720-cdaa1c8abbe3 h1:EqYZdM6ui++F2NPdFCjKAboOr14eVTIIiRfngBgg/WA= +lmika.dev/pkg/modash v0.0.0-20250729120720-cdaa1c8abbe3/go.mod h1:8NDl/yR1eCCEhip9FJlVuMNXIeaztQ0Ks/tizExFcTI= diff --git a/main.go b/main.go index e34cc71..3a8563f 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,7 @@ func main() { // Create application with options err := wails.Run(&options.App{ - Title: "dequoter", + Title: "Dequoter", Width: 1024, Height: 768, AssetServer: &assetserver.Options{ diff --git a/models.go b/models.go new file mode 100644 index 0000000..06f33cf --- /dev/null +++ b/models.go @@ -0,0 +1,16 @@ +package main + +type TextSpan struct { + Text string `json:"text"` + Pos int `json:"pos"` + Len int `json:"len"` +} + +type ProcessTextRequest struct { + Action string `json:"action"` + Input []TextSpan `json:"input"` +} + +type ProcessTextResponse struct { + Output []TextSpan `json:"output"` +} diff --git a/textfilters.go b/textfilters.go new file mode 100644 index 0000000..ce70201 --- /dev/null +++ b/textfilters.go @@ -0,0 +1,22 @@ +package main + +import ( + "bytes" + "encoding/json" + "strconv" +) + +type TextFilter func(input string) (output string, err error) + +var TextFilters = map[string]TextFilter{ + "unquote": func(input string) (output string, err error) { + return strconv.Unquote(input) + }, + "format-json": func(input string) (output string, err error) { + var dst bytes.Buffer + if err := json.Indent(&dst, []byte(input), "", " "); err != nil { + return "", err + } + return dst.String(), nil + }, +}