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.
This commit is contained in:
Levi Neely 2026-08-10 11:29:59 +02:00
parent 46524d37dd
commit abbd718e6a
9 changed files with 352 additions and 0 deletions

39
data/scripts/acme/AddTests Executable file
View File

@ -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

26
data/scripts/acme/AskFile Executable file
View File

@ -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: <filename>"
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

39
data/scripts/acme/Document Executable file
View File

@ -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

40
data/scripts/acme/Explain Executable file
View File

@ -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 <filename>):\n\n```\n<selection>\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

39
data/scripts/acme/Fix Executable file
View File

@ -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

View File

@ -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
```

39
data/scripts/acme/Refactor Executable file
View File

@ -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

64
data/scripts/acme/SendVerbatim Executable file
View File

@ -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

View File

@ -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