From abbd718e6a1898971f7cc82d9f2732dbb11feb35 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Mon, 10 Aug 2026 11:29:59 +0200 Subject: [PATCH] acme: add ollie integration commands Add acme scripts for interacting with ollie: - AskFile: describe the current file - Explain: explain selected code - Document: add documentation comments - Fix: fix selected code - Refactor: refactor selected code - AddTests: write unit tests for selection - SendVerbatim: send selection as-is Scripts use the acme 9P filesystem to read selections and pipe prompts to ollie via 'o prompt'. Also update justfile to install/uninstall the acme scripts. --- data/scripts/acme/AddTests | 39 +++++++++++++++++++++ data/scripts/acme/AskFile | 26 ++++++++++++++ data/scripts/acme/Document | 39 +++++++++++++++++++++ data/scripts/acme/Explain | 40 +++++++++++++++++++++ data/scripts/acme/Fix | 39 +++++++++++++++++++++ data/scripts/acme/README.md | 56 +++++++++++++++++++++++++++++ data/scripts/acme/Refactor | 39 +++++++++++++++++++++ data/scripts/acme/SendVerbatim | 64 ++++++++++++++++++++++++++++++++++ justfile | 10 ++++++ 9 files changed, 352 insertions(+) create mode 100755 data/scripts/acme/AddTests create mode 100755 data/scripts/acme/AskFile create mode 100755 data/scripts/acme/Document create mode 100755 data/scripts/acme/Explain create mode 100755 data/scripts/acme/Fix create mode 100644 data/scripts/acme/README.md create mode 100755 data/scripts/acme/Refactor create mode 100755 data/scripts/acme/SendVerbatim diff --git a/data/scripts/acme/AddTests b/data/scripts/acme/AddTests new file mode 100755 index 0000000..e97980f --- /dev/null +++ b/data/scripts/acme/AddTests @@ -0,0 +1,39 @@ +#!/bin/bash +# AddTests - Ask ollie to write unit tests for the selected code +# +# Usage: Select code, then middle-click AddTests in the tag + +set -euo pipefail + +if [[ -z "${winid:-}" ]]; then + echo "AddTests must be run from within acme" >&2 + exit 1 +fi + +# Get the window name (filename) from the tag +filename=$(9p read acme/$winid/tag | awk '{print $1}') + +# Read the current selection +echo 'addr=dot' | 9p write acme/$winid/ctl +selection=$(9p read acme/$winid/xdata 2>/dev/null || true) + +if [[ -z "$selection" ]]; then + echo "No selection. Select some code first." >&2 + exit 1 +fi + +# Build location string +location="" +if [[ -n "$filename" && "$filename" != *"+Errors" && "$filename" != "+*" ]]; then + location=" in \`$filename\`" +fi + +# Build the prompt +prompt="Write unit tests for this code${location}: + +\`\`\` +$selection +\`\`\`" + +# Send to ollie +echo "$prompt" | o prompt diff --git a/data/scripts/acme/AskFile b/data/scripts/acme/AskFile new file mode 100755 index 0000000..1f64e1d --- /dev/null +++ b/data/scripts/acme/AskFile @@ -0,0 +1,26 @@ +#!/bin/bash +# AskFile - Ask ollie about the current file in acme +# +# Usage: Middle-click AskFile in the tag +# Sends: "Describe and explain this file: " + +set -euo pipefail + +if [[ -z "${winid:-}" ]]; then + echo "AskFile must be run from within acme" >&2 + exit 1 +fi + +# Get the window name (filename) from the tag +filename=$(9p read acme/$winid/tag | awk '{print $1}') + +if [[ -z "$filename" || "$filename" == *"+Errors" || "$filename" == "+*" ]]; then + echo "No file associated with this window" >&2 + exit 1 +fi + +# Build the prompt +prompt="Describe and explain this file: $filename" + +# Send to ollie via the o script +echo "$prompt" | o prompt diff --git a/data/scripts/acme/Document b/data/scripts/acme/Document new file mode 100755 index 0000000..ccd58d9 --- /dev/null +++ b/data/scripts/acme/Document @@ -0,0 +1,39 @@ +#!/bin/bash +# Document - Ask ollie to add documentation comments to selected code +# +# Usage: Select code, then middle-click Document in the tag + +set -euo pipefail + +if [[ -z "${winid:-}" ]]; then + echo "Document must be run from within acme" >&2 + exit 1 +fi + +# Get the window name (filename) from the tag +filename=$(9p read acme/$winid/tag | awk '{print $1}') + +# Read the current selection +echo 'addr=dot' | 9p write acme/$winid/ctl +selection=$(9p read acme/$winid/xdata 2>/dev/null || true) + +if [[ -z "$selection" ]]; then + echo "No selection. Select some code first." >&2 + exit 1 +fi + +# Build location string +location="" +if [[ -n "$filename" && "$filename" != *"+Errors" && "$filename" != "+*" ]]; then + location=" in \`$filename\`" +fi + +# Build the prompt +prompt="Add documentation comments to this code${location}: + +\`\`\` +$selection +\`\`\`" + +# Send to ollie +echo "$prompt" | o prompt diff --git a/data/scripts/acme/Explain b/data/scripts/acme/Explain new file mode 100755 index 0000000..d64ceef --- /dev/null +++ b/data/scripts/acme/Explain @@ -0,0 +1,40 @@ +#!/bin/bash +# Explain - Ask ollie to explain the selected code in acme +# +# Usage: Select code, then middle-click Explain in the tag +# Sends: "Explain this code (from ):\n\n```\n\n```" + +set -euo pipefail + +if [[ -z "${winid:-}" ]]; then + echo "Explain must be run from within acme" >&2 + exit 1 +fi + +# Get the window name (filename) from the tag +filename=$(9p read acme/$winid/tag | awk '{print $1}') + +# Read the current selection by setting addr to dot and reading xdata +echo 'addr=dot' | 9p write acme/$winid/ctl +selection=$(9p read acme/$winid/xdata 2>/dev/null || true) + +if [[ -z "$selection" ]]; then + echo "No selection. Select some code first." >&2 + exit 1 +fi + +# Build context string +context="" +if [[ -n "$filename" && "$filename" != *"+Errors" && "$filename" != "+*" ]]; then + context=" (from $filename)" +fi + +# Build the prompt +prompt="Explain this code${context}: + +\`\`\` +$selection +\`\`\`" + +# Send to ollie +echo "$prompt" | o prompt diff --git a/data/scripts/acme/Fix b/data/scripts/acme/Fix new file mode 100755 index 0000000..d8ad140 --- /dev/null +++ b/data/scripts/acme/Fix @@ -0,0 +1,39 @@ +#!/bin/bash +# Fix - Ask ollie to fix the selected code +# +# Usage: Select code, then middle-click Fix in the tag + +set -euo pipefail + +if [[ -z "${winid:-}" ]]; then + echo "Fix must be run from within acme" >&2 + exit 1 +fi + +# Get the window name (filename) from the tag +filename=$(9p read acme/$winid/tag | awk '{print $1}') + +# Read the current selection +echo 'addr=dot' | 9p write acme/$winid/ctl +selection=$(9p read acme/$winid/xdata 2>/dev/null || true) + +if [[ -z "$selection" ]]; then + echo "No selection. Select some code first." >&2 + exit 1 +fi + +# Build location string +location="" +if [[ -n "$filename" && "$filename" != *"+Errors" && "$filename" != "+*" ]]; then + location=" in \`$filename\`" +fi + +# Build the prompt +prompt="Fix this code${location}: + +\`\`\` +$selection +\`\`\`" + +# Send to ollie +echo "$prompt" | o prompt diff --git a/data/scripts/acme/README.md b/data/scripts/acme/README.md new file mode 100644 index 0000000..3b221fc --- /dev/null +++ b/data/scripts/acme/README.md @@ -0,0 +1,56 @@ +# Ollie Acme Commands + +These scripts integrate ollie with the acme text editor. They use the acme 9P +filesystem to read selections and send prompts to ollie. + +## Prerequisites + +- An active ollie session with `$session` and `$agent` environment variables set +- The `o` script in PATH +- plan9port's `9p` command + +## Commands + +| Command | Selection Required | Description | +|---------|-------------------|-------------| +| AskFile | No | Describe and explain the current file | +| Explain | Yes | Explain the selected code | +| Document | Yes | Add documentation comments to selected code | +| Fix | Yes | Fix issues in the selected code | +| Refactor | Yes | Refactor the selected code | +| AddTests | Yes | Write unit tests for the selected code | +| SendVerbatim | Yes | Send selection as-is (wrapped in code fence) | + +## Installation + +Add the scripts directory to your PATH or symlink them to a directory in PATH: + +``` +export PATH="$PATH:/path/to/ollie/data/scripts/acme" +``` + +Or symlink individual commands: + +``` +ln -s /path/to/ollie/data/scripts/acme/* ~/bin/ +``` + +## Usage + +1. Start an ollie session and set environment: + ``` + eval $(o env mysession myagent) + ``` + +2. In acme, add the commands to your window's tag: + ``` + AskFile Explain Fix Refactor Document AddTests SendVerbatim + ``` + +3. For commands requiring selection, select text first, then middle-click the command. + +## Example Tag + +``` +/home/user/project/main.go Del Snarf Undo Put | AskFile Explain Fix Refactor +``` diff --git a/data/scripts/acme/Refactor b/data/scripts/acme/Refactor new file mode 100755 index 0000000..faeb35a --- /dev/null +++ b/data/scripts/acme/Refactor @@ -0,0 +1,39 @@ +#!/bin/bash +# Refactor - Ask ollie to refactor the selected code +# +# Usage: Select code, then middle-click Refactor in the tag + +set -euo pipefail + +if [[ -z "${winid:-}" ]]; then + echo "Refactor must be run from within acme" >&2 + exit 1 +fi + +# Get the window name (filename) from the tag +filename=$(9p read acme/$winid/tag | awk '{print $1}') + +# Read the current selection +echo 'addr=dot' | 9p write acme/$winid/ctl +selection=$(9p read acme/$winid/xdata 2>/dev/null || true) + +if [[ -z "$selection" ]]; then + echo "No selection. Select some code first." >&2 + exit 1 +fi + +# Build location string +location="" +if [[ -n "$filename" && "$filename" != *"+Errors" && "$filename" != "+*" ]]; then + location=" in \`$filename\`" +fi + +# Build the prompt +prompt="Refactor this code${location}: + +\`\`\` +$selection +\`\`\`" + +# Send to ollie +echo "$prompt" | o prompt diff --git a/data/scripts/acme/SendVerbatim b/data/scripts/acme/SendVerbatim new file mode 100755 index 0000000..b7639e8 --- /dev/null +++ b/data/scripts/acme/SendVerbatim @@ -0,0 +1,64 @@ +#!/bin/bash +# SendVerbatim - Send the selected text to ollie as-is (wrapped in code fence) +# +# Usage: Select text, then middle-click SendVerbatim in the tag +# The selection is sent wrapped in a code fence with language detection + +set -euo pipefail + +if [[ -z "${winid:-}" ]]; then + echo "SendVerbatim must be run from within acme" >&2 + exit 1 +fi + +# Get the window name (filename) from the tag +filename=$(9p read acme/$winid/tag | awk '{print $1}') + +# Read the current selection +echo 'addr=dot' | 9p write acme/$winid/ctl +selection=$(9p read acme/$winid/xdata 2>/dev/null || true) + +if [[ -z "$selection" ]]; then + echo "No selection. Select some text first." >&2 + exit 1 +fi + +# Detect language from file extension +lang="" +if [[ -n "$filename" && "$filename" != *"+Errors" && "$filename" != "+*" ]]; then + ext="${filename##*.}" + case "$ext" in + go) lang="go" ;; + c|h) lang="c" ;; + cpp|cc|cxx|hpp|hxx) lang="cpp" ;; + py) lang="python" ;; + js) lang="javascript" ;; + ts) lang="typescript" ;; + rs) lang="rust" ;; + rb) lang="ruby" ;; + java) lang="java" ;; + kt) lang="kotlin" ;; + sh|bash) lang="bash" ;; + zsh) lang="zsh" ;; + pl) lang="perl" ;; + lua) lang="lua" ;; + sql) lang="sql" ;; + html) lang="html" ;; + css) lang="css" ;; + json) lang="json" ;; + yaml|yml) lang="yaml" ;; + toml) lang="toml" ;; + xml) lang="xml" ;; + md) lang="markdown" ;; + diff) lang="diff" ;; + *) lang="" ;; + esac +fi + +# Build the prompt - just the code fence with selection +prompt="\`\`\`${lang} +$selection +\`\`\`" + +# Send to ollie +echo "$prompt" | o prompt diff --git a/justfile b/justfile index 530cbf8..befab8e 100644 --- a/justfile +++ b/justfile @@ -188,6 +188,14 @@ install-data: install -m755 data/scripts/ollie-remount {{bin}}/ollie-remount install -m755 data/scripts/logseq-cli {{bin}}/logseq-cli install -m755 data/scripts/o {{bin}}/o + # Acme scripts + install -m755 data/scripts/acme/AskFile {{bin}}/AskFile + install -m755 data/scripts/acme/Explain {{bin}}/Explain + install -m755 data/scripts/acme/Document {{bin}}/Document + install -m755 data/scripts/acme/Fix {{bin}}/Fix + install -m755 data/scripts/acme/Refactor {{bin}}/Refactor + install -m755 data/scripts/acme/AddTests {{bin}}/AddTests + install -m755 data/scripts/acme/SendVerbatim {{bin}}/SendVerbatim install-autostart: @echo === Installing autostart files === @@ -206,6 +214,7 @@ uninstall: rm -f {{bin}}/Ollie {{bin}}/Kmpl {{bin}}/Oi {{bin}}/Theo rm -f {{bin}}/ollie-remount {{bin}}/o rm -f {{bin}}/prompt {{bin}}/ollieread {{bin}}/sendctl {{bin}}/ollie-ls + rm -f {{bin}}/AskFile {{bin}}/Explain {{bin}}/Document {{bin}}/Fix {{bin}}/Refactor {{bin}}/AddTests {{bin}}/SendVerbatim rm -rf {{cfg}} # Service files rm -f ~/.config/systemd/user/ollie.service @@ -223,6 +232,7 @@ uninstall-kf5: rm -f {{bin}}/Ollie {{bin}}/Kmpl {{bin}}/Oi {{bin}}/Theo rm -f {{bin}}/ollie-remount {{bin}}/o rm -f {{bin}}/prompt {{bin}}/ollieread {{bin}}/sendctl {{bin}}/ollie-ls + rm -f {{bin}}/AskFile {{bin}}/Explain {{bin}}/Document {{bin}}/Fix {{bin}}/Refactor {{bin}}/AddTests {{bin}}/SendVerbatim rm -rf {{cfg}} # Service files rm -f ~/.config/systemd/user/ollie.service