Extracted syscall packages

pull/3/head
Zef Hemel 2022-04-01 17:07:08 +02:00
parent 7f647758c2
commit 3aafa63073
34 changed files with 411 additions and 124 deletions

View File

@ -1,5 +1,6 @@
export type PageMeta = {
name: string;
lastModified: number;
version?: number;
lastOpened?: number;
created?: boolean;
};

View File

@ -0,0 +1,93 @@
import { syscall } from "./syscall";
export function getCurrentPage(): Promise<string> {
return syscall("editor.getCurrentPage");
}
export function getText(): Promise<string> {
return syscall("editor.getText");
}
export function getCursor(): Promise<number> {
return syscall("editor.getCursor");
}
export function save(): Promise<void> {
return syscall("editor.save");
}
export function navigate(name: string, pos?: number): Promise<void> {
return syscall("editor.navigate", name, pos);
}
export function reloadPage(): Promise<void> {
return syscall("editor.reloadPage");
}
export function openUrl(url: string): Promise<void> {
return syscall("editor.openUrl", url);
}
export function flashNotification(message: string): Promise<void> {
return syscall("editor.flashNotification", message);
}
export function showRhs(html: string): Promise<void> {
return syscall("editor.showRhs", html);
}
export function insertAtPos(text: string, pos: number): Promise<void> {
return syscall("editor.insertAtPos", text, pos);
}
export function replaceRange(
from: number,
to: number,
text: string
): Promise<void> {
return syscall("editor.replaceRange", from, to, text);
}
export function moveCursor(pos: number): Promise<void> {
return syscall("editor.moveCursor", pos);
}
export function insertAtCursor(text: string): Promise<void> {
return syscall("editor.insertAtCursor", text);
}
export type SyntaxNode = {
name: string;
text: string;
from: number;
to: number;
};
export function getSyntaxNodeUnderCursor(): Promise<SyntaxNode> {
return syscall("editor.getSyntaxNodeUnderCursor");
}
export function getLineUnderCursor(): Promise<string> {
return syscall("editor.getLineUnderCursor");
}
export function matchBefore(
re: string
): Promise<{ from: number; to: number; text: string } | null> {
return syscall("editor.matchBefore", re);
}
export function getSyntaxNodeAtPos(pos: number): Promise<SyntaxNode> {
return syscall("editor.getSyntaxNodeAtPos", pos);
}
export function dispatch(change: any): Promise<void> {
return syscall("editor.dispatch", change);
}
export function prompt(
message: string,
defaultValue = ""
): Promise<string | undefined> {
return syscall("editor.prompt", message, defaultValue);
}

View File

@ -0,0 +1,54 @@
import { syscall } from "./syscall";
export type KV = {
key: string;
value: any;
};
export async function set(
page: string,
key: string,
value: any
): Promise<void> {
return syscall("index.set", page, key, value);
}
export async function batchSet(page: string, kvs: KV[]): Promise<void> {
return syscall("index.batchSet", page, kvs);
}
export async function get(page: string, key: string): Promise<any> {
return syscall("index.get", page, key);
}
export async function del(page: string, key: string): Promise<void> {
return syscall("index.delete", page, key);
}
export async function scanPrefixForPage(
page: string,
prefix: string
): Promise<{ key: string; page: string; value: any }[]> {
return syscall("index.scanPrefixForPage", page, prefix);
}
export async function scanPrefixGlobal(
prefix: string
): Promise<{ key: string; page: string; value: any }[]> {
return syscall("index.scanPrefixGlobal", prefix);
}
export async function clearPageIndexForPage(page: string): Promise<void> {
return syscall("index.clearPageIndexForPage", page);
}
export async function deletePrefixForPage(
page: string,
prefix: string
): Promise<void> {
return syscall("index.deletePrefixForPage", page, prefix);
}
export async function clearPageIndex(): Promise<void> {
return syscall("index.clearPageIndex");
}

View File

@ -0,0 +1,4 @@
{
"name": "plugos-silverbullet-syscall",
"version": "1.0.0"
}

View File

