@setoelkahfi / svara / commits / 40d0f24

feat!: added functioning commands for most shortcuts

mellbacon committed Jul 14, 2023 at 14:53 UTC 40d0f24f11330a66425f9ab5f3c641e52442b7e6
2 files changed +101 -27
src/config/commands.ts
+21 -14
@@ -1,3 +1,4 @@
1 +import { append, copy, cut, deleteChars, redoChange, undoChange } from "../lib/Editor.svelte";
2 import { addEditorTab } from "../lib/EditorTabList.svelte";
3 import { saveFile, openFile, openFolder } from "../lib/File";
4 import { appWindow } from "@tauri-apps/api/window";
@@ -35,32 +36,33 @@ export const commands = {
36 },
37 "undo": {
38 "keybind": "Control+Z",
38 - "command": () => {
39 - console.warn("Feature not implemented yet.")
39 + "command": async () => {
40 + await undoChange();
41 }
42 },
43 "redo": {
44 "keybind": "Control+Shift+Z",
44 - "command": () => {
45 - console.warn("Feature not implemented yet.")
45 + "command": async () => {
46 + await redoChange();
47 }
48 },
49 "cut": {
50 "keybind": "Control+X",
50 - "command": () => {
51 - console.warn("Feature not implemented yet.")
51 + "command": async () => {
52 + await cut();
53 }
54 },
55 "copy": {
56 "keybind": "Control+C",
56 - "command": () => {
57 - console.warn("Feature not implemented yet.")
57 + "command": async () => {
58 + await copy();
59 }
60 },
61 "paste": {
62 "keybind": "Control+V",
62 - "command": () => {
63 - console.warn("Feature not implemented yet.")
63 + "command": async () => {
64 + const content = await navigator.clipboard.readText();
65 + append(content);
66 }
67 },
68 "pasteFromHistory": {
@@ -71,8 +73,8 @@ export const commands = {
73 },
74 "delete": {
75 "keybind": "Delete",
74 - "command": () => {
75 - console.warn("Feature not implemented yet.")
76 + "command": async () => {
77 + await deleteChars();
78 }
79 },
80 "find": {
@@ -107,8 +109,13 @@ export const commands = {
109 },
110 "fullscreen": {
111 "keybind": "F11",
110 - "command": () => {
111 - console.warn("Feature not implemented yet.")
112 + "command": async () => {
113 + if (await appWindow.isFullscreen()) {
114 + appWindow.setFullscreen(false);
115 + }
116 + else {
117 + appWindow.setFullscreen(true);
118 + }
119 }
120 },
121 "runFile": {
src/lib/Editor.svelte
+80 -13
@@ -2,14 +2,14 @@
2 import {keymap, highlightSpecialChars, drawSelection, highlightActiveLine, dropCursor,
3 rectangularSelection, crosshairCursor,
4 lineNumbers, highlightActiveLineGutter, EditorView} from "@codemirror/view"
5 - import {EditorState } from "@codemirror/state"
5 + import {EditorState} from "@codemirror/state"
6 import {defaultHighlightStyle, syntaxHighlighting} from "@codemirror/language"
7 - import {defaultKeymap, history, historyKeymap, indentWithTab} from "@codemirror/commands"
8 - import {searchKeymap} from "@codemirror/search"
7 + import {defaultKeymap, history, indentWithTab, undo, redo, deleteCharForward, deleteToLineEnd} from "@codemirror/commands";
8 import { onMount, tick } from "svelte";
9 import { writable } from "svelte/store";
10 import { saveFile, updateSaveState } from "./File";
11 import { appSettings } from "../config/config";
12 + import { getCurrentEditor } from "./EditorTabList.svelte";
13
14 let ref;
15 let editorView: EditorView;
@@ -35,8 +35,27 @@
35 export function getLang(ext) {
36 return getLangFromExt(ext);
37 }
38 + export function getView() {
39 + return editorView;
40 + }
41
42 onMount(async () => {
43 + // disable default copy/paste/delete keys
44 + // instead implement our own functions for copy/paste/delete so it can be bound to different keybindings
45 + const disabledKeys = [
46 + {
47 + key: "Ctrl-v",
48 + preventDefault: true
49 + },
50 + {
51 + key: "Ctrl-c",
52 + preventDefault: true
53 + },
54 + {
55 + key: "Delete",
56 + preventDefault: true
57 + }
58 + ]
59 editorView = new EditorView({
60 parent: ref,
61 state: EditorState.create({
@@ -54,9 +73,8 @@
73 EditorState.allowMultipleSelections.of(true),
74 syntaxHighlighting(defaultHighlightStyle, {fallback: true}),
75 keymap.of([
57 - ...defaultKeymap,
58 - ...historyKeymap,
59 - ...searchKeymap,
76 + ...disabledKeys,
77 + ...defaultKeymap
78 ])
79 ],
80 doc: content
@@ -67,9 +85,9 @@
85 });
86
87 let _ = null;
70 - async function updateContent() {
88 + export async function updateContent() {
89 await tick();
72 - content = editorView.state.doc.toString();1
90 + content = editorView.state.doc.toString();
91 if (await appSettings.get("editor.autosave") === true) {
92 clearTimeout(_);
93 _ = setTimeout(async () => {
@@ -94,7 +112,7 @@
112 updateLineInfo();
113 language.set($file_info.language);
114 }
97 - function updateLineInfo() {
115 + export function updateLineInfo() {
116 let lineNumber = editorView.state.doc.lineAt(editorView.state.selection.main.head).number;
117 let columnNumber = editorView.state.selection.ranges[0].head - editorView.state.doc.lineAt(editorView.state.selection.main.head).from;
118 line_info.set({line: lineNumber.toString(), column: (columnNumber + 1).toString()})
@@ -131,12 +149,61 @@
149 }
150 }
151 export function setEditorFontSize(value: number) {
134 - const editorContainer = document.querySelector(".cm-scroller") as HTMLElement;
135 - editorContainer.style.setProperty("font-size", `${value}px`, "important")
152 + // there could be a better way to do all this but. eh
153 + const editors = document.querySelectorAll(".cm-scroller");
154 + for (const editorContainer of editors) {
155 + (editorContainer as HTMLElement).style.setProperty("font-size", `${value}px`, "important")
156 + }
157 }
158 export function setEditorFontFamily(family: string) {
138 - const editorContainer = document.querySelector(".cm-scroller") as HTMLElement;
139 - editorContainer.style.setProperty("font-family", family, "important");
159 + const editors = document.querySelectorAll(".cm-scroller");
160 + for (const editorContainer of editors) {
161 + (editorContainer as HTMLElement).style.setProperty("font-family", family, "important")
162 + }
163 + }
164 +
165 + // yes im aware how messy all these functions are but it works!
166 + export async function append(value: string) {
167 + let cursorpos = getCurrentEditor().getView().state.selection.main.head + value.length;
168 + const lines = value.split("\n").length - 1;
169 + if (lines > 0) {
170 + cursorpos -= lines;
171 + }
172 + getCurrentEditor().getView().dispatch({
173 + changes: {
174 + from: getCurrentEditor().getView().state.selection.ranges[0].from,
175 + to: getCurrentEditor().getView().state.selection.ranges[0].to,
176 + insert: value,
177 + },
178 + selection: {anchor: cursorpos, head: cursorpos},
179 + scrollIntoView: true
180 + })
181 + await getCurrentEditor().updateContent();
182 + getCurrentEditor().updateLineInfo();
183 + }
184 + export async function copy() {
185 + const selection = getCurrentEditor().getView().state.sliceDoc(getCurrentEditor().getView().state.selection.main.from, getCurrentEditor().getView().state.selection.main.to)
186 + await navigator.clipboard.writeText(selection);
187 + }
188 + export async function cut() {
189 + deleteToLineEnd(getCurrentEditor().getView())
190 + await getCurrentEditor().updateContent();
191 + getCurrentEditor().updateLineInfo();
192 + }
193 + export async function undoChange() {
194 + undo(getCurrentEditor().getView());
195 + await getCurrentEditor().updateContent();
196 + getCurrentEditor().updateLineInfo();
197 + }
198 + export async function redoChange() {
199 + redo(getCurrentEditor().getView());
200 + await getCurrentEditor().updateContent();
201 + getCurrentEditor().updateLineInfo();
202 + }
203 + export async function deleteChars() {
204 + deleteCharForward(getCurrentEditor().getView());
205 + await getCurrentEditor().updateContent();
206 + getCurrentEditor().updateLineInfo();
207 }
208 </script>
209