Space script to move a task to another page

Here’s a space script I’ve been using recently to move tasks from one note to another:

async function refile(targetPage, targetHeading) {
  try {
    const cursorPos = await syscall("editor.getCursor");
    const text = await syscall("editor.getText");
    const currentItemBounds = await syscall("system.invokeFunction", "editor.determineItemBounds", text, cursorPos, undefined, true);
    const currentItemText = text.slice(currentItemBounds.from, currentItemBounds.to);
    const targetContent = await syscall("space.readPage", targetPage);
    const headingRegex = new RegExp(`^#+\\s${targetHeading}`, 'm');
    const headingMatch = targetContent.match(headingRegex);
    if (!headingMatch) {
      throw new Error("Heading not found.");
    }

    const headingIndex = headingMatch.index + headingMatch[0].length;
    let insertPosition = targetContent.indexOf("\n", headingIndex);

    if (insertPosition === -1) {
      insertPosition = headingIndex;
    } else {
      insertPosition += 1;
    }

    const listEndRegex = /^[^\s(-|\*)]/gm;
    let listEndMatch = listEndRegex.exec(targetContent.slice(insertPosition));
    listEndMatch = listEndMatch ? insertPosition + listEndMatch.index : targetContent.length;

    // Remove any extra new lines between items
    const cleanedTargetContent = targetContent.slice(0, listEndMatch).replace(/\n{2,}/g, '\n') + `${currentItemText}\n` + targetContent.slice(listEndMatch);
    await syscall("space.writePage", targetPage, cleanedTargetContent);
    await syscall("editor.replaceRange", currentItemBounds.from, currentItemBounds.to, "");
    await syscall("editor.flashNotification", "Item refiled successfully.");
  } catch (error) {
    await syscall("editor.flashNotification", error.message, "error");
  }
}

Most of my tasks lately are going into a simple TODOs file with headings of Personal, Work, etc. So I have these commands to easily move tasks to one of these headings:

silverbullet.registerCommand({name: "refile-todos-personal"}, async () => {
  const targetPage = "TODOs";
  const targetHeading = "Personal";
  await refile(targetPage, targetHeading);
});

silverbullet.registerCommand({name: "refile-todos-work"}, async () => {
  const targetPage = "TODOs";
  const targetHeading = "Work";
  await refile(targetPage, targetHeading);
});

Keep in mind this does not work very well when moving tasks on the same page you’re currently editing. The targets are also hardcoded for now, but I don’t think it should be too hard to make a generic ‘refile’ command that opens up a filterbox to select a target page and header to move an item to.

2 Likes