@ -0,0 +1,20 @@
import { syscall } from "./syscall";
import { PageMeta } from "../common/types";
export async function listPages(): Promise<PageMeta[]> {
return syscall("space.listPages");
}
export async function readPage(
name: string
): Promise<{ text: string; meta: PageMeta }> {
return syscall("space.readPage", name);
}
export async function writePage(name: string, text: string): Promise<PageMeta> {
return syscall("space.writePage", name, text);
}
export async function deletePage(name: string): Promise<PageMeta> {
return syscall("space.deletePage", name);
}

View File

@ -0,0 +1,8 @@
import { syscall } from "./syscall";
export async function invokeFunctionOnServer(
name: string,
...args: any[]
): Promise<any> {
return syscall("system.invokeFunctionOnServer", name, ...args);
}

5
plugos-syscall/event.ts Normal file
View File

@ -0,0 +1,5 @@
import { syscall } from "./syscall";
export async function dispatch(eventName: string, data: any): Promise<void> {
return syscall("event.dispatch", eventName, data);
}

12
plugos-syscall/fetch.ts Normal file
View File

@ -0,0 +1,12 @@
import { syscall } from "./syscall";
export async function json(url: RequestInfo, init: RequestInit): Promise<any> {
return syscall("fetch.json", url, init);
}
export async function text(
url: RequestInfo,
init: RequestInit
): Promise<string> {
return syscall("fetch.text", url, init);
}

View File

@ -0,0 +1,4 @@
{
"name": "plugos-syscall",
"version": "1.0.0"
}

8
plugos-syscall/shell.ts Normal file
View File

@ -0,0 +1,8 @@
import { syscall } from "./syscall";
export async function run(
cmd: string,
args: string[]
): Promise<{ stdout: string; stderr: string }> {
return syscall("shell.run", cmd, args);
}

40
plugos-syscall/store.ts Normal file
View File

@ -0,0 +1,40 @@
import { syscall } from "./syscall";
export type KV = {
key: string;
value: any;
};
export async function set(key: string, value: any): Promise<void> {
return syscall("store.set", key, value);
}
export async function batchSet(kvs: KV[]): Promise<void> {
return syscall("store.batchSet", kvs);
}
export async function get(key: string): Promise<any> {
return syscall("store.get", key);
}
export async function del(key: string): Promise<void> {
return syscall("store.delete", key);
}
export async function batchDel(keys: string[]): Promise<void> {
return syscall("store.batchDelete", keys);
}
export async function queryPrefix(
prefix: string
): Promise<{ key: string; value: any }[]> {
return syscall("store.scanPrefix", prefix);
}
export async function deletePrefix(prefix: string): Promise<void> {
return syscall("store.deletePrefix", prefix);
}
export async function deleteAll(): Promise<void> {
return syscall("store.deleteAll");
}

View File

@ -0,0 +1,5 @@
declare global {
function syscall(name: string, ...args: any[]): Promise<any>;
}
export const syscall = self.syscall;

View File

@ -1,7 +1,6 @@
import { syscall } from "../lib/syscall";
import { insertAtCursor } from "plugos-silverbullet-syscall/editor";
export async function insertToday() {
console.log("Inserting date!");
let niceDate = new Date().toISOString().split("T")[0];
await syscall("editor.insertAtCursor", niceDate);
await insertAtCursor(niceDate);
}

View File

@ -1,6 +1,7 @@
import { IndexEvent } from "../../webapp/app_event";
import { whiteOutQueries } from "./materialized_queries";
import { syscall } from "../lib/syscall";
import { batchSet } from "plugos-silverbullet-syscall/index";
type Item = {
item: string;
@ -35,5 +36,5 @@ export async function indexItems({ name, text }: IndexEvent) {
});
}
console.log("Found", items.length, "item(s)");
await syscall("index.batchSet", name, items);
await batchSet(name, items);
}

View File

@ -1,8 +1,8 @@
import { syscall } from "../lib/syscall";
import mdParser from "../../webapp/parser";
import { getText } from "plugos-silverbullet-syscall/editor";
export async function renderMD() {
let text = await syscall("editor.getText");
let text = await getText();
let tree = mdParser.parser.parse(text);
let slicesToRemove: [number, number][] = [];

View File

@ -1,4 +1,9 @@
import { syscall } from "../lib/syscall";
import {
getCursor,
getText,
insertAtPos,
replaceRange,
} from "plugos-silverbullet-syscall/editor";
export async function toggleH1() {
await togglePrefix("# ");
@ -13,15 +18,15 @@ function lookBack(s: string, pos: number, backString: string): boolean {
}
async function togglePrefix(prefix: string) {
let text = (await syscall("editor.getText")) as string;
let pos = (await syscall("editor.getCursor")) as number;
let text = await getText();
let pos = await getCursor();
if (text[pos] === "\n") {
pos--;
}
while (pos > 0 && text[pos] !== "\n") {
if (lookBack(text, pos, prefix)) {
// Already has this prefix, let's flip it
await syscall("editor.replaceRange", pos - prefix.length, pos, "");
await replaceRange(pos - prefix.length, pos, "");
return;
}
pos--;
@ -29,5 +34,5 @@ async function togglePrefix(prefix: string) {
if (pos) {
pos++;
}
await syscall("editor.insertAtPos", prefix, pos);
await insertAtPos(prefix, pos);
}

View File

@ -1,7 +1,16 @@
import { syscall } from "../lib/syscall";
import {
flashNotification,
getCurrentPage,
reloadPage,
save,
} from "plugos-silverbullet-syscall/editor";
import { readPage, writePage } from "plugos-silverbullet-syscall/space";
import { invokeFunctionOnServer } from "plugos-silverbullet-syscall/system";
import { scanPrefixGlobal } from "plugos-silverbullet-syscall";
export const queryRegex =
/(<!--\s*#query\s+(?<table>\w+)\s*(filter\s+["'](?<filter>[^"']+)["'])?\s*(group by\s+(?<groupBy>\w+))?\s*-->)(.+?)(<!--\s*#end\s*-->)/gs;
/(<!--\s*#query\s+(?<table>\w+)\s*(filter\s+["'](?<filter>[^"']+)["'])?\s*-->)(.+?)(<!--\s*#end\s*-->)/gs;
export function whiteOutQueries(text: string): string {
return text.replaceAll(queryRegex, (match) =>
@ -25,18 +34,16 @@ async function replaceAsync(
}
export async function updateMaterializedQueriesCommand() {
await syscall(
"system.invokeFunctionOnServer",
"updateMaterializedQueriesOnPage",
await syscall("editor.getCurrentPage")
);
await syscall("editor.reloadPage");
await syscall("editor.flashNotification", "Updated materialized queries");
const currentPage = await getCurrentPage();
await save();
await invokeFunctionOnServer("updateMaterializedQueriesOnPage", currentPage);
await reloadPage();
await flashNotification("Updated materialized queries");
}
// Called from client, running on server
export async function updateMaterializedQueriesOnPage(pageName: string) {
let { text } = await syscall("space.readPage", pageName);
let { text } = await readPage(pageName);
text = await replaceAsync(text, queryRegex, async (match, ...args) => {
let { table, filter, groupBy } = args[args.length - 1];
const startQuery = args[0];
@ -48,22 +55,19 @@ export async function updateMaterializedQueriesOnPage(pageName: string) {
key,
page,
value: { task, complete, children },
} of await syscall("index.scanPrefixGlobal", "task:")) {
} of await scanPrefixGlobal("task:")) {
let [, pos] = key.split(":");
if (!filter || (filter && task.includes(filter))) {
results.push(
`* [${complete ? "x" : " "}] [[${page}@${pos}]] ${task}`
`* [${complete ? "x" : " "}] [[${page}@${pos}]] ${task}` +
(children ? "\n" + children.join("\n") : "")
);
if (children) {
results.push(children.join("\n"));
}
}
}
return `${startQuery}\n${results.join("\n")}\n${endQuery}`;
return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`;
case "link":
let uniqueLinks = new Set<string>();
for (let {key, page, value: name} of await syscall(
"index.scanPrefixGlobal",
for (let { key, page, value: name } of await scanPrefixGlobal(
`pl:${pageName}:`
)) {
let [, pos] = key.split(":");
@ -80,20 +84,20 @@ export async function updateMaterializedQueriesOnPage(pageName: string) {
key,
page,
value: { item, children },
}; of await syscall("index.scanPrefixGlobal", "it:")) {
} of await scanPrefixGlobal("it:")) {
let [, pos] = key.split(":");
if (!filter || (filter && item.includes(filter))) {
results.push(`* [[${page}@${pos}]] ${item}`);
if (children) {
results.push(children.join("\n"));
results.push(
`* [[${page}@${pos}]] ${item}` +
(children ? "\n" + children.join("\n") : "")
);
}
}
}
return `${startQuery}\n${results.join("\n")}\n${endQuery}`;
return `${startQuery}\n${results.sort().join("\n")}\n${endQuery}`;
default:
return match;
}
});
// console.log("New text", text);
await syscall("space.writePage", pageName, text);
await writePage(pageName, text);
}

View File

@ -1,6 +1,11 @@
import { ClickEvent } from "../../webapp/app_event";
import { syscall } from "../lib/syscall";
import { updateMaterializedQueriesCommand } from "./materialized_queries";
import {
getSyntaxNodeAtPos,
getSyntaxNodeUnderCursor,
navigate as navigateTo,
openUrl,
} from "plugos-silverbullet-syscall/editor";
const materializedQueryPrefix = /<!--\s*#query\s+/;
@ -16,10 +21,10 @@ async function navigate(syntaxNode: any) {
if (pageLink.includes("@")) {
[pageLink, pos] = syntaxNode.text.split("@");
}
await syscall("editor.navigate", pageLink, +pos);
await navigateTo(pageLink, +pos);
break;
case "URL":
await syscall("editor.openUrl", syntaxNode.text);
await openUrl(syntaxNode.text);
break;
case "CommentBlock":
if (syntaxNode.text.match(materializedQueryPrefix)) {
@ -30,19 +35,19 @@ async function navigate(syntaxNode: any) {
// Markdown link: [bla](URLHERE) needs extraction
let match = /\[[^\\]+\]\(([^\)]+)\)/.exec(syntaxNode.text);
if (match) {
await syscall("editor.openUrl", match[1]);
await openUrl(match[1]);
}
break;
}
}
export async function linkNavigate() {
await navigate(await syscall("editor.getSyntaxNodeUnderCursor"));
await navigate(await getSyntaxNodeUnderCursor());
}
export async function clickNavigate(event: ClickEvent) {
if (event.ctrlKey || event.metaKey) {
let syntaxNode = await syscall("editor.getSyntaxNodeAtPos", event.pos);
let syntaxNode = await getSyntaxNodeAtPos(event.pos);
await navigate(syntaxNode);
}
}

View File

@ -1,6 +1,27 @@
import { IndexEvent } from "../../webapp/app_event";
import { pageLinkRegex } from "../../webapp/constant";
import { syscall } from "../lib/syscall";
import {
batchSet,
clearPageIndex as clearPageIndexSyscall,
clearPageIndexForPage,
scanPrefixGlobal,
} from "plugos-silverbullet-syscall/index";
import {
flashNotification,
getCurrentPage,
getText,
matchBefore,
navigate,
} from "plugos-silverbullet-syscall/editor";
import { dispatch } from "plugos-syscall/event";
import {
deletePage as deletePageSyscall,
listPages,
readPage,
writePage,
} from "plugos-silverbullet-syscall/space";
import { invokeFunctionOnServer } from "plugos-silverbullet-syscall/system";
const wikilinkRegex = new RegExp(pageLinkRegex, "g");
@ -20,25 +41,21 @@ export async function indexLinks({ name, text }: IndexEvent) {
});
}
console.log("Found", backLinks.length, "wiki link(s)");
await syscall("index.batchSet", name, backLinks);
await batchSet(name, backLinks);
}
export async function deletePage() {
let pageName = await syscall("editor.getCurrentPage");
let pageName = await getCurrentPage();
console.log("Navigating to start page");
await syscall("editor.navigate", "start");
await navigate("start");
console.log("Deleting page from space");
await syscall("space.deletePage", pageName);
await deletePageSyscall(pageName);
}
export async function renamePage() {
const oldName = await syscall("editor.getCurrentPage");
const oldName = await getCurrentPage();
console.log("Old name is", oldName);
const newName = await syscall(
"editor.prompt",
`Rename ${oldName} to:`,
oldName
);
const newName = await prompt(`Rename ${oldName} to:`, oldName);
if (!newName) {
return;
}
@ -47,13 +64,13 @@ export async function renamePage() {
let pagesToUpdate = await getBackLinks(oldName);
console.log("All pages containing backlinks", pagesToUpdate);
let text = await syscall("editor.getText");
let text = await getText();
console.log("Writing new page to space");
await syscall("space.writePage", newName, text);
await writePage(newName, text);
console.log("Navigating to new page");
await syscall("editor.navigate", newName);
await navigate(newName);
console.log("Deleting page from space");
await syscall("space.deletePage", oldName);
await deletePageSyscall(oldName);
let pageToUpdateSet = new Set<string>();
for (let pageToUpdate of pagesToUpdate) {
@ -62,7 +79,7 @@ export async function renamePage() {
for (let pageToUpdate of pageToUpdateSet) {
console.log("Now going to update links in", pageToUpdate);
let { text } = await syscall("space.readPage", pageToUpdate);
let { text } = await readPage(pageToUpdate);
console.log("Received text", text);
if (!text) {
// Page likely does not exist, but at least we can skip it
@ -71,7 +88,7 @@ export async function renamePage() {
let newText = text.replaceAll(`[[${oldName}]]`, `[[${newName}]]`);
if (text !== newText) {
console.log("Changes made, saving...");
await syscall("space.writePage", pageToUpdate, newText);
await writePage(pageToUpdate, newText);
}
}
}
@ -82,7 +99,7 @@ type BackLink = {
};
async function getBackLinks(pageName: string): Promise<BackLink[]> {
let allBackLinks = await syscall("index.scanPrefixGlobal", `pl:${pageName}:`);
let allBackLinks = await scanPrefixGlobal(`pl:${pageName}:`);
let pagesToUpdate: BackLink[] = [];
for (let { key, value } of allBackLinks) {
let keyParts = key.split(":");
@ -95,28 +112,28 @@ async function getBackLinks(pageName: string): Promise<BackLink[]> {
}
export async function showBackLinks() {
const pageName = await syscall("editor.getCurrentPage");
const pageName = await getCurrentPage();
let backLinks = await getBackLinks(pageName);
console.log("Backlinks", backLinks);
}
export async function reindexCommand() {
await syscall("editor.flashNotification", "Reindexing...");
await syscall("system.invokeFunctionOnServer", "reindexSpace");
await syscall("editor.flashNotification", "Reindexing done");
await flashNotification("Reindexing...");
await invokeFunctionOnServer("reindexSpace");
await flashNotification("Reindexing done");
}
// Completion
export async function pageComplete() {
let prefix = await syscall("editor.matchBefore", "\\[\\[[\\w\\s]*");
let prefix = await matchBefore("\\[\\[[\\w\\s]*");
if (!prefix) {
return null;
}
let allPages = await syscall("space.listPages");
let allPages = await listPages();
return {
from: prefix.from + 2,
options: allPages.map((pageMeta: any) => ({
options: allPages.map((pageMeta) => ({
label: pageMeta.name,
type: "page",
})),
@ -126,13 +143,13 @@ export async function pageComplete() {
// Server functions
export async function reindexSpace() {
console.log("Clearing page index...");
await syscall("index.clearPageIndex");
await clearPageIndexSyscall();
console.log("Listing all pages");
let pages = await syscall("space.listPages");
let pages = await listPages();
for (let { name } of pages) {
console.log("Indexing", name);
const pageObj = await syscall("space.readPage", name);
await syscall("event.dispatch", "page:index", {
const pageObj = await readPage(name);
await dispatch("page:index", {
name,
text: pageObj.text,
});
@ -141,5 +158,5 @@ export async function reindexSpace() {
export async function clearPageIndex(page: string) {
console.log("Clearing page index for page", page);
await syscall("index.clearPageIndexForPage", page);
await clearPageIndexForPage(page);
}

View File

@ -1,5 +1,3 @@
import { syscall } from "../lib/syscall";
function countWords(str: string): number {
const matches = str.match(/[\w\d\'-]+/gi);
return matches ? matches.length : 0;
@ -9,12 +7,3 @@ function readingTime(wordCount: number): number {
// 225 is average word reading speed for adults
return Math.ceil(wordCount / 225);
}
export async function wordCount({ text }: { text: string }) {
let sysCallText = (await syscall("editor.getText")) as string;
const count = countWords(sysCallText);
console.log("Word count", count);
let syntaxNode = await syscall("editor.getSyntaxNodeUnderCursor");
console.log("Syntax node", syntaxNode);
return count;
}

View File

@ -1,3 +1,4 @@
build:
curl https://unicode.org/Public/emoji/14.0/emoji-test.txt > emoji-data.txt
node build.js
rm emoji-data.txt

View File

@ -1,11 +1,11 @@
// @ts-ignore
import emojis from "./emoji.json";
import { syscall } from "../lib/syscall";
import { matchBefore } from "plugos-silverbullet-syscall/editor";
const emojiMatcher = /\(([^\)]+)\)\s+(.+)$/;
export async function emojiCompleter() {
let prefix = await syscall("editor.matchBefore", ":[\\w\\s]*");
let prefix = await matchBefore(":[\\w\\s]*");
if (!prefix) {
return null;
}

View File

@ -1,4 +1,6 @@
import { syscall } from "../lib/syscall";
import { run } from "plugos-syscall/shell";
import { flashNotification, prompt } from "plugos-silverbullet-syscall/editor";
import { invokeFunctionOnServer } from "plugos-silverbullet-syscall/system";
export async function commit(message?: string) {
if (!message) {
@ -8,9 +10,9 @@ export async function commit(message?: string) {
"Snapshotting the current space to git with commit message",
message
);
await syscall("shell.run", "git", ["add", "./*.md"]);
await run("git", ["add", "./*.md"]);
try {
await syscall("shell.run", "git", ["commit", "-a", "-m", message]);
await run("git", ["commit", "-a", "-m", message]);
} catch (e) {
// We can ignore, this happens when there's no changes to commit
}
@ -18,26 +20,26 @@ export async function commit(message?: string) {
}
export async function snapshotCommand() {
let revName = await syscall("editor.prompt", `Revision name:`);
let revName = await prompt(`Revision name:`);
if (!revName) {
revName = "Snapshot";
}
console.log("Revision name", revName);
await syscall("system.invokeFunctionOnServer", "commit", revName);
await invokeFunctionOnServer("commit", revName);
}
export async function syncCommand() {
await syscall("editor.flashNotification", "Syncing with git");
await syscall("system.invokeFunctionOnServer", "sync");
await syscall("editor.flashNotification", "Git sync complete!");
await flashNotification("Syncing with git");
await invokeFunctionOnServer("sync");
await flashNotification("Git sync complete!");
}
export async function sync() {
console.log("Going to sync with git");
await commit();
console.log("Then pulling from remote");
await syscall("shell.run", "git", ["pull"]);
await run("git", ["pull"]);
console.log("And then pushing to remote");
await syscall("shell.run", "git", ["push"]);
await run("git", ["push"]);
console.log("Done!");
}

View File

@ -1,5 +1,5 @@
import MarkdownIt from "markdown-it";
import { syscall } from "../lib/syscall";
import { getText, showRhs } from "plugos-silverbullet-syscall/editor";
var taskLists = require("markdown-it-task-lists");
@ -10,7 +10,7 @@ const md = new MarkdownIt({
}).use(taskLists);
export async function renderMarkdown() {
let text = await syscall("editor.getText");
let text = await getText();
let html = md.render(text);
await syscall("editor.showRhs", `<html><body>${html}</body></html>`);
await showRhs(`<html><body>${html}</body></html>`);
}

8
plugs/package.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "plugs",
"version": "1.0.0",
"dependencies": {
"plugos-silverbullet-syscall": "file:../plugos-silverbullet-syscall",
"plugos-syscall": "file:../plugos-syscall"
}
}

View File

@ -1,8 +1,14 @@
import type { ClickEvent } from "../../webapp/app_event";
import { IndexEvent } from "../../webapp/app_event";
import { syscall } from "../lib/syscall";
import { whiteOutQueries } from "../core/materialized_queries";
import { batchSet, scanPrefixGlobal } from "plugos-silverbullet-syscall/index";
import { readPage, writePage } from "plugos-silverbullet-syscall/space";
import {
dispatch,
getLineUnderCursor,
getSyntaxNodeAtPos,
} from "plugos-silverbullet-syscall/editor";
const allTasksPageName = "ALL TASKS";
const taskRe = /[\-\*]\s*\[([ Xx])\]\s*(.*)/g;
@ -45,11 +51,11 @@ export async function indexTasks({ name, text }: IndexEvent) {
});
}
console.log("Found", tasks.length, "task(s)");
await syscall("index.batchSet", name, tasks);
await batchSet(name, tasks);
}
export async function updateTaskPage() {
let allTasks = await syscall("index.scanPrefixGlobal", "task:");
let allTasks = await scanPrefixGlobal("task:");
let pageTasks = new Map<string, Task[]>();
for (let {
key,
@ -61,7 +67,7 @@ export async function updateTaskPage() {
}
let [, pos] = key.split(":");
let tasks = pageTasks.get(page) || [];
tasks.push({ task, complete, pos });
tasks.push({ task, complete, pos: +pos });
pageTasks.set(page, tasks);
}
@ -78,17 +84,17 @@ export async function updateTaskPage() {
}
let taskMd = mdPieces.join("\n");
await syscall("space.writePage", allTasksPageName, taskMd);
await writePage(allTasksPageName, taskMd);
}
export async function taskToggle(event: ClickEvent) {
let syntaxNode = await syscall("editor.getSyntaxNodeAtPos", event.pos);
let syntaxNode = await getSyntaxNodeAtPos(event.pos);
if (syntaxNode && syntaxNode.name === "TaskMarker") {
let changeTo = "[x]";
if (syntaxNode.text === "[x]" || syntaxNode.text === "[X]") {
changeTo = "[ ]";
}
await syscall("editor.dispatch", {
await dispatch({
changes: {
from: syntaxNode.from,
to: syntaxNode.to,
@ -100,12 +106,12 @@ export async function taskToggle(event: ClickEvent) {
});
if (event.page === allTasksPageName) {
// Propagate back to the page in question
let line = (await syscall("editor.getLineUnderCursor")) as string;
let line = await getLineUnderCursor();
let match = line.match(extractPageLink);
if (match) {
let [, page, posS] = match;
let pos = +posS;
let pageData = await syscall("space.readPage", page);
let pageData = await readPage(page);
let text = pageData.text;
// Apply the toggle
@ -113,7 +119,7 @@ export async function taskToggle(event: ClickEvent) {
text.substring(0, pos) +
text.substring(pos).replace(/^([\-\*]\s*)\[[ xX]\]/, "$1" + changeTo);
await syscall("space.writePage", page, text);
await writePage(page, text);
}
}
}

View File

@ -1,6 +1,6 @@
import { mkdir, readdir, readFile, stat, unlink, writeFile } from "fs/promises";
import * as path from "path";
import { PageMeta } from "./types";
import { PageMeta } from "../common/types";
import { EventHook } from "../plugos/hooks/event";
export interface Storage {

View File

@ -1,4 +1,4 @@
import { PageMeta } from "../types";
import { PageMeta } from "../../common/types";
import { SysCallMapping } from "../../plugos/system";
import { Storage } from "../disk_storage";

View File

@ -1,6 +1,6 @@
import { PageMeta } from "../types";
import { FilterList, Option } from "./filter";
import { faFileLines } from "@fortawesome/free-solid-svg-icons";
import { PageMeta } from "../../common/types";
export function PageNavigator({
allPages,

View File

@ -1,8 +1,8 @@
import { PageMeta } from "./types";
import { EventEmitter } from "../common/event";
import { Manifest } from "../common/manifest";
import { safeRun } from "./util";
import { Plug } from "../plugos/plug";
import { PageMeta } from "../common/types";
export type SpaceEvents = {
pageCreated: (meta: PageMeta) => void;

View File

@ -36,6 +36,9 @@ export default (editor: Editor): SysCallMapping => ({
getCursor: (): number => {
return editor.editorView!.state.selection.main.from;
},
save: async () => {
return editor.save(true);
},
navigate: async (ctx, name: string, pos: number) => {
await editor.navigate(name, pos);
},

View File

@ -1,6 +1,6 @@
import { Editor } from "../editor";
import { PageMeta } from "../types";
import { SysCallMapping } from "../../plugos/system";
import { PageMeta } from "../../common/types";
export default (editor: Editor): SysCallMapping => ({
listPages: async (): Promise<PageMeta[]> => {

View File

@ -1,12 +1,5 @@
import { AppCommand } from "./hooks/command";
export type PageMeta = {
name: string;
lastModified: number;
version?: number;
lastOpened?: number;
created?: boolean;
};
import { PageMeta } from "../common/types";
export const slashCommandRegexp = /\/[\w\-]*/;