Skip to content

Commit 3e13d2f

Browse files
author
Kang Tu
committed
feat(prompt): add clipboard context support for code changes and questions
1 parent ee56653 commit 3e13d2f

File tree

3 files changed

+85
-45
lines changed

3 files changed

+85
-45
lines changed

ai-code-change.el

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
(declare-function ai-code-read-string "ai-code-input")
2121
(declare-function ai-code--insert-prompt "ai-code-prompt-mode")
22+
(declare-function ai-code--get-clipboard-text "ai-code-interface")
2223

2324
(defun ai-code--is-comment-line (line)
2425
"Check if LINE is a comment line based on current buffer's comment syntax.
@@ -34,43 +35,55 @@ ignoring leading whitespace."
3435
;;;###autoload
3536
(defun ai-code-code-change (arg)
3637
"Generate prompt to change code under cursor or in selected region.
37-
With a prefix argument (universal-argument), prompt for a change without adding any context.
38+
With a prefix argument (C-u), append the clipboard contents as context.
3839
If a region is selected, change that specific region.
3940
Otherwise, change the function under cursor.
4041
If nothing is selected and no function context, prompts for general code change.
4142
Inserts the prompt into the AI prompt file and optionally sends to AI.
4243
4344
Argument ARG is the prefix argument."
4445
(interactive "P")
45-
(if arg
46-
(let ((prompt (ai-code-read-string "Change code (no context): " "")))
47-
(ai-code--insert-prompt prompt))
48-
(unless buffer-file-name
49-
(user-error "Error: buffer-file-name must be available"))
50-
(let* ((function-name (which-function))
51-
(region-active (region-active-p))
52-
(region-text (when region-active
53-
(buffer-substring-no-properties (region-beginning) (region-end))))
54-
(region-start-line (when region-active
55-
(line-number-at-pos (region-beginning))))
56-
(prompt-label
57-
(cond (region-active
58-
(if function-name
59-
(format "Change code in function %s: " function-name)
60-
"Change selected code: "))
61-
(function-name
62-
(format "Change function %s: " function-name))
63-
(t "Change code: ")))
64-
(initial-prompt (ai-code-read-string prompt-label ""))
65-
(files-context-string (ai-code--get-context-files-string))
66-
(final-prompt
67-
(concat initial-prompt
68-
(when region-text
69-
(format "\nCode from line %d:\n%s" region-start-line region-text))
70-
(when function-name (format "\nFunction: %s" function-name))
71-
files-context-string
72-
"\nNote: Please make the code change described above.")))
73-
(ai-code--insert-prompt final-prompt))))
46+
(unless buffer-file-name
47+
(user-error "Error: buffer-file-name must be available"))
48+
(let* ((clipboard-context (when arg (ai-code--get-clipboard-text)))
49+
(function-name (which-function))
50+
(region-active (region-active-p))
51+
(region-text (when region-active
52+
(buffer-substring-no-properties (region-beginning) (region-end))))
53+
(region-start-line (when region-active
54+
(line-number-at-pos (region-beginning))))
55+
(prompt-label
56+
(cond
57+
((and clipboard-context
58+
(string-match-p "\\S-" clipboard-context))
59+
(cond
60+
(region-active
61+
(if function-name
62+
(format "Change code in function %s (clipboard context): " function-name)
63+
"Change selected code (clipboard context): "))
64+
(function-name
65+
(format "Change function %s (clipboard context): " function-name))
66+
(t "Change code (clipboard context): ")))
67+
(region-active
68+
(if function-name
69+
(format "Change code in function %s: " function-name)
70+
"Change selected code: "))
71+
(function-name
72+
(format "Change function %s: " function-name))
73+
(t "Change code: ")))
74+
(initial-prompt (ai-code-read-string prompt-label ""))
75+
(files-context-string (ai-code--get-context-files-string))
76+
(final-prompt
77+
(concat initial-prompt
78+
(when region-text
79+
(format "\nCode from line %d:\n%s" region-start-line region-text))
80+
(when function-name (format "\nFunction: %s" function-name))
81+
files-context-string
82+
(when (and clipboard-context
83+
(string-match-p "\\S-" clipboard-context))
84+
(concat "\n\nClipboard context:\n" clipboard-context))
85+
"\nNote: Please make the code change described above.")))
86+
(ai-code--insert-prompt final-prompt)))
7487

7588
;;;###autoload
7689
(defun ai-code-implement-todo (arg)

ai-code-discussion.el

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616

1717
(declare-function ai-code-read-string "ai-code-input")
1818
(declare-function ai-code--insert-prompt "ai-code-prompt-mode")
19+
(declare-function ai-code--get-clipboard-text "ai-code-interface")
1920

2021
;;;###autoload
2122
(defun ai-code-ask-question (arg)
2223
"Generate prompt to ask questions about specific code.
23-
With a prefix argument (\M-x), prompt for a question without adding any context.
24+
With a prefix argument (C-u), append the clipboard contents as context.
2425
If current buffer is a file, keep existing logic.
2526
If current buffer is a dired buffer:
2627
- If there are files or directories marked, use them as context (use git repo relative path, start with @ character)
@@ -32,18 +33,17 @@ Inserts the prompt into the AI prompt file and optionally sends to AI.
3233
3334
Argument ARG is the prefix argument."
3435
(interactive "P")
35-
(if arg
36-
(let ((question (ai-code-read-string "Ask question (no context): " "")))
37-
(ai-code--insert-prompt question))
36+
(let ((clipboard-context (when arg (ai-code--get-clipboard-text))))
3837
(cond
3938
;; Handle dired buffer
4039
((eq major-mode 'dired-mode)
41-
(ai-code--ask-question-dired))
40+
(ai-code--ask-question-dired clipboard-context))
4241
;; Handle regular file buffer
43-
(t (ai-code--ask-question-file)))))
42+
(t (ai-code--ask-question-file clipboard-context)))))
4443

