[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot d1cdcf1 119/139: Friendlier M-x eglot
From: |
João Távora |
Subject: |
[elpa] externals/eglot d1cdcf1 119/139: Friendlier M-x eglot |
Date: |
Mon, 14 May 2018 09:55:05 -0400 (EDT) |
branch: externals/eglot
commit d1cdcf163849ca1a7bfcbc3287f4e2c28cae77af
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>
Friendlier M-x eglot
* eglot.el (eglot-server-programs): Renamed from eglot-executables
(eglot--interactive): Redesign
(eglot): Docstring.
(eglot--connect): Now a synchronous gig.
(eglot--interactive): Friendlier.
(eglot): Improve docstring, rework a bit.
(eglot-reconnect): Rework a bit.
(eglot--process-sentinel): Insert "byebye" ruler here.
* README.md: Update
---
README.md | 39 ++++++++++-------
eglot.el | 140 +++++++++++++++++++++++++++++++-------------------------------
2 files changed, 94 insertions(+), 85 deletions(-)
diff --git a/README.md b/README.md
index 66f2131..c2931be 100644
--- a/README.md
+++ b/README.md
@@ -12,17 +12,25 @@ Eglot
M-x eglot
```
-*That's it*. Either this guesses the LSP executable to start for the
-language of your choice, or it prompts you to enter the program.
+*That's it*. If you're lucky, this guesses the LSP executable to start
+for the language of your choice, or it prompts you to enter one:
-If you have these programs installed, `M-x eglot` works out-of-the-box
-with:
+`M-x eglot` currently guesses and works out-of-the-box with:
* Javascript's [javascript-typescript-stdio][javascript-typescript-langserver]
* Rust's [rls][rls]
* Python's [pyls][pyls]
+* Bash's [bash-language-server][bash-language-server]
-You can also enter a `server:port` pattern to connect to an LSP
+I'll add more as I test more features. In the meantime you can
+customize `eglot-server-programs`:
+
+```lisp
+(add-to-list 'eglot-server-programs '(fancy-mode . ("fancy-language-server"
"--args"")))
+```
+
+Let me know how well it works and I'll add it to the list, or submit a
+PR. You can also enter a `server:port` pattern to connect to an LSP
server. To skip the guess and always be prompted use `C-u M-x eglot`.
# Supported Protocol features
@@ -89,21 +97,22 @@ server. To skip the guess and always be prompted use `C-u
M-x eglot`.
# Differences to lsp-mode.el
-Eglot is **really beta** and may currently underperform
-[lsp-mode.el][emacs-lsp], which is more mature and has a host of
-[plugins][emacs-lsp-plugins] for bells and whistles. If you think the
minimalist approach
-of `eglot.el` is not for you, you could be better served with
-`lsp-mode.el` for now.
+Eglot is **beta**. It may currently underperform
+[lsp-mode.el][emacs-lsp], both in functionality and correctness. That
+other extension is much more mature and has a host of
+[plugins][emacs-lsp-plugins] for bells and whistles. If you don't
+like the minimalist approach of `eglot.el`, you could be better served
+with `lsp-mode.el` for now.
User-visible differences:
-- Single entry point `M-x eglot`, not `M-x eglot-<language>`. Also no
- `eglot-<language>` extra packages.
+- Single and friendly entry point `M-x eglot`, not `M-x
+ eglot-<language>`. Also no `eglot-<language>` extra packages.
- No "whitelisting" or "blacklisting" directories to languages. `M-x
eglot` starts servers to handle major modes inside a specific
project. Uses Emacs's built-in `project.el` library to discover
- projects. Automatically detects current and future opened files under that
- project and syncs with server.
+ projects. Automatically detects current and future opened files
+ under that project and syncs with server.
- Easy way to quit/restart a server, just middle/right click on the
connection name.
- Pretty interactive mode-line section for live tracking of server
@@ -134,6 +143,6 @@ Under the hood:
[javascript-typescript-langserver]:
https://github.com/sourcegraph/javascript-typescript-langserver
[emacs-lsp]: https://github.com/emacs-lsp/lsp-mode
[emacs-lsp-plugins]: https://github.com/emacs-lsp
-
+[bash-language-server]: https://github.com/mads-hartmann/bash-language-server
diff --git a/eglot.el b/eglot.el
index b2709a6..22799cc 100644
--- a/eglot.el
+++ b/eglot.el
@@ -47,9 +47,10 @@
:prefix "eglot-"
:group 'applications)
-(defvar eglot-executables '((rust-mode . ("rls"))
- (python-mode . ("pyls"))
- (js-mode . ("javascript-typescript-stdio")))
+(defvar eglot-server-programs '((rust-mode . ("rls"))
+ (python-mode . ("pyls"))
+ (js-mode . ("javascript-typescript-stdio"))
+ (sh-mode . ("bash-language-server" "start")))
"Alist mapping major modes to server executables.")
(defface eglot-mode-line
@@ -204,10 +205,8 @@ CONTACT is as `eglot--contact'. Returns a process object."
:publishDiagnostics `(:relatedInformation :json-false))
:experimental (eglot--obj)))
-(defun eglot--connect (project managed-major-mode
- short-name contact &optional success-fn)
- "Connect for PROJECT, MANAGED-MAJOR-MODE, SHORT-NAME and CONTACT.
-SUCCESS-FN with no args if all goes well."
+(defun eglot--connect (project managed-major-mode short-name contact)
+ "Connect for PROJECT, MANAGED-MAJOR-MODE, SHORT-NAME and CONTACT."
(let* ((proc (eglot--make-process short-name managed-major-mode contact))
(buffer (process-buffer proc)))
(setf (eglot--contact proc) contact
@@ -216,70 +215,68 @@ SUCCESS-FN with no args if all goes well."
(with-current-buffer buffer
(let ((inhibit-read-only t))
(setf (eglot--short-name proc) short-name)
- (push proc
- (gethash (project-current)
- eglot--processes-by-project))
+ (push proc (gethash project eglot--processes-by-project))
(erase-buffer)
(read-only-mode t)
- (with-current-buffer (eglot-events-buffer proc)
- (let ((inhibit-read-only t))
- (insert
- (format "\n-----------------------------------\n"))))
- (eglot--request
- proc
- :initialize
- (eglot--obj :processId (unless (eq (process-type proc)
- 'network)
- (emacs-pid))
- :rootUri (eglot--path-to-uri
- (car (project-roots (project-current))))
- :initializationOptions []
- :capabilities (eglot--client-capabilities))
- :success-fn
- (cl-function
- (lambda (&key capabilities)
- (setf (eglot--capabilities proc) capabilities)
- (setf (eglot--status proc) nil)
- (dolist (buffer (buffer-list))
- (with-current-buffer buffer
- (eglot--maybe-activate-editing-mode proc)))
- (when success-fn (funcall success-fn proc))
- (eglot--notify proc :initialized (eglot--obj :__dummy__ t)))))))))
+ (cl-destructuring-bind (&key capabilities)
+ (eglot--sync-request
+ proc
+ :initialize
+ (eglot--obj :processId (unless (eq (process-type proc)
+ 'network)
+ (emacs-pid))
+ :rootUri (eglot--path-to-uri
+ (car (project-roots project)))
+ :initializationOptions []
+ :capabilities (eglot--client-capabilities)))
+ (setf (eglot--capabilities proc) capabilities)
+ (setf (eglot--status proc) nil)
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (eglot--maybe-activate-editing-mode proc)))
+ (eglot--notify proc :initialized (eglot--obj :__dummy__ t))
+ proc)))))
(defvar eglot--command-history nil
"History of COMMAND arguments to `eglot'.")
(defun eglot--interactive ()
"Helper for `eglot'."
- (let* ((managed-major-mode
+ (let* ((guessed-mode (if buffer-file-name major-mode))
+ (managed-mode
(cond
- ((or current-prefix-arg
- (not buffer-file-name))
+ ((or (>= (prefix-numeric-value current-prefix-arg) 16)
+ (not guessed-mode))
(intern
(completing-read
"[eglot] Start a server to manage buffers of what major mode? "
(mapcar #'symbol-name (eglot--all-major-modes)) nil t
- (symbol-name major-mode) nil
- (symbol-name major-mode) nil)))
- (t major-mode)))
- (guessed-command
- (cdr (assoc managed-major-mode eglot-executables))))
+ (symbol-name guessed-mode) nil (symbol-name guessed-mode) nil)))
+ (t guessed-mode)))
+ (guessed-command (cdr (assoc managed-mode eglot-server-programs)))
+ (base-prompt "[eglot] Enter program to execute (or <host>:<port>): ")
+ (prompt
+ (cond (current-prefix-arg base-prompt)
+ ((null guessed-command)
+ (concat (format "[eglot] Sorry, couldn't guess for `%s'!"
+ managed-mode)
+ "\n" base-prompt))
+ ((and (listp guessed-command)
+ (not (executable-find (car guessed-command))))
+ (concat (format "[eglot] I guess you want to run `%s'"
+ (combine-and-quote-strings guessed-command))
+ (format ", but I can't find `%s' in PATH!"
+ (car guessed-command))
+ "\n" base-prompt)))))
(list
- managed-major-mode
- (let ((prompt
- (cond (current-prefix-arg
- "[eglot] Enter program to execute (or <host>:<port>): ")
- ((null guessed-command)
- (format "[eglot] Sorry, couldn't guess for `%s'!\n\
-Enter program to execute (or <host>:<port>): "
- managed-major-mode)))))
- (if prompt
- (split-string-and-unquote
- (read-shell-command prompt
- (if (listp guessed-command)
- (combine-and-quote-strings
guessed-command))
- 'eglot-command-history))
- guessed-command))
+ managed-mode
+ (if prompt
+ (split-string-and-unquote
+ (read-shell-command prompt
+ (if (listp guessed-command)
+ (combine-and-quote-strings guessed-command))
+ 'eglot-command-history))
+ guessed-command)
t)))
;;;###autoload
@@ -296,8 +293,11 @@ is also know as the server's \"contact\".
MANAGED-MAJOR-MODE is an Emacs major mode.
-With a prefix arg, prompt for MANAGED-MAJOR-MODE and COMMAND,
-else guess them from current context and `eglot-executables'.
+Interactively, guess MANAGED-MAJOR-MODE from current buffer and
+COMMAND from `eglot-server-programs'. With a single
+\\[universal-argument] prefix arg, prompt for COMMAND. With two
+\\[universal-argument] prefix args, also prompt for
+MANAGED-MAJOR-MODE.
INTERACTIVE is t if called interactively."
(interactive (eglot--interactive))
@@ -313,16 +313,13 @@ INTERACTIVE is t if called interactively."
(eglot-reconnect current-process interactive)
(when (process-live-p current-process)
(eglot-shutdown current-process))
- (eglot--connect project
- managed-major-mode
- short-name
- command
- (lambda (proc)
- (eglot--message "Connected! Process `%s' now \
+ (let ((proc (eglot--connect project
+ managed-major-mode
+ short-name
+ command)))
+ (eglot--message "Connected! Process `%s' now \
managing `%s' buffers in project `%s'."
- proc
- managed-major-mode
- short-name)))))))
+ proc managed-major-mode short-name))))))
(defun eglot-reconnect (process &optional interactive)
"Reconnect to PROCESS.
@@ -333,8 +330,8 @@ INTERACTIVE is t if called interactively."
(eglot--connect (eglot--project process)
(eglot--major-mode process)
(eglot--short-name process)
- (eglot--contact process)
- (lambda (_proc) (eglot--message "Reconnected!"))))
+ (eglot--contact process))
+ (eglot--message "Reconnected!"))
(defvar eglot--inhibit-auto-reconnect nil
"If non-nil, don't autoreconnect on unexpected quit.")
@@ -343,6 +340,9 @@ INTERACTIVE is t if called interactively."
"Called when PROC undergoes CHANGE."
(eglot--log-event proc `(:message "Process state changed" :change ,change))
(when (not (process-live-p proc))
+ (with-current-buffer (eglot-events-buffer proc)
+ (let ((inhibit-read-only t))
+ (insert "\n----------b---y---e---b---y---e----------\n")))
;; Cancel outstanding timers
(maphash (lambda (_id triplet)
(cl-destructuring-bind (_success _error timeout) triplet
- [elpa] externals/eglot 8160cd4 071/139: Handle dynamic registration in general (but nothing specific yet), (continued)
- [elpa] externals/eglot 8160cd4 071/139: Handle dynamic registration in general (but nothing specific yet), João Távora, 2018/05/14
- [elpa] externals/eglot c4ffabc 083/139: Half-decent completion support, João Távora, 2018/05/14
- [elpa] externals/eglot d431d41 088/139: Fix bug in hover support, João Távora, 2018/05/14
- [elpa] externals/eglot 1356844 097/139: Fix odd bugs, João Távora, 2018/05/14
- [elpa] externals/eglot 6e76b08 100/139: Support workspace/applyEdit, João Távora, 2018/05/14
- [elpa] externals/eglot 5ce9ab0 106/139: Call eglot-eldoc-function after completion finishes, João Távora, 2018/05/14
- [elpa] externals/eglot ecd334f 101/139: Update README, João Távora, 2018/05/14
- [elpa] externals/eglot 39e8b9e 081/139: Add (dummy) tests and Travis CI integration, João Távora, 2018/05/14
- [elpa] externals/eglot 23b79e0 111/139: Shorten summary line to appease package-lint.el, João Távora, 2018/05/14
- [elpa] externals/eglot 37b7329 098/139: Reasonable textDocument/documentHighlight support, João Távora, 2018/05/14
- [elpa] externals/eglot d1cdcf1 119/139: Friendlier M-x eglot,
João Távora <=
- [elpa] externals/eglot 764347d 128/139: New command eglot-help-at-point and a README update, João Távora, 2018/05/14
- [elpa] externals/eglot 9bf3166 136/139: Don't define a menu if nothing to show there for now, João Távora, 2018/05/14
- [elpa] externals/eglot 54fc885 113/139: More RLS-specifics: update Flymake diags when indexing done, João Távora, 2018/05/14
- [elpa] externals/eglot 56c2e1d 104/139: Get rid of eglot-mode, João Távora, 2018/05/14
- [elpa] externals/eglot 9577dfc 125/139: Duh, json.el is in Emacs, and json-mode.el is useless here, João Távora, 2018/05/14
- [elpa] externals/eglot d33a9b5 103/139: Simplify eglot--signal-textDocument/didChange, João Távora, 2018/05/14
- [elpa] externals/eglot ef80455 121/139: Support :completionItem/resolve, João Távora, 2018/05/14
- [elpa] externals/eglot f89f859 114/139: Simplify mode-line updating logic, João Távora, 2018/05/14
- [elpa] externals/eglot 3a6c637 099/139: Support textDocument/rename, João Távora, 2018/05/14
- [elpa] externals/eglot 581608f 115/139: Resist server failure during synchronous requests, João Távora, 2018/05/14