|
5 | 5 | (:require |
6 | 6 | [clojure-mcp.tools.form-edit.core :as core] |
7 | 7 | [clojure-mcp.tools.agent-tool-builder.file-changes :as file-changes] |
8 | | - [clojure-mcp.utils.emacs-integration :as emacs] |
9 | 8 | [clojure-mcp.utils.diff :as diff-utils] |
10 | 9 | [clojure-mcp.tools.unified-read-file.file-timestamps :as file-timestamps] |
11 | 10 | [clojure-mcp.config :as config] |
|
95 | 94 | (assoc ::source (:content result)) |
96 | 95 | (assoc ::old-content (:content result)))))) |
97 | 96 |
|
98 | | -(defn emacs-buffer-modified-check |
99 | | - "Check if the emacs buffer is modified and saves it. When used before |
100 | | - check-file-modifed, it will trigger the modification error. |
101 | | - |
102 | | - A modified buffer is another level to check for file modifications. |
103 | | -
|
104 | | - Marking it as modified. This in turn will trigger the check last modified |
105 | | - to error out requiring the LLM to read the file before editing." |
106 | | - [ctx] |
107 | | - (let [file-path (::file-path ctx) |
108 | | - config (::config ctx)] |
109 | | - (if (and (emacs/config-enables-emacs-notifications? config) |
110 | | - (emacs/save-emacs-buffer-if-modified file-path)) |
111 | | - ;; prevent race condition of write and then relying on read |
112 | | - (assoc ctx ::file-modifed true) |
113 | | - ctx))) |
114 | | - |
115 | 97 | (defn check-file-modified |
116 | 98 | "Checks if the file has been modified since last read. |
117 | 99 | Returns error if modified without being read again. |
|
207 | 189 | {::error true |
208 | 190 | ::message (str "Error parsing source: " (.getMessage e))}))) |
209 | 191 |
|
210 | | -(defn capture-edit-offsets |
211 | | - "Captures the position offsets of the current zipper location. |
212 | | - This should be called immediately after editing operations while position information is valid. |
213 | | - |
214 | | - Requires ::zloc in the context. |
215 | | - Adds ::offsets to the context when successful." |
216 | | - [ctx] |
217 | | - (try |
218 | | - (let [zloc (::zloc ctx) |
219 | | - positions (z/position-span zloc) |
220 | | - output-source (or (::output-source ctx) (z/root-string zloc)) |
221 | | - offsets (core/zloc-offsets output-source positions)] |
222 | | - (assoc ctx ::offsets offsets)) |
223 | | - (catch Exception e |
224 | | - ;; Don't fail the pipeline if offsets can't be captured, just log it |
225 | | - ;; This allows non-Emacs workflows to continue |
226 | | - (log/error e "Warning: Failed to capture edit offsets -" (.getMessage e)) |
227 | | - ctx))) |
228 | | - |
229 | 192 | (defn validate-form-type |
230 | 193 | "Validates that the form type is supported for the operation. |
231 | 194 | Returns the context unchanged if valid, or error context if invalid. |
|
376 | 339 | (str "Changes made, but diff generation failed: " (.getMessage e)))))] |
377 | 340 | (assoc ctx ::diff diff))) |
378 | 341 |
|
379 | | -#_(defn emacs-set-auto-revert |
380 | | - "Ensures that the file is open in Emacs with auto-revert-mode enabled if notifications are enabled. |
381 | | - Requires ::file-path and ::config in the context." |
382 | | - [ctx] |
383 | | - (try |
384 | | - (let [file-path (::file-path ctx) |
385 | | - config (::config ctx)] |
386 | | - ;; Only notify if emacs notifications are enabled in config |
387 | | - (if (emacs/config-enables-emacs-notifications? config) |
388 | | - (do |
389 | | - (emacs/ensure-auto-revert file-path) ;; Now ensure-auto-revert is always async |
390 | | - ctx) |
391 | | - ;; Otherwise return context unchanged |
392 | | - ctx)) |
393 | | - ;; Fail silently if emacs isn't started |
394 | | - (catch Exception _ |
395 | | - ;; Return context unchanged if Emacs integration fails |
396 | | - ctx))) |
397 | | - |
398 | 342 | (defn save-file |
399 | 343 | "Saves the updated source to the file, creating parent directories if needed. |
400 | 344 | Requires ::output-source and ::file-path in the context. |
|
430 | 374 | (file-timestamps/update-file-timestamp-to-current-mtime! nrepl-client-atom file-path)) |
431 | 375 | ctx)) |
432 | 376 |
|
433 | | -(defn highlight-form |
434 | | - "Highlights the edited form in Emacs if notifications are enabled. |
435 | | - Requires ::file-path, ::offsets, and ::config in the context." |
436 | | - [ctx] |
437 | | - (try |
438 | | - (let [[start end] (::offsets ctx) |
439 | | - config (::config ctx)] |
440 | | - ;; Only notify if emacs notifications are enabled in config |
441 | | - (when (emacs/config-enables-emacs-notifications? config) |
442 | | - (emacs/highlight-region (::file-path ctx) start end 2.0)) |
443 | | - ctx) |
444 | | - ;; Fail silently to support non-emacs workflow |
445 | | - (catch Exception _ |
446 | | - ;; Return context unchanged if highlighting fails |
447 | | - ctx))) |
448 | | - |
449 | 377 | ;; Format result for tool consumption |
450 | 378 | (defn format-result |
451 | 379 | "Format the result of the pipeline for tool consumption. |
|
504 | 432 | ctx |
505 | 433 | lint-repair-code |
506 | 434 | validate-form-type |
507 | | - emacs-buffer-modified-check |
508 | 435 | load-source |
509 | 436 | file-changes/capture-original-file-content |
510 | 437 | check-file-modified |
511 | 438 | enhance-defmethod-name |
512 | 439 | parse-source |
513 | 440 | find-form |
514 | 441 | edit-form |
515 | | - capture-edit-offsets |
516 | 442 | zloc->output-source |
517 | 443 | format-source |
518 | 444 | determine-file-type |
|
522 | 448 | ctx |
523 | 449 | (-> ctx |
524 | 450 | save-file |
525 | | - update-file-timestamp |
526 | | - highlight-form)))))) |
527 | | - |
528 | | -(defn edit-locations->offsets [ctx] |
529 | | - (try |
530 | | - (let [zloc (::zloc ctx) |
531 | | - positions (last (::edit-locations ctx)) |
532 | | - output-source (or (::output-source ctx) (z/root-string zloc)) |
533 | | - offsets (core/zloc-offsets output-source positions)] |
534 | | - (assoc ctx ::offsets offsets)) |
535 | | - (catch Exception e |
536 | | - ;; Don't fail the pipeline if offsets can't be captured, just log it |
537 | | - ;; This allows non-Emacs workflows to continue |
538 | | - (log/error e (str "Warning: Failed to capture edit offsets -" (ex-message e))) |
539 | | - ctx))) |
| 451 | + update-file-timestamp)))))) |
540 | 452 |
|
541 | 453 | (defn edit-sexp |
542 | 454 | [{:keys [::zloc ::match-form ::new-form ::operation ::replace-all ::whitespace-sensitive] :as ctx}] |
|
585 | 497 | ctx |
586 | 498 | #(lint-repair-code % ::match-form) |
587 | 499 | #(lint-repair-code % ::new-form) |
588 | | - emacs-buffer-modified-check |
589 | 500 | load-source |
590 | 501 | file-changes/capture-original-file-content |
591 | 502 | check-file-modified |
592 | 503 | parse-source |
593 | 504 | edit-sexp |
594 | 505 | zloc->output-source |
595 | | - edit-locations->offsets |
596 | 506 | format-source |
597 | 507 | determine-file-type |
598 | 508 | generate-diff |
|
601 | 511 | ctx |
602 | 512 | (-> ctx |
603 | 513 | save-file |
604 | | - update-file-timestamp |
605 | | - highlight-form)))))) |
| 514 | + update-file-timestamp)))))) |
606 | 515 |
|
607 | 516 | (comment |
608 | 517 | ;; Example usage of the pipelines |
|
613 | 522 | "(defn example-fn [x y]\n (* x y))" |
614 | 523 | :after |
615 | 524 | nil |
616 | | - {:enable-emacs-notifications true}))) |
| 525 | + {}))) |
0 commit comments