Skip to content

Commit 8426fb4

Browse files
authored
Merge pull request #59 from BetterThanTomorrow/58-multi-edit
Replace four edit tools with one supporting multi edit batch tool * Fixes #58
2 parents b8e02f2 + 4af8364 commit 8426fb4

19 files changed

Lines changed: 785 additions & 597 deletions

File tree

AGENTS.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,14 @@ Implemented in `integrations/calva/editor-util.cljs`:
124124
## Structural Editing Tools
125125

126126
### Text Targeting
127-
Tools use `targetLineText` (first line of target form) + line number ±2:
127+
The `clojure_edit_files` tool uses `targetLineText` (first line of target form) + line number ±2:
128128
```clojure
129-
;; replace_top_level_form or insert_top_level_form
130-
{:filePath "/absolute/path.clj"
131-
:line 23
132-
:targetLineText "(defn multiply-numbers"
133-
:newForm "(defn multiply-numbers\n [x y]\n (* x y))"}
129+
;; clojure_edit_files batch with replace/insert edits
130+
{:edits [{:type "replace"
131+
:filePath "/absolute/path.clj"
132+
:line 23
133+
:targetLineText "(defn multiply-numbers"
134+
:newForm "(defn multiply-numbers\n [x y]\n (* x y))"}]}
134135
```
135136

136137
### Automatic Features

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Changes to Calva Backseat Driver
44

55
## [Unreleased]
66

