Have made some large improvements
All checks were successful
Build / build (push) Successful in 2m48s

- Added support for multiple cursors
- Enabled wrapping
- Added uppercase, lowercase, and lorem ipsum support
- Added support for processing only selected ranges
This commit is contained in:
Leon Mika 2025-09-14 21:58:30 +10:00
parent a047d89dad
commit 3a23118036
7 changed files with 99 additions and 18 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
build
node_modules
frontend/dist
.DS_Store

View file

@ -15,8 +15,11 @@
data-action="keyup.enter->commands#runCommand keydown.esc->commands#dismissDialog keyup->commands#handleKeyup">
</div>
<select multiple class="command-options" data-commands-target="commandSelect">
<option value="format-json"><span class="option-label">JSON: Format</span></option>
<option value="lorem-ipsum"><span class="option-label">Lorem Ipsum: Generate</span></option>
<option value="lower-case"><span class="option-label">Lower Case</span></option>
<option value="unquote"><span class="option-label">Unquote</span></option>
<option value="format-json"><span class="option-label">Format JSON</span></option>
<option value="upper-case"><span class="option-label">Upper Case</span></option>
</select>
</div>
</dialog>

View file

@ -1,5 +1,6 @@
.cm-editor {
height: 100%;
width: 100%;
font-size: 1.1em;
}

40
frontend/src/cmplugins.js Normal file
View file

@ -0,0 +1,40 @@
import {EditorSelection} from "@codemirror/state";
import {keymap} from "@codemirror/view";
function spawnNewCursor(view, forward) {
const { state } = view
const selection = state.selection
const newRanges = []
for (let range of selection.ranges) {
// Keep existing cursor
newRanges.push(range)
newRanges.push(view.moveVertically(range, forward, 1));
}
view.dispatch({
selection: EditorSelection.create(newRanges)
})
return true
}
export const multiCursorKeymap = keymap.of([
{
key: "Ctrl-Alt-ArrowDown", // Control+Option+Down on Mac
run: (view) => spawnNewCursor(view, true),
},
{
key: "Ctrl-Alt-ArrowUp", // Control+Option+Down on Mac
run: (view) => spawnNewCursor(view, false),
}
])
export const commandPalette = keymap.of([{
key: "Cmd-p",
run: () => {
let event = new CustomEvent('dq-showcommands');
window.dispatchEvent(event);
return true;
}
}]);

View file

@ -2,26 +2,22 @@ import './style.css';
import './app.css';
import {EditorView, basicSetup} from "codemirror";
import {keymap} from "@codemirror/view";
import { Application } from "@hotwired/stimulus";
import {Application} from "@hotwired/stimulus";
import {textProcessor} from "./services.js";
import {multiCursorKeymap, commandPalette} from "./cmplugins.js";
import { textProcessor } from "./services.js";
import {CommandsController} from "./controllers/commands_controller.js";
const view = new EditorView({
parent: document.querySelector("#app"),
doc: "",
extensions: [
basicSetup,
keymap.of([{
key: "Cmd-p",
run: () => {
let event = new CustomEvent('dq-showcommands');
window.dispatchEvent(event);
return true;
}
}]),
EditorView.lineWrapping,
multiCursorKeymap,
commandPalette,
]
})

View file

@ -18,11 +18,27 @@ class TextProcessor {
return;
}
let ranges = this._editor.state.selection.ranges;
let shouldBeAll = ranges.reduce((a, r) => a && r.from === r.to, true);
let inputs = [];
if (shouldBeAll) {
inputs.push({
text: this._editor.state.doc.toString(),
pos: 0,
len: this._editor.state.doc.length,
});
} else {
inputs = ranges.map(r => ({
text: this._editor.state.doc.slice(r.from, r.to).toString(),
pos: r.from,
len: r.to - r.from,
}))
}
ProcessText({
action: command,
input: [
{text: this._editor.state.doc.toString(), pos: 0, len: this._editor.state.doc.length}
],
input: inputs,
});
}
}

View file

@ -1,22 +1,46 @@
package main
import (
"bufio"
"bytes"
"encoding/json"
"strconv"
"strings"
)
type TextFilter func(input string) (output string, err error)
var TextFilters = map[string]TextFilter{
"upper-case": func(input string) (output string, err error) {
return strings.ToUpper(input), nil
},
"lower-case": func(input string) (output string, err error) {
return strings.ToLower(input), nil
},
"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
scnr := bufio.NewScanner(strings.NewReader(input))
for scnr.Scan() {
line := scnr.Text()
if err := json.Indent(&dst, []byte(line), "", " "); err == nil {
dst.WriteString("\n")
} else {
return "", err
}
}
return dst.String(), nil
},
"lorem-ipsum": func(input string) (output string, err error) {
return "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor " +
"incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud " +
"exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
"dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. " +
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.", nil
},
}