added codemirror editor
mellbacon committed
May 15, 2023 at 18:33 UTC
d733710aa1e617ecdea91de45b747ddcb6419e2e
9 files changed
+280
-7
package.json
+1
@@ -13,6 +13,7 @@
13
},
14
"dependencies": {
15
"@tauri-apps/api": "^1.2.0",
16
+ "codemirror": "^6.0.1",
17
"sass": "^1.62.0",
18
"sortablejs": "^1.15.0",
19
"svelte-splitpanes": "^0.7.13"
src/App.svelte
+11
-1
@@ -4,7 +4,7 @@
4
import { Pane, Splitpanes } from 'svelte-splitpanes';
5
import SidebarView from "./lib/SidebarView.svelte";
6
import Statusbar from "./lib/Statusbar.svelte";
7
- import EditorTabList from "./lib/EditorTabList.svelte";
7
+ import EditorTabList, {hidden} from "./lib/EditorTabList.svelte";
8
import { onMount } from "svelte";
9
import { loadTheme } from "./config/themehandler";
10
import { appWindow } from '@tauri-apps/api/window';
@@ -68,6 +68,7 @@
68
<Pane>
69
<div id="container">
70
<EditorTabList />
71
+ <div id="tabview" class:hidden={$hidden}></div>
72
</div>
73
</Pane>
74
</Splitpanes>
@@ -84,4 +85,13 @@
85
background-repeat: no-repeat;
86
background-position: center;
87
}
88
+ #tabview {
89
+ width: 100%;
90
+ margin-left: 0.1rem;
91
+ z-index: 1;
92
+ position: absolute;
93
+ }
94
+ .hidden {
95
+ visibility: hidden;
96
+ }
97
</style>
\ No newline at end of file
src/config/themes/dark-theme.json
+6
-1
@@ -33,6 +33,7 @@
33
"foreground": "#ffffff"
34
},
35
"editor": {
36
+ "background": "#171717",
37
"tabContainerBackground": "#2D2D2D",
38
"tabBackground": "#1c1c1c",
39
"tabForeground": "#ffffff",
@@ -41,7 +42,11 @@
42
"tabActiveBackground": "#171717",
43
"tabActiveForeground": "#ffffff",
44
"tabHoverBackground": "2b2b2b",
44
- "tabHoverForeground": "#ffffff"
45
+ "tabHoverForeground": "#ffffff",
46
+ "gutterForeground": "#898989",
47
+ "gutterActiveForeground": "#ffffff",
48
+ "gutterActiveBackground": "#212121",
49
+ "activeLineBackground": "#212121"
50
},
51
"filetree": {
52
"treeNodeBackground": "",
src/lib/Editor.svelte
new
+88
@@ -0,0 +1,88 @@
1
+<script lang="ts">
2
+ import {keymap, highlightSpecialChars, drawSelection, highlightActiveLine, dropCursor,
3
+ rectangularSelection, crosshairCursor,
4
+ lineNumbers, highlightActiveLineGutter, EditorView} from "@codemirror/view"
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"
9
+ import { onMount, tick } from "svelte";
10
+
11
+ let ref;
12
+ let editorView;
13
+ export let hidden = false;
14
+ export let content = "";
15
+
16
+ onMount(() => {
17
+ editorView = new EditorView({
18
+ parent: ref,
19
+ state: EditorState.create({
20
+ extensions: [
21
+ lineNumbers(),
22
+ highlightActiveLineGutter(),
23
+ highlightSpecialChars(),
24
+ highlightActiveLine(),
25
+ dropCursor(),
26
+ history(),
27
+ drawSelection(),
28
+ crosshairCursor(),
29
+ rectangularSelection(),
30
+ keymap.of([indentWithTab]),
31
+ EditorState.allowMultipleSelections.of(true),
32
+ syntaxHighlighting(defaultHighlightStyle, {fallback: true}),
33
+ keymap.of([
34
+ ...defaultKeymap,
35
+ ...historyKeymap,
36
+ ...searchKeymap,
37
+ ])
38
+ ],
39
+ doc: content
40
+ })
41
+ })
42
+ });
43
+</script>
44
+
45
+<div bind:this={ref} class="editor" class:hidden></div>
46
+
47
+<style lang="scss">
48
+ .editor {
49
+ height: 100%;
50
+ width: 100%;
51
+ }
52
+ .hidden {
53
+ display: none;
54
+ }
55
+ :global(.cm-editor:focus),
56
+ :global(.cm-focused) {
57
+ outline: none !important;
58
+ }
59
+ :global(.cm-editor),
60
+ :global(.cm-wrap) {
61
+ cursor: text;
62
+ height: 100%;
63
+ }
64
+ :global(.cm-scroller) {
65
+ font-size: 14px !important;
66
+ line-height: 1.3;
67
+ overflow-y: overlay;
68
+ overflow-x: overlay !important;
69
+ padding-top: 3px;
70
+ &::-webkit-scrollbar {
71
+ width: 5px;
72
+ height: 5px;
73
+ }
74
+ &::-webkit-scrollbar-thumb {
75
+ border-radius: 20px;
76
+ }
77
+ &::-webkit-scrollbar-corner {
78
+ background-color: transparent;
79
+ }
80
+ }
81
+ :global(.cm-content) {
82
+ padding: 0 !important;
83
+ }
84
+ :global(.cm-lineNumbers), :global(.cm-gutterElement) {
85
+ min-width: 50px !important;
86
+ text-align: center !important;
87
+ }
88
+</style>
\ No newline at end of file
src/lib/EditorTabList.svelte
+4
-1
@@ -34,11 +34,14 @@
34
export function addTab(path?: string, label?: string) {
35
editorTab.addTab(path, label);
36
}
37
+ export function addEditorTab(path?: string, label?: string) {
38
+ editorTab.addEditorTab(path, label);
39
+ }
40
export function closeTab(tabid: number) {
41
editorTab.closeTab(tabid);
42
}
43
41
- let hidden = editorTab.hidden;
44
+ export let hidden = editorTab.hidden;
45
let tabs = editorTab.tabs;
46
</script>
47
<div id="editor-tabs" class:hidden={$hidden}>
src/lib/Header.svelte
+2
-2
@@ -2,11 +2,11 @@
2
import { appWindow } from "@tauri-apps/api/window";
3
import Dropdown from "./utility/Dropdown.svelte";
4
import Settings from "carbon-icons-svelte/lib/Settings.svelte";
5
- import { addTab } from "../lib/EditorTabList.svelte";
5
+ import { addTab, addEditorTab } from "../lib/EditorTabList.svelte";
6
7
const items = [
8
{menuname: "File", children: [
9
- {name: "New File", shortcut: "Ctrl + N", action: () => {addTab()}},
9
+ {name: "New File", shortcut: "Ctrl + N", action: () => {addEditorTab()}},
10
{name: "Open File...", shortcut: "Ctrl + O", action: () => {console.log("click")}},
11
{name: "Save File", shortcut: "Ctrl + S", action: () => {console.log("click")}},
12
{name: "Save File As...", shortcut: "Ctrl + Shift + S", action: () => {console.log("click")}},
src/lib/Tab/Tab.ts
+23
-2
@@ -1,4 +1,5 @@
1
import { writable } from "svelte/store";
2
+import Editor from "../Editor.svelte";
3
4
export class Tab {
5
id = 0;
@@ -22,6 +23,7 @@ export class Tab {
23
}
24
}
25
this.tabs.set(this.tablist);
26
+ this.updateView();
27
}
28
updateTabs() {
29
if (this.tablist.length === 0) {
@@ -58,6 +60,20 @@ export class Tab {
60
61
this.updateTabs();
62
}
63
+ addEditorTab(path: string, label: string = "") {
64
+ if (this.tabOpen(path)) {
65
+ return;
66
+ }
67
+ let content = new Editor({target: document.getElementById("tabview"), props: {content: ""}});
68
+
69
+ let tab = new this.Tab(this.id, label, content, path);
70
+ tab.isfile = true;
71
+ this.tablist = [...this.tablist, tab];
72
+
73
+ this.updateView();
74
+
75
+ this.updateTabs();
76
+ }
77
closeTab(tabid: number) {
78
if (this.activeid === tabid) {
79
for (let i = 0; i <= this.tablist.length - 1; i++) {
@@ -74,7 +90,7 @@ export class Tab {
90
}
91
}
92
77
- //tablist.find(t => t.id === tabid).content.$destroy();
93
+ this.tablist.find(t => t.id === tabid).content.$destroy();
94
this.tablist = this.tablist.filter(t => t.id !== tabid);
95
this.tabs.set(this.tablist);
96
@@ -83,9 +99,14 @@ export class Tab {
99
this.id = 0;
100
}
101
}
86
- CloseAllTabs() {
102
+ closeAllTabs() {
103
for (const tab of this.tablist) {
104
this.closeTab(tab.id);
105
}
106
}
107
+ updateView() {
108
+ for (let tab of this.tablist) {
109
+ tab.updateView(this.activeid);
110
+ }
111
+ }
112
}
src/theme.scss
+34
@@ -36,6 +36,13 @@ $tab-container-height: 2rem;
36
--editor-tabHoverBackground: #2b2b2b;
37
--editor-tabHoverForeground: #ffffff;
38
39
+ --editor-background: #171717;
40
+ --editor-gutter-foreground: #898989;
41
+ --editor-gutter-activeForeground: #ffffff;
42
+ --editor-gutter-activeBackground: #212121;
43
+ --editor-activeLineBackground: #212121;
44
+
45
+
46
--filetree-treeNodeBackground: transparent;
47
--filetree-treeNodeForeground: #808080;
48
--filetree-treeNodeHoverBackground: #353535;
@@ -147,6 +154,33 @@ html {
154
}
155
}
156
157
+#tabview {
158
+ margin-top: calc($tab-container-height + 5px);
159
+ height: calc(100% - 6.1rem + 0.1rem);
160
+}
161
+
162
+.cm-activeLine {
163
+ background-color: var(--editor-activeLineBackground) !important;
164
+}
165
+.cm-gutters {
166
+ background-color: var(--editor-background) !important;
167
+ color: var(--editor-gutter-foreground);
168
+ border: none !important;
169
+}
170
+.cm-activeLineGutter {
171
+ color: var(--editor-gutter-activeForeground) !important;
172
+ background-color: var(--editor-gutter-activeBackground) !important;
173
+}
174
+.cm-scroller {
175
+ background-color: var(--editor-background);
176
+}
177
+.cm-cursor {
178
+ border-left-color: var(--window-foreground) !important;
179
+}
180
+.ͼ4 .cm-line::selection {
181
+ background-color: #4d5054 !important;
182
+}
183
+
184
#statusbar {
185
box-shadow: 0px -1px 0 0px var(--window-borderColor);
186
height: calc($statusbar-height + 0.1rem);
yarn.lock
+111
@@ -2,6 +2,70 @@
2
# yarn lockfile v1
3
4
5
+"@codemirror/autocomplete@^6.0.0":
6
+ version "6.7.1"
7
+ resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz#3364799b78dff70fb8f81615536c52ea53ce40b2"
8
+ integrity sha512-hSxf9S0uB+GV+gBsjY1FZNo53e1FFdzPceRfCfD1gWOnV6o21GfB5J5Wg9G/4h76XZMPrF0A6OCK/Rz5+V1egg==
9
+ dependencies:
10
+ "@codemirror/language" "^6.0.0"
11
+ "@codemirror/state" "^6.0.0"
12
+ "@codemirror/view" "^6.6.0"
13
+ "@lezer/common" "^1.0.0"
14
+
15
+"@codemirror/commands@^6.0.0":
16
+ version "6.2.4"
17
+ resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec"
18
+ integrity sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==
19
+ dependencies:
20
+ "@codemirror/language" "^6.0.0"
21
+ "@codemirror/state" "^6.2.0"
22
+ "@codemirror/view" "^6.0.0"
23
+ "@lezer/common" "^1.0.0"
24
+
25
+"@codemirror/language@^6.0.0":
26
+ version "6.6.0"
27
+ resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.6.0.tgz#2204407174a38a68053715c19e28ad61f491779f"
28
+ integrity sha512-cwUd6lzt3MfNYOobdjf14ZkLbJcnv4WtndYaoBkbor/vF+rCNguMPK0IRtvZJG4dsWiaWPcK8x1VijhvSxnstg==
29
+ dependencies:
30
+ "@codemirror/state" "^6.0.0"
31
+ "@codemirror/view" "^6.0.0"
32
+ "@lezer/common" "^1.0.0"
33
+ "@lezer/highlight" "^1.0.0"
34
+ "@lezer/lr" "^1.0.0"
35
+ style-mod "^4.0.0"
36
+
37
+"@codemirror/lint@^6.0.0":
38
+ version "6.2.1"
39
+ resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.2.1.tgz#654581d8cc293c315ecfa5c9d61d78c52bbd9ccd"
40
+ integrity sha512-y1muai5U/uUPAGRyHMx9mHuHLypPcHWxzlZGknp/U5Mdb5Ol8Q5ZLp67UqyTbNFJJ3unVxZ8iX3g1fMN79S1JQ==
41
+ dependencies:
42
+ "@codemirror/state" "^6.0.0"
43
+ "@codemirror/view" "^6.0.0"
44
+ crelt "^1.0.5"
45
+
46
+"@codemirror/search@^6.0.0":
47
+ version "6.4.0"
48
+ resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.4.0.tgz#2b256a9e0eaa9317fb48e3cc81eb2735360a59b4"
49
+ integrity sha512-zMDgaBXah+nMLK2dHz9GdCnGbQu+oaGRXS1qviqNZkvOCv/whp5XZFyoikLp/23PM9RBcbuKUUISUmQHM1eRHw==
50
+ dependencies:
51
+ "@codemirror/state" "^6.0.0"
52
+ "@codemirror/view" "^6.0.0"
53
+ crelt "^1.0.5"
54
+
55
+"@codemirror/state@^6.0.0", "@codemirror/state@^6.1.4", "@codemirror/state@^6.2.0":
56
+ version "6.2.0"
57
+ resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2"
58
+ integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==
59
+
60
+"@codemirror/view@^6.0.0", "@codemirror/view@^6.6.0":
61
+ version "6.11.2"
62
+ resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.11.2.tgz#964a746119e6d07c75fddecaf90cb463ccf59f71"
63
+ integrity sha512-AzxJ9Aub6ubBvoPBGvjcd4zITqcBBiLpJ89z0ZjnphOHncbvUvQcb9/WMVGpuwTT95+jW4knkH6gFIy0oLdaUQ==
64
+ dependencies:
65
+ "@codemirror/state" "^6.1.4"
66
+ style-mod "^4.0.0"
67
+ w3c-keyname "^2.2.4"
68
+
69
"@esbuild/android-arm64@0.17.17":
70
version "0.17.17"
71
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz#164b054d58551f8856285f386e1a8f45d9ba3a31"
@@ -135,6 +199,25 @@
199
"@jridgewell/resolve-uri" "3.1.0"
200
"@jridgewell/sourcemap-codec" "1.4.14"
201
202
+"@lezer/common@^1.0.0":
203
+ version "1.0.2"
204
+ resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.0.2.tgz#8fb9b86bdaa2ece57e7d59e5ffbcb37d71815087"
205
+ integrity sha512-SVgiGtMnMnW3ActR8SXgsDhw7a0w0ChHSYAyAUxxrOiJ1OqYWEKk/xJd84tTSPo1mo6DXLObAJALNnd0Hrv7Ng==
206
+
207
+"@lezer/highlight@^1.0.0":
208
+ version "1.1.4"
209
+ resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.1.4.tgz#98ed821e89f72981b7ba590474e6ee86c8185619"
210
+ integrity sha512-IECkFmw2l7sFcYXrV8iT9GeY4W0fU4CxX0WMwhmhMIVjoDdD1Hr6q3G2NqVtLg/yVe5n7i4menG3tJ2r4eCrPQ==
211
+ dependencies:
212
+ "@lezer/common" "^1.0.0"
213
+
214
+"@lezer/lr@^1.0.0":
215
+ version "1.3.4"
216
+ resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.3.4.tgz#8795bf2ba4f69b998e8fb4b5a7c57ea68753474c"
217
+ integrity sha512-7o+e4og/QoC/6btozDPJqnzBhUaD1fMfmvnEKQO1wRRiTse1WxaJ3OMEXZJnkgT6HCcTVOctSoXK9jGJw2oe9g==
218
+ dependencies:
219
+ "@lezer/common" "^1.0.0"
220
+
221
"@nodelib/fs.scandir@2.1.5":
222
version "2.1.5"
223
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@@ -311,11 +394,29 @@ carbon-icons-svelte@^11.4.0:
394
optionalDependencies:
395
fsevents "~2.3.2"
396
397
+codemirror@^6.0.1:
398
+ version "6.0.1"
399
+ resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29"
400
+ integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==
401
+ dependencies:
402
+ "@codemirror/autocomplete" "^6.0.0"
403
+ "@codemirror/commands" "^6.0.0"
404
+ "@codemirror/language" "^6.0.0"
405
+ "@codemirror/lint" "^6.0.0"
406
+ "@codemirror/search" "^6.0.0"
407
+ "@codemirror/state" "^6.0.0"
408
+ "@codemirror/view" "^6.0.0"
409
+
410
concat-map@0.0.1:
411
version "0.0.1"
412
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
413
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
414
415
+crelt@^1.0.5:
416
+ version "1.0.5"
417
+ resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.5.tgz#57c0d52af8c859e354bace1883eb2e1eb182bb94"
418
+ integrity sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==
419
+
420
debug@^4.3.4:
421
version "4.3.4"
422
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
@@ -735,6 +836,11 @@ strip-indent@^3.0.0:
836
dependencies:
837
min-indent "^1.0.0"
838
839
+style-mod@^4.0.0:
840
+ version "4.0.3"
841
+ resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad"
842
+ integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==
843
+
844
supports-preserve-symlinks-flag@^1.0.0:
845
version "1.0.0"
846
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
@@ -816,6 +922,11 @@ vitefu@^0.2.4:
922
resolved "https://registry.yarnpkg.com/vitefu/-/vitefu-0.2.4.tgz#212dc1a9d0254afe65e579351bed4e25d81e0b35"
923
integrity sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==
924
925
+w3c-keyname@^2.2.4:
926
+ version "2.2.6"
927
+ resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.6.tgz#8412046116bc16c5d73d4e612053ea10a189c85f"
928
+ integrity sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==
929
+
930
wrappy@1:
931
version "1.0.2"
932
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"