Create Displayable interface, fix file save-as
This commit is contained in:
parent
55aac46630
commit
50ba297473
|
|
@ -1,9 +1,4 @@
|
|||
import {
|
||||
Transaction,
|
||||
StateEffect,
|
||||
Compartment,
|
||||
Extension,
|
||||
} from "@codemirror/state";
|
||||
import { Transaction, Compartment, Extension } from "@codemirror/state";
|
||||
import {
|
||||
EditorView,
|
||||
keymap,
|
||||
|
|
@ -27,8 +22,10 @@ import {
|
|||
} from "@codemirror/language";
|
||||
import { languages } from "@codemirror/language-data";
|
||||
import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
|
||||
import van from "vanjs-core";
|
||||
|
||||
import { OpenFile } from "./filestate";
|
||||
import { Displayable } from "./editorgrid";
|
||||
|
||||
const fixedHeightEditor = EditorView.theme({
|
||||
"&": {
|
||||
|
|
@ -44,12 +41,13 @@ const fixedHeightEditor = EditorView.theme({
|
|||
".cm-scroller": { overflow: "auto scroll" },
|
||||
});
|
||||
|
||||
export class Editor {
|
||||
export class Editor implements Displayable {
|
||||
view: EditorView;
|
||||
file: OpenFile;
|
||||
deleteFn?: () => void;
|
||||
|
||||
private wordWrapCompartment = new Compartment();
|
||||
private languageCompartment = new Compartment();
|
||||
|
||||
dispatch(tr: Transaction, inhibitSync = false) {
|
||||
this.view.update([tr]);
|
||||
|
|
@ -95,6 +93,7 @@ export class Editor {
|
|||
fixedHeightEditor,
|
||||
kmap,
|
||||
this.wordWrapCompartment.of(EditorView.lineWrapping),
|
||||
this.languageCompartment.of([]),
|
||||
lineNumbers(),
|
||||
highlightSpecialChars(),
|
||||
foldGutter(),
|
||||
|
|
@ -113,12 +112,16 @@ export class Editor {
|
|||
// lintKeymap,
|
||||
],
|
||||
});
|
||||
LanguageDescription.matchFilename(languages, file.filePath.val)
|
||||
?.load()
|
||||
.then((Lang) => {
|
||||
const eff = StateEffect.appendConfig.of(Lang);
|
||||
this.view.dispatch({ effects: [eff] });
|
||||
});
|
||||
|
||||
van.derive(() => {
|
||||
LanguageDescription.matchFilename(languages, file.filePath.val)
|
||||
?.load()
|
||||
.then((Lang) => {
|
||||
// const eff = StateEffect.appendConfig.of(Lang);
|
||||
const eff = this.languageCompartment.reconfigure(Lang);
|
||||
this.view.dispatch({ effects: [eff] });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get dom() {
|
||||
|
|
@ -130,9 +133,13 @@ export class Editor {
|
|||
this.view.focus();
|
||||
}
|
||||
|
||||
title(): string {
|
||||
return this.file.filePath.val + (this.file.isDirty() ? "*" : "");
|
||||
}
|
||||
|
||||
changeWidth(increment: number) {
|
||||
const w = parseInt(window.getComputedStyle(this.view.dom).width, 10);
|
||||
this.view.dom.style.width = (w + increment) + 'px';
|
||||
this.view.dom.style.width = w + increment + "px";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,18 @@ import { OpenFile } from "./filestate";
|
|||
import * as u from "./utils";
|
||||
import { Editor } from "./editor";
|
||||
|
||||
const EditorWrapper = (editor: State<Editor>, del: () => void, k: number) => {
|
||||
export interface Displayable {
|
||||
setDeleteFunction(del: () => void): void;
|
||||
title(): string;
|
||||
close(): void;
|
||||
dom: HTMLElement;
|
||||
}
|
||||
|
||||
const EditorWrapper = (
|
||||
editor: State<Displayable>,
|
||||
del: () => void,
|
||||
k: number,
|
||||
) => {
|
||||
// Set the delete function on the editor when it's created
|
||||
van.derive(() => {
|
||||
if (editor.val) {
|
||||
|
|
@ -18,12 +29,7 @@ const EditorWrapper = (editor: State<Editor>, del: () => void, k: number) => {
|
|||
{ class: "flex flex-col" },
|
||||
v.div(
|
||||
{ class: "flex" },
|
||||
v.span(
|
||||
{ class: "mx-1 flex-1" },
|
||||
() =>
|
||||
editor.val.file.filePath.val +
|
||||
(editor.val.file.isDirty() ? "*" : ""),
|
||||
),
|
||||
v.span({ class: "mx-1 flex-1" }, () => editor.val.title()),
|
||||
u.InlineButton(() => editor.val.close(), "Close", "❌"),
|
||||
),
|
||||
v.div({ class: "flex-auto h-4" }, editor.val.dom),
|
||||
|
|
@ -55,6 +61,7 @@ const TabHeader = (tab: State<Editor[]>, del: () => void, k: number) =>
|
|||
v.span({ class: "mx-1 flex-1" }, "Tab " + k),
|
||||
u.InlineButton(del, "Close", "❌"),
|
||||
);
|
||||
|
||||
const EditorGrid = (tab: State<Editor[]>, del: () => void, k: number) => {
|
||||
console.log("Rendering", tab.val, "with key", k);
|
||||
const main = v.main({
|
||||
|
|
@ -64,12 +71,15 @@ const EditorGrid = (tab: State<Editor[]>, del: () => void, k: number) => {
|
|||
vanX.list(main, tab.val, EditorWrapper);
|
||||
return main;
|
||||
};
|
||||
|
||||
const TabBar = v.div({ class: "flex-none flex" });
|
||||
|
||||
export const EditorTabs = v.div(
|
||||
{
|
||||
class: "flex flex-col flex-auto min-w-4",
|
||||
},
|
||||
TabBar,
|
||||
);
|
||||
|
||||
vanX.list(TabBar, editors, TabHeader);
|
||||
vanX.list(EditorTabs, editors, EditorGrid);
|
||||
|
|
|
|||
|
|
@ -40,13 +40,14 @@ export class OpenFile {
|
|||
}
|
||||
|
||||
private setPath(path: string) {
|
||||
delete openFiles[this.filePath?.val];
|
||||
delete openFiles[this.filePath.val];
|
||||
this.filePath.val = path;
|
||||
openFiles[path] = this;
|
||||
// TODO: what if openFiles[path] already exists?
|
||||
}
|
||||
|
||||
async saveFile() {
|
||||
if (this.filePath) {
|
||||
if (this.filePath.val) {
|
||||
await window.electronAPI.saveFile(
|
||||
this.rootState.val.doc.toString(),
|
||||
this.filePath.val,
|
||||
|
|
|
|||
Loading…
Reference in New Issue