Have made some large improvements
All checks were successful
Build / build (push) Successful in 2m48s
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:
parent
a047d89dad
commit
3a23118036
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
build
|
build
|
||||||
node_modules
|
node_modules
|
||||||
frontend/dist
|
frontend/dist
|
||||||
|
.DS_Store
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
data-action="keyup.enter->commands#runCommand keydown.esc->commands#dismissDialog keyup->commands#handleKeyup">
|
data-action="keyup.enter->commands#runCommand keydown.esc->commands#dismissDialog keyup->commands#handleKeyup">
|
||||||
</div>
|
</div>
|
||||||
<select multiple class="command-options" data-commands-target="commandSelect">
|
<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="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>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
.cm-editor {
|
.cm-editor {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
40
frontend/src/cmplugins.js
Normal file
40
frontend/src/cmplugins.js
Normal 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;
|
||||||
|
}
|
||||||
|
}]);
|
|
@ -2,26 +2,22 @@ import './style.css';
|
||||||
import './app.css';
|
import './app.css';
|
||||||
|
|
||||||
import {EditorView, basicSetup} from "codemirror";
|
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";
|
import {CommandsController} from "./controllers/commands_controller.js";
|
||||||
|
|
||||||
|
|
||||||
const view = new EditorView({
|
const view = new EditorView({
|
||||||
parent: document.querySelector("#app"),
|
parent: document.querySelector("#app"),
|
||||||
doc: "",
|
doc: "",
|
||||||
extensions: [
|
extensions: [
|
||||||
basicSetup,
|
basicSetup,
|
||||||
keymap.of([{
|
EditorView.lineWrapping,
|
||||||
key: "Cmd-p",
|
multiCursorKeymap,
|
||||||
run: () => {
|
commandPalette,
|
||||||
let event = new CustomEvent('dq-showcommands');
|
|
||||||
window.dispatchEvent(event);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}]),
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,27 @@ class TextProcessor {
|
||||||
return;
|
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({
|
ProcessText({
|
||||||
action: command,
|
action: command,
|
||||||
input: [
|
input: inputs,
|
||||||
{text: this._editor.state.doc.toString(), pos: 0, len: this._editor.state.doc.length}
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,46 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TextFilter func(input string) (output string, err error)
|
type TextFilter func(input string) (output string, err error)
|
||||||
|
|
||||||
var TextFilters = map[string]TextFilter{
|
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) {
|
"unquote": func(input string) (output string, err error) {
|
||||||
return strconv.Unquote(input)
|
return strconv.Unquote(input)
|
||||||
},
|
},
|
||||||
"format-json": func(input string) (output string, err error) {
|
"format-json": func(input string) (output string, err error) {
|
||||||
var dst bytes.Buffer
|
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
|
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
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue