Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
.vscode
yarn.lock
coverage
node_modules
node_modules
.idea
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
"build": "parcel build src/index.ts -o build/pyroam.js",
"test": "jest --coverage"
},
"dependencies": {
"roam-client": "^1.76.3"
},
"devDependencies": {
"@babel/core": "^7.13.8",
"@babel/preset-env": "^7.13.9",
Expand Down
55 changes: 29 additions & 26 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { createUid, processCodeBlocks } from "./helpers";
import {processCodeBlocks} from "./helpers"
import {createBlock, getOrderByBlockUid, getParentUidByBlockUid} from "roam-client"

/* === WRAPPERS === */
export const q = async (query) => {
//@ts-ignore
const result = await window.roamAlphaAPI.q(query);
if (!result || result.length === 0) {
return null;
} else return result;
};

export const updateBlock = async (uid, string) => {
//@ts-ignore
await window.roamAlphaAPI.updateBlock({
block: {
uid: uid,
Expand All @@ -19,20 +18,6 @@ export const updateBlock = async (uid, string) => {
});
};

export const createBlock = async (parentUid, order, uid, string) => {
//@ts-ignore
await window.roamAlphaAPI.createBlock({
location: {
"parent-uid": parentUid,
order: order,
},
block: {
uid: uid,
string: string,
},
});
};

/* === COMPOSITE FUNCTIONS === */
export const getBlockStringByUid = async (uid) => {
const query = `[:find (pull ?block [:block/string])
Expand All @@ -54,11 +39,14 @@ export const writeToNestedBlock = async (parentUid, string) => {

const result = await q(query);
if (!result) {
const nestedUid = createUid();
createBlock(parentUid, 0, nestedUid, string);
createBlock({
node: {text: string},
parentUid,
order: 0
})
} else {
const nestedUid = result[0][0].uid;
updateBlock(nestedUid, string);
return updateBlock(nestedUid, string);
}
};

Expand All @@ -84,13 +72,28 @@ export const getUidOfClosestBlockReferencing = async (uid: string, page: string)
};

export const getAllCodeBlocksNestedUnder = async (topUid) => {
//@ts-ignore
var results = await window.roamAlphaAPI.q('[:find\
const results = await window.roamAlphaAPI.q('[:find\
(pull ?cell [:block/string :block/order :block/uid {:block/_children ...}])\
:where [?notebookBlock :block/uid "' + topUid + '"]\
[?cell :block/parents ?notebookBlock]\
[?cell :block/string ?string]\
[(clojure.string/starts-with? ?string "```python")]]');
const cells = processCodeBlocks(results, topUid);
return cells;
};
[(clojure.string/starts-with? ?string "```python")]]')
return processCodeBlocks(results, topUid);
};

export async function createNextPythonBlock(activeUid: string) {
// todo generate hiccup for displaying complex things?
// todo interactive output
// todo proper click on the new code block

const order = getOrderByBlockUid(activeUid) + 1
const newUuid = createBlock({
node: {
text: "```python\n```",
},
parentUid: getParentUidByBlockUid(activeUid),
order,
})

console.log("Created new python block:", newUuid)
}
34 changes: 9 additions & 25 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* ====== BASIC ======= */

export const sleep = (m) => {
var t = m ? m : 10;
return new Promise((r) => setTimeout(r, t));
Expand All @@ -20,32 +21,15 @@ export const addScriptToPage = (tagId, script) => {
);
};

export const createUid = () => {
// From roam42 based on https://github.com/ai/nanoid#js version 3.1.2
let nanoid = (t = 21) => {
let e = "",
r = crypto.getRandomValues(new Uint8Array(t));
for (; t--;) {
let n = 63 & r[t];
e +=
n < 36
? n.toString(36)
: n < 62
? (n - 26).toString(36).toUpperCase()
: n < 63
? "_"
: "-";
}
return e;
};
return nanoid(9);
};
export function getActiveRoamInputElement() {
const el = document.activeElement
return el.closest(".rm-block__input")
}

export const getActiveBlockUid = () => {
const el = document.activeElement;
const uid = el.closest(".rm-block__input").id.slice(-9);
return uid;
};
const roamInput = getActiveRoamInputElement()
return roamInput.id.slice(-9)
}

export const removeBackticks = (str: string) => {
var ttt = "``" + "`";
Expand Down Expand Up @@ -129,4 +113,4 @@ export const processCodeBlocks = (codeblocks, uid) => {
}
})
return cells;
}
}
16 changes: 12 additions & 4 deletions src/keyboard.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import {runActiveBlockAndWriteToNext, runActiveNotebook} from "./notebook"
import {getActiveBlockUid} from "./helpers"
import {createNextPythonBlock} from "./api"

import { runActiveBlockAndWriteToNext, runActiveNotebook } from "./notebook";

export const handleKeyPress = async (e) => {
export const handleKeyPress = async (e: KeyboardEvent) => {
if (e.code === "Enter" && e.altKey === true && !e.shiftKey) {
runActiveBlockAndWriteToNext();
await runActiveBlockAndWriteToNext()
} else if (e.code === "Enter" && e.metaKey === true ) {
await runActiveBlockAndWriteToNext()
await createNextPythonBlock(getActiveBlockUid())
e.stopPropagation()
} else if (e.code === "Enter" && e.altKey === true && e.shiftKey === true) {
runActiveNotebook();
} else if (e.key === "-" && e.ctrlKey === true && e.metaKey === true) {
console.log("pyroam: Removing key listener")
document.removeEventListener("keydown", handleKeyPress)
}
};
24 changes: 12 additions & 12 deletions src/notebook.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { getActiveBlockUid, getActiveCodeBlockContent as getActiveCodeBlockContent, removeBackticks } from "./helpers";
import { q, writeToNestedBlock, getUidOfClosestBlockReferencing, getAllCodeBlocksNestedUnder, getBlockStringByUid } from "./api";
import { runPython } from "./pyodide";
import {getActiveBlockUid, getActiveCodeBlockContent as getActiveCodeBlockContent} from "./helpers"
import {getAllCodeBlocksNestedUnder, getUidOfClosestBlockReferencing, writeToNestedBlock} from "./api"
import {runPython} from "./pyodide"


const runAllBlocksBelowUidAndWrite = async (notebookUid) => {
const cells = await getAllCodeBlocksNestedUnder(notebookUid);
const activeUid = getActiveBlockUid();
const cells = await getAllCodeBlocksNestedUnder(notebookUid)
const activeUid = getActiveBlockUid()

for (const cell of cells) {
if (cell.uid === activeUid) cell.string = getActiveCodeBlockContent()

const out = await runPython(cell.string);
const out = await runPython(cell.string)
await writeToNestedBlock(cell.uid, out)
}
}
Expand All @@ -19,18 +19,18 @@ const runAllBlocksBelowUidAndWrite = async (notebookUid) => {
* Runs only the active cell
*/
export const runActiveBlockAndWriteToNext = async () => {
const activeUid = getActiveBlockUid();
const activeUid = getActiveBlockUid()
const code = getActiveCodeBlockContent()
const out = await runPython(code)
await writeToNestedBlock(activeUid, out)
};
}

/**
* Runs the whole notebook
*/
export const runActiveNotebook = async () => {
const uid = getActiveBlockUid();
const notebookUid = await getUidOfClosestBlockReferencing(uid, "pyroam/notebook");
const uid = getActiveBlockUid()
const notebookUid = await getUidOfClosestBlockReferencing(uid, "pyroam/notebook")
console.log("Notebook Block uid:" + notebookUid)
runAllBlocksBelowUidAndWrite(notebookUid);
}
runAllBlocksBelowUidAndWrite(notebookUid)
}