7+
- [Replace four structural editing tools with single batch `clojure_edit_files` tool](https://github.com/BetterThanTomorrow/calva-backseat-driver/issues/58)
8+
- Supports replace, insert, append, and create operations in one call
9+
- Schema pre-validation, automatic sort order, per-file diagnostics
10+
- Removes: `replace_top_level_form`, `insert_top_level_form`, `clojure_create_file`, `clojure_append_code`
11+
712
## [v0.0.33] - 2026-05-15
813

914
- [Make editing tools headless](https://github.com/BetterThanTomorrow/calva-backseat-driver/issues/57)

assets/instructions/backseat-driver.instructions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ The term Clojure is used to cover all Clojure dialects and runtimes — Clojure,
88

99
"Use the REPL" means `clojure_evaluate_code`. This is the primary tool for Clojure Interactive Programming.
1010

11-
Backseat Driver provides 11 tools in two groups:
11+
Backseat Driver provides 8 tools in two groups:
1212

1313
**REPL Exploration & Understanding**: `clojure_evaluate_code`, `clojure_load_file`, `clojure_list_sessions`, `clojure_repl_output_log`, `clojure_symbol_info`, `clojuredocs_info`
1414

15-
**Structural Editing**: `clojure_create_file`, `clojure_append_code`, `replace_top_level_form`, `insert_top_level_form`, `clojure_balance_brackets`
15+
**Structural Editing**: `clojure_edit_files`, `clojure_balance_brackets`
1616

1717
## Joyride Boundary
1818

assets/instructions/editing-clojure-files.instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: 'Structural editing rules for Clojure files — read these instructions when creating or modifying Clojure files regardless of dialect or runtime and when using structural editing tools (clojure_create_file, replace_top_level_form, insert_top_level_form, clojure_append_code, clojure_balance_brackets)'
2+
description: 'Structural editing rules for Clojure files — read these instructions when creating or modifying Clojure files regardless of dialect or runtime and when using structural editing tools (clojure_edit_files, clojure_balance_brackets)'
33
---
44

55
# Editing Clojure Files?

assets/skills/backseat-driver/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: backseat-driver
3-
description: 'Effective use of the Backseat Driver extension and its tools for Clojure interactive programming. Use when: working in Clojure (including all dialects and runtimes) project, be it reading, planning, developing, or evaluating code in the REPL, looking up function documentation or ClojureDocs examples, choosing REPL sessions, editing Clojure files structurally, checking REPL output, planning implementations, reviewing code, or developing solutions incrementally. Whenever you consider any of these tools: clojure_evaluate_code, clojure_load_file, clojuredocs_info, clojure_list_sessions, clojure_symbol_info, clojure_repl_output_log, replace_top_level_form, insert_top_level_form, clojure_append_code, clojure_create_file, clojure_balance_brackets. Also use this skill when PLANNING or DISCUSSING Clojure development approaches — not only at the moment of REPL evaluation.'
3+
description: 'Effective use of the Backseat Driver extension and its tools for Clojure interactive programming. Use when: working in Clojure (including all dialects and runtimes) project, be it reading, planning, developing, or evaluating code in the REPL, looking up function documentation or ClojureDocs examples, choosing REPL sessions, editing Clojure files structurally, checking REPL output, planning implementations, reviewing code, or developing solutions incrementally. Whenever you consider any of these tools: clojure_evaluate_code, clojure_load_file, clojuredocs_info, clojure_list_sessions, clojure_symbol_info, clojure_repl_output_log, clojure_edit_files, clojure_balance_brackets. Also use this skill when PLANNING or DISCUSSING Clojure development approaches — not only at the moment of REPL evaluation.'
44
---
55

66
# Backseat Driver — Effective Tool Usage

assets/skills/editing-clojure-files/SKILL.md

Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: editing-clojure-files
3-
description: 'Structural editing of Clojure files using Backseat Driver tools. Use when: creating/adding/inserting/replacing/deleting top-level forms, fixing bracket balance, resolving indentation issues, planning multi-edit sequences, recovering from failed edits, or working with Rich Comment Forms in Clojure files, regardless of dialect or runtime. Use whenever you consider any of these tools: clojure_create_file, clojure_append_code, insert_top_level_form, replace_top_level_form, clojure_balance_brackets. Use when editing Clojure and unsure which tool to pick. Use this skill when PLANNING or DISCUSSING Clojure file edits — not only at the moment of editing.'
3+
description: 'Structural editing of Clojure files using Backseat Driver tools. Use when: creating/adding/inserting/replacing/deleting top-level forms, fixing bracket balance, resolving indentation issues, planning multi-edit sequences, recovering from failed edits, or working with Rich Comment Forms in Clojure files, regardless of dialect or runtime. Use whenever you consider any of these tools: clojure_edit_files, clojure_balance_brackets. Use when editing Clojure and unsure which tool to pick. Use this skill when PLANNING or DISCUSSING Clojure file edits — not only at the moment of editing.'
44
---
55

66
# Editing Clojure Files
@@ -23,40 +23,58 @@ Smaller, simpler forms mean less code to get right in a single edit, fewer inden
2323

2424
When a function you need to modify is already long or deeply nested, improve its structure first, then make the requested change. Structural edits on bloated forms are error-prone.
2525

26-
## Tool Selection
26+
## The Tool: `clojure_edit_files`
2727

28+
One tool handles all structural editing operations. It accepts a batch of edits, validates them up front, groups by file, sorts for safe application order, and applies them sequentially.
29+
30+
### Edit Types
31+
32+
| Type | Purpose | Required fields |
33+
|------|---------|-----------------|
34+
| `create` | Create a new file with content | `filePath`, `content` |
35+
| `append` | Append forms to end of file | `filePath`, `code` |
36+
| `replace` | Replace an existing top-level form | `filePath`, `line`, `targetLineText`, `newForm` |
37+
| `insert` | Insert a form before an existing form | `filePath`, `line`, `targetLineText`, `newForm` |
38+
39+
### Constraints
40+
41+
- At most one `create` per file per call
42+
- At most one `append` per file per call
43+
- All edits are schema-validated before any are applied — one invalid edit blocks the entire batch
44+
- Within a file: creates run first, then replace/insert (highest line first), then appends
45+
- Across files: files are processed sequentially
46+
47+
### Usage Pattern
48+
49+
```json
50+
{
51+
"edits": [
52+
{"type": "replace", "filePath": "/path/to/file.clj", "line": 23, "targetLineText": "(defn process-data", "newForm": "(defn process-data\n [items]\n (map transform items))"},
53+
{"type": "insert", "filePath": "/path/to/file.clj", "line": 10, "targetLineText": "(defn helper", "newForm": "(defn new-fn\n [x]\n (inc x))"},
54+
{"type": "append", "filePath": "/path/to/other.clj", "code": "(defn added-fn\n []\n :done)"},
55+
{"type": "create", "filePath": "/path/to/new_file.clj", "content": "(ns my.new-file)\n\n(defn init []\n :ok)"}
56+
]
57+
}
2858
```
29-
What are you doing?
30-
├── Creating a new file?
31-
│ → clojure_create_file
32-
│ Include all known content at creation time.
33-
│ Namespace kebab-case → filename snake_case.
34-
35-
├── Adding forms to end of existing file?
36-
│ → clojure_append_code
37-
38-
├── Inserting a form before an existing form?
39-
│ → insert_top_level_form
40-
41-
├── Modifying an existing form?
42-
│ → replace_top_level_form
43-
44-
├── Deleting a form?
45-
│ → replace_top_level_form with empty newForm
46-
47-
├── Fixing broken brackets?
48-
│ → clojure_balance_brackets
49-
│ Accept its output as authoritative. NEVER modify it.
50-
51-
└── Editing line comments (; ...)?
52-
→ Use built-in text editing tools (not structural tools)
59+
60+
### Deleting a Form
61+
62+
Use `replace` with an empty `newForm`:
63+
```json
64+
{"type": "replace", "filePath": "/path/file.clj", "line": 15, "targetLineText": "(defn obsolete-fn", "newForm": ""}
5365
```
5466

55-
When brackets are broken, structural top-level edits are not possible. Use `clojure_balance_brackets` to analyse the breakage, then fall back to regular text editing tools if needed. If repeated attempts fail, escalate to the human via the #askQuestions tool.
67+
### When Brackets Are Broken
68+
69+
Structural top-level edits are not possible when brackets are unbalanced. Use `clojure_balance_brackets` to analyse the breakage, then fall back to regular text editing tools if needed. If repeated attempts fail, escalate to the human via the #askQuestions tool.
70+
71+
### Line Comments
72+
73+
Structural tools operate on forms, not line comments (`;`). Use built-in text editing tools for line comments.
5674

5775
## Targeting Forms
5876

59-
The `replace_top_level_form` and `insert_top_level_form` tools locate forms using two parameters: `line` (1-based line number) and `targetLineText` (the exact first line of the target form). Accuracy here is critical.
77+
The `replace` and `insert` edit types locate forms using two parameters: `line` (1-based line number) and `targetLineText` (the exact first line of the target form). Accuracy here is critical.
6078

6179
Read the file immediately before editing to get accurate line numbers and exact text.
6280

@@ -102,27 +120,20 @@ Definitions must precede their call sites in the file. When edits would create a
102120

103121
## Edit Process
104122

105-
Verification is mandatory after every edit:
123+
Verification is mandatory after every batch:
106124

107125
1. **Check problems first** — review current diagnostics; fix existing compilation problems before introducing new edits
108-
2. **Edit the file**use the structural tool with REPL-verified code
109-
3. **Check diagnostics** — read post-edit linting info; act on unexpected problems before the next edit
126+
2. **Batch edits**assemble all edits for the call with REPL-verified code
127+
3. **Check diagnostics** — read post-edit diagnostics from the response; act on unexpected problems before the next batch
110128
4. **Reload**`clojure_load_file` to load the file, or `(require 'the.namespace :reload)` to confirm the file loads cleanly
111129

112130
In a hot-reload environment, the REPL output log shows compile errors and warnings immediately after the edit. Read and act on them before proceeding.
113131

114-
## Multiple Edits: Bottom-to-Top
115-
116-
Always edit from highest line number to lowest. Each edit shifts line numbers below it — working bottom-up keeps planned numbers accurate.
132+
## Multiple Edits Are Automatic
117133

118-
1. Read the file — identify all edit targets with line numbers
119-
2. Sort edits by line number, **descending**
120-
3. Apply each edit (highest line first)
121-
4. Read the file afterward to verify final state
134+
The tool automatically sorts edits within each file for safe application order (highest line number first for replace/insert). You do not need to manually sort — just provide all edits in a single call and the tool handles ordering.
122135

123-
Example: editing forms at lines 10, 25, 40 → edit order: 40 → 25 → 10.
124-
125-
Expect temporary linter warnings about undefined symbols during a multi-edit sequence — they resolve once the full sequence completes.
136+
Expect temporary linter warnings about undefined symbols during a multi-edit sequence — they resolve once the full batch completes.
126137

127138
## Error Recovery
128139

@@ -140,17 +151,13 @@ Target line text not found. Expected: '(defn wrong-function [x]' near line 23
140151
```
141152
Fix: Use `grep_search` scoped to the file to find the target text's current line number — cheaper than reading the whole file. Plain text mode for exact matches; in regex mode, escape parens as `\(`.
142153

143-
### Comment Targeting
154+
### Partial Batch Failure
144155

145-
Structural tools operate on forms, not line comments:
146-
```
147-
Target line text cannot start with a comment (;). You can only target forms/sexpressions.
148-
```
149-
Fix: Use `replace_string_in_file` or equivalent text tool for line comments.
156+
The tool continues on failure within a file. The response shows which edits succeeded and which failed. For failed edits, re-read the file, get updated line numbers, and retry in a new batch.
150157

151158
### Scan Window Miss
152159

153-
The text exists but outside the ±2 window — most commonly because previous edits shifted line numbers. Search the file for the target text to get its current line number.
160+
The text exists but outside the ±2 window — most commonly because a prior edit in the same batch shifted line numbers beyond the ±2 tolerance. Re-read the file and retry with updated targeting.
154161

155162
## Extensibility
156163

@@ -160,9 +167,8 @@ When this skill is loaded, also load any corresponding `clojure-coding` or `cloj
160167

161168
## Invariants
162169

163-
- Clojure file edits use structural tools; line comments use text editing tools
164-
- New `.clj`/`.cljs`/`.cljc`/`.bb` files are created with `clojure_create_file`
165-
- Multi-edit sequences proceed bottom-to-top (highest line number first)
170+
- Clojure file edits use `clojure_edit_files`; line comments use text editing tools
171+
- New `.clj`/`.cljs`/`.cljc`/`.bb` files are created with `clojure_edit_files` type `create`
166172
- Indentation is verified before every structural edit — Parinfer depends on it
167173
- Post-edit diagnostics are read and acted on before proceeding
168174
- `targetLineText` is always the exact first line of the target form

0 commit comments

Comments
 (0)