45-
(defun ai-code--ask-question-dired ()
46-
"Handle ask question for dired buffer."
44+
(defun ai-code--ask-question-dired (clipboard-context)
45+
"Handle ask question for dired buffer.
46+
CLIPBOARD-CONTEXT is optional clipboard text to append as context."
4747
(let* ((all-marked (dired-get-marked-files))
4848
(file-at-point (dired-get-filename nil t))
4949
(truly-marked (remove file-at-point all-marked))
@@ -55,20 +55,32 @@ Argument ARG is the prefix argument."
5555
(git-relative-files (when context-files
5656
(ai-code--get-git-relative-paths context-files)))
5757
(files-context-string (when git-relative-files
58-
(concat "\nFiles:\n"
59-
(mapconcat (lambda (f) (concat "@" f))
58+
(concat "\nFiles:\n"
59+
(mapconcat (lambda (f) (concat "@" f))
6060
git-relative-files "\n"))))
6161
(prompt-label (cond
62+
((and clipboard-context
63+
(string-match-p "\\S-" clipboard-context))
64+
(if has-marks
65+
"Question about marked files/directories (clipboard context): "
66+
(if file-at-point
67+
(format "Question about %s (clipboard context): " (file-name-nondirectory file-at-point))
68+
"General question about directory (clipboard context): ")))
6269
(has-marks "Question about marked files/directories: ")
6370
(file-at-point (format "Question about %s: " (file-name-nondirectory file-at-point)))
6471
(t "General question about directory: ")))
6572
(question (ai-code-read-string prompt-label ""))
66-
(final-prompt (concat question files-context-string
73+
(final-prompt (concat question
74+
files-context-string
75+
(when (and clipboard-context
76+
(string-match-p "\\S-" clipboard-context))
77+
(concat "\n\nClipboard context:\n" clipboard-context))
6778
"\nNote: This is a question only - please do not modify the code.")))
6879
(ai-code--insert-prompt final-prompt)))
6980

70-
(defun ai-code--ask-question-file ()
71-
"Handle ask question for regular file buffer."
81+
(defun ai-code--ask-question-file (clipboard-context)
82+
"Handle ask question for regular file buffer.
83+
CLIPBOARD-CONTEXT is optional clipboard text to append as context."
7284
(let* ((file-extension (when buffer-file-name
7385
(file-name-extension buffer-file-name)))
7486
(is-diff-or-patch (and file-extension
@@ -80,6 +92,18 @@ Argument ARG is the prefix argument."
8092
(buffer-substring-no-properties (region-beginning) (region-end))))
8193
(prompt-label
8294
(cond
95+
((and clipboard-context
96+
(string-match-p "\\S-" clipboard-context))
97+
(cond
98+
(region-active
99+
(if function-name
100+
(format "Question about selected code in function %s (clipboard context): " function-name)
101+
"Question about selected code (clipboard context): "))
102+
(function-name
103+
(format "Question about function %s (clipboard context): " function-name))
104+
(buffer-file-name
105+
(format "General question about %s (clipboard context): " (file-name-nondirectory buffer-file-name)))
106+
(t "General question (clipboard context): ")))
83107
(region-active
84108
(if function-name
85109
(format "Question about selected code in function %s: " function-name)
@@ -98,6 +122,9 @@ Argument ARG is the prefix argument."
98122
(when function-name
99123
(format "\nFunction: %s" function-name))
100124
files-context-string
125+
(when (and clipboard-context
126+
(string-match-p "\\S-" clipboard-context))
127+
(concat "\n\nClipboard context:\n" clipboard-context))
101128
"\nNote: This is a question only - please do not modify the code.")))
102129
(ai-code--insert-prompt final-prompt)))
103130

ai-code-interface.el

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ Shows the current backend label to the right."
153153
]
154154
["AI Code Actions"
155155
(ai-code--infix-toggle-suffix)
156-
("c" "Code change (C-u: global)" ai-code-code-change)
156+
("c" "Code change (C-u: clipboard)" ai-code-code-change)
157157
("i" "Implement TODO (C-u: keep it)" ai-code-implement-todo)
158-
("q" "Ask question (C-u: global)" ai-code-ask-question)
158+
("q" "Ask question (C-u: clipboard)" ai-code-ask-question)
159159
("x" "Explain code" ai-code-explain)
160160
("<SPC>" "Send command (C-u: clipboard)" ai-code-send-command)
161161
]

0 commit comments

Comments
 (0)