-
+
-
diff --git a/www/package.json b/www/package.json
index 7c48500..0a18390 100644
--- a/www/package.json
+++ b/www/package.json
@@ -24,6 +24,7 @@
},
"homepage": "https://github.com/ryex/ic10emu#readme",
"devDependencies": {
+ "@oneidentity/zstd-js": "^1.0.3",
"copy-webpack-plugin": "^12.0.2",
"hello-wasm-pack": "^0.1.0",
"ts-loader": "^9.5.1",
@@ -35,8 +36,9 @@
"dependencies": {
"ace-code": "^1.32.7",
"ace-linters": "^1.1.1",
- "uuid": "^9.0.1",
"ic10emu_wasm": "file:../ic10emu_wasm/pkg",
- "ic10lsp_wasm": "file:../ic10lsp_wasm/pkg"
+ "ic10lsp_wasm": "file:../ic10lsp_wasm/pkg",
+ "lzma-web": "^3.0.1",
+ "uuid": "^9.0.1"
}
}
diff --git a/www/pnpm-lock.yaml b/www/pnpm-lock.yaml
index fbbaa31..3f3e163 100644
--- a/www/pnpm-lock.yaml
+++ b/www/pnpm-lock.yaml
@@ -17,11 +17,17 @@ dependencies:
ic10lsp_wasm:
specifier: file:../ic10lsp_wasm/pkg
version: file:../ic10lsp_wasm/pkg
+ lzma-web:
+ specifier: ^3.0.1
+ version: 3.0.1
uuid:
specifier: ^9.0.1
version: 9.0.1
devDependencies:
+ '@oneidentity/zstd-js':
+ specifier: ^1.0.3
+ version: 1.0.3
copy-webpack-plugin:
specifier: ^12.0.2
version: 12.0.2(webpack@5.90.3)
@@ -125,6 +131,12 @@ packages:
fastq: 1.17.1
dev: true
+ /@oneidentity/zstd-js@1.0.3:
+ resolution: {integrity: sha512-Jm6sawqxLzBrjC4sg2BeXToa33yPzUmq20CKsehKY2++D/gHb/oSwVjNgT+RH4vys+r8FynrgcNzGwhZWMLzfQ==}
+ dependencies:
+ '@types/emscripten': 1.39.10
+ dev: true
+
/@pkgjs/parseargs@0.11.0:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@@ -163,6 +175,10 @@ packages:
'@types/node': 20.11.28
dev: true
+ /@types/emscripten@1.39.10:
+ resolution: {integrity: sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==}
+ dev: true
+
/@types/eslint-scope@3.7.7:
resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==}
dependencies:
@@ -1665,6 +1681,10 @@ packages:
hasBin: true
dev: false
+ /lzma-web@3.0.1:
+ resolution: {integrity: sha512-sb5cdfd+PLNljK/HUgYzvnz4G7r0GFK8sonyGrqJS0FVyUQjFYcnmU2LqTWFi6r48lH1ZBstnxyLWepKM/t7QA==}
+ dev: false
+
/media-typer@0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
diff --git a/www/src/index.js b/www/src/index.js
index f26e1ca..20037a1 100644
--- a/www/src/index.js
+++ b/www/src/index.js
@@ -176,7 +176,8 @@ async function decompress(bytes) {
async function setDocFragment(content) {
- const bytes = new TextEncoder().encode(content);
+ const obj = JSON.stringify({ sessions: [{ content }] })
+ const bytes = new TextEncoder().encode(obj);
try {
const c_bytes = await compress(bytes);
const fragment = base64url_encode(c_bytes);
@@ -185,27 +186,51 @@ async function setDocFragment(content) {
console.log("Error compressing content fragment:", e);
return;
}
+
+}
+
+async function decompressFragment(c_bytes) {
+ try {
+ const bytes = await decompress(c_bytes);
+ const content = new TextDecoder().decode(bytes);
+ return content;
+ } catch (e) {
+ console.log("Error decompressing content fragment:", e);
+ return null;
+ }
+}
+
+function isJsonContent(content) {
+ try {
+ const obj = JSON.parse(content);
+ return [true, obj];
+ } catch (_) {
+ return [false, null];
+ }
}
async function getContentFromFragment(editor, default_content) {
const fragment = window.location.hash.slice(1);
- console.log("fragment is", fragment);
if (fragment.length > 0) {
const c_bytes = base64url_decode(fragment);
- console.log("compressed", c_bytes);
- try {
- const bytes = await decompress(c_bytes);
- console.log("bytes", bytes);
- const content = new TextDecoder().decode(bytes);
- console.log("content is", content);
- editor.getSession().setValue(content);
- } catch (e) {
- console.log("Error decompressing content fragment:", e);
- return;
+ const data = await decompressFragment(c_bytes);
+ if (data !== null) {
+ const [is_json, session] = isJsonContent(data);
+ if (is_json) {
+ try {
+ const content = session.sessions[0].content
+ editor.getSession().setValue(content);
+ return;
+ } catch (e) {
+ console.log("Bad session data:", e);
+ }
+ } else {
+ editor.getSession().setValue(data);
+ return;
+ }
}
- } else {
- editor.getSession().setValue(default_content);
}
+ editor.getSession().setValue(default_content);
}
async function setupLsp(editor, mode) {
@@ -229,6 +254,64 @@ async function setupLsp(editor, mode) {
}
+function reCalcEditorSize(editor) {
+ const navBar = document.getElementById("navBar");
+ const statusBarContainer = document.getElementById("statusBarContainer");
+
+ const correction = navBar.offsetHeight + statusBarContainer.offsetHeight;
+ const editorContainer = document.getElementById("editor");
+ editorContainer.style.height = `calc( 100vh - ${correction}px - 0.5rem)`;
+ editor.resize(true);
+}
+
+const EditorSettings = {
+ keyboard: "ace",
+ cursor: "ace",
+ fontSize: 16,
+ relativeLineNumbers: false,
+}
+
+function loadEditorSettings(settings) {
+ const saved_settings = window.localStorage.getItem("editorSettings");
+ if (saved_settings !== null && saved_settings.length > 0) {
+ try {
+ const saved = JSON.parse(saved_settings);
+ const temp = Object.assign({}, settings, saved);
+ console.log("tmp load", temp);
+ Object.assign(settings, temp);
+ } catch (e) {
+ console.log("error loading editor settings", e);
+ }
+ }
+}
+
+function saveEditorSettings(settings) {
+ const toSave = JSON.stringify(settings);
+ window.localStorage.setItem("editorSettings", toSave);
+}
+
+function updateEditorSettings(editor, settings) {
+ if (settings.keyboard === 'ace') {
+ editor.setOption('keyboardHandler', null);
+ } else {
+ editor.setOption('keyboardHandler', `ace/keyboard/${settings.keyboard}`);
+ }
+ editor.setOption('cursorStyle', settings.cursor);
+ editor.setOption('fontSize', `${settings.fontSize}px`);
+ editor.setOption('relativeLineNumbers', settings.relativeLineNumbers);
+}
+
+function displayEditorSettings(settings) {
+ document.getElementsByName("editorKeybindRadio").forEach((el) => {
+ el.checked = el.value === settings.keyboard;
+ });
+ document.getElementsByName("editorCursorRadio").forEach((el) => {
+ el.checked = el.value === settings.cursor;
+ });
+ document.getElementById("editorSettingsFontSize").value = settings.fontSize;
+ document.getElementById("editorSettingsRelativeLineNumbers").checked = settings.relativeLineNumbers;
+}
+
docReady(() => {
const mode = new IC10Mode()
var editor = ace.edit("editor", {
@@ -242,6 +325,38 @@ docReady(() => {
firstLineNumber: 0,
printMarginColumn: 52,
});
+ loadEditorSettings(EditorSettings);
+ displayEditorSettings(EditorSettings);
+ updateEditorSettings(editor, EditorSettings);
+ reCalcEditorSize(editor);
+ window.addEventListener('resize', (e) => { reCalcEditorSize(editor) });
+ document.getElementsByName("editorKeybindRadio").forEach((el) => {
+ el.addEventListener('change', (e) => {
+ EditorSettings.keyboard = e.target.value;
+ saveEditorSettings(EditorSettings);
+ updateEditorSettings(editor, EditorSettings);
+ })
+ });
+ document.getElementsByName("editorCursorRadio").forEach((el) => {
+ el.addEventListener('change', (e) => {
+ EditorSettings.cursor = e.target.value;
+ saveEditorSettings(EditorSettings);
+ updateEditorSettings(editor, EditorSettings);
+ })
+ });
+ document.getElementById("editorSettingsFontSize").addEventListener('change', (e) => {
+ EditorSettings.fontSize = e.target.value;
+ saveEditorSettings(EditorSettings);
+ updateEditorSettings(editor, EditorSettings);
+ });
+ document.getElementById("editorSettingsRelativeLineNumbers").addEventListener('change', (e) => {
+ EditorSettings.relativeLineNumbers = e.target.checked;
+ saveEditorSettings(EditorSettings);
+ updateEditorSettings(editor, EditorSettings);
+ })
+
+ console.log(editor.getOption('keyboardHandler'));
+
editor.getSession().on('change', () => {
var val = editor.getSession().getValue();
setDocFragment(val);
@@ -252,6 +367,7 @@ docReady(() => {
statusBar.updateStatus(editor);
ace_ext_keybinding_menu.init(editor);
// editor.setOption("keyboardHandler", "ace/keyboard/vim");
+ editor.setAutoScrollEditorIntoView(true);
editor.session.setValue(demoCode)