emacs-elpa-diffs
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]