-
Notifications
You must be signed in to change notification settings - Fork 158
feat: customizable lsp event handler and lsp server log #339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -311,6 +311,31 @@ For example: | |
(setq copilot-network-proxy '(:host "127.0.0.1" :port 7890)) | ||
``` | ||
|
||
### copilot-on-request | ||
|
||
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) | ||
|
||
For example: | ||
|
||
```elisp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And before the code snippets. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
; Display desktop notification if emacs is built with d-bus | ||
(copilot-on-request | ||
'window/showMessageRequest | ||
(lambda (msg) (notifications-notify :title "Emacs Copilot" :body (plist-get msg :message)))) | ||
``` | ||
|
||
### copilot-on-notification | ||
|
||
Register a listener for copilot notifications. | ||
|
||
For example: | ||
|
||
```elisp | ||
(copilot-on-notification | ||
'window/logMessage | ||
(lambda (msg) (message (plist-get msg :message)) | ||
``` | ||
|
||
## Known Issues | ||
|
||
### Wrong Position of Other Completion Popups | ||
|
@@ -334,7 +359,7 @@ But I decided to allow them to coexist, allowing you to choose a better one at a | |
## Reporting Bugs | ||
|
||
+ Make sure you have restarted your Emacs (and rebuild the plugin if necessary) after updating the plugin. | ||
+ 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. | ||
+ 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-language-server-log*` buffer. | ||
+ If an exception is thrown, please also paste the stack trace (use `M-x toggle-debug-on-error` to enable stack trace). | ||
|
||
## Roadmap | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -405,6 +405,7 @@ SUCCESS-FN is the CALLBACK." | |
#'make-instance | ||
'jsonrpc-process-connection | ||
:name "copilot" | ||
:request-dispatcher #'copilot--handle-request | ||
:notification-dispatcher #'copilot--handle-notification | ||
:process (make-process :name "copilot server" | ||
:command (copilot--command) | ||
|
@@ -718,31 +719,76 @@ automatically, browse to %s." user-code verification-uri)) | |
(defvar copilot--panel-lang nil | ||
"Language of current panel solutions.") | ||
|
||
(defvar copilot--request-handlers (make-hash-table :test 'equal) | ||
"Hash table storing request handlers.") | ||
|
||
(defun copilot-on-request (method handler) | ||
"Register a request HANDLER for the given METHOD. | ||
Each request METHOD can have only one HANDLER." | ||
(puthash method handler copilot--request-handlers)) | ||
|
||
(defun copilot--handle-request (_ method msg) | ||
"Handle MSG of type METHOD by calling the appropriate registered handler." | ||
(let ((handler (gethash method copilot--request-handlers))) | ||
(when handler | ||
(funcall handler msg)))) | ||
|
||
(defvar copilot--notification-handlers (make-hash-table :test 'equal) | ||
"Hash table storing lists of notification handlers.") | ||
|
||
(defun copilot-on-notification (method handler) | ||
"Register a notification HANDLER for the given METHOD." | ||
(let ((handlers (gethash method copilot--notification-handlers '()))) | ||
(puthash method (cons handler handlers) copilot--notification-handlers))) | ||
|
||
(defun copilot--handle-notification (_ method msg) | ||
"Handle MSG of type METHOD." | ||
(when (eql method 'PanelSolution) | ||
(copilot--dbind (((:completionText completion-text)) ((:score completion-score))) msg | ||
(with-current-buffer "*copilot-panel*" | ||
(unless (member (secure-hash 'sha256 completion-text) | ||
(org-map-entries (lambda () (org-entry-get nil "SHA")))) | ||
(save-excursion | ||
(goto-char (point-max)) | ||
(insert "* Solution\n" | ||
" :PROPERTIES:\n" | ||
" :SCORE: " (number-to-string completion-score) "\n" | ||
" :SHA: " (secure-hash 'sha256 completion-text) "\n" | ||
" :END:\n" | ||
"#+BEGIN_SRC " copilot--panel-lang "\n" | ||
completion-text "\n#+END_SRC\n\n") | ||
(call-interactively #'mark-whole-buffer) | ||
(org-sort-entries nil ?R nil nil "SCORE")))))) | ||
(when (eql method 'PanelSolutionsDone) | ||
(message "Copilot: Finish synthesizing solutions.") | ||
(display-buffer "*copilot-panel*") | ||
(with-current-buffer "*copilot-panel*" | ||
(save-excursion | ||
(goto-char (point-max)) | ||
(insert "End of solutions.\n"))))) | ||
"Handle MSG of type METHOD by calling all appropriate registered handlers." | ||
(let ((handlers (gethash method copilot--notification-handlers '()))) | ||
(dolist (handler handlers) | ||
(funcall handler msg)))) | ||
|
||
(copilot-on-notification | ||
'window/logMessage | ||
(lambda (msg) | ||
(copilot--dbind (:type log-level :message log-msg) msg | ||
(with-current-buffer (get-buffer-create "*copilot-language-server-log*") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's a good idea to extra the buffer names to constants. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ATM, I was trying to stay consistent with the existing code and I think this can be addressed in a different PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that's a fair point. |
||
(save-excursion | ||
(goto-char (point-max)) | ||
(insert (propertize (concat log-msg "\n") | ||
'face (pcase log-level | ||
(4 'shadow) | ||
(3 'success) | ||
(2 'warning) | ||
(1 'error))))))))) | ||
|
||
(copilot-on-notification | ||
'PanelSolution | ||
(lambda (msg) | ||
(copilot--dbind (((:completionText completion-text)) ((:score completion-score))) msg | ||
(with-current-buffer "*copilot-panel*" | ||
(unless (member (secure-hash 'sha256 completion-text) | ||
(org-map-entries (lambda () (org-entry-get nil "SHA")))) | ||
(save-excursion | ||
(goto-char (point-max)) | ||
(insert "* Solution\n" | ||
" :PROPERTIES:\n" | ||
" :SCORE: " (number-to-string completion-score) "\n" | ||
" :SHA: " (secure-hash 'sha256 completion-text) "\n" | ||
" :END:\n" | ||
"#+BEGIN_SRC " copilot--panel-lang "\n" | ||
completion-text "\n#+END_SRC\n\n") | ||
(call-interactively #'mark-whole-buffer) | ||
(org-sort-entries nil ?R nil nil "SCORE"))))))) | ||
|
||
(copilot-on-notification | ||
'PanelSolutionsDone | ||
(lambda (_msg) | ||
(message "Copilot: Finish synthesizing solutions.") | ||
(display-buffer "*copilot-panel*") | ||
(with-current-buffer "*copilot-panel*" | ||
(save-excursion | ||
(goto-char (point-max)) | ||
(insert "End of solutions.\n"))))) | ||
|
||
(defun copilot--get-panel-completions (callback) | ||
"Get panel completions with CALLBACK." | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, add blank lines after each heading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed