1
0

Rewrote some navigation stuff based on new parser

This commit is contained in:
Zef Hemel 2022-04-03 18:42:12 +02:00
parent 16bf0d866d
commit 07453d638b
21 changed files with 206 additions and 235 deletions

View File

@ -3,13 +3,13 @@ import {MarkdownTree, nodeAtPos, parse, render} from "../tree";
export function markdownSyscalls(): SysCallMapping {
return {
parse(ctx, text: string): MarkdownTree {
"markdown.parse": (ctx, text: string): MarkdownTree => {
return parse(text);
},
nodeAtPos(ctx, mdTree: MarkdownTree, pos: number): MarkdownTree | null {
"markdown.nodeAtPos": (ctx, mdTree: MarkdownTree, pos: number): MarkdownTree | null => {
return nodeAtPos(mdTree, pos);
},
render(ctx, mdTree: MarkdownTree): string {
"markdown.render": (ctx, mdTree: MarkdownTree): string => {
return render(mdTree);
},
};

View File

@ -8,7 +8,7 @@ export async function parse(text: string): Promise<MarkdownTree> {
export async function nodeAtPos(
mdTree: MarkdownTree,
pos: number
): Promise<any | null> {
): Promise<MarkdownTree | null> {
return syscall("markdown.nodeAtPos", mdTree, pos);
}

View File

@ -10,11 +10,7 @@ import {System} from "../system";
import {EndpointHook, EndpointHookT} from "../hooks/endpoint";
import {safeRun} from "../util";
import knex from "knex";
import {
ensureTable,
storeReadSyscalls,
storeWriteSyscalls,
} from "../syscalls/store.knex_node";
import {ensureTable, storeSyscalls} from "../syscalls/store.knex_node";
import {fetchSyscalls} from "../syscalls/fetch.node";
import {EventHook, EventHookT} from "../hooks/event";
import {eventSyscalls} from "../syscalls/event";
@ -55,16 +51,11 @@ safeRun(async () => {
system.addHook(new NodeCronHook());
let eventHook = new EventHook();
system.addHook(eventHook);
system.registerSyscalls("event", [], eventSyscalls(eventHook));
system.registerSyscalls([], eventSyscalls(eventHook));
system.addHook(new EndpointHook(app, ""));
system.registerSyscalls("shell", [], shellSyscalls("."));
system.registerSyscalls("fetch", [], fetchSyscalls());
system.registerSyscalls(
"store",
[],
storeWriteSyscalls(db, "item"),
storeReadSyscalls(db, "item")
);
system.registerSyscalls([], shellSyscalls("."));
system.registerSyscalls([], fetchSyscalls());
system.registerSyscalls([], storeSyscalls(db, "item"));
app.listen(args.port, () => {
console.log(`Plugbox server listening on port ${args.port}`);
});

View File

@ -4,7 +4,7 @@ import { System } from "./system";
test("Run a Node sandbox", async () => {
let system = new System("server");
system.registerSyscalls("", [], {
system.registerSyscalls([], {
addNumbers: (ctx, a, b) => {
return a + b;
},
@ -12,12 +12,12 @@ test("Run a Node sandbox", async () => {
throw new Error("#fail");
},
});
system.registerSyscalls("", ["restricted"], {
system.registerSyscalls(["restricted"], {
restrictedSyscall: () => {
return "restricted";
},
});
system.registerSyscalls("", ["dangerous"], {
system.registerSyscalls(["dangerous"], {
dangerousSyscall: () => {
return "yay";
},

View File

@ -3,7 +3,7 @@ import { EventHook } from "../hooks/event";
export function eventSyscalls(eventHook: EventHook): SysCallMapping {
return {
async dispatch(ctx, eventName: string, data: any) {
"event.dispatch": async(ctx, eventName: string, data: any) => {
return eventHook.dispatchEvent(eventName, data);
},
};

View File

@ -3,11 +3,11 @@ import { SysCallMapping } from "../system";
export function fetchSyscalls(): SysCallMapping {
return {
async json(ctx, url: RequestInfo, init: RequestInit) {
"fetch.json": async (ctx, url: RequestInfo, init: RequestInit) => {
let resp = await fetch(url, init);
return resp.json();
},
async text(ctx, url: RequestInfo, init: RequestInit) {
"fetch.text": async(ctx, url: RequestInfo, init: RequestInit) => {
let resp = await fetch(url, init);
return resp.text();
},

View File

@ -6,7 +6,7 @@ const execFilePromise = promisify(execFile);
export default function (cwd: string): SysCallMapping {
return {
run: async (
"shell.run": async (
ctx,
cmd: string,
args: string[]

View File

@ -8,7 +8,7 @@ require("fake-indexeddb/auto");
test("Test store", async () => {
let system = new System("server");
system.registerSyscalls("store", [], storeSyscalls("test", "test"));
system.registerSyscalls([], storeSyscalls("test", "test"));
let plug = await system.load(
"test",
{

View File

@ -17,26 +17,26 @@ export function storeSyscalls(
const items = db.table(tableName);
return {
async delete(ctx, key: string) {
"store.delete": async (ctx, key: string) => {
await items.delete(key);
},
async deletePrefix(ctx, prefix: string) {
"store.deletePrefix": async (ctx, prefix: string) => {
await items.where("key").startsWith(prefix).delete();
},
async deleteAll() {
"store.deleteAll": async () => {
await items.clear();
},
async set(ctx, key: string, value: any) {
"store.set": async (ctx, key: string, value: any) => {
await items.put({
key,
value,
});
},
async batchSet(ctx, kvs: KV[]) {
"store.batchSet": async (ctx, kvs: KV[]) => {
await items.bulkPut(
kvs.map(({ key, value }) => ({
key,
@ -45,17 +45,17 @@ export function storeSyscalls(
);
},
async get(ctx, key: string): Promise<any | null> {
"store.get": async (ctx, key: string): Promise<any | null> => {
let result = await items.get({
key,
});
return result ? result.value : null;
},
async queryPrefix(
"store.queryPrefix": async (
ctx,
keyPrefix: string
): Promise<{ key: string; value: any }[]> {
): Promise<{ key: string; value: any }[]> => {
let results = await items.where("key").startsWith(keyPrefix).toArray();
return results.map((result) => ({
key: result.key,

View File

@ -1,11 +1,7 @@
import {createSandbox} from "../environments/node_sandbox";
import {expect, test} from "@jest/globals";
import {System} from "../system";
import {
ensureTable,
storeReadSyscalls,
storeWriteSyscalls,
} from "./store.knex_node";
import {ensureTable, storeSyscalls} from "./store.knex_node";
import knex from "knex";
import fs from "fs/promises";
@ -19,12 +15,7 @@ test("Test store", async () => {
});
await ensureTable(db, "test_table");
let system = new System("server");
system.registerSyscalls(
"store",
[],
storeWriteSyscalls(db, "test_table"),
storeReadSyscalls(db, "test_table")
);
system.registerSyscalls([], storeSyscalls(db, "test_table"));
let plug = await system.load(
"test",
{

View File

@ -23,21 +23,21 @@ export async function ensureTable(db: Knex<any, unknown>, tableName: string) {
}
}
export function storeWriteSyscalls(
export function storeSyscalls(
db: Knex<any, unknown>,
tableName: string
): SysCallMapping {
const apiObj: SysCallMapping = {
delete: async (ctx, key: string) => {
"store.delete": async (ctx, key: string) => {
await db<Item>(tableName).where({ key }).del();
},
deletePrefix: async (ctx, prefix: string) => {
"store.deletePrefix": async (ctx, prefix: string) => {
return db<Item>(tableName).andWhereLike("key", `${prefix}%`).del();
},
deleteAll: async (ctx) => {
"store.deleteAll": async (ctx) => {
await db<Item>(tableName).del();
},
set: async (ctx, key: string, value: any) => {
"store.set": async (ctx, key: string, value: any) => {
let changed = await db<Item>(tableName)
.where({ key })
.update("value", JSON.stringify(value));
@ -49,26 +49,17 @@ export function storeWriteSyscalls(
}
},
// TODO: Optimize
batchSet: async (ctx, kvs: KV[]) => {
"store.batchSet": async (ctx, kvs: KV[]) => {
for (let { key, value } of kvs) {
await apiObj.set(ctx, key, value);
await apiObj["store.set"](ctx, key, value);
}
},
batchDelete: async (ctx, keys: string[]) => {
"store.batchDelete": async (ctx, keys: string[]) => {
for (let key of keys) {
await apiObj.delete(ctx, key);
await apiObj["store.delete"](ctx, key);
}
},
};
return apiObj;
}
export function storeReadSyscalls(
db: Knex<any, unknown>,
tableName: string
): SysCallMapping {
return {
get: async (ctx, key: string): Promise<any | null> => {
"store.get": async (ctx, key: string): Promise<any | null> => {
let result = await db<Item>(tableName).where({ key }).select("value");
if (result.length) {
return JSON.parse(result[0].value);
@ -76,7 +67,7 @@ export function storeReadSyscalls(
return null;
}
},
queryPrefix: async (ctx, prefix: string) => {
"store.queryPrefix": async (ctx, prefix: string) => {
return (
await db<Item>(tableName)
.andWhereLike("key", `${prefix}%`)
@ -87,4 +78,5 @@ export function storeReadSyscalls(
}));
},
};
return apiObj;
}

View File

@ -29,31 +29,32 @@ type Syscall = {
};
export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
readonly runtimeEnv: RuntimeEnvironment;
protected plugs = new Map<string, Plug<HookT>>();
protected registeredSyscalls = new Map<string, Syscall>();
protected enabledHooks = new Set<Hook<HookT>>();
readonly runtimeEnv: RuntimeEnvironment;
constructor(env: RuntimeEnvironment) {
super();
this.runtimeEnv = env;
}
get loadedPlugs(): Map<string, Plug<HookT>> {
return this.plugs;
}
addHook(feature: Hook<HookT>) {
this.enabledHooks.add(feature);
feature.apply(this);
}
registerSyscalls(
namespace: string,
requiredCapabilities: string[],
...registrationObjects: SysCallMapping[]
) {
for (const registrationObject of registrationObjects) {
for (let [name, callback] of Object.entries(registrationObject)) {
const callName = namespace ? `${namespace}.${name}` : name;
this.registeredSyscalls.set(callName, {
this.registeredSyscalls.set(name, {
requiredPermissions: requiredCapabilities,
callback,
});
@ -116,10 +117,6 @@ export class System<HookT> extends EventEmitter<SystemEvents<HookT>> {
this.plugs.delete(name);
}
get loadedPlugs(): Map<string, Plug<HookT>> {
return this.plugs;
}
toJSON(): SystemJSON<HookT> {
let plugJSON: { [key: string]: Manifest<HookT> } = {};
for (let [name, plug] of this.plugs) {

View File

@ -1,62 +1,54 @@
import {ClickEvent} from "../../webapp/app_event";
import {updateMaterializedQueriesCommand} from "./materialized_queries";
import {
getSyntaxNodeAtPos,
getSyntaxNodeUnderCursor,
getText,
navigate as navigateTo,
openUrl,
} from "plugos-silverbullet-syscall/editor";
import {getCursor, getText, navigate as navigateTo, openUrl,} from "plugos-silverbullet-syscall/editor";
import {taskToggleAtPos} from "../tasks/task";
import {nodeAtPos, parse} from "plugos-silverbullet-syscall/markdown";
import type {MarkdownTree} from "../../common/tree";
const materializedQueryPrefix = /<!--\s*#query\s+/;
async function actionClickOrActionEnter(syntaxNode: any) {
if (!syntaxNode) {
async function actionClickOrActionEnter(mdTree: MarkdownTree | null) {
if (!mdTree) {
return;
}
console.log("Attempting to navigate based on syntax node", syntaxNode);
switch (syntaxNode.name) {
console.log("Attempting to navigate based on syntax node", mdTree);
switch (mdTree.type) {
case "WikiLinkPage":
let pageLink = syntaxNode.text;
let pos = 0;
let pageLink = mdTree.children![0].text!;
let pos = "0";
if (pageLink.includes("@")) {
[pageLink, pos] = syntaxNode.text.split("@");
[pageLink, pos] = pageLink.split("@");
}
await navigateTo(pageLink, +pos);
break;
case "URL":
await openUrl(syntaxNode.text);
await openUrl(mdTree.children![0].text!);
break;
case "CommentBlock":
if (syntaxNode.text.match(materializedQueryPrefix)) {
if (mdTree.children![0].text!.match(materializedQueryPrefix)) {
await updateMaterializedQueriesCommand();
}
break;
case "Link":
// Markdown link: [bla](URLHERE) needs extraction
let match = /\[[^\\]+\]\(([^\)]+)\)/.exec(syntaxNode.text);
if (match) {
await openUrl(match[1]);
}
await openUrl(mdTree.children![4].children![0].text!);
break;
case "TaskMarker":
await taskToggleAtPos(syntaxNode.from + 1);
await taskToggleAtPos(mdTree.from + 1);
break;
}
}
export async function linkNavigate() {
await actionClickOrActionEnter(await getSyntaxNodeUnderCursor());
let mdTree = await parse(await getText());
let newNode = await nodeAtPos(mdTree, await getCursor());
await actionClickOrActionEnter(newNode);
}
export async function clickNavigate(event: ClickEvent) {
if (event.ctrlKey || event.metaKey) {
let syntaxNode = await getSyntaxNodeAtPos(event.pos);
let mdTree = await parse(await getText());
let newNode = await nodeAtPos(mdTree, event.pos);
console.log("New node", newNode);
await actionClickOrActionEnter(syntaxNode);
await actionClickOrActionEnter(newNode);
}
}

View File

@ -51,13 +51,13 @@ export class ExpressServer {
useNullAsDefault: true,
});
system.registerSyscalls("shell", ["shell"], shellSyscalls(rootPath));
system.registerSyscalls(["shell"], shellSyscalls(rootPath));
system.addHook(new NodeCronHook());
system.registerSyscalls("index", [], pageIndexSyscalls(this.db));
system.registerSyscalls("space", [], spaceSyscalls(this.storage));
system.registerSyscalls("event", [], eventSyscalls(this.eventHook));
system.registerSyscalls("markdown", [], markdownSyscalls());
system.registerSyscalls([], pageIndexSyscalls(this.db));
system.registerSyscalls([], spaceSyscalls(this.storage));
system.registerSyscalls([], eventSyscalls(this.eventHook));
system.registerSyscalls([], markdownSyscalls());
system.addHook(new EndpointHook(app, "/_"));
}

View File

@ -1,11 +1,7 @@
import {Knex} from "knex";
import {SysCallMapping} from "../../plugos/system";
import {
ensureTable,
storeReadSyscalls,
storeWriteSyscalls,
} from "../../plugos/syscalls/store.knex_node";
import {ensureTable, storeSyscalls,} from "../../plugos/syscalls/store.knex_node";
type IndexItem = {
page: string;
@ -52,39 +48,38 @@ export async function ensurePageIndexTable(db: Knex<any, unknown>) {
}
export function pageIndexSyscalls(db: Knex<any, unknown>): SysCallMapping {
const readCalls = storeReadSyscalls(db, "page_index");
const writeCalls = storeWriteSyscalls(db, "page_index");
const storeCalls = storeSyscalls(db, "page_index");
const apiObj: SysCallMapping = {
set: async (ctx, page: string, key: string, value: any) => {
await writeCalls.set(ctx, pageKey(page, key), value);
await writeCalls.set(ctx, globalKey(page, key), value);
"index.set": async (ctx, page: string, key: string, value: any) => {
await storeCalls["store.set"](ctx, pageKey(page, key), value);
await storeCalls["store.set"](ctx, globalKey(page, key), value);
},
batchSet: async (ctx, page: string, kvs: KV[]) => {
"index.batchSet": async (ctx, page: string, kvs: KV[]) => {
for (let { key, value } of kvs) {
await apiObj.set(ctx, page, key, value);
await apiObj["index.set"](ctx, page, key, value);
}
},
delete: async (ctx, page: string, key: string) => {
await writeCalls.delete(ctx, pageKey(page, key));
await writeCalls.delete(ctx, globalKey(page, key));
"index.delete": async (ctx, page: string, key: string) => {
await storeCalls["store.delete"](ctx, pageKey(page, key));
await storeCalls["store.delete"](ctx, globalKey(page, key));
},
get: async (ctx, page: string, key: string) => {
return readCalls.get(ctx, pageKey(page, key));
"index.get": async (ctx, page: string, key: string) => {
return storeCalls["store.get"](ctx, pageKey(page, key));
},
scanPrefixForPage: async (ctx, page: string, prefix: string) => {
return (await readCalls.queryPrefix(ctx, pageKey(page, prefix))).map(
({ key, value }: { key: string; value: any }) => {
"index.scanPrefixForPage": async (ctx, page: string, prefix: string) => {
return (
await storeCalls["store.queryPrefix"](ctx, pageKey(page, prefix))
).map(({ key, value }: { key: string; value: any }) => {
const { key: pageKey } = unpackPageKey(key);
return {
page,
key: pageKey,
value,
};
}
);
});
},
scanPrefixGlobal: async (ctx, prefix: string) => {
return (await readCalls.queryPrefix(ctx, `k~${prefix}`)).map(
"index.scanPrefixGlobal": async (ctx, prefix: string) => {
return (await storeCalls["store.queryPrefix"](ctx, `k~${prefix}`)).map(
({ key, value }: { key: string; value: any }) => {
const { page, key: pageKey } = unpackGlobalKey(key);
return {
@ -95,22 +90,22 @@ export function pageIndexSyscalls(db: Knex<any, unknown>): SysCallMapping {
}
);
},
clearPageIndexForPage: async (ctx, page: string) => {
await apiObj.deletePrefixForPage(ctx, page, "");
"index.clearPageIndexForPage": async (ctx, page: string) => {
await apiObj["index.deletePrefixForPage"](ctx, page, "");
},
deletePrefixForPage: async (ctx, page: string, prefix: string) => {
"index.deletePrefixForPage": async (ctx, page: string, prefix: string) => {
// Collect all global keys for this page to delete
let keysToDelete = (
await readCalls.queryPrefix(ctx, pageKey(page, prefix))
await storeCalls["store.queryPrefix"](ctx, pageKey(page, prefix))
).map(({ key }: { key: string; value: string }) =>
globalKey(page, unpackPageKey(key).key)
);
// Delete all page keys
await writeCalls.deletePrefix(ctx, pageKey(page, prefix));
await writeCalls.batchDelete(ctx, keysToDelete);
await storeCalls["store.deletePrefix"](ctx, pageKey(page, prefix));
await storeCalls["store.batchDelete"](ctx, keysToDelete);
},
clearPageIndex: async (ctx) => {
await writeCalls.deleteAll(ctx);
"index.clearPageIndex": async (ctx) => {
await storeCalls["store.deleteAll"](ctx);
},
};
return apiObj;

View File

@ -4,19 +4,23 @@ import { Storage } from "../disk_storage";
export default (storage: Storage): SysCallMapping => {
return {
listPages: (ctx): Promise<PageMeta[]> => {
"space.listPages": (ctx): Promise<PageMeta[]> => {
return storage.listPages();
},
readPage: async (
"space.readPage": async (
ctx,
name: string
): Promise<{ text: string; meta: PageMeta }> => {
return storage.readPage(name);
},
writePage: async (ctx, name: string, text: string): Promise<PageMeta> => {
"space.writePage": async (
ctx,
name: string,
text: string
): Promise<PageMeta> => {
return storage.writePage(name, text);
},
deletePage: async (ctx, name: string) => {
"space.deletePage": async (ctx, name: string) => {
return storage.deletePage(name);
},
};

View File

@ -47,7 +47,6 @@ import {CompleterHook} from "./hooks/completer";
import {pasteLinkExtension} from "./editor_paste";
import {markdownSyscalls} from "../common/syscalls/markdown";
class PageState {
scrollTop: number;
selection: EditorSelection;
@ -61,11 +60,9 @@ class PageState {
const saveInterval = 2000;
export class Editor implements AppEventDispatcher {
private system = new System<SilverBulletHooks>("client");
readonly commandHook: CommandHook;
readonly slashCommandHook: SlashCommandHook;
readonly completerHook: CompleterHook;
openPages = new Map<string, PageState>();
editorView?: EditorView;
viewState: AppViewState;
@ -73,6 +70,8 @@ export class Editor implements AppEventDispatcher {
space: Space;
pageNavigator: PathPageNavigator;
eventHook: EventHook;
saveTimeout: any;
private system = new System<SilverBulletHooks>("client");
constructor(space: Space, parent: Element) {
this.space = space;
@ -110,11 +109,15 @@ export class Editor implements AppEventDispatcher {
});
this.pageNavigator = new PathPageNavigator();
this.system.registerSyscalls("editor", [], editorSyscalls(this));
this.system.registerSyscalls("space", [], spaceSyscalls(this));
this.system.registerSyscalls("index", [], indexerSyscalls(this.space));
this.system.registerSyscalls("system", [], systemSyscalls(this.space));
this.system.registerSyscalls("markdown", [], markdownSyscalls());
this.system.registerSyscalls([], editorSyscalls(this));
this.system.registerSyscalls([], spaceSyscalls(this));
this.system.registerSyscalls([], indexerSyscalls(this.space));
this.system.registerSyscalls([], systemSyscalls(this.space));
this.system.registerSyscalls([], markdownSyscalls());
}
get currentPage(): string | undefined {
return this.viewState.currentPage;
}
async init() {
@ -180,8 +183,6 @@ export class Editor implements AppEventDispatcher {
}
}
saveTimeout: any;
async save(immediate: boolean = false): Promise<void> {
return new Promise((resolve, reject) => {
if (!this.viewState.unsavedChanges) {
@ -236,10 +237,6 @@ export class Editor implements AppEventDispatcher {
return this.eventHook.dispatchEvent(name, data);
}
get currentPage(): string | undefined {
return this.viewState.currentPage;
}
createEditorState(pageName: string, text: string): EditorState {
let commandKeyBindings: KeyBinding[] = [];
for (let def of this.commandHook.editorCommands.values()) {

View File

@ -28,37 +28,37 @@ function ensureAnchor(expr: any, start: boolean) {
export function editorSyscalls(editor: Editor): SysCallMapping {
return {
getCurrentPage: (): string => {
"editor.getCurrentPage": (): string => {
return editor.currentPage!;
},
getText: () => {
"editor.getText": () => {
return editor.editorView?.state.sliceDoc();
},
getCursor: (): number => {
"editor.getCursor": (): number => {
return editor.editorView!.state.selection.main.from;
},
save: async () => {
"editor.save": async () => {
return editor.save(true);
},
navigate: async (ctx, name: string, pos: number) => {
"editor.navigate": async (ctx, name: string, pos: number) => {
await editor.navigate(name, pos);
},
reloadPage: async (ctx) => {
"editor.reloadPage": async (ctx) => {
await editor.reloadPage();
},
openUrl: async (ctx, url: string) => {
"editor.openUrl": async (ctx, url: string) => {
window.open(url, "_blank")!.focus();
},
flashNotification: (ctx, message: string) => {
"editor.flashNotification": (ctx, message: string) => {
editor.flashNotification(message);
},
showRhs: (ctx, html: string) => {
"editor.showRhs": (ctx, html: string) => {
editor.viewDispatch({
type: "show-rhs",
html: html,
});
},
insertAtPos: (ctx, text: string, pos: number) => {
"editor.insertAtPos": (ctx, text: string, pos: number) => {
editor.editorView!.dispatch({
changes: {
insert: text,
@ -66,7 +66,7 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
},
});
},
replaceRange: (ctx, from: number, to: number, text: string) => {
"editor.replaceRange": (ctx, from: number, to: number, text: string) => {
editor.editorView!.dispatch({
changes: {
insert: text,
@ -75,14 +75,14 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
},
});
},
moveCursor: (ctx, pos: number) => {
"editor.moveCursor": (ctx, pos: number) => {
editor.editorView!.dispatch({
selection: {
anchor: pos,
},
});
},
insertAtCursor: (ctx, text: string) => {
"editor.insertAtCursor": (ctx, text: string) => {
let editorView = editor.editorView!;
let from = editorView.state.selection.main.from;
editorView.dispatch({
@ -95,7 +95,7 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
},
});
},
getSyntaxNodeUnderCursor: (): SyntaxNode | undefined => {
"editor.getSyntaxNodeUnderCursor": (): SyntaxNode | undefined => {
const editorState = editor.editorView!.state;
let selection = editorState.selection.main;
if (selection.empty) {
@ -110,13 +110,13 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
}
}
},
getLineUnderCursor: (): string => {
"editor.getLineUnderCursor": (): string => {
const editorState = editor.editorView!.state;
let selection = editorState.selection.main;
let line = editorState.doc.lineAt(selection.from);
return editorState.sliceDoc(line.from, line.to);
},
matchBefore: (
"editor.matchBefore": (
ctx,
regexp: string
): { from: number; to: number; text: string } | null => {
@ -135,7 +135,7 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
}
return null;
},
getSyntaxNodeAtPos: (ctx, pos: number): SyntaxNode | undefined => {
"editor.getSyntaxNodeAtPos": (ctx, pos: number): SyntaxNode | undefined => {
const editorState = editor.editorView!.state;
let node = syntaxTree(editorState).resolveInner(pos);
if (node) {
@ -147,10 +147,14 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
};
}
},
dispatch: (ctx, change: Transaction) => {
"editor.dispatch": (ctx, change: Transaction) => {
editor.editorView!.dispatch(change);
},
prompt: (ctx, message: string, defaultValue = ""): string | null => {
"editor.prompt": (
ctx,
message: string,
defaultValue = ""
): string | null => {
return prompt(message, defaultValue);
},
};

View File

@ -5,13 +5,13 @@ import {transportSyscalls} from "../../plugos/syscalls/transport";
export function indexerSyscalls(space: Space): SysCallMapping {
return transportSyscalls(
[
"scanPrefixForPage",
"scanPrefixGlobal",
"get",
"set",
"batchSet",
"delete",
"index.scanPrefixForPage",
"index.scanPrefixGlobal",
"index.get",
"index.set",
"index.batchSet",
"index.delete",
],
(ctx, name, ...args) => space.remoteSyscall(ctx.plug, `index.${name}`, args)
(ctx, name, ...args) => space.remoteSyscall(ctx.plug, name, args)
);
}

View File

@ -4,19 +4,23 @@ import {PageMeta} from "../../common/types";
export function spaceSyscalls(editor: Editor): SysCallMapping {
return {
listPages: async (): Promise<PageMeta[]> => {
"space.listPages": async (): Promise<PageMeta[]> => {
return [...(await editor.space.listPages())];
},
readPage: async (
"space.readPage": async (
ctx,
name: string
): Promise<{ text: string; meta: PageMeta }> => {
return await editor.space.readPage(name);
},
writePage: async (ctx, name: string, text: string): Promise<PageMeta> => {
"space.writePage": async (
ctx,
name: string,
text: string
): Promise<PageMeta> => {
return await editor.space.writePage(name, text);
},
deletePage: async (ctx, name: string) => {
"space.deletePage": async (ctx, name: string) => {
// If we're deleting the current page, navigate to the start page
if (editor.currentPage === name) {
await editor.navigate("start");

View File

@ -3,7 +3,11 @@ import { Space } from "../space";
export function systemSyscalls(space: Space): SysCallMapping {
return {
async invokeFunctionOnServer(ctx, name: string, ...args: any[]) {
"system.invokeFunctionOnServer": async (
ctx,
name: string,
...args: any[]
) => {
if (!ctx.plug) {
throw Error("No plug associated with context");
}