Skip to content

Commit 9c54616

Browse files
authored
Chore: Improve code refactoring auto-suggestion (#271)
* Add default refactoring prompt and goal candidates * Add refactoring presets and selection UI * update HISTORY
1 parent f593a64 commit 9c54616

3 files changed

Lines changed: 92 additions & 4 deletions

File tree

HISTORY.org

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Release history
33

44
** Main branch change
5+
- Chore: Improve code refactoring auto-suggestion, user can select from several refactoring goal
6+
- Doc: Add Awesome Codex CLI badge to README
57
- Feat: Add whisper speech-to-text input command with post-transcription actions for insert, editable send-to-session, and clipboard copy
68
- Fix: Slowness of ai coding session given clickable session link feature
79

ai-code-agile.el

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,33 @@
333333
:description "Introduce a new hierarchy to clarify different responsibilities and support future extension."))
334334
"Catalog of refactoring techniques curated from Martin Fowler's \"Refactoring\".")
335335

336+
(defconst ai-code--refactoring-suggestion-default-instruction
337+
"Analyze the code context below. Identify potential refactoring opportunities (e.g., complexity, duplication, clarity) and make the code easy to understand. Do not change code logic. Suggest the most impactful refactoring technique and explain why."
338+
"Default instruction for refactoring suggestion prompts.")
339+
340+
(defconst ai-code--refactoring-suggestion-default-label
341+
"General refactoring analysis"
342+
"Default short description for refactoring suggestion prompts.")
343+
344+
(defconst ai-code--refactoring-suggestion-presets
345+
`((,ai-code--refactoring-suggestion-default-label . ,ai-code--refactoring-suggestion-default-instruction)
346+
("Improve readability and testability" . "Analyze the code context below. Focus on making the code easier to understand, improving readability, and increasing testability. Do not change code logic. Suggest the most impactful refactoring technique and explain why.")
347+
("Reduce complexity" . "Analyze the code context below. Focus on reducing complexity and simplifying control flow. Do not change code logic. Suggest the most impactful refactoring technique and explain why.")
348+
("Remove duplication" . "Analyze the code context below. Focus on removing duplication and consolidating repeated logic. Do not change code logic. Suggest the most impactful refactoring technique and explain why.")
349+
("Clarify naming and responsibilities" . "Analyze the code context below. Focus on clarifying naming and separating responsibilities more cleanly. Do not change code logic. Suggest the most impactful refactoring technique and explain why."))
350+
"Preset refactoring suggestion prompts keyed by short description.")
351+
352+
(defun ai-code--read-refactoring-suggestion-instruction ()
353+
"Read a refactoring suggestion instruction with editable completion."
354+
(let* ((selected-description
355+
(completing-read "Select refactoring goal: "
356+
(mapcar #'car ai-code--refactoring-suggestion-presets)
357+
nil t nil nil ai-code--refactoring-suggestion-default-label))
358+
(default-instruction
359+
(or (cdr (assoc selected-description ai-code--refactoring-suggestion-presets))
360+
ai-code--refactoring-suggestion-default-instruction)))
361+
(ai-code-read-string "Edit suggestion request: " default-instruction)))
362+
336363
(defun ai-code--refactoring--ensure-string (value)
337364
"Return VALUE coerced to a string when appropriate."
338365
(cond
@@ -575,8 +602,7 @@ If TDD-MODE is non-nil, adds TDD constraints to the prompt."
575602
(format "\n```\n%s\n```" region-text)
576603
""))
577604
;; Get the main instruction from the user
578-
(user-instruction (ai-code-read-string "Edit suggestion request: "
579-
"Analyze the code context below. Identify potential refactoring opportunities (e.g., complexity, duplication, clarity). Do not change code logic. Suggest the most impactful refactoring technique and explain why.")) ;; Improved initial-input
605+
(user-instruction (ai-code--read-refactoring-suggestion-instruction))
580606
;; Add TDD constraint if in TDD mode
581607
(tdd-constraint (if tdd-mode " Ensure all tests still pass after refactoring." ""))
582608
;; Add file information to context

test/test_ai-code-agile.el

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,11 @@
260260
"Verify Dired refactoring suggestions include selected files."
261261
(with-temp-buffer
262262
(let (captured-prompt)
263-
(cl-letf (((symbol-function 'ai-code-read-string)
264-
(lambda (_prompt &optional initial _candidates) initial))
263+
(cl-letf (((symbol-function 'completing-read)
264+
(lambda (&rest _) "Improve readability and testability"))
265+
((symbol-function 'ai-code-read-string)
266+
(lambda (_prompt &optional initial-input _candidates)
267+
initial-input))
265268
((symbol-function 'ai-code--git-root)
266269
(lambda (&optional _dir) "/repo/"))
267270
((symbol-function 'ai-code--insert-prompt)
@@ -280,5 +283,62 @@
280283
(should (string-match-p "\nFiles:\n@src/foo\\.el\n@test/bar\\.el"
281284
(subst-char-in-string ?\\ ?/ captured-prompt)))))))
282285

286+
(ert-deftest ai-code-test-handle-ask-llm-suggestion-offers-common-refactoring-goals ()
287+
"Verify refactoring suggestion prompt selects a short description first."
288+
(with-temp-buffer
289+
(let (captured-short-descriptions captured-selected-description
290+
captured-read-string-initial-input captured-prompt)
291+
(cl-letf (((symbol-function 'ai-code-read-string)
292+
(lambda (_prompt &optional initial-input _candidates)
293+
(setq captured-read-string-initial-input initial-input)
294+
"Custom edited prompt"))
295+
((symbol-function 'completing-read)
296+
(lambda (_prompt collection &rest _)
297+
(setq captured-short-descriptions collection)
298+
(setq captured-selected-description "Reduce complexity")
299+
captured-selected-description))
300+
((symbol-function 'ai-code--insert-prompt)
301+
(lambda (text)
302+
(setq captured-prompt text)
303+
t)))
304+
(ai-code--handle-ask-llm-suggestion
305+
'(:region-active nil
306+
:current-function "my-function"
307+
:file-name "/repo/src/foo.el"
308+
:dired-targets nil)
309+
nil)
310+
(should (equal captured-short-descriptions
311+
'("General refactoring analysis"
312+
"Improve readability and testability"
313+
"Reduce complexity"
314+
"Remove duplication"
315+
"Clarify naming and responsibilities")))
316+
(should (equal captured-selected-description "Reduce complexity"))
317+
(should (equal captured-read-string-initial-input
318+
"Analyze the code context below. Focus on reducing complexity and simplifying control flow. Do not change code logic. Suggest the most impactful refactoring technique and explain why."))
319+
(should (string-match-p "Custom edited prompt Context: Function 'my-function'"
320+
captured-prompt))))))
321+
322+
(ert-deftest ai-code-test-handle-ask-llm-suggestion-default-prompt-mentions-easy-to-understand ()
323+
"Verify the default refactoring prompt mentions making code easy to understand."
324+
(with-temp-buffer
325+
(let (captured-read-string-initial-input)
326+
(cl-letf (((symbol-function 'completing-read)
327+
(lambda (&rest _) ai-code--refactoring-suggestion-default-label))
328+
((symbol-function 'ai-code-read-string)
329+
(lambda (_prompt &optional initial-input _candidates)
330+
(setq captured-read-string-initial-input initial-input)
331+
initial-input))
332+
((symbol-function 'ai-code--insert-prompt)
333+
(lambda (_text) t)))
334+
(ai-code--handle-ask-llm-suggestion
335+
'(:region-active nil
336+
:current-function "my-function"
337+
:file-name "/repo/src/foo.el"
338+
:dired-targets nil)
339+
nil)
340+
(should (string-match-p "easy to understand"
341+
captured-read-string-initial-input))))))
342+
283343
(provide 'test_ai-code-agile)
284344
;;; test_ai-code-agile.el ends here

0 commit comments

Comments
 (0)