Skip to content

Commit fda007f

Browse files
committed
feat: customizable lsp event handler and lsp server log
1 parent 8ddfbee commit fda007f

File tree

2 files changed

+92
-25
lines changed

2 files changed

+92
-25
lines changed

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,27 @@ For example:
296296
(setq copilot-network-proxy '(:host "127.0.0.1" :port 7890))
297297
```
298298

299+
### copilot-on-request
300+
Register a handler to be called when a request of type method is received. Return JSON serializable as result or calling `jsonrpc-error` for errors. [readmore](https://www.gnu.org/software/emacs/manual/html_node/elisp/JSONRPC-Overview.html)
301+
302+
For example:
303+
```elisp
304+
; Display desktop notification if emacs is built with d-bus
305+
(copilot-on-request
306+
'window/showMessageRequest
307+
(lambda (msg) (notifications-notify :title "Emacs Copilot" :body (plist-get msg :message))))
308+
```
309+
310+
### copilot-on-notification
311+
Register a listener for copilot notifications.
312+
313+
For example:
314+
```elisp
315+
(copilot-on-notification
316+
'window/logMessage
317+
(lambda (msg) (message (plist-get msg :message))
318+
```
319+
299320
## Known Issues
300321

301322
### Wrong Position of Other Completion Popups
@@ -319,7 +340,7 @@ But I decided to allow them to coexist, allowing you to choose a better one at a
319340
## Reporting Bugs
320341

321342
+ Make sure you have restarted your Emacs (and rebuild the plugin if necessary) after updating the plugin.
322-
+ Please enable event logging by customize `copilot-log-max` (to e.g. 1000), then paste related logs in the `*copilot events*` and `*copilot stderr*` buffer.
343+
+ Please enable event logging by customize `copilot-log-max` (to e.g. 1000) and enable debug log `(setq copilot-server-args '("--stdio" "--debug"))`, then paste related logs in the `*copilot events*`, `*copilot stderr*` and `*copilot agent log*` buffer.
323344
+ If an exception is thrown, please also paste the stack trace (use `M-x toggle-debug-on-error` to enable stack trace).
324345

325346
## Roadmap

copilot.el

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ SUCCESS-FN is the CALLBACK."
290290
#'make-instance
291291
'jsonrpc-process-connection
292292
:name "copilot"
293+
:request-dispatcher #'copilot--handle-request
293294
:notification-dispatcher #'copilot--handle-notification
294295
:process (make-process :name "copilot agent"
295296
:command (append
@@ -624,31 +625,76 @@ automatically, browse to %s." user-code verification-uri))
624625
(defvar copilot--panel-lang nil
625626
"Language of current panel solutions.")
626627

628+
(defvar copilot--request-handlers (make-hash-table :test 'equal)
629+
"Hash table storing request handlers.")
630+
631+
(defun copilot-on-request (method handler)
632+
"Register HANDLER to be called when a request of type METHOD is received.
633+
Each METHOD can have only one HANDLER."
634+
(puthash method handler copilot--request-handlers))
635+
636+
(defun copilot--handle-request (_ method msg)
637+
"Handle MSG of type METHOD by calling the appropriate registered handler."
638+
(let ((handler (gethash method copilot--request-handlers)))
639+
(when handler
640+
(funcall handler msg))))
641+
642+
(defvar copilot--notification-handlers (make-hash-table :test 'equal)
643+
"Hash table storing lists of notification handlers.")
644+
645+
(defun copilot-on-notification (method handler)
646+
"Register HANDLER to be called when a notification of type METHOD is received."
647+
(let ((handlers (gethash method copilot--notification-handlers '())))
648+
(puthash method (cons handler handlers) copilot--notification-handlers)))
649+
627650
(defun copilot--handle-notification (_ method msg)
628-
"Handle MSG of type METHOD."
629-
(when (eql method 'PanelSolution)
630-
(copilot--dbind (:completionText completion-text :score completion-score) msg
631-
(with-current-buffer "*copilot-panel*"
632-
(unless (member (secure-hash 'sha256 completion-text)
633-
(org-map-entries (lambda () (org-entry-get nil "SHA"))))
634-
(save-excursion
635-
(goto-char (point-max))
636-
(insert "* Solution\n"
637-
" :PROPERTIES:\n"
638-
" :SCORE: " (number-to-string completion-score) "\n"
639-
" :SHA: " (secure-hash 'sha256 completion-text) "\n"
640-
" :END:\n"
641-
"#+BEGIN_SRC " copilot--panel-lang "\n"
642-
completion-text "\n#+END_SRC\n\n")
643-
(call-interactively #'mark-whole-buffer)
644-
(org-sort-entries nil ?R nil nil "SCORE"))))))
645-
(when (eql method 'PanelSolutionsDone)
646-
(message "Copilot: Finish synthesizing solutions.")
647-
(display-buffer "*copilot-panel*")
648-
(with-current-buffer "*copilot-panel*"
649-
(save-excursion
650-
(goto-char (point-max))
651-
(insert "End of solutions.\n")))))
651+
"Handle MSG of type METHOD by calling all appropriate registered handlers."
652+
(let ((handlers (gethash method copilot--notification-handlers '())))
653+
(dolist (handler handlers)
654+
(funcall handler msg))))
655+
656+
(copilot-on-notification
657+
'window/logMessage
658+
(lambda (msg)
659+
(copilot--dbind (:type log-level :message log-msg) msg
660+
(with-current-buffer (get-buffer-create "*copilot agent log*")
661+
(save-excursion
662+
(goto-char (point-max))
663+
(insert (propertize (concat log-msg "\n")
664+
'face (pcase log-level
665+
(4 'shadow)
666+
(3 'success)
667+
(2 'warning)
668+
(1 'error)))))))))
669+
670+
(copilot-on-notification
671+
'PanelSolution
672+
(lambda (msg)
673+
(copilot--dbind (:completionText completion-text :score completion-score) msg
674+
(with-current-buffer "*copilot-panel*"
675+
(unless (member (secure-hash 'sha256 completion-text)
676+
(org-map-entries (lambda () (org-entry-get nil "SHA"))))
677+
(save-excursion
678+
(goto-char (point-max))
679+
(insert "* Solution\n"
680+
" :PROPERTIES:\n"
681+
" :SCORE: " (number-to-string completion-score) "\n"
682+
" :SHA: " (secure-hash 'sha256 completion-text) "\n"
683+
" :END:\n"
684+
"#+BEGIN_SRC " copilot--panel-lang "\n"
685+
completion-text "\n#+END_SRC\n\n")
686+
(call-interactively #'mark-whole-buffer)
687+
(org-sort-entries nil ?R nil nil "SCORE")))))))
688+
689+
(copilot-on-notification
690+
'PanelSolutionsDone
691+
(lambda (_msg)
692+
(message "Copilot: Finish synthesizing solutions.")
693+
(display-buffer "*copilot-panel*")
694+
(with-current-buffer "*copilot-panel*"
695+
(save-excursion
696+
(goto-char (point-max))
697+
(insert "End of solutions.\n")))))
652698

653699
(defun copilot--get-panel-completions (callback)
654700
"Get panel completions with CALLBACK."

0 commit comments

Comments
 (0)