[Space-Script] Selection -> Bash CodeBlock

Hi everyone! :tada:

This is my first script which I did using the helpt of ChatGPT (I’m not a dev or coder myself).
But I wanted to share it with you all.

It’s a simple yet handy script that wraps a selected portion of text in a bash codeblock by adding the ```bash delimiter one line above the selection and the closing ``` delimiter one line below.

What This Script Does:

Automatically wraps selected text in a Bash code block.
Ensures the ```bash and ``` delimiters are properly placed above and below the selected text.
Triggered with a keyboard shortcut (Alt-Cmd-1) by default, but you can modify it).

silverbullet.registerCommand({
   name: "Selection to Bash CodeBlock",
   key: "Alt-Cmd-1"
}, async () => {
  const selection = await syscall("editor.getSelection");
  const from = selection.from;
  const to = selection.to;

  // Get the content of the editor to identify line positions
  const content = await syscall("editor.getText");
  const beforeSelection = content.slice(0, from);
  const afterSelection = content.slice(to);

  // Find the positions of the line boundaries
  const startOfLineBefore = beforeSelection.lastIndexOf("\n") + 1;
  const endOfLineAfter = to + afterSelection.indexOf("\n", 1);

  await syscall("editor.dispatch", {
    changes: [
      { from: startOfLineBefore, to: startOfLineBefore, insert: "```bash\n" },
      { from: endOfLineAfter, to: endOfLineAfter, insert: "\n```" },
    ],
  });
});

It works perfectly for me, though it might not be the cleanest implementation since I’m still new to scripting. Feedback and improvements are welcome! :blush:

4 Likes

Hi everyone :wave:

I’ve updated my previous script for wrapping selections in code block delimiters. The new version doesn’t just wrap selections → it now toggles! :bulb: When you trigger it:

  • If the selection is not wrapped, it will add the delimiters (e.g., ```bash).
  • If the selection is already wrapped, it will recognize the delimiters and remove them.

Why the Update?

This enhancement makes the script more intuitive and saves you time when editing. No more manually removing ```bash lines and backticks when you want to undo a code block!
How to Use:

Screenrecording

Customization:
Want a different language? Just change the CODE_BLOCK_SYNTAX constant at the top of the script. Super simple!
CODE_BLOCK_SYNTAX = "bash";

Change also the Name and Shortcut-Keys for your use case:
name: "Selection to Bash"
key: "Alt-Cmd-1"

Here’s the updated space-script for anyone who wants to check it out:

//-------------------Toggle selection to Codeblock--------------------
silverbullet.registerCommand({
  name: "Selection to Bash",
  key: "Alt-Cmd-1"
}, async () => {
  // Define the syntax for the code block to add
  const CODE_BLOCK_SYNTAX = "bash"; // Change this to your desired language

  // Get the current selection and editor content
  const selection = await syscall("editor.getSelection");
  const from = selection.from;
  const to = selection.to;
  const content = await syscall("editor.getText");
  const lines = content.split("\n");

  // Determine the start and end line numbers of the selection
  const startLine = content.slice(0, from).split("\n").length - 1;
  const endLine = content.slice(0, to).split("\n").length - 1;

  // Get the line above and below the selection
  const lineAboveIndex = Math.max(startLine - 1, 0);
  const lineBelowIndex = Math.min(endLine + 1, lines.length - 1);
  const lineAbove = lines[lineAboveIndex]?.trim();
  const lineBelow = lines[lineBelowIndex]?.trim();

  // Check for existing delimiters with a wildcard for code block names (including hyphens)
  const delimiterPattern = /^```([\w-]+)?$/;  
  const startsWithDelimiter = delimiterPattern.test(lineAbove);
  const endsWithDelimiter = lineBelow === "```";

  if (startsWithDelimiter && endsWithDelimiter) {
    // If the selection is already wrapped, remove the delimiters
    const startOfLineAbove = content.split("\n").slice(0, lineAboveIndex).join("\n").length + (lineAboveIndex > 0 ? 1 : 0);
    const endOfLineBelow = content.split("\n").slice(0, lineBelowIndex + 1).join("\n").length;

    await syscall("editor.dispatch", {
      changes: [
        { from: startOfLineAbove, to: startOfLineAbove + lineAbove.length + 1, insert: "" },
        { from: endOfLineBelow - "\n```".length, to: endOfLineBelow, insert: "" },
      ],
    });
  } else {
    // Otherwise, add the new delimiters around the selection
    const beforeSelection = content.slice(0, from);
    const afterSelection = content.slice(to);

    // Find the line boundaries for adding delimiters
    const startOfLineBefore = beforeSelection.lastIndexOf("\n") + 1;
    const endOfLineAfter = to + (afterSelection.indexOf("\n") === -1 ? afterSelection.length : afterSelection.indexOf("\n"));

    await syscall("editor.dispatch", {
      changes: [
        { from: startOfLineBefore, to: startOfLineBefore, insert: `\`\`\`${CODE_BLOCK_SYNTAX}\n` },
        { from: endOfLineAfter, to: endOfLineAfter, insert: "\n```" },
      ],
    });
  }
});

Hope this makes your workflow smoother! :rocket:
Feedback and ideas are always welcome. Let me know what you think!

Happy silverbulleting! :black_heart:

4 Likes