[elpa] master updated (02b929e -> 51a9354)

2018-05-14 Thread Tino Calancha
calancha pushed a change to branch master.

  from  02b929e   * el-search/el-search.el: Prefer adverb "backward" in 
names and text
   new  4cd7eca   Skip tests when Git is not available
   new  45ec30f   gited.el: Merge branch 'show-trunk-ci-status'
   new  51a9354   * packages/gited/gited.el: Bump version to v5.0.1


Summary of changes:
 packages/gited/gited.el | 57 +++--
 1 file changed, 41 insertions(+), 16 deletions(-)



[elpa] master 45ec30f 2/3: gited.el: Merge branch 'show-trunk-ci-status'

2018-05-14 Thread Tino Calancha
branch: master
commit 45ec30f49360bea8fdffa2ffab6be711cab2a88a
Author: Tino Calancha 
Commit: Tino Calancha 

gited.el: Merge branch 'show-trunk-ci-status'
---
 packages/gited/gited.el | 51 -
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/packages/gited/gited.el b/packages/gited/gited.el
index b1c9958..82e03ad 100644
--- a/packages/gited/gited.el
+++ b/packages/gited/gited.el
@@ -244,6 +244,7 @@
 ;;; Code:
 
 
+(require 'gited-ci)
 (require 'cl-lib)
 (require 'tabulated-list)
 (require 'dired)
@@ -665,6 +666,8 @@ The value returned is the value of the last form in BODY."
   (declare (indent 1) (debug t))
   (let ((cur-branch (make-symbol "cur-branch")))
 `(let ((,cur-branch gited-current-branch))
+   (when (gited-modified-files-p)
+ (user-error "Cannot checkout a new branch: there are modified files"))
(unwind-protect
(progn
  (gited-git-checkout nil ,branch)
@@ -1094,32 +1097,43 @@ DATA is a string to specify what we want to extract.  
For instance:
   (gited-git-command args (current-buffer) nil 'unquote)
   (buffer-string
 
-(defun gited--last-commit-msg ()
+(defun gited--last-commit-msg (&optional branch)
   "Return the last commit."
-  (gited--extract-from-commit "HEAD" "%B"))
+  (gited--extract-from-commit (or branch "HEAD") "%B"))
 
-(defun gited--last-commit-title ()
+(defun gited--last-commit-title (&optional branch)
   "Return title of the last commit."
-  (gited--extract-from-commit "HEAD" "%s"))
+  (gited--extract-from-commit (or branch "HEAD") "%s"))
 
-(defun gited--last-commit-author ()
+(defun gited--last-commit-author (&optional branch)
   "Return the last commit."
-  (gited--extract-from-commit "HEAD" "%an <%ae>"))
+  (gited--extract-from-commit (or branch "HEAD") "%an <%ae>"))
 
-(defun gited--last-commit-date ()
+(defun gited--last-commit-date (&optional branch)
   "Return the last commit."
-  (gited--extract-from-commit "HEAD" "%ai"))
+  (gited--extract-from-commit (or branch "HEAD") "%ai"))
+
+(defun gited--last-commit-hash (&optional branch)
+  "Return the last commit hash string."
+  (gited--extract-from-commit (or branch "HEAD") "%H"))
+
+(defun gited--last-trunk-commit ()
+  (gited--last-commit-hash (gited-trunk-branch)))
 
 ;; Non-nil while running an asynchronous Gited subprocess.
 (defvar-local gited--running-async-op nil)
 
-(defun gited-async-operation (command &optional remote-op-p buffer)
+(defvar gited-async-operation-callback nil
+  "A function to call once the current async process sucessfully completes.")
+
+(defun gited-async-operation (command &optional remote-op-p buffer callback)
   "Run COMMAND asynchronously.
 COMMAND perform a branch operation, i.e., rename or delete a branch.
 Optional arg REMOTE-OP-P, means the operation modify the remote
 repository.  Otherwise, the operation just change local branches.
 Optional arg BUFFER is the output buffer for the operation.  Otherwise,
-use `gited-output-buffer'."
+use `gited-output-buffer'.
+Optional arg CALLBACK is called if COMMAND completes successfully."
   (interactive)
   (if gited--running-async-op
   (user-error "Cannot run 2 Gited async process in parallel")
@@ -1140,6 +1154,7 @@ use `gited-output-buffer'."
   (setq gited--running-async-op t))
 (with-no-warnings
   (require 'shell) (shell-mode))
+(setq gited-async-operation-callback callback)
 (set-process-sentinel proc 'gited-async-operation-sentinel)
 (set-process-filter proc 'comint-output-filter)
 ;; Associate out-buf with gited-buf; this is used in the sentinel.
@@ -1168,7 +1183,12 @@ STATE is the state of process PROC."
   gited-op-string nil))
   ;; State is 'finished\n' when the process exit with code 0.
   (if (string-prefix-p "finished" state)
-  (message "%s done!" op-string)
+  (progn
+(message "%s done!" op-string)
+(when gited-async-operation-callback
+  (prog1  
+  (funcall gited-async-operation-callback)
+(setq gited-async-operation-callback nil
 (beep)
 (message "Process exited with non-zero status.  Please check")
 (display-buffer gited-output-buffer)
@@ -2077,6 +2097,7 @@ show similar info as that command."
  gited-current-remote-rep
   (message "OK, pull canceled")
 (let ((buf (gited--output-buffer))
+  (last-trunk-commit (gited--last-trunk-commit))
   (cmd (format "%s pull %s"
vc-git-program
gited-current-remote-rep))
@@ -2084,7 +2105,8 @@ show similar info as that command."
   (setq gited-output-buffer buf
 gited-op-string cmd)
   (with-current-buffer buf (erase-buffer))
-  (gited-async-operation cmd 'remote-op-p
+  (setq gited-last-trunk-commit last-trunk-commit)
+

[elpa] master 4cd7eca 1/3: Skip tests when Git is not available

2018-05-14 Thread Tino Calancha
branch: master
commit 4cd7ecac8091cad7b1c9526603191641c04cbc1d
Author: Tino Calancha 
Commit: Tino Calancha 

Skip tests when Git is not available

* packages/gited/gited-tests.el (gited-test2): New test
---
 packages/gited/gited.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/gited/gited.el b/packages/gited/gited.el
index b00cfca..b1c9958 100644
--- a/packages/gited/gited.el
+++ b/packages/gited/gited.el
@@ -10,7 +10,7 @@
 ;; Compatibility: GNU Emacs: 24.4
 ;; Version: 0.4.3
 ;; Package-Requires: ((emacs "24.4") (cl-lib "0.5"))
-;; Last-Updated: Tue Apr 10 11:31:19 JST 2018
+;; Last-Updated: Tue Apr 10 11:28:04 JST 2018
 ;;   By: calancha
 ;; Update #: 687
 



[elpa] master 51a9354 3/3: * packages/gited/gited.el: Bump version to v5.0.1

2018-05-14 Thread Tino Calancha
branch: master
commit 51a93541232fce6d0b1c0d0d6caebdc393a850bb
Author: Tino Calancha 
Commit: Tino Calancha 

* packages/gited/gited.el: Bump version to v5.0.1
---
 packages/gited/gited.el | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/packages/gited/gited.el b/packages/gited/gited.el
index 82e03ad..7f6857b 100644
--- a/packages/gited/gited.el
+++ b/packages/gited/gited.el
@@ -8,11 +8,11 @@
 
 ;; Created: Wed Oct 26 01:28:54 JST 2016
 ;; Compatibility: GNU Emacs: 24.4
-;; Version: 0.4.3
+;; Version: 0.5.1
 ;; Package-Requires: ((emacs "24.4") (cl-lib "0.5"))
-;; Last-Updated: Tue Apr 10 11:28:04 JST 2018
+;; Last-Updated: Tue May 15 13:30:52 JST 2018
 ;;   By: calancha
-;; Update #: 687
+;; Update #: 696
 
 ;;
 ;;



[elpa] externals/eglot 5e4eec0: * eglot-tests.el: Fix copyright

2018-05-14 Thread Stefan Monnier
branch: externals/eglot
commit 5e4eec039cc90378bac7b85397050b0a1f1a33e0
Author: Stefan Monnier 
Commit: Stefan Monnier 

* eglot-tests.el: Fix copyright
---
 eglot-tests.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index 119d873..accb113 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -1,6 +1,6 @@
 ;;; eglot-tests.el --- Tests for eglot.el-*- lexical-binding: t; 
-*-
 
-;; Copyright (C) 2018  João Távora
+;; Copyright (C) 2018  Free Software Foundation, Inc.
 
 ;; Author: João Távora 
 ;; Keywords: tests



[elpa] master 02b929e: * el-search/el-search.el: Prefer adverb "backward" in names and text

2018-05-14 Thread Michael Heerdegen
branch: master
commit 02b929ebd6a8b84fafdfedb92f4832ae1a851cf9
Author: Michael Heerdegen 
Commit: Michael Heerdegen 

* el-search/el-search.el: Prefer adverb "backward" in names and text

Prefer the adverb "backward" over "backwards" in package "el-search".

(el-search-pattern-backward, el-search-search-backward-from-isearch):
Renamed from "el-search-pattern-backwards" and
"el-search-search-backwards-from-isearch".  Change all occurrences;
define obsolete function aliases for the old names.
Change all other occurrences of the adverb to "backward".
---
 packages/el-search/el-search.el | 45 -
 1 file changed, 26 insertions(+), 19 deletions(-)

diff --git a/packages/el-search/el-search.el b/packages/el-search/el-search.el
index e2b7179..8b42eb2 100644
--- a/packages/el-search/el-search.el
+++ b/packages/el-search/el-search.el
@@ -7,7 +7,7 @@
 ;; Created: 29 Jul 2015
 ;; Keywords: lisp
 ;; Compatibility: GNU Emacs 25
-;; Version: 1.6.6
+;; Version: 1.6.7
 ;; Package-Requires: ((emacs "25") (stream "2.2.4") (cl-print "1.0"))
 
 
@@ -76,8 +76,8 @@
 ;;   C-S, M-s e s (el-search-pattern)
 ;; Start a search in the current buffer/go to the next match.
 ;;
-;;   C-R, M-s e r (el-search-pattern-backwards)
-;; Search backwards.
+;;   C-R, M-s e r (el-search-pattern-backward)
+;; Search backward.
 ;;
 ;;   C-%, M-s e % (el-search-query-replace)
 ;; Do a query-replace.
@@ -529,7 +529,7 @@ The default value is ask-multi."
 
 (defvar el-search-keep-transient-map-commands
   '(el-search-pattern
-el-search-pattern-backwards
+el-search-pattern-backward
 el-search-jump-to-search-head
 el-search-from-beginning
 el-search-skip-directory
@@ -1548,7 +1548,7 @@ in, in order, when called with no arguments."
   (cl-flet ((keybind (apply-partially #'funcall function)))
 
 (keybind emacs-lisp-mode-map   ?s #'el-search-pattern)
-(keybind emacs-lisp-mode-map   ?r #'el-search-pattern-backwards)
+(keybind emacs-lisp-mode-map   ?r #'el-search-pattern-backward)
 (keybind emacs-lisp-mode-map   ?% #'el-search-query-replace)
 (keybind emacs-lisp-mode-map   ?h #'el-search-this-sexp) ;h like 
in "highlight" or "here"
 (keybind global-map?j #'el-search-jump-to-search-head)
@@ -1563,7 +1563,7 @@ in, in order, when called with no arguments."
 (keybind el-search-read-expression-map ?o 
#'el-search-set-occur-flag-exit-minibuffer)
 
 (keybind isearch-mode-map  ?s #'el-search-search-from-isearch)
-(keybind isearch-mode-map  ?r 
#'el-search-search-backwards-from-isearch)
+(keybind isearch-mode-map  ?r 
#'el-search-search-backward-from-isearch)
 (keybind isearch-mode-map  ?% #'el-search-replace-from-isearch)
 (keybind isearch-mode-map  ?o #'el-search-occur-from-isearch)
 
@@ -1584,7 +1584,7 @@ in, in order, when called with no arguments."
 (el-search-loop-over-bindings
  (lambda (_map key command)
(when (memq command '(el-search-pattern
- el-search-pattern-backwards
+ el-search-pattern-backward
  el-search-query-replace
  el-search-from-beginning
  el-search-skip-directory
@@ -2415,8 +2415,8 @@ With prefix arg, restart the current search."
   (el-search-continue-search))
 
 ;;;###autoload
-(defun el-search-pattern-backwards (pattern)
-  "Search the current buffer backwards for matches of PATTERN."
+(defun el-search-pattern-backward (pattern)
+  "Search the current buffer backward for matches of PATTERN."
   (declare (interactive-only t));; FIXME: define noninteractive version - and 
-1 with hms like
 ;; `el-search--search-pattern-1'
   (interactive (el-search-pattern--interactive))
@@ -2476,7 +2476,7 @@ With prefix arg, restart the current search."
 (ding)
 (el-search--message-no-log "No matches")
 (sit-for .7))
-(let ((keys (car (where-is-internal 
'el-search-pattern-backwards
+(let ((keys (car (where-is-internal 
'el-search-pattern-backward
   (el-search--message-no-log
(if keys
(format "No (more) match; hit %s to wrap search" 
(key-description keys))
@@ -2496,7 +2496,11 @@ With prefix arg, restart the current search."
   (setq el-search--success t))
 
 (define-obsolete-function-alias 'el-search-previous-match
-  'el-search-pattern-backwards "since el-search-1.3")
+  'el-search-pattern-backward "since el-search-1.3")
+(define-obsolete-function-alias 'el-search-pattern-backwards
+  'el-search-pattern-backward "since el-search-1.6.7")
+
+
 
 ;;;###autoload
 (defun el-search-this-sexp (sexp)
@@ -2633,12 +2637,12 @@ Prompt for a 

[elpa] master 58afd67: Auto-update of .gitignore

2018-05-14 Thread Stefan Monnier
branch: master
commit 58afd670b21873ab2e86b4624b8160a78fa8bb8c
Author: Stefan Monnier 
Commit: Stefan Monnier 

Auto-update of .gitignore
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 3d6627e..fad1bfc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ packages/cl-print/
 packages/dash/
 packages/dismal/
 packages/ebdb/
+packages/eglot/
 packages/ergoemacs-mode/
 packages/exwm/
 packages/hyperbole/



[elpa] master 950ac36: Add packages/eglot as an :external

2018-05-14 Thread Jo�o T�vora
branch: master
commit 950ac36ab6c448b35988c8270d1a27ff8c81a71d
Author: João Távora 
Commit: João Távora 

Add packages/eglot as an :external

* externals-list ("eglot"): Add :external package
---
 externals-list | 1 +
 1 file changed, 1 insertion(+)

diff --git a/externals-list b/externals-list
index d66de4a..32d1a31 100644
--- a/externals-list
+++ b/externals-list
@@ -54,6 +54,7 @@
  ("dts-mode"   :subtree "https://github.com/bgamari/dts-mode.git";)
  ("easy-kill"  :subtree "https://github.com/leoliu/easy-kill";)
  ("ebdb":external "https://github.com/girzel/ebdb.git";)
+ ("eglot"   :external "https://github.com/joaotavora/eglot.git";)
  ("eldoc-eval" :subtree 
"https://github.com/thierryvolpiatto/eldoc-eval.git";)
  ("enwc"   :subtree 
"bzr::bzr://bzr.savannah.nongnu.org/enwc/trunk")
  ("ergoemacs-mode" :external 
"https://github.com/ergoemacs/ergoemacs-mode.git";)



[elpa] externals/elpa 6e76b08 100/139: Support workspace/applyEdit

2018-05-14 Thread Jo�o T�vora
branch: externals/elpa
commit 6e76b085a7c21790ee9df905159a7d7b1f90
Author: João Távora 
Commit: João Távora 

Support workspace/applyEdit

* eglot.el (eglot--reply): Don't send result or error if not
provided.
(eglot--server-workspace/applyEdit): New server method.
(eglot--apply-text-edits): Rework.
(eglot--apply-workspace-edit): New helper.
(eglot-rename): Simplify.
---
 eglot.el | 135 ++-
 1 file changed, 82 insertions(+), 53 deletions(-)

diff --git a/eglot.el b/eglot.el
index 9ba87ef..37ad616 100644
--- a/eglot.el
+++ b/eglot.el
@@ -664,10 +664,10 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 
 (cl-defun eglot--reply (process id &key result error)
   "Reply to PROCESS's request ID with MESSAGE."
-  (eglot--process-send process (eglot--obj :jsonrpc  "2.0"
-   :id id
-   :result result
-   :error error)))
+  (eglot--process-send
+   process `(:jsonrpc  "2.0" :id ,id
+   ,@(when result `(:result ,result))
+   ,@(when error `(:error ,error)
 
 
 ;;; Helpers
@@ -1031,6 +1031,20 @@ running.  INTERACTIVE is t if called interactively."
registrations)
   (eglot--reply proc id :result (eglot--obj :message "OK")
 
+(cl-defun eglot--server-workspace/applyEdit
+(proc &key id _label edit)
+  "Handle notification client/registerCapability"
+  (condition-case err
+  (progn
+(eglot--apply-workspace-edit edit 'confirm)
+(eglot--reply proc id :result `(:applied )))
+(error
+ (eglot--reply proc id
+   :result `(:applied :json-false)
+   :error
+   (eglot--obj :code -32001
+   :message (format "%s" err))
+
 (defvar eglot--recent-before-changes nil
   "List of recent changes as collected by `eglot--before-change'.")
 (defvar eglot--recent-after-changes nil
@@ -1370,61 +1384,76 @@ DUMMY is ignored"
  entries))
 (funcall oldfun)))
 
-(defun eglot--apply-text-edits (uri edits proc &optional version)
-  "Apply the EDITS for buffer of URI and return it."
-  (let* ((path (eglot--uri-to-path uri))
- (buffer (and path
-  (find-file-noselect path
-(unless buffer
-  (eglot--error "Can't find `%s' to perform server edits"))
-(with-current-buffer buffer
-  (unless (eq proc (eglot--current-process))
-(eglot--error "Buffer `%s' for `%s' isn't managed by %s"
-  (current-buffer) uri proc))
-  (unless (or (not version)
-  (equal version eglot--versioned-identifier))
-(eglot--error "Edits on `%s' require version %d, you have %d"
-  uri version eglot--versioned-identifier))
-  (eglot--mapply
-   (eglot--lambda (&key range newText)
- (save-restriction
-   (widen)
-   (save-excursion
- (let ((start (eglot--lsp-position-to-point (plist-get range 
:start
-   (goto-char start)
-   (delete-region start
-  (eglot--lsp-position-to-point (plist-get range 
:end)))
-   (insert newText)
-   edits)
-  (eglot--message "%s: %s edits" (current-buffer) (length edits)))
-buffer))
+(defun eglot--apply-text-edits (buffer edits &optional version)
+  "Apply the EDITS for BUFFER."
+  (with-current-buffer buffer
+(unless (or (not version)
+(equal version eglot--versioned-identifier))
+  (eglot--error "Edits on `%s' require version %d, you have %d"
+buffer version eglot--versioned-identifier))
+(eglot--mapply
+ (eglot--lambda (&key range newText)
+   (save-restriction
+ (widen)
+ (save-excursion
+   (let ((start (eglot--lsp-position-to-point (plist-get range 
:start
+ (goto-char start)
+ (delete-region start
+(eglot--lsp-position-to-point (plist-get range 
:end)))
+ (insert newText)
+ edits)
+(eglot--message "%s: Performed %s edits" (current-buffer) (length edits
+
+(defun eglot--apply-workspace-edit (wedit &optional confirm)
+  "Apply the workspace edit WEDIT.  If CONFIRM, ask user first."
+  (let (prepared)
+(cl-destructuring-bind (&key changes documentChanges)
+wedit
+  (cl-loop
+   for change on documentChanges
+   do (push (cl-destructuring-bind (&key textDocument edits) change
+  (cl-destructuring-bind (&key uri version) textDocument
+(list (eglot--uri-to-path uri) edits version)))
+prepared))
+  (cl-loop for (uri edits) on changes by #'cddr
+   do (push (list (eglot--uri-to-path uri) edits) prepared)))
+(if (or confirm
+  

[elpa] externals/eglot 2775dea 003/139: Rename eglot--continuations eglot--pending-continuations

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 2775deaf534eab2b919ef99fc7da957987a02092
Author: João Távora 
Commit: João Távora 

Rename eglot--continuations eglot--pending-continuations
---
 eglot.el | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/eglot.el b/eglot.el
index f2ef418..166f23c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -67,7 +67,7 @@
 (eglot--define-process-var eglot--expected-bytes nil
   "How many bytes declared by server")
 
-(eglot--define-process-var eglot--continuations (make-hash-table)
+(eglot--define-process-var eglot--pending-continuations (make-hash-table)
   "A hash table of request ID to continuation lambdas")
 
 (eglot--define-process-var eglot--events-buffer nil
@@ -264,12 +264,14 @@
   (let* ((response-id (plist-get message :id))
  (err (plist-get message :error))
  (continuations (and response-id
- (gethash response-id (eglot--continuations)
+ (gethash response-id 
(eglot--pending-continuations)
 (cond ((and response-id
 (not continuations))
(eglot--warn "Ooops no continuation for id %s" response-id))
   (continuations
(cancel-timer (third continuations))
+   (remhash response-id
+(eglot--pending-continuations))
(cond (err
   (apply (second continuations) err))
  (t
@@ -303,7 +305,7 @@
  (timeout-fn (or timeout-fn
  (lambda ()
(eglot--warn "Tired of waiting for reply to %s" id)
-   (remhash id (eglot--continuations process)
+   (remhash id (eglot--pending-continuations 
process)
  (error-fn (or error-fn
(cl-function
 (lambda (&key code message)
@@ -330,7 +332,7 @@
  timeout-fn
(lambda ()
  (throw catch-tag (apply 
timeout-fn))
-   (eglot--continuations process))
+   (eglot--pending-continuations process))
   (unless async-p
 (while t
   (unless (eq (process-status process) 'open)



[elpa] externals/elpa 29f6b4c 129/139: Tweak README.md

2018-05-14 Thread Jo�o T�vora
branch: externals/elpa
commit 29f6b4c8cd783a47a2b9c741a518df99aa959360
Author: João Távora 
Commit: João Távora 

Tweak README.md

* README.md (Commands and keybindings): New section.
---
 README.md | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index a3789a4..4dfe0a6 100644
--- a/README.md
+++ b/README.md
@@ -37,20 +37,22 @@ server. To skip the guess and always be prompted use `C-u 
M-x eglot`.
 
 Here's a summary of available commands:
 
-- `M-x eglot-reconnect` reconnects to the server
+- `M-x eglot`, as described above;
+
+- `M-x eglot-reconnect` reconnects to the server;
 
 - `M-x eglot-rename` asks the server to rename the symbol at point
 
 - `M-x eglot-help-at-point` asks the server for help for symbol at
   point. Currently this is what `eldoc-mode` displays in the echo
-  area.
+  area;
 
 - `M-x eglot-events-buffer` jumps to the events buffer for debugging
   communication with the server.
 
 There are *no keybindings* specific to Eglot, but you can bind stuff
 in `eglot-mode-map`, which is active as long as Eglot is managing a
-file in your project. The commands don't need to be eglot-specific,
+file in your project. The commands don't need to be Eglot-specific,
 either:
 
 ```



[elpa] externals/elpa c417eb4 009/139: Cancel timeouts when process dies unexpectedly

2018-05-14 Thread Jo�o T�vora
branch: externals/elpa
commit c417eb4343ff76c18d323dd2a9861526940551f0
Author: João Távora 
Commit: João Távora 

Cancel timeouts when process dies unexpectedly
---
 eglot.el | 53 -
 1 file changed, 32 insertions(+), 21 deletions(-)

diff --git a/eglot.el b/eglot.el
index e3b288b..5699775 100644
--- a/eglot.el
+++ b/eglot.el
@@ -153,9 +153,16 @@
   (with-current-buffer (process-buffer process)
 (eglot--debug "Process state changed to %s" change)
 (when (not (process-live-p process))
+  ;; Remember to cancel all timers
+  ;;
+  (maphash (lambda (id v) 
+ (cl-destructuring-bind (_success _error timeout) v
+   (eglot--message "Cancelling timer for continuation %s" id)
+   (cancel-timer timeout)))
+   (eglot--pending-continuations process))
   (cond ((process-get process 'eglot--moribund)
  (eglot--message "Process exited with status %s"
-  (process-exit-status process)))
+ (process-exit-status process)))
 (t
  (eglot--warn "Process unexpectedly changed to %s" change))
 
@@ -319,26 +326,30 @@
   :method  ,method
   :params  ,params))
 (catch catch-tag
-  (puthash id
-   (list (if async-p
- success-fn
-   (lambda (&rest args)
- (throw catch-tag (apply success-fn args
- (if async-p
- error-fn
-   (lambda (&rest args)
- (throw catch-tag (apply error-fn args
- (run-with-timer 5 nil
- (if async-p
- timeout-fn
-   (lambda ()
- (throw catch-tag (apply 
timeout-fn))
-   (eglot--pending-continuations process))
-  (unless async-p
-(while t
-  (unless (eq (process-status process) 'open)
-(eglot--error "Process %s died unexpectedly" process))
-  (accept-process-output nil 0.01))
+  (let ((timeout-timer
+ (run-with-timer 5 nil
+ (if async-p
+ timeout-fn
+   (lambda ()
+ (throw catch-tag (apply timeout-fn)))
+(puthash id
+ (list (if async-p
+   success-fn
+ (lambda (&rest args)
+   (throw catch-tag (apply success-fn args
+   (if async-p
+   error-fn
+ (lambda (&rest args)
+   (throw catch-tag (apply error-fn args
+   timeout-timer)
+ (eglot--pending-continuations process))
+(unless async-p
+  (unwind-protect
+  (while t
+(unless (process-live-p process)
+  (eglot--error "Process %s died unexpectedly" process))
+(accept-process-output nil 0.01))
+(cancel-timer timeout-timer)))
 
 
 ;;; Requests



[elpa] externals/elpa 88e3655 040/139: Appease checkdoc.el

2018-05-14 Thread Jo�o T�vora
branch: externals/elpa
commit 88e36555fab9375000aca7dccf37d7e0d3a8861a
Author: João Távora 
Commit: João Távora 

Appease checkdoc.el

* eglot.el (eglot--process-send, eglot--next-request-id)
(eglot--current-buffer-VersionedTextDocumentIdentifier)
(eglot--current-buffer-TextDocumentItem)
(eglot--after-change, eglot--signalDidOpen)
(eglot--signalDidClose, eglot--maybe-signal-didChange):
Add docstring.
---
 eglot.el | 9 +
 1 file changed, 9 insertions(+)

diff --git a/eglot.el b/eglot.el
index 8bb0729..cd546a3 100644
--- a/eglot.el
+++ b/eglot.el
@@ -390,6 +390,7 @@ identifier.  ERROR is non-nil if this is an error."
 (defvar eglot--expect-carriage-return nil)
 
 (defun eglot--process-send (id proc message)
+  "Send MESSAGE to PROC (ID is optional)."
   (let* ((json (json-encode message))
  (to-send (format "Content-Length: %d\r\n\r\n%s"
   (string-bytes json)
@@ -403,6 +404,7 @@ identifier.  ERROR is non-nil if this is an error."
 (defvar eglot--next-request-id 0)
 
 (defun eglot--next-request-id ()
+  "Compute the next id for a client request."
   (setq eglot--next-request-id (1+ eglot--next-request-id)))
 
 (defun eglot-forget-pending-continuations (process)
@@ -789,6 +791,7 @@ running.  INTERACTIVE is t if called interactively."
   eglot--versioned-identifier)
 
 (defun eglot--current-buffer-VersionedTextDocumentIdentifier ()
+  "Compute VersionedTextDocumentIdentifier object for current buffer."
   (eglot--obj :uri
   (concat "file://"
   (url-hexify-string
@@ -797,6 +800,7 @@ running.  INTERACTIVE is t if called interactively."
   :version (eglot--current-buffer-versioned-identifier)))
 
 (defun eglot--current-buffer-TextDocumentItem ()
+  "Compute TextDocumentItem object for current buffer."
   (append
(eglot--current-buffer-VersionedTextDocumentIdentifier)
(eglot--obj :languageId (cdr (assoc major-mode
@@ -808,24 +812,29 @@ running.  INTERACTIVE is t if called interactively."
  (buffer-substring-no-properties (point-min) (point-max))
 
 (defun eglot--after-change (start end length)
+  "Hook onto `after-change-functions'.
+Records START, END and LENGTH locally."
   (cl-incf eglot--versioned-identifier)
   (push (list start end length) eglot--recent-changes)
   ;; (eglot--message "start is %s, end is %s, length is %s" start end length)
   )
 
 (defun eglot--signalDidOpen ()
+  "Send textDocument/didOpen to server."
   (eglot--notify (eglot--current-process-or-lose)
  :textDocument/didOpen
  (eglot--obj :textDocument
  (eglot--current-buffer-TextDocumentItem
 
 (defun eglot--signalDidClose ()
+  "Send textDocument/didClose to server."
   (eglot--notify (eglot--current-process-or-lose)
  :textDocument/didClose
  (eglot--obj :textDocument
  (eglot--current-buffer-TextDocumentItem
 
 (defun eglot--maybe-signal-didChange ()
+  "Send textDocument/didChange to server."
   (when eglot--recent-changes
 (save-excursion
   (save-restriction



[elpa] externals/eglot 42177d0 107/139: New "deferred requests" that wait until server is ready

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 42177d02d765c039a1343f5f6966dc50ec278c21
Author: João Távora 
Commit: João Távora 

New "deferred requests" that wait until server is ready

Calling textDocument/hover or textDocument/documentHighlight before
the server has had a chance to process a textDocument/didChange is
normally useless. The matter is worse for servers like RLS which only
become ready much later and send a special notif for it (see
https://github.com/rust-lang-nursery/rls/issues/725).

So, keeping the same coding style add a DEFERRED arg to eglot--request
that makes it maybe not run the function immediately. Add a bunch of
logic for probing readiness of servers.

* README.md: Update

* eglot.el (eglot--deferred-actions): New process-local var.
(eglot--process-filter): Call deferred actions.
(eglot--request): Rewrite.
(eglot--sync-request): Rewrite.
(eglot--call-deferred, eglot--ready-predicates)
(eglot--server-ready-p): New helpers.
(eglot--signal-textDocument/didChange): Set spinner and call
deferred actions.
(eglot-completion-at-point): Pass DEFERRED to eglot-sync-request.
(eglot-eldoc-function): Pass DEFERRED to eglot-request
(eglot--rls-probably-ready-for-p): New helper.
(rust-mode-hook): Add eglot--setup-rls-idiosyncrasies
(eglot--setup-rls-idiosyncrasies): New helper.
---
 README.md |  10 +--
 eglot.el  | 237 +++---
 2 files changed, 140 insertions(+), 107 deletions(-)

diff --git a/README.md b/README.md
index faf2dea..66f2131 100644
--- a/README.md
+++ b/README.md
@@ -111,19 +111,21 @@ User-visible differences:
 - Automatically restarts frequently crashing servers (like RLS).
 - Server-initiated edits are confirmed with the user.
 - Diagnostics work out-of-the-box (no `flycheck.el` needed).
+- Smoother/more responsive (read below).

 Under the hood:
 
 - Message parser is much much simpler.
-- Easier to read and maintain elisp. Yeah I know, *extremely
-  subjective*, so judge for yourself.
+- Defers signature requests like `textDocument/hover` until server is
+  ready. Also sends `textDocument/didChange` for groups of edits, not
+  one per each tiny change.
+- Easier to read and maintain elisp. Yeah I know, *very subjective*,
+  so judge for yourself.
 - About 1k LOC lighter.
 - Development doesn't require Cask, just Emacs.
 - Project support doesn't need `projectile.el`, uses Emacs's `project.el`
 - Requires the upcoming Emacs 26
 - Contained in one file
-- Sends `textDocument/didChange` for groups of edits, not one per each
-  tiny change.
 - Its missing tests! This is *not good*
 
 [lsp]: https://microsoft.github.io/language-server-protocol/
diff --git a/eglot.el b/eglot.el
index d5eae03..9a0b824 100644
--- a/eglot.el
+++ b/eglot.el
@@ -135,6 +135,10 @@ A list (WHAT SERIOUS-P)." t)
 Either a list of strings (a shell command and arguments), or a
 list of a single string of the form :")
 
+(eglot--define-process-var eglot--deferred-actions
+(make-hash-table :test #'equal)
+  "Actions deferred to when server is thought to be ready.")
+
 (defun eglot--make-process (name managed-major-mode contact)
   "Make a process from CONTACT.
 NAME is a name to give the inferior process or connection.
@@ -442,7 +446,8 @@ INTERACTIVE is t if called interactively."
   (throw done 
:waiting-for-more-bytes-in-this-message
   ;; Saved parsing state for next visit to this filter
   ;;
-  (setf (eglot--expected-bytes proc) expected-bytes))
+  (setf (eglot--expected-bytes proc) expected-bytes
+(eglot--call-deferred proc)))
 
 (defun eglot-events-buffer (process &optional interactive)
   "Display events buffer for current LSP connection PROCESS.
@@ -549,110 +554,118 @@ is a symbol saying if this is a client or server 
originated."
   (interactive (list (eglot--current-process-or-lose)))
   (setf (eglot--status process) nil))
 
-(cl-defun eglot--request (process
-  method
-  params
-  &key success-fn error-fn timeout-fn (async-p t)
-  (timeout eglot-request-timeout))
-  "Make a request to PROCESS, expecting a reply.
-Return the ID of this request, unless ASYNC-P is nil, in which
-case never returns locally.  Wait TIMEOUT seconds for a
-response."
-  (let* ((id (eglot--next-request-id))
- (timeout-fn (or timeout-fn
- (lambda ()
-   (eglot--warn
-"(request) Tired of waiting for reply to %s" id
- (error-fn (or error-fn
-   (cl-function
-(lambda (&key code message &allow-other-keys)
-  (setf (eglot--status process) `(,message t))
-  (eglot--warn
-   "(request) Request id=%s error

[elpa] externals/eglot af14364 093/139: Only request stuff that server says it's capable of

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit af143643bbdb0764812c7f4a8e342ce5f9b20c7c
Author: João Távora 
Commit: João Távora 

Only request stuff that server says it's capable of

* eglot.el (eglot--server-capable): New helper.
(eglot-xref-backend)
(xref-backend-identifier-completion-table)
(xref-backend-references, xref-backend-apropos)
(eglot-completion-at-point, eglot-eldoc-function): Use it.
---
 eglot.el | 98 +++-
 1 file changed, 53 insertions(+), 45 deletions(-)

diff --git a/eglot.el b/eglot.el
index 02439df..7cc3756 100644
--- a/eglot.el
+++ b/eglot.el
@@ -740,6 +740,10 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
(font-lock-ensure)
(buffer-string)
 
+(defun eglot--server-capable (feat)
+  "Determine if current server is capable of FEAT."
+  (plist-get (eglot--capabilities (eglot--current-process-or-lose)) feat))
+
 
 ;;; Minor modes
 ;;;
@@ -1158,7 +1162,9 @@ Calls REPORT-FN maybe if server publishes diagnostics in 
time."
   ;; make the server report new diagnostics.
   (eglot--signal-textDocument/didChange))
 
-(defun eglot-xref-backend () "EGLOT xref backend." 'eglot)
+(defun eglot-xref-backend ()
+  "EGLOT xref backend."
+  (when (eglot--server-capable :definitionProvider) 'eglot))
 
 (defvar eglot--xref-known-symbols nil)
 
@@ -1179,26 +1185,27 @@ DUMMY is ignored"
(plist-get position :character
 
 (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot)))
-  (let ((proc (eglot--current-process-or-lose))
-(text-id (eglot--current-buffer-TextDocumentIdentifier)))
-(completion-table-with-cache
- (lambda (string)
-   (setq eglot--xref-known-symbols
- (eglot--mapply
-  (eglot--lambda (&key name kind location containerName)
-(propertize name
-:position (plist-get
-   (plist-get location :range)
-   :start)
-:locations (list location)
-:textDocument text-id
-:kind kind
-:containerName containerName))
-  (eglot--sync-request proc
-   :textDocument/documentSymbol
-   (eglot--obj
-:textDocument text-id
-   (all-completions string eglot--xref-known-symbols)
+  (when (eglot--server-capable :documentSymbolProvider)
+(let ((proc (eglot--current-process-or-lose))
+  (text-id (eglot--current-buffer-TextDocumentIdentifier)))
+  (completion-table-with-cache
+   (lambda (string)
+ (setq eglot--xref-known-symbols
+   (eglot--mapply
+(eglot--lambda (&key name kind location containerName)
+  (propertize name
+  :position (plist-get
+ (plist-get location :range)
+ :start)
+  :locations (list location)
+  :textDocument text-id
+  :kind kind
+  :containerName containerName))
+(eglot--sync-request proc
+ :textDocument/documentSymbol
+ (eglot--obj
+  :textDocument text-id
+ (all-completions string eglot--xref-known-symbols))
 
 (cl-defmethod xref-backend-identifier-at-point ((_backend (eql eglot)))
   (let ((symatpt (symbol-at-point)))
@@ -1226,6 +1233,7 @@ DUMMY is ignored"
  location-or-locations)))
 
 (cl-defmethod xref-backend-references ((_backend (eql eglot)) identifier)
+  (unless (eglot--server-capable :referencesProvider) (cl-return nil))
   (let* ((identifier (if (get-text-property 0 :position identifier)
  identifier
(car (member identifier eglot--xref-known-symbols
@@ -1234,8 +1242,7 @@ DUMMY is ignored"
  (textDocument
   (and identifier (get-text-property 0 :textDocument identifier
 (unless (and position textDocument)
-  (eglot--error "Sorry, can't discover where %s is in the workspace"
-identifier))
+  (eglot--error "Don't know where %s is in the workspace" identifier))
 (eglot--mapply
  (eglot--lambda (&key uri range)
(eglot--xref-make identifier uri (plist-get range :start)))
@@ -1249,21 +1256,21 @@ DUMMY is ignored"
:context (eglot--obj :includeDeclaration t))
 
 (cl-defmethod xref-backend-apropos ((_backend (eql eglot)) pattern)
-  (eglot--mapply
-   (eglot--lambda (&key name location &allow-other-keys)
- (let ((range (plist-get location :range))
-

[elpa] externals/eglot 49fb02f 135/139: Use RLS in Travis CI and add actual tests

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 49fb02fc1c838da6c4764d498540115c85acbdff
Author: João Távora 
Commit: João Távora 

Use RLS in Travis CI and add actual tests

Also run a hook when connected

* eglot-tests.el (eglot--with-dirs-and-files)
(eglot--make-file-or-dirs, eglot--call-with-dirs-and-files)
(eglot--find-file-noselect): New helpers.
(auto-detect-running-server, auto-reconnect): New actual tests.

* eglot.el (eglot-connect): Run hook when connected
(eglot-connect-hook): New variable

* .travis.yml: Use rust stable and install rls

* README.md: Update mention of automated tests
---
 .travis.yml|   9 +++-
 README.md  |   3 +-
 eglot-tests.el | 128 +
 eglot.el   |   3 ++
 4 files changed, 140 insertions(+), 3 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 7a89327..2f0db4c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
-language: generic
+language: rust
 sudo: false
+rust:
+  - stable
 
 env:
   global:
@@ -13,7 +15,10 @@ install:
   # Configure $PATH: Emacs installed to /tmp/emacs
   - export PATH=/tmp/emacs/bin:${PATH}
   - emacs --version
-
+  # Install RLS
+  - rustup update
+  - rustup component add rls-preview rust-analysis rust-src
+
 script:
   - make check
 
diff --git a/README.md b/README.md
index 4683951..e5a2394 100644
--- a/README.md
+++ b/README.md
@@ -162,7 +162,8 @@ Under the hood:
 - Project support doesn't need `projectile.el`, uses Emacs's `project.el`
 - Requires the upcoming Emacs 26
 - Contained in one file
-- Its missing tests! This is *not good*
+- Has automated tests that check against actual LSP servers
+  
 
 [lsp]: https://microsoft.github.io/language-server-protocol/
 [rls]: https://github.com/rust-lang-nursery/rls
diff --git a/eglot-tests.el b/eglot-tests.el
index 0f29519..119d873 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -24,9 +24,137 @@
 
 ;;; Code:
 (require 'eglot)
+(require 'cl-lib)
 (require 'ert)
 
+;; Helpers
+
+(defmacro eglot--with-dirs-and-files (dirs &rest body)
+  (declare (indent defun) (debug t))
+  `(eglot--call-with-dirs-and-files
+,dirs #'(lambda () ,@body)))
+
+(defun eglot--make-file-or-dirs (ass)
+  (let ((file-or-dir-name (car ass))
+(content (cdr ass)))
+(cond ((listp content)
+   (make-directory file-or-dir-name 'parents)
+   (let ((default-directory (concat default-directory "/" 
file-or-dir-name)))
+ (mapc #'eglot--make-file-or-dirs content)))
+  ((stringp content)
+   (with-temp-buffer
+ (insert content)
+ (write-region nil nil file-or-dir-name nil 'nomessage)))
+  (t
+   (message "[yas] oops don't know this content")
+
+(defun eglot--call-with-dirs-and-files (dirs fn)
+  (let* ((default-directory (make-temp-file "eglot--fixture" t))
+ new-buffers new-processes)
+(with-temp-message ""
+  (unwind-protect
+  (let ((find-file-hook
+ (cons (lambda () (push (current-buffer) new-buffers))
+   find-file-hook))
+(eglot-connect-hook
+ (lambda (proc) (push proc new-processes
+(mapc #'eglot--make-file-or-dirs dirs)
+(funcall fn))
+(eglot--message "Killing buffers %s,  deleting %s, killing %s"
+(mapconcat #'buffer-name new-buffers ", ")
+default-directory
+new-processes)
+(delete-directory default-directory 'recursive)
+(let ((eglot-autoreconnect nil))
+  (mapc #'eglot-shutdown
+(cl-remove-if-not #'process-live-p new-processes)))
+(mapc #'kill-buffer new-buffers)
+
+(cl-defmacro eglot--with-test-timeout (timeout &body body)
+  (declare (indent 1) (debug t))
+  `(eglot--call-with-test-timeout ,timeout (lambda () ,@body)))
+
+(defun eglot--call-with-test-timeout (timeout fn)
+  (let* ((tag (make-symbol "tag"))
+ (timed-out (make-symbol "timeout"))
+ (timer )
+ (eglot-request-timeout 1)
+ (retval))
+(unwind-protect
+(setq retval
+  (catch tag
+(setq timer
+  (run-with-timer timeout nil
+  (lambda () (throw tag timed-out
+(funcall fn)))
+  (cancel-timer timer)
+  (when (eq retval timed-out)
+(error "Test timeout!")
+
+(defun eglot--find-file-noselect (file &optional noerror)
+  (unless (or noerror
+  (file-readable-p file)) (error "%s does not exist" file))
+  (find-file-noselect file))
+
+
+;; `rust-mode' is not a part of emacs. So define these two shims which
+;; should be more than enough for testing
+(unless (functionp 'rust-mode)
+  (define-derived-mode rust-mode prog-mode "Rust"))
+(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))
+
+
 (ert-deftest dummy () "A du

[elpa] externals/eglot f89f859 114/139: Simplify mode-line updating logic

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit f89f859eb71597f4ba7327d8758c2e9c7afb67fe
Author: João Távora 
Commit: João Távora 

Simplify mode-line updating logic

* eglot.el (eglot--define-process-var): Simplify.
(eglot--short-name, eglot--spinner, eglot--status): Don't
auto-update mode-line.
(eglot--process-receive): Update it here.
---
 eglot.el | 24 +---
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/eglot.el b/eglot.el
index 1ba5324..bf0b9e9 100644
--- a/eglot.el
+++ b/eglot.el
@@ -78,11 +78,9 @@
 (if (project-current) "" " (Also no current project)"
 
 (defmacro eglot--define-process-var
-(var-sym initval &optional doc mode-line-update-p)
+(var-sym initval &optional doc)
   "Define VAR-SYM as a generalized process-local variable.
-INITVAL is the default value.  DOC is the documentation.
-MODE-LINE-UPDATE-P says to also force a mode line update
-after setting it."
+INITVAL is the default value.  DOC is the documentation."
   (declare (indent 2))
   `(progn
  (put ',var-sym 'function-documentation ,doc)
@@ -94,16 +92,11 @@ after setting it."
(let ((def ,initval))
  (process-put proc ',var-sym def)
  def
- (gv-define-setter ,var-sym (to-store &optional process)
-   (let* ((prop ',var-sym))
- ,(let ((form '(let ((proc (or ,process 
(eglot--current-process-or-lose
- (process-put proc ',prop ,to-store
-(if mode-line-update-p
-`(backquote (prog1 ,form (force-mode-line-update t)))
-  `(backquote ,form)))
+ (gv-define-setter ,var-sym (to-store process)
+   `(let ((once ,to-store)) (process-put ,process ',',var-sym once) 
once
 
 (eglot--define-process-var eglot--short-name nil
-  "A short name for the process" t)
+  "A short name for the process")
 
 (eglot--define-process-var eglot--major-mode nil
   "The major-mode this server is managing.")
@@ -128,11 +121,11 @@ after setting it."
 
 (eglot--define-process-var eglot--spinner `(nil nil t)
   "\"Spinner\" used by some servers.
-A list (ID WHAT DONE-P)." t)
+A list (ID WHAT DONE-P).")
 
 (eglot--define-process-var eglot--status `(:unknown nil)
   "Status as declared by the server.
-A list (WHAT SERIOUS-P)." t)
+A list (WHAT SERIOUS-P).")
 
 (eglot--define-process-var eglot--contact nil
   "Method used to contact a server.
@@ -531,7 +524,8 @@ is a symbol saying if this is a client or server 
originated."
(apply (cl-first continuations) res)
  (funcall (cl-first continuations) res)
   (id
-   (eglot--warn "Ooops no continuation for id %s" id)
+   (eglot--warn "Ooops no continuation for id %s" id)))
+(force-mode-line-update t)))
 
 (defvar eglot--expect-carriage-return nil)
 



[elpa] externals/eglot 29f6b4c 129/139: Tweak README.md

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 29f6b4c8cd783a47a2b9c741a518df99aa959360
Author: João Távora 
Commit: João Távora 

Tweak README.md

* README.md (Commands and keybindings): New section.
---
 README.md | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index a3789a4..4dfe0a6 100644
--- a/README.md
+++ b/README.md
@@ -37,20 +37,22 @@ server. To skip the guess and always be prompted use `C-u 
M-x eglot`.
 
 Here's a summary of available commands:
 
-- `M-x eglot-reconnect` reconnects to the server
+- `M-x eglot`, as described above;
+
+- `M-x eglot-reconnect` reconnects to the server;
 
 - `M-x eglot-rename` asks the server to rename the symbol at point
 
 - `M-x eglot-help-at-point` asks the server for help for symbol at
   point. Currently this is what `eldoc-mode` displays in the echo
-  area.
+  area;
 
 - `M-x eglot-events-buffer` jumps to the events buffer for debugging
   communication with the server.
 
 There are *no keybindings* specific to Eglot, but you can bind stuff
 in `eglot-mode-map`, which is active as long as Eglot is managing a
-file in your project. The commands don't need to be eglot-specific,
+file in your project. The commands don't need to be Eglot-specific,
 either:
 
 ```



[elpa] externals/eglot 3e0f1c3 122/139: Misc little adjustments for readability

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 3e0f1c353924e36c6b90b16c1a03bf716a7521d6
Author: João Távora 
Commit: João Távora 

Misc little adjustments for readability

* eglot.el (eglot--log-event, eglot--process-receive)
(eglot--xref-make, xref-backend-apropos): Use cl-destructuring-bind.
(eglot--server-window/showMessageRequest): Compact.
---
 eglot.el | 122 ++-
 1 file changed, 58 insertions(+), 64 deletions(-)

diff --git a/eglot.el b/eglot.el
index 3557303..4c5d53e 100644
--- a/eglot.el
+++ b/eglot.el
@@ -467,62 +467,58 @@ INTERACTIVE is t if called interactively."
 PROC is the current process.  MESSAGE is a JSON-like plist.  TYPE
 is a symbol saying if this is a client or server originated."
   (with-current-buffer (eglot-events-buffer proc)
-(let* ((inhibit-read-only t)
-   (id (plist-get message :id))
-   (error (plist-get message :error))
-   (method (plist-get message :method))
-   (subtype (cond ((and method id)   'request)
-  (method'notification)
-  (id'reply)
-  (t 'message)))
-   (type
-(format "%s-%s" (or type :internal) subtype)))
-  (goto-char (point-max))
-  (let ((msg (format "%s%s%s:\n%s\n"
- type
- (if id (format " (id:%s)" id) "")
- (if error " ERROR" "")
- (pp-to-string message
-(when error
-  (setq msg (propertize msg 'face 'error)))
-(insert-before-markers msg)
+(cl-destructuring-bind (&key method id error &allow-other-keys) message
+  (let* ((inhibit-read-only t)
+ (subtype (cond ((and method id)   'request)
+(method'notification)
+(id'reply)
+(t 'message)))
+ (type
+  (format "%s-%s" (or type :internal) subtype)))
+(goto-char (point-max))
+(let ((msg (format "%s%s%s:\n%s\n"
+   type
+   (if id (format " (id:%s)" id) "")
+   (if error " ERROR" "")
+   (pp-to-string message
+  (when error
+(setq msg (propertize msg 'face 'error)))
+  (insert-before-markers msg))
 
 (defun eglot--process-receive (proc message)
   "Process MESSAGE from PROC."
-  (let* ((id (plist-get message :id))
- (method (plist-get message :method))
- (err (plist-get message :error))
- (continuations (and id
- (not method)
- (gethash id (eglot--pending-continuations 
proc)
-(eglot--log-event proc message 'server)
-(when err (setf (eglot--status proc) `(,err t)))
-(cond (method
-   ;; a server notification or a server request
-   (let* ((handler-sym (intern (concat "eglot--server-" method
- (if (functionp handler-sym)
- (apply handler-sym proc (append
-  (plist-get message :params)
-  (if id `(:id ,id
-   (eglot--warn "No implementation of method %s yet" method)
-   (when id
- (eglot--reply
-  proc id
-  :error (eglot--obj :code -32601
- :message "Method unimplemented"))
-  (continuations
-   (cancel-timer (cl-third continuations))
-   (remhash id (eglot--pending-continuations proc))
-   (if err
-   (apply (cl-second continuations) err)
- (let ((res (plist-get message :result)))
-   (if (listp res)
-   (apply (cl-first continuations) res)
- (funcall (cl-first continuations) res)
-  (id
-   (eglot--warn "Ooops no continuation for id %s" id)))
-(eglot--call-deferred proc)
-(force-mode-line-update t)))
+  (cl-destructuring-bind (&key method id error &allow-other-keys) message
+(let* ((continuations (and id
+   (not method)
+   (gethash id (eglot--pending-continuations 
proc)
+  (eglot--log-event proc message 'server)
+  (when error (setf (eglot--status proc) `(,error t)))
+  (cond (method
+ ;; a server notification or a server request
+ (let* ((handler-sym (intern (concat "eglot--server-" method
+   (if (functionp handler-sym)
+   (apply handler-sym proc (append
+(plist-get message :params)
+(if id `(:id ,id
+   

[elpa] externals/eglot bfd82b5 108/139: Fancier RLS spinner

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit bfd82b55d4ab7bb846f9f728e0b5693c487eb307
Author: João Távora 
Commit: João Távora 

Fancier RLS spinner

* eglot.el (eglot--mode-line-format): Use (nth 3) of
eglot--spinner.
(eglot--server-window/progress): Save detail message in spinner.
---
 eglot.el | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/eglot.el b/eglot.el
index 9a0b824..4739cea 100644
--- a/eglot.el
+++ b/eglot.el
@@ -869,7 +869,7 @@ Uses THING, FACE, DEFS and PREPEND."
(name (and (process-live-p proc) (eglot--short-name proc)))
(pending (and proc (hash-table-count
(eglot--pending-continuations proc
-   (`(,_id ,doing ,done-p) (and proc (eglot--spinner proc)))
+   (`(,_id ,doing ,done-p ,detail) (and proc (eglot--spinner 
proc)))
(`(,status ,serious-p) (and proc (eglot--status proc
 (append
  `(,(eglot--mode-line-props "eglot" 'eglot-mode-line
@@ -888,7 +888,9 @@ Uses THING, FACE, DEFS and PREPEND."
  (format "An error occured: %s\n" status
  ,@(when (and doing (not done-p))
  `("/" ,(eglot--mode-line-props
- doing 'compilation-mode-line-run
+ (format "%s%s" doing
+ (if detail (format ":%s" detail) ""))
+ 'compilation-mode-line-run
  '((mouse-1 eglot-events-buffer "go to events buffer")
  ,@(when (cl-plusp pending)
  `("/" ,(eglot--mode-line-props
@@ -1460,7 +1462,7 @@ Proceed? "
   "Guess if the RLS running in PROC is ready for WHAT."
   (or (eq what :textDocument/completion) ; RLS normally ready for this
 ; one, even if building
-  (pcase-let ((`(,_id ,what ,done) (eglot--spinner proc)))
+  (pcase-let ((`(,_id ,what ,done ,_detail) (eglot--spinner proc)))
 (and (equal "Indexing" what) done
 
 (add-hook 'rust-mode-hook 'eglot--setup-rls-idiosyncrasies)
@@ -1470,9 +1472,9 @@ Proceed? "
   (add-hook 'eglot--ready-predicates 'eglot--rls-probably-ready-for-p t t))
 
 (cl-defun eglot--server-window/progress
-(process &key id done title &allow-other-keys)
+(process &key id done title message &allow-other-keys)
   "Handle notification window/progress"
-  (setf (eglot--spinner process) (list id title done)))
+  (setf (eglot--spinner process) (list id title done message)))
 
 (provide 'eglot)
 ;;; eglot.el ends here



[elpa] externals/eglot c7bd095 118/139: Improve eglot-eldoc-function

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit c7bd0952335bab43667974f15672b9fa3c99913e
Author: João Távora 
Commit: João Távora 

Improve eglot-eldoc-function

Use the :range key if the server provided it. Also simplify code with
a new eglot--with-lsp-range macro.

* eglot.el (eglot--format-markup): Tweak comment.
(eglot--with-lsp-range): New helper macro.
(eglot--server-textDocument/publishDiagnostics)
(eglot--apply-text-edits): Use it.
(eglot-eldoc-function): Use range if server provides it.
---
 eglot.el | 69 +++-
 1 file changed, 38 insertions(+), 31 deletions(-)

diff --git a/eglot.el b/eglot.el
index d1e4d15..b2709a6 100644
--- a/eglot.el
+++ b/eglot.el
@@ -740,7 +740,7 @@ DEFERRED is passed to `eglot--request', which see."
   "Format MARKUP according to LSP's spec."
   (cond ((stringp markup)
  (with-temp-buffer
-   (ignore-errors (funcall (intern "markdown-mode"))) ;escape 
bytecompiler
+   (ignore-errors (funcall (intern "markdown-mode"))) ;escape bytecomp
(font-lock-ensure)
(insert markup)
(string-trim (buffer-string
@@ -757,6 +757,15 @@ DEFERRED is passed to `eglot--request', which see."
   "Determine if current server is capable of FEAT."
   (plist-get (eglot--capabilities (eglot--current-process-or-lose)) feat))
 
+(cl-defmacro eglot--with-lsp-range ((start end) range &body body
+&aux (range-sym (cl-gensym)))
+  "Bind LSP RANGE to START and END. Evaluate BODY."
+  (declare (indent 2) (debug (sexp sexp &rest form)))
+  `(let* ((,range-sym ,range)
+  (,start (eglot--lsp-position-to-point (plist-get ,range-sym :start)))
+  (,end (eglot--lsp-position-to-point (plist-get ,range-sym :end
+ ,@body))
+
 
 ;;; Minor modes
 ;;;
@@ -965,17 +974,13 @@ called interactively."
  collect (cl-destructuring-bind (&key range severity _group
   _code source message)
  diag-spec
-   (cl-destructuring-bind (&key start end)
-   range
- (let* ((begin-pos (eglot--lsp-position-to-point start))
-(end-pos (eglot--lsp-position-to-point end)))
-   (flymake-make-diagnostic
-(current-buffer)
-begin-pos end-pos
-(cond ((<= severity 1) :error)
-  ((= severity 2)  :warning)
-  (t   :note))
-(concat source ": " message)
+   (eglot--with-lsp-range (beg end) range
+ (flymake-make-diagnostic (current-buffer)
+  beg end
+  (cond ((<= severity 1) :error)
+((= severity 2)  :warning)
+(t   :note))
+  (concat source ": " message
  into diags
  finally (cond (eglot--current-flymake-report-fn
 (funcall eglot--current-flymake-report-fn diags)
@@ -1302,15 +1307,23 @@ DUMMY is ignored"
 (proc (eglot--current-process-or-lose))
 (position-params (eglot--current-buffer-TextDocumentPositionParams)))
 (when (eglot--server-capable :hoverProvider)
-  (eglot--request proc :textDocument/hover position-params
-  :success-fn (eglot--lambda (&key contents _range)
-(eldoc-message
- (mapconcat #'eglot--format-markup
-(if (vectorp contents)
-contents
-  (list contents))
-"\n")))
-  :deferred :textDocument/hover))
+  (eglot--request
+   proc :textDocument/hover position-params
+   :success-fn (eglot--lambda (&key contents range)
+ (when (get-buffer-window buffer)
+   (with-current-buffer buffer
+ (eldoc-message
+  (concat
+   (and range
+(eglot--with-lsp-range (beg end) range
+  (concat (buffer-substring beg end)  ": ")))
+   (mapconcat #'eglot--format-markup
+  (append
+   (cond ((vectorp contents)
+  contents)
+ (contents
+  (list contents "\n")

[elpa] externals/eglot 24466a9 096/139: When killing server, always wait 3 seconds

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 24466a958563daf2803edc1f4b732c3e2412a06c
Author: João Távora 
Commit: João Távora 

When killing server, always wait 3 seconds

* eglot.el (eglot--request): Accept TIMEOUT param.
---
 eglot.el | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/eglot.el b/eglot.el
index 2e409ef..9ce7e26 100644
--- a/eglot.el
+++ b/eglot.el
@@ -552,10 +552,12 @@ is a symbol saying if this is a client or server 
originated."
 (cl-defun eglot--request (process
   method
   params
-  &key success-fn error-fn timeout-fn (async-p t))
+  &key success-fn error-fn timeout-fn (async-p t)
+  (timeout eglot-request-timeout))
   "Make a request to PROCESS, expecting a reply.
 Return the ID of this request, unless ASYNC-P is nil, in which
-case never returns locally."
+case never returns locally.  Wait TIMEOUT seconds for a
+response."
   (let* ((id (eglot--next-request-id))
  (timeout-fn (or timeout-fn
  (lambda ()
@@ -583,7 +585,7 @@ case never returns locally."
 (catch catch-tag
   (let ((timeout-timer
  (run-with-timer
-  eglot-request-timeout nil
+  timeout nil
   (if async-p
   (lambda ()
 (remhash id (eglot--pending-continuations process))
@@ -912,10 +914,12 @@ running.  INTERACTIVE is t if called interactively."
:success-fn brutal
:async-p (not sync)
:error-fn brutal
-   :timeout-fn brutal))
+   :timeout-fn brutal
+   :timeout 3))
  :error-fn brutal
  :async-p (not sync)
- :timeout-fn brutal)))
+ :timeout-fn brutal
+ :timeout 3)))
 
 (cl-defun eglot--server-window/showMessage (_process &key type message)
   "Handle notification window/showMessage"



[elpa] externals/eglot 23b79e0 111/139: Shorten summary line to appease package-lint.el

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 23b79e07da6c62e7f056c6cc5b6b676e43b8017c
Author: João Távora 
Commit: João Távora 

Shorten summary line to appease package-lint.el
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index fbddf16..21ec247 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1,4 +1,4 @@
-;;; eglot.el --- A client for Language Server Protocol (LSP) servers  -*- 
lexical-binding: t; -*-
+;;; eglot.el --- Client for Language Server Protocol (LSP) servers  -*- 
lexical-binding: t; -*-
 
 ;; Copyright (C) 2017  João Távora
 



[elpa] externals/eglot 6e76b08 100/139: Support workspace/applyEdit

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 6e76b085a7c21790ee9df905159a7d7b1f90
Author: João Távora 
Commit: João Távora 

Support workspace/applyEdit

* eglot.el (eglot--reply): Don't send result or error if not
provided.
(eglot--server-workspace/applyEdit): New server method.
(eglot--apply-text-edits): Rework.
(eglot--apply-workspace-edit): New helper.
(eglot-rename): Simplify.
---
 eglot.el | 135 ++-
 1 file changed, 82 insertions(+), 53 deletions(-)

diff --git a/eglot.el b/eglot.el
index 9ba87ef..37ad616 100644
--- a/eglot.el
+++ b/eglot.el
@@ -664,10 +664,10 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 
 (cl-defun eglot--reply (process id &key result error)
   "Reply to PROCESS's request ID with MESSAGE."
-  (eglot--process-send process (eglot--obj :jsonrpc  "2.0"
-   :id id
-   :result result
-   :error error)))
+  (eglot--process-send
+   process `(:jsonrpc  "2.0" :id ,id
+   ,@(when result `(:result ,result))
+   ,@(when error `(:error ,error)
 
 
 ;;; Helpers
@@ -1031,6 +1031,20 @@ running.  INTERACTIVE is t if called interactively."
registrations)
   (eglot--reply proc id :result (eglot--obj :message "OK")
 
+(cl-defun eglot--server-workspace/applyEdit
+(proc &key id _label edit)
+  "Handle notification client/registerCapability"
+  (condition-case err
+  (progn
+(eglot--apply-workspace-edit edit 'confirm)
+(eglot--reply proc id :result `(:applied )))
+(error
+ (eglot--reply proc id
+   :result `(:applied :json-false)
+   :error
+   (eglot--obj :code -32001
+   :message (format "%s" err))
+
 (defvar eglot--recent-before-changes nil
   "List of recent changes as collected by `eglot--before-change'.")
 (defvar eglot--recent-after-changes nil
@@ -1370,61 +1384,76 @@ DUMMY is ignored"
  entries))
 (funcall oldfun)))
 
-(defun eglot--apply-text-edits (uri edits proc &optional version)
-  "Apply the EDITS for buffer of URI and return it."
-  (let* ((path (eglot--uri-to-path uri))
- (buffer (and path
-  (find-file-noselect path
-(unless buffer
-  (eglot--error "Can't find `%s' to perform server edits"))
-(with-current-buffer buffer
-  (unless (eq proc (eglot--current-process))
-(eglot--error "Buffer `%s' for `%s' isn't managed by %s"
-  (current-buffer) uri proc))
-  (unless (or (not version)
-  (equal version eglot--versioned-identifier))
-(eglot--error "Edits on `%s' require version %d, you have %d"
-  uri version eglot--versioned-identifier))
-  (eglot--mapply
-   (eglot--lambda (&key range newText)
- (save-restriction
-   (widen)
-   (save-excursion
- (let ((start (eglot--lsp-position-to-point (plist-get range 
:start
-   (goto-char start)
-   (delete-region start
-  (eglot--lsp-position-to-point (plist-get range 
:end)))
-   (insert newText)
-   edits)
-  (eglot--message "%s: %s edits" (current-buffer) (length edits)))
-buffer))
+(defun eglot--apply-text-edits (buffer edits &optional version)
+  "Apply the EDITS for BUFFER."
+  (with-current-buffer buffer
+(unless (or (not version)
+(equal version eglot--versioned-identifier))
+  (eglot--error "Edits on `%s' require version %d, you have %d"
+buffer version eglot--versioned-identifier))
+(eglot--mapply
+ (eglot--lambda (&key range newText)
+   (save-restriction
+ (widen)
+ (save-excursion
+   (let ((start (eglot--lsp-position-to-point (plist-get range 
:start
+ (goto-char start)
+ (delete-region start
+(eglot--lsp-position-to-point (plist-get range 
:end)))
+ (insert newText)
+ edits)
+(eglot--message "%s: Performed %s edits" (current-buffer) (length edits
+
+(defun eglot--apply-workspace-edit (wedit &optional confirm)
+  "Apply the workspace edit WEDIT.  If CONFIRM, ask user first."
+  (let (prepared)
+(cl-destructuring-bind (&key changes documentChanges)
+wedit
+  (cl-loop
+   for change on documentChanges
+   do (push (cl-destructuring-bind (&key textDocument edits) change
+  (cl-destructuring-bind (&key uri version) textDocument
+(list (eglot--uri-to-path uri) edits version)))
+prepared))
+  (cl-loop for (uri edits) on changes by #'cddr
+   do (push (list (eglot--uri-to-path uri) edits) prepared)))
+(if (or confirm
+ 

[elpa] externals/eglot 29f58a6 127/139: Get rid of catch/loop/throw idiom (suggested by Thien-Thi Nguyen)

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 29f58a6514aec28e4e6df9611e4f58c7289e3cc6
Author: João Távora 
Commit: João Távora 

Get rid of catch/loop/throw idiom (suggested by Thien-Thi Nguyen)

* eglot.el (eglot--process-filter)
(eglot--request): Replace catch/loop/throw idiom with let/test/loop/set
---
 eglot.el | 44 +++-
 1 file changed, 19 insertions(+), 25 deletions(-)

diff --git a/eglot.el b/eglot.el
index aabaf54..c8612cf 100644
--- a/eglot.el
+++ b/eglot.el
@@ -400,8 +400,7 @@ INTERACTIVE is t if called interactively."
   (when (buffer-live-p (process-buffer proc))
 (with-current-buffer (process-buffer proc)
   (let ((inhibit-read-only t)
-(expected-bytes (eglot--expected-bytes proc))
-(done (make-symbol "eglot--process-filter-done-tag")))
+(expected-bytes (eglot--expected-bytes proc)))
 ;; Insert the text, advancing the process marker.
 ;;
 (save-excursion
@@ -411,8 +410,8 @@ INTERACTIVE is t if called interactively."
 ;; Loop (more than one message might have arrived)
 ;;
 (unwind-protect
-(catch done
-  (while t
+(let (done)
+  (while (not done)
 (cond
  ((not expected-bytes)
   ;; Starting a new message
@@ -425,7 +424,7 @@ INTERACTIVE is t if called interactively."
   t)
  (string-to-number (match-string 1
   (unless expected-bytes
-(throw done :waiting-for-new-message)))
+(setq done :waiting-for-new-message)))
  (t
   ;; Attempt to complete a message body
   ;;
@@ -453,7 +452,7 @@ INTERACTIVE is t if called interactively."
  (t
   ;; Message is still incomplete
   ;;
-  (throw done 
:waiting-for-more-bytes-in-this-message
+  (setq done 
:waiting-for-more-bytes-in-this-message
   ;; Saved parsing state for next visit to this filter
   ;;
   (setf (eglot--expected-bytes proc) expected-bytes))
@@ -652,25 +651,20 @@ DEFERRED is passed to `eglot--async-request', which see."
   ;; bad idea, since that might lead to the request never having a
   ;; chance to run, because `eglot--ready-predicates'.
   (when deferred (eglot--signal-textDocument/didChange))
-  (let* ((done (make-symbol "eglot--request-catch-tag"))
- (res
-  (catch done (eglot--async-request
-   proc method params
-   :success-fn (lambda (&rest args)
- (throw done (if (vectorp (car args))
- (car args) args)))
-   :error-fn (eglot--lambda
- (&key code message &allow-other-keys)
-   (throw done
-  `(error ,(format "Oops: %s: %s"
-   code message
-   :timeout-fn (lambda ()
- (throw done '(error "Timed out")))
-   :deferred deferred)
- ;; now spin, baby!
- (while t (accept-process-output nil 0.01)
-(when (and (listp res) (eq 'error (car res))) (eglot--error (cadr res)))
-res))
+  (let ((retval))
+(eglot--async-request
+ proc method params
+ :success-fn (lambda (&rest args)
+   (setq retval `(done ,(if (vectorp (car args))
+(car args) args
+ :error-fn (eglot--lambda (&key code message &allow-other-keys)
+ (setq retval `(error ,(format "Oops: %s: %s" code message
+ :timeout-fn (lambda ()
+   (setq retval '(error "Timed out")))
+ :deferred deferred)
+(while (not retval) (accept-process-output nil 30))
+(when (eq 'error (car retval)) (eglot--error (cadr retval)))
+(cadr retval)))
 
 (cl-defun eglot--notify (process method params)
   "Notify PROCESS of something, don't expect a reply.e"



[elpa] externals/eglot 8e6488f 023/139: Don't switch to possibly dead buffer in sentinel

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 8e6488f2dbdb55708fb2743aa9e86d583b8f9148
Author: João Távora 
Commit: João Távora 

Don't switch to possibly dead buffer in sentinel

* eglot.el (eglot--process-sentinel): Don't with-current-buffer.
---
 eglot.el | 44 ++--
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/eglot.el b/eglot.el
index 44023b7..22ff031 100644
--- a/eglot.el
+++ b/eglot.el
@@ -153,24 +153,23 @@ INTERACTIVE is t if called interactively."
 (eglot--protocol-initialize proc interactive)))
 
 (defun eglot--process-sentinel (process change)
-  (with-current-buffer (process-buffer process)
-(eglot--debug "(sentinel) Process state changed to %s" change)
-(when (not (process-live-p process))
-  ;; Remember to cancel all timers
-  ;;
-  (maphash (lambda (id quad)
- (cl-destructuring-bind (_success _error timeout _env) quad
-   (eglot--message
-"(sentinel) Cancelling timer for continuation %s" id)
-   (cancel-timer timeout)))
-   (eglot--pending-continuations process))
-  (cond ((eglot--moribund process)
- (eglot--message "(sentinel) Moribund process exited with status 
%s"
- (process-exit-status process)))
-(t
- (eglot--warn "(sentinel) Process unexpectedly changed to %s"
-  change)))
-  (delete-process process
+  (eglot--debug "(sentinel) Process state changed to %s" change)
+  (when (not (process-live-p process))
+;; Remember to cancel all timers
+;;
+(maphash (lambda (id quad)
+   (cl-destructuring-bind (_success _error timeout _env) quad
+ (eglot--message
+  "(sentinel) Cancelling timer for continuation %s" id)
+ (cancel-timer timeout)))
+ (eglot--pending-continuations process))
+(cond ((eglot--moribund process)
+   (eglot--message "(sentinel) Moribund process exited with status %s"
+   (process-exit-status process)))
+  (t
+   (eglot--warn "(sentinel) Process unexpectedly changed to %s"
+change)))
+(delete-process process)))
 
 (defun eglot--process-filter (proc string)
   "Called when new data STRING has arrived for PROC."
@@ -371,7 +370,8 @@ identifier.  ERROR is non-nil if this is an error."
  (error-fn
   (or error-fn
   (cl-function
-   (lambda (&key code message)
+   (lambda (&key data code message &allow-other-keys)
+ (setf (eglot--status process) '("error" t))
  (eglot--warn
   "(request) Request id=%s errored with code=%s: %s"
   id code message)
@@ -446,9 +446,9 @@ INTERACTIVE is t if caller was called interactively."
process
:initialize
`(:processId  ,(emacs-pid)
- :rootPath  ,(concat "file://"
- (expand-file-name (car (project-roots
- 
(project-current)
+ :rootPath  ,(concat 
+  (expand-file-name (car (project-roots
+  (project-current)
  :initializationOptions  []
  :capabilities (:workspace (:executeCommand 
(:dynamicRegistration t))
:textDocument (:synchronization 
(:didSave t



[elpa] externals/eglot 9577dfc 125/139: Duh, json.el is in Emacs, and json-mode.el is useless here

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 9577dfc251ed6be8c355b406bc1a196e9d059a07
Author: João Távora 
Commit: João Távora 

Duh, json.el is in Emacs, and json-mode.el is useless here

* eglot.el (Package-Requires): Don't require json-mode
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index e33e540..3b3aada 100644
--- a/eglot.el
+++ b/eglot.el
@@ -7,7 +7,7 @@
 ;; Maintainer: João Távora 
 ;; URL: https://github.com/joaotavora/eglot
 ;; Keywords: convenience, languages
-;; Package-Requires: ((emacs "26.1") (json-mode "1.6.0"))
+;; Package-Requires: ((emacs "26.1"))
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by



[elpa] externals/eglot f8bfb7e 064/139: Handle requests from server correctly

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit f8bfb7e26aed285167d9a41ed986894b2646ebae
Author: João Távora 
Commit: João Távora 

Handle requests from server correctly

* eglot.el (eglot--process-receive): Redesign.
(eglot--process-send): Take REPLY arg. Discover if message is error.
(eglot--reply): new function
(eglot--log-event): Tweak docstring.
(eglot--process-receive): Reply with -32601 if unimplemented.
(eglot--server-window/showMessageRequest)
(eglot--server-client/registerCapability): Use eglot--reply
---
 eglot.el | 95 ++--
 1 file changed, 50 insertions(+), 45 deletions(-)

diff --git a/eglot.el b/eglot.el
index df03d04..332f1fe 100644
--- a/eglot.el
+++ b/eglot.el
@@ -460,7 +460,7 @@ INTERACTIVE is t if called interactively."
   "Log an eglot-related event.
 PROC is the current process.  TYPE is an identifier.  MESSAGE is
 a JSON-like plist or anything else.  ID is a continuation
-identifier.  ERROR is non-nil if this is an error."
+identifier.  ERROR is non-nil if this is a JSON-RPC error."
   (with-current-buffer (eglot-events-buffer proc)
 (let ((inhibit-read-only t))
   (goto-char (point-max))
@@ -475,53 +475,49 @@ identifier.  ERROR is non-nil if this is an error."
 
 (defun eglot--process-receive (proc message)
   "Process MESSAGE from PROC."
-  (let* ((response-id (plist-get message :id))
+  (let* ((id (plist-get message :id))
+ (method (plist-get message :method))
  (err (plist-get message :error))
- (continuations (and response-id
- (gethash response-id
-  (eglot--pending-continuations proc)
+ (continuations (and id
+ (not method)
+ (gethash id (eglot--pending-continuations 
proc)
 (eglot--log-event proc
-  (cond ((not response-id)
- 'server-notification)
-((not continuations)
- 'unexpected-server-reply)
-(t
- 'server-reply))
+  (cond ((and method id)   'server-request)
+(method'server-notification)
+(continuations 'server-reply)
+;; pyls keeps on sending these
+(t 'unexpected-server-thingy))
   message
-  response-id
+  id
   err)
-(when err
-  (setf (eglot--status proc) '("error" t)))
-(cond ((and response-id
-(not continuations))
-   (eglot--warn "Ooops no continuation for id %s" response-id))
-  (continuations
-   (cancel-timer (cl-third continuations))
-   (remhash response-id
-(eglot--pending-continuations proc))
-   (cond (err
-  (apply (cl-second continuations) err))
- (t
-  (apply (cl-first continuations) (plist-get message 
:result)
-  (t
+(when err (setf (eglot--status proc) '("error" t)))
+(cond (method
;; a server notification or a server request
-   (let* ((method (plist-get message :method))
-  (handler-sym (intern (concat "eglot--server-"
+   (let* ((handler-sym (intern (concat "eglot--server-"
method
  (if (functionp handler-sym)
  (apply handler-sym proc (append
   (plist-get message :params)
-  (let ((id (plist-get message :id)))
-(if id `(:id ,id)
-   ;; pyls keeps on sending nil notifs for each notif we
-   ;; send it, just ignore these.
-   (unless (null method)
- (eglot--warn "No implemetation for notification %s yet"
-  method
+  (if id `(:id ,id
+   (eglot--warn "No implementation of method %s yet"
+method)
+   (when id
+ (eglot--reply
+  proc id
+  :error (eglot--obj :code -32601
+ :message "Method unimplemented"))
+  (continuations
+   (cancel-timer (cl-third continuations))
+   (remhash id (eglot--pending-continuations proc))
+   (if err
+   (apply (cl-second continuations) err)
+ (apply (cl-first continuations) (plist-get message :result
+  (id
+   (eglot--warn "Ooops no continuation for id %s" id)
 
 (defvar eglot--expect-carriage-return nil)
 
-(d

[elpa] externals/eglot 9ff97a6 079/139: Increase request timeout length to 10 seconds

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 9ff97a648244d4d08d6670b2204692ae49753f1b
Author: João Távora 
Commit: João Távora 

Increase request timeout length to 10 seconds

* eglot.el (eglot-request-timeout): New var.
(eglot--request): Use it.
---
 eglot.el | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/eglot.el b/eglot.el
index 1d72b4c..cd48519 100644
--- a/eglot.el
+++ b/eglot.el
@@ -48,8 +48,11 @@
 
 (defface eglot-mode-line
   '((t (:inherit font-lock-constant-face :weight bold)))
-  "Face for package-name in EGLOT's mode line."
-  :group 'eglot)
+  "Face for package-name in EGLOT's mode line.")
+
+(defcustom eglot-request-timeout 10
+  "How many seconds to way for a reply from the server."
+  :type :integer)
 
 
 ;;; Process management
@@ -617,7 +620,7 @@ is a symbol saying if this is a client or server 
originated."
 (catch catch-tag
   (let ((timeout-timer
  (run-with-timer
-  5 nil
+  eglot-request-timeout nil
   (if async-p
   (lambda ()
 (remhash id (eglot--pending-continuations process))



[elpa] externals/eglot 77856c2 130/139: Reinstate the catch/loop/throw idiom in eglot-request

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 77856c2f9194b6975421be411d80cfcf102fd10d
Author: João Távora 
Commit: João Távora 

Reinstate the catch/loop/throw idiom in eglot-request

This reverts parts of commit 29f58a6514aec28e4e6df9611e4f58c7289e3cc6.

Unfortunately, this may cause problems when calling the error
callbacks directly as in the process sentinel. In that particular
scenario the accept-process-output won't have return, because no
output has is being handled. Consequently, if we're unlucky, we have
another 30 seconds to way before the flag is tested and the loop
exits.

* eglot.el (eglot-request): Use catch/loop/throw again
---
 eglot.el | 33 +++--
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/eglot.el b/eglot.el
index 13f6f61..6f90349 100644
--- a/eglot.el
+++ b/eglot.el
@@ -651,20 +651,25 @@ DEFERRED is passed to `eglot--async-request', which see."
   ;; bad idea, since that might lead to the request never having a
   ;; chance to run, because `eglot--ready-predicates'.
   (when deferred (eglot--signal-textDocument/didChange))
-  (let ((retval))
-(eglot--async-request
- proc method params
- :success-fn (lambda (&rest args)
-   (setq retval `(done ,(if (vectorp (car args))
-(car args) args
- :error-fn (eglot--lambda (&key code message &allow-other-keys)
- (setq retval `(error ,(format "Oops: %s: %s" code message
- :timeout-fn (lambda ()
-   (setq retval '(error "Timed out")))
- :deferred deferred)
-(while (not retval) (accept-process-output nil 30))
-(when (eq 'error (car retval)) (eglot--error (cadr retval)))
-(cadr retval)))
+  (let* ((done (make-symbol "eglot--request-catch-tag"))
+ (res
+  (catch done (eglot--async-request
+   proc method params
+   :success-fn (lambda (&rest args)
+ (throw done (if (vectorp (car args))
+ (car args) args)))
+   :error-fn (eglot--lambda
+ (&key code message &allow-other-keys)
+   (throw done
+  `(error ,(format "Oops: %s: %s"
+   code message
+   :timeout-fn (lambda ()
+ (throw done '(error "Timed out")))
+   :deferred deferred)
+ ;; now spin, baby!
+ (while t (accept-process-output nil 0.01)
+(when (and (listp res) (eq 'error (car res))) (eglot--error (cadr res)))
+res))
 
 (cl-defun eglot--notify (process method params)
   "Notify PROCESS of something, don't expect a reply.e"



[elpa] externals/eglot f1b6485 053/139: Trim some edges and add a bunch of boring RPC methods

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit f1b648592e01229b18fc8dfae6e69b1149620326
Author: João Távora 
Commit: João Távora 

Trim some edges and add a bunch of boring RPC methods

* eglot.el (eglot--connect): Don't call eglot--protocol-initialize.
(eglot--process-filter): Break long line.
(eglot--process-receive): Also pass id to handler if a server request.
(eglot--log): New helper.
(eglot-editing-mode): Manage before-revert-hook,
after-revert-hook, before-save-hook, after-save-hook.
(eglot--protocol-initialize): Removed.
(eglot--server-window/showMessage): Simplify.
(eglot--server-window/showMessageRequest)
(eglot--server-window/logMessage, eglot--server-telemetry/event):
New handlers.
(eglot--signal-textDocument/willSave)
(eglot--signal-textDocument/didSave): New notifications.
(eglot--signal-textDocument/didOpen)
(eglot--signal-textDocument/didClose): Check
eglot--buffer-open-count.
(eglot--buffer-open-count): New var.
---
 eglot.el | 135 +++
 1 file changed, 102 insertions(+), 33 deletions(-)

diff --git a/eglot.el b/eglot.el
index e7fe18c..ebc07d2 100644
--- a/eglot.el
+++ b/eglot.el
@@ -198,13 +198,26 @@ SUCCESS-FN with no args if all goes well."
   (let ((inhibit-read-only t))
 (insert
  (format "\n---\n"
-(eglot--protocol-initialize
+(eglot--request
  proc
+ :initialize
+ (eglot--obj :processId  (emacs-pid)
+ :rootPath  (concat
+ (expand-file-name (car (project-roots
+ (project-current)
+ :initializationOptions  []
+ :capabilities
+ (eglot--obj
+  :workspace (eglot--obj)
+  :textDocument (eglot--obj
+ :publishDiagnostics `(:relatedInformation 
t
+ :success-fn
  (cl-function
   (lambda (&key capabilities)
 (setf (eglot--capabilities proc) capabilities)
 (setf (eglot--status proc) nil)
-(when success-fn (funcall success-fn proc)
+(when success-fn (funcall success-fn proc))
+(eglot--notify proc :initialized nil
 
 (defvar eglot--command-history nil
   "History of COMMAND arguments to `eglot'.")
@@ -347,7 +360,8 @@ INTERACTIVE is t if called interactively."
;;
(setq expected-bytes
  (and (search-forward-regexp
-   "\\(?:.*: .*\r\n\\)*Content-Length: 
*\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
+   "\\(?:.*: .*\r\n\\)*Content-Length: \
+*\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
(+ (point) 100)
t)
   (string-to-number (match-string 1
@@ -454,11 +468,15 @@ identifier.  ERROR is non-nil if this is an error."
  (t
   (apply (cl-first continuations) (plist-get message 
:result)
   (t
+   ;; a server notification or a server request
(let* ((method (plist-get message :method))
   (handler-sym (intern (concat "eglot--server-"
method
  (if (functionp handler-sym)
- (apply handler-sym proc (plist-get message :params))
+ (apply handler-sym proc (append
+  (plist-get message :params)
+  (let ((id (plist-get message :id)))
+(if id `(:id ,id)
(eglot--warn "No implemetation for notification %s yet"
 method)))
 
@@ -587,6 +605,10 @@ identifier.  ERROR is non-nil if this is an error."
   "Message out with FORMAT with ARGS."
   (message (concat "[eglot] " (apply #'format format args
 
+(defun eglot--log (format &rest args)
+  "Log out with FORMAT with ARGS."
+  (message (concat "[eglot-log] " (apply #'format format args
+
 (defun eglot--warn (format &rest args)
   "Warning message with FORMAT and ARGS."
   (apply #'eglot--message (concat "(warning) " format) args)
@@ -614,15 +636,22 @@ identifier.  ERROR is non-nil if this is an error."
 (add-hook 'before-change-functions 'eglot--before-change nil t)
 (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
 (add-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose nil t)
+(add-hook 'before-revert-hook 'eglot--signal-textDocument/didClose nil t)
+(add-hook 'after-revert-hook 'eglot--signal-textDocument/didOpen nil t)
+(add-hook 'before-save-hook 'eglot--signal-textDocument/

[elpa] externals/eglot 22dc2f7 034/139: Ready to start fixing flymake integration

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 22dc2f7ba341b66bc904afa0ffa75b7da86a413e
Author: João Távora 
Commit: João Távora 

Ready to start fixing flymake integration

* eglot.el (eglot-editing-mode): Turn on flymake-mode.
(eglot-flymake-backend): Always start by reporting no diagnostics.
(eglot--textDocument/publishDiagnostics): No annoying message.
---
 eglot.el | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index d3428a7..aa23252 100644
--- a/eglot.el
+++ b/eglot.el
@@ -573,7 +573,6 @@ running.  INTERACTIVE is t if called interactively."
   (eglot--warn "outdated publishDiagnostics report from server"))
  (buffer
   (with-current-buffer buffer
-(eglot--message "OK so add some %s diags" (length diagnostics))
 (cl-flet ((pos-at
(pos-plist)
(car (flymake-diag-region
@@ -662,6 +661,7 @@ running.  INTERACTIVE is t if called interactively."
 (eglot-mode 1)
 (add-hook 'after-change-functions 'eglot--after-change nil t)
 (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
+(flymake-mode 1)
 (if (eglot--current-process)
 (eglot--signalDidOpen)
   (if (y-or-n-p "No process, try to start one with `eglot-new-process'? ")
@@ -857,7 +857,10 @@ running.  INTERACTIVE is t if called interactively."
 (defun eglot-flymake-backend (report-fn &rest _more)
   "An EGLOT Flymake backend.
 Calls REPORT-FN maybe if server publishes diagnostics in time."
-  ;; FIXME: perhaps should call it immediately?
+  ;; call immediately with no diagnostics, this just means we don't
+  ;; have them yet (and also clears any pending ones).
+  ;;
+  (funcall report-fn nil)
   (setq eglot--current-flymake-report-fn report-fn)
   (eglot--maybe-signal-didChange))
 



[elpa] externals/eglot 9665a3e 051/139: Fix textDocument/didChange

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 9665a3eec28fcf1bc52542cbe5e99d16f4fbc03a
Author: João Távora 
Commit: João Távora 

Fix textDocument/didChange

* eglot.el (eglot-editing-mode): Manage before-change-functions.
(eglot--recent-changes): Deleted.
(eglot--recent-before-changes): New var.
(eglot--recent-after-changes): Renamed from eglot--recent-changes.
(eglot--pos-to-lsp-position, eglot--before-change): New helpers.
(eglot--after-change): Rework.
(eglot--signal-textDocument/didChange): Rework.
---
 eglot.el | 98 +++-
 1 file changed, 66 insertions(+), 32 deletions(-)

diff --git a/eglot.el b/eglot.el
index 469d3f7..1bf0d56 100644
--- a/eglot.el
+++ b/eglot.el
@@ -611,6 +611,7 @@ identifier.  ERROR is non-nil if this is an error."
(eglot-editing-mode
 (eglot-mode 1)
 (add-hook 'after-change-functions 'eglot--after-change nil t)
+(add-hook 'before-change-functions 'eglot--before-change nil t)
 (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
 (add-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose nil t)
 (flymake-mode 1)
@@ -620,6 +621,7 @@ identifier.  ERROR is non-nil if this is an error."
(t
 (remove-hook 'flymake-diagnostic-functions 'eglot-flymake-backend t)
 (remove-hook 'after-change-functions 'eglot--after-change t)
+(remove-hook 'before-change-functions 'eglot--before-change t)
 (remove-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose t
 
 (define-minor-mode eglot-mode
@@ -868,7 +870,9 @@ running.  INTERACTIVE is t if called interactively."
  (t
   (eglot--message "OK so %s isn't visited" filename)
 
-(defvar eglot--recent-changes nil
+(defvar eglot--recent-before-changes nil
+  "List of recent changes as collected by `eglot--before-change'.")
+(defvar eglot--recent-after-changes nil
   "List of recent changes as collected by `eglot--after-change'.")
 
 (defvar-local eglot--versioned-identifier 0)
@@ -895,46 +899,76 @@ running.  INTERACTIVE is t if called interactively."
  (widen)
  (buffer-substring-no-properties (point-min) (point-max))
 
-(defun eglot--after-change (start end length)
+(defun eglot--pos-to-lsp-position (pos)
+  "Convert point POS to LSP position."
+  (save-excursion
+(eglot--obj :line
+;; F!@(#*&#$)CKING OFF-BY-ONE
+(1- (line-number-at-pos pos t))
+:character
+(- (goto-char pos)
+   (line-beginning-position)
+
+(defun eglot--before-change (start end)
+  "Hook onto `before-change-functions'.
+Records START and END, crucially convert them into
+LSP (line/char) positions before that information is
+lost (because the after-change thingy doesn't know if newlines
+were deleted/added)"
+  (push (list (eglot--pos-to-lsp-position start)
+  (eglot--pos-to-lsp-position end))
+eglot--recent-before-changes))
+
+(defun eglot--after-change (start end pre-change-length)
   "Hook onto `after-change-functions'.
-Records START, END and LENGTH locally."
+Records START, END and PRE-CHANGE-LENGTH locally."
   (cl-incf eglot--versioned-identifier)
-  (push (list start end length) eglot--recent-changes)
-  ;; (eglot--message "start is %s, end is %s, length is %s" start end length)
-  )
+  (push (list start end pre-change-length) eglot--recent-after-changes))
 
 (defun eglot--signal-textDocument/didChange ()
   "Send textDocument/didChange to server."
-  (when eglot--recent-changes
+  (when (and eglot--recent-before-changes
+ eglot--recent-after-changes)
 (save-excursion
   (save-restriction
 (widen)
-(let* ((start (cl-reduce #'min (mapcar #'car eglot--recent-changes)))
-   (end (cl-reduce #'max (mapcar #'cadr eglot--recent-changes
-  (eglot--notify
-   (eglot--current-process-or-lose)
-   :textDocument/didChange
-   (eglot--obj
-:textDocument 
(eglot--current-buffer-VersionedTextDocumentIdentifier)
-:contentChanges
-(vector
+(if (/= (length eglot--recent-before-changes)
+(length eglot--recent-after-changes))
+(eglot--notify
+ (eglot--current-process-or-lose)
+ :textDocument/didChange
  (eglot--obj
-  :range (eglot--obj
-  :start
-  (eglot--obj :line
-  (line-number-at-pos start t)
-  :character
-  (- (goto-char start)
- (line-beginning-position)))
-  :end
-  (eglot--obj :line
-  (line-number-at-pos end t)
-  :character
-  (- (goto-char end)
-  

[elpa] externals/eglot 6689a15 026/139: Add eglot-clear-status interactive command

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 6689a1588366a5d461207b11130b167e14a1dcf4
Author: João Távora 
Commit: João Távora 

Add eglot-clear-status interactive command

* eglot.el (eglot-clear-status): New
(eglot-forget-pending-continuations): Fix bug.
(eglot--mode-line-format): Add link to eglot-clear-status.
---
 eglot.el | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index 1a82cc5..db594f4 100644
--- a/eglot.el
+++ b/eglot.el
@@ -361,9 +361,14 @@ identifier.  ERROR is non-nil if this is an error."
 
 (defun eglot-forget-pending-continuations (process)
   "Stop waiting for responses from the current LSP PROCESS."
-  (interactive (eglot--current-process-or-lose))
+  (interactive (list (eglot--current-process-or-lose)))
   (clrhash (eglot--pending-continuations process)))
 
+(defun eglot-clear-status (process)
+  "Clear most recent error message from PROCESS."
+  (interactive (list (eglot--current-process-or-lose)))
+  (setf (eglot--status process) nil))
+
 (cl-defun eglot--request (process
   method
   params
@@ -668,12 +673,15 @@ running.  INTERACTIVE is t if called interactively."
  `("/"
(:propertize
 ,status
-help-echo ,(concat "mouse-1: go to events buffer")
+help-echo ,(concat "mouse-1: go to events buffer\n"
+   "mouse-3: clear this status")
 mouse-face mode-line-highlight
 face compilation-mode-line-fail
 keymap ,(let ((map (make-sparse-keymap)))
   (define-key map [mode-line mouse-1]
 'eglot-events-buffer)
+  (define-key map [mode-line mouse-3]
+'eglot-clear-status)
   map
  ,@(when (and doing (not done-p))
  `("/"



[elpa] externals/eglot 17e0ca4 047/139: Fix Flymake diagnostic positions

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 17e0ca499e34638d5a52b4daf6b01e06fed3610c
Author: João Távora 
Commit: João Távora 

Fix Flymake diagnostic positions

It's better not to use flymake-diag-region here.

* eglot.el (eglot--textDocument/publishDiagnostics):
Calculate position by hand.
---
 eglot.el | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/eglot.el b/eglot.el
index 86c0a4c..bb0427a 100644
--- a/eglot.el
+++ b/eglot.el
@@ -637,10 +637,13 @@ running.  INTERACTIVE is t if called interactively."
   (with-current-buffer buffer
 (cl-flet ((pos-at
(pos-plist)
-   (car (flymake-diag-region
- (current-buffer)
- (plist-get pos-plist :line)
- (plist-get pos-plist :character)
+   (save-excursion
+ (goto-char (point-min))
+ (forward-line (plist-get pos-plist :line))
+ (forward-char
+  (min (plist-get pos-plist :character)
+   (- (line-end-position)
+  (line-beginning-position)))
   (cl-loop for diag-spec across diagnostics
collect (cl-destructuring-bind (&key range severity
 _code _source message)



[elpa] externals/eglot b69302c 060/139: Make M-x eglot's interactive spec a separate function

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit b69302c4795be8d783f853488824626a08241778
Author: João Távora 
Commit: João Távora 

Make M-x eglot's interactive spec a separate function

* eglot.el (eglot--interactive): New function.
(eglot): Rework a little.
---
 eglot.el | 104 ---
 1 file changed, 53 insertions(+), 51 deletions(-)

diff --git a/eglot.el b/eglot.el
index 3d0c044..ec7f3e6 100644
--- a/eglot.el
+++ b/eglot.el
@@ -234,6 +234,39 @@ SUCCESS-FN with no args if all goes well."
 (defvar eglot--command-history nil
   "History of COMMAND arguments to `eglot'.")
 
+(defun eglot--interactive ()
+  "Helper for `eglot'."
+  (let* ((managed-major-mode
+  (cond
+   ((or current-prefix-arg
+(not buffer-file-name))
+(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
+(list
+ managed-major-mode
+ (let ((prompt
+(cond (current-prefix-arg
+   "[eglot] Execute program (or connect to :) ")
+  ((null guessed-command)
+   (format "[eglot] Sorry, couldn't guess for `%s'!\n\
+Execute program (or connect to :) "
+   managed-major-mode)
+   (if prompt
+   (split-string-and-unquote
+(read-shell-command prompt
+(combine-and-quote-strings guessed-command)
+'eglot-command-history))
+ guessed-command))
+ t)))
+
 (defun eglot (managed-major-mode command &optional interactive)
   "Start a Language Server Protocol server.
 Server is started with COMMAND and manages buffers of
@@ -251,64 +284,33 @@ With a prefix arg, prompt for MANAGED-MAJOR-MODE and 
COMMAND,
 else guess them from current context and `eglot-executables'.
 
 INTERACTIVE is t if called interactively."
-  (interactive
-   (let* ((managed-major-mode
-   (cond
-((or current-prefix-arg
- (not buffer-file-name))
- (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
- (list
-  managed-major-mode
-  (let ((prompt
- (cond (current-prefix-arg
-"[eglot] Execute program (or connect to :) ")
-   ((null guessed-command)
-(format "[eglot] Sorry, couldn't guess for `%s'!\n\
-Execute program (or connect to :) "
-managed-major-mode)
-(if prompt
-(split-string-and-unquote
- (read-shell-command prompt
- (combine-and-quote-strings guessed-command)
- 'eglot-command-history))
-  guessed-command))
-  t)))
+  (interactive (eglot--interactive))
   (let* ((project (project-current))
  (short-name (eglot--project-short-name project)))
 (unless project (eglot--error "Cannot work without a current project!"))
 (unless command (eglot--error "Don't know how to start EGLOT for %s 
buffers"
   major-mode))
 (let ((current-process (eglot--current-process)))
-  (cond ((and (process-live-p current-process)
-  interactive
-  (y-or-n-p "[eglot] Live process found, reconnect instead? "))
- (eglot-reconnect current-process interactive))
-(t
- (when (process-live-p current-process)
-   (eglot-shutdown current-process 'sync))
- (eglot--connect
-  project
-  managed-major-mode
-  short-name
-  command
-  (lambda (proc)
-(eglot--message "Connected! Process `%s' now managing `%s' \
+  (if (and (process-live-p current-process)
+   interactive
+   (y-or-n-p "[eglot] Live process found, reconnect instead? "))
+  (eglot-reconnect current-process interactive)
+(when (process-live-p current-process)
+  (eglot-shutdown current-process 'sync))
+(eglot--connect
+ project
+ managed-major-mode
+ short-name
+ command
+ (lambda (proc)
+   (eglot--message "Connected! Process `%s' now managing `%

[elpa] externals/eglot 6f6f01d 018/139: Doc fixes

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 6f6f01d15ee5558bf951181b1f872154dd405aae
Author: João Távora 
Commit: João Távora 

Doc fixes

* eglot.el (eglot-mode-map): Move up before minor mode.
---
 eglot.el | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/eglot.el b/eglot.el
index 8356f8e..9e5f6c2 100644
--- a/eglot.el
+++ b/eglot.el
@@ -36,12 +36,12 @@
   :group 'applications)
 
 (defvar eglot-executables '((rust-mode . ("rls")))
-  "Alist mapping major modes to server executables")
+  "Alist mapping major modes to server executables.")
 
 (defvar eglot--processes-by-project (make-hash-table :test #'equal))
 
 (defun eglot--current-process ()
-  "The current logical EGLOT process"
+  "The current logical EGLOT process."
   (let ((cur (project-current)))
 (and cur
  (gethash cur eglot--processes-by-project
@@ -98,7 +98,8 @@
 probe))
 
 (defun eglot-new-process (&optional interactive)
-  "Starts a new EGLOT process and initializes it"
+  "Start a new EGLOT process and initialize it.
+INTERACTIVE is t if called interactively."
   (interactive (list t))
   (let ((project (project-current))
 (command (eglot--command 'errorp)))
@@ -226,12 +227,14 @@
  )))
 
 (defmacro eglot--obj (&rest what)
-  "Make an object suitable for `json-encode'"
+  "Make WHAT a suitable argument for `json-encode'."
   ;; FIXME: maybe later actually do something, for now this just fixes
   ;; the indenting of literal plists.
   `(list ,@what))
 
 (defun eglot-events-buffer (process &optional interactive)
+  "Display events buffer for current LSP connection PROCESS.
+INTERACTIVE is t if called interactively."
   (interactive (list (eglot--current-process-or-lose) t))
   (let* ((probe (eglot--events-buffer process))
  (buffer (or (and (buffer-live-p probe)
@@ -264,7 +267,7 @@
   "A list of variables with saved values on every request.")
 
 (defvar eglot--environment nil
-  "Dynamically bound alist of symbol and values")
+  "Dynamically bound alist of symbol and values.")
 
 (defun eglot--process-receive (proc message)
   "Process MESSAGE from PROC."
@@ -325,6 +328,7 @@
   (setq eglot--next-request-id (1+ eglot--next-request-id)))
 
 (defun eglot-forget-pending-continuations (process)
+  "Stop waiting for responses from the current LSP PROCESS."
   (interactive (eglot--current-process-or-lose))
   (clrhash (eglot--pending-continuations process)))
 
@@ -641,7 +645,7 @@ running.  INTERACTIVE is t if called interactively."
(" [" eglot--mode-line-format "] ")))
 
 (defvar eglot--recent-changes nil
-  "List of recent changes as collected by `eglot--after-change'")
+  "List of recent changes as collected by `eglot--after-change'.")
 
 (defvar-local eglot--versioned-identifier 0)
 



[elpa] externals/eglot 41f5922 137/139: Now send willSaveWaitUntil

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 41f5922c1b396c54b1ff2e74ed804328f361c9df
Author: João Távora 
Commit: João Távora 

Now send willSaveWaitUntil

* eglot.el (eglot--client-capabilities): Report willSaveWaitUntil.
(eglot--server-workspace/applyEdit): Fix docstring.
(eglot--signal-textDocument/willSave): Send willSaveWaitUntil
(eglot--signal-textDocument/didOpen)
(eglot--signal-textDocument/didClose): Don't eglot--obj.
(eglot--apply-text-edits): Simplify. Use current buffer.
(eglot--apply-workspace-edit): Use new eglot--apply-text-edits.
---
 README.md |  6 +++---
 eglot.el  | 70 ++-
 2 files changed, 36 insertions(+), 40 deletions(-)

diff --git a/README.md b/README.md
index e5a2394..056065c 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ either:
 (define-key eglot-mode-map (kbd "") 'xref-find-definitions)
 ```
 
-# Supported Protocol features
+# Supported Protocol features (3.6)
 
 ## General
 - [x] initialize
@@ -85,14 +85,14 @@ either:
 - [ ] workspace/didChangeConfiguration
 - [ ] workspace/configuration (3.6.0)
 - [ ] workspace/didChangeWatchedFiles
-- [x] workspace/symbol
+- [x] workspace/symbol is
 - [x] workspace/applyEdit
 
 ## Text Synchronization
 - [x] textDocument/didOpen
 - [x] textDocument/didChange (incremental or full)
 - [x] textDocument/willSave
-- [ ] textDocument/willSaveWaitUntil
+- [x] textDocument/willSaveWaitUntil
 - [x] textDocument/didSave
 - [x] textDocument/didClose
 
diff --git a/eglot.el b/eglot.el
index 6dc2213..eab7ce7 100644
--- a/eglot.el
+++ b/eglot.el
@@ -203,9 +203,7 @@ CONTACT is as `eglot--contact'.  Returns a process object."
:textDocument (eglot--obj
   :synchronization (eglot--obj
 :dynamicRegistration :json-false
-:willSave t
-:willSaveWaitUntil :json-false
-:didSave t)
+:willSave t :willSaveWaitUntil t :didSave 
t)
   :completion `(:dynamicRegistration :json-false)
   :hover  `(:dynamicRegistration :json-false)
   :signatureHelp  `(:dynamicRegistration :json-false)
@@ -1023,7 +1021,7 @@ called interactively."
 
 (cl-defun eglot--server-workspace/applyEdit
 (proc &key id _label edit)
-  "Handle notification client/registerCapability"
+  "Handle server request workspace/applyEdit"
   (condition-case err
   (progn
 (eglot--apply-workspace-edit edit 'confirm)
@@ -1127,26 +1125,27 @@ Records START, END and PRE-CHANGE-LENGTH locally."
 (defun eglot--signal-textDocument/didOpen ()
   "Send textDocument/didOpen to server."
   (setq eglot--recent-changes (cons [] []))
-  (eglot--notify (eglot--current-process-or-lose)
- :textDocument/didOpen
- (eglot--obj :textDocument
- (eglot--TextDocumentItem
+  (eglot--notify
+   (eglot--current-process-or-lose)
+   :textDocument/didOpen `(:textDocument ,(eglot--TextDocumentItem
 
 (defun eglot--signal-textDocument/didClose ()
   "Send textDocument/didClose to server."
-  (eglot--notify (eglot--current-process-or-lose)
- :textDocument/didClose
- (eglot--obj :textDocument
- (eglot--TextDocumentIdentifier
+  (eglot--notify
+   (eglot--current-process-or-lose)
+   :textDocument/didClose `(:textDocument ,(eglot--TextDocumentIdentifier
 
 (defun eglot--signal-textDocument/willSave ()
   "Send textDocument/willSave to server."
-  (eglot--notify
-   (eglot--current-process-or-lose)
-   :textDocument/willSave
-   (eglot--obj
-:reason 1 ; Manual, emacs laughs in the face of auto-save muahahahaha
-:textDocument (eglot--TextDocumentIdentifier
+  (let ((proc (eglot--current-process-or-lose))
+(params `(:reason 1 :textDocument ,(eglot--TextDocumentIdentifier
+(eglot--notify proc :textDocument/willSave params)
+(ignore-errors
+  (let ((eglot-request-timeout 0.5))
+(when (plist-get :willSaveWaitUntil
+ (eglot--server-capable :textDocumentSync))
+  (eglot--apply-text-edits
+   (eglot--request proc :textDocument/willSaveWaituntil params)))
 
 (defun eglot--signal-textDocument/didSave ()
   "Send textDocument/didSave to server."
@@ -1426,22 +1425,20 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
  entries))
 (funcall oldfun)))
 
-(defun eglot--apply-text-edits (buffer edits &optional version)
-  "Apply the EDITS for BUFFER."
-  (with-current-buffer buffer
-(unless (or (not version)
-(equal version eglot--versioned-identifier))
-  (eglot--error "Edits on `%s' require version %d, you have %d"
-buffer version eglot--versioned-identifier))
-(eglot--mapply
- (eglot-

[elpa] externals/eglot 418412b 131/139: Fix copyright header. Obviously not since 2003

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 418412b292e39348ff6fd66805884683bc812219
Author: João Távora 
Commit: João Távora 

Fix copyright header. Obviously not since 2003
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 6f90349..f6eabe1 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1,6 +1,6 @@
 ;;; eglot.el --- Client for Language Server Protocol (LSP) servers  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2003-2018 Free Software Foundation, Inc.
+;; Copyright (C) 2018 Free Software Foundation, Inc.
 
 ;; Version: 0.1
 ;; Author: João Távora 



[elpa] externals/eglot efd14d6 015/139: Fix mode line

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit efd14d6d201102c8941d31e7c98f1eb5f33d3520
Author: João Távora 
Commit: João Távora 

Fix mode line

* eglot.el (mode-line-misc-info): conditionalize to eglot-mode
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 0a52da7..8946692 100644
--- a/eglot.el
+++ b/eglot.el
@@ -572,7 +572,7 @@ running.  INTERACTIVE is t if called interactively."
   map)))
 
 (add-to-list 'mode-line-misc-info
- `(t
+ `(eglot-mode
(" [" eglot--mode-line-format "] ")))
 
 (provide 'eglot)



[elpa] externals/eglot 51ff863 046/139: Must re-announce didOpen after reconnect

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 51ff863284138721d4c66ae2232df0696d097f44
Author: João Távora 
Commit: João Távora 

Must re-announce didOpen after reconnect

* eglot.el (eglot-reconnect): Also call
eglot--maybe-activate-editing-mode for all buffers.
---
 eglot.el | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index 3561da2..86c0a4c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -205,8 +205,11 @@ INTERACTIVE is t if called interactively."
(eglot--major-mode process)
(eglot--short-name process)
(eglot--bootstrap-fn process)
-   (lambda (_proc)
- (eglot--message "Reconnected!"
+   (lambda (proc)
+ (eglot--message "Reconnected!")
+ (dolist (buffer (buffer-list))
+   (with-current-buffer buffer
+ (eglot--maybe-activate-editing-mode proc))
 
 (defvar eglot--command-history nil
   "History of COMMAND arguments to `eglot'.")



[elpa] externals/eglot 7d0bf64 062/139: Workaround RLS's regusal to treat nil as empty json object

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 7d0bf64235fb3a572396a1fb0db8c2f26141f4aa
Author: João Távora 
Commit: João Távora 

Workaround RLS's regusal to treat nil as empty json object

* eglot.el (eglot--connect): Use dummy params.
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 0300ad3..8f371d2 100644
--- a/eglot.el
+++ b/eglot.el
@@ -229,7 +229,7 @@ SUCCESS-FN with no args if all goes well."
 (setf (eglot--capabilities proc) capabilities)
 (setf (eglot--status proc) nil)
 (when success-fn (funcall success-fn proc))
-(eglot--notify proc :initialized nil
+(eglot--notify proc :initialized (eglot--obj :__dummy__ t)
 
 (defvar eglot--command-history nil
   "History of COMMAND arguments to `eglot'.")



[elpa] externals/eglot 328c7ae 025/139: Auto update mode-line after setting some process properties

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 328c7aeb9dc0ede8334be6b520545abeb0db308a
Author: João Távora 
Commit: João Távora 

Auto update mode-line after setting some process properties

* eglot.el (eglot--define-process-var): Rework.
(eglot--short-name, eglot--spinner, eglot--status): Update mode-line
after setting it.
---
 eglot.el | 22 +++---
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/eglot.el b/eglot.el
index ff71a2f..1a82cc5 100644
--- a/eglot.el
+++ b/eglot.el
@@ -55,7 +55,12 @@
 (if (project-current) ""
   " (Also no current project)"
 
-(defmacro eglot--define-process-var (var-sym initval &optional doc)
+(defmacro eglot--define-process-var
+(var-sym initval &optional doc mode-line-update-p)
+  "Define VAR-SYM as a generalized process-local variable.
+INITVAL is the default value.  DOC is the documentation.
+MODE-LINE-UPDATE-P says to also force a mode line update
+after setting it."
   (declare (indent 2))
   `(progn
  (put ',var-sym 'function-documentation ,doc)
@@ -67,12 +72,15 @@
(process-put proc ',var-sym def)
def
  (gv-define-setter ,var-sym (to-store &optional process)
-   (let ((prop ',var-sym))
- `(let ((proc (or ,process (eglot--current-process-or-lose
-(process-put proc ',prop ,to-store))
+   (let* ((prop ',var-sym))
+ ,(let ((form '(let ((proc (or ,process 
(eglot--current-process-or-lose
+ (process-put proc ',prop ,to-store
+(if mode-line-update-p
+`(backquote (prog1 ,form (force-mode-line-update t)))
+  `(backquote ,form)))
 
 (eglot--define-process-var eglot--short-name nil
-  "A short name for the process")
+  "A short name for the process" t)
 
 (eglot--define-process-var eglot--expected-bytes nil
   "How many bytes declared by server")
@@ -91,11 +99,11 @@
 
 (eglot--define-process-var eglot--spinner `(nil nil t)
   "\"Spinner\" used by some servers.
-A list (ID WHAT DONE-P).")
+A list (ID WHAT DONE-P)." t)
 
 (eglot--define-process-var eglot--status `(:unknown nil)
   "Status as declared by the server.
-A list (WHAT SERIOUS-P).")
+A list (WHAT SERIOUS-P)." t)
 
 (defun eglot--command (&optional errorp)
   (let ((probe (cdr (assoc major-mode eglot-executables



[elpa] externals/eglot 75495dc 033/139: Slightly more user friendly start

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 75495dcb2ce2d1e4e0ee3ebfab990b8f1731ac01
Author: João Távora 
Commit: João Távora 

Slightly more user friendly start

* eglot.el (eglot-new-process): signal DidOpen for every file in project.
(eglot-editing-mode): Offer to start process.
---
 eglot.el | 35 ---
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/eglot.el b/eglot.el
index 6e5954c..d3428a7 100644
--- a/eglot.el
+++ b/eglot.el
@@ -193,7 +193,17 @@ INTERACTIVE is t if called interactively."
major-mode))
probe)))
   (lambda ()
-(eglot--message "Connected"
+(eglot--message "Connected")
+(dolist (buffer (buffer-list))
+  (with-current-buffer buffer
+(if (and buffer-file-name
+ (cl-some
+  (lambda (root)
+(string-prefix-p
+ (expand-file-name root)
+ (expand-file-name buffer-file-name)))
+  (project-roots project)))
+(eglot--signalDidOpen)))
 
 (defun eglot--process-sentinel (process change)
   "Called with PROCESS undergoes CHANGE."
@@ -647,16 +657,19 @@ running.  INTERACTIVE is t if called interactively."
   nil
   nil
   eglot-mode-map
-  (cond (eglot-editing-mode
- (eglot-mode 1)
- (add-hook 'after-change-functions 'eglot--after-change nil t)
- (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
- (if (eglot--current-process)
- (eglot--signalDidOpen)
-   (eglot--warn "No process")))
-(t
- (remove-hook 'flymake-diagnostic-functions 'eglot-flymake-backend t)
- (remove-hook 'after-change-functions 'eglot--after-change t
+  (cond
+   (eglot-editing-mode
+(eglot-mode 1)
+(add-hook 'after-change-functions 'eglot--after-change nil t)
+(add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
+(if (eglot--current-process)
+(eglot--signalDidOpen)
+  (if (y-or-n-p "No process, try to start one with `eglot-new-process'? ")
+  (eglot-new-process t)
+(eglot--warn "No process"
+   (t
+(remove-hook 'flymake-diagnostic-functions 'eglot-flymake-backend t)
+(remove-hook 'after-change-functions 'eglot--after-change t
 
 (define-minor-mode eglot-mode
   "Minor mode for all buffers managed by EGLOT in some way."  nil



[elpa] externals/eglot 05c67ee 112/139: Adjust flymake integration

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 05c67eece9a94cf9f8ee58b18fb4a1318b2425b3
Author: João Távora 
Commit: João Távora 

Adjust flymake integration

When opening a new file (signalling textDocument/didOpen) it makes
sense to call the flymake callback (if it exists) with no diagnostics,
just to get rid of that "Wait", since we don't know if later in this
callback cycle the server will ever report new diagnostics.

* eglot.el (eglot--managed-mode): Don't call flymake-mode or eldoc-mode
(eglot--managed-mode-hook): Add them here.
(eglot--maybe-activate-editing-mode): Call flymake callback.
(eglot--server-textDocument/publishDiagnostics): Set unreported
diagnostics to nil if invoking callback.
---
 eglot.el | 29 ++---
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/eglot.el b/eglot.el
index 21ec247..f865c22 100644
--- a/eglot.el
+++ b/eglot.el
@@ -798,9 +798,7 @@ DEFERRED is passed to `eglot--request', which see."
 (add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t)
 (add-function :before-until (local 'eldoc-documentation-function)
   #'eglot-eldoc-function)
-(add-function :around (local imenu-create-index-function) #'eglot-imenu)
-(flymake-mode 1)
-(eldoc-mode 1))
+(add-function :around (local imenu-create-index-function) #'eglot-imenu))
(t
 (remove-hook 'flymake-diagnostic-functions 'eglot-flymake-backend t)
 (remove-hook 'after-change-functions 'eglot--after-change t)
@@ -818,6 +816,9 @@ DEFERRED is passed to `eglot--request', which see."
   (when (and (process-live-p proc) (y-or-n-p "[eglot] Kill server too? "))
 (eglot-shutdown proc t))
 
+(add-hook 'eglot--managed-mode-hook 'flymake-mode)
+(add-hook 'eglot--managed-mode-hook 'eldoc-mode)
+
 (defun eglot--buffer-managed-p (&optional proc)
   "Tell if current buffer is managed by PROC."
   (and buffer-file-name (let ((cur (eglot--current-process)))
@@ -832,7 +833,8 @@ that case, also signal textDocument/didOpen."
   (when (eglot--buffer-managed-p proc)
 (eglot--managed-mode 1)
 (eglot--signal-textDocument/didOpen)
-(flymake-start)))
+(flymake-start)
+(funcall (or eglot--current-flymake-report-fn #'ignore) nil)))
 
 (add-hook 'find-file-hook 'eglot--maybe-activate-editing-mode)
 
@@ -999,11 +1001,11 @@ called interactively."
   (t   :note))
 (concat source ": " message)
  into diags
- finally (if eglot--current-flymake-report-fn
- (funcall eglot--current-flymake-report-fn
-  diags)
-   (setq eglot--unreported-diagnostics
- diags)
+ finally (cond (eglot--current-flymake-report-fn
+(funcall eglot--current-flymake-report-fn diags)
+(setq eglot--unreported-diagnostics nil))
+   (t
+(setq eglot--unreported-diagnostics diags))
  (t
   (eglot--message "OK so %s isn't visited" filename)
 
@@ -1174,15 +1176,12 @@ Records START, END and PRE-CHANGE-LENGTH locally."
 (defun eglot-flymake-backend (report-fn &rest _more)
   "An EGLOT Flymake backend.
 Calls REPORT-FN maybe if server publishes diagnostics in time."
-  ;; Maybe call immediately if anything unreported (this will clear
-  ;; any pending diags)
+  (setq eglot--current-flymake-report-fn report-fn)
+  ;; Report anything unreported
   (when eglot--unreported-diagnostics
 (funcall report-fn eglot--unreported-diagnostics)
 (setq eglot--unreported-diagnostics nil))
-  ;; Setup so maybe it's called later, too.
-  (setq eglot--current-flymake-report-fn report-fn)
-  ;; Take this opportunity to signal a didChange that might eventually
-  ;; make the server report new diagnostics.
+  ;; Signal a didChange that might eventually bring new diagnotics
   (eglot--signal-textDocument/didChange))
 
 (defun eglot-xref-backend ()



[elpa] externals/eglot a4f99e0 005/139: Introduce and use `eglot--current-process-or-lose'

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit a4f99e09d3a4eaafb1d59875f0d314549a104137
Author: João Távora 
Commit: João Távora 

Introduce and use `eglot--current-process-or-lose'
---
 eglot.el | 83 +++-
 1 file changed, 45 insertions(+), 38 deletions(-)

diff --git a/eglot.el b/eglot.el
index 92c1216..5ca6833 100644
--- a/eglot.el
+++ b/eglot.el
@@ -45,12 +45,16 @@
   (eglot--error "No current project, so no process"))
 (gethash cur eglot--processes-by-project)))
 
+(defun eglot--current-process-or-lose ()
+  (or (eglot--current-process)
+  (eglot--error "No current EGLOT process")))
+
 (defmacro eglot--define-process-var (var-sym initval &optional doc)
   (declare (indent 2))
   `(progn
  (put ',var-sym 'function-documentation ,doc)
  (defun ,var-sym (&optional process)
-   (let* ((proc (or process (eglot--current-process)))
+   (let* ((proc (or process (eglot--current-process-or-lose)))
   (probe (process-get proc ',var-sym)))
  (or probe
  (let ((def ,initval))
@@ -58,7 +62,7 @@
def
  (gv-define-setter ,var-sym (to-store &optional process)
(let ((prop ',var-sym))
- `(let ((proc (or ,process (eglot--current-process
+ `(let ((proc (or ,process (eglot--current-process-or-lose
 (process-put proc ',prop ,to-store))
 
 (eglot--define-process-var eglot--message-mark nil
@@ -103,7 +107,7 @@
 major-mode))
 probe))
 
-(defun eglot-new-process (&optional _interactive)
+(defun eglot-new-process (&optional interactive)
   "Starts a new EGLOT process and initializes it"
   (interactive (list t))
   (let ((project (project-current))
@@ -141,10 +145,10 @@
 (let ((inhibit-read-only t))
   (insert
(format "\n---\n"
-  (eglot--protocol-initialize proc))
+  (eglot--protocol-initialize proc interactive))
 
 (defun eglot-quit-server (process &optional sync)
-  (interactive (list (eglot--current-process)))
+  (interactive (list (eglot--current-process-or-lose)))
   (eglot--message "Asking server to terminate")
   (eglot--request
   process
@@ -238,7 +242,7 @@
  )))
 
 (defun eglot-events-buffer (process &optional interactive)
-  (interactive (list (eglot--current-process) t))
+  (interactive (list (eglot--current-process-or-lose) t))
   (let* ((probe (eglot--events-buffer process))
  (buffer (or (and (buffer-live-p probe)
   probe)
@@ -302,7 +306,7 @@
   (setq eglot--next-request-id (1+ eglot--next-request-id)))
 
 (defun eglot-forget-pending-continuations (process)
-  (interactive (eglot--current-process))
+  (interactive (eglot--current-process-or-lose))
   (clrhash (eglot--pending-continuations process)))
 
 (defun eglot--call-with-request (process
@@ -350,38 +354,41 @@
   (accept-process-output nil 0.01))
 
 
-(defun eglot--protocol-initialize (process)
+(defun eglot--protocol-initialize (process interactive)
   (eglot--request
-process
-:initialize
-`(:processId  ,(emacs-pid)
-  :rootPath  ,(concat "" ;; FIXME RLS doesn't like "file://"
-  (expand-file-name (car (project-roots
-  
(project-current)
-  :initializationOptions  []
-  :capabilities (:workspace (:executeCommand 
(:dynamicRegistration t))
-:textDocument (:synchronization 
(:didSave t)))
-  )
-(lambda (&key capabilities)
-  (cl-destructuring-bind
-  (&rest all
- &key
- _textDocumentSync
- _hoverProvider
- _completionProvider
- _definitionProvider
- _referencesProvider
- _documentHighlightProvider
- _documentSymbolProvider
- _workspaceSymbolProvider
- _codeActionProvider
- _documentFormattingProvider
- _documentRangeFormattingProvider
- _renameProvider
- _executeCommandProvider
- )
-  capabilities
-(message "so yeah I got lots (%d) of capabilities" (length all))
+   process
+   :initialize
+   `(:processId  ,(emacs-pid)
+ :rootPath  ,(concat "" ;; FIXME RLS doesn't like "file://"
+ (expand-file-name (car (project-roots
+ 
(project-current)
+ :initializationOptions  []
+ :capabilities (:workspace (:executeCommand 
(:dynamicRegistration t))
+   :textDocument (:synchronization 
(:didSave t
+   (lambda (&key capabilitie

[elpa] externals/eglot e60c7fc 013/139: Overhaul async mechanism safety

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit e60c7fce4048e8080a770013b0fbf8c26a5e5d54
Author: João Távora 
Commit: João Távora 

Overhaul async mechanism safety
---
 eglot.el | 172 +++
 1 file changed, 95 insertions(+), 77 deletions(-)

diff --git a/eglot.el b/eglot.el
index b59ee02..af9904a 100644
--- a/eglot.el
+++ b/eglot.el
@@ -84,24 +84,8 @@
 (eglot--define-process-var eglot--capabilities :unreported
   "Holds list of capabilities that server reported")
 
-(cl-defmacro eglot--request (process
-  method
-  params
-  success-fn
-  &key
-  error-fn
-  timeout-fn
-  (async-p t))
-  (append `(eglot--call-with-request
-,process
-,async-p
-,method
-,params
-(cl-function ,success-fn))
-  (and error-fn
-   `((cl-function ,error-fn)))
-  (and timeout-fn
-   `((cl-function ,timeout-fn)
+(eglot--define-process-var eglot--moribund nil
+  "Non-nil if process is about to exit")
 
 (defun eglot--command (&optional errorp)
   (let ((probe (cdr (assoc major-mode eglot-executables
@@ -116,12 +100,12 @@
   (interactive (list t))
   (let ((project (project-current))
 (command (eglot--command 'errorp)))
-(unless project (eglot--error "Cannot work without a current project!"))
+(unless project (eglot--error "(new-process) Cannot work without a current 
project!"))
 (let ((current-process (eglot--current-process)))
   (when (and current-process
  (process-live-p current-process))
-(eglot--message "Asking current process to terminate first")
-(eglot-quit-server current-process 'sync)))
+(eglot--message "(new-process) Asking current process to terminate 
first")
+(eglot-quit-server current-process 'sync interactive)))
 (let* ((short-name (file-name-base
 (directory-file-name
  (car (project-roots (project-current))
@@ -154,20 +138,23 @@
 
 (defun eglot--process-sentinel (process change)
   (with-current-buffer (process-buffer process)
-(eglot--debug "Process state changed to %s" change)
+(eglot--debug "(sentinel) Process state changed to %s" change)
 (when (not (process-live-p process))
   ;; Remember to cancel all timers
   ;;
-  (maphash (lambda (id v) 
- (cl-destructuring-bind (_success _error timeout) v
-   (eglot--message "Cancelling timer for continuation %s" id)
+  (maphash (lambda (id triplet)
+ (cl-destructuring-bind (_success _error timeout) triplet
+   (eglot--message
+"(sentinel) Cancelling timer for continuation %s" id)
(cancel-timer timeout)))
(eglot--pending-continuations process))
-  (cond ((process-get process 'eglot--moribund)
- (eglot--message "Process exited with status %s"
+  (cond ((eglot--moribund process)
+ (eglot--message "(sentinel) Moribund process exited with status 
%s"
  (process-exit-status process)))
 (t
- (eglot--warn "Process unexpectedly changed to %s" change))
+ (eglot--warn "(sentinel) Process unexpectedly changed to %s"
+  change)))
+  (delete-process process
 
 (defun eglot--process-filter (proc string)
   (when (buffer-live-p (process-buffer proc))
@@ -306,35 +293,44 @@
   (interactive (eglot--current-process-or-lose))
   (clrhash (eglot--pending-continuations process)))
 
-(defun eglot--call-with-request (process
-  async-p
-  method
-  params
-  success-fn
-  &optional error-fn timeout-fn)
+(cl-defun eglot--request (process
+   method
+   params
+   &key success-fn error-fn timeout-fn (async-p t))
   (let* ((id (eglot--next-request-id))
- (timeout-fn (or timeout-fn
- (lambda ()
-   (eglot--warn "Tired of waiting for reply to %s" id)
-   (remhash id (eglot--pending-continuations 
process)
- (error-fn (or error-fn
-   (cl-function
-(lambda (&key code message)
-  (eglot--warn "Request id=%s errored with code=%s: %s"
-id code message)
+ (timeout-fn
+  (or timeout-fn
+  (lambda ()
+(eglot--warn
+ "(request) Tired of waiting for reply to %s" id)
+(re

[elpa] externals/eglot 0ec7801 012/139: Simplify `eglot--protocol-initialize`

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 0ec78011fee3be96f110fc37756a9baac6595348
Author: João Távora 
Commit: João Távora 

Simplify `eglot--protocol-initialize`

* eglot.el (eglot--protocol-initialize): Simplify
---
 eglot.el | 29 +++--
 1 file changed, 7 insertions(+), 22 deletions(-)

diff --git a/eglot.el b/eglot.el
index cd91d78..b59ee02 100644
--- a/eglot.el
+++ b/eglot.el
@@ -70,7 +70,7 @@
   "Point where next unread message starts")
 
 (eglot--define-process-var eglot--short-name nil
-  "A short name")
+  "A short name for the process")
 
 (eglot--define-process-var eglot--expected-bytes nil
   "How many bytes declared by server")
@@ -81,6 +81,9 @@
 (eglot--define-process-var eglot--events-buffer nil
   "A buffer pretty-printing the EGLOT RPC events")
 
+(eglot--define-process-var eglot--capabilities :unreported
+  "Holds list of capabilities that server reported")
+
 (cl-defmacro eglot--request (process
   method
   params
@@ -367,29 +370,11 @@
  :capabilities (:workspace (:executeCommand 
(:dynamicRegistration t))
:textDocument (:synchronization 
(:didSave t
(lambda (&key capabilities)
- (cl-destructuring-bind
- (&rest all
-&key
-;; capabilities reported by server
-_textDocumentSync
-_hoverProvider
-_completionProvider
-_definitionProvider
-_referencesProvider
-_documentHighlightProvider
-_documentSymbolProvider
-_workspaceSymbolProvider
-_codeActionProvider
-_documentFormattingProvider
-_documentRangeFormattingProvider
-_renameProvider
-_executeCommandProvider
-)
- capabilities
-   (when interactive
+ (setf (eglot--capabilities process) capabilities)
+ (when interactive
  (eglot--message
   "So yeah I got lots (%d) of capabilities"
-  (length all)))
+  (length capabilities))
 
 (defun eglot-quit-server (process &optional sync)
   (interactive (list (eglot--current-process-or-lose)))



[elpa] externals/eglot 581608f 115/139: Resist server failure during synchronous requests

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 581608fa8c3f319415a3476a949b53e209299bc8
Author: João Távora 
Commit: João Távora 

Resist server failure during synchronous requests

Calling the error handler unprotected could lead to the rest of the
sentinel not running at all. This defeated the auto-reconnection in
Rust, for example.

* eglot.el (eglot--process-sentinel): Rework.
---
 eglot.el | 81 +++-
 1 file changed, 39 insertions(+), 42 deletions(-)

diff --git a/eglot.el b/eglot.el
index bf0b9e9..d49367b 100644
--- a/eglot.el
+++ b/eglot.el
@@ -339,50 +339,47 @@ INTERACTIVE is t if called interactively."
 (defvar eglot--inhibit-auto-reconnect nil
   "If non-nil, don't autoreconnect on unexpected quit.")
 
-(defun eglot--process-sentinel (process change)
-  "Called with PROCESS undergoes CHANGE."
+(defun eglot--process-sentinel (proc change)
+  "Called when PROC undergoes CHANGE."
   (eglot--debug "(sentinel) Process state changed to %s" change)
-  (when (not (process-live-p process))
-;; Cancel timers and error any outstanding continuations
-;;
+  (when (not (process-live-p proc))
+;; Cancel outstanding timers
 (maphash (lambda (_id triplet)
-   (cl-destructuring-bind (_success error timeout) triplet
- (cancel-timer timeout)
- (funcall error :code -1 :message (format "Server died"
- (eglot--pending-continuations process))
-;; Turn off `eglot--managed-mode' where appropriate.
-;;
-(dolist (buffer (buffer-list))
-  (with-current-buffer buffer
-(when (eglot--buffer-managed-p process)
-  (eglot--managed-mode -1
-;; Forget about the process-project relationship
-;;
-(setf (gethash (eglot--project process) eglot--processes-by-project)
-  (delq process
-(gethash (eglot--project process) 
eglot--processes-by-project)))
-(cond ((eglot--moribund process)
-   (eglot--message "(sentinel) Moribund process exited with status %s"
-   (process-exit-status process)))
-  ((null eglot--inhibit-auto-reconnect)
-   (eglot--warn
-"(sentinel) Reconnecting after process unexpectedly changed to 
`%s'."
-change)
-   (condition-case-unless-debug err
-   (eglot-reconnect process)
- (error (eglot--warn "Auto-reconnect failed: %s " err) ))
-   (setq eglot--inhibit-auto-reconnect
- (run-with-timer
-  3 nil
-  (lambda ()
-(setq eglot--inhibit-auto-reconnect nil)
-  (t
-   (eglot--warn
-"(sentinel) Not auto-reconnecting, last one didn't last long."
-change)))
-(force-mode-line-update t)
-(delete-process process)))
-
+   (cl-destructuring-bind (_success _error timeout) triplet
+ (cancel-timer timeout)))
+ (eglot--pending-continuations proc))
+(unwind-protect
+;; Call all outstanding error handlers
+(maphash (lambda (_id triplet)
+   (cl-destructuring-bind (_success error _timeout) triplet
+ (funcall error :code -1 :message (format "Server died"
+ (eglot--pending-continuations proc))
+  ;; Turn off `eglot--managed-mode' where appropriate.
+  (dolist (buffer (buffer-list))
+(with-current-buffer buffer
+  (when (eglot--buffer-managed-p proc)
+(eglot--managed-mode -1
+  ;; Forget about the process-project relationship
+  (setf (gethash (eglot--project proc) eglot--processes-by-project)
+(delq proc
+  (gethash (eglot--project proc) eglot--processes-by-project)))
+  (cond ((eglot--moribund proc)
+ (eglot--message "(sentinel) Moribund process exited with status 
%s"
+ (process-exit-status proc)))
+((null eglot--inhibit-auto-reconnect)
+ (eglot--warn
+  "(sentinel) Reconnecting after process unexpectedly changed to 
`%s'."
+  change)
+ (setq eglot--inhibit-auto-reconnect
+   (run-with-timer 3 nil
+   (lambda ()
+ (setq eglot--inhibit-auto-reconnect 
nil
+ (eglot-reconnect proc))
+(t
+ (eglot--warn
+  "(sentinel) Not auto-reconnecting, last one didn't last long."
+  change)))
+  (delete-process proc
 (defun eglot--process-filter (proc string)
   "Called when new data STRING has arrived for PROC."
   (when (buffer-live-p (process-buffer proc))



[elpa] externals/eglot 37b7329 098/139: Reasonable textDocument/documentHighlight support

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 37b73290e881df071efb6fb44854b05d57d758bf
Author: João Távora 
Commit: João Távora 

Reasonable textDocument/documentHighlight support

* README.md: Update.

* eglot.el (eglot--current-buffer-TextDocumentPositionParams): New
helper.
(xref-backend-identifier-completion-table): Refactor a bit.
(xref-backend-identifier-at-point): Use when-let and
eglot--current-buffer-TextDocumentPositionParams
(xref-backend-definitions, xref-backend-references): Refactor a
bit.
(eglot-completion-at-point): Use
eglot--current-buffer-TextDocumentPositionParams
(eglot-eldoc-function): Rewrite to handle
textDocument/documentHighlight.
(eglot--highlights): New variable.
(eglot--client-capabilities): Update with support for documentHighlight.
---
 README.md |  13 +++
 eglot.el  | 117 +++---
 2 files changed, 74 insertions(+), 56 deletions(-)

diff --git a/README.md b/README.md
index fef2d16..5838bc5 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@ server. To skip the guess and always be prompted use `C-u M-x 
eglot`.
 - [x] textDocument/completion
 - [ ] completionItem/resolve
 - [x] textDocument/definition
-- [ ] textDocument/documentHighlight
+- [x] textDocument/documentHighlight
 - [x] textDocument/documentSymbol
 - [ ] textDocument/executeCommand
 - [ ] textDocument/format
@@ -46,17 +46,18 @@ server. To skip the guess and always be prompted use `C-u 
M-x eglot`.
 
 # Differences to lsp-mode.el
 
-This is really beta and currently does less than
-[lsp-mode.el][emacs-lsp] which is more
-mature. Though I think `eglot.el` will eventually beat it, you could
-be better served with `lsp-mode.el` for now.
+This is really beta and currently does a little less than
+[lsp-mode.el][emacs-lsp] which is more mature. Though I think
+`eglot.el` will eventually beat it, you could be better served with
+`lsp-mode.el` for now.
 
 User-visible differences:
 
 - Single entry point, `M-x eglot` to enable LSP in a project.
   Automatically detects current and future opened files under that
   project and syncs with server.
-- Easy way to restart a 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
   communication.

diff --git a/eglot.el b/eglot.el
index 807df98..c5c99f2 100644
--- a/eglot.el
+++ b/eglot.el
@@ -193,11 +193,12 @@ CONTACT is as `eglot--contact'.  Returns a process 
object."
 :willSave t
 :willSaveWaitUntil :json-false
 :didSave t)
-  :completion `(:dynamicRegistration :json-false)
-  :hover  `(:dynamicRegistration :json-false)
-  :references `(:dynamicRegistration :json-false)
-  :definition `(:dynamicRegistration :json-false)
-  :documentSymbol `(:dynamicRegistration :json-false)
+  :completion `(:dynamicRegistration :json-false)
+  :hover  `(:dynamicRegistration :json-false)
+  :references `(:dynamicRegistration :json-false)
+  :definition `(:dynamicRegistration :json-false)
+  :documentSymbol `(:dynamicRegistration :json-false)
+  :documentHighlight  `(:dynamicRegistration :json-false)
   :publishDiagnostics `(:relatedInformation :json-false))
:experimental (eglot--obj)))
 
@@ -1057,6 +1058,11 @@ running.  INTERACTIVE is t if called interactively."
  (widen)
  (buffer-substring-no-properties (point-min) (point-max))
 
+(defun eglot--current-buffer-TextDocumentPositionParams ()
+  "Compute TextDocumentPositionParams."
+  (eglot--obj :textDocument (eglot--current-buffer-TextDocumentIdentifier)
+  :position (eglot--pos-to-lsp-position)))
+
 (defun eglot--before-change (start end)
   "Hook onto `before-change-functions'.
 Records START and END, crucially convert them into
@@ -1206,11 +1212,12 @@ DUMMY is ignored"
(eglot--mapply
 (eglot--lambda (&key name kind location containerName)
   (propertize name
-  :position (plist-get
- (plist-get location :range)
- :start)
+  :textDocumentPositionParams
+  (eglot--obj :textDocument text-id
+  :position (plist-get
+ (plist-get location 
:range)
+ :start))
   :locations (list location)
-  :textDocument tex

[elpa] externals/eglot 39e8b9e 081/139: Add (dummy) tests and Travis CI integration

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 39e8b9e46e9d59f6995ec1415c6663f03b9fa032
Author: João Távora 
Commit: João Távora 

Add (dummy) tests and Travis CI integration

* .travis.yml: New file.

* Makefile: New file.

* README.md: Add Travis badge.

* eglot-tests.el: New file with a dummy test.
---
 .travis.yml| 19 +++
 Makefile   | 35 +++
 README.md  |  1 +
 eglot-tests.el | 32 
 4 files changed, 87 insertions(+)

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000..7a89327
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,19 @@
+language: generic
+sudo: false
+
+env:
+  global:
+- EGLOT_TESTING=t # For kicks, so I don't forget this syntax
+  matrix:
+- EMACS_VERSION=26-prerelease
+
+install:
+  - curl -LO 
https://github.com/npostavs/emacs-travis/releases/download/bins/emacs-bin-${EMACS_VERSION}.tar.gz
+  - tar -xaf emacs-bin-${EMACS_VERSION}.tar.gz -C /
+  # Configure $PATH: Emacs installed to /tmp/emacs
+  - export PATH=/tmp/emacs/bin:${PATH}
+  - emacs --version
+
+script:
+  - make check
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 000..7b85351
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,35 @@
+### Makefile for EGLOT
+### 
+# Variables
+#
+EMACS=emacs
+
+LOAD_PATH=-L .
+
+ELFILES := eglot.el eglot-tests.el
+ELCFILES := $(ELFILES:.el=.elc)
+
+all: compile
+
+# Compilation
+#
+%.elc: %.el
+   $(EMACS) -Q $(LOAD_PATH) --batch -f batch-byte-compile $<
+
+compile: $(ELCFILES)
+
+# Automated tests
+#
+check: compile
+
+check: SELECTOR=t
+check: compile
+   $(EMACS) -Q --batch $(LOAD_PATH)\
+   -l eglot-tests  \
+   -f ert-run-tests-batch-and-exit \
+
+# Cleanup
+#
+clean:
+   find . -iname '*.elc' -exec rm {} \;
+.PHONY: all compile clean check
diff --git a/README.md b/README.md
index 0314664..955ef54 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+[![Build 
Status](https://travis-ci.org/joaotavora/eglot.png)](https://travis-ci.org/joaotavora/eglot)
 Eglot
 -
 
diff --git a/eglot-tests.el b/eglot-tests.el
new file mode 100644
index 000..0f29519
--- /dev/null
+++ b/eglot-tests.el
@@ -0,0 +1,32 @@
+;;; eglot-tests.el --- Tests for eglot.el-*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2018  João Távora
+
+;; Author: João Távora 
+;; Keywords: tests
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see .
+
+;;; Commentary:
+
+;; Tests for eglot.el
+
+;;; Code:
+(require 'eglot)
+(require 'ert)
+
+(ert-deftest dummy () "A dummy test" (should t))
+
+(provide 'eglot-tests)
+;;; eglot-tests.el ends here



[elpa] externals/eglot 71e47d2 102/139: Fix odd bugs and tweak stuff

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 71e47d2091005cc69d679c2b5f8cb4f436b57c54
Author: João Távora 
Commit: João Távora 

Fix odd bugs and tweak stuff

* eglot.el (eglot--log-event): Insert before markers.
(eglot--process-receive): Shave lines.
(xref-backend-references): Use cl-return-from.
(eglot--log-event): Simplify
(eglot-completion-at-point): Saner annotation
---
 eglot.el | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/eglot.el b/eglot.el
index 37ad616..546671e 100644
--- a/eglot.el
+++ b/eglot.el
@@ -462,7 +462,7 @@ INTERACTIVE is t if called interactively."
 (when interactive (display-buffer buffer))
 buffer))
 
-(defun eglot--log-event (proc message type)
+(defun eglot--log-event (proc message &optional type)
   "Log an eglot-related event.
 PROC is the current process.  MESSAGE is a JSON-like plist.  TYPE
 is a symbol saying if this is a client or server originated."
@@ -477,7 +477,7 @@ is a symbol saying if this is a client or server 
originated."
   ;; pyls keeps on sending these
   (t 'unexpected-thingy)))
(type
-(format "%s-%s" type subtype)))
+(format "%s-%s" (or type :internal) subtype)))
   (goto-char (point-max))
   (let ((msg (format "%s%s%s:\n%s\n"
  type
@@ -486,7 +486,7 @@ is a symbol saying if this is a client or server 
originated."
  (pp-to-string message
 (when error
   (setq msg (propertize msg 'face 'error)))
-(insert msg)
+(insert-before-markers msg)
 
 (defun eglot--process-receive (proc message)
   "Process MESSAGE from PROC."
@@ -500,14 +500,12 @@ is a symbol saying if this is a client or server 
originated."
 (when err (setf (eglot--status proc) `(,err t)))
 (cond (method
;; a server notification or a server request
-   (let* ((handler-sym (intern (concat "eglot--server-"
-   method
+   (let* ((handler-sym (intern (concat "eglot--server-" method
  (if (functionp handler-sym)
  (apply handler-sym proc (append
   (plist-get message :params)
   (if id `(:id ,id
-   (eglot--warn "No implementation of method %s yet"
-method)
+   (eglot--warn "No implementation of method %s yet" method)
(when id
  (eglot--reply
   proc id
@@ -1264,7 +1262,8 @@ DUMMY is ignored"
  location-or-locations)))
 
 (cl-defmethod xref-backend-references ((_backend (eql eglot)) identifier)
-  (unless (eglot--server-capable :referencesProvider) (cl-return nil))
+  (unless (eglot--server-capable :referencesProvider)
+(cl-return-from xref-backend-references nil))
   (let ((params
  (or (get-text-property 0 :textDocumentPositionParams identifier)
  (let ((rich (car (member identifier eglot--xref-known-symbols
@@ -1316,10 +1315,10 @@ DUMMY is ignored"
:documentation documentation :sortText sortText))
  items
:annotation-function
-   (lambda (what) (let ((detail (get-text-property 0 :detail what))
-(kind-name (get-text-property 0 :kind what)))
-(concat (if detail (format " %s" detail) "")
-(if kind-name (format " (%s)" kind-name) ""
+   (lambda (what)
+ (propertize (concat " " (or (get-text-property 0 :detail what)
+ (get-text-property 0 :kind what)))
+ 'face 'font-lock-function-name-face))
:display-sort-function
(lambda (items) (sort items (lambda (a b)
  (string-lessp



[elpa] externals/eglot 458bc69 110/139: More correctly setup rust-mode-related autoloads

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 458bc6989e33ab0b95b6f1c8d2aa90e0a06c468d
Author: João Távora 
Commit: João Távora 

More correctly setup rust-mode-related autoloads

By autoloading the add-hook form and the eglot--setup-rls-idiosyncrasies
definition, a user can start rust-mode without loading eglot.el along
with it.

* eglot.el (rust-mode-hook)
(eglot--setup-rls-idiosyncrasies): Wrap in autoloaded progn.
---
 eglot.el | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/eglot.el b/eglot.el
index eba0e84..fbddf16 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1471,12 +1471,11 @@ Proceed? "
 (and (equal "Indexing" what) done
 
 ;;;###autoload
-(add-hook 'rust-mode-hook 'eglot--setup-rls-idiosyncrasies)
-
-;;;###autoload
-(defun eglot--setup-rls-idiosyncrasies ()
-  "RLS needs special treatment..."
-  (add-hook 'eglot--ready-predicates 'eglot--rls-probably-ready-for-p t t))
+(progn
+  (add-hook 'rust-mode-hook 'eglot--setup-rls-idiosyncrasies)
+  (defun eglot--setup-rls-idiosyncrasies ()
+"Prepare `eglot' to deal with RLS's special treatment."
+(add-hook 'eglot--ready-predicates 'eglot--rls-probably-ready-for-p t t)))
 
 (cl-defun eglot--server-window/progress
 (process &key id done title message &allow-other-keys)



[elpa] branch externals/eglot created (now 4c0bfc3)

2018-05-14 Thread Jo�o T�vora
capitaomorte pushed a change to branch externals/eglot.

at  4c0bfc3   Support didChangeWatchedFiles with dynamic registration

This branch includes the following new commits:

   new  d90efdf   Initial commit
   new  3a8f9a1   Remove a couple of comments
   new  2775dea   Rename eglot--continuations eglot--pending-continuations
   new  3489176   Add a mode-line construct and some minor fanciness
   new  a4f99e0   Introduce and use `eglot--current-process-or-lose'
   new  72895ca   Handle notifications
   new  0222e7e   Improve `eglot--current-process'
   new  6f0a8df   Organize a bit
   new  c417eb4   Cancel timeouts when process dies unexpectedly
   new  bc011d0   Minor cleanup
   new  dfab9a0   Experimental diagnostic overlays
   new  0ec7801   Simplify `eglot--protocol-initialize`
   new  e60c7fc   Overhaul async mechanism safety
   new  e1d36d2   Fix some byte-compilation warnings
   new  efd14d6   Fix mode line
   new  8bd634c   Start working on this again
   new  4f246b5   * eglot.el (eglot-mode-map): Move up before minor mode.
   new  6f6f01d   Doc fixes
   new  c222c3b   Lay groundwork for uniform treatment of network 
connections
   new  16be2fc   Fix parser to accept multiple messages in one chunk
   new  1dc2a9f   Implement spinners and RLS's window/progress
   new  b4dd4f8   Report server status in the mode-line
   new  8e6488f   Don't switch to possibly dead buffer in sentinel
   new  7c82a03   Start experimenting with python
   new  328c7ae   Auto update mode-line after setting some process 
properties
   new  6689a15   Add eglot-clear-status interactive command
   new  3403f86   Correctly report what we currently are capable of
   new  95983c9   Change status to error everytime an error is found
   new  7ec0dcf   Events buffer uses eglot-mode, source buffers use 
eglot-editing-mode
   new  63f2208   Less obstrusive flymake stuff for now
   new  e8f859e   Rework commands for connecting and reconnecting
   new  931093e   Don't clutter UI with warnings
   new  75495dc   Slightly more user friendly start
   new  22dc2f7   Ready to start fixing flymake integration
   new  c948713   Auto-reconnect on unexpected connection loss
   new  b511b7d   Redesign and simplify parser
   new  be52e1e   Rework connection restarting again
   new  92bf3a0   Signal textDocument/didClose
   new  fdb4de1   Simplify flymake integration
   new  88e3655   Appease checkdoc.el
   new  c95a0a4   Multiple servers per project are possible
   new  0e95167   Watch for files opened under umbrella of existing process
   new  cc183a6   Fix assorted bugs
   new  f7f77e1   Make M-x eglot the main entry point
   new  d2eca65   Fix another Flymake sync bug
   new  51ff863   Must re-announce didOpen after reconnect
   new  17e0ca4   Fix Flymake diagnostic positions
   new  2b61a3b   Delete two useless forward declarations
   new  46bb1c0   Reorganize file
   new  a3545fb   Rename RPC methods for clarity
   new  9665a3e   Fix textDocument/didChange
   new  1514e0f   Fix a couple of Rust-related edge cases
   new  f1b6485   Trim some edges and add a bunch of boring RPC methods
   new  9d404c9   Update README.md
   new  b1554fc   * eglot.el (eglot--process-receive): Skip null method 
notifs.
   new  29d4103   Fix mode-line mouse-clicks from outside selected window
   new  f76f04e   More correctly keep track of didOpen/didClose per buffer
   new  95187cf   Connect to LSP server via TCP
   new  eebd32b   When user declines to reconnect, first quit existing 
server
   new  b69302c   Make M-x eglot's interactive spec a separate function
   new  4d4b85d   eglot-editing-mode becomes eglot--managed-mode
   new  7d0bf64   Workaround RLS's regusal to treat nil as empty json object
   new  c2862f4   Don't auto-reconnect if last attempt lasted less than 3 
seconds
   new  f8bfb7e   Handle requests from server correctly
   new  df5d76d   Reply to client/registerCapability (don't handle it yet)
   new  ea918ab   Include source info in diagnostics
   new  e7ffc31   Make reported capabilities into its own function
   new  b657b32   Use rootUri instead of rootPath
   new  79a2a1e   Be quite explicit about our lack of capabilities right now
   new  a199c8e   Honour textDocumentSync
   new  8160cd4   Handle dynamic registration in general (but nothing 
specific yet)
   new  9882bf2   Cleanup mistake with TextDocumentItem and 
TextDocumentIdentifier
   new  e86f9b4   New helper eglot--sync-request
   new  ff5a03d   Very basic xref support
   new  193c57d   Half-decent xref support
   new  571b08f   Fix the odd bug here and there
   new  e9b5e54   ETOOMANYLAMBDAS
   new  1add335   Workaround two suspected Emacs bugs
   new  9ff97a6   In

[elpa] externals/eglot e964abe 091/139: Get rid of eglot--buffer-open-count

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit e964abeba3e1f164fa05e9f7aaa79c4419ee1fe7
Author: João Távora 
Commit: João Távora 

Get rid of eglot--buffer-open-count

Hasn't really proved useful yet.

* eglot.el (eglot--buffer-open-count): Remove.
(eglot--signal-textDocument/didOpen)
(eglot--signal-textDocument/didClose): Simplify.
---
 eglot.el | 35 ---
 1 file changed, 8 insertions(+), 27 deletions(-)

diff --git a/eglot.el b/eglot.el
index 1318fee..a600f47 100644
--- a/eglot.el
+++ b/eglot.el
@@ -135,9 +135,6 @@ A list (WHAT SERIOUS-P)." t)
 Either a list of strings (a shell command and arguments), or a
 list of a single string of the form :")
 
-(eglot--define-process-var eglot--buffer-open-count (make-hash-table)
-  "Keeps track of didOpen/didClose notifs for each buffer.")
-
 (defun eglot--make-process (name managed-major-mode contact)
   "Make a process from CONTACT.
 NAME is a name to give the inferior process or connection.
@@ -1158,33 +1155,17 @@ Records START, END and PRE-CHANGE-LENGTH locally."
 
 (defun eglot--signal-textDocument/didOpen ()
   "Send textDocument/didOpen to server."
-  (let* ((proc (eglot--current-process-or-lose))
- (count (1+ (or (gethash (current-buffer)
- (eglot--buffer-open-count proc))
-0
-(when (> count 1)
-  (eglot--error "Too many textDocument/didOpen notifs for %s" 
(current-buffer)))
-(setf (gethash (current-buffer) (eglot--buffer-open-count proc))
-  count)
-(eglot--notify proc
-   :textDocument/didOpen
-   (eglot--obj :textDocument
-   (eglot--current-buffer-TextDocumentItem)
+  (eglot--notify (eglot--current-process-or-lose)
+ :textDocument/didOpen
+ (eglot--obj :textDocument
+ (eglot--current-buffer-TextDocumentItem
 
 (defun eglot--signal-textDocument/didClose ()
   "Send textDocument/didClose to server."
-  (let* ((proc (eglot--current-process-or-lose))
- (count (1- (or (gethash (current-buffer)
- (eglot--buffer-open-count proc))
-0
-(when (< count 0)
-  (eglot--error "Too many textDocument/didClose notifs for %s" 
(current-buffer)))
-(setf (gethash (current-buffer) (eglot--buffer-open-count proc))
-  count)
-(eglot--notify proc
-   :textDocument/didClose
-   (eglot--obj :textDocument
-   
(eglot--current-buffer-TextDocumentIdentifier)
+  (eglot--notify (eglot--current-process-or-lose)
+ :textDocument/didClose
+ (eglot--obj :textDocument
+ (eglot--current-buffer-TextDocumentIdentifier
 
 (defun eglot--signal-textDocument/willSave ()
   "Send textDocument/willSave to server."



[elpa] externals/eglot 9af84a2 124/139: Prepare to sumbit to GNU ELPA

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 9af84a283fa3d5247be413d8300b1aa23e6c0124
Author: João Távora 
Commit: João Távora 

Prepare to sumbit to GNU ELPA

* eglot.el: Update headers.
---
 eglot.el | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/eglot.el b/eglot.el
index 635ca26..e33e540 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1,12 +1,13 @@
 ;;; eglot.el --- Client for Language Server Protocol (LSP) servers  -*- 
lexical-binding: t; -*-
 
-;; Copyright (C) 2017  João Távora
+;; Copyright (C) 2003-2018 Free Software Foundation, Inc.
 
 ;; Version: 0.1
-;; Author: João Távora
-;; Url: https://github.com/joaotavora/eglot
+;; Author: João Távora 
+;; Maintainer: João Távora 
+;; URL: https://github.com/joaotavora/eglot
 ;; Keywords: convenience, languages
-;; Package-Requires: ((emacs "26.1"))
+;; Package-Requires: ((emacs "26.1") (json-mode "1.6.0"))
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by



[elpa] externals/eglot d0b7773 117/139: Reduce log chatter

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit d0b777334941075d8c6ef1d28d256272973f33f0
Author: João Távora 
Commit: João Távora 

Reduce log chatter

* eglot.el (eglot--process-sentinel, eglot--request): Use
eglot--log-event.
(eglot--log-event): Print "message" if type unknown.
(eglot--debug, eglot--log): Remove.
(eglot--server-window/logMessage, eglot--server-telemetry/event):
Make noops.
(eglot--call-deferred): Also reduce chatter here.
---
 eglot.el | 48 
 1 file changed, 16 insertions(+), 32 deletions(-)

diff --git a/eglot.el b/eglot.el
index 8b8d712..d1e4d15 100644
--- a/eglot.el
+++ b/eglot.el
@@ -341,7 +341,7 @@ INTERACTIVE is t if called interactively."
 
 (defun eglot--process-sentinel (proc change)
   "Called when PROC undergoes CHANGE."
-  (eglot--debug "(sentinel) Process state changed to %s" change)
+  (eglot--log-event proc `(:message "Process state changed" :change ,change))
   (when (not (process-live-p proc))
 ;; Cancel outstanding timers
 (maphash (lambda (_id triplet)
@@ -474,8 +474,7 @@ is a symbol saying if this is a client or server 
originated."
(subtype (cond ((and method id)   'request)
   (method'notification)
   (id'reply)
-  ;; pyls keeps on sending these
-  (t 'unexpected-thingy)))
+  (t 'message)))
(type
 (format "%s-%s" (or type :internal) subtype)))
   (goto-char (point-max))
@@ -553,7 +552,7 @@ is a symbol saying if this is a client or server 
originated."
 
 (defun eglot--call-deferred (proc)
   "Call PROC's deferred actions, who may again defer themselves."
-  (let ((actions (hash-table-values (eglot--deferred-actions proc
+  (when-let ((actions (hash-table-values (eglot--deferred-actions proc
 (eglot--log-event proc `(:running-deferred ,(length actions)))
 (mapc #'funcall (mapcar #'car actions
 
@@ -619,16 +618,15 @@ timeout keeps counting."
 ;; Really run it
 ;;
 (puthash id
- (list (or success-fn (eglot--lambda (&rest result-body)
-(eglot--debug
- "Request %s, id=%s replied to with 
result=%s"
- method id result-body)))
-   (or error-fn (eglot--lambda
-(&key code message &allow-other-keys)
-  (setf (eglot--status proc) `(,message t))
-  (eglot--warn
-   "Request %s, id=%s errored with code=%s: %s"
-   method id code message)))
+ (list (or success-fn
+   (eglot--lambda (&rest _ignored)
+ (eglot--log-event
+  proc (eglot--obj :message "success ignored" :id 
id
+   (or error-fn
+   (eglot--lambda (&key code message &allow-other-keys)
+ (setf (eglot--status proc) `(,message t))
+ proc (eglot--obj :message "error ignored, status set"
+  :id id :error code)))
(funcall make-timeout))
  (eglot--pending-continuations proc))
 (eglot--process-send proc (eglot--obj :jsonrpc "2.0"
@@ -680,12 +678,6 @@ DEFERRED is passed to `eglot--request', which see."
 
 ;;; Helpers
 ;;;
-(defun eglot--debug (format &rest args)
-  "Debug message FORMAT with ARGS."
-  (display-warning 'eglot
-   (apply #'format format args)
-   :debug))
-
 (defun eglot--error (format &rest args)
   "Error out with FORMAT with ARGS."
   (error (apply #'format format args)))
@@ -694,10 +686,6 @@ DEFERRED is passed to `eglot--request', which see."
   "Message out with FORMAT with ARGS."
   (message (concat "[eglot] " (apply #'format format args
 
-(defun eglot--log (format &rest args)
-  "Log out with FORMAT with ARGS."
-  (message (concat "[eglot-log] " (apply #'format format args
-
 (defun eglot--warn (format &rest args)
   "Warning message with FORMAT and ARGS."
   (apply #'eglot--message (concat "(warning) " format) args)
@@ -954,15 +942,11 @@ called interactively."
   :error (eglot--obj :code -32800
  :message "User cancelled"))
 
-(cl-defun eglot--server-window/logMessage (_process &key type message)
-  "Handle notification window/logMessage"
-  (eglot--log (propertize "Server reports (type=%s): %s"
-  'face (if (<= type 1) 'error))
-  type message))
+(cl-defun eglot--server-window/logMessage (_proc &key _type _message)
+  "Handle notification window/logMessage") ;; noop, use events buffer
 
-

[elpa] externals/eglot 5ce9ab0 106/139: Call eglot-eldoc-function after completion finishes

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 5ce9ab01d609aff1a5b3d90d0d772dbf709ca6c1
Author: João Távora 
Commit: João Távora 

Call eglot-eldoc-function after completion finishes

* eglot.el (eglot-completion-at-point): Call
eglot-eldoc-function after completion finishes.
---
 eglot.el | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 0795bc3..d5eae03 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1292,7 +1292,9 @@ DUMMY is ignored"
(lambda (items) (sort items (lambda (a b)
  (string-lessp
   (get-text-property 0 :sortText a)
-  (get-text-property 0 :sortText b)
+  (get-text-property 0 :sortText b)
+   :exit-function
+   (lambda (_string _status) (eglot-eldoc-function))
 
 (defvar eglot--highlights nil "Overlays for textDocument/documentHighlight.")
 



[elpa] externals/eglot d40f9ac 094/139: Half-decent imenu support via textDocument/documentSymbol

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit d40f9ac8af850b95868bf810dd67b3c5009bf598
Author: João Távora 
Commit: João Távora 

Half-decent imenu support via textDocument/documentSymbol

* README.md: Update capability

* eglot.el (eglot--lsp-position-to-point): New function.
(eglot--managed-mode): Handle imenu-create-index-function.
(eglot--server-textDocument/publishDiagnostics): Use
eglot--lsp-position-to-point.
(eglot-imenu): New function.
(eglot--client-capabilities): Capable of documentSymbol.
---
 README.md |  2 +-
 eglot.el  | 96 ---
 2 files changed, 62 insertions(+), 36 deletions(-)

diff --git a/README.md b/README.md
index 611839b..fef2d16 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ server. To skip the guess and always be prompted use `C-u M-x 
eglot`.
 - [ ] completionItem/resolve
 - [x] textDocument/definition
 - [ ] textDocument/documentHighlight
-- [ ] textDocument/documentSymbol
+- [x] textDocument/documentSymbol
 - [ ] textDocument/executeCommand
 - [ ] textDocument/format
 - [x] textDocument/hover
diff --git a/eglot.el b/eglot.el
index 7cc3756..d7ea329 100644
--- a/eglot.el
+++ b/eglot.el
@@ -193,10 +193,11 @@ CONTACT is as `eglot--contact'.  Returns a process 
object."
 :willSave t
 :willSaveWaitUntil :json-false
 :didSave t)
-  :completion `(:dynamicRegistration :json-false)
-  :hover  `(:dynamicRegistration :json-false)
-  :references `(:dynamicRegistration :json-false)
-  :definition `(:dynamicRegistration :json-false)
+  :completion `(:dynamicRegistration :json-false)
+  :hover  `(:dynamicRegistration :json-false)
+  :references `(:dynamicRegistration :json-false)
+  :definition `(:dynamicRegistration :json-false)
+  :documentSymbol `(:dynamicRegistration :json-false)
   :publishDiagnostics `(:relatedInformation :json-false))
:experimental (eglot--obj)))
 
@@ -703,6 +704,17 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (- (goto-char (or pos (point)))
(line-beginning-position)
 
+(defun eglot--lsp-position-to-point (pos-plist)
+  "Convert LSP position POS-PLIST to Emacs point."
+  (save-excursion (goto-char (point-min))
+  (forward-line (plist-get pos-plist :line))
+  (forward-char
+   (min (plist-get pos-plist :character)
+(- (line-end-position)
+   (line-beginning-position
+  (point)))
+
+
 (defun eglot--mapply (fun seq)
   "Apply FUN to every element of SEQ."
   (mapcar (lambda (e) (apply fun e)) seq))
@@ -766,6 +778,7 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t)
 (add-function :before-until (local 'eldoc-documentation-function)
   #'eglot-eldoc-function)
+(advice-add imenu-create-index-function :around #'eglot-imenu)
 (flymake-mode 1)
 (eldoc-mode 1))
(t
@@ -779,7 +792,8 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (remove-hook 'xref-backend-functions 'eglot-xref-backend t)
 (remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
 (remove-function (local 'eldoc-documentation-function)
- #'eglot-eldoc-function
+ #'eglot-eldoc-function)
+(advice-remove imenu-create-index-function #'eglot-imenu
 
 (define-minor-mode eglot-mode
   "Minor mode for all buffers managed by EGLOT in some way."  nil
@@ -956,36 +970,28 @@ running.  INTERACTIVE is t if called interactively."
 (cond
  (buffer
   (with-current-buffer buffer
-(cl-flet ((pos-at (pos-plist)
-  (save-excursion (goto-char (point-min))
-  (forward-line (plist-get pos-plist 
:line))
-  (forward-char
-   (min (plist-get pos-plist 
:character)
-(- (line-end-position)
-   (line-beginning-position
-  (point
-  (cl-loop for diag-spec across diagnostics
-   collect (cl-destructuring-bind (&key range severity _group
-_code source message)
-   diag-spec
- (cl-destructuring-bind (&key start end)
- range
-   (let* ((b

[elpa] externals/eglot 589e1ea 138/139: Remove an unused variable

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 589e1ea7a38c765ede6f3c17dae76d0502e96290
Author: João Távora 
Commit: João Távora 

Remove an unused variable

* eglot.el (eglot--expect-carriage-return): Get rid of this.
---
 eglot.el | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/eglot.el b/eglot.el
index eab7ce7..9b0f290 100644
--- a/eglot.el
+++ b/eglot.el
@@ -532,8 +532,6 @@ is a symbol saying if this is a client or server 
originated."
   (eglot--call-deferred proc)
   (force-mode-line-update t
 
-(defvar eglot--expect-carriage-return nil)
-
 (defun eglot--process-send (proc message)
   "Send MESSAGE to PROC (ID is optional)."
   (let ((json (json-encode message)))
@@ -542,7 +540,7 @@ is a symbol saying if this is a client or server 
originated."
   json))
 (eglot--log-event proc message 'client)))
 
-(defvar eglot--next-request-id 0)
+(defvar eglot--next-request-id 0 "ID for next request.")
 
 (defun eglot--next-request-id ()
   "Compute the next id for a client request."



[elpa] externals/eglot c7b9002 116/139: Only call deferred actions after a full message has been received

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit c7b90028bcdc52001849da5355ce48e03caca0f7
Author: João Távora 
Commit: João Távora 

Only call deferred actions after a full message has been received

Otherwise it can be quite wasteful.

* eglot.el (eglot--process-filter): Don't eglot--call-deferred here.
(eglot--process-receive): Do it here.
---
 eglot.el | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index d49367b..8b8d712 100644
--- a/eglot.el
+++ b/eglot.el
@@ -380,6 +380,7 @@ INTERACTIVE is t if called interactively."
   "(sentinel) Not auto-reconnecting, last one didn't last long."
   change)))
   (delete-process proc
+
 (defun eglot--process-filter (proc string)
   "Called when new data STRING has arrived for PROC."
   (when (buffer-live-p (process-buffer proc))
@@ -441,8 +442,7 @@ INTERACTIVE is t if called interactively."
   (throw done 
:waiting-for-more-bytes-in-this-message
   ;; Saved parsing state for next visit to this filter
   ;;
-  (setf (eglot--expected-bytes proc) expected-bytes
-(eglot--call-deferred proc)))
+  (setf (eglot--expected-bytes proc) expected-bytes))
 
 (defun eglot-events-buffer (process &optional interactive)
   "Display events buffer for current LSP connection PROCESS.
@@ -522,6 +522,7 @@ is a symbol saying if this is a client or server 
originated."
  (funcall (cl-first continuations) res)
   (id
(eglot--warn "Ooops no continuation for id %s" id)))
+(eglot--call-deferred proc)
 (force-mode-line-update t)))
 
 (defvar eglot--expect-carriage-return nil)



[elpa] externals/eglot 889ef20 085/139: Tweak the async request engine.

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 889ef20069d7d6511ce7f8f5b13928f3e7100eb5
Author: João Távora 
Commit: João Távora 

Tweak the async request engine.

* eglot.el (eglot--request): Return the continuation id.
(eglot--lambda): Move up in the file.
(eglot--sync-request): Use a catch-tag.
---
 eglot.el | 44 ++--
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/eglot.el b/eglot.el
index 068e2ca..3bed8d9 100644
--- a/eglot.el
+++ b/eglot.el
@@ -593,7 +593,9 @@ is a symbol saying if this is a client or server 
originated."
   method
   params
   &key success-fn error-fn timeout-fn (async-p t))
-  "Make a request to PROCESS, expecting a reply."
+  "Make a request to PROCESS, expecting a reply.
+Return the ID of this request, unless ASYNC-P is nil, in which
+case never returns locally."
   (let* ((id (eglot--next-request-id))
  (timeout-fn
   (or timeout-fn
@@ -658,22 +660,34 @@ is a symbol saying if this is a client or server 
originated."
 (when (memq timeout-timer timer-list)
   (eglot--message
"(request) Last-change cancelling timer for continuation %s" id)
-  (cancel-timer timeout-timer
+  (cancel-timer timeout-timer))
+;; Finally, return the id.
+id))
+
+(cl-defmacro eglot--lambda (cl-lambda-list &body body)
+  (declare (indent 1) (debug (sexp &rest form)))
+  `(cl-function
+(lambda ,cl-lambda-list
+  ,@body)))
 
 (defun eglot--sync-request (proc method params)
   "Like `eglot--request' for PROC, METHOD and PARAMS, but synchronous.
 Meaning only return locally if successful, otherwise exit non-locally."
   (let* ((timeout-error-sym (cl-gensym))
- (retval (eglot--request proc method params
- :success-fn (lambda (&rest args)
-   (if (vectorp (car args))
-   (car args)
- args))
- :error-fn (cl-function
-(lambda (&key code message 
&allow-other-keys)
-  (eglot--error "Oops: %s: %s" 
code message)))
- :timeout-fn (lambda () timeout-error-sym)
- :async-p nil)))
+ (catch-tag (make-symbol "eglot--sync-request-catch-tag"))
+ (retval
+  (catch catch-tag
+(eglot--request proc method params
+:success-fn (lambda (&rest args)
+  (throw catch-tag (if (vectorp (car 
args))
+   (car args)
+ args)))
+:error-fn (eglot--lambda
+  (&key code message &allow-other-keys)
+(eglot--error "Oops: %s: %s" code 
message))
+:timeout-fn (lambda ()
+  (throw catch-tag timeout-error-sym))
+:async-p nil
 ;; FIXME: There's maybe an emacs bug here. Because timeout-fn runs
 ;; in a timer, the better and obvious choice of throwing the erro
 ;; in the lambda is not quitting the `accept-process-output'
@@ -741,12 +755,6 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
   "Apply FUN to every element of SEQ."
   (mapcar (lambda (e) (apply fun e)) seq))
 
-(cl-defmacro eglot--lambda (cl-lambda-list &body body)
-  (declare (indent 1) (debug (sexp &rest form)))
-  `(cl-function
-(lambda ,cl-lambda-list
-  ,@body)))
-
 (defun eglot--path-to-uri (path)
   "Urify PATH."
   (url-hexify-string



[elpa] externals/eglot 54fc885 113/139: More RLS-specifics: update Flymake diags when indexing done

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 54fc8854b8e0782cb46c46b83af99ed6b65c2688
Author: João Távora 
Commit: João Távora 

More RLS-specifics: update Flymake diags when indexing done

RLS could/should report diagnostics for every opened file, even if
there aren't any problems. Because it doesn't, loop for every buffer
managed by the process and call eglot--current-flymake-report-fn

* eglot.el
(eglot--server-window/progress): Call eglot--current-flymake-report-fn
---
 eglot.el | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/eglot.el b/eglot.el
index f865c22..1ba5324 100644
--- a/eglot.el
+++ b/eglot.el
@@ -825,6 +825,9 @@ DEFERRED is passed to `eglot--request', which see."
   (or (and (null proc) cur)
   (and proc (eq proc cur))
 
+(defvar-local eglot--current-flymake-report-fn nil
+  "Current flymake report function for this buffer")
+
 (defun eglot--maybe-activate-editing-mode (&optional proc)
   "Maybe activate mode function `eglot--managed-mode'.
 If PROC is supplied, do it only if BUFFER is managed by it.  In
@@ -969,9 +972,6 @@ called interactively."
   "Handle notification telemetry/event"
   (eglot--log "Server telemetry: %s" any))
 
-(defvar-local eglot--current-flymake-report-fn nil
-  "Current flymake report function for this buffer")
-
 (defvar-local eglot--unreported-diagnostics nil
   "Unreported diagnostics for this buffer.")
 
@@ -1479,7 +1479,13 @@ Proceed? "
 (cl-defun eglot--server-window/progress
 (process &key id done title message &allow-other-keys)
   "Handle notification window/progress"
-  (setf (eglot--spinner process) (list id title done message)))
+  (setf (eglot--spinner process) (list id title done message))
+  (when (and (equal "Indexing" title) done)
+(dolist (buffer (buffer-list))
+  (with-current-buffer buffer
+(when (eglot--buffer-managed-p process)
+  (funcall (or eglot--current-flymake-report-fn #'ignore)
+   eglot--unreported-diagnostics))
 
 (provide 'eglot)
 ;;; eglot.el ends here



[elpa] externals/eglot 1add335 078/139: Workaround two suspected Emacs bugs

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 1add3354d5c46bae530565b77636b8f11207f40f
Author: João Távora 
Commit: João Távora 

Workaround two suspected Emacs bugs

* eglot.el (eglot--process-filter): Use a proper unique tag. Use
unwind-protect.
(eglot--sync-request): Rework.
(eglot--server-client/registerCapability): Use a proper done tag.
---
 eglot.el | 135 ++-
 1 file changed, 72 insertions(+), 63 deletions(-)

diff --git a/eglot.el b/eglot.el
index 321307d..1d72b4c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -415,7 +415,8 @@ INTERACTIVE is t if called interactively."
   (when (buffer-live-p (process-buffer proc))
 (with-current-buffer (process-buffer proc)
   (let ((inhibit-read-only t)
-(expected-bytes (eglot--expected-bytes proc)))
+(expected-bytes (eglot--expected-bytes proc))
+(done (make-symbol "eglot--process-filter-done-tag")))
 ;; Insert the text, advancing the process marker.
 ;;
 (save-excursion
@@ -424,51 +425,52 @@ INTERACTIVE is t if called interactively."
   (set-marker (process-mark proc) (point)))
 ;; Loop (more than one message might have arrived)
 ;;
-(catch 'done
-  (while t
-(cond ((not expected-bytes)
-   ;; Starting a new message
-   ;;
-   (setq expected-bytes
- (and (search-forward-regexp
-   "\\(?:.*: .*\r\n\\)*Content-Length: \
+(unwind-protect
+(catch done
+  (while t
+(cond ((not expected-bytes)
+   ;; Starting a new message
+   ;;
+   (setq expected-bytes
+ (and (search-forward-regexp
+   "\\(?:.*: .*\r\n\\)*Content-Length: \
 *\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
-   (+ (point) 100)
-   t)
-  (string-to-number (match-string 1
-   (unless expected-bytes
- (throw 'done :waiting-for-new-message)))
-  (t
-   ;; Attempt to complete a message body
-   ;;
-   (let ((available-bytes (- (position-bytes (process-mark 
proc))
- (position-bytes (point)
- (cond
-  ((>= available-bytes
-   expected-bytes)
-   (let* ((message-end (byte-to-position
-(+ (position-bytes (point))
-   expected-bytes
- (unwind-protect
- (save-restriction
-   (narrow-to-region (point) message-end)
-   (let* ((json-object-type 'plist)
-  (json-message (json-read)))
- ;; Process content in another buffer,
- ;; shielding buffer from tamper
- ;;
- (with-temp-buffer
-   (eglot--process-receive proc 
json-message
-   (goto-char message-end)
-   (delete-region (point-min) (point))
-   (setq expected-bytes nil
+   (+ (point) 100)
+   t)
+  (string-to-number (match-string 1
+   (unless expected-bytes
+ (throw done :waiting-for-new-message)))
   (t
-   ;; Message is still incomplete
+   ;; Attempt to complete a message body
;;
-   (throw 'done 
:waiting-for-more-bytes-in-this-message
-;; Saved parsing state for next visit to this filter
-;;
-(setf (eglot--expected-bytes proc) expected-bytes)
+   (let ((available-bytes (- (position-bytes (process-mark 
proc))
+ (position-bytes (point)
+ (cond
+  ((>= available-bytes
+   expected-bytes)
+   (let* ((message-end (byte-to-position
+(+ (position-bytes (point))
+   expected-bytes
+ (unwind-protect
+ (save-restriction
+   (narrow-to-region (point) message-end)
+   (let* 

[elpa] externals/eglot 8160cd4 071/139: Handle dynamic registration in general (but nothing specific yet)

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 8160cd41fd7c0ff1ce436da2d1100f14f7c33efe
Author: João Távora 
Commit: João Távora 

Handle dynamic registration in general (but nothing specific yet)

* eglot.el (eglot--server-client/registerCapability): Implement.
(eglot--register-workspace/didChangeWatchedFiles): Dummy registrator.
---
 eglot.el | 41 -
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/eglot.el b/eglot.el
index 68fe3e2..2b3f270 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1003,15 +1003,28 @@ running.  INTERACTIVE is t if called interactively."
 (cl-defun eglot--server-client/registerCapability
 (proc &key id registrations)
   "Handle notification client/registerCapability"
-  (mapc (lambda (reg)
-  (apply (cl-function
-  (lambda (&key _id _method _registerOptions)
-;;; TODO: handle this
-))
- reg))
-registrations)
-  (eglot--reply proc id :error (eglot--obj :code -32601
-   :message "sorry :-(")))
+  (catch 'done
+(mapc
+ (lambda (reg)
+   (apply
+(cl-function
+ (lambda (&key id method registerOptions)
+   (pcase-let*
+   ((handler-sym (intern (concat "eglot--register-"
+ method)))
+(`(,ok ,message)
+ (and (functionp handler-sym)
+  (apply handler-sym proc :id id registerOptions
+ (unless ok
+   (throw
+'done
+(eglot--reply proc id
+  :error (eglot--obj
+  :code -32601
+  :message (or message "sorry :-("
+reg))
+ registrations)
+(eglot--reply proc id :result (eglot--obj :message "OK"
 
 (defvar eglot--recent-before-changes nil
   "List of recent changes as collected by `eglot--before-change'.")
@@ -1177,6 +1190,16 @@ Calls REPORT-FN maybe if server publishes diagnostics in 
time."
   (eglot--signal-textDocument/didChange))
 
 
+;;; Dynamic registration
+;;;
+(cl-defun eglot--register-workspace/didChangeWatchedFiles
+(_proc &key _id _watchers)
+  "Handle dynamic registration of workspace/didChangeWatchedFiles"
+  ;; TODO: file-notify-add-watch and
+  ;; file-notify-rm-watch can probably handle this
+  (list nil "Sorry, can't do this yet"))
+
+
 ;;; Rust-specific
 ;;;
 (cl-defun eglot--server-window/progress



[elpa] externals/eglot a199c8e 070/139: Honour textDocumentSync

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit a199c8ef754434b6210cbd56f7dcef5f04e686c2
Author: João Távora 
Commit: João Távora 

Honour textDocumentSync

* eglot.el (eglot--signal-textDocument/didChange): Honour textDocumentSync
---
 eglot.el | 72 +---
 1 file changed, 37 insertions(+), 35 deletions(-)

diff --git a/eglot.el b/eglot.el
index 5701422..68fe3e2 100644
--- a/eglot.el
+++ b/eglot.el
@@ -251,7 +251,9 @@ SUCCESS-FN with no args if all goes well."
 (eglot--request
  proc
  :initialize
- (eglot--obj :processId  (emacs-pid)
+ (eglot--obj :processId (unless (eq (process-type proc)
+'network)
+  (emacs-pid))
  :rootUri  (eglot--uri
 (expand-file-name (car (project-roots
 (project-current)
@@ -1070,44 +1072,44 @@ Records START, END and PRE-CHANGE-LENGTH locally."
   "Send textDocument/didChange to server."
   (when (and eglot--recent-before-changes
  eglot--recent-after-changes)
-(save-excursion
+(let* ((proc (eglot--current-process-or-lose))
+   (sync-kind (plist-get (eglot--capabilities proc) 
:textDocumentSync)))
   (save-restriction
 (widen)
-(if (/= (length eglot--recent-before-changes)
-(length eglot--recent-after-changes))
-(eglot--notify
- (eglot--current-process-or-lose)
- :textDocument/didChange
- (eglot--obj
-  :textDocument 
(eglot--current-buffer-VersionedTextDocumentIdentifier)
-  :contentChanges
-  (vector
-   (eglot--obj
-:text (buffer-substring-no-properties (point-min) 
(point-max))
-  (let ((combined (cl-mapcar 'append
- eglot--recent-before-changes
- eglot--recent-after-changes)))
-(eglot--notify
- (eglot--current-process-or-lose)
- :textDocument/didChange
- (eglot--obj
-  :textDocument 
(eglot--current-buffer-VersionedTextDocumentIdentifier)
-  :contentChanges
+(unless (or (not sync-kind)
+(eq sync-kind 0))
+  (eglot--notify
+   proc
+   :textDocument/didChange
+   (eglot--obj
+:textDocument
+(eglot--current-buffer-VersionedTextDocumentIdentifier)
+:contentChanges
+(if (or (eq sync-kind 1)
+(/= (length eglot--recent-before-changes)
+(length eglot--recent-after-changes)))
+(vector
+ (eglot--obj
+  :text (buffer-substring-no-properties (point-min) 
(point-max
   (apply
#'vector
-   (mapcar (pcase-lambda (`(,before-start-position
-,before-end-position
-,after-start
-,after-end
-,len))
- (eglot--obj
-  :range
-  (eglot--obj
-   :start before-start-position
-   :end before-end-position)
-  :rangeLength len
-  :text (buffer-substring-no-properties after-start 
after-end)))
-   (reverse combined))
+   (mapcar
+(pcase-lambda (`(,before-start-position
+ ,before-end-position
+ ,after-start
+ ,after-end
+ ,len))
+  (eglot--obj
+   :range
+   (eglot--obj
+:start before-start-position
+:end before-end-position)
+   :rangeLength len
+   :text (buffer-substring-no-properties after-start 
after-end)))
+(reverse
+ (cl-mapcar 'append
+eglot--recent-before-changes
+eglot--recent-after-changes)))
   (setq eglot--recent-before-changes nil
 eglot--recent-after-changes nil))
 



[elpa] externals/eglot 56cf02d 126/139: Rework autoreconnection logic

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 56cf02da4e832e6f38ff9aa9a3fffb1002710b8b
Author: João Távora 
Commit: João Távora 

Rework autoreconnection logic

Can't be a global var, has to be a per process thing.

* eglot.el (eglot-autoreconnect): New defcustom
(eglot--inhibit-autoreconnect): Renamed from eglot--inhibit-autoreconnect
(eglot--connect): Run autoreconnect timer here.
(eglot--inhibit-auto-reconnect): Removed.
(eglot--process-sentinel): Don't run timer here. Rework.
(eglot, eglot-reconnect): Pass INTERACTIVE to eglot--connect.
---
 eglot.el | 57 +++--
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/eglot.el b/eglot.el
index 3b3aada..aabaf54 100644
--- a/eglot.el
+++ b/eglot.el
@@ -59,9 +59,19 @@
   "Face for package-name in EGLOT's mode line.")
 
 (defcustom eglot-request-timeout 10
-  "How many seconds to way for a reply from the server."
+  "How many seconds to wait for a reply from the server."
   :type :integer)
 
+(defcustom eglot-autoreconnect 3
+  "Control EGLOT's ability to reconnect automatically.
+If t, always reconnect automatically (not recommended).  If nil,
+never reconnect automatically after unexpected server shutdowns,
+crashes or network failures.  A positive integer number says to
+only autoreconnect if the previous successful connection attempt
+lasted more than that many seconds."
+  :type '(choice (boolean :tag "Whether to inhibit autoreconnection")
+ (integer :tag "Number of seconds")))
+
 
 ;;; Process management
 (defvar eglot--processes-by-project (make-hash-table :test #'equal)
@@ -129,6 +139,9 @@ A list (ID WHAT DONE-P).")
   "Status as declared by the server.
 A list (WHAT SERIOUS-P).")
 
+(eglot--define-process-var eglot--inhibit-autoreconnect eglot-autoreconnect
+  "If non-nil, don't autoreconnect on unexpected quit.")
+
 (eglot--define-process-var eglot--contact nil
   "Method used to contact a server.
 Either a list of strings (a shell command and arguments), or a
@@ -206,8 +219,9 @@ 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)
-  "Connect for PROJECT, MANAGED-MAJOR-MODE, SHORT-NAME and CONTACT."
+(defun eglot--connect (project managed-major-mode short-name contact 
interactive)
+  "Connect for PROJECT, MANAGED-MAJOR-MODE, SHORT-NAME and CONTACT.
+INTERACTIVE is t if inside interactive call."
   (let* ((proc (eglot--make-process short-name managed-major-mode contact))
  (buffer (process-buffer proc)))
 (setf (eglot--contact proc) contact
@@ -215,6 +229,15 @@ CONTACT is as `eglot--contact'.  Returns a process object."
   (eglot--major-mode proc) managed-major-mode)
 (with-current-buffer buffer
   (let ((inhibit-read-only t))
+(setf (eglot--inhibit-autoreconnect proc)
+  (cond
+   ((booleanp eglot-autoreconnect) (not eglot-autoreconnect))
+   (interactive nil)
+   ((cl-plusp eglot-autoreconnect)
+(run-with-timer eglot-autoreconnect nil
+(lambda ()
+  (setf (eglot--inhibit-autoreconnect proc)
+(null eglot-autoreconnect)))
 (setf (eglot--short-name proc) short-name)
 (push proc (gethash project eglot--processes-by-project))
 (erase-buffer)
@@ -317,7 +340,8 @@ INTERACTIVE is t if called interactively."
 (let ((proc (eglot--connect project
 managed-major-mode
 short-name
-command)))
+command
+interactive)))
   (eglot--message "Connected! Process `%s' now \
 managing `%s' buffers in project `%s'."
   proc managed-major-mode short-name))
@@ -331,12 +355,10 @@ INTERACTIVE is t if called interactively."
   (eglot--connect (eglot--project process)
   (eglot--major-mode process)
   (eglot--short-name process)
-  (eglot--contact process))
+  (eglot--contact process)
+  interactive)
   (eglot--message "Reconnected!"))
 
-(defvar eglot--inhibit-auto-reconnect nil
-  "If non-nil, don't autoreconnect on unexpected quit.")
-
 (defun eglot--process-sentinel (proc change)
   "Called when PROC undergoes CHANGE."
   (eglot--log-event proc `(:message "Process state changed" :change ,change))
@@ -364,22 +386,13 @@ INTERACTIVE is t if called interactively."
   (setf (gethash (eglot--project proc) eglot--processes-by-project)
 (delq proc
   (gethash (eglot--project proc) eglot--processes-by-project)))
-  (cond ((eglot--

[elpa] externals/eglot 764347d 128/139: New command eglot-help-at-point and a README update

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 764347d24c9894b0de3a7aca2a7ea5b2d691c4e2
Author: João Távora 
Commit: João Távora 

New command eglot-help-at-point and a README update

* README.md (Commands and keybindings): New section.

* eglot.el (eglot-eldoc-function): Use eglot--hover-info.
Don't care about kind in highlightSymbol
(eglot--hover-info): New helper.
(eglot-help-at-point): New command.
---
 README.md | 25 +
 eglot.el  | 41 -
 2 files changed, 53 insertions(+), 13 deletions(-)

diff --git a/README.md b/README.md
index 8a94466..a3789a4 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,31 @@ 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`.
 
+# Commands and keybindings
+
+Here's a summary of available commands:
+
+- `M-x eglot-reconnect` reconnects to the server
+
+- `M-x eglot-rename` asks the server to rename the symbol at point
+
+- `M-x eglot-help-at-point` asks the server for help for symbol at
+  point. Currently this is what `eldoc-mode` displays in the echo
+  area.
+
+- `M-x eglot-events-buffer` jumps to the events buffer for debugging
+  communication with the server.
+
+There are *no keybindings* specific to Eglot, but you can bind stuff
+in `eglot-mode-map`, which is active as long as Eglot is managing a
+file in your project. The commands don't need to be eglot-specific,
+either:
+
+```
+(define-key eglot-mode-map (kbd "C-c h") 'eglot-help-at-point)
+(define-key eglot-mode-map (kbd "") 'xref-find-definitions)
+```
+
 # Supported Protocol features
 
 ## General
diff --git a/eglot.el b/eglot.el
index c8612cf..13f6f61 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1314,6 +1314,28 @@ DUMMY is ignored"
 
 (defvar eglot--highlights nil "Overlays for textDocument/documentHighlight.")
 
+(defun eglot--hover-info (contents &optional range)
+  (concat (and range
+   (eglot--with-lsp-range (beg end) range
+ (concat (buffer-substring beg end)  ": ")))
+  (mapconcat #'eglot--format-markup
+ (append
+  (cond ((vectorp contents)
+ contents)
+(contents
+ (list contents "\n")))
+
+(defun eglot-help-at-point ()
+  "Request \"hover\" information for the thing at point."
+  (interactive)
+  (cl-destructuring-bind (&key contents range)
+  (eglot--request (eglot--current-process-or-lose) :textDocument/hover
+  (eglot--TextDocumentPositionParams))
+(when (seq-empty-p contents) (eglot--error "No hover info here"))
+(with-help-window "*eglot help*"
+  (with-current-buffer standard-output
+(insert (eglot--hover-info contents range))
+
 (defun eglot-eldoc-function ()
   "EGLOT's `eldoc-documentation-function' function."
   (let ((buffer (current-buffer))
@@ -1325,17 +1347,7 @@ DUMMY is ignored"
:success-fn (eglot--lambda (&key contents range)
  (when (get-buffer-window buffer)
(with-current-buffer buffer
- (eldoc-message
-  (concat
-   (and range
-(eglot--with-lsp-range (beg end) range
-  (concat (buffer-substring beg end)  ": ")))
-   (mapconcat #'eglot--format-markup
-  (append
-   (cond ((vectorp contents)
-  contents)
- (contents
-  (list contents "\n"))
+ (eldoc-message (eglot--hover-info contents range)
:deferred :textDocument/hover))
 (when (eglot--server-capable :documentHighlightProvider)
   (eglot--async-request
@@ -1346,12 +1358,11 @@ DUMMY is ignored"
(when (get-buffer-window buffer)
  (with-current-buffer buffer
(eglot--mapply
-(eglot--lambda (&key range kind)
+(eglot--lambda (&key range _kind)
   (eglot--with-lsp-range (beg end) range
 (let ((ov (make-overlay beg end)))
   (overlay-put ov 'face 'highlight)
   (overlay-put ov 'evaporate t)
-  (overlay-put ov :kind kind)
   ov)))
 highlights)
:deferred :textDocument/documentHighlight)))
@@ -1482,3 +1493,7 @@ Proceed? "
 
 (provide 'eglot)

[elpa] externals/eglot 9bf3166 136/139: Don't define a menu if nothing to show there for now

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 9bf31667f1d1a4dfea61a96e44f658e70d9ebd85
Author: João Távora 
Commit: João Távora 

Don't define a menu if nothing to show there for now

* eglot.el (eglot-menu): Remove it.
(eglot--mode-line-format): Don't define a menu.
---
 eglot.el | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/eglot.el b/eglot.el
index 4477242..6dc2213 100644
--- a/eglot.el
+++ b/eglot.el
@@ -843,10 +843,6 @@ that case, also signal textDocument/didOpen."
 
 ;;; Mode-line, menu and other sugar
 ;;;
-(defvar eglot-menu)
-
-(easy-menu-define eglot-menu eglot-mode-map "EGLOT" `("EGLOT" ))
-
 (defvar eglot--mode-line-format `(:eval (eglot--mode-line-format)))
 
 (put 'eglot--mode-line-format 'risky-local-variable t)
@@ -881,8 +877,7 @@ Uses THING, FACE, DEFS and PREPEND."
(`(,_id ,doing ,done-p ,detail) (and proc (eglot--spinner 
proc)))
(`(,status ,serious-p) (and proc (eglot--status proc
 (append
- `(,(eglot--mode-line-props "eglot" 'eglot-mode-line
-'((down-mouse-1 eglot-menu "pop up EGLOT 
menu"
+ `(,(eglot--mode-line-props "eglot" 'eglot-mode-line nil))
  (when name
`(":" ,(eglot--mode-line-props
name 'eglot-mode-line



[elpa] externals/eglot be52e1e 037/139: Rework connection restarting again

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit be52e1ee6a39c6f775a308c229c7a75ac28485bd
Author: João Távora 
Commit: João Távora 

Rework connection restarting again

Quitting a process removes it from the project.

* eglot.el (eglot-editing-mode,eglot-mode): Forward declare.
(eglot--project): New process-local var.
(eglot--connect): Takes a project.
(eglot-new-process): Rework.
(eglot--sentinel): Remove proc from eglot--processes-by-project.
---
 eglot.el | 85 ++--
 1 file changed, 51 insertions(+), 34 deletions(-)

diff --git a/eglot.el b/eglot.el
index b9aa94c..12e7fef 100644
--- a/eglot.el
+++ b/eglot.el
@@ -44,6 +44,9 @@
 
 (defvar eglot--processes-by-project (make-hash-table :test #'equal))
 
+(defvar eglot-editing-mode) ; forward decl
+(defvar eglot-mode) ; forward decl
+
 (defvar eglot--special-buffer-process nil
   "Current buffer's eglot process.")
 
@@ -103,6 +106,9 @@ after setting it."
 (eglot--define-process-var eglot--moribund nil
   "Non-nil if process is about to exit")
 
+(eglot--define-process-var eglot--project nil
+  "The project the process belongs to.")
+
 (eglot--define-process-var eglot--spinner `(nil nil t)
   "\"Spinner\" used by some servers.
 A list (ID WHAT DONE-P)." t)
@@ -134,12 +140,13 @@ Returns a process object."
   name)
 proc))
 
-(defun eglot--connect (short-name bootstrap-fn &optional success-fn)
-  "Make a connection with SHORT-NAME and BOOTSTRAP-FN.
+(defun eglot--connect (project short-name bootstrap-fn &optional success-fn)
+  "Make a connection with PROJECT, SHORT-NAME and BOOTSTRAP-FN.
 Call SUCCESS-FN with no args if all goes well."
   (let* ((proc (funcall bootstrap-fn short-name))
  (buffer (process-buffer proc)))
-(setf (eglot--bootstrap-fn proc) bootstrap-fn)
+(setf (eglot--bootstrap-fn proc) bootstrap-fn
+  (eglot--project proc) project)
 (with-current-buffer buffer
   (let ((inhibit-read-only t))
 (setf (eglot--short-name proc) short-name)
@@ -164,48 +171,57 @@ INTERACTIVE is t if called interactively."
   (interactive (list (eglot--current-process-or-lose) t))
   (when (process-live-p process)
 (eglot-quit-server process 'sync interactive))
-  (eglot--connect (eglot--short-name process)
-  (eglot--bootstrap-fn process)
-  (lambda ()
-(eglot--message "Reconnected"
+  (eglot--connect
+   (eglot--project process)
+   (eglot--short-name process)
+   (eglot--bootstrap-fn process)
+   (lambda ()
+ (eglot--message "Reconnected"
 
 (defun eglot-new-process (&optional interactive)
   "Start a new EGLOT process and initialize it.
 INTERACTIVE is t if called interactively."
   (interactive (list t))
   (let ((project (project-current)))
-(unless project (eglot--error "(new-process) Cannot work without a current 
project!"))
+(unless project (eglot--error
+ "(new-process) Cannot work without a current project!"))
 (let ((current-process (eglot--current-process))
   (command (let ((probe (cdr (assoc major-mode eglot-executables
  (unless probe
(eglot--error "Don't know how to start EGLOT for %s 
buffers"
  major-mode))
  probe)))
-  (cond ((and current-process
-  (process-live-p current-process))
- (eglot--message "(new-process) Reconnecting instead")
- (eglot-reconnect current-process interactive))
-(t
- (eglot--connect
-  (file-name-base
-   (directory-file-name
-(car (project-roots (project-current)
-  (lambda (name)
-(eglot-make-local-process
- name
- command))
-  (lambda ()
-(eglot--message "Connected")
-(dolist (buffer (buffer-list))
-  (with-current-buffer buffer
-(if (and buffer-file-name
- (cl-some
-  (lambda (root)
-(string-prefix-p
- (expand-file-name root)
- (expand-file-name buffer-file-name)))
-  (project-roots project)))
-(eglot--signalDidOpen)))
+  (cond
+   ((and current-process
+ (process-live-p current-process))
+(when (and
+   interactive
+   (y-or-n-p "[eglot] Live process found, reconnect instead? "))
+  (eglot-reconnect current-process interactive)))
+   (t
+(eglot--connect
+ project
+ (file-name-base
+  (directory-file-name
+   (car (project-roots (project-current)
+ (lambda (name)
+   

[elpa] externals/eglot fc6879f 084/139: Explain why didOpen on after-revert-hook is a bad idea

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit fc6879fc69dc0a2cfda6168ee65920efb4a770c1
Author: João Távora 
Commit: João Távora 

Explain why didOpen on after-revert-hook is a bad idea

The reason is that the global find-file-hook is called again, and that
already does the didOpen. Too many didOpen's would be bad.

* eglot.el (eglot--managed-mode): Remove commented lines.
---
 eglot.el | 2 --
 1 file changed, 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index 2ab4781..068e2ca 100644
--- a/eglot.el
+++ b/eglot.el
@@ -784,7 +784,6 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
 (add-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose nil t)
 (add-hook 'before-revert-hook 'eglot--signal-textDocument/didClose nil t)
-;;(add-hook 'after-revert-hook 'eglot--signal-textDocument/didOpen nil t)
 (add-hook 'before-save-hook 'eglot--signal-textDocument/willSave nil t)
 (add-hook 'after-save-hook 'eglot--signal-textDocument/didSave nil t)
 (add-hook 'xref-backend-functions 'eglot-xref-backend nil t)
@@ -796,7 +795,6 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (remove-hook 'before-change-functions 'eglot--before-change t)
 (remove-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose t)
 (remove-hook 'before-revert-hook 'eglot--signal-textDocument/didClose t)
-;; (remove-hook 'after-revert-hook 'eglot--signal-textDocument/didOpen t)
 (remove-hook 'before-save-hook 'eglot--signal-textDocument/willSave t)
 (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t)
 (remove-hook 'xref-backend-functions 'eglot-xref-backend t)



[elpa] externals/eglot d431d41 088/139: Fix bug in hover support

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit d431d4109918500ff9a99782b45d975709f1d6be
Author: João Távora 
Commit: João Távora 

Fix bug in hover support

* eldoc.el (eglot-eldoc-function): Use eglot--format-markup.
(subr-x): Require it.
(eglot--format-markup): Pacify byte-compiler.
---
 eglot.el | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index 8e92725..9d7b16d 100644
--- a/eglot.el
+++ b/eglot.el
@@ -34,6 +34,7 @@
 (require 'warnings)
 (require 'flymake)
 (require 'xref)
+(require 'subr-x)
 
 
 ;;; User tweakable stuff
@@ -763,7 +764,7 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
   "Format MARKUP according to LSP's spec."
   (cond ((stringp markup)
  (with-temp-buffer
-   (ignore-errors (funcall 'markdown-mode))
+   (ignore-errors (funcall (intern "markdown-mode"))) ;escape 
bytecompiler
(font-lock-ensure)
(insert markup)
(string-trim (buffer-string
@@ -1428,7 +1429,7 @@ DUMMY is ignored"
:position (eglot--pos-to-lsp-position))
   :success-fn (eglot--lambda (&key contents _range)
 (eldoc-message
- (mapconcat #'eglot--format
+ (mapconcat #'eglot--format-markup
 (if (vectorp contents)
 contents
   (list contents))



[elpa] externals/eglot 8a80fb7 105/139: Simplify `eglot-shutdown`

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 8a80fb7d5b93c92591958e9b08caafc302521de0
Author: João Távora 
Commit: João Távora 

Simplify `eglot-shutdown`

* eglot.el (eglot, eglot-reconnect)
(eglot--managed-mode): Call new eglot-shutdown.
(eglot-shutdown): Simplify.
(eglot--process-sentinel): Also call error functions.
(eglot--process-filter): Reindent.
---
 eglot.el | 146 +--
 1 file changed, 66 insertions(+), 80 deletions(-)

diff --git a/eglot.el b/eglot.el
index bed98ed..0795bc3 100644
--- a/eglot.el
+++ b/eglot.el
@@ -310,7 +310,7 @@ INTERACTIVE is t if called interactively."
(y-or-n-p "[eglot] Live process found, reconnect instead? "))
   (eglot-reconnect current-process interactive)
 (when (process-live-p current-process)
-  (eglot-shutdown current-process 'sync))
+  (eglot-shutdown current-process))
 (eglot--connect project
 managed-major-mode
 short-name
@@ -327,7 +327,7 @@ managing `%s' buffers in project `%s'."
 INTERACTIVE is t if called interactively."
   (interactive (list (eglot--current-process-or-lose) t))
   (when (process-live-p process)
-(eglot-shutdown process 'sync interactive))
+(eglot-shutdown process interactive))
   (eglot--connect (eglot--project process)
   (eglot--major-mode process)
   (eglot--short-name process)
@@ -341,13 +341,12 @@ INTERACTIVE is t if called interactively."
   "Called with PROCESS undergoes CHANGE."
   (eglot--debug "(sentinel) Process state changed to %s" change)
   (when (not (process-live-p process))
-;; Remember to cancel all timers
+;; Cancel timers and error any outstanding continuations
 ;;
-(maphash (lambda (id triplet)
-   (cl-destructuring-bind (_success _error timeout) triplet
- (eglot--message
-  "(sentinel) Cancelling timer for continuation %s" id)
- (cancel-timer timeout)))
+(maphash (lambda (_id triplet)
+   (cl-destructuring-bind (_success error timeout) triplet
+ (cancel-timer timeout)
+ (funcall error :code -1 :message (format "Server died"
  (eglot--pending-continuations process))
 ;; Turn off `eglot--managed-mode' where appropriate.
 ;;
@@ -400,46 +399,47 @@ INTERACTIVE is t if called interactively."
 (unwind-protect
 (catch done
   (while t
-(cond ((not expected-bytes)
-   ;; Starting a new message
-   ;;
-   (setq expected-bytes
- (and (search-forward-regexp
-   "\\(?:.*: .*\r\n\\)*Content-Length: \
+(cond
+ ((not expected-bytes)
+  ;; Starting a new message
+  ;;
+  (setq expected-bytes
+(and (search-forward-regexp
+  "\\(?:.*: .*\r\n\\)*Content-Length: \
 *\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
-   (+ (point) 100)
-   t)
-  (string-to-number (match-string 1
-   (unless expected-bytes
- (throw done :waiting-for-new-message)))
-  (t
-   ;; Attempt to complete a message body
-   ;;
-   (let ((available-bytes (- (position-bytes (process-mark 
proc))
- (position-bytes (point)
- (cond
-  ((>= available-bytes
-   expected-bytes)
-   (let* ((message-end (byte-to-position
-(+ (position-bytes (point))
-   expected-bytes
- (unwind-protect
- (save-restriction
-   (narrow-to-region (point) message-end)
-   (let* ((json-object-type 'plist)
-  (json-message (json-read)))
- ;; Process content in another buffer,
- ;; shielding buffer from tamper
- ;;
- (with-temp-buffer
-   (eglot--process-receive proc 
json-message
-   (goto-char message-end)
-   (delete-region (point-min) (point))
-   (setq expected-bytes nil
-  (t
-   ;; Message is still in

[elpa] externals/eglot 2b61a3b 048/139: Delete two useless forward declarations

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 2b61a3bf70d340c1f865cde91cc1228cdb13af1f
Author: João Távora 
Commit: João Távora 

Delete two useless forward declarations

* eglot.el (eglot-mode, eglot-editing-mode-map): Remove forward decls.
---
 eglot.el | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/eglot.el b/eglot.el
index bb0427a..f25c7bd 100644
--- a/eglot.el
+++ b/eglot.el
@@ -46,9 +46,6 @@
 (defvar eglot--processes-by-project (make-hash-table :test #'equal)
   "Keys are projects.  Values are lists of processes.")
 
-(defvar eglot-editing-mode) ; forward decl
-(defvar eglot-mode) ; forward decl
-
 (defvar-local eglot--special-buffer-process nil
   "Current buffer's eglot process.")
 
@@ -643,7 +640,8 @@ running.  INTERACTIVE is t if called interactively."
  (forward-char
   (min (plist-get pos-plist :character)
(- (line-end-position)
-  (line-beginning-position)))
+  (line-beginning-position
+ (point
   (cl-loop for diag-spec across diagnostics
collect (cl-destructuring-bind (&key range severity
 _code _source message)



[elpa] externals/eglot 79a2a1e 069/139: Be quite explicit about our lack of capabilities right now

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 79a2a1e12eb5ead6ee3419457607ab38647e1ac2
Author: João Távora 
Commit: João Távora 

Be quite explicit about our lack of capabilities right now

* eglot.el (eglot--client-capabilities): Spread out.
---
 eglot.el | 35 +--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index 8e39591..5701422 100644
--- a/eglot.el
+++ b/eglot.el
@@ -192,9 +192,40 @@ CONTACT is as `eglot--contact'.  Returns a process object."
 (defun eglot--client-capabilities ()
   "What the EGLOT LSP client supports."
   (eglot--obj
-   :workspace (eglot--obj)
+   :workspace(eglot--obj
+  :applyEdit nil
+  :workspaceEdit nil
+  :didChangeConfiguration nil
+  :didChangeWatchedFiles nil
+  :symbol nil
+  :executeCommand nil
+  :workspaceFolders nil
+  :configuration nil)
:textDocument (eglot--obj
-  :publishDiagnostics `(:relatedInformation nil
+  :synchronization (eglot--obj
+:dynamicRegistration :json-false
+:willSave t
+:willSaveWaitUntil :json-false
+:didSave t)
+  :completion nil
+  :hover nil
+  :signatureHelp nil
+  :references nil
+  :documentHighlight nil
+  :documentSymbol nil
+  :formatting nil
+  :rangeFormatting nil
+  :onTypeFormatting nil
+  :definition nil
+  :typeDefinition nil
+  :implementation nil
+  :codeAction nil
+  :codeLens nil
+  :documentLink nil
+  :colorProvider nil
+  :rename nil
+  :publishDiagnostics `(:relatedInformation :json-false))
+   :experimental (eglot--obj)))
 
 (defun eglot--connect (project managed-major-mode
short-name contact &optional success-fn)



[elpa] externals/eglot 9882bf2 072/139: Cleanup mistake with TextDocumentItem and TextDocumentIdentifier

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 9882bf243cc5b2a4f3700838d2a42a2d9d792f18
Author: João Távora 
Commit: João Távora 

Cleanup mistake with TextDocumentItem and TextDocumentIdentifier

Also introduce eglot--path-to-uri

* eglot.el (eglot--path-to-uri): Rename from eglot--uri and rework.
(eglot--connect): Use it.
(eglot--current-buffer-TextDocumentIdentifier): New function.
(eglot--current-buffer-VersionedTextDocumentIdentifier)
(eglot--signal-textDocument/didChange)
(eglot--signal-textDocument/didClose)
(eglot--signal-textDocument/willSave)
(eglot--signal-textDocument/didSave): Use it.
---
 eglot.el | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/eglot.el b/eglot.el
index 2b3f270..2afb0e7 100644
--- a/eglot.el
+++ b/eglot.el
@@ -254,9 +254,8 @@ SUCCESS-FN with no args if all goes well."
  (eglot--obj :processId (unless (eq (process-type proc)
 'network)
   (emacs-pid))
- :rootUri  (eglot--uri
-(expand-file-name (car (project-roots
-(project-current)
+ :rootUri  (eglot--path-to-uri
+(car (project-roots (project-current
  :initializationOptions  []
  :capabilities (eglot--client-capabilities))
  :success-fn
@@ -699,7 +698,11 @@ identifier.  ERROR is non-nil if this is a JSON-RPC error."
  (apply #'format format args)
  :warning)))
 
-(defun eglot--uri (path) "Add file:// to PATH." (concat "file://" path))
+(defun eglot--path-to-uri (path)
+  "Urify PATH."
+  (url-hexify-string
+   (concat "file://" (file-truename path))
+   url-path-allowed-chars))
 
 
 ;;; Minor modes
@@ -1033,15 +1036,14 @@ running.  INTERACTIVE is t if called interactively."
 
 (defvar-local eglot--versioned-identifier 0)
 
+(defun eglot--current-buffer-TextDocumentIdentifier ()
+  "Compute TextDocumentIdentifier object for current buffer."
+  (eglot--obj :uri (eglot--path-to-uri buffer-file-name)))
+
 (defun eglot--current-buffer-VersionedTextDocumentIdentifier ()
   "Compute VersionedTextDocumentIdentifier object for current buffer."
-  (eglot--obj :uri
-  (eglot--uri
-   (url-hexify-string
-(file-truename buffer-file-name)
-url-path-allowed-chars))
-  ;; FIXME: later deal with workspaces
-  :version eglot--versioned-identifier))
+  (append (eglot--current-buffer-TextDocumentIdentifier)
+  (eglot--obj :version eglot--versioned-identifier)))
 
 (defun eglot--current-buffer-TextDocumentItem ()
   "Compute TextDocumentItem object for current buffer."
@@ -1154,7 +1156,7 @@ Records START, END and PRE-CHANGE-LENGTH locally."
 (eglot--notify proc
:textDocument/didClose
(eglot--obj :textDocument
-   (eglot--current-buffer-TextDocumentItem)
+   
(eglot--current-buffer-TextDocumentIdentifier)
 
 (defun eglot--signal-textDocument/willSave ()
   "Send textDocument/willSave to server."
@@ -1163,7 +1165,7 @@ Records START, END and PRE-CHANGE-LENGTH locally."
:textDocument/willSave
(eglot--obj
 :reason 1 ; Manual, emacs laughs in the face of auto-save muahahahaha
-:textDocument (eglot--current-buffer-TextDocumentItem
+:textDocument (eglot--current-buffer-TextDocumentIdentifier
 
 (defun eglot--signal-textDocument/didSave ()
   "Send textDocument/didSave to server."
@@ -1173,7 +1175,7 @@ Records START, END and PRE-CHANGE-LENGTH locally."
(eglot--obj
 ;; TODO: Handle TextDocumentSaveRegistrationOptions to control this.
 :text (buffer-substring-no-properties (point-min) (point-max))
-:textDocument (eglot--current-buffer-TextDocumentItem
+:textDocument (eglot--current-buffer-TextDocumentIdentifier
 
 (defun eglot-flymake-backend (report-fn &rest _more)
   "An EGLOT Flymake backend.



[elpa] externals/eglot e63dad0 092/139: Simplify mode-line code with a helper.

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit e63dad0bc5ae5f1233907e1ae3c1dbd7c2a02d81
Author: João Távora 
Commit: João Távora 

Simplify mode-line code with a helper.

* eglot.el (eglot--mdoe-line-props): New helper.
(eglot--mode-line-format): Use it.
---
 eglot.el | 118 ---
 1 file changed, 38 insertions(+), 80 deletions(-)

diff --git a/eglot.el b/eglot.el
index a600f47..02439df 100644
--- a/eglot.el
+++ b/eglot.el
@@ -817,93 +817,51 @@ that case, also signal textDocument/didOpen."
 (with-selected-window (posn-window (event-start event))
   (call-interactively what
 
+(defun eglot--mode-line-props (thing face defs &optional prepend)
+  "Helper for function `eglot--mode-line-format'.
+Uses THING, FACE, DEFS and PREPEND."
+  (cl-loop with map = (make-sparse-keymap)
+   for (elem . rest) on defs
+   for (key def help) = elem
+   do (define-key map `[mode-line ,key] (eglot--mode-line-call def))
+   concat (format "%s: %s" key help) into blurb
+   when rest concat "\n" into blurb
+   finally (return `(:propertize ,thing
+ face ,face
+ keymap ,map help-echo ,(concat 
prepend blurb)
+ mouse-face mode-line-highlight
+
 (defun eglot--mode-line-format ()
-  "Compose the mode-line format spec."
+  "Compose the EGLOT's mode-line."
   (pcase-let* ((proc (eglot--current-process))
-   (name (and proc
-  (process-live-p proc)
-  (eglot--short-name proc)))
-   (pending (and proc
- (hash-table-count
-  (eglot--pending-continuations proc
-   (`(,_id ,doing ,done-p)
-(and proc
- (eglot--spinner proc)))
-   (`(,status ,serious-p)
-(and proc
- (eglot--status proc
+   (name (and (process-live-p proc) (eglot--short-name proc)))
+   (pending (and proc (hash-table-count
+   (eglot--pending-continuations proc
+   (`(,_id ,doing ,done-p) (and proc (eglot--spinner proc)))
+   (`(,status ,serious-p) (and proc (eglot--status proc
 (append
- `((:propertize "eglot"
-face eglot-mode-line
-keymap ,(let ((map (make-sparse-keymap)))
-  (define-key map [mode-line down-mouse-1]
-(eglot--mode-line-call 'eglot-menu))
-  map)
-mouse-face mode-line-highlight
-help-echo "mouse-1: pop-up EGLOT menu"
-))
+ `(,(eglot--mode-line-props "eglot" 'eglot-mode-line
+'((down-mouse-1 eglot-menu "pop up EGLOT 
menu"
  (when name
-   `(":"
- (:propertize
-  ,name
-  face eglot-mode-line
-  keymap ,(let ((map (make-sparse-keymap)))
-(define-key map [mode-line mouse-1]
-  (eglot--mode-line-call 'eglot-events-buffer))
-(define-key map [mode-line mouse-2]
-  (eglot--mode-line-call 'eglot-shutdown))
-(define-key map [mode-line mouse-3]
-  (eglot--mode-line-call 'eglot-reconnect))
-map)
-  mouse-face mode-line-highlight
-  help-echo ,(concat "mouse-1: go to events buffer\n"
- "mouse-2: quit server\n"
- "mouse-3: reconnect to server"))
+   `(":" ,(eglot--mode-line-props
+   name 'eglot-mode-line
+   '((mouse-1 eglot-events-buffer "go to events buffer")
+ (mouse-2 eglot-shutdown  "quit server")
+ (mouse-3 eglot-reconnect "reconnect to server")))
  ,@(when serious-p
- `("/"
-   (:propertize
-,status
-help-echo ,(concat "mouse-1: go to events buffer\n"
-   "mouse-3: clear this status")
-mouse-face mode-line-highlight
-face compilation-mode-line-fail
-keymap ,(let ((map (make-sparse-keymap)))
-  (define-key map [mode-line mouse-1]
-(eglot--mode-line-call 'eglot-events-buffer))
-  (define-key map [mode-line mouse-3]
-(eglot--mode-line-call 'eglot-clear-status))
-  map
+ `("/" ,(eglot--mode-line-props
+ status 'compilation-mode-line-fail
+ '((mouse-1 eglot-events-buffer "go to events buffer")
+   (mouse-3 eglot-clear-status  "c

[elpa] externals/eglot f257d63 089/139: * eglot.el: Reformat to shave off some lines.

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit f257d63256bdefe184c916479ef88e76f7f7d396
Author: João Távora 
Commit: João Távora 

* eglot.el: Reformat to shave off some lines.
---
 eglot.el | 268 +--
 1 file changed, 108 insertions(+), 160 deletions(-)

diff --git a/eglot.el b/eglot.el
index 9d7b16d..ba3b5be 100644
--- a/eglot.el
+++ b/eglot.el
@@ -43,10 +43,9 @@
   :prefix "eglot-"
   :group 'applications)
 
-(defvar eglot-executables
-  '((rust-mode . ("rls"))
-(python-mode . ("pyls"))
-(js-mode . ("javascript-typescript-stdio")))
+(defvar eglot-executables '((rust-mode . ("rls"))
+(python-mode . ("pyls"))
+(js-mode . ("javascript-typescript-stdio")))
   "Alist mapping major modes to server executables.")
 
 (defface eglot-mode-line
@@ -80,8 +79,7 @@
   "Return the current EGLOT process or error."
   (or (eglot--current-process)
   (eglot--error "No current EGLOT process%s"
-(if (project-current) ""
-  " (Also no current project)"
+(if (project-current) "" " (Also no current project)"
 
 (defmacro eglot--define-process-var
 (var-sym initval &optional doc mode-line-update-p)
@@ -166,13 +164,12 @@ CONTACT is as `eglot--contact'.  Returns a process 
object."
(match-string 1 singleton)
(string-to-number
 (match-string 2 singleton)))
-(make-process
- :name readable-name
- :buffer buffer
- :command contact
- :connection-type 'pipe
- :stderr (get-buffer-create (format "*%s stderr*"
-name))
+(make-process :name readable-name
+  :buffer buffer
+  :command contact
+  :connection-type 'pipe
+  :stderr (get-buffer-create (format "*%s stderr*"
+ name))
 (set-process-filter proc #'eglot--process-filter)
 (set-process-sentinel proc #'eglot--process-sentinel)
 proc))
@@ -186,9 +183,7 @@ CONTACT is as `eglot--contact'.  Returns a process object."
 
 (defun eglot--project-short-name (project)
   "Give PROJECT a short name."
-  (file-name-base
-   (directory-file-name
-(car (project-roots project)
+  (file-name-base (directory-file-name (car (project-roots project)
 
 (defun eglot--all-major-modes ()
   "Return all know major modes."
@@ -202,14 +197,7 @@ CONTACT is as `eglot--contact'.  Returns a process object."
   "What the EGLOT LSP client supports."
   (eglot--obj
:workspace(eglot--obj
-  :applyEdit nil
-  :workspaceEdit nil
-  :didChangeConfiguration nil
-  :didChangeWatchedFiles nil
-  :symbol nil
-  :executeCommand nil
-  :workspaceFolders nil
-  :configuration nil)
+  :symbol `(:dynamicRegistration :json-false))
:textDocument (eglot--obj
   :synchronization (eglot--obj
 :dynamicRegistration :json-false
@@ -277,8 +265,7 @@ SUCCESS-FN with no args if all goes well."
 (intern
  (completing-read
   "[eglot] Start a server to manage buffers of what major mode? "
-  (mapcar #'symbol-name
-  (eglot--all-major-modes)) nil t
+  (mapcar #'symbol-name (eglot--all-major-modes)) nil t
   (symbol-name major-mode) nil
   (symbol-name major-mode) nil)))
(t major-mode)))
@@ -332,17 +319,16 @@ INTERACTIVE is t if called interactively."
   (eglot-reconnect current-process interactive)
 (when (process-live-p current-process)
   (eglot-shutdown current-process 'sync))
-(eglot--connect
- project
- managed-major-mode
- short-name
- command
- (lambda (proc)
-   (eglot--message "Connected! Process `%s' now managing `%s' \
-buffers in project `%s'."
-   proc
-   managed-major-mode
-   short-name)))
+(eglot--connect project
+managed-major-mode
+short-name
+command
+(lambda (proc)
+  (eglot--message "Connected! Process `%s' now \
+managing `%s' buffers in project `%s'."
+  proc
+  managed-major-mode
+  short-name)))
 
 (defun eglot-reconnect (process &optional interactive)
   "Reconnect to PROCESS.
@@ -350,12 +336,1

[elpa] externals/eglot 714e5be 086/139: Half-baked textDocument/hover support

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 714e5be3080d5bef55e5b3143d3d1d3dd593a508
Author: João Távora 
Commit: João Távora 

Half-baked textDocument/hover support

* eglot.el (eglot--format-markup): New helper.
(eglot--managed-mode): Handle eldoc-documentation-function.
(eglot-eldoc-function): New function.

* README.md: update
---
 README.md |  2 +-
 eglot.el  | 42 --
 2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index f70d15f..611839b 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ server. To skip the guess and always be prompted use `C-u M-x 
eglot`.
 - [ ] textDocument/documentSymbol
 - [ ] textDocument/executeCommand
 - [ ] textDocument/format
-- [ ] textDocument/hover
+- [x] textDocument/hover
 - [ ] textDocument/rename
 - [x] textDocument/references
 - [ ] textDocument/signatureHelp
diff --git a/eglot.el b/eglot.el
index 3bed8d9..2c97f2f 100644
--- a/eglot.el
+++ b/eglot.el
@@ -772,6 +772,23 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (13 . "Enum") (14 . "Keyword") (15 . "Snippet") (16 . "Color")
 (17 . "File") (18 . "Reference")))
 
+(defun eglot--format-markup (markup)
+  "Format MARKUP according to LSP's spec."
+  (cond ((stringp markup)
+ (with-temp-buffer
+   (ignore-errors (funcall 'markdown-mode))
+   (font-lock-ensure)
+   (insert markup)
+   (string-trim (buffer-string
+(t
+ (with-temp-buffer
+   (ignore-errors (funcall (intern (concat
+(plist-get markup :language)
+"-mode" 
+   (insert (plist-get markup :value))
+   (font-lock-ensure)
+   (buffer-string)
+
 
 ;;; Minor modes
 ;;;
@@ -796,7 +813,10 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (add-hook 'after-save-hook 'eglot--signal-textDocument/didSave nil t)
 (add-hook 'xref-backend-functions 'eglot-xref-backend nil t)
 (add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t)
-(flymake-mode 1))
+(add-function :before-until (local 'eldoc-documentation-function)
+  #'eglot-eldoc-function)
+(flymake-mode 1)
+(eldoc-mode 1))
(t
 (remove-hook 'flymake-diagnostic-functions 'eglot-flymake-backend t)
 (remove-hook 'after-change-functions 'eglot--after-change t)
@@ -806,7 +826,9 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (remove-hook 'before-save-hook 'eglot--signal-textDocument/willSave t)
 (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t)
 (remove-hook 'xref-backend-functions 'eglot-xref-backend t)
-(remove-hook 'completion-at-point-functions #'eglot-completion-at-point 
t
+(remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
+(remove-function (local 'eldoc-documentation-function)
+ #'eglot-eldoc-function
 
 (define-minor-mode eglot-mode
   "Minor mode for all buffers managed by EGLOT in some way."  nil
@@ -1410,6 +1432,22 @@ DUMMY is ignored"
 (get-text-property 0 :sortText a)
 (get-text-property 0 :sortText b)
 
+(defun eglot-eldoc-function ()
+  "EGLOT's `eldoc-documentation-function' function."
+  (eglot--request (eglot--current-process-or-lose)
+  :textDocument/hover
+  (eglot--obj
+   :textDocument (eglot--current-buffer-TextDocumentIdentifier)
+   :position (eglot--pos-to-lsp-position))
+  :success-fn (eglot--lambda (&key contents _range)
+(eldoc-message
+ (mapconcat #'eglot--format
+(if (vectorp contents)
+contents
+  (list contents))
+"\n"
+  nil)
+
 
 ;;; Dynamic registration
 ;;;



[elpa] externals/eglot e7ffc31 067/139: Make reported capabilities into its own function

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit e7ffc31b9d7cc792241e3d077d2b7bb51e21ad84
Author: João Távora 
Commit: João Távora 

Make reported capabilities into its own function

* eglot.el (eglot--client-capabilities): New function.
(eglot--connect): Use it.
---
 eglot.el | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/eglot.el b/eglot.el
index 10435a1..b305ca3 100644
--- a/eglot.el
+++ b/eglot.el
@@ -189,6 +189,13 @@ CONTACT is as `eglot--contact'.  Returns a process object."
   (push sym retval
 retval))
 
+(defun eglot--client-capabilities ()
+  "What the EGLOT LSP client supports."
+  (eglot--obj
+   :workspace (eglot--obj)
+   :textDocument (eglot--obj
+  :publishDiagnostics `(:relatedInformation nil
+
 (defun eglot--connect (project managed-major-mode
short-name contact &optional success-fn)
   "Connect for PROJECT, MANAGED-MAJOR-MODE, SHORT-NAME and CONTACT.
@@ -218,11 +225,7 @@ SUCCESS-FN with no args if all goes well."
  (expand-file-name (car (project-roots
  (project-current)
  :initializationOptions  []
- :capabilities
- (eglot--obj
-  :workspace (eglot--obj)
-  :textDocument (eglot--obj
- :publishDiagnostics `(:relatedInformation 
t
+ :capabilities (eglot--client-capabilities))
  :success-fn
  (cl-function
   (lambda (&key capabilities)



[elpa] externals/eglot b4dd4f8 022/139: Report server status in the mode-line

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit b4dd4f850e4af8b202b47c3a6a2c0664ebbeaa30
Author: João Távora 
Commit: João Távora 

Report server status in the mode-line

* eglot.el (eglot--status): New var.
(eglot--log-event): Try to be more useful for other stuff.
(eglot--protocol-initialize): Set status to nil on
successful connect.
(eglot--window/showMessage): Set status to error if needed.
(eglot--mode-line-format): Display status if serious.
---
 eglot.el | 57 +++--
 1 file changed, 47 insertions(+), 10 deletions(-)

diff --git a/eglot.el b/eglot.el
index e5d6937..44023b7 100644
--- a/eglot.el
+++ b/eglot.el
@@ -92,6 +92,10 @@
   "\"Spinner\" used by some servers.
 A list (ID WHAT DONE-P).")
 
+(eglot--define-process-var eglot--status `(:unknown nil)
+  "Status as declared by the server.
+A list (WHAT SERIOUS-P).")
+
 (defun eglot--command (&optional errorp)
   (let ((probe (cdr (assoc major-mode eglot-executables
 (unless (or (not errorp)
@@ -265,15 +269,22 @@ INTERACTIVE is t if called interactively."
   (display-buffer buffer))
 buffer))
 
-(defun eglot--log-event (proc type message id error)
+(defun eglot--log-event (proc type message &optional id error)
+  "Log an eglot-related event.
+PROC is the current process.  TYPE is an identifier.  MESSAGE is
+a JSON-like plist or anything else.  ID is a continuation
+identifier.  ERROR is non-nil if this is an error."
   (with-current-buffer (eglot-events-buffer proc)
 (let ((inhibit-read-only t))
   (goto-char (point-max))
-  (insert (format "%s%s%s:\n%s\n"
-  type
-  (if id (format " (id:%s)" id) "")
-  (if error " ERROR" "")
-  (pp-to-string message))
+  (let ((msg (format "%s%s%s:\n%s\n"
+ type
+ (if id (format " (id:%s)" id) "")
+ (if error " ERROR" "")
+ (pp-to-string message
+(when error
+  (setq msg (propertize msg 'face 'error)))
+(insert msg)
 
 (defvar eglot--environment-vars
   '(eglot--current-flymake-report-fn)
@@ -445,6 +456,7 @@ INTERACTIVE is t if caller was called interactively."
 (lambda (&key capabilities)
   (setf (eglot--capabilities process) capabilities)
   (when interactive
+(setf (eglot--status process) nil)
 (eglot--message
  "So yeah I got lots (%d) of capabilities"
  (length capabilities)))
@@ -535,6 +547,16 @@ running.  INTERACTIVE is t if called interactively."
  (t
   (eglot--message "OK so %s isn't visited" filename)
 
+(cl-defun eglot--window/showMessage
+(process &key type message)
+  "Handle notification window/showMessage"
+  (when (<= 1 type)
+(setf (eglot--status process) '("error" t))
+(eglot--log-event process
+  (propertize "server-error" 'face 'error)
+  message))
+  (eglot--message "Server reports (type=%s): %s" type message))
+
 
 ;;; Helpers
 ;;;
@@ -603,8 +625,12 @@ running.  INTERACTIVE is t if called interactively."
(pending (and proc
  (hash-table-count
   (eglot--pending-continuations proc
-   (`(,_id ,what ,done-p) (and proc
-   (eglot--spinner
+   (`(,_id ,doing ,done-p)
+(and proc
+ (eglot--spinner proc)))
+   (`(,status ,serious-p)
+(and proc
+ (eglot--status proc
 (append
  `((:propertize "eglot"
 face eglot-mode-line
@@ -629,10 +655,21 @@ running.  INTERACTIVE is t if called interactively."
   help-echo ,(concat "mouse-1: go to events buffer\n"
  "mouse-2: quit server\n"
  "mouse-3: new process"))
- ,@(when (and what (not done-p))
+ ,@(when serious-p
+ `("/"
+   (:propertize
+,status
+help-echo ,(concat "mouse-1: go to events buffer")
+mouse-face mode-line-highlight
+face compilation-mode-line-fail
+keymap ,(let ((map (make-sparse-keymap)))
+  (define-key map [mode-line mouse-1]
+'eglot-events-buffer)
+  map
+ ,@(when (and doing (not done-p))
  `("/"
(:propertize
-,what
+,doing
 help-echo ,(concat "mouse-1: go to events buffer")
 mouse-face mode-line-highlight
 face compilation-mode-line-run



[elpa] externals/eglot 95187cf 058/139: Connect to LSP server via TCP

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 95187cfcecbfafb090c530808e2f6932cf9d860e
Author: João Távora 
Commit: João Távora 

Connect to LSP server via TCP

* eglot.el (eglot--make-process): Rename from
eglot-make-local-process.
(eglot): Fix docstring and rework.
(eglot--bootstrap-fn): Remove
(eglot--contact): New process-local var.
(eglot--connect): Take CONTACT arg.
(eglot--reconnect): Rework.
---
 eglot.el | 137 ++-
 1 file changed, 73 insertions(+), 64 deletions(-)

diff --git a/eglot.el b/eglot.el
index ac52b9a..c5a0c0f 100644
--- a/eglot.el
+++ b/eglot.el
@@ -133,30 +133,40 @@ A list (ID WHAT DONE-P)." t)
   "Status as declared by the server.
 A list (WHAT SERIOUS-P)." t)
 
-(eglot--define-process-var eglot--bootstrap-fn nil
-  "Function for returning processes/connetions to LSP servers.
-Must be a function of one arg, a name, returning a process
-object.")
+(eglot--define-process-var eglot--contact nil
+  "Method used to contact a server.
+Either a list of strings (a shell command and arguments), or a
+list of a single string of the form :")
 
 (eglot--define-process-var eglot--buffer-open-count (make-hash-table)
   "Keeps track of didOpen/didClose notifs for each buffer.")
 
-(defun eglot-make-local-process (name command)
-  "Make a local LSP process from COMMAND.
+(defun eglot--make-process (name contact)
+  "Make a process from CONTACT.
 NAME is a name to give the inferior process or connection.
-Returns a process object."
+CONTACT is as `eglot--contact'.  Returns a process object."
   (let* ((readable-name (format "EGLOT server (%s)" name))
+ (buffer (get-buffer-create
+  (format "*%s inferior*" readable-name)))
+ (singleton (and (null (cdr contact)) (car contact)))
  (proc
-  (make-process
-   :name readable-name
-   :buffer (get-buffer-create
-(format "*%s inferior*" readable-name))
-   :command command
-   :connection-type 'pipe
-   :filter 'eglot--process-filter
-   :sentinel 'eglot--process-sentinel
-   :stderr (get-buffer-create (format "*%s stderr*"
-  name)
+  (if (and
+   singleton
+   (string-match "^[\s\t]*\\(.*\\):\\([[:digit:]]+\\)[\s\t]*$"
+ singleton))
+  (open-network-stream readable-name
+   buffer
+   (match-string 1 singleton)
+   (string-to-number (match-string 2 
singleton)))
+(make-process
+ :name readable-name
+ :buffer buffer
+ :command contact
+ :connection-type 'pipe
+ :stderr (get-buffer-create (format "*%s stderr*"
+name))
+(set-process-filter proc #'eglot--process-filter)
+(set-process-sentinel proc #'eglot--process-sentinel)
 proc))
 
 (defmacro eglot--obj (&rest what)
@@ -180,13 +190,12 @@ Returns a process object."
 retval))
 
 (defun eglot--connect (project managed-major-mode
-   short-name bootstrap-fn &optional success-fn)
-  "Make a connection for PROJECT, SHORT-NAME and MANAGED-MAJOR-MODE.
-Use BOOTSTRAP-FN to make the actual process object.  Call
+   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."
-  (let* ((proc (funcall bootstrap-fn short-name))
+  (let* ((proc (eglot--make-process short-name contact))
  (buffer (process-buffer proc)))
-(setf (eglot--bootstrap-fn proc) bootstrap-fn
+(setf (eglot--contact proc) contact
   (eglot--project proc) project
   (eglot--major-mode proc) managed-major-mode)
 (with-current-buffer buffer
@@ -226,15 +235,17 @@ SUCCESS-FN with no args if all goes well."
   "History of COMMAND arguments to `eglot'.")
 
 (defun eglot (managed-major-mode command &optional interactive)
-  ;; FIXME: Later make this function also connect to TCP servers by
-  ;; overloading semantics on COMMAND.
   "Start a Language Server Protocol server.
 Server is started with COMMAND and manages buffers of
 MANAGED-MAJOR-MODE for the current project.
 
 COMMAND is a list of strings, an executable program and
-optionally its arguments.  MANAGED-MAJOR-MODE is an Emacs major
-mode.
+optionally its arguments.  If the first and only string in the
+list is of the form \":\" it is taken as an
+indication to connect to a server instead of starting one.  This
+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'.
@@ -257,47 +268,45 @@ INTERACTIVE is t if

[elpa] externals/eglot fceb6bb 090/139: Get rid of eglot--special-buffer-process

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit fceb6bb5dd740101033d61c5a094bdd1f8b89957
Author: João Távora 
Commit: João Távora 

Get rid of eglot--special-buffer-process

Hasn't really proved useful yet.

* eglot.el (eglot--special-buffer-process): Delete.
(eglot--current-process): Simplify.
(eglot--events-buffer): Simplify.
---
 eglot.el | 18 --
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/eglot.el b/eglot.el
index ba3b5be..1318fee 100644
--- a/eglot.el
+++ b/eglot.el
@@ -61,19 +61,11 @@
 (defvar eglot--processes-by-project (make-hash-table :test #'equal)
   "Keys are projects.  Values are lists of processes.")
 
-(defvar-local eglot--special-buffer-process nil
-  "Current buffer's eglot process.")
-
 (defun eglot--current-process ()
   "The current logical EGLOT process."
-  (or eglot--special-buffer-process
-  (let* ((cur (project-current))
- (processes
-  (and cur
-   (gethash cur eglot--processes-by-project
-(cl-find major-mode
- processes
- :key #'eglot--major-mode
+  (let* ((cur (project-current))
+ (processes (and cur (gethash cur eglot--processes-by-project
+(cl-find major-mode processes :key #'eglot--major-mode)))
 
 (defun eglot--current-process-or-lose ()
   "Return the current EGLOT process or error."
@@ -465,9 +457,7 @@ INTERACTIVE is t if called interactively."
(with-current-buffer buffer
  (buffer-disable-undo)
  (read-only-mode t)
- (setf (eglot--events-buffer process) buffer
-   eglot--special-buffer-process process)
- (eglot-mode))
+ (setf (eglot--events-buffer process) buffer))
buffer
 (when interactive (display-buffer buffer))
 buffer))



[elpa] externals/eglot ecd334f 101/139: Update README

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit ecd334f6466b0a1488735e4cb6d41ab4fa65660f
Author: João Távora 
Commit: João Távora 

Update README
---
 README.md | 115 +-
 1 file changed, 84 insertions(+), 31 deletions(-)

diff --git a/README.md b/README.md
index a8d1c8b..faf2dea 100644
--- a/README.md
+++ b/README.md
@@ -2,19 +2,21 @@
 Eglot
 -
 
-*E*macs Poly*glot*. An Emacs client to Language Server Protocol servers.
+*E*macs Poly*glot*. An Emacs client to [Language Server Protocol][lsp] servers.
 
 ```
 (add-to-list 'load-path "/path/to/eglot")
-(require 'eglot)
+(require 'eglot) ; Requires emacs 26!
 
+;; Now find some project file inside some Git-controlled dir
 M-x eglot
 ```
 
-*That's it*. Either this guesses the local LSP program to start for
-the language of your choice or it prompts you for such a
-thing. Currently, if you have these programs installed, it works
-out-of-the-box for:
+*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.
+
+If you have these programs installed, `M-x eglot` works out-of-the-box
+with:
 
 * Javascript's [javascript-typescript-stdio][javascript-typescript-langserver]
 * Rust's [rls][rls]
@@ -25,60 +27,111 @@ server. To skip the guess and always be prompted use `C-u 
M-x eglot`.
 
 # Supported Protocol features
 
-- [x] textDocument/didChange (incremental)
-- [x] textDocument/didClose
+## General
+- [x] initialize
+- [x] initalized
+- [x] shutdown
+- [x] exit
+- [ ] $/cancelRequest
+
+## Window
+- [x] window/showMessage
+- [x] window/showMessageRequest
+- [x] window/logMessage
+- [x] telemetry/event
+
+## Client
+- [ ] client/registerCapability
+- [ ] client/unregisterCapability
+
+## Workspace
+- [ ] workspace/workspaceFolders (3.6.0)
+- [ ] workspace/didChangeWorkspaceFolders (3.6.0)
+- [ ] workspace/didChangeConfiguration
+- [ ] workspace/configuration (3.6.0)
+- [ ] workspace/didChangeWatchedFiles
+- [x] workspace/symbol
+- [x] workspace/applyEdit
+
+## Text Synchronization
 - [x] textDocument/didOpen
+- [x] textDocument/didChange (incremental or full)
+- [x] textDocument/willSave
+- [ ] textDocument/willSaveWaitUntil
 - [x] textDocument/didSave
+- [x] textDocument/didClose
 
-- [ ] textDocument/codeAction
+## Diagnostics
+- [x] textDocument/publishDiagnostics
+
+## Language features
 - [x] textDocument/completion
 - [ ] completionItem/resolve
+- [x] textDocument/hover
+- [ ] textDocument/signatureHelp
 - [x] textDocument/definition
+- [ ] textDocument/typeDefinition (3.6.0)
+- [ ] textDocument/implementation (3.6.0)
+- [x] textDocument/references
 - [x] textDocument/documentHighlight
 - [x] textDocument/documentSymbol
-- [ ] textDocument/executeCommand
-- [ ] textDocument/format
-- [x] textDocument/hover
+- [ ] textDocument/codeAction
+- [ ] textDocument/codeLens
+- [ ] codeLens/resolve
+- [ ] textDocument/documentLink
+- [ ] documentLink/resolve
+- [ ] textDocument/documentColor
+- [ ] textDocument/colorPresentation (3.6.0)
+- [ ] textDocument/formatting 
+- [ ] textDocument/rangeFormatting
+- [ ] textDocument/onTypeFormatting
 - [x] textDocument/rename
-- [x] textDocument/references
-- [ ] textDocument/signatureHelp
-- [x] workspace/symbol
 
 # Differences to lsp-mode.el
 
-This is really beta and currently does a little less than
-[lsp-mode.el][emacs-lsp] which is more mature. Though I think
-`eglot.el` will eventually beat it, you could be better served with
+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.
 
 User-visible differences:
 
-- Single entry point, `M-x eglot` to enable LSP in a project.
-  Automatically detects current and future opened files under that
+- Single entry point `M-x eglot`, not `M-x eglot-`. Also no
+  `eglot-` 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.
 - 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
   communication.
+- Automatically restarts frequently crashing servers (like RLS).
+- Server-initiated edits are confirmed with the user.
+- Diagnostics work out-of-the-box (no `flycheck.el` needed).

-Differences under the hood:
-
-- Message parser is much much simpler
-- Easier to read and maintain elisp. Yeah I know, subjective... But
-  judge for yourself.
-- No external dependencies apart from Emacs (no `flycheck.el`, no
-  `projectile.el`, no Cask, etc).

[elpa] externals/eglot ea918ab 066/139: Include source info in diagnostics

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit ea918abb952c3e624e57681a9b313df32ddcd014
Author: João Távora 
Commit: João Távora 

Include source info in diagnostics

* eglot.el (eglot--server-textDocument/publishDiagnostics):
Include source info.
---
 eglot.el | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index d073be2..10435a1 100644
--- a/eglot.el
+++ b/eglot.el
@@ -936,7 +936,7 @@ running.  INTERACTIVE is t if called interactively."
  (point
   (cl-loop for diag-spec across diagnostics
collect (cl-destructuring-bind (&key range severity _group
-_code _source message)
+_code source message)
diag-spec
  (cl-destructuring-bind (&key start end)
  range
@@ -951,7 +951,7 @@ running.  INTERACTIVE is t if called interactively."
  :warning)
 (t
  :note))
-  message
+  (concat source ": " message)
into diags
finally
(if eglot--current-flymake-report-fn



[elpa] externals/eglot 29d4103 056/139: Fix mode-line mouse-clicks from outside selected window

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 29d4103a947c255361c600f9ed74381ad3f2ec6a
Author: João Távora 
Commit: João Távora 

Fix mode-line mouse-clicks from outside selected window

* eglot.el (eglot--mode-line-call): New helper.
(eglot--mode-line-format): Use it.
---
 eglot.el | 28 +++-
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/eglot.el b/eglot.el
index 693535a..bdd339d 100644
--- a/eglot.el
+++ b/eglot.el
@@ -695,6 +695,13 @@ that case, also signal textDocument/didOpen."
 
 (put 'eglot--mode-line-format 'risky-local-variable t)
 
+(defun eglot--mode-line-call (what)
+  "Make an interactive lambda for calling WHAT from mode-line."
+  (lambda (event)
+(interactive "e")
+(with-selected-window (posn-window (event-start event))
+  (call-interactively what
+
 (defun eglot--mode-line-format ()
   "Compose the mode-line format spec."
   (pcase-let* ((proc (eglot--current-process))
@@ -715,7 +722,7 @@ that case, also signal textDocument/didOpen."
 face eglot-mode-line
 keymap ,(let ((map (make-sparse-keymap)))
   (define-key map [mode-line down-mouse-1]
-eglot-menu)
+(eglot--mode-line-call 'eglot-menu))
   map)
 mouse-face mode-line-highlight
 help-echo "mouse-1: pop-up EGLOT menu"
@@ -726,9 +733,12 @@ that case, also signal textDocument/didOpen."
   ,name
   face eglot-mode-line
   keymap ,(let ((map (make-sparse-keymap)))
-(define-key map [mode-line mouse-1] 'eglot-events-buffer)
-(define-key map [mode-line mouse-2] 'eglot-shutdown)
-(define-key map [mode-line mouse-3] 'eglot-reconnect)
+(define-key map [mode-line mouse-1]
+  (eglot--mode-line-call 'eglot-events-buffer))
+(define-key map [mode-line mouse-2]
+  (eglot--mode-line-call 'eglot-shutdown))
+(define-key map [mode-line mouse-3]
+  (eglot--mode-line-call 'eglot-reconnect))
 map)
   mouse-face mode-line-highlight
   help-echo ,(concat "mouse-1: go to events buffer\n"
@@ -744,9 +754,9 @@ that case, also signal textDocument/didOpen."
 face compilation-mode-line-fail
 keymap ,(let ((map (make-sparse-keymap)))
   (define-key map [mode-line mouse-1]
-'eglot-events-buffer)
+(eglot--mode-line-call 'eglot-events-buffer))
   (define-key map [mode-line mouse-3]
-'eglot-clear-status)
+(eglot--mode-line-call 'eglot-clear-status))
   map
  ,@(when (and doing (not done-p))
  `("/"
@@ -757,7 +767,7 @@ that case, also signal textDocument/didOpen."
 face compilation-mode-line-run
 keymap ,(let ((map (make-sparse-keymap)))
   (define-key map [mode-line mouse-1]
-'eglot-events-buffer)
+(eglot--mode-line-call 'eglot-events-buffer))
   map
  ,@(when (cl-plusp pending)
  `("/"
@@ -775,9 +785,9 @@ that case, also signal textDocument/didOpen."
  'eglot-mode-line))
 keymap ,(let ((map (make-sparse-keymap)))
   (define-key map [mode-line mouse-1]
-'eglot-events-buffer)
+(eglot--mode-line-call 'eglot-events-buffer))
   (define-key map [mode-line mouse-3]
-'eglot-forget-pending-continuations)
+(eglot--mode-line-call 
'eglot-forget-pending-continuations))
   map)
 
 (add-to-list 'mode-line-misc-info



[elpa] externals/eglot 56c2e1d 104/139: Get rid of eglot-mode

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 56c2e1dec4413e146242e97714867c0c9a6ed947
Author: João Távora 
Commit: João Távora 

Get rid of eglot-mode

* eglot.el (eglot--managed-mode): Don't call eglot-mode. When
shutting down, offer to kill server.
(mode-line-misc-info): Update to use eglot--managed-mode
---
 eglot.el | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/eglot.el b/eglot.el
index 3eb43ce..bed98ed 100644
--- a/eglot.el
+++ b/eglot.el
@@ -769,7 +769,6 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
   nil nil eglot-mode-map
   (cond
(eglot--managed-mode
-(eglot-mode 1)
 (add-hook 'after-change-functions 'eglot--after-change nil t)
 (add-hook 'before-change-functions 'eglot--before-change nil t)
 (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
@@ -796,11 +795,10 @@ Meaning only return locally if successful, otherwise exit 
non-locally."
 (remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
 (remove-function (local 'eldoc-documentation-function)
  #'eglot-eldoc-function)
-(remove-function (local imenu-create-index-function) #'eglot-imenu
-
-(define-minor-mode eglot-mode
-  "Minor mode for all buffers managed by EGLOT in some way."  nil
-  nil eglot-mode-map)
+(remove-function (local imenu-create-index-function) #'eglot-imenu)
+(let ((proc (eglot--current-process)))
+  (when (and (process-live-p proc) (y-or-n-p "[eglot] Kill server too? "))
+(eglot-shutdown proc nil t))
 
 (defun eglot--buffer-managed-p (&optional proc)
   "Tell if current buffer is managed by PROC."
@@ -886,7 +884,8 @@ Uses THING, FACE, DEFS and PREPEND."
(mouse-3 eglot-clear-status  "clear this status"))
  (format "%d pending requests\n" pending)
 
-(add-to-list 'mode-line-misc-info `(eglot-mode (" [" eglot--mode-line-format 
"] ")))
+(add-to-list 'mode-line-misc-info
+ `(eglot--managed-mode (" [" eglot--mode-line-format "] ")))
 
 
 ;;; Protocol implementation (Requests, notifications, etc)



[elpa] externals/eglot b511b7d 036/139: Redesign and simplify parser

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit b511b7d2da0e48a460bbcf4e7e9380a7253aa5d1
Author: João Távora 
Commit: João Távora 

Redesign and simplify parser

Fix horrible bugs. This is the correct way.

* eglot.el (eglot--process-filter): Redesign.
---
 eglot.el | 106 ---
 1 file changed, 47 insertions(+), 59 deletions(-)

diff --git a/eglot.el b/eglot.el
index 71dab80..b9aa94c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -234,71 +234,59 @@ INTERACTIVE is t if called interactively."
   (when (buffer-live-p (process-buffer proc))
 (with-current-buffer (process-buffer proc)
   (let ((inhibit-read-only t)
-(pre-insertion-mark (copy-marker (process-mark proc)))
 (expected-bytes (eglot--expected-bytes proc)))
 ;; Insert the text, advancing the process marker.
-(goto-char (process-mark proc))
-(insert string)
-(set-marker (process-mark proc) (point))
-
-;; goto point just before insertion
 ;;
-(goto-char pre-insertion-mark)
-
-;; loop for each message (more than one might have arrived)
+(save-excursion
+  (goto-char (process-mark proc))
+  (insert string)
+  (set-marker (process-mark proc) (point)))
+;; Loop (more than one message might have arrived)
 ;;
 (catch 'done
   (while t
-(let* ((match (search-forward-regexp
-   "\\(?:.*: .*\r\n\\)*Content-Length: 
\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
-   (+ (point) 100)
-   t))
-   (new-expected-bytes (and match
-(string-to-number (match-string 
1)
-  (when new-expected-bytes
-(when expected-bytes
-  (eglot--warn
-   (concat "Unexpectedly starting new message but %s bytes "
-   "reportedly remaining from previous one")
-   expected-bytes))
-(setf (eglot--expected-bytes proc) new-expected-bytes)
-(setq expected-bytes new-expected-bytes)))
-
-;; check for message body
-;;
-(let ((available-bytes (- (position-bytes (process-mark proc))
-  (position-bytes (point)
-  (cond ((not expected-bytes) ; previous search didn't match
- (eglot--warn
-  "Skipping %s bytes of unexpected garbage from process %s"
-  available-bytes
-  proc)
- (goto-char (process-mark proc))
- (throw 'done :skipping-garbage))
-((>= available-bytes
- expected-bytes)
- (let* ((message-end (byte-to-position
-  (+ (position-bytes (point))
- expected-bytes
-   (unwind-protect
-   (save-restriction
- (narrow-to-region (point)
-   message-end)
- (let* ((json-object-type 'plist)
-(json-message (json-read)))
-   ;; process in another buffer, shielding
-   ;; buffer from tamper
-   (with-temp-buffer
- (eglot--process-receive proc json-message
- (goto-char message-end)
- (setf (eglot--expected-bytes proc) nil
-   expected-bytes nil)))
- (when (= (point) (process-mark proc))
-   (throw 'done :clean-done)))
-(t
- ;; just adding some stuff to the end that doesn't yet
- ;; complete the message
- (throw 'done :waiting-for-more-bytes))
+(cond ((not expected-bytes)
+   ;; Starting a new message
+   ;;
+   (setq expected-bytes
+ (and (search-forward-regexp
+   "\\(?:.*: .*\r\n\\)*Content-Length: 
*\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
+   (+ (point) 100)
+   t)
+  (string-to-number (match-string 1
+   (unless expected-bytes
+ (throw 'done :waiting-for-new-message)))
+  (t
+   ;; Attempt to complete a message body
+   ;;
+   (let ((available-bytes (- (position-bytes (process-mark 
proc))
+ (position-bytes (point)
+   

[elpa] externals/eglot d254f97 082/139: Solve another textDocument/didChange bug

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit d254f974e1991f3787da5c06a76da33ab1181548
Author: João Távora 
Commit: João Távora 

Solve another textDocument/didChange bug

* eglot.el (eglot--signal-textDocument/didChange): Rework a bit.
(eglot--after-change): Store the actual after-text in the
eglot--recent-after-changes.
---
 eglot.el | 99 
 1 file changed, 56 insertions(+), 43 deletions(-)

diff --git a/eglot.el b/eglot.el
index 045588d..f6bf010 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1128,52 +1128,65 @@ were deleted/added)"
   "Hook onto `after-change-functions'.
 Records START, END and PRE-CHANGE-LENGTH locally."
   (cl-incf eglot--versioned-identifier)
-  (push (list start end pre-change-length) eglot--recent-after-changes))
+  (push (list start end pre-change-length
+  (buffer-substring-no-properties start end))
+eglot--recent-after-changes))
 
 (defun eglot--signal-textDocument/didChange ()
   "Send textDocument/didChange to server."
-  (when (and eglot--recent-before-changes
- eglot--recent-after-changes)
-(let* ((proc (eglot--current-process-or-lose))
-   (sync-kind (plist-get (eglot--capabilities proc) 
:textDocumentSync)))
-  (save-restriction
-(widen)
-(unless (or (not sync-kind)
-(eq sync-kind 0))
-  (eglot--notify
-   proc
-   :textDocument/didChange
-   (eglot--obj
-:textDocument
-(eglot--current-buffer-VersionedTextDocumentIdentifier)
-:contentChanges
-(if (or (eq sync-kind 1)
-(/= (length eglot--recent-before-changes)
-(length eglot--recent-after-changes)))
-(vector
- (eglot--obj
-  :text (buffer-substring-no-properties (point-min) 
(point-max
-  (apply
-   #'vector
-   (mapcar
-(pcase-lambda (`(,before-start-position
- ,before-end-position
- ,after-start
- ,after-end
- ,len))
-  (eglot--obj
-   :range
-   (eglot--obj
-:start before-start-position
-:end before-end-position)
-   :rangeLength len
-   :text (buffer-substring-no-properties after-start 
after-end)))
-(reverse
- (cl-mapcar 'append
-eglot--recent-before-changes
-eglot--recent-after-changes)))
-  (setq eglot--recent-before-changes nil
-eglot--recent-after-changes nil))
+  (unwind-protect
+  (when (or eglot--recent-before-changes
+eglot--recent-after-changes)
+(let* ((proc (eglot--current-process-or-lose))
+   (sync-kind (plist-get (eglot--capabilities proc)
+ :textDocumentSync))
+   (emacs-messup
+(/= (length eglot--recent-before-changes)
+(length eglot--recent-after-changes)))
+   (full-sync-p (or (eq sync-kind 1) emacs-messup)))
+  (when emacs-messup
+(unless (eq sync-kind 1)
+  (eglot--warn "Using full sync because before: %s and after: %s"
+   eglot--recent-before-changes
+   eglot--recent-after-changes)))
+  (save-restriction
+(widen)
+(unless (or (not sync-kind)
+(eq sync-kind 0))
+  (eglot--notify
+   proc
+   :textDocument/didChange
+   (eglot--obj
+:textDocument
+(eglot--current-buffer-VersionedTextDocumentIdentifier)
+:contentChanges
+(if full-sync-p
+(vector
+ (eglot--obj
+  :text (buffer-substring-no-properties (point-min)
+(point-max
+  (apply
+   #'vector
+   (mapcar
+(pcase-lambda (`(,before-start-position
+ ,before-end-position
+ ,_after-start
+ ,_after-end
+ ,len
+ ,after-text))
+  (eglot--obj
+   :range
+   (eglot--obj
+:start before-start-position
+:end before-end-position)
+   :rangeLength len
+   :text after-text))
+(reverse
+ (cl-mapcar 'append
+  

[elpa] externals/eglot fdb4de1 039/139: Simplify flymake integration

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit fdb4de165885d4ff777a40dcaca289452545db8d
Author: João Távora 
Commit: João Távora 

Simplify flymake integration

And get rid of the ridiculous environment thingy

* eglot.el (eglot--process-sentinel): Continuations are triplets.
(eglot--environment-vars, eglot--environment): Remove.
(eglot--process-receive): Simplify.
(eglot--unreported-diagnostics): New variable.
(eglot--textDocument/publishDiagnostics): Simplify.
(eglot-flymake-backend): Report unreported diagnostics.
---
 eglot.el | 58 +++---
 1 file changed, 23 insertions(+), 35 deletions(-)

diff --git a/eglot.el b/eglot.el
index 8584440..8bb0729 100644
--- a/eglot.el
+++ b/eglot.el
@@ -229,8 +229,8 @@ INTERACTIVE is t if called interactively."
   (when (not (process-live-p process))
 ;; Remember to cancel all timers
 ;;
-(maphash (lambda (id quad)
-   (cl-destructuring-bind (_success _error timeout _env) quad
+(maphash (lambda (id triplet)
+   (cl-destructuring-bind (_success _error timeout) triplet
  (eglot--message
   "(sentinel) Cancelling timer for continuation %s" id)
  (cancel-timer timeout)))
@@ -349,13 +349,6 @@ identifier.  ERROR is non-nil if this is an error."
   (setq msg (propertize msg 'face 'error)))
 (insert msg)
 
-(defvar eglot--environment-vars
-  '(eglot--current-flymake-report-fn)
-  "A list of variables with saved values on every request.")
-
-(defvar eglot--environment nil
-  "Dynamically bound alist of symbol and values.")
-
 (defun eglot--process-receive (proc message)
   "Process MESSAGE from PROC."
   (let* ((response-id (plist-get message :id))
@@ -388,13 +381,9 @@ identifier.  ERROR is non-nil if this is an error."
   (t
(let* ((method (plist-get message :method))
   (handler-sym (intern (concat "eglot--"
-   method)))
-  (eglot--environment (cl-fourth continuations)))
+   method
  (if (functionp handler-sym)
- (cl-progv
- (mapcar #'car eglot--environment)
- (mapcar #'cdr eglot--environment)
-   (apply handler-sym proc (plist-get message :params)))
+ (apply handler-sym proc (plist-get message :params))
(eglot--debug "No implemetation for notification %s yet"
  method)))
 
@@ -476,9 +465,7 @@ identifier.  ERROR is non-nil if this is an error."
error-fn
  (lambda (&rest args)
(throw catch-tag (apply error-fn args
-   timeout-timer
-   (cl-loop for var in eglot--environment-vars
-collect (cons var (symbol-value var
+   timeout-timer)
  (eglot--pending-continuations process))
 (unless async-p
   (unwind-protect
@@ -563,23 +550,18 @@ running.  INTERACTIVE is t if called interactively."
 
 ;;; Notifications
 ;;;
-(defvar eglot--current-flymake-report-fn nil)
+(defvar-local eglot--current-flymake-report-fn nil
+  "Current flymake report function for this buffer")
+(defvar-local eglot--unreported-diagnostics nil
+  "Unreported diagnostics for this buffer.")
 
 (cl-defun eglot--textDocument/publishDiagnostics
 (_process &key uri diagnostics)
   "Handle notification publishDiagnostics"
   (let* ((obj (url-generic-parse-url uri))
 (filename (car (url-path-and-query obj)))
- (buffer (find-buffer-visiting filename))
- (report-fn (cdr (assoc 'eglot--current-flymake-report-fn
-eglot--environment
+ (buffer (find-buffer-visiting filename)))
 (cond
- ((not eglot--current-flymake-report-fn)
-  (eglot--warn "publishDiagnostics called but no report-fn"))
- ((and report-fn
-   (not (eq report-fn
-eglot--current-flymake-report-fn)))
-  (eglot--warn "outdated publishDiagnostics report from server"))
  (buffer
   (with-current-buffer buffer
 (cl-flet ((pos-at
@@ -607,9 +589,12 @@ running.  INTERACTIVE is t if called interactively."
  :note))
   message
into diags
-   finally (funcall
-eglot--current-flymake-report-fn
-diags)
+   finally
+   (if eglot--current-flymake-report-fn
+   (funcall eglot--current-flymake-report-fn
+diags)
+ (setq eglot--unreported-diagnostics
+   diags))
  (t

[elpa] externals/elpa 4c0bfc3 139/139: Support didChangeWatchedFiles with dynamic registration

2018-05-14 Thread Jo�o T�vora
branch: externals/elpa
commit 4c0bfc335181a6d3d54141d4fb952cff887621e6
Author: João Távora 
Commit: João Távora 

Support didChangeWatchedFiles with dynamic registration

RLS uses this, presumaly for knowing about Cargo.toml changes and stuff.

* README.md: Update protocol compliance.

* eglot.el (filenotify): Require it.
(eglot--file-watches): New process-local var.
(eglot--process-sentinel): Kill all watches
(eglot--register-unregister): New helper.
(eglot--server-client/registerCapability): Simplify.
(eglot--server-client/unregisterCapability): New method.
(eglot--register-workspace/didChangeWatchedFiles)
(eglot--unregister-workspace/didChangeWatchedFiles): New
capability.
(eglot--client-capabilities): Update.
---
 README.md |   7 +++--
 eglot.el  | 102 --
 2 files changed, 76 insertions(+), 33 deletions(-)

diff --git a/README.md b/README.md
index 056065c..7550a30 100644
--- a/README.md
+++ b/README.md
@@ -76,15 +76,16 @@ either:
 - [x] telemetry/event
 
 ## Client
-- [ ] client/registerCapability
-- [ ] client/unregisterCapability
+- [x] client/registerCapability (but only
+  `workspace/didChangeWatchedFiles`, like RLS asks)
+- [x] client/unregisterCapability  (ditto)
 
 ## Workspace
 - [ ] workspace/workspaceFolders (3.6.0)
 - [ ] workspace/didChangeWorkspaceFolders (3.6.0)
 - [ ] workspace/didChangeConfiguration
 - [ ] workspace/configuration (3.6.0)
-- [ ] workspace/didChangeWatchedFiles
+- [x] workspace/didChangeWatchedFiles
 - [x] workspace/symbol is
 - [x] workspace/applyEdit
 
diff --git a/eglot.el b/eglot.el
index 9b0f290..85b2d89 100644
--- a/eglot.el
+++ b/eglot.el
@@ -39,6 +39,7 @@
 (require 'flymake)
 (require 'xref)
 (require 'subr-x)
+(require 'filenotify)
 
 
 ;;; User tweakable stuff
@@ -148,6 +149,9 @@ list of a single string of the form :")
 (make-hash-table :test #'equal)
   "Actions deferred to when server is thought to be ready.")
 
+(eglot--define-process-var eglot--file-watches (make-hash-table :test #'equal)
+  "File system watches for the didChangeWatchedfiles thingy.")
+
 (defun eglot--make-process (name managed-major-mode contact)
   "Make a process from CONTACT.
 NAME is a name to give the inferior process or connection.
@@ -199,6 +203,9 @@ CONTACT is as `eglot--contact'.  Returns a process object."
   "What the EGLOT LSP client supports."
   (eglot--obj
:workspace(eglot--obj
+  :applyEdit t
+  :workspaceEdit `(:documentChanges :json-false)
+  :didChangeWatchesFiles `(:dynamicRegistration t)
   :symbol `(:dynamicRegistration :json-false))
:textDocument (eglot--obj
   :synchronization (eglot--obj
@@ -365,11 +372,14 @@ INTERACTIVE is t if called interactively."
 (with-current-buffer (eglot-events-buffer proc)
   (let ((inhibit-read-only t))
 (insert "\n--b---y---e---b---y---e--\n")))
-;; Cancel outstanding timers
+;; Cancel outstanding timers and file system watches
 (maphash (lambda (_id triplet)
(cl-destructuring-bind (_success _error timeout) triplet
  (cancel-timer timeout)))
  (eglot--pending-continuations proc))
+(maphash (lambda (_id watches)
+   (mapcar #'file-notify-rm-watch watches))
+ (eglot--file-watches proc))
 (unwind-protect
 ;; Call all outstanding error handlers
 (maphash (lambda (_id triplet)
@@ -990,32 +1000,31 @@ called interactively."
  (t
   (eglot--message "OK so %s isn't visited" filename)
 
+(cl-defun eglot--register-unregister (proc jsonrpc-id things how)
+  "Helper for `eglot--server-client/registerCapability'.
+THINGS are either registrations or unregisterations."
+  (dolist (thing (cl-coerce things 'list))
+(cl-destructuring-bind (&key id method registerOptions) thing
+  (let (retval)
+(unwind-protect
+(setq retval (apply (intern (format "eglot--%s-%s" how method))
+proc :id id registerOptions))
+  (unless (eq t (car retval))
+(cl-return-from eglot--register-unregister
+  (eglot--reply
+   proc jsonrpc-id
+   :error `(:code -32601 :message ,(or (cadr retval) 
"sorry")
+  (eglot--reply proc jsonrpc-id :result (eglot--obj :message "OK")))
+
 (cl-defun eglot--server-client/registerCapability
 (proc &key id registrations)
-  "Handle notification client/registerCapability"
-  (let ((jsonrpc-id id)
-(done (make-symbol "done")))
-(catch done
-  (mapc
-   (lambda (reg)
- (apply
-  (cl-function
-   (lambda (&key id method registerOptions)
- (pcase-let*
- ((handler-sym (intern (concat "eglot--register-"
-   method)))
-  (`(,ok ,message)

[elpa] externals/eglot 1dc2a9f 021/139: Implement spinners and RLS's window/progress

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 1dc2a9fe3521586b15f90ed74d06f586fe478dfd
Author: João Távora 
Commit: João Távora 

Implement spinners and RLS's window/progress

* eglot.el (eglot--window/progress): New.
(eglot--mode-line-format): Rework.
(eglot--snpinner): New var.
(compile): require it.
---
 eglot.el | 107 ++-
 1 file changed, 64 insertions(+), 43 deletions(-)

diff --git a/eglot.el b/eglot.el
index ab13b3a..e5d6937 100644
--- a/eglot.el
+++ b/eglot.el
@@ -30,6 +30,7 @@
 (require 'url-parse)
 (require 'url-util)
 (require 'pcase)
+(require 'compile) ; for some faces
 
 (defgroup eglot nil
   "Interaction with Language Server Protocol servers"
@@ -87,6 +88,10 @@
 (eglot--define-process-var eglot--moribund nil
   "Non-nil if process is about to exit")
 
+(eglot--define-process-var eglot--spinner `(nil nil t)
+  "\"Spinner\" used by some servers.
+A list (ID WHAT DONE-P).")
+
 (defun eglot--command (&optional errorp)
   (let ((probe (cdr (assoc major-mode eglot-executables
 (unless (or (not errorp)
@@ -591,17 +596,15 @@ running.  INTERACTIVE is t if called interactively."
 
 (defun eglot--mode-line-format ()
   "Compose the mode-line format spec."
-  (let* ((proc (eglot--current-process))
- (name (and proc
-(process-live-p proc)
-(eglot--short-name proc)))
- (pending (and proc
-   (hash-table-count
-(eglot--pending-continuations proc
- (format-number (lambda (n) (cond ((and n (not (zerop n)))
-   (format "%d" n))
-  (n "-")
-  (t "*")
+  (pcase-let* ((proc (eglot--current-process))
+   (name (and proc
+  (process-live-p proc)
+  (eglot--short-name proc)))
+   (pending (and proc
+ (hash-table-count
+  (eglot--pending-continuations proc
+   (`(,_id ,what ,done-p) (and proc
+   (eglot--spinner
 (append
  `((:propertize "eglot"
 face eglot-mode-line
@@ -612,41 +615,51 @@ running.  INTERACTIVE is t if called interactively."
 mouse-face mode-line-highlight
 help-echo "mouse-1: pop-up EGLOT menu"
 ))
- (if name
- `(" "
-   (:propertize
-,name
-face eglot-mode-line
-keymap ,(let ((map (make-sparse-keymap)))
-  (define-key map [mode-line mouse-1] 'eglot-events-buffer)
-  (define-key map [mode-line mouse-2] 'eglot-quit-server)
-  (define-key map [mode-line mouse-3] 'eglot-new-process)
-  map)
-mouse-face mode-line-highlight
-help-echo ,(concat "mouse-1: events buffer\n"
-   "mouse-2: quit server\n"
-   "mouse-3: new process"))
-   "/"
-   (:propertize
-,(funcall format-number pending)
-help-echo ,(if name
-   (format
-"%s pending events outgoing\n%s"
+ (when name
+   `(":"
+ (:propertize
+  ,name
+  face eglot-mode-line
+  keymap ,(let ((map (make-sparse-keymap)))
+(define-key map [mode-line mouse-1] 'eglot-events-buffer)
+(define-key map [mode-line mouse-2] 'eglot-quit-server)
+(define-key map [mode-line mouse-3] 'eglot-new-process)
+map)
+  mouse-face mode-line-highlight
+  help-echo ,(concat "mouse-1: go to events buffer\n"
+ "mouse-2: quit server\n"
+ "mouse-3: new process"))
+ ,@(when (and what (not done-p))
+ `("/"
+   (:propertize
+,what
+help-echo ,(concat "mouse-1: go to events buffer")
+mouse-face mode-line-highlight
+face compilation-mode-line-run
+keymap ,(let ((map (make-sparse-keymap)))
+  (define-key map [mode-line mouse-1]
+'eglot-events-buffer)
+  map
+ ,@(when (cl-plusp pending)
+ `("/"
+   (:propertize
+(format "%d" pending)
+help-echo ,(format
+"%s unanswered requests\n%s"
 pending
 (concat "mouse-1: go to events buffer"
 "mouse-3: forget pending continuations"))
- "No current connection")
-mouse-face mode-l

[elpa] externals/eglot 92bf3a0 038/139: Signal textDocument/didClose

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 92bf3a0485b4af11c0915bd3467e21c7b4bfe21a
Author: João Távora 
Commit: João Távora 

Signal textDocument/didClose

* eglot.el (eglot-editing-mode): Signal didClose.
(eglot--signalDidClose): New.
---
 eglot.el | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 12e7fef..8584440 100644
--- a/eglot.el
+++ b/eglot.el
@@ -671,6 +671,7 @@ running.  INTERACTIVE is t if called interactively."
 (eglot-mode 1)
 (add-hook 'after-change-functions 'eglot--after-change nil t)
 (add-hook 'flymake-diagnostic-functions 'eglot-flymake-backend nil t)
+(add-hook 'kill-buffer-hook 'eglot--signalDidClose nil t)
 (flymake-mode 1)
 (if (eglot--current-process)
 (eglot--signalDidOpen)
@@ -679,7 +680,8 @@ running.  INTERACTIVE is t if called interactively."
 (eglot--warn "No process"
(t
 (remove-hook 'flymake-diagnostic-functions 'eglot-flymake-backend t)
-(remove-hook 'after-change-functions 'eglot--after-change t
+(remove-hook 'after-change-functions 'eglot--after-change t)
+(remove-hook 'kill-buffer-hook 'eglot--signalDidClose t
 
 (define-minor-mode eglot-mode
   "Minor mode for all buffers managed by EGLOT in some way."  nil
@@ -832,6 +834,12 @@ running.  INTERACTIVE is t if called interactively."
  (eglot--obj :textDocument
  (eglot--current-buffer-TextDocumentItem
 
+(defun eglot--signalDidClose ()
+  (eglot--notify (eglot--current-process-or-lose)
+ :textDocument/didClose
+ (eglot--obj :textDocument
+ (eglot--current-buffer-TextDocumentItem
+
 (defun eglot--maybe-signal-didChange ()
   (when eglot--recent-changes
 (save-excursion



[elpa] externals/eglot cc183a6 043/139: Fix assorted bugs

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit cc183a6c62567bf7fb6303e133455ad9c8da7479
Author: João Távora 
Commit: João Távora 

Fix assorted bugs

* eglot.el (eglot--special-buffer-process): Must be buffer-local.
(eglot--define-process-var): Fix disaster waiting to happen.
(eglot--process-receive): Explicitly pass PROC to
eglot--pending-continuations.
(eglot--textDocument/publishDiagnostics): Clear unreported diagnostics
---
 eglot.el | 33 ++---
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/eglot.el b/eglot.el
index f4ac858..5c014f3 100644
--- a/eglot.el
+++ b/eglot.el
@@ -48,7 +48,7 @@
 (defvar eglot-editing-mode) ; forward decl
 (defvar eglot-mode) ; forward decl
 
-(defvar eglot--special-buffer-process nil
+(defvar-local eglot--special-buffer-process nil
   "Current buffer's eglot process.")
 
 (defun eglot--current-process ()
@@ -78,13 +78,14 @@ after setting it."
   (declare (indent 2))
   `(progn
  (put ',var-sym 'function-documentation ,doc)
- (defun ,var-sym (&optional process)
-   (let* ((proc (or process (eglot--current-process-or-lose)))
-  (probe (process-get proc ',var-sym)))
- (or probe
- (let ((def ,initval))
-   (process-put proc ',var-sym def)
-   def
+ (defun ,var-sym (proc)
+   (let* ((plist (process-plist proc))
+  (probe (plist-member plist ',var-sym)))
+ (if probe
+ (cadr probe)
+   (let ((def ,initval))
+ (process-put proc ',var-sym def)
+ def
  (gv-define-setter ,var-sym (to-store &optional process)
(let* ((prop ',var-sym))
  ,(let ((form '(let ((proc (or ,process 
(eglot--current-process-or-lose
@@ -417,7 +418,8 @@ identifier.  ERROR is non-nil if this is an error."
   (let* ((response-id (plist-get message :id))
  (err (plist-get message :error))
  (continuations (and response-id
- (gethash response-id 
(eglot--pending-continuations)
+ (gethash response-id
+  (eglot--pending-continuations proc)
 (eglot--log-event proc
   (cond ((not response-id)
  'server-notification)
@@ -436,7 +438,7 @@ identifier.  ERROR is non-nil if this is an error."
   (continuations
(cancel-timer (cl-third continuations))
(remhash response-id
-(eglot--pending-continuations))
+(eglot--pending-continuations proc))
(cond (err
   (apply (cl-second continuations) err))
  (t
@@ -655,11 +657,12 @@ running.  INTERACTIVE is t if called interactively."
   message
into diags
finally
-   (if eglot--current-flymake-report-fn
-   (funcall eglot--current-flymake-report-fn
-diags)
- (setq eglot--unreported-diagnostics
-   diags))
+   (if (null eglot--current-flymake-report-fn)
+   (setq eglot--unreported-diagnostics
+ diags)
+ (funcall eglot--current-flymake-report-fn
+  diags)
+ (setq eglot--unreported-diagnostics nil))
  (t
   (eglot--message "OK so %s isn't visited" filename)
 



[elpa] externals/eglot df5d76d 065/139: Reply to client/registerCapability (don't handle it yet)

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit df5d76d6a0f3b0f72a1cf11b73c349aa5d990f5a
Author: João Távora 
Commit: João Távora 

Reply to client/registerCapability (don't handle it yet)

* eglot.el (eglot--server-client/registerCapability): New
function.
---
 eglot.el | 13 +
 1 file changed, 13 insertions(+)

diff --git a/eglot.el b/eglot.el
index 332f1fe..d073be2 100644
--- a/eglot.el
+++ b/eglot.el
@@ -962,6 +962,19 @@ running.  INTERACTIVE is t if called interactively."
  (t
   (eglot--message "OK so %s isn't visited" filename)
 
+(cl-defun eglot--server-client/registerCapability
+(proc &key id registrations)
+  "Handle notification client/registerCapability"
+  (mapc (lambda (reg)
+  (apply (cl-function
+  (lambda (&key _id _method _registerOptions)
+;;; TODO: handle this
+))
+ reg))
+registrations)
+  (eglot--reply proc id :error (eglot--obj :code -32601
+   :message "sorry :-(")))
+
 (defvar eglot--recent-before-changes nil
   "List of recent changes as collected by `eglot--before-change'.")
 (defvar eglot--recent-after-changes nil



[elpa] externals/elpa 77856c2 130/139: Reinstate the catch/loop/throw idiom in eglot-request

2018-05-14 Thread Jo�o T�vora
branch: externals/elpa
commit 77856c2f9194b6975421be411d80cfcf102fd10d
Author: João Távora 
Commit: João Távora 

Reinstate the catch/loop/throw idiom in eglot-request

This reverts parts of commit 29f58a6514aec28e4e6df9611e4f58c7289e3cc6.

Unfortunately, this may cause problems when calling the error
callbacks directly as in the process sentinel. In that particular
scenario the accept-process-output won't have return, because no
output has is being handled. Consequently, if we're unlucky, we have
another 30 seconds to way before the flag is tested and the loop
exits.

* eglot.el (eglot-request): Use catch/loop/throw again
---
 eglot.el | 33 +++--
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/eglot.el b/eglot.el
index 13f6f61..6f90349 100644
--- a/eglot.el
+++ b/eglot.el
@@ -651,20 +651,25 @@ DEFERRED is passed to `eglot--async-request', which see."
   ;; bad idea, since that might lead to the request never having a
   ;; chance to run, because `eglot--ready-predicates'.
   (when deferred (eglot--signal-textDocument/didChange))
-  (let ((retval))
-(eglot--async-request
- proc method params
- :success-fn (lambda (&rest args)
-   (setq retval `(done ,(if (vectorp (car args))
-(car args) args
- :error-fn (eglot--lambda (&key code message &allow-other-keys)
- (setq retval `(error ,(format "Oops: %s: %s" code message
- :timeout-fn (lambda ()
-   (setq retval '(error "Timed out")))
- :deferred deferred)
-(while (not retval) (accept-process-output nil 30))
-(when (eq 'error (car retval)) (eglot--error (cadr retval)))
-(cadr retval)))
+  (let* ((done (make-symbol "eglot--request-catch-tag"))
+ (res
+  (catch done (eglot--async-request
+   proc method params
+   :success-fn (lambda (&rest args)
+ (throw done (if (vectorp (car args))
+ (car args) args)))
+   :error-fn (eglot--lambda
+ (&key code message &allow-other-keys)
+   (throw done
+  `(error ,(format "Oops: %s: %s"
+   code message
+   :timeout-fn (lambda ()
+ (throw done '(error "Timed out")))
+   :deferred deferred)
+ ;; now spin, baby!
+ (while t (accept-process-output nil 0.01)
+(when (and (listp res) (eq 'error (car res))) (eglot--error (cadr res)))
+res))
 
 (cl-defun eglot--notify (process method params)
   "Notify PROCESS of something, don't expect a reply.e"



[elpa] externals/eglot 95983c9 028/139: Change status to error everytime an error is found

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 95983c9b526da4258c862d55f27099ec4f2350ee
Author: João Távora 
Commit: João Távora 

Change status to error everytime an error is found

* eglot.el (eglot--process-receive): Also set error status.
(eglot--request): Fix a compilation warning.
---
 eglot.el | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 1f2737e..457f316 100644
--- a/eglot.el
+++ b/eglot.el
@@ -317,6 +317,8 @@ identifier.  ERROR is non-nil if this is an error."
   message
   response-id
   err)
+(when err
+  (setf (eglot--status proc) '("error" t)))
 (cond ((and response-id
 (not continuations))
(eglot--warn "Ooops no continuation for id %s" response-id))
@@ -384,7 +386,7 @@ identifier.  ERROR is non-nil if this is an error."
  (error-fn
   (or error-fn
   (cl-function
-   (lambda (&key data code message &allow-other-keys)
+   (lambda (&key code message &allow-other-keys)
  (setf (eglot--status process) '("error" t))
  (eglot--warn
   "(request) Request id=%s errored with code=%s: %s"



[elpa] externals/eglot 3489176 004/139: Add a mode-line construct and some minor fanciness

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 348917660aab0ecef794561160fd95a0fdf820dd
Author: João Távora 
Commit: João Távora 

Add a mode-line construct and some minor fanciness
---
 eglot.el | 126 ---
 1 file changed, 112 insertions(+), 14 deletions(-)

diff --git a/eglot.el b/eglot.el
index 166f23c..92c1216 100644
--- a/eglot.el
+++ b/eglot.el
@@ -64,6 +64,9 @@
 (eglot--define-process-var eglot--message-mark nil
   "Point where next unread message starts")
 
+(eglot--define-process-var eglot--short-name nil
+  "A short name")
+
 (eglot--define-process-var eglot--expected-bytes nil
   "How many bytes declared by server")
 
@@ -92,25 +95,29 @@
   (and timeout-fn
`((cl-function ,timeout-fn)
 
-(defun eglot--command ()
-  (cdr (assoc major-mode eglot-executables)))
+(defun eglot--command (&optional errorp)
+  (let ((probe (cdr (assoc major-mode eglot-executables
+(unless (or (not errorp)
+probe)
+  (eglot--error "Don't know how to start EGLOT for %s buffers"
+major-mode))
+probe))
 
-(defun eglot-new-process (&optional interactive)
+(defun eglot-new-process (&optional _interactive)
   "Starts a new EGLOT process and initializes it"
   (interactive (list t))
   (let ((project (project-current))
-(command (eglot--command)))
-(unless command (eglot--error "Cannot work without an LSP executable"))
+(command (eglot--command 'errorp)))
 (unless project (eglot--error "Cannot work without a current project!"))
 (let ((current-process (eglot--current-process)))
   (when (and current-process
  (process-live-p current-process))
 (eglot-quit-server current-process 'sync)))
-(let ((good-name
-   (format "EGLOT server (%s)"
-   (file-name-base
-(directory-file-name
- (car (project-roots (project-current
+(let* ((short-name (file-name-base
+(directory-file-name
+ (car (project-roots (project-current))
+   (good-name
+(format "EGLOT server (%s)" short-name)))
   (with-current-buffer (get-buffer-create
 (format "*%s inferior*" good-name))
 (let* ((proc
@@ -123,6 +130,7 @@
   :stderr (get-buffer-create (format "*%s stderr*"
  good-name
(inhibit-read-only t))
+  (setf (eglot--short-name proc) short-name)
   (puthash (project-current) proc eglot--processes-by-project)
   (erase-buffer)
   (let ((marker (point-marker)))
@@ -133,9 +141,7 @@
 (let ((inhibit-read-only t))
   (insert
(format "\n---\n"
-  (eglot--protocol-initialize proc)
-  (when interactive
-(display-buffer (eglot-events-buffer proc
+  (eglot--protocol-initialize proc))
 
 (defun eglot-quit-server (process &optional sync)
   (interactive (list (eglot--current-process)))
@@ -246,7 +252,7 @@
buffer))
buffer
 (when interactive
-  (pop-to-buffer buffer))
+  (display-buffer buffer))
 buffer))
 
 (defun eglot--log-event (proc type message)
@@ -295,6 +301,10 @@
 (defun eglot--next-request-id ()
   (setq eglot--next-request-id (1+ eglot--next-request-id)))
 
+(defun eglot-forget-pending-continuations (process)
+  (interactive (eglot--current-process))
+  (clrhash (eglot--pending-continuations process)))
+
 (defun eglot--call-with-request (process
   async-p
   method
@@ -389,5 +399,93 @@
  (apply #'format format args)
  :warning))
 
+
+
+;;; Mode line
+;;;
+
+
+(defface eglot-mode-line
+  '((t (:inherit font-lock-constant-face :weight bold)))
+  "Face for package-name in EGLOT's mode line."
+  :group 'eglot)
+
+(define-minor-mode eglot-mode
+  "Minor mode for buffers where EGLOT is possible")
+
+(defvar eglot-menu)
+
+(defvar eglot-mode-map (make-sparse-keymap))
+
+(easy-menu-define eglot-menu eglot-mode-map "SLY"
+  `("EGLOT" ))
+
+(defvar eglot--mode-line-format
+  `(:eval (eglot--mode-line-format)))
+
+(put 'eglot--mode-line-format 'risky-local-variable t)
+
+(defun eglot--mode-line-format ()
+  (let* ((proc (eglot--current-process))
+ (name (and proc
+(process-live-p proc)
+(eglot--short-name proc)))
+ (pending (and proc
+   (hash-table-count
+(eglot--pending-continuations proc
+ (format-number (lambda (n) (cond ((and n (not (zerop n)))
+   (format "%d" n))
+  (n "-")
+  

[elpa] externals/eglot 16be2fc 020/139: Fix parser to accept multiple messages in one chunk

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit 16be2fc884f6a450a31245789ec05969ae396177
Author: João Távora 
Commit: João Távora 

Fix parser to accept multiple messages in one chunk

* eglot.el (eglot--process-filter): Redesign slightly.
(eglot--message-mark): Remove. don't need this.
---
 eglot.el | 130 +++
 1 file changed, 64 insertions(+), 66 deletions(-)

diff --git a/eglot.el b/eglot.el
index cd213e7..ab13b3a 100644
--- a/eglot.el
+++ b/eglot.el
@@ -69,9 +69,6 @@
  `(let ((proc (or ,process (eglot--current-process-or-lose
 (process-put proc ',prop ,to-store))
 
-(eglot--define-process-var eglot--message-mark nil
-  "Point where next unread message starts")
-
 (eglot--define-process-var eglot--short-name nil
   "A short name for the process")
 
@@ -139,9 +136,6 @@ INTERACTIVE is t if called interactively."
 (setf (eglot--short-name proc) short-name)
 (puthash (project-current) proc eglot--processes-by-project)
 (erase-buffer)
-(let ((marker (point-marker)))
-  (set-marker-insertion-type marker nil)
-  (setf (eglot--message-mark proc) marker))
 (read-only-mode t)
 (with-current-buffer (eglot-events-buffer proc)
   (let ((inhibit-read-only t))
@@ -170,71 +164,75 @@ INTERACTIVE is t if called interactively."
   (delete-process process
 
 (defun eglot--process-filter (proc string)
+  "Called when new data STRING has arrived for PROC."
   (when (buffer-live-p (process-buffer proc))
 (with-current-buffer (process-buffer proc)
-  (let ((moving (= (point) (process-mark proc)))
-(inhibit-read-only t)
+  (let ((inhibit-read-only t)
 (pre-insertion-mark (copy-marker (process-mark proc)))
-(expected-bytes (eglot--expected-bytes proc))
-(message-mark (eglot--message-mark proc)))
-(save-excursion
-  ;; Insert the text, advancing the process marker.
-  (goto-char (process-mark proc))
-  (insert string)
-  (set-marker (process-mark proc) (point)))
-(if moving (goto-char (process-mark proc)))
-
-;; check for new message header
+(expected-bytes (eglot--expected-bytes proc)))
+;; Insert the text, advancing the process marker.
+(goto-char (process-mark proc))
+(insert string)
+(set-marker (process-mark proc) (point))
+
+;; goto point just before insertion
 ;;
-(save-excursion
-  (goto-char pre-insertion-mark)
-  (let* ((match (search-forward-regexp
- "\\(?:.*: .*\r\n\\)*Content-Length: 
\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n"
- (+ (point) 100)
- t))
- (new-expected-bytes (and match
-  (string-to-number (match-string 
1)
-(when new-expected-bytes
-  (when expected-bytes
-(eglot--warn
- (concat "Unexpectedly starting new message but %s bytes "
- "reportedly remaining from previous one")
- expected-bytes))
-  (set-marker message-mark (point))
-  (setf (eglot--expected-bytes proc) new-expected-bytes)
-  (setq expected-bytes new-expected-bytes
-
-;; check for message body
+(goto-char pre-insertion-mark)
+
+;; loop for each message (more than one might have arrived)
 ;;
-(let ((available-bytes (- (position-bytes (process-mark proc))
-  (position-bytes message-mark
-  (cond ((not expected-bytes)
- (eglot--warn
-  "Skipping %s bytes of unexpected garbage from process %s"
-  available-bytes
-  proc)
- (set-marker message-mark (process-mark proc)))
-((>= available-bytes
- expected-bytes)
- (let* ((message-end (byte-to-position
-  (+ (position-bytes message-mark)
- expected-bytes
-   (unwind-protect
-   (save-excursion
- (save-restriction
-   (goto-char message-mark)
-   (narrow-to-region message-mark
- message-end)
-   (eglot--process-receive
-proc
-(let ((json-object-type 'plist))
-  (json-read)
- (set-marker message-mark message-end)
- (setf (eglot--expected-bytes proc) nil
-(t
- ;; just adding some stuff to the end that doesn't yet
- 

[elpa] externals/eglot a7ddce6 080/139: Support javascript's javascript-typescript-langserver

2018-05-14 Thread Jo�o T�vora
branch: externals/eglot
commit a7ddce694ac1f35c240700ff6f9edd379704feeb
Author: João Távora 
Commit: João Távora 

Support javascript's javascript-typescript-langserver

* README.md: Improve a bit

* eglot.el (eglot--make-process): Take MANAGED-MAJOR-MODE arg
(eglot-executables): Add basic javascript support.
(eglot--connect): Pass mode to eglot--make-process
(eglot--interactive): Check that guessed command is a listp.
(eglot): Minor improvement to message.
(eglot--current-buffer-TextDocumentItem): Guess language from mode
symbol.
---
 README.md | 42 +-
 eglot.el  | 41 +++--
 2 files changed, 60 insertions(+), 23 deletions(-)

diff --git a/README.md b/README.md
index 8809421..0314664 100644
--- a/README.md
+++ b/README.md
@@ -11,14 +11,41 @@ M-x eglot
 ```
 
 *That's it*. Either this guesses the local LSP program to start for
-the language of your choice or it prompts you for such a thing. 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`.
+the language of your choice or it prompts you for such a
+thing. Currently, if you have these programs installed, it works
+out-of-the-box for:
 
-## Differences to lsp-mode.el
+* Javascript's [javascript-typescript-stdio][javascript-typescript-langserver]
+* Rust's [rls][rls]
+* Python's [pyls][pyls]
+
+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
+
+- [x] textDocument/didChange (incremental)
+- [x] textDocument/didClose
+- [x] textDocument/didOpen
+- [x] textDocument/didSave
+
+- [ ] textDocument/codeAction
+- [ ] textDocument/completion (incl. completion/resolve)
+- [x] textDocument/definition
+- [ ] textDocument/documentHighlight
+- [ ] textDocument/documentSymbol
+- [ ] textDocument/executeCommand
+- [ ] textDocument/format
+- [ ] textDocument/hover
+- [ ] textDocument/rename
+- [x] textDocument/references
+- [ ] textDocument/signatureHelp
+- [x] workspace/symbol
+
+# Differences to lsp-mode.el
 
 This is really beta and currently does less than
-[lsp-mode.el](https://github.com/emacs-lsp/lsp-mode) which is more
+[lsp-mode.el][emacs-lsp] which is more
 mature. Though I think `eglot.el` will eventually beat it, you could
 be better served with `lsp-mode.el` for now.
 
@@ -45,5 +72,10 @@ Differences under the hood:
   tiny change. 
 - Its missing tests! This is *not good*
 
+[rls]: https://github.com/rust-lang-nursery/rls
+[pyls]: https://github.com/palantir/python-language-server
+[javascript-typescript-langserver]: 
https://github.com/sourcegraph/javascript-typescript-langserver
+[emacs-lsp]: https://github.com/emacs-lsp/lsp-mode
+
 

diff --git a/eglot.el b/eglot.el
index cd48519..045588d 100644
--- a/eglot.el
+++ b/eglot.el
@@ -42,8 +42,10 @@
   :prefix "eglot-"
   :group 'applications)
 
-(defvar eglot-executables '((rust-mode . ("rls"))
-(python-mode . ("pyls")))
+(defvar eglot-executables
+  '((rust-mode . ("rls"))
+(python-mode . ("pyls"))
+(js-mode . ("javascript-typescript-stdio")))
   "Alist mapping major modes to server executables.")
 
 (defface eglot-mode-line
@@ -145,23 +147,24 @@ list of a single string of the form :")
 (eglot--define-process-var eglot--buffer-open-count (make-hash-table)
   "Keeps track of didOpen/didClose notifs for each buffer.")
 
-(defun eglot--make-process (name contact)
+(defun eglot--make-process (name managed-major-mode contact)
   "Make a process from CONTACT.
 NAME is a name to give the inferior process or connection.
+MANAGED-MAJOR-MODE is a symbol naming a major mode.
 CONTACT is as `eglot--contact'.  Returns a process object."
-  (let* ((readable-name (format "EGLOT server (%s)" name))
+  (let* ((readable-name (format "EGLOT server (%s/%s)" name 
managed-major-mode))
  (buffer (get-buffer-create
   (format "*%s inferior*" readable-name)))
- (singleton (and (null (cdr contact)) (car contact)))
+ singleton
  (proc
-  (if (and
-   singleton
-   (string-match "^[\s\t]*\\(.*\\):\\([[:digit:]]+\\)[\s\t]*$"
- singleton))
+  (if (and (setq singleton (and (null (cdr contact)) (car contact)))
+   (string-match "^[\s\t]*\\(.*\\):\\([[:digit:]]+\\)[\s\t]*$"
+ singleton))
   (open-network-stream readable-name
buffer
(match-string 1 singleton)
-   (string-to-number (match-string 2 
singleton)))
+   (string-to-number
+(match-string 2 singleton)))
 (make-process
  :name readable-name
  :buffer b

  1   2   3   >