[elpa] externals/eglot 0b9cffe 08/12: Per #22: Apply text edits atomically

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 0b9cffeda617679772f88f4c232f0b8704c1ae33
Author: João Távora 
Commit: João Távora 

Per #22: Apply text edits atomically

As suggested by mkcms , but do it in
eglot--apply-text-edits, where it benefits all its users.

* eglot.el (eglot--apply-text-edits): Use atomic-change-group.
---
 eglot.el | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/eglot.el b/eglot.el
index e96a3e6..489e365 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1583,17 +1583,18 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
   (unless (or (not version) (equal version eglot--versioned-identifier))
 (eglot--error "Edits on `%s' require version %d, you have %d"
   (current-buffer) version eglot--versioned-identifier))
-  (mapc (pcase-lambda (`(,newText ,beg . ,end))
-  (save-restriction
-(narrow-to-region beg end)
-(let ((source (current-buffer)))
-  (with-temp-buffer
-(insert newText)
-(let ((temp (current-buffer)))
-  (with-current-buffer source (replace-buffer-contents 
temp)))
-(mapcar (eglot--lambda (&key range newText)
-  (cons newText (eglot--range-region range 'markers)))
-edits))
+  (atomic-change-group
+(mapc (pcase-lambda (`(,newText ,beg . ,end))
+(save-restriction
+  (narrow-to-region beg end)
+  (let ((source (current-buffer)))
+(with-temp-buffer
+  (insert newText)
+  (let ((temp (current-buffer)))
+(with-current-buffer source (replace-buffer-contents 
temp)))
+  (mapcar (eglot--lambda (&key range newText)
+(cons newText (eglot--range-region range 'markers)))
+  edits)))
   (eglot--message "%s: Performed %s edits" (current-buffer) (length edits)))
 
 (defun eglot--apply-workspace-edit (wedit &optional confirm)



[elpa] externals/eglot updated (a1f1dd6 -> 0176264)

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

  from  a1f1dd6   * eglot.el (Version): Bump to 0.10
   new  a9010f1   Implement formatting (#19)
   new  efc0f45   Minor cleanup to new textDocument/formatting feature
   new  610d95b   Use gfm-mode for formatted strings (#20)
   new  364348d   Close #25: Improve eglot-ensure and mention it in 
README.md
   new  0cde01f   Close #26: Guess server for js2-mode and rjsx-mode
   new  cbc418c   Per #22: Simplify eglot-format-buffer
   new  17ef74e   Defer textDocument/formatting requests
   new  0b9cffe   Per #22: Apply text edits atomically
   new  df5e72e   Close #23: Report progress when applying edits
   new  48c3f45   Close #22: Apply text edits as a single undoable edit
   new  04ef055   Close #27: empty ranges are valid in LSP
   new  0176264   * eglot.el (Version): Bump to 0.11


Summary of changes:
 README.md  |  18 ++--
 eglot-tests.el |  20 +
 eglot.el   | 132 -
 3 files changed, 129 insertions(+), 41 deletions(-)



[elpa] externals/eglot 610d95b 03/12: Use gfm-mode for formatted strings (#20)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 610d95b88a238d0eb2d631cfaa4f2afecffe0211
Author: Rami Chowdhury <460769+neca...@users.noreply.github.com>
Commit: João Távora 

Use gfm-mode for formatted strings (#20)

* eglot.el (eglot--format-markup): Use gfm-mode instead of
markdown-mode.

Copyright-paperwork-exempt: yes
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index ac17fb8..1aa3661 100644
--- a/eglot.el
+++ b/eglot.el
@@ -847,7 +847,7 @@ If optional MARKER, return a marker instead"
   "Format MARKUP according to LSP's spec."
   (pcase-let ((`(,string ,mode)
(if (stringp markup) (list (string-trim markup)
-  (intern "markdown-mode"))
+  (intern "gfm-mode"))
  (list (plist-get markup :value)
(intern (concat (plist-get markup :language) "-mode" 
))
 (with-temp-buffer



[elpa] externals/eglot df5e72e 09/12: Close #23: Report progress when applying edits

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit df5e72ee2589308abee70231cf9ee2a2cee93f22
Author: João Távora 
Commit: João Távora 

Close #23: Report progress when applying edits

Use make-progress-reporter in eglot--apply-text-edits

As suggested by mkcms , but do it in
eglot--apply-text-edits, where it benefits all its users.

* eglot.el (eglot--apply-text-edits): Use a progress reporter.
Fix marker point recovery.
---
 eglot.el | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/eglot.el b/eglot.el
index 489e365..9e686ee 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1584,18 +1584,27 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
 (eglot--error "Edits on `%s' require version %d, you have %d"
   (current-buffer) version eglot--versioned-identifier))
   (atomic-change-group
-(mapc (pcase-lambda (`(,newText ,beg . ,end))
-(save-restriction
-  (narrow-to-region beg end)
+(let* ((howmany (length edits))
+   (reporter (make-progress-reporter
+  (format "[eglot] applying %s edits to `%s'..."
+  howmany (current-buffer))
+  0 howmany))
+   (done 0))
+  (mapc (pcase-lambda (`(,newText ,beg . ,end))
   (let ((source (current-buffer)))
 (with-temp-buffer
   (insert newText)
   (let ((temp (current-buffer)))
-(with-current-buffer source (replace-buffer-contents 
temp)))
-  (mapcar (eglot--lambda (&key range newText)
-(cons newText (eglot--range-region range 'markers)))
-  edits)))
-  (eglot--message "%s: Performed %s edits" (current-buffer) (length edits)))
+(with-current-buffer source
+  (save-excursion
+(save-restriction
+  (narrow-to-region beg end)
+  (replace-buffer-contents temp)))
+  (progress-reporter-update reporter (cl-incf done)))
+(mapcar (eglot--lambda (&key range newText)
+  (cons newText (eglot--range-region range 'markers)))
+edits))
+  (progress-reporter-done reporter
 
 (defun eglot--apply-workspace-edit (wedit &optional confirm)
   "Apply the workspace edit WEDIT.  If CONFIRM, ask user first."



[elpa] externals/eglot 364348d 04/12: Close #25: Improve eglot-ensure and mention it in README.md

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 364348d134c1b49e94c6d7916cedd01c91292d76
Author: João Távora 
Commit: João Távora 

Close #25: Improve eglot-ensure and mention it in README.md

* README.md (Installation and Usage): Mention eglot-ensure.

* eglot.el (eglot-ensure): No-op for non-file buffers.
(eglot--connect): Don't fallback to 'eglot-lsp-server here.
(eglot--guess-contact): Error if something can't be guessed.
---
 README.md | 11 ++-
 eglot.el  | 44 ++--
 2 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/README.md b/README.md
index 936aaea..c3f4434 100644
--- a/README.md
+++ b/README.md
@@ -35,13 +35,22 @@ I'll add to this list as I test more servers. In the 
meantime you can
 customize `eglot-server-programs`:
 
 ```lisp
-(add-to-list 'eglot-server-programs '(fancy-mode . ("fancy-language-server" 
"--args"")))
+(add-to-list 'eglot-server-programs '(foo-mode . ("foo-language-server" 
"--args"")))
 ```
 
 Let me know how well it works and we can add it to the list.  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`.
 
+You can also do:
+
+```lisp
+  (add-hook 'foo-mode-hook 'eglot-ensure)
+```
+
+To attempt to start an eglot session automatically everytime a
+`foo-mode` buffer is visited.
+
 # Commands and keybindings
 
 Here's a summary of available commands:
diff --git a/eglot.el b/eglot.el
index 1aa3661..ecbd509 100644
--- a/eglot.el
+++ b/eglot.el
@@ -299,7 +299,7 @@ class SERVER-CLASS."
  server connect-success)
 (setq server
   (make-instance
-   (or server-class 'eglot-lsp-server)
+   server-class
:process proc :major-mode managed-major-mode
:project project :contact contact
:name name :project-nickname nickname
@@ -341,23 +341,28 @@ class SERVER-CLASS."
 
 (defun eglot--guess-contact (&optional interactive)
   "Helper for `eglot'.
-Return (MANAGED-MODE PROJECT CONTACT CLASS).
-If INTERACTIVE, maybe prompt user."
+Return (MANAGED-MODE PROJECT CLASS CONTACT).  If INTERACTIVE is
+non-nil, maybe prompt user, else error as soon as something can't
+be guessed."
   (let* ((guessed-mode (if buffer-file-name major-mode))
  (managed-mode
   (cond
-   ((or (>= (prefix-numeric-value current-prefix-arg) 16)
-(not guessed-mode))
+   ((and interactive
+ (or (>= (prefix-numeric-value current-prefix-arg) 16)
+ (not guessed-mode)))
 (intern
  (completing-read
   "[eglot] Start a server to manage buffers of what major mode? "
   (mapcar #'symbol-name (eglot--all-major-modes)) nil t
   (symbol-name guessed-mode) nil (symbol-name guessed-mode) nil)))
+   ((not guessed-mode)
+(eglot--error "Can't guess mode to manage for `%s'" 
(current-buffer)))
(t guessed-mode)))
  (project (or (project-current) `(transient . ,default-directory)))
  (guess (cdr (assoc managed-mode eglot-server-programs)))
- (class (and (consp guess) (symbolp (car guess))
- (prog1 (car guess) (setq guess (cdr guess)
+ (class (or (and (consp guess) (symbolp (car guess))
+ (prog1 (car guess) (setq guess (cdr guess
+'eglot-lsp-server))
  (program (and (listp guess) (stringp (car guess)) (car guess)))
  (base-prompt
   (and interactive
@@ -374,16 +379,18 @@ If INTERACTIVE, maybe prompt user."
   (format ", but I can't find `%s' in PATH!" 
program)
   "\n" base-prompt)
  (contact
-  (if prompt
-  (let ((s (read-shell-command
-prompt
-(if program (combine-and-quote-strings guess))
-'eglot-command-history)))
-(if (string-match "^\\([^\s\t]+\\):\\([[:digit:]]+\\)$"
-  (string-trim s))
-(list (match-string 1 s) (string-to-number (match-string 2 
s)))
-  (split-string-and-unquote s)))
-guess)))
+  (or (and prompt
+   (let ((s (read-shell-command
+ prompt
+ (if program (combine-and-quote-strings guess))
+ 'eglot-command-history)))
+ (if (string-match "^\\([^\s\t]+\\):\\([[:digit:]]+\\)$"
+   (string-trim s))
+ (list (match-string 1 s)
+   (string-to-number (match-string 2 s)))
+   (split-string-and-unquote s
+  guess
+  (eglot--error "Couldn't guess for `%s'!" managed-mode
 (list managed-mode project c

[elpa] externals/eglot efc0f45 02/12: Minor cleanup to new textDocument/formatting feature

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit efc0f452ead0b44ae257ba498d54b6e24e4e3f35
Author: João Távora 
Commit: João Távora 

Minor cleanup to new textDocument/formatting feature

* README.md (Language feature): Tick textDocument/formatting

* eglot.el (eglot-client-capabilities): Add formatting capability.
Also move codeAction capability to the correct section.

(eglot-format-buffer): Remove unused lexical variable before-point.
---
 README.md | 2 +-
 eglot.el  | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 2ced833..936aaea 100644
--- a/README.md
+++ b/README.md
@@ -155,7 +155,7 @@ eglot-shutdown`.
 - [ ] documentLink/resolve
 - [ ] textDocument/documentColor
 - [ ] textDocument/colorPresentation (3.6.0)
-- [ ] textDocument/formatting 
+- [x] textDocument/formatting 
 - [ ] textDocument/rangeFormatting
 - [ ] textDocument/onTypeFormatting
 - [x] textDocument/rename
diff --git a/eglot.el b/eglot.el
index 98802de..ac17fb8 100644
--- a/eglot.el
+++ b/eglot.el
@@ -163,7 +163,6 @@ deferred to the future.")
 :workspace (list
 :applyEdit t
 :executeCommand `(:dynamicRegistration :json-false)
-:codeAction `(:dynamicRegistration :json-false)
 :workspaceEdit `(:documentChanges :json-false)
 :didChangeWatchesFiles `(:dynamicRegistration t)
 :symbol `(:dynamicRegistration :json-false))
@@ -179,6 +178,8 @@ deferred to the future.")
  :definition `(:dynamicRegistration :json-false)
  :documentSymbol `(:dynamicRegistration :json-false)
  :documentHighlight  `(:dynamicRegistration :json-false)
+ :codeAction `(:dynamicRegistration :json-false)
+ :formatting `(:dynamicRegistration :json-false)
  :rename `(:dynamicRegistration :json-false)
  :publishDiagnostics `(:relatedInformation :json-false))
 :experimental (list
@@ -1397,8 +1398,6 @@ DUMMY is ignored."
:tabSize tab-width
:insertSpaces (not indent-tabs-mode)))
:textDocument/formatting))
- (before-point
-  (buffer-substring (max (- (point) 60) (point-min)) (point)))
  (after-point
   (buffer-substring (point) (min (+ (point) 60) (point-max
  (regexp (and (not (bobp))



[elpa] externals/eglot 48c3f45 10/12: Close #22: Apply text edits as a single undoable edit

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 48c3f455cf15ad9025821ca227885fcc826c6d54
Author: João Távora 
Commit: João Távora 

Close #22: Apply text edits as a single undoable edit

As suggested by mkcms , but do it in
eglot--apply-text-edits, where it benefits all its users.

Also, just using undo-boundary is not enough, one needs
undo-amalgamate-change-group to mess with the boundaries already in
buffer-undo-list.

* eglot.el (eglot--apply-text-edits): Use
  undo-amalgamate-change-group.
---
 eglot.el | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 9e686ee..2fdf433 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1584,7 +1584,8 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
 (eglot--error "Edits on `%s' require version %d, you have %d"
   (current-buffer) version eglot--versioned-identifier))
   (atomic-change-group
-(let* ((howmany (length edits))
+(let* ((change-group (prepare-change-group))
+   (howmany (length edits))
(reporter (make-progress-reporter
   (format "[eglot] applying %s edits to `%s'..."
   howmany (current-buffer))
@@ -1604,6 +1605,7 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
 (mapcar (eglot--lambda (&key range newText)
   (cons newText (eglot--range-region range 'markers)))
 edits))
+  (undo-amalgamate-change-group change-group)
   (progress-reporter-done reporter
 
 (defun eglot--apply-workspace-edit (wedit &optional confirm)



[elpa] externals/eglot 0cde01f 05/12: Close #26: Guess server for js2-mode and rjsx-mode

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 0cde01f984b4278b1a964a79a98f2758afd10e7c
Author: João Távora 
Commit: João Távora 

Close #26: Guess server for js2-mode and rjsx-mode

* eglot.el (eglot-server-programs): Add entries for js2-mode and
rjsx-mode.  Coalesce entries for c++ and c-mode.  Improve
docstring.
(eglot--guess-contact): Allow lists are keys in
eglot-server-programs.
---
 eglot.el | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/eglot.el b/eglot.el
index ecbd509..447e8c1 100644
--- a/eglot.el
+++ b/eglot.el
@@ -78,15 +78,19 @@
 
 (defvar eglot-server-programs '((rust-mode . (eglot-rls "rls"))
 (python-mode . ("pyls"))
-(js-mode . ("javascript-typescript-stdio"))
+((js-mode
+  js2-mode
+  rjsx-mode) . ("javascript-typescript-stdio"))
 (sh-mode . ("bash-language-server" "start"))
-(c++-mode . (eglot-cquery "cquery"))
-(c-mode . (eglot-cquery "cquery"))
+((c++-mode
+  c-mode) . (eglot-cquery "cquery"))
 (php-mode . ("php" "vendor/felixfbecker/\
 language-server/bin/php-language-server.php")))
   "How the command `eglot' guesses the server to start.
 An association list of (MAJOR-MODE . SPEC) pair.  MAJOR-MODE is a
-mode symbol.  SPEC is
+mode symbol, or a list of mode symbols.  The associated SPEC
+specifies how to start a server for managing buffers of those
+modes.  SPEC can be:
 
 * In the most common case, a list of strings (PROGRAM [ARGS...]).
 PROGRAM is called with ARGS and is expected to serve LSP requests
@@ -359,7 +363,10 @@ be guessed."
 (eglot--error "Can't guess mode to manage for `%s'" 
(current-buffer)))
(t guessed-mode)))
  (project (or (project-current) `(transient . ,default-directory)))
- (guess (cdr (assoc managed-mode eglot-server-programs)))
+ (guess (cdr (assoc managed-mode eglot-server-programs
+(lambda (m1 m2)
+  (or (eq m1 m2)
+  (and (listp m1) (memq m2 m1)))
  (class (or (and (consp guess) (symbolp (car guess))
  (prog1 (car guess) (setq guess (cdr guess
 'eglot-lsp-server))



[elpa] externals/eglot a9010f1 01/12: Implement formatting (#19)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit a9010f1924fa31f686824585cbcf5057c8892afc
Author: mkcms 
Commit: João Távora 

Implement formatting (#19)

Implement textDocument/formatting

* eglot.el (eglot-format-buffer): New command to format
current buffer.

* eglot-tests.el (formatting): New test.
---
 eglot-tests.el | 20 
 eglot.el   | 29 +
 2 files changed, 49 insertions(+)

diff --git a/eglot-tests.el b/eglot-tests.el
index 1a25371..602606c 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -375,6 +375,26 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (while (not eldoc-last-message) (accept-process-output nil 0.1))
 (should (string-match "^exit" eldoc-last-message))
 
+(ert-deftest formatting ()
+  "Test document formatting in a python LSP"
+  (skip-unless (and (executable-find "pyls")
+(or (executable-find "yapf")
+(executable-find "autopep8"
+  (eglot--with-dirs-and-files
+  '(("project" . (("something.py" . "def foo():pass"
+(eglot--with-timeout 4
+  (with-current-buffer
+  (eglot--find-file-noselect "project/something.py")
+(should (eglot--tests-connect))
+(search-forward ":")
+(eglot-format-buffer)
+(should (looking-at "pass"))
+(should (or
+ ;; yapf
+ (string= (buffer-string) "def foo():\npass\n")
+ ;; autopep8
+ (string= (buffer-string) "def foo(): pass\n")))
+
 (ert-deftest javascript-basic ()
   "Test basic autocompletion in a python LSP"
   (skip-unless (executable-find "~/.yarn/bin/javascript-typescript-stdio"))
diff --git a/eglot.el b/eglot.el
index ecfde4a..98802de 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1382,6 +1382,35 @@ DUMMY is ignored."
 :workspace/symbol
 (list :query pattern)
 
+(defun eglot-format-buffer ()
+  "Format contents of current buffer."
+  (interactive)
+  (unless (eglot--server-capable :documentFormattingProvider)
+(eglot--error "Server can't format!"))
+  (let* ((server (eglot--current-server-or-lose))
+ (resp
+  (eglot--request
+   server
+   :textDocument/formatting
+   (list :textDocument (eglot--TextDocumentIdentifier)
+ :options (list
+   :tabSize tab-width
+   :insertSpaces (not indent-tabs-mode)))
+   :textDocument/formatting))
+ (before-point
+  (buffer-substring (max (- (point) 60) (point-min)) (point)))
+ (after-point
+  (buffer-substring (point) (min (+ (point) 60) (point-max
+ (regexp (and (not (bobp))
+  (replace-regexp-in-string
+   "[\s\t\n\r]+" "[\s\t\n\r]+"
+   (concat "\\(" (regexp-quote after-point) "\\)")
+(when resp
+  (save-excursion
+(eglot--apply-text-edits resp))
+  (when (and (bobp) regexp (search-forward-regexp regexp nil t))
+(goto-char (match-beginning 1))
+
 (defun eglot-completion-at-point ()
   "EGLOT's `completion-at-point' function."
   (let ((bounds (bounds-of-thing-at-point 'symbol))



[elpa] tag 0.11 created (now 0176264)

2018-06-22 Thread Jo�o T�vora
capitaomorte pushed a change to tag 0.11.

at  0176264   (commit)
This tag includes the following new commits:

   new  a9010f1   Implement formatting (#19)
   new  efc0f45   Minor cleanup to new textDocument/formatting feature
   new  610d95b   Use gfm-mode for formatted strings (#20)
   new  364348d   Close #25: Improve eglot-ensure and mention it in 
README.md
   new  0cde01f   Close #26: Guess server for js2-mode and rjsx-mode
   new  cbc418c   Per #22: Simplify eglot-format-buffer
   new  17ef74e   Defer textDocument/formatting requests
   new  0b9cffe   Per #22: Apply text edits atomically
   new  df5e72e   Close #23: Report progress when applying edits
   new  48c3f45   Close #22: Apply text edits as a single undoable edit
   new  04ef055   Close #27: empty ranges are valid in LSP
   new  0176264   * eglot.el (Version): Bump to 0.11




[elpa] externals/eglot 0176264 12/12: * eglot.el (Version): Bump to 0.11

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 017626433e8176a07b36e38075deac09f0608db1
Author: João Távora 
Commit: João Távora 

* eglot.el (Version): Bump to 0.11
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index f4a03da..62116d3 100644
--- a/eglot.el
+++ b/eglot.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2018 Free Software Foundation, Inc.
 
-;; Version: 0.10
+;; Version: 0.11
 ;; Author: João Távora 
 ;; Maintainer: João Távora 
 ;; URL: https://github.com/joaotavora/eglot



[elpa] externals/eglot 17ef74e 07/12: Defer textDocument/formatting requests

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 17ef74e6d4074196f0295ed54700ea7813049d39
Author: João Távora 
Commit: João Távora 

Defer textDocument/formatting requests

* eglot.el (eglot-format-buffer): Pass DEFERRED to eglot--request.
---
 eglot.el | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 0f366c4..e96a3e6 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1410,7 +1410,8 @@ DUMMY is ignored."
 (list :textDocument (eglot--TextDocumentIdentifier)
   :options (list :tabSize tab-width
  :insertSpaces
- (if indent-tabs-mode :json-false t))
+ (if indent-tabs-mode :json-false t)))
+:textDocument/formatting)))
 
 (defun eglot-completion-at-point ()
   "EGLOT's `completion-at-point' function."



[elpa] externals/eglot cbc418c 06/12: Per #22: Simplify eglot-format-buffer

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit cbc418c8ea01283d7e2b1d2bd243ac9d2c60bb88
Author: João Távora 
Commit: João Távora 

Per #22: Simplify eglot-format-buffer

Use replace-buffer-contents, as suggested by mkcms
, but do it in eglot--apply-text-edits, where it
benefits all its users.

* README.md (Commands and keybindings): Mention
eglot-format-buffer.

* eglot.el (eglot-format-buffer): Don't try to heuristically
preserve point here.
(eglot--apply-text-edits): Use replace-buffer-contents.

* eglot-tests.el (formatting): adjust test to strictly check for point
position.
---
 README.md  |  5 -
 eglot-tests.el |  4 ++--
 eglot.el   | 46 +++---
 3 files changed, 25 insertions(+), 30 deletions(-)

diff --git a/README.md b/README.md
index c3f4434..a56d750 100644
--- a/README.md
+++ b/README.md
@@ -61,7 +61,10 @@ Here's a summary of available commands:
 
 - `M-x eglot-shutdown` says bye-bye to the server;
 
-- `M-x eglot-rename` asks the server to rename the symbol at point;
+- `M-x eglot-rename` ask the server to rename the symbol at point;
+
+- `M-x eglot-format-buffer` ask the server to reformat the current
+  buffer.
 
 - `M-x eglot-code-actions` asks the server for any code actions at
   point. These may tipically be simple fixes, like deleting an unused
diff --git a/eglot-tests.el b/eglot-tests.el
index 602606c..f56280e 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -386,9 +386,9 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (with-current-buffer
   (eglot--find-file-noselect "project/something.py")
 (should (eglot--tests-connect))
-(search-forward ":")
+(search-forward ":pa")
 (eglot-format-buffer)
-(should (looking-at "pass"))
+(should (looking-at "ss"))
 (should (or
  ;; yapf
  (string= (buffer-string) "def foo():\npass\n")
diff --git a/eglot.el b/eglot.el
index 447e8c1..0f366c4 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1403,27 +1403,14 @@ DUMMY is ignored."
   (interactive)
   (unless (eglot--server-capable :documentFormattingProvider)
 (eglot--error "Server can't format!"))
-  (let* ((server (eglot--current-server-or-lose))
- (resp
-  (eglot--request
-   server
-   :textDocument/formatting
-   (list :textDocument (eglot--TextDocumentIdentifier)
- :options (list
-   :tabSize tab-width
-   :insertSpaces (not indent-tabs-mode)))
-   :textDocument/formatting))
- (after-point
-  (buffer-substring (point) (min (+ (point) 60) (point-max
- (regexp (and (not (bobp))
-  (replace-regexp-in-string
-   "[\s\t\n\r]+" "[\s\t\n\r]+"
-   (concat "\\(" (regexp-quote after-point) "\\)")
-(when resp
-  (save-excursion
-(eglot--apply-text-edits resp))
-  (when (and (bobp) regexp (search-forward-regexp regexp nil t))
-(goto-char (match-beginning 1))
+  (eglot--apply-text-edits
+   (eglot--request
+(eglot--current-server-or-lose)
+:textDocument/formatting
+(list :textDocument (eglot--TextDocumentIdentifier)
+  :options (list :tabSize tab-width
+ :insertSpaces
+ (if indent-tabs-mode :json-false t))
 
 (defun eglot-completion-at-point ()
   "EGLOT's `completion-at-point' function."
@@ -1595,12 +1582,17 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
   (unless (or (not version) (equal version eglot--versioned-identifier))
 (eglot--error "Edits on `%s' require version %d, you have %d"
   (current-buffer) version eglot--versioned-identifier))
-  (eglot--widening
-   (mapc (pcase-lambda (`(,newText ,beg . ,end))
-   (goto-char beg) (delete-region beg end) (insert newText))
- (mapcar (eglot--lambda (&key range newText)
-   (cons newText (eglot--range-region range 'markers)))
- edits)))
+  (mapc (pcase-lambda (`(,newText ,beg . ,end))
+  (save-restriction
+(narrow-to-region beg end)
+(let ((source (current-buffer)))
+  (with-temp-buffer
+(insert newText)
+(let ((temp (current-buffer)))
+  (with-current-buffer source (replace-buffer-contents 
temp)))
+(mapcar (eglot--lambda (&key range newText)
+  (cons newText (eglot--range-region range 'markers)))
+edits))
   (eglot--message "%s: Performed %s edits" (current-buffer) (length edits)))
 
 (defun eglot--apply-workspace-edit (wedit &optional confirm)



[elpa] externals/eglot 04ef055 11/12: Close #27: empty ranges are valid in LSP

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 04ef0558a1a4c64287f7c5b77b8c68df095a8b3b
Author: João Távora 
Commit: João Távora 

Close #27: empty ranges are valid in LSP

The previous hack in eglot--range-region, designed to appease cquery's
occasional practice of publishing diagnostics with empty regions, was
moved to the proper notification handler.

Reported by mkcms .

* eglot.el (eglot--range-region): Allow empty ranges, which are
allowed in LSP.
(eglot-handle-notification :textDocument/publishDiagnostics): Maybe
fallback to flymake-diag-region here.
---
 eglot.el | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/eglot.el b/eglot.el
index 2fdf433..f4a03da 100644
--- a/eglot.el
+++ b/eglot.el
@@ -896,10 +896,7 @@ If optional MARKERS, make markers."
   (let* ((st (plist-get range :start))
  (beg (eglot--lsp-position-to-point st markers))
  (end (eglot--lsp-position-to-point (plist-get range :end) markers)))
-;; Fallback to `flymake-diag-region' if server botched the range
-(if (/= beg end) (cons beg end) (flymake-diag-region
- (current-buffer) (plist-get st :line)
- (1- (plist-get st :character))
+(cons beg end)))
 
 
 ;;; Minor modes
@@ -1125,7 +1122,18 @@ Don't leave this function with the server still running."
   _code source message)
  diag-spec
(setq message (concat source ": " message))
-   (pcase-let ((`(,beg . ,end) (eglot--range-region range)))
+   (pcase-let
+   ((`(,beg . ,end) (eglot--range-region range)))
+ ;; Fallback to `flymake-diag-region' if server
+ ;; botched the range
+ (if (= beg end)
+ (let* ((st (plist-get range :start))
+(diag-region
+ (flymake-diag-region
+  (current-buffer) (plist-get st :line)
+  (1- (plist-get st :character)
+   (setq beg (car diag-region)
+ end (cdr diag-region
  (eglot--make-diag (current-buffer) beg end
(cond ((<= sev 1) 'eglot-error)
  ((= sev 2)  'eglot-warning)



[elpa] externals/eglot updated (0176264 -> f385d9c)

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

  from  0176264   * eglot.el (Version): Bump to 0.11
   new  f4de5d7   Fix copyright header. Obviously not since 2003
   new  b3c8b59   Refactor JSON-RPC lib jrpc.el from eglot.el
   new  2f1d76d   Proper server shutdown when jrpc.el is used
   new  870c60a   Merge master into jsonrpc-refactor (using imerge)
   new  0e1a5f0   jrpc-connect is now passed a generic dispatching function
   new  5cda0ec   Fix a ridiculous bug when generating transient projects
   new  258e3b0   Merge master into jsonrpc-refactor (using imerge)
   new  e5120aa   Add jrpc.el to Makefile
   new  33ae871   More flexible jrpc.el and improve eglot.el's doc
   new  3265c1d   Simpler callback protocol for JSONRPC parameters and 
results
   new  7f2e894   Merge branch 'master' into jsonrpc-refactor (using good 
ol' git merge)
   new  7cd94b9   Improve jrpc.el's doc (and change jrpc-request's protocol 
a tiny bit)
   new  078a1a6   Add full "Commentary" section to jrpc.el
   new  e906d25   Overhaul JSON and JSRONRPC error handling
   new  07359a2   Allow null timeouts and set default to 3 seconds
   new  7769c07   Send message, then establish continuations
   new  67d8335   jrpc.el should know nothing of mode-line updates
   new  e5ba4f6   Automatically reply with error if dispatcher doesn't
   new  a2aa1ed   Robustify timer handling for jrpc-async-request
   new  5cea412   Fix typos and phrasing in commentary and docstrings
   new  bb60c0c   Rename jrpc.el to jsonrpc.el
   new  cef3c29   Heroically merge master into jsonrpc-refactor (using 
imerge)
   new  c30f0f3   Get rid of jsonrpc.el customization group and timeout
   new  489182d   New jsonrpc-error error type
   new  4bbf810   Don't return implementation details in 
jsonrpc-async-request
   new  5e8fe4c   Add jsonrpc-tests.el
   new  0e44b27   jsonrpc.el uses classes and generic functions
   new  6f1ecc6   Merge branch use-eieio-server-defclass into 
jsonrpc-refactor
   new  05ff697   Document current API breaches a bit
   new  9e9dc57   Merge branch 'master' into jsonrpc-refactor (using 
regular merge)
   new  7f4e273   Merge master into jsonrpc-refactor (using imerge)
   new  5874af9   Fix deferred actions (forgot the crucial non-local exit)
   new  481f16e   * eglot.el (eglot-eldoc-function): Remove spurious log 
message
   new  980f3e7   Fix another merge-related bug in eglot-eldoc-function
   new  c43dff4   On request timeout, clear it from the deferred actions
   new  f594dd7   jsonrpc-request also calls for deferred action cleanup
   new  a4441c6   Merge master into jsonrpc-refactor (using imerge)
   new  6c9d41e   Add reasonably sophisticated deferred action tests
   new  c790274   jsonrpc--next-request-id is a connection slot
   new  0ba7964   * jsonrpc.el (jsonrpc-log-event): Log time of event.
   new  dae1de1   Tweak Makefile to run both tests in a row
   new  d7e1b92   * jsonrpc.el (jsonrpc-message): Fix formatting bug.
   new  4525eca   Support json.c.  API purely based on classes
   new  fab7f8b   Improve Makefile test targets
   new  68c266e   Avoid more catastrophes
   new  44e9647   Simplify JSONRPC connection shutdown
   new  2917214   Merge master into jsonrpc-refactor
   new  f730fff   Merge branch 'master' into jsonrpc-refactor
   new  d371f05   Request dispatcher's return value determines response
   new  2da7d92   Simplify JSONRPC status setting
   new  1ec47fb   Remove connection grabbing antics from jsonrpc.el
   new  bf9c850   Get rid of jsonrpc-obj
   new  a65d3f4   Make message and warning helpers private
   new  46e6107   Reshuffle definitions inside jsonrpc.el
   new  d87f4bf   jsonrpc--log-event should also be private
   new  10559a5   Shuffle definitions around again
   new  7371f68   * jsonrpc.el: Rewrite commentary.
   new  6531c8b   Merge branch 'master' into jsonrpc-refactor
   new  1f09fd3   Review commentary section before another review cycle
   new  aaca7de   Fix ridiculous bug
   new  59cc3fb   jsonrpc-connection-receive is now a public convenience 
function
   new  856a224   Simplify jsonrpc-connection-send
   new  0b474ec   Fix use of jsonrpc-message in tests
   new  69a622a   Fix some typos
   new  47b957d   Let's not send Content-type for now.
   new  61d1276   Fix another bug in jsonrpc-connection-send
   new  8fda30c   Merge master into jsonrpc-refactor (using imerge)
   new  0f20fdf   Tiny README.md change
   new  f385d9c   Merge branch 'jsonrpc-refactor', bump version to 1.0


Summary of changes:
 Makefile |   17 +-
 README.md|6 +-
 eglot-tests.el   |   32 +-
 eglot.el | 1069 +++---
 jsonrpc-tests.el |  204 +++
 jsonrpc

[elpa] externals/eglot f4de5d7 01/69: Fix copyright header. Obviously not since 2003

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit f4de5d7938cc93eabf52cdfabe8c34744a959501
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 13f6f61..4cb3bec 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 5cda0ec 06/69: Fix a ridiculous bug when generating transient projects

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 5cda0ec5291e4daf7b89bf433bed13bd231e9aea
Author: João Távora 
Commit: João Távora 

Fix a ridiculous bug when generating transient projects

* eglot.el (eglot--find-current-process, eglot--interactive): Fix
horrible bug.
---
 eglot.el | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index 13aeff6..11d048e 100644
--- a/eglot.el
+++ b/eglot.el
@@ -136,7 +136,7 @@ called interactively."
 
 (defun eglot--find-current-process ()
   "The current logical EGLOT process."
-  (let* ((probe (or (project-current) (cons 'transient default-directory
+  (let* ((probe (or (project-current) `(transient . ,default-directory
 (cl-find major-mode (gethash probe eglot--processes-by-project)
  :key #'eglot--major-mode)))
 
@@ -208,7 +208,7 @@ called interactively."
  "\n" base-prompt)
 (list
  managed-mode
- (or (project-current) `(transient . default-directory))
+ (or (project-current) `(transient . ,default-directory))
  (if prompt
  (split-string-and-unquote
   (read-shell-command prompt



[elpa] externals/eglot 2f1d76d 03/69: Proper server shutdown when jrpc.el is used

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 2f1d76d2f6b49ed0249abfcf4ff65faac51dc930
Author: João Távora 
Commit: João Távora 

Proper server shutdown when jrpc.el is used

The shutdown hook can't be a buffer-local thing, it has
to be a server property. Also, on shutdown in eglot.el,
remember to first unmanage buffers and only then affect
eglot--processes-by-project.

* eglot.el (eglot--on-shutdown): reverse order of first
two sexps.
(eglot--connect): Pass a shutdown function to jrpc-connect
(eglot--managed-mode): Don't use jrpc-server-moribund-hook
(eglot--buffer-managed-p): Simplify. Use eglot--find-current-process.
---
 eglot.el | 59 ---
 jrpc.el  | 24 +++-
 2 files changed, 43 insertions(+), 40 deletions(-)

diff --git a/eglot.el b/eglot.el
index 934270c..f33a851 100644
--- a/eglot.el
+++ b/eglot.el
@@ -95,13 +95,14 @@ A list (ID WHAT DONE-P).")
 
 (defun eglot--on-shutdown (proc)
   ;; Turn off `eglot--managed-mode' where appropriate.
-  (setf (gethash (eglot--project proc) eglot--processes-by-project)
-(delq proc
-  (gethash (eglot--project proc) eglot--processes-by-project)))
   (dolist (buffer (buffer-list))
 (with-current-buffer buffer
   (when (eglot--buffer-managed-p proc)
 (eglot--managed-mode -1
+  ;; Sever the project/process relationship for proc
+  (setf (gethash (eglot--project proc) eglot--processes-by-project)
+(delq proc
+  (gethash (eglot--project proc) eglot--processes-by-project)))
   (cond ((eglot--moribund proc))
 ((not (eglot--inhibit-autoreconnect proc))
  (eglot--warn "Reconnecting unexpected server exit.")
@@ -267,7 +268,7 @@ INTERACTIVE is t if called interactively."
 
 (defun eglot--connect (project managed-major-mode name command
dont-inhibit)
-  (let ((proc (jrpc-connect name command "eglot--server-")))
+  (let ((proc (jrpc-connect name command "eglot--server-" 
#'eglot--on-shutdown)))
 (setf (eglot--project proc) project)
 (setf (eglot--major-mode proc)managed-major-mode)
 (push proc (gethash project eglot--processes-by-project))
@@ -326,11 +327,11 @@ INTERACTIVE is t if called interactively."
   "Convert point POS to LSP position."
   (save-excursion
 (jrpc-obj :line
-;; F!@(#*&#$)CKING OFF-BY-ONE
-(1- (line-number-at-pos pos t))
-:character
-(- (goto-char (or pos (point)))
-   (line-beginning-position)
+  ;; F!@(#*&#$)CKING OFF-BY-ONE
+  (1- (line-number-at-pos pos t))
+  :character
+  (- (goto-char (or pos (point)))
+ (line-beginning-position)
 
 (defun eglot--lsp-position-to-point (pos-plist)
   "Convert LSP position POS-PLIST to Emacs point."
@@ -401,7 +402,6 @@ INTERACTIVE is t if called interactively."
(eglot--managed-mode
 (add-hook 'jrpc-find-process-functions 'eglot--find-current-process nil t)
 (add-hook 'jrpc-ready-predicates 'eglot--server-ready-p nil t)
-(add-hook 'jrpc-server-moribund-hook 'eglot--on-shutdown nil t)
 (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)
@@ -417,7 +417,6 @@ INTERACTIVE is t if called interactively."
(t
 (remove-hook 'jrpc-find-process-functions 'eglot--find-current-process t)
 (remove-hook 'jrpc-ready-predicates 'eglot--server-ready-p t)
-(remove-hook 'jrpc-server-moribund-hook 'eglot--on-shutdown 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)
@@ -439,11 +438,9 @@ INTERACTIVE is t if called interactively."
 
 (defun eglot--buffer-managed-p (&optional proc)
   "Tell if current buffer can be managed by PROC."
-  (and buffer-file-name
-   (cond ((null proc) (jrpc-current-process))
- (t (and (eq major-mode (eglot--major-mode proc))
- (let ((proj (project-current)))
-   (and proj (equal proj (eglot--project proc)
+  (and buffer-file-name (let ((cur (eglot--find-current-process)))
+  (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")
@@ -585,12 +582,12 @@ Uses THING, FACE, DEFS and PREPEND."
   _code source message)
  diag-spec
(eglot--with-lsp-range (beg end) range
-  (flymake-make-diagnostic 
(current-buffer)
-   

[elpa] externals/eglot 3265c1d 10/69: Simpler callback protocol for JSONRPC parameters and results

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 3265c1d1b92ebfb07484d8ebb5a88f1af26e7106
Author: João Távora 
Commit: João Távora 

Simpler callback protocol for JSONRPC parameters and results

Instead of introspecting the :params or :result object to discover if
an object is present, and changing the Elisp function call type
(funcall vs apply) accordingly, alway funcall. It's up to the
application to destructure if it wishes. jrpc-lambda can help with
that and keep the application code simple.

* eglot.el (eglot--on-shutdown): Fix indentation.
(eglot--dispatch): Simplify.
(xref-backend-identifier-completion-table)
(xref-backend-definitions, xref-backend-references)
(xref-backend-apropos, eglot-completion-at-point)
(eglot-eldoc-function, eglot-imenu, eglot--apply-text-edits):
Don't use jrpc-mapply.

* jrpc.el (jrpc--process-receive): Allow only keys defined in
JSONRPC2.0
(jrpc--process-receive): Don't overload function call type based
on remote response.
(jrpc-lambda): Return a unary lambda.
(jrpc-request): Simplify.
(jrpc-mapply): Remove.
---
 eglot.el | 35 +--
 jrpc.el  | 32 +---
 2 files changed, 26 insertions(+), 41 deletions(-)

diff --git a/eglot.el b/eglot.el
index 4f2e25b..caf2e8c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -128,7 +128,7 @@ A list (ID WHAT DONE-P).")
 (eglot--managed-mode -1
   ;; Kill any expensive watches
   (maphash (lambda (_id watches)
-   (mapcar #'file-notify-rm-watch watches))
+ (mapcar #'file-notify-rm-watch watches))
(eglot--file-watches proc))
   ;; Sever the project/process relationship for proc
   (setf (gethash (eglot--project proc) eglot--processes-by-project)
@@ -314,7 +314,7 @@ INTERACTIVE is t if called interactively."
 
 (defvar eglot-connect-hook nil "Hook run after connecting in 
`eglot--connect'.")
 
-(defun eglot--dispatch (proc method id &rest params)
+(defun eglot--dispatch (proc method id params)
   "Dispatcher passed to `jrpc-connect'.
 Builds a function from METHOD, passes it PROC, ID and PARAMS."
   (let* ((handler-sym (intern (concat "eglot--server-" method
@@ -865,7 +865,7 @@ DUMMY is ignored"
   (completion-table-with-cache
(lambda (string)
  (setq eglot--xref-known-symbols
-   (jrpc-mapply
+   (mapcar
 (jrpc-lambda (&key name kind location containerName)
   (propertize name
   :textDocumentPositionParams
@@ -898,7 +898,7 @@ DUMMY is ignored"
   :textDocument/definition
   (get-text-property
0 :textDocumentPositionParams identifier)
-(jrpc-mapply
+(mapcar
  (jrpc-lambda (&key uri range)
(eglot--xref-make identifier uri (plist-get range :start)))
  location-or-locations)))
@@ -912,7 +912,7 @@ DUMMY is ignored"
(and rich (get-text-property 0 :textDocumentPositionParams 
rich))
 (unless params
   (eglot--error "Don' know where %s is in the workspace!" identifier))
-(jrpc-mapply
+(mapcar
  (jrpc-lambda (&key uri range)
(eglot--xref-make identifier uri (plist-get range :start)))
  (jrpc-request (jrpc-current-process-or-lose)
@@ -924,7 +924,7 @@ DUMMY is ignored"
 
 (cl-defmethod xref-backend-apropos ((_backend (eql eglot)) pattern)
   (when (eglot--server-capable :workspaceSymbolProvider)
-(jrpc-mapply
+(mapcar
  (jrpc-lambda (&key name location &allow-other-keys)
(cl-destructuring-bind (&key uri range) location
  (eglot--xref-make name uri (plist-get range :start
@@ -947,7 +947,7 @@ DUMMY is ignored"
  (eglot--TextDocumentPositionParams)
  :textDocument/completion))
  (items (if (vectorp resp) resp (plist-get resp :items
-(jrpc-mapply
+(mapcar
  (jrpc-lambda (&rest all &key label &allow-other-keys)
(add-text-properties 0 1 all label) label)
  items
@@ -1040,7 +1040,7 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
 (jrpc-async-request
  proc :textDocument/signatureHelp position-params
  :success-fn (jrpc-lambda (&key signatures activeSignature
-  activeParameter)
+activeParameter)
(when-buffer-window
 (when (cl-plusp (length signatures))
   (setq sig-showing t)
@@ -1063,7 +1063,7 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
(mapc #'delete-overlay eglot--highlights)
(setq eglot--highlights
  (when-buffer-window
-   

[elpa] externals/eglot e5ba4f6 18/69: Automatically reply with error if dispatcher doesn't

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit e5ba4f64e25940dfab1b214f919b91c9a6836aa0
Author: João Távora 
Commit: João Távora 

Automatically reply with error if dispatcher doesn't

* jrpc.el (jrpc-connect): Improve doc.
(jrpc--process-receive): Overhaul error handling.
(jrpc-reply): Protect against missing ID
(jrpc-error): Signal an error with jrpc-specific info.
(jrpc-message): Protect against funky args.
(jrpc-request): Learn to handle jrpc-specific errors.
---
 jrpc.el | 76 ++---
 1 file changed, 45 insertions(+), 31 deletions(-)

diff --git a/jrpc.el b/jrpc.el
index c974fd9..223a4ce 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -143,12 +143,15 @@ If nil, don't use a timeout (not recommended)."
   (jrpc-error "No current JSON-RPC process")))
 
 (defun jrpc-error (format &rest args)
-  "Error out with FORMAT with ARGS."
-  (error (apply #'format format args)))
+  "Error out with FORMAT with ARGS.
+If invoked inside a dispatcher function, this function is suitable
+for replying to the remote endpoint with a -32603 error code and
+FORMAT as the message."
+  (signal 'error (format "[jrpc] %s" (apply #'format format args
 
 (defun jrpc-message (format &rest args)
   "Message out with FORMAT with ARGS."
-  (message (concat "[jrpc] " (apply #'format format args
+  (message "[jrpc] %s" (concat "[jrpc] %s" (apply #'format format args
 
 (defun jrpc-warn (format &rest args)
   "Warning message with FORMAT and ARGS."
@@ -266,18 +269,17 @@ passed the moribund process object as a single argument.
 
 DISPATCHER specifies how the server-invoked methods find their
 Elisp counterpart. It is a function passed (PROC METHOD ID PARAMS
-as arguments:
-
-PROC is the process object returned by this function.
-
-ID is server identifier for a server request, or nil for a server
-notification. In the case of a server request, DISPATCHER is
-reponsible using ID and `jrpc-reply' (which see) to reply.
-
-METHOD is a symbol.
-
-PARAMS contains the method parameters: an object, array, or other
-type.
+as arguments. PROC is the process object returned by this
+function. ID is the server identifier for a server request, or
+nil for a server notification. METHOD is a symbol. PARAMS
+contains the method parameters as JSON data.
+
+If ID is non-nil, DISPATCHER is expected to reply to the
+request. If it doesn't, or if it signals an error before doing
+so, jrpc.el will automatially reply with an error. If DISPATCHER
+signals an error with alist elements `jrpc-error-message' and
+`jrpc-error-code' in its DATA, the corresponding elements are
+used for the automated error reply.
 
 `jrpc-connect' returns a process object representing the server."
   (let* ((proc (jrpc--make-process name contact)))
@@ -430,19 +432,25 @@ is a symbol saying if this is a client or server 
originated."
  (error (jrpc-warn "Invalid JSONRPC message %s: %s" message
(cdr oops))
 nil)))
-  (continuations))
+  (continuations)
+  (lisp-err))
 (jrpc-log-event proc message 'server)
 (when error (setf (jrpc-status proc) `(,error t)))
 (cond (method
-   (unwind-protect
-   (funcall (jrpc--dispatcher proc) proc method id params)
- (unless (or (not id)
- (member id (jrpc--server-request-ids proc)))
-   (jrpc-reply
-proc id
-:error (jrpc-obj :code -32603 :message "Internal error")))
- (setf (jrpc--server-request-ids proc)
-   (delete id (jrpc--server-request-ids proc)
+   (condition-case-unless-debug oops
+   (funcall (jrpc--dispatcher proc) proc (intern method) id params)
+ (error (setq lisp-err oops)))
+   (unless (or (member id (jrpc--server-request-ids proc))
+   (not (or id lisp-err)))
+ (jrpc-reply
+  proc id
+  :error (jrpc-obj
+  :code (or (alist-get 'jrpc-error-code (cdr lisp-err))
+-32603)
+  :message (or (alist-get 'jrpc-error-message (cdr 
lisp-err))
+   "Internal error"
+   (setf (jrpc--server-request-ids proc)
+ (delete id (jrpc--server-request-ids proc
   ((setq continuations
  (and id (gethash id (jrpc--request-continuations proc
(let ((timer (nth 2 continuations)))
@@ -593,12 +601,16 @@ DEFERRED is passed to `jrpc-async-request', which see."
 (jrpc-async-request
  proc method params
  :success-fn (lambda (result) (throw tag `(done ,result)))
- :error-fn (jrpc-lambda (&key code message _data)
- (throw tag `(error ,(format "%s: %s" code message
- :timeout-fn (lambda () 

[elpa] externals/eglot 67d8335 17/69: jrpc.el should know nothing of mode-line updates

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 67d833598956521c848223304c2ef35fcb6812ca
Author: João Távora 
Commit: João Távora 

jrpc.el should know nothing of mode-line updates

* eglot.el (eglot--dispatch): METHOD can be a symbol.
Call force-mode-line-update here.
---
 eglot.el | 5 +++--
 jrpc.el  | 3 +--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/eglot.el b/eglot.el
index 4e02c72..81229a5 100644
--- a/eglot.el
+++ b/eglot.el
@@ -317,11 +317,12 @@ INTERACTIVE is t if called interactively."
 (defun eglot--dispatch (proc method id params)
   "Dispatcher passed to `jrpc-connect'.
 Builds a function from METHOD, passes it PROC, ID and PARAMS."
-  (let* ((handler-sym (intern (concat "eglot--server-" method
+  (let* ((handler-sym (intern (format "eglot--server-%s" method
 (if (functionp handler-sym) ;; FIXME: fails if params is array, not object
 (apply handler-sym proc (append params (if id `(:id ,id
   (jrpc-reply proc id
-  :error (jrpc-obj :code -32601 :message "Unimplemented")
+  :error (jrpc-obj :code -32601 :message "Unimplemented")))
+(force-mode-line-update t)))
 
 (defun eglot--connect (project managed-major-mode name contact)
   (let* ((contact (if (functionp contact) (funcall contact) contact))
diff --git a/jrpc.el b/jrpc.el
index bb4fe28..c974fd9 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -452,8 +452,7 @@ is a symbol saying if this is a client or server 
originated."
  (funcall (nth 0 continuations) result)))
   (id
(jrpc-warn "No continuation for id %s" id)))
-(jrpc--call-deferred proc)
-(force-mode-line-update t)))
+(jrpc--call-deferred proc)))
 
 (defun jrpc--process-send (proc message)
   "Send MESSAGE to PROC (ID is optional)."



[elpa] externals/eglot 0e1a5f0 05/69: jrpc-connect is now passed a generic dispatching function

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 0e1a5f07f0163d92fb66f711b6b3e291e866229e
Author: João Távora 
Commit: João Távora 

jrpc-connect is now passed a generic dispatching function

* eglot.el (eglot--dispatch): New helper.
(eglot--connect): Use it.

* jrpc.el (jrpc--dispatcher, jrpc--request-continuations)
(jrpc--server-request-ids): New process-local var.
(jrpc--pending-continuations, jrpc--method-prefix): Remove.
(jrpc-connect): Take DISPATCHER instead of PREFIX.
(jrpc--process-receive): Use proc's dispatcher.
(jrpc--process-send): Make private.
(jrpc-forget-pending-continuations, jrpc-async-request)
(jrpc-reply, jrpc-notify): Use new function names.
---
 eglot.el |  11 +-
 jrpc.el  | 128 +--
 2 files changed, 78 insertions(+), 61 deletions(-)

diff --git a/eglot.el b/eglot.el
index 879972d..13aeff6 100644
--- a/eglot.el
+++ b/eglot.el
@@ -277,9 +277,18 @@ INTERACTIVE is t if called interactively."
 
 (defvar eglot-connect-hook nil "Hook run after connecting in 
`eglot--connect'.")
 
+(defun eglot--dispatch (proc method id &rest params)
+  ;; a server notification or a server request
+  (let* ((handler-sym (intern (concat "eglot--server-" method
+(if (functionp handler-sym)
+(apply handler-sym proc (append params (if id `(:id ,id
+  (jrpc-reply
+  proc id
+  :error (jrpc-obj :code -32601 :message "Unimplemented")
+
 (defun eglot--connect (project managed-major-mode name command
dont-inhibit)
-  (let ((proc (jrpc-connect name command "eglot--server-" 
#'eglot--on-shutdown)))
+  (let ((proc (jrpc-connect name command #'eglot--dispatch 
#'eglot--on-shutdown)))
 (setf (eglot--project proc) project)
 (setf (eglot--major-mode proc)managed-major-mode)
 (push proc (gethash project eglot--processes-by-project))
diff --git a/jrpc.el b/jrpc.el
index 973e901..ea0122b 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -25,14 +25,6 @@
 ;; Originally extracted from eglot.el (Emacs LSP client)
 ;;
 ;;
-;; codemessage meaning
-;; -32700  Parse error Invalid JSON was received by the server.
-;; An error occurred on the server while parsing the JSON text.
-;; -32600  Invalid Request The JSON sent is not a valid Request object.
-;; -32601  Method not foundThe method does not exist / is not 
available.
-;; -32602  Invalid params  Invalid method parameter(s).
-;; -32603  Internal error  Internal JSON-RPC error.
-
 ;;; Code:
 
 (require 'cl-lib)
@@ -98,8 +90,8 @@ INITVAL is the default value.  DOC is the documentation."
 (jrpc-define-process-var jrpc-name nil
   "A name for the process")
 
-(jrpc-define-process-var jrpc--method-prefix nil
-  "Emacs-lisp function prefix for server-invoked methods.")
+(jrpc-define-process-var jrpc--dispatcher nil
+  "Emacs-lisp function for server-invoked methods.")
 
 (jrpc-define-process-var jrpc-status `(:unknown nil)
   "Status as declared by the server.
@@ -108,8 +100,11 @@ A list (WHAT SERIOUS-P).")
 (jrpc-define-process-var jrpc--expected-bytes nil
   "How many bytes declared by server")
 
-(jrpc-define-process-var jrpc--pending-continuations (make-hash-table)
-  "A hash table of request ID to continuation lambdas")
+(jrpc-define-process-var jrpc--request-continuations (make-hash-table)
+  "A hash table of request ID to continuation lambdas.")
+
+(jrpc-define-process-var jrpc--server-request-ids nil
+  "Server-initiated request id that client hasn't replied to.")
 
 (jrpc-define-process-var jrpc--events-buffer nil
   "A buffer pretty-printing the JSON-RPC RPC events")
@@ -128,7 +123,7 @@ A function passed the process object for the server.")
 
 (defun jrpc-outstanding-request-ids (proc)
   "IDs of outstanding JSON-RPC requests for PROC."
-  (hash-table-keys (jrpc--pending-continuations proc)))
+  (hash-table-keys (jrpc--request-continuations proc)))
 
 (defun jrpc--make-process (name contact)
   "Make a process from CONTACT.
@@ -164,7 +159,7 @@ CONTACT is as `jrpc-contact'.  Returns a process object."
   ;; the indenting of literal plists, i.e. is basically `list'
   `(list ,@what))
 
-(cl-defun jrpc-connect (name contact prefix &optional on-shutdown)
+(cl-defun jrpc-connect (name contact dispatcher &optional on-shutdown)
   "Connect to JSON-RPC server hereafter known as NAME through CONTACT.
 
 NAME is a string naming the server.
@@ -173,21 +168,35 @@ CONTACT is either a list of strings (a shell command and
 arguments), or a list of a single string of the form
 :.
 
-PREFIX specifies how the server-invoked methods find their Elisp
-counterpart. If a server invokes method \"FooBar\" and PREFIX is
-\"fancy-mode-\", then the function `fancy-mode-FooBar' will be
-called with arguments (PROCESS [JSON]). JSON is either a plist of
-key-value pairs or, for JSON arrays, a non-list sequence.
-
 ON-SHUTDOWN, when non-nil, is a function called on server exit
 

[elpa] externals/eglot c30f0f3 23/69: Get rid of jsonrpc.el customization group and timeout

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit c30f0f3262c5e6d70934c7c2a9e7d7c23e696360
Author: João Távora 
Commit: João Távora 

Get rid of jsonrpc.el customization group and timeout

* eglot.el (eglot-shutdown, eglot--signal-textDocument/willSave):
Pass :timeout to jsonrpc-request.
(defadvice jsonrpc-request): Add :timeout kwarg

* jsonrpc.el (defgroup jsonrpc, jsonrpc-request-timeout): Remove.
(jrpc-default-request-timeout): New constant.
(jsonrpc-async-request): Use it.
(jsonrpc-request): Accept timeout kwarg and pass it on.
---
 eglot.el   | 17 -
 jsonrpc.el | 20 +++-
 2 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/eglot.el b/eglot.el
index 41e57b4..020e352 100644
--- a/eglot.el
+++ b/eglot.el
@@ -148,9 +148,9 @@ called interactively."
   (interactive (list (jsonrpc-current-process-or-lose) t))
   (eglot--message "Asking %s politely to terminate" proc)
   (unwind-protect
-  (let ((jsonrpc-request-timeout 3))
+  (progn
 (setf (eglot--moribund proc) t)
-(jsonrpc-request proc :shutdown nil)
+(jsonrpc-request proc :shutdown nil :timeout 3)
 ;; this one should always fail, hence ignore-errors
 (ignore-errors (jsonrpc-request proc :exit nil)))
 ;; Turn off `eglot--managed-mode' where appropriate.
@@ -749,7 +749,7 @@ Records START, END and PRE-CHANGE-LENGTH locally."
 ;; bad idea, since that might lead to the request never having a
 ;; chance to run, because `jsonrpc-ready-predicates'.
 (advice-add #'jsonrpc-request :before
-(cl-function (lambda (_proc _method _params &key deferred)
+(cl-function (lambda (_proc _method _params &key deferred _timeout)
(when (and eglot--managed-mode deferred)
  (eglot--signal-textDocument/didChange
 '((name . eglot--signal-textDocument/didChange)))
@@ -805,12 +805,11 @@ Records START, END and PRE-CHANGE-LENGTH locally."
   (let ((proc (jsonrpc-current-process-or-lose))
 (params `(:reason 1 :textDocument ,(eglot--TextDocumentIdentifier
 (jsonrpc-notify proc :textDocument/willSave params)
-(ignore-errors
-  (let ((jsonrpc-request-timeout 0.5))
-(when (plist-get :willSaveWaitUntil
- (eglot--server-capable :textDocumentSync))
-  (eglot--apply-text-edits
-   (jsonrpc-request proc :textDocument/willSaveWaituntil params)))
+(when (eglot--server-capable :textDocumentSync :willSaveWaitUntil)
+  (ignore-errors
+(eglot--apply-text-edits
+ (jsonrpc-request proc :textDocument/willSaveWaituntil params
+  :timeout 0.5))
 
 (defun eglot--signal-textDocument/didSave ()
   "Send textDocument/didSave to server."
diff --git a/jsonrpc.el b/jsonrpc.el
index d5f7745..cda035e 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -123,16 +123,6 @@
 (require 'pcase)
 (require 'array) ; xor
 
-(defgroup jsonrpc nil
-  "Interaction between JSONRPC endpoints"
-  :prefix "jsonrpc-"
-  :group 'applications)
-
-(defcustom jsonrpc-request-timeout 3
-  "How many seconds to wait for a JSONRPC from the server.
-If nil, don't use a timeout (not recommended)."
-  :type :integer)
-
 (defvar jsonrpc-find-process-functions nil
   "Special hook to find an active JSON-RPC process.")
 
@@ -505,12 +495,15 @@ request and a process object.")
   (let ((e (gensym "jsonrpc-lambda-elem")))
 `(lambda (,e) (apply (cl-function (lambda ,cl-lambda-list ,@body)) ,e
 
+(defconst jrpc-default-request-timeout 10
+  "Time in seconds before timing out a JSONRPC request.")
+
 (cl-defun jsonrpc-async-request (proc
  method
  params
  &rest args
  &key success-fn error-fn timeout-fn
- (timeout jsonrpc-request-timeout)
+ (timeout jrpc-default-request-timeout)
  (deferred nil))
   "Make a request to PROC, expecting a reply, return immediately.
 The JSONRPC request is formed by METHOD, a symbol, and PARAMS a
@@ -591,7 +584,7 @@ TIMEOUT is nil)"
  (jsonrpc--request-continuations proc))
 (list id timer)))
 
-(cl-defun jsonrpc-request (proc method params &key deferred)
+(cl-defun jsonrpc-request (proc method params &key deferred timeout)
   "Make a request to PROC, wait for a reply.
 Like `jsonrpc-async-request' for PROC, METHOD and PARAMS, but
 synchronous, i.e. doesn't exit until anything
@@ -618,7 +611,8 @@ DEFERRED is passed to `jsonrpc-async-request', which see."
   :timeout-fn
   (lambda ()
 (throw tag '(error (jsonrpc-error-message . "Timed out"
-  :deferred deferred))
+  :deferred deferred
+  :timeout timeout))
 (while t (accept-process-ou

[elpa] externals/eglot 7cd94b9 12/69: Improve jrpc.el's doc (and change jrpc-request's protocol a tiny bit)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 7cd94b9e51920ca46c0b24e80f20f7ad07794bc5
Author: João Távora 
Commit: João Távora 

Improve jrpc.el's doc (and change jrpc-request's protocol a tiny bit)

* jrpc.el (jrpc-async-request)
(jrpc-request,jrpc-notify,jrpc-reply): Improve docstring.
(jrpc-connect): Improve docstring and add autoload cookie
(jrpc-request): DEFERRED param is now &key
(defgroup jrpc): Fix description.

* eglot.el (advice-add jrpc-request): Use &key deferred.
(eglot-completion-at-point): Pass :deferred to jrpc-request
---
 eglot.el | 10 ---
 jrpc.el  | 93 
 2 files changed, 58 insertions(+), 45 deletions(-)

diff --git a/eglot.el b/eglot.el
index b820dde..4e02c72 100644
--- a/eglot.el
+++ b/eglot.el
@@ -744,11 +744,13 @@ Records START, END and PRE-CHANGE-LENGTH locally."
  `[(,pre-change-length
 ,(buffer-substring-no-properties start end))])))
 
-;; HACK!
+;; HACK! Launching a deferred sync request with outstanding changes is a
+;; bad idea, since that might lead to the request never having a
+;; chance to run, because `jrpc-ready-predicates'.
 (advice-add #'jrpc-request :before
-(lambda (_proc _method _params &optional deferred)
+(cl-function (lambda (_proc _method _params &key deferred)
   (when (and eglot--managed-mode deferred)
-(eglot--signal-textDocument/didChange
+(eglot--signal-textDocument/didChange)
 
 (defun eglot--signal-textDocument/didChange ()
   "Send textDocument/didChange to server."
@@ -937,7 +939,7 @@ DUMMY is ignored"
   (let* ((resp (jrpc-request proc
  :textDocument/completion
  (eglot--TextDocumentPositionParams)
- :textDocument/completion))
+ :deferred :textDocument/completion))
  (items (if (vectorp resp) resp (plist-get resp :items
 (mapcar
  (jrpc-lambda (&rest all &key label &allow-other-keys)
diff --git a/jrpc.el b/jrpc.el
index ce22e92..43f80a2 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -33,7 +33,7 @@
 (require 'warnings)
 
 (defgroup jrpc nil
-  "Interaction with Language Server Protocol servers"
+  "Interaction between JSONRPC endpoints"
   :prefix "jrpc-"
   :group 'applications)
 
@@ -157,6 +157,7 @@ object."
   ;; the indenting of literal plists, i.e. is basically `list'
   `(list ,@what))
 
+;;;###autoload
 (cl-defun jrpc-connect (name contact dispatcher &optional on-shutdown)
   "Connect to JSON-RPC server hereafter known as NAME through CONTACT.
 
@@ -168,43 +169,35 @@ in the list is an integer number instead of a string, the 
list is
 interpreted as (HOST PORT PARAMETERS...) to connect to an
 existing server via TCP, with the remaining PARAMETERS are given
 to `open-network-stream's optional arguments.  CONTACT can also
-be a live connected process object.
+be a live connected process object. In that case its buffer,
+filter and sentinel are overwritten by `jrpc-connect'.
 
-ON-SHUTDOWN, when non-nil, is a function called on server exit
-and passed the moribund process object.
+ON-SHUTDOWN, if non-nil, is a function called on server exit and
+passed the moribund process object as a single argument.
 
 DISPATCHER specifies how the server-invoked methods find their
-Elisp counterpart. It is a function which is passed (PROC METHOD
-ID PARAMS...) as arguments.
+Elisp counterpart. It is a function passed (PROC METHOD ID PARAMS
+as arguments:
 
 PROC is the process object returned by this function.
 
 ID is server identifier for a server request, or nil for a server
-notification.
+notification. In the case of a server request, DISPATCHER is
+reponsible using ID and `jrpc-reply' (which see) to reply.
 
 METHOD is a symbol.
 
-PARAMS contains the method parameters.  If the parameters are a
-JSON object, PARAMS... is a plist of the form (KEY1 VALUE1 KEY2
-VALUE2...).  It they are an array, a string or a number, the
-first and only element of PARAMS is a vector, string or number,
-respectively. If the parameters are a single boolean, PARAMS is
-either the symbol `:json-false' or `t'. In the case of a server
-request, DISPATCHER is reponsible for replying to it with
-`jrpc-reply' (which see).
+PARAMS contains the method parameters: an object, array, or other
+type.
 
 `jrpc-connect' returns a process object representing the server."
-  (let* ((proc (jrpc--make-process name contact))
- (buffer (process-buffer proc)))
+  (let* ((proc (jrpc--make-process name contact)))
 (setf (jrpc-contact proc) contact
   (jrpc-name proc) name
   (jrpc--dispatcher proc) dispatcher
   (jrpc--on-shutdown proc) on-shutdown)
-(with-current-buffer buffer
-  (let ((inhibit-read-only t))
-(erase-buffer)
-(read-only-mode t)
-   

[elpa] externals/eglot 5874af9 32/69: Fix deferred actions (forgot the crucial non-local exit)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 5874af97c2d17b1ffacba8d3f584662ef9aedbc8
Author: João Távora 
Commit: João Távora 

Fix deferred actions (forgot the crucial non-local exit)

Noticed by Filipp Gunbin 

* jsonrpc.el (jsonrpc--async-request-1): Forgot the non-local
exit.
---
 jsonrpc.el | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 2bcff2e..1bd71c1 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -621,8 +621,9 @@ TIMEOUT is nil)."
  (apply #'jsonrpc-async-request
 connection
 method params args)
-   (or timer (funcall make-timer)) id)
- (jsonrpc--deferred-actions connection
+   (or timer (setq timer (funcall make-timer))) id)
+ (jsonrpc--deferred-actions connection))
+(cl-return-from jsonrpc--async-request-1 (list nil timer
 ;; Really send it
 ;;
 (jsonrpc-connection-send connection (jsonrpc-obj :jsonrpc "2.0"



[elpa] externals/eglot 7769c07 16/69: Send message, then establish continuations

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 7769c07cba9d66522e6cc45f93ea15215f96ae5f
Author: João Távora 
Commit: João Távora 

Send message, then establish continuations

This way, if serializing fails, or something else, we won't be
bothered by the failing timeout.

* jrpc.el (jrpc-async-request): Send, then establish continuations.
---
 jrpc.el | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/jrpc.el b/jrpc.el
index 7303414..bb4fe28 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -558,8 +558,12 @@ Return the request ID, or nil, in case the request was 
deferred."
 (puthash (list deferred buf) (list later (funcall make-timeout))
  (jrpc--deferred-actions proc))
 (cl-return-from jrpc-async-request nil)
-;; Really run it
+;; Really send it
 ;;
+(jrpc--process-send proc (jrpc-obj :jsonrpc "2.0"
+   :id id
+   :method method
+   :params params))
 (puthash id
  (list (or success-fn
(jrpc-lambda (&rest _ignored)
@@ -573,10 +577,6 @@ Return the request ID, or nil, in case the request was 
deferred."
  :id id :error code
(funcall make-timeout))
  (jrpc--request-continuations proc))
-(jrpc--process-send proc (jrpc-obj :jsonrpc "2.0"
-   :id id
-   :method method
-   :params params))
 id))
 
 (cl-defun jrpc-request (proc method params &key deferred)



[elpa] externals/eglot 0ba7964 40/69: * jsonrpc.el (jsonrpc-log-event): Log time of event.

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 0ba79647dbab24c65df097b0e53f6891b25e20e1
Author: João Távora 
Commit: João Távora 

* jsonrpc.el (jsonrpc-log-event): Log time of event.
---
 jsonrpc.el | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index a8c86d0..7a50b64 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -450,12 +450,15 @@ originated."
 (id'reply)
 (t 'message)))
  (type
-  (format "%s-%s" (or type :internal) subtype)))
+  (concat (format "%s" (or type 'internal))
+  (if type
+  (format "-%s" subtype)
 (goto-char (point-max))
-(let ((msg (format "%s%s%s:\n%s\n"
+(let ((msg (format "%s%s%s %s:\n%s\n"
type
(if id (format " (id:%s)" id) "")
(if error " ERROR" "")
+   (current-time-string)
(pp-to-string message
   (when error
 (setq msg (propertize msg 'face 'error)))



[elpa] externals/eglot d7e1b92 42/69: * jsonrpc.el (jsonrpc-message): Fix formatting bug.

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit d7e1b926636950ad1e21df9f85686fc338597c03
Author: João Távora 
Commit: João Távora 

* jsonrpc.el (jsonrpc-message): Fix formatting bug.
---
 jsonrpc.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 7a50b64..55d4dba 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -160,7 +160,7 @@ FORMAT as the message."
 
 (defun jsonrpc-message (format &rest args)
   "Message out with FORMAT with ARGS."
-  (message "[jsonrpc] %s" (concat "[jsonrpc] %s" (apply #'format format 
args
+  (message "[jsonrpc] %s" (apply #'format format args)))
 
 (defun jsonrpc--debug (server format &rest args)
   "Debug message for SERVER with FORMAT and ARGS."



[elpa] externals/eglot e906d25 14/69: Overhaul JSON and JSRONRPC error handling

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit e906d25d6eeb5e75eb7fab8b45d9f88f9a6567c4
Author: João Távora 
Commit: João Távora 

Overhaul JSON and JSRONRPC error handling

Also fix some bugs.

* jrpc.el (pcase, array): Require it.
(jrpc--connect): Default error function properly logs error event.
(jrpc--process-filter): Protect against JSON errors.
(jrpc--process-receive): Protect against JSONRPC errors.
(jrpc-reply): Check if both result and error.
(jrpc--process-send): Ensure json-object-type is plist.
(jrpc--process-sentinel): Correctly call error handler. Use #'ignore,
not identity. Use pcase-let instead of cl-dbind
---
 jrpc.el | 102 ++--
 1 file changed, 60 insertions(+), 42 deletions(-)

diff --git a/jrpc.el b/jrpc.el
index d314c36..eff941a 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -117,6 +117,8 @@
 (require 'json)
 (require 'subr-x)
 (require 'warnings)
+(require 'pcase)
+(require 'array) ; xor
 
 (defgroup jrpc nil
   "Interaction between JSONRPC endpoints"
@@ -294,17 +296,17 @@ type.
 (insert "\n--b---y---e---b---y---e--\n")))
 ;; Cancel outstanding timers
 (maphash (lambda (_id triplet)
-   (cl-destructuring-bind (_success _error timeout) triplet
+   (pcase-let ((`(,_success ,_error ,timeout) triplet))
  (cancel-timer timeout)))
  (jrpc--request-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"
+   (pcase-let ((`(,_success ,error ,_timeout) triplet))
+ (funcall error `(:code -1 :message "Server died"
  (jrpc--request-continuations proc))
   (jrpc-message "Server exited with status %s" (process-exit-status proc))
-  (funcall (or (jrpc--on-shutdown proc) #'identity) proc)
+  (funcall (or (jrpc--on-shutdown proc) #'ignore) proc)
   (delete-process proc
 
 (defun jrpc--process-filter (proc string)
@@ -352,12 +354,19 @@ type.
 (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
-  (jrpc--process-receive proc json-message
+ (json-message
+  (condition-case-unless-debug oops
+  (json-read)
+(error
+ (jrpc-warn "Invalid JSON: %s %s"
+(cdr oops) (buffer-string))
+ nil
+(when json-message
+  ;; Process content in another
+  ;; buffer, shielding proc buffer from
+  ;; tamper
+  (with-temp-buffer
+(jrpc--process-receive proc 
json-message)
   (goto-char message-end)
   (delete-region (point-min) (point))
   (setq expected-bytes nil
@@ -412,36 +421,43 @@ is a symbol saying if this is a client or server 
originated."
 
 (defun jrpc--process-receive (proc message)
   "Process MESSAGE from PROC."
-  (cl-destructuring-bind (&key method id error params result _jsonrpc) message
-(let* ((continuations (and id
-   (not method)
-   (gethash id (jrpc--request-continuations 
proc)
-  (jrpc-log-event proc message 'server)
-  (when error (setf (jrpc-status proc) `(,error t)))
-  (cond (method
- (unwind-protect
- (funcall (jrpc--dispatcher proc) proc method id params)
-   (unless (or (not id)
-   (member id (jrpc--server-request-ids proc)))
- (jrpc-reply
-  proc id
-  :error (jrpc-obj :code -32603 :message "Internal error")))
-   (setf (jrpc--server-request-ids proc)
- (delete id (jrpc--server-request-ids proc)
-(continuations
- (cancel-timer (cl-third continuations))
- (remhash id (jrpc--request-continuations proc))
- (if error
- (funcall (cl-second continuat

[elpa] externals/eglot 5e8fe4c 26/69: Add jsonrpc-tests.el

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 5e8fe4c2153ce110287b4f39276dd3d49f92e127
Author: João Távora 
Commit: João Távora 

Add jsonrpc-tests.el

* Makefile (jsonrpc-check): Add test target.

* jsonrpc-tests.el: New file.
---
 Makefile |   5 +++
 jsonrpc-tests.el | 104 +++
 2 files changed, 109 insertions(+)

diff --git a/Makefile b/Makefile
index 41619fc..cdfeb79 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,11 @@ check: compile
-l eglot-tests  \
-f ert-run-tests-batch-and-exit \
 
+jsonrpc-check: jsonrpc.elc
+   $(EMACS) -Q --batch $(LOAD_PATH)\
+   -l jsonrpc-tests\
+   -f ert-run-tests-batch-and-exit \
+
 # Cleanup
 #
 clean:
diff --git a/jsonrpc-tests.el b/jsonrpc-tests.el
new file mode 100644
index 000..a3de884
--- /dev/null
+++ b/jsonrpc-tests.el
@@ -0,0 +1,104 @@
+;;; jsonrpc-tests.el --- tests for jsonrpc.el-*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+
+;; Author: João Távora 
+;; Maintainer: João Távora 
+;; URL: https://github.com/joaotavora/eglot
+;; 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:
+
+;; 
+
+;;; Code:
+
+(require 'ert)
+(require 'jsonrpc)
+
+(cl-defmacro jsonrpc--with-emacsrpc-fixture ((endpoint-sym) &body body)
+  (declare (indent 1) (debug t))
+  (let ((server (gensym)))
+`(let* ((,server (make-network-process
+  :name "Emacs RPC server" :server t :host "localhost" 
:service 4
+  :log (lambda (_server client _message)
+ (jsonrpc-connect
+  (process-name client) client
+  (lambda (endpoint method id params)
+(unless (memq method '(+ - * / vconcat append 
sit-for))
+  (signal 'jsonrpc-error 
`((jsonrpc-error-message
+. "Sorry, this 
isn't allowed")
+   (jsonrpc-error-code 
. -32601
+(jsonrpc-reply endpoint id :result
+   (apply method (append params 
nil
+(,endpoint-sym (jsonrpc-connect
+"Emacs RPC client" '("localhost" 4)
+(lambda (_endpoint method _id &rest _params)
+  (message "server wants to %s" method)
+   (unwind-protect
+   ,@body
+ (unwind-protect
+ (delete-process ,server)
+   (delete-process (jsonrpc--process ,endpoint-sym)))
+
+(ert-deftest returns-3 ()
+  "returns 3"
+  (jsonrpc--with-emacsrpc-fixture (server-endpoint)
+(should (= 3 (jsonrpc-request server-endpoint '+ '(1 2))
+
+(ert-deftest errors-with--32601 ()
+  "errors with -32601"
+  (jsonrpc--with-emacsrpc-fixture (server-endpoint)
+(condition-case err
+(progn
+  (jsonrpc-request server-endpoint 'delete-directory "~/tmp")
+  (ert-fail "A `jsonrpc-error' should have been signalled!"))
+  (jsonrpc-error
+   (should (= -32601 (cdr (assoc 'jsonrpc-error-code (cdr err)
+
+(ert-deftest signals-an--32603-JSONRPC-error ()
+  "signals an -32603 JSONRPC error"
+  (jsonrpc--with-emacsrpc-fixture (server-endpoint)
+(condition-case err
+(progn
+  (jsonrpc-request server-endpoint '+ '(a 2))
+  (ert-fail "A `jsonrpc-error' should have been signalled!"))
+  (jsonrpc-error
+   (should (= -32603 (cdr (assoc 'jsonrpc-error-code (cdr err)
+
+(ert-deftest times-out ()
+  "times out"
+  (jsonrpc--with-emacsrpc-fixture (server-endpoint)
+(should-error
+ (jsonrpc-request server-endpoint 'sit-for '(5) :timeout 2
+
+(ert-deftest stretching-it-but-works ()
+  "stretching it, but works"
+  (jsonrpc--with-emacsrpc-fixture (server-endpoint)
+(should (equal
+ [1 2 3 3 4 5]
+ (jsonrpc-request server-endpoint 'vconcat '([1 2 3] [3 4 5]))
+
+(ert-deftest json-el-cant-serialize-this ()
+ 

[elpa] externals/eglot 05ff697 29/69: Document current API breaches a bit

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

Document current API breaches a bit

* eglot-tests.el (eglot--call-with-dirs-and-files)
(auto-reconnect): use eglot--process

* eglot.el (eglot-shutdown, eglot, eglot-reconnect)
(eglot--connect): Use eglot--process
(eglot--process): Alias to concentrate the hack here.
(eglot--signal-textDocument/didChange): Tweak comment.
---
 eglot-tests.el |  8 
 eglot.el   | 19 ---
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index 8afbfa5..777d2da 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -67,7 +67,7 @@
   (let ((eglot-autoreconnect nil))
 (mapc #'eglot-shutdown
   (cl-remove-if-not
-   (lambda (server) (process-live-p (jsonrpc--process server)))
+   (lambda (server) (process-live-p (eglot--process server)))
new-servers)))
   (dolist (buf new-buffers) ;; have to save otherwise will get prompted
 (with-current-buffer buf (save-buffer) (kill-buffer)))
@@ -145,13 +145,13 @@
   ;; In 1.2 seconds > `eglot-autoreconnect' kill servers. We
   ;; should have a automatic reconnection.
   (run-with-timer 1.2 nil (lambda () (delete-process
-  (jsonrpc--process server
-  (while (process-live-p (jsonrpc--process server))
+  (eglot--process server
+  (while (process-live-p (eglot--process server))
 (accept-process-output nil 0.5))
   (should (jsonrpc-current-connection))
   ;; Now try again too quickly
   (setq server (jsonrpc-current-connection))
-  (let ((proc (jsonrpc--process server)))
+  (let ((proc (eglot--process server)))
 (run-with-timer 0.5 nil (lambda () (delete-process proc)))
 (while (process-live-p proc) (accept-process-output nil 0.5)))
   (should (not (jsonrpc-current-connection
diff --git a/eglot.el b/eglot.el
index 1328331..ccb7b49 100644
--- a/eglot.el
+++ b/eglot.el
@@ -191,6 +191,11 @@ lasted more than that many seconds."
 (defvar eglot--servers-by-project (make-hash-table :test #'equal)
   "Keys are projects.  Values are lists of processes.")
 
+;; HACK: Do something to fix this in the jsonrpc API or here, but in
+;; the meantime concentrate the hack here.
+(defalias 'eglot--process 'jsonrpc--process
+  "An abuse of `jsonrpc--process', a jsonrpc.el internal.")
+
 (defun eglot-shutdown (server &optional _interactive)
   "Politely ask SERVER to quit.
 Forcefully quit it if it doesn't respond.  Don't leave this
@@ -206,9 +211,9 @@ function with the server still running."
 ;; Turn off `eglot--managed-mode' where appropriate.
 (dolist (buffer (eglot--managed-buffers server))
   (with-current-buffer buffer (eglot--managed-mode-onoff server -1)))
-(when (process-live-p (jsonrpc--process server))
+(when (process-live-p (eglot--process server))
   (eglot--warn "Brutally deleting non-compliant server %s" (jsonrpc-name 
server))
-  (delete-process (jsonrpc--process server)
+  (delete-process (eglot--process server)
 
 (defun eglot--on-shutdown (server)
   "Called by jsonrpc.el when SERVER is already dead."
@@ -330,7 +335,7 @@ INTERACTIVE is t if called interactively."
 (car (project-roots project)
  (current-server (jsonrpc-current-connection))
  (live-p (and current-server
-  (process-live-p (jsonrpc--process current-server)
+  (process-live-p (eglot--process current-server)
 (if (and live-p
  interactive
  (y-or-n-p "[eglot] Live process found, reconnect instead? "))
@@ -351,7 +356,7 @@ managing `%s' buffers in project `%s'."
   "Reconnect to SERVER.
 INTERACTIVE is t if called interactively."
   (interactive (list (jsonrpc-current-connection-or-lose) t))
-  (when (process-live-p (jsonrpc--process server))
+  (when (process-live-p (eglot--process server))
 (eglot-shutdown server interactive))
   (eglot--connect (eglot--project server)
   (eglot--major-mode server)
@@ -391,7 +396,7 @@ And NICKNAME and CONTACT."
  server
  :initialize
  (jsonrpc-obj :processId (unless (eq (process-type
-  (jsonrpc--process server))
+  (eglot--process server))
  'network)
(emacs-pid))
   :rootPath  (expand-file-name
@@ -415,7 +420,7 @@ And NICKNAME and CONTACT."
 (setf (eglot--inhibit-autoreconnect server)

[elpa] externals/eglot 489182d 24/69: New jsonrpc-error error type

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 489182d53e11c98b859fe8baaf8f2b3c04c39fb5
Author: João Távora 
Commit: João Távora 

New jsonrpc-error error type

* jsonrpc.el (usage example): update to use jsonrpc-error.
(jsonrpc-error): New error type.
(jsonrpc-error, jsonrpc-request): Signal it.
---
 jsonrpc.el | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index cda035e..f801931 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -76,13 +76,15 @@
 ;;   (message "Sadly, server reports %s: %s"
 ;;code message)))
 ;;
+ Usage example:
+;;
 ;; Finally, here's an example Emacs JSONRPC server that offers a (very
 ;; small) subset of Elisp for remote calling:
 ;;
-;;   (defvar server) (defvar server-endpoint)
+;;   (defvar server-server) (defvar server-endpoint)
 ;;   (defvar server-allowed-functions '(+ - * / vconcat append sit-for))
 ;;
-;;   (setq server
+;;   (setq server-server
 ;; (make-network-process
 ;;  :name "Emacs RPC server" :server t :host "localhost" :service 9393
 ;;  :log (lambda (_server client _message)
@@ -90,9 +92,9 @@
 ;;  (process-name client) client
 ;;  (lambda (proc method id params)
 ;;(unless (memq method server-allowed-functions)
-;;  (signal 'error `((jsonrpc-error-message
-;;. "Sorry, this isn't allowed")
-;;   (jsonrpc-error-code . 32601
+;;  (signal 'jsonrpc-error `((jsonrpc-error-message
+;;. "Sorry, this isn't 
allowed")
+;;   (jsonrpc-error-code . 
32601
 ;;(jsonrpc-reply proc id :result
 ;;   (apply method (append params nil
 
@@ -135,12 +137,15 @@
   (or (jsonrpc-current-process)
   (jsonrpc-error "No current JSON-RPC process")))
 
+(define-error 'jsonrpc-error "jsonrpc-error")
+
 (defun jsonrpc-error (format &rest args)
   "Error out with FORMAT and ARGS.
 If invoked inside a dispatcher function, this function is suitable
 for replying to the remote endpoint with a -32603 error code and
 FORMAT as the message."
-  (signal 'error (format "[jsonrpc] %s" (apply #'format format args
+  (signal 'error
+  (list (apply #'format-message (concat "[jsonrpc] " format) args
 
 (defun jsonrpc-message (format &rest args)
   "Message out with FORMAT with ARGS."
@@ -618,9 +623,9 @@ DEFERRED is passed to `jsonrpc-async-request', which see."
   (when id (remhash id (jsonrpc--request-continuations proc)))
   (when timer (cancel-timer timer))
 (when (eq 'error (car retval))
-  (signal 'error
+  (signal 'jsonrpc-error
   (cons
-   (format "[jsonrpc] jsonrpc-request (%s) failed:" (car 
id-and-timer))
+   (format "request id=%s failed:" (car id-and-timer))
(cdr retval
 (cadr retval)))
 



[elpa] externals/eglot a2aa1ed 19/69: Robustify timer handling for jrpc-async-request

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit a2aa1edd38176a470bf16e2c0211da1260422934
Author: João Távora 
Commit: João Távora 

Robustify timer handling for jrpc-async-request

* jrpc.el (jrpc-async-request): Improve timeout handling. Return a list (ID 
TIMER)
(jrpc-request): Protect against user-quits, cancelling timer
---
 jrpc.el | 56 ++--
 1 file changed, 34 insertions(+), 22 deletions(-)

diff --git a/jrpc.el b/jrpc.el
index 223a4ce..1d29023 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -531,12 +531,14 @@ identical DEFERRED and for the same buffer happens in the
 meantime.  However, in that situation, the original timeout is
 kept.
 
-Return the request ID, or nil, in case the request was deferred."
+Return a list (ID TIMER). ID is the new request's ID, or nil if
+the request was deferred. TIMER is a timer object set (or nil, if
+TIMEOUT is nil)"
   (let* ((id (jrpc--next-request-id))
- (existing-timer nil)
- (make-timeout
+ (timer nil)
+ (make-timer
   (lambda ( )
-(or existing-timer
+(or timer
 (when timeout
   (run-with-timer
timeout nil
@@ -550,7 +552,7 @@ Return the request ID, or nil, in case the request was 
deferred."
 (when deferred
   (let* ((buf (current-buffer))
  (existing (gethash (list deferred buf) (jrpc--deferred-actions 
proc
-(when existing (setq existing-timer (cadr existing)))
+(when existing (setq timer (cadr existing)))
 (if (run-hook-with-args-until-failure 'jrpc-ready-predicates
   deferred proc)
 (remhash (list deferred buf) (jrpc--deferred-actions proc))
@@ -562,9 +564,11 @@ Return the request ID, or nil, in case the request was 
deferred."
   (save-excursion (goto-char point)
   (apply #'jrpc-async-request proc
  method params args)))
-(puthash (list deferred buf) (list later (funcall make-timeout))
+(puthash (list deferred buf)
+ (list later (setq timer (funcall make-timer)))
  (jrpc--deferred-actions proc))
-(cl-return-from jrpc-async-request nil)
+;; Non-local exit!
+(cl-return-from jrpc-async-request (list nil timer))
 ;; Really send it
 ;;
 (jrpc--process-send proc (jrpc-obj :jsonrpc "2.0"
@@ -582,9 +586,9 @@ Return the request ID, or nil, in case the request was 
deferred."
  (jrpc-log-event
   proc (jrpc-obj :message "error ignored, status set"
  :id id :error code
-   (funcall make-timeout))
+   (setq timer (funcall make-timer)))
  (jrpc--request-continuations proc))
-id))
+(list id timer)))
 
 (cl-defun jrpc-request (proc method params &key deferred)
   "Make a request to PROC, wait for a reply.
@@ -596,21 +600,29 @@ request is successful, otherwise exit non-locally with an 
error.
 
 DEFERRED is passed to `jrpc-async-request', which see."
   (let* ((tag (cl-gensym "jrpc-request-catch-tag"))
+ req-id req-timer
  (retval
-  (catch tag
-(jrpc-async-request
- proc method params
- :success-fn (lambda (result) (throw tag `(done ,result)))
- :error-fn (jrpc-lambda (&key code message data)
- (throw tag `(error (jrpc-error-code . ,code)
-(jrpc-error-message . ,message)
-(jrpc-error-data . ,data
- :timeout-fn (lambda ()
-   (throw tag '(error (jrpc-error-message . "Timed 
out"
- :deferred deferred)
-(while t (accept-process-output nil 30)
+  (unwind-protect ; protect against user-quit, for example
+  (catch tag
+(pcase-let
+((`(,id ,timer)
+  (jrpc-async-request
+   proc method params
+   :success-fn (lambda (result) (throw tag `(done 
,result)))
+   :error-fn (jrpc-lambda (&key code message data)
+   (throw tag `(error (jrpc-error-code . ,code)
+  (jrpc-error-message . 
,message)
+  (jrpc-error-data . 
,data
+   :timeout-fn (lambda ()
+ (throw tag '(error (jrpc-error-message . 
"Timed out"
+   :deferred deferred)))
+  (setq req-id (or id 'deferred) req-timer timer))
+(while t (accept-process

[elpa] externals/eglot 078a1a6 13/69: Add full "Commentary" section to jrpc.el

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 078a1a631f0e8ff60b02d20681bdddf3eb90a5e1
Author: João Távora 
Commit: João Távora 

Add full "Commentary" section to jrpc.el
---
 jrpc.el | 86 +
 1 file changed, 86 insertions(+)

diff --git a/jrpc.el b/jrpc.el
index 43f80a2..d314c36 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -24,6 +24,92 @@
 
 ;; Originally extracted from eglot.el (Emacs LSP client)
 ;;
+;; This library implements the JSONRPC 2.0 specification as described
+;; in http://www.jsonrpc.org/.  As the name suggests, JSONRPC is a
+;; generic Remote Procedure Call protocol designed around JSON
+;; objects.
+;;
+;; Quoting from the spec: "[JSONRPC] is transport agnostic in that the
+;; concepts can be used within the same process, over sockets, over
+;; http, or in many various message passing environments."
+;;
+;; To approach this agosticity, jrpc.el uses Emacs's "process"
+;; abstraction since it mostly hides the underlying differences
+;; between local subprocesses and network endpoints.  Thus everywhere
+;; in this library (be it in the internals or in the user-visible
+;; protocol), JSONRPC endpoint is an (augmented) process object.
+;;
+;; The main entry point is `jrpc-connect'.  It is passed a name
+;; identifying the connection and a "contact", which will determine
+;; the connection type to make.  It can a list of strings (a command
+;; and arguments for creating subprocesses) or a (HOST PORT-NUMBER
+;; PARAMS...) for connecting via TCP.  For flexibility, it can also be
+;; a pre-connected process.
+;;
+;; `jrpc-connect' returns a process upon connection.  This value
+;; should be saved to be later given to `jrpc-notify', `jrpc-reply',
+;; `jrpc-request' and `jrpc-async-request' as a way of contacting the
+;; connected remote endpoint.
+;;
+;; `jrpc-connect' is also passed a dispatcher function for handling
+;; handling the contacts asynchronously initiated by the remote
+;; endpoint's, as well as a optional function for cleaning up after
+;; the teardown of the JSONRPC connection.
+;;
+;; The JSON objects are passed to the dispatcher after being read by
+;; `json-read' of Emacs's json.el library.  They are read as plists,
+;; and, likewise, json.el-compatible plists should be given to
+;; `jrpc-notify', `jrpc-request', etc...
+;;
+;; To facilitate handling of key-value plists, this library make
+;; liberal use of cl-lib.el and suggests (but doesn't force) its
+;; clients to do the same.  A macro `jrpc-lambda' can be used to
+;; create a lambda for destructuring a JSON-object like in this
+;; example:
+;;
+;; (jrpc-async-request myproc :frobnicate `(:foo "trix")
+;; :success-fn (jrpc-lambda (&key bar baz 
&allow-other-keys)
+;;   (message "Server replied back %s and %s!"
+;;bar baz))
+;; :error-fn (jrpc-lambda (&key code message _data)
+;; (message "Sadly, server reports %s: %s"
+;;  code message)))
+;;
+;; Finally, here's an example Emacs JSONRPC server that offers a (very
+;; small) subset of Elisp for remote calling:
+;;
+;; (defvar server) (defvar server-endpoint)
+;; (defvar server-allowed-functions '(+ - * / vconcat append sit-for))
+;;
+;; (delete-process server)
+;; (setq server
+;;   (make-network-process
+;;:name "Emacs RPC server" :server t :host "localhost" :service 9393
+;;:log (lambda (_server client _message)
+;;   (jrpc-connect
+;;(process-name client) client
+;;(lambda (proc method id params)
+;;  (unless (memq method server-allowed-functions)
+;;(signal 'error `((jrpc-error-message . "Sorry, this 
isn't allowed")
+;; (jrpc-error-code . 32601
+;;  (jrpc-reply proc id :result (apply method (append params 
nil
+;;
+;; (setq server-endpoint (jrpc-connect "Emacs RPC client" '("localhost" 9393)
+;; (lambda (_proc method id &rest params)
+;;   (message "server wants to %s" 
method
+;;
+;;   ;; returns 3
+;;   (jrpc-request server-endpoint '+ '(1 2))
+;;   ;; errors with -32601
+;;   (jrpc-request server-endpoint 'delete-directory "~/tmp")
+;;   ;; signals an -32603 JSONRPC error
+;;   (jrpc-request server-endpoint '+ '(a 2))
+;;   ;; times out
+;;   (jrpc-request server-endpoint 'sit-for '(5))
+;;   ;; stretching it, but works
+;;   (jrpc-request server-endpoint 'vconcat '([1 2 3] [3 4 5]))
+;;   ;; json.el can't serialize this, json.el errors and request isn't sent
+;;   (jrpc-request server-endpoint 'append '((1 2 3) (3 4 5)))
 ;;
 ;;; Code:
 



[elpa] externals/eglot 5cea412 20/69: Fix typos and phrasing in commentary and docstrings

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 5cea41288625c2052e5139ada524720c8383a205
Author: João Távora 
Commit: João Távora 

Fix typos and phrasing in commentary and docstrings
---
 jrpc.el | 50 --
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/jrpc.el b/jrpc.el
index 1d29023..f59dacc 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -33,7 +33,7 @@
 ;; concepts can be used within the same process, over sockets, over
 ;; http, or in many various message passing environments."
 ;;
-;; To approach this agosticity, jrpc.el uses Emacs's "process"
+;; To approach this agnosticism, jrpc.el uses Emacs's "process"
 ;; abstraction since it mostly hides the underlying differences
 ;; between local subprocesses and network endpoints.  Thus everywhere
 ;; in this library (be it in the internals or in the user-visible
@@ -54,7 +54,7 @@
 ;; `jrpc-connect' is also passed a dispatcher function for handling
 ;; handling the contacts asynchronously initiated by the remote
 ;; endpoint's, as well as a optional function for cleaning up after
-;; the teardown of the JSONRPC connection.
+;; the tear-down of the JSONRPC connection.
 ;;
 ;; The JSON objects are passed to the dispatcher after being read by
 ;; `json-read' of Emacs's json.el library.  They are read as plists,
@@ -81,7 +81,6 @@
 ;; (defvar server) (defvar server-endpoint)
 ;; (defvar server-allowed-functions '(+ - * / vconcat append sit-for))
 ;;
-;; (delete-process server)
 ;; (setq server
 ;;   (make-network-process
 ;;:name "Emacs RPC server" :server t :host "localhost" :service 9393
@@ -98,18 +97,18 @@
 ;; (lambda (_proc method id &rest params)
 ;;   (message "server wants to %s" 
method
 ;;
-;;   ;; returns 3
-;;   (jrpc-request server-endpoint '+ '(1 2))
-;;   ;; errors with -32601
-;;   (jrpc-request server-endpoint 'delete-directory "~/tmp")
-;;   ;; signals an -32603 JSONRPC error
-;;   (jrpc-request server-endpoint '+ '(a 2))
-;;   ;; times out
-;;   (jrpc-request server-endpoint 'sit-for '(5))
-;;   ;; stretching it, but works
-;;   (jrpc-request server-endpoint 'vconcat '([1 2 3] [3 4 5]))
-;;   ;; json.el can't serialize this, json.el errors and request isn't sent
-;;   (jrpc-request server-endpoint 'append '((1 2 3) (3 4 5)))
+;; ;; returns 3
+;; (jrpc-request server-endpoint '+ '(1 2))
+;; ;; errors with -32601
+;; (jrpc-request server-endpoint 'delete-directory "~/tmp")
+;; ;; signals an -32603 JSONRPC error
+;; (jrpc-request server-endpoint '+ '(a 2))
+;; ;; times out
+;; (jrpc-request server-endpoint 'sit-for '(5))
+;; ;; stretching it, but works
+;; (jrpc-request server-endpoint 'vconcat '([1 2 3] [3 4 5]))
+;; ;; json.el can't serialize this, json.el errors and request isn't sent
+;; (jrpc-request server-endpoint 'append '((1 2 3) (3 4 5)))
 ;;
 ;;; Code:
 
@@ -143,7 +142,7 @@ If nil, don't use a timeout (not recommended)."
   (jrpc-error "No current JSON-RPC process")))
 
 (defun jrpc-error (format &rest args)
-  "Error out with FORMAT with ARGS.
+  "Error out with FORMAT and ARGS.
 If invoked inside a dispatcher function, this function is suitable
 for replying to the remote endpoint with a -32603 error code and
 FORMAT as the message."
@@ -205,7 +204,7 @@ A list (WHAT SERIOUS-P).")
   "Method used to contact a server.")
 
 (jrpc-define-process-var jrpc--on-shutdown nil
-  "Function run when JSON-RPC server is dying.
+  "Function run when JSONRPC server is dying.
 Run after running any error handlers for outstanding requests.
 A function passed the process object for the server.")
 
@@ -214,7 +213,7 @@ A function passed the process object for the server.")
   "Actions deferred to when server is thought to be ready.")
 
 (defun jrpc-outstanding-request-ids (proc)
-  "IDs of outstanding JSON-RPC requests for PROC."
+  "IDs of outstanding JSONRPC requests for PROC."
   (hash-table-keys (jrpc--request-continuations proc)))
 
 (defun jrpc--make-process (name contact)
@@ -276,7 +275,7 @@ contains the method parameters as JSON data.
 
 If ID is non-nil, DISPATCHER is expected to reply to the
 request. If it doesn't, or if it signals an error before doing
-so, jrpc.el will automatially reply with an error. If DISPATCHER
+so, jrpc.el will automatically reply with an error. If DISPATCHER
 signals an error with alist elements `jrpc-error-message' and
 `jrpc-error-code' in its DATA, the corresponding elements are
 used for the automated error reply.
@@ -382,7 +381,7 @@ used for the automated error reply.
   (setf (jrpc--expected-bytes proc) expected-bytes))
 
 (defun jrpc-events-buffer (process &optional interactive)
-  "Display events buffer for current LSP connection PROCESS.
+  "Display events buffer for current JSONRPC connection PROCESS.
 INTERACTIVE is t if called interactively."
   (interactive (list (jrpc-current-process-or-lose) t))
   (let* ((probe (jrpc--events-buffer process))
@@ -478,7 +477,

[elpa] externals/eglot 33ae871 09/69: More flexible jrpc.el and improve eglot.el's doc

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 33ae871b957fe9727ee3230c64ccec693cdb52fd
Author: João Távora 
Commit: João Távora 

More flexible jrpc.el and improve eglot.el's doc

Generalize and rework CONTACT arg to jrpc-connect

* eglot.el (eglot--command-history): Tweak docstring.
(eglot--interactive): Rework.
(eglot): Rework docstring. COMMAND is now CONTACT.
(eglot--connect): Use new jrpc-connect protocol.
(eglot-server-programs): Reword doc.

* jrpc.el (jrpc--make-process): Use new form of CONTACT.
(jrpc-connect): Explain new semantics of CONTACT.
---
 eglot.el | 66 +---
 jrpc.el  | 53 ++-
 2 files changed, 65 insertions(+), 54 deletions(-)

diff --git a/eglot.el b/eglot.el
index 13c1b49..4f2e25b 100644
--- a/eglot.el
+++ b/eglot.el
@@ -75,7 +75,9 @@
 (sh-mode . ("bash-language-server" "start"))
 (php-mode . ("php" "vendor/felixfbecker/\
 language-server/bin/php-language-server.php")))
-  "Alist mapping major modes to server executables.")
+  "Alist of (MAJOR-MODE . CONTACT) mapping major modes to server executables.
+CONTACT can be anything accepted by that parameter in the
+function `eglot', which see.")
 
 (defface eglot-mode-line
   '((t (:inherit font-lock-constant-face :weight bold)))
@@ -198,7 +200,7 @@ called interactively."
:experimental (jrpc-obj)))
 
 (defvar eglot--command-history nil
-  "History of COMMAND arguments to `eglot'.")
+  "History of CONTACT arguments to `eglot'.")
 
 (defun eglot--interactive ()
   "Helper for `eglot'."
@@ -213,6 +215,7 @@ called interactively."
   (mapcar #'symbol-name (eglot--all-major-modes)) nil t
   (symbol-name guessed-mode) nil (symbol-name guessed-mode) nil)))
(t guessed-mode)))
+ (project (or (project-current) `(transient . ,default-directory)))
  (guessed-command (cdr (assoc managed-mode eglot-server-programs)))
  (base-prompt "[eglot] Enter program to execute (or :): ")
  (prompt
@@ -222,26 +225,30 @@ called interactively."
  managed-mode)
  "\n" base-prompt))
 ((and (listp guessed-command)
+  (not (integerp (cadr guessed-command)))
   (not (executable-find (car guessed-command
  (concat (format "[eglot] I guess you want to run `%s'"
  (combine-and-quote-strings guessed-command))
  (format ", but I can't find `%s' in PATH!"
  (car guessed-command))
- "\n" base-prompt)
-(list
- managed-mode
- (or (project-current) `(transient . ,default-directory))
- (if prompt
- (split-string-and-unquote
-  (read-shell-command prompt
-  (if (listp guessed-command)
-  (combine-and-quote-strings guessed-command))
-  'eglot-command-history))
-   guessed-command)
- t)))
+ "\n" base-prompt
+ (contact
+  (cond ((not prompt) guessed-command)
+(t
+ (let ((string (read-shell-command
+prompt
+(if (listp guessed-command)
+(combine-and-quote-strings 
guessed-command))
+'eglot-command-history)))
+   (if (and string (string-match
+"^\\([^\s\t]+\\):\\([[:digit:]]+\\)$"
+(string-trim string)))
+   (list (match-string 1 string) (match-string 2 string))
+ (split-string-and-unquote string)))
+(list managed-mode project contact t)))
 
 ;;;###autoload
-(defun eglot (managed-major-mode project command &optional interactive)
+(defun eglot (managed-major-mode project contact &optional interactive)
   "Manage a project with a Language Server Protocol (LSP) server.
 
 The LSP server is started (or contacted) via COMMAND.  If this
@@ -253,7 +260,7 @@ code-analysis via `xref-find-definitions', `flymake-mode',
 `eldoc-mode', `completion-at-point', among others.
 
 Interactively, the command attempts to guess MANAGED-MAJOR-MODE
-from current buffer, COMMAND from `eglot-server-programs' and
+from current buffer, CONTACT from `eglot-server-programs' and
 PROJECT from `project-current'.  If it can't guess, the user is
 prompted.  With a single \\[universal-argument] prefix arg, it
 always prompt for COMMAND.  With two \\[universal-argument]
@@ -261,11 +268,14 @@ prefix args, also prompts for MANAGED-MAJOR-MODE.
 
 PROJECT is a project instance as returned by `project-current'.
 
-COMMAND is a list of strings, an exe

[elpa] externals/eglot 6531c8b 58/69: Merge branch 'master' into jsonrpc-refactor

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 6531c8b208736c9f30f829608791deaa44a9160f
Merge: 7371f68 1506172
Author: João Távora 
Commit: João Távora 

Merge branch 'master' into jsonrpc-refactor
---
 eglot-tests.el | 19 +++-
 eglot.el   | 94 +-
 2 files changed, 72 insertions(+), 41 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index 56ec980..b57b949 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -181,6 +181,9 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (define-derived-mode rust-mode prog-mode "Rust"))
 (add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))
 
+(defun eglot--tests-connect ()
+  (apply #'eglot--connect (eglot--guess-contact)))
+
 (ert-deftest auto-detect-running-server ()
   "Visit a file and M-x eglot, then visit a neighbour. "
   (skip-unless (executable-find "rls"))
@@ -192,7 +195,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (eglot--with-timeout 2
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
-  (should (setq server (apply #'eglot (eglot--interactive
+  (should (setq server (eglot--tests-connect)))
   (should (eglot--current-server)))
 (with-current-buffer
 (eglot--find-file-noselect "project/merdix.rs")
@@ -212,7 +215,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (eglot--with-timeout 3
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
-  (should (setq server (apply #'eglot (eglot--interactive
+  (should (setq server (eglot--tests-connect)))
   ;; In 1.2 seconds > `eglot-autoreconnect' kill servers. We
   ;; should have a automatic reconnection.
   (run-with-timer 1.2 nil (lambda () (delete-process
@@ -244,7 +247,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
 :client-notifications c-notifs
 :client-replies c-replies
 )
-(should (apply #'eglot (eglot--interactive)))
+(should (eglot--tests-connect))
 (let (register-id)
   (eglot--wait-for (s-requests 1)
   (&key id method &allow-other-keys)
@@ -274,7 +277,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (eglot--find-file-noselect "diag-project/main.rs")
 (should (zerop (shell-command "cargo init")))
 (eglot--sniffing (:server-notifications s-notifs)
-  (apply #'eglot (eglot--interactive))
+  (eglot--tests-connect)
   (eglot--wait-for (s-notifs 1)
   (&key _id method &allow-other-keys)
 (string= method 'textDocument/publishDiagnostics))
@@ -304,7 +307,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   :client-replies c-replies
   :client-requests c-reqs
   )
-  (apply #'eglot (eglot--interactive))
+  (eglot--tests-connect)
   (goto-char (point-min))
   (search-forward "return te")
   (insert "st")
@@ -342,7 +345,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   :client-replies c-replies
   :client-requests c-reqs
   )
-  (apply #'eglot (eglot--interactive))
+  (eglot--tests-connect)
   (goto-char (point-min)) (search-forward "return te")
   (eglot-rename "bla")
   (should (equal (buffer-string) "fn test() -> i32 { let bla=3; return 
bla; }")))
@@ -355,7 +358,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (eglot--with-timeout 4
   (with-current-buffer
   (eglot--find-file-noselect "project/something.py")
-(should (apply #'eglot (eglot--interactive)))
+(should (eglot--tests-connect))
 (goto-char (point-max))
 (completion-at-point)
 (should (looking-back "sys.exit"))
@@ -368,7 +371,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (eglot--with-timeout 4
   (with-current-buffer
   (eglot--find-file-noselect "project/something.py")
-(should (apply #'eglot (eglot--interactive)))
+(should (eglot--tests-connect))
 (goto-char (point-max))
 (setq eldoc-last-message nil)
 (completion-at-point)
diff --git a/eglot.el b/eglot.el
index 32879ec..0a060a5 100644
--- a/eglot.el
+++ b/eglot.el
@@ -46,6 +46,13 @@
 ;; To "unmanage" these buffers, shutdown the server with M-x
 ;; eglot-shutdown.
 ;;
+;; You can also do:
+;;
+;;   (add-hook 'foo-mode-hook 'eglot-ensure)
+;;
+;; To attempt to start an eglot session automatically everytime a
+;; foo-mode buffer is visited.
+;;
 ;;; Code:
 
 (require 'json)
@@ -255,8 +262,10 @@ function with the server still running."
 (defvar eglot--command-history nil
   "History of CONTACT arguments to `eglot'.")
 
-(defun eglot--interactive ()
-  "Helper for `eglot'."
+(defun eglot--guess-contact (&optional interactive)

[elpa] externals/eglot c43dff4 35/69: On request timeout, clear it from the deferred actions

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit c43dff4d31b724c9ce2e9fba1f742384885abb9b
Author: João Távora 
Commit: João Távora 

On request timeout, clear it from the deferred actions

Noticed by Filipp Gunbin 

* jsonrpc.el (jsonrpc--async-request-1): Clear deferred action in
  timeout handler.
---
 jsonrpc.el | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/jsonrpc.el b/jsonrpc.el
index 1bd71c1..c032687 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -601,6 +601,8 @@ TIMEOUT is nil)."
  timeout nil
  (lambda ()
(remhash id (jsonrpc--request-continuations connection))
+   (remhash (list deferred buf)
+(jsonrpc--deferred-actions connection))
(if timeout-fn (funcall timeout-fn)
  (jsonrpc--debug
   connection `(:timed-out ,method :id ,id



[elpa] externals/eglot a65d3f4 53/69: Make message and warning helpers private

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit a65d3f4495c9e0ddf0d443f7c9042bb59b46eb38
Author: João Távora 
Commit: João Távora 

Make message and warning helpers private

* jsonrpc.el (jsonrpc--message): Rename from jsonrpc-message.
(jsonrpc--warn): Rename from jsonrpc-warn.
(jsonrpc--process-sentinel): Use jsonrpc--message.
(jsonrpc-shutdown, jsonrpc--connection-receive)
(jsonrpc--process-filter): Use jsonrpc--warn.
---
 jsonrpc.el | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 868233a..4c2140c 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -126,7 +126,7 @@ object, using the keywords `:code', `:message' and `:data'."
 (jsonrpc-error-message . ,message)
 (jsonrpc-error-data . ,data))
 
-(defun jsonrpc-message (format &rest args)
+(defun jsonrpc--message (format &rest args)
   "Message out with FORMAT with ARGS."
   (message "[jsonrpc] %s" (apply #'format format args)))
 
@@ -135,9 +135,9 @@ object, using the keywords `:code', `:message' and `:data'."
   (jsonrpc-log-event
server (if (stringp format)`(:message ,(format format args)) format)))
 
-(defun jsonrpc-warn (format &rest args)
+(defun jsonrpc--warn (format &rest args)
   "Warning message with FORMAT and ARGS."
-  (apply #'jsonrpc-message (concat "(warning) " format) args)
+  (apply #'jsonrpc--message (concat "(warning) " format) args)
   (let ((warning-minimum-level :error))
 (display-warning 'jsonrpc
  (apply #'format format args)
@@ -278,7 +278,7 @@ connection object, called when the process dies .")
  (pcase-let ((`(,_success ,error ,_timeout) triplet))
(funcall error `(:code -1 :message "Server died"
(jsonrpc--request-continuations connection))
-(jsonrpc-message "Server exited with status %s" (process-exit-status 
proc))
+(jsonrpc--message "Server exited with status %s" (process-exit-status 
proc))
 (process-put proc 'jsonrpc-sentinel-done t)
 (delete-process proc)
 (funcall (jsonrpc--on-shutdown connection) connection)
@@ -332,8 +332,8 @@ connection object, called when the process dies .")
   (condition-case-unless-debug oops
   (jsonrpc--json-read)
 (error
- (jsonrpc-warn "Invalid JSON: %s %s"
-   (cdr oops) 
(buffer-string))
+ (jsonrpc--warn "Invalid JSON: %s %s"
+(cdr oops) 
(buffer-string))
  nil
 (when json-message
   ;; Process content in another
@@ -438,7 +438,7 @@ originated."
 (if error (funcall (nth 1 continuations) error)
   (funcall (nth 0 continuations) result)))
(;; An abnormal situation
-id (jsonrpc-warn "No continuation for id %s" id)))
+id (jsonrpc--warn "No continuation for id %s" id)))
   (jsonrpc--call-deferred connection
 
 (cl-defmethod jsonrpc-connection-send ((connection jsonrpc-process-connection)
@@ -484,7 +484,7 @@ originated."
(delete-process proc)
(accept-process-output nil 0.1)
while (not (process-get proc 'jsonrpc-sentinel-done))
-   do (jsonrpc-warn
+   do (jsonrpc--warn
"Sentinel for %s still hasn't run,  deleting it!" proc)))
 
 (defun jsonrpc-forget-pending-continuations (connection)



[elpa] externals/eglot 2da7d92 50/69: Simplify JSONRPC status setting

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 2da7d9285d6edc271d7619f8be6e0d6e5c4e5d2c
Author: João Távora 
Commit: João Távora 

Simplify JSONRPC status setting

* eglot.el (eglot--connect): Don't set jsonrpc-status.
(eglot-clear-status): New interactive command.
(eglot--mode-line-format): Simplify.

* jsonrpc.el (jsonrpc--async-request-1): Simplify.
(jsonrpc-connection): Replace status with last-error.
(jsonrpc-clear-status): Delete.
(jsonrpc--connection-receive): Set last-error.
---
 eglot.el   | 15 ++-
 jsonrpc.el | 24 +++-
 2 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/eglot.el b/eglot.el
index 13413ab..f8bd32c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -423,7 +423,6 @@ appeases checkdoc, that's all."
:initializationOptions (eglot-initialization-options server)
:capabilities (eglot-client-capabilities server)))
   (setf (eglot--capabilities server) capabilities)
-  (setf (jsonrpc-status server) nil)
   (dolist (buffer (buffer-list))
 (with-current-buffer buffer
   (eglot--maybe-activate-editing-mode server)))
@@ -613,6 +612,11 @@ that case, also signal textDocument/didOpen."
 
 (add-hook 'find-file-hook 'eglot--maybe-activate-editing-mode)
 
+(defun eglot-clear-status (server)
+  "Clear the last JSONRPC error for SERVER."
+  (interactive (list (jsonrpc-current-connection-or-lose)))
+  (setf (jsonrpc-last-error server) nil))
+
 
 ;;; Mode-line, menu and other sugar
 ;;;
@@ -652,7 +656,7 @@ Uses THING, FACE, DEFS and PREPEND."
(pending (and server (hash-table-count
  (jsonrpc--request-continuations server
(`(,_id ,doing ,done-p ,detail) (and server (eglot--spinner 
server)))
-   (`(,status ,serious-p) (and server (jsonrpc-status server
+   (last-error (and server (jsonrpc-last-error server
 (append
  `(,(eglot--mode-line-props "eglot" 'eglot-mode-line nil))
  (when nick
@@ -662,11 +666,12 @@ Uses THING, FACE, DEFS and PREPEND."
  (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
+ ,@(when last-error
  `("/" ,(eglot--mode-line-props
  "error" 'compilation-mode-line-fail
- '((mouse-3 jsonrpc-clear-status  "clear this status"))
- (format "An error occured: %s\n" status
+ '((mouse-3 eglot-clear-status  "clear this status"))
+ (format "An error occured: %s\n" (plist-get last-error
+ :message)
  ,@(when (and doing (not done-p))
  `("/" ,(eglot--mode-line-props
  (format "%s%s" doing
diff --git a/jsonrpc.el b/jsonrpc.el
index 36f45ef..094b353 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -171,9 +171,9 @@ object, using the keywords `:code', `:message' and `:data'."
 :initform #'ignore
 :initarg :notification-dispatcher
 :documentation "Dispatcher for remotely invoked notifications.")
-   (status
-:initform `(:unknown nil) :accessor jsonrpc-status
-:documentation "Status (WHAT SERIOUS-P) as declared by the server.")
+   (last-error
+:accessor jsonrpc-last-error
+:documentation "Last JSONRPC error message received from endpoint.")
(-request-continuations
 :initform (make-hash-table)
 :accessor jsonrpc--request-continuations
@@ -429,7 +429,7 @@ originated."
   message
 (let (continuations)
   (jsonrpc-log-event connection message 'server)
-  (when error (setf (jsonrpc-status connection) `(,error t)))
+  (setf (jsonrpc-last-error connection) error)
   (cond
(;; A remote request
 (and method id)
@@ -516,11 +516,6 @@ originated."
   (interactive (list (jsonrpc-current-connection-or-lose)))
   (clrhash (jsonrpc--request-continuations connection)))
 
-(defun jsonrpc-clear-status (connection)
-  "Clear most recent error message from CONNECTION."
-  (interactive (list (jsonrpc-current-connection-or-lose)))
-  (setf (jsonrpc-status connection) nil))
-
 (defun jsonrpc--call-deferred (connection)
   "Call CONNECTION's deferred actions, who may again defer themselves."
   (when-let ((actions (hash-table-values (jsonrpc--deferred-actions 
connection
@@ -631,13 +626,16 @@ TIMEOUT is nil)."
  (list (or success-fn
(jsonrpc-lambda (&rest _ignored)
  (jsonrpc--debug
-  connection (jsonrpc-obj :message "success ignored" 
:id id
+  connection (jsonrpc-obj :message "success ignored"
+  :id id
   

[elpa] externals/eglot dae1de1 41/69: Tweak Makefile to run both tests in a row

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit dae1de13d9ea6dc9d66680285e81174c54e83698
Author: João Távora 
Commit: João Távora 

Tweak Makefile to run both tests in a row

* Makefile (ELFILES): Add jsonrpc-tests.el
(check): Also make jsonrpc-check
(jsonrpc-check): Depend on jsonrpc-tests.el
---
 Makefile | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index cdfeb79..6b95f9c 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ EMACS=emacs
 
 LOAD_PATH=-L .
 
-ELFILES := eglot.el jsonrpc.el eglot-tests.el
+ELFILES := eglot.el jsonrpc.el eglot-tests.el jsonrpc-tests.el
 ELCFILES := $(ELFILES:.el=.elc)
 
 all: compile
@@ -20,15 +20,12 @@ compile: $(ELCFILES)
 
 # Automated tests
 #
-check: compile
-
-check: SELECTOR=t
-check: compile
+check: compile jsonrpc-check
$(EMACS) -Q --batch $(LOAD_PATH)\
-l eglot-tests  \
-f ert-run-tests-batch-and-exit \
 
-jsonrpc-check: jsonrpc.elc
+jsonrpc-check: jsonrpc.elc jsonrpc-tests.elc
$(EMACS) -Q --batch $(LOAD_PATH)\
-l jsonrpc-tests\
-f ert-run-tests-batch-and-exit \



[elpa] externals/eglot bf9c850 52/69: Get rid of jsonrpc-obj

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit bf9c850404a7b6a644c497d4c558ce6ee9801da9
Author: João Távora 
Commit: João Távora 

Get rid of jsonrpc-obj

* jsonrpc.el (jsonrpc-obj): Remove this.
(jsonrpc--async-request-1): Don't jsonrpc-obj.
---
 jsonrpc.el | 13 +++--
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 41044e3..868233a 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -238,13 +238,6 @@ connection object, called when the process dies .")
   (let ((inhibit-read-only t)) (erase-buffer) (read-only-mode t) proc))
 (process-put proc 'jsonrpc-connection conn)))
 
-(defmacro jsonrpc-obj (&rest what)
-  "Make WHAT a suitable argument for `json-encode'."
-  (declare (debug (&rest form)))
-  ;; FIXME: maybe later actually do something, for now this just fixes
-  ;; the indenting of literal plists, i.e. is basically `list'
-  `(list ,@what))
-
 (defun jsonrpc--json-read ()
   "Read JSON object in buffer, move point to end of buffer."
   ;; TODO: I guess we can make these macros if/when jsonrpc.el
@@ -608,12 +601,12 @@ TIMEOUT is nil)."
  (list (or success-fn
(jsonrpc-lambda (&rest _ignored)
  (jsonrpc--debug
-  connection (jsonrpc-obj :message "success ignored"
-  :id id
+  connection (list :message "success ignored"
+   :id id
(or error-fn
(jsonrpc-lambda (&key code message &allow-other-keys)
  (jsonrpc--debug
-  connection (jsonrpc-obj
+  connection (list
   :message
   (format "error ignored, status set (%s)"
   message)



[elpa] externals/eglot cef3c29 22/69: Heroically merge master into jsonrpc-refactor (using imerge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit cef3c29a4a2bfbb87d3fa0518626a4e0fdcb95dc
Merge: bb60c0c 24877ae
Author: João Távora 
Commit: João Távora 

Heroically merge master into jsonrpc-refactor (using imerge)
---
 .travis.yml|   4 +
 eglot-tests.el |  93 +--
 eglot.el   | 286 -
 jsonrpc.el |  67 +++---
 4 files changed, 242 insertions(+), 208 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 2f0db4c..9b0a6d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,6 +18,10 @@ install:
   # Install RLS
   - rustup update
   - rustup component add rls-preview rust-analysis rust-src
+  # Install https://github.com/palantir/python-language-server
+  - virtualenv .
+  - . ./bin/activate
+  - pip install 'python-language-server[all]'
 
 script:
   - make check
diff --git a/eglot-tests.el b/eglot-tests.el
index 9359a78..a19f121 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -26,11 +26,12 @@
 (require 'eglot)
 (require 'cl-lib)
 (require 'ert)
+(require 'edebug)
 
 ;; Helpers
 
 (defmacro eglot--with-dirs-and-files (dirs &rest body)
-  (declare (indent defun) (debug t))
+  (declare (indent 1) (debug t))
   `(eglot--call-with-dirs-and-files
 ,dirs #'(lambda () ,@body)))
 
@@ -51,24 +52,24 @@
 (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)
+(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)
+  (let ((eglot-autoreconnect nil))
+(mapc #'eglot-shutdown
+  (cl-remove-if-not #'process-live-p new-processes)))
+  (dolist (buf new-buffers) ;; have to save otherwise will get prompted
+(with-current-buffer buf (save-buffer) (kill-buffer)))
+  (delete-directory default-directory 'recursive
 
 (cl-defmacro eglot--with-test-timeout (timeout &body body)
   (declare (indent 1) (debug t))
@@ -85,8 +86,9 @@
   (catch tag
 (setq timer
   (run-with-timer timeout nil
-  (lambda () ;; (throw tag timed-out)
-)))
+  (lambda ()
+(unless edebug-active
+  (throw tag timed-out)
 (funcall fn)))
   (cancel-timer timer)
   (when (eq retval timed-out)
@@ -109,12 +111,13 @@
 
 (ert-deftest auto-detect-running-server ()
   "Visit a file and M-x eglot, then visit a neighbour. "
+  (skip-unless (executable-find "rls"))
   (let (proc)
-(eglot--with-test-timeout 2
-  (eglot--with-dirs-and-files
-  '(("project" . (("coiso.rs" . "bla")
-  ("merdix.rs" . "bla")))
-("anotherproject" . (("cena.rs" . "bla"
+(eglot--with-dirs-and-files
+'(("project" . (("coiso.rs" . "bla")
+("merdix.rs" . "bla")))
+  ("anotherproject" . (("cena.rs" . "bla"
+  (eglot--with-test-timeout 2
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
   (setq proc
@@ -131,12 +134,13 @@
 
 (ert-deftest auto-reconnect ()
   "Start a server. Kill it. Watch it reconnect."
+  (skip-unless (executable-find "rls"))
   (let (proc
 (eglot-autoreconnect 1))
-(eglot--with-test-timeout 3
-  (eglot--with-dirs-and-files
-  '(("project" . (("coiso.rs" . "bla")
-  ("merdix.rs" . "bla"
+(eglot--with-dirs-and-files
+'(("project" . (("coiso.rs" . "bla")
+  

[elpa] externals/eglot f594dd7 36/69: jsonrpc-request also calls for deferred action cleanup

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit f594dd7f59fa878a085e66e338d251ff1d16017d
Author: João Távora 
Commit: João Távora 

jsonrpc-request also calls for deferred action cleanup

Noticed by Filipp Gunbin 

* jsonrpc.el (jsonrpc--async-request-1): In the non-local exit
also return the id.
(jsonrpc-request): Cleanup deferred actions here too.
---
 jsonrpc.el | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index c032687..beb3d01 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -625,7 +625,7 @@ TIMEOUT is nil)."
 method params args)
(or timer (setq timer (funcall make-timer))) id)
  (jsonrpc--deferred-actions connection))
-(cl-return-from jsonrpc--async-request-1 (list nil timer
+(cl-return-from jsonrpc--async-request-1 (list id timer
 ;; Really send it
 ;;
 (jsonrpc-connection-send connection (jsonrpc-obj :jsonrpc "2.0"
@@ -677,8 +677,10 @@ DEFERRED is passed to `jsonrpc-async-request', which see."
   :deferred deferred
   :timeout timeout))
 (while t (accept-process-output nil 30)))
-(pcase-let ((`(,id ,timer) id-and-timer))
-  (when id (remhash id (jsonrpc--request-continuations 
connection)))
+(pcase-let* ((`(,id ,timer) id-and-timer))
+  (remhash id (jsonrpc--request-continuations connection))
+  (remhash (list deferred (current-buffer))
+   (jsonrpc--deferred-actions connection))
   (when timer (cancel-timer timer))
 (when (eq 'error (car retval))
   (signal 'jsonrpc-error



[elpa] externals/eglot aaca7de 60/69: Fix ridiculous bug

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit aaca7deee8d081622d4c04310cdfab8fe6057063
Author: João Távora 
Commit: João Távora 

Fix ridiculous bug

* jsonrpc.el (jsonrpc-connection-send): Content-Length must be a
string.
---
 jsonrpc.el | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 0c38257..9a90f33 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -184,12 +184,12 @@ ID, METHOD, PARAMS, RESULT and ERROR. ")
 
 ;;; API optional
 (cl-defgeneric jsonrpc-connection-ready-p (connection what)
-"Tell if CONNECTION is ready for WHAT in current buffer.
+  "Tell if CONNECTION is ready for WHAT in current buffer.
 If it isn't, a deferrable `jsonrpc-async-request' will be
 deferred to the future.  By default, all connections are ready
 for sending requests immediately."
-(:method (_s _what)   ;; by default all connections are ready
- t))
+  (:method (_s _what)   ;; by default all connections are ready
+   t))
 
 
 ;;; Convenience
@@ -395,7 +395,7 @@ connection object, called when the process dies .")
  ,@(when error  `(:error  ,error
  (json (jsonrpc--json-encode message))
  (headers
-  `(("Content-Length" . ,(string-bytes json))
+  `(("Content-Length" . ,(format "%d" (string-bytes json)))
 ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8"
 (process-send-string
  (jsonrpc--process connection)



[elpa] externals/eglot 856a224 62/69: Simplify jsonrpc-connection-send

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 856a22431522c5df8269e3f6b7f345edd6d1e54e
Author: João Távora 
Commit: João Távora 

Simplify jsonrpc-connection-send

* jsonrpc.el (jsonrpc-connection-send): Use args.
---
 jsonrpc.el | 33 ++---
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index cec16b7..f063870 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -421,27 +421,22 @@ connection object, called when the process dies .")
 (cl-defmethod jsonrpc-connection-send ((connection jsonrpc-process-connection)
&rest args
&key
-   id
+   _id
method
-   params
-   result
-   error)
+   _params
+   _result
+   _error
+   _partial)
   "Send MESSAGE, a JSON object, to CONNECTION."
-  (let* ((method
-  (cond ((keywordp method)
- (substring (symbol-name method) 1))
-((and method (symbolp method)) (symbol-name method))
-(t method)))
- (message `(:jsonrpc "2.0"
- ,@(when method `(:method ,method))
- ,@(when id `(:id ,id))
- ,@(when params `(:params ,params))
- ,@(when result `(:result ,result))
- ,@(when error  `(:error  ,error
- (json (jsonrpc--json-encode message))
- (headers
-  `(("Content-Length" . ,(format "%d" (string-bytes json)))
-("Content-Type" . "application/vscode-jsonrpc; charset=utf-8"
+  (plist-put args :method
+ (cond ((keywordp method) (substring (symbol-name method) 1))
+   ((and method (symbolp method)) (symbol-name method))
+   (t method)))
+  (let* ( (message `(:jsonrpc "2.0" ,@args))
+  (json (jsonrpc--json-encode message))
+  (headers
+   `(("Content-Length" . ,(format "%d" (string-bytes json)))
+ ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8"
 (process-send-string
  (jsonrpc--process connection)
  (cl-loop for (header . value) in headers



[elpa] externals/eglot d87f4bf 55/69: jsonrpc--log-event should also be private

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit d87f4bf8b788756e61d4cde7a8d0099839525da2
Author: João Távora 
Commit: João Távora 

jsonrpc--log-event should also be private

* eglot-tests.el (eglot--sniffing): Use jsonrpc--log-event.

* jsonrpc.el (jsonrpc-connection-send)
(jsonrpc--connection-receive, jsonrpc--debug): Use
jsonrpc--log-event.
(jsonrpc--log-event): Rename from jsonrpc-log-event.
---
 eglot-tests.el | 4 ++--
 jsonrpc.el | 8 
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index 40970a7..56ec980 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -124,7 +124,7 @@
client-notifications
client-replies))
(advice-add
-#'jsonrpc-log-event :before
+#'jsonrpc--log-event :before
 (lambda (_proc message &optional type)
   (cl-destructuring-bind (&key method id _error &allow-other-keys)
   message
@@ -148,7 +148,7 @@
   `(push message ,client-replies)
 '((name . ,log-event-ad-sym)))
,@body)
-   (advice-remove #'jsonrpc-log-event ',log-event-ad-sym
+   (advice-remove #'jsonrpc--log-event ',log-event-ad-sym
 
 (cl-defmacro eglot--wait-for ((events-sym &optional (timeout 1) message) args 
&body body)
   "Spin until FN match in EVENTS-SYM, flush events after it.
diff --git a/jsonrpc.el b/jsonrpc.el
index 0537699..f5808fc 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -266,7 +266,7 @@ connection object, called when the process dies .")
  (format "Content-Length: %d\r\n\r\n%s"
  (string-bytes json)
  json))
-(jsonrpc-log-event connection message 'client)))
+(jsonrpc--log-event connection message 'client)))
 
 (cl-defmethod jsonrpc-process-type ((conn jsonrpc-process-connection))
   "Return the process-type of JSONRPC connection CONN"
@@ -520,7 +520,7 @@ DEFERRED is passed to `jsonrpc-async-request', which see."
   (cl-destructuring-bind (&key method id error params result _jsonrpc)
   message
 (let (continuations)
-  (jsonrpc-log-event connection message 'server)
+  (jsonrpc--log-event connection message 'server)
   (setf (jsonrpc-last-error connection) error)
   (cond
(;; A remote request
@@ -636,7 +636,7 @@ TIMEOUT is nil)."
 
 (defun jsonrpc--debug (server format &rest args)
   "Debug message for SERVER with FORMAT and ARGS."
-  (jsonrpc-log-event
+  (jsonrpc--log-event
server (if (stringp format)`(:message ,(format format args)) format)))
 
 (defun jsonrpc--warn (format &rest args)
@@ -647,7 +647,7 @@ TIMEOUT is nil)."
  (apply #'format format args)
  :warning)))
 
-(defun jsonrpc-log-event (connection message &optional type)
+(defun jsonrpc--log-event (connection message &optional type)
   "Log an jsonrpc-related event.
 CONNECTION is the current connection.  MESSAGE is a JSON-like
 plist.  TYPE is a symbol saying if this is a client or server



[elpa] externals/eglot 0e44b27 27/69: jsonrpc.el uses classes and generic functions

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 0e44b27b6b5a9b2c29ce2ff685b09e28954a4296
Author: João Távora 
Commit: João Távora 

jsonrpc.el uses classes and generic functions

* jsonrpc.el: Rework commentary.
(jsonrpc-find-connection-functions, jsonrpc-current-connection)
(jsonrpc-current-connection-or-lose): Rename from old
process-based counterpart.
(jsonrpc-connection, jsonrpc-process-connection): New classes
(jsonrpc-define-process-var): Delete.
(jsonrpc--make-process-connection): Rework from old
jsonrpc--make-process.
(jsonrpc-connect): Rework.
(jsonrpc--process-sentinel): Rework.
(jsonrpc--process-filter): Rework.
(jsonrpc-events-buffer, jsonrpc-log-event): Take a connection.
(jsonrpc--connection-receive): Rename from old process-based
conterpart.
(jsonrpc-connection-send): Rename from old process-based
conterpart.  Now a generic function.
(jsonrpc-forget-pending-continuations)
(jsonrpc-clear-status, jsonrpc--call-deferred): Take a connection.
(jsonrpc-connection-ready-p): New generic function.
(jsonrpc-async-request, jsonrpc--async-request-1): Take a
connection. Rework.
(jsonrpc-request, jsonrpc-notify, jsonrpc-reply): Take a
connection.
---
 jsonrpc.el | 450 -
 1 file changed, 233 insertions(+), 217 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 35516d0..a380b7a 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -33,20 +33,28 @@
 ;; concepts can be used within the same process, over sockets, over
 ;; http, or in many various message passing environments."
 ;;
-;; To approach this agnosticism, jsonrpc.el uses Emacs's "process"
-;; abstraction since it mostly hides the underlying differences
-;; between local subprocesses and network endpoints.  Thus everywhere
-;; in this library (be it in the internals or in the user-visible
-;; protocol), JSONRPC endpoint is an (augmented) process object.
+;; To approach this agnosticism, jsonrpc.el uses objects derived from
+;; an abstract class, `jsonrpc-connection' to represent the connection
+;; to the remote JSON endpoint.  Abstract operations such as sending
+;; and receiving are modelled as generic functions, so that users of
+;; JSONRPC working in complicated transport infrastructures can
+;; specify a subclass of `jsonrpc-connection' and write specific
+;; methods for it.  Nevertheless, jsonrpc.el comes built-in with
+;; `jsonrpc-process-connection' class that works both with local
+;; subprocesses (through stdin/stdout) and TCP hosts (using
+;; sockets). This uses some simple HTTP-style envelopping for JSON
+;; objects travelling through the wire.
 ;;
-;; The main entry point is `jsonrpc-connect'.  It is passed a name
-;; identifying the connection and a "contact", which will determine
-;; the connection type to make.  It can a list of strings (a command
-;; and arguments for creating subprocesses) or a (HOST PORT-NUMBER
-;; PARAMS...) for connecting via TCP.  For flexibility, it can also be
-;; a pre-connected process.
+;; Thus, the main entry point `jsonrpc-connect', returns one of these
+;; objects by default.  It is passed a name identifying the connection
+;; and a "contact", which will determine the connection type to make.
+;; This contact can a list of strings (a command and arguments for
+;; creating subprocesses) or a list of the form (HOST PORT-NUMBER
+;; PARAMS...)  for connecting via TCP.  For the providing the
+;; aforementioned flexibility, it can also be a any object of a
+;; subclass of `jsonrpc-connection'.
 ;;
-;; `jsonrpc-connect' returns a process upon connection.  This value
+;; `jsonrpc-connect' returns a connection upon connection.  This value
 ;; should be saved to be later given to `jsonrpc-notify',
 ;; `jsonrpc-reply', `jsonrpc-request' and `jsonrpc-async-request' as a
 ;; way of contacting the connected remote endpoint.
@@ -90,17 +98,17 @@
 ;;  :log (lambda (_server client _message)
 ;; (jsonrpc-connect
 ;;  (process-name client) client
-;;  (lambda (proc method id params)
+;;  (lambda (endpoint method id params)
 ;;(unless (memq method server-allowed-functions)
 ;;  (signal 'jsonrpc-error `((jsonrpc-error-message
 ;;. "Sorry, this isn't 
allowed")
-;;   (jsonrpc-error-code . 
32601
-;;(jsonrpc-reply proc id :result
+;;   (jsonrpc-error-code . 
-32601
+;;(jsonrpc-reply endpoint id :result
 ;;   (apply method (append params nil
 
 ;;   (setq server-endpoint (jsonrpc-connect
 ;;  "Emacs RPC client" '("localhost" 9393)
-;;  (lambda (_proc method id &rest params)
+;;  (lambda (end

[elpa] externals/eglot 2917214 47/69: Merge master into jsonrpc-refactor

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 29172141500e5608c0744fb99edca2ff0c6f9cdc
Merge: 44e9647 1f7bcb1
Author: João Távora 
Commit: João Távora 

Merge master into jsonrpc-refactor
---
 eglot.el | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/eglot.el b/eglot.el
index cdb1c5b..70d133b 100644
--- a/eglot.el
+++ b/eglot.el
@@ -596,6 +596,9 @@ If optional MARKERS, make markers."
 (cl-find major-mode (gethash probe eglot--servers-by-project)
  :key #'eglot--major-mode)))
 
+(defvar-local eglot--unreported-diagnostics nil
+  "Unreported Flymake diagnostics for this buffer.")
+
 (defun eglot--maybe-activate-editing-mode (&optional server)
   "Maybe activate mode function `eglot--managed-mode'.
 If SERVER is supplied, do it only if BUFFER is managed by it.  In
@@ -604,6 +607,7 @@ that case, also signal textDocument/didOpen."
   (let* ((cur (and buffer-file-name (eglot--find-current-server)))
  (server (or (and (null server) cur) (and server (eq server cur) 
cur
 (when server
+  (setq eglot--unreported-diagnostics `(:just-opened . nil))
   (eglot--managed-mode-onoff server 1)
   (eglot--signal-textDocument/didOpen
 
@@ -730,9 +734,6 @@ Uses THING, FACE, DEFS and PREPEND."
   (_server (_method (eql telemetry/event)) &rest _any)
   "Handle notification telemetry/event") ;; noop, use events buffer
 
-(defvar-local eglot--unreported-diagnostics nil
-  "Unreported diagnostics for this buffer.")
-
 (cl-defmethod eglot-handle-notification
   (server (_method (eql textDocument/publishDiagnostics)) &key uri diagnostics)
   "Handle notification publishDiagnostics"



[elpa] externals/eglot 4bbf810 25/69: Don't return implementation details in jsonrpc-async-request

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 4bbf810fccf371f89f79be28bbc3afcefe12d3a4
Author: João Távora 
Commit: João Távora 

Don't return implementation details in jsonrpc-async-request

* jsonrpc.el (jsonrpc-async-request): Pass everything to
jsonrpc-async-request-1.
(jsonrpc--async-request-1): New function.
(jsonrpc-request): Use it.
---
 jsonrpc.el | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index f801931..35516d0 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -507,9 +507,9 @@ request and a process object.")
  method
  params
  &rest args
- &key success-fn error-fn timeout-fn
- (timeout jrpc-default-request-timeout)
- (deferred nil))
+ &key _success-fn _error-fn
+ _timeout-fn
+ _timeout _deferred)
   "Make a request to PROC, expecting a reply, return immediately.
 The JSONRPC request is formed by METHOD, a symbol, and PARAMS a
 JSON object.
@@ -529,9 +529,21 @@ sent at all, in case it is overridden in the meantime by a 
new
 request with identical DEFERRED and for the same buffer.
 However, in that situation, the original timeout is kept.
 
+Returns nil."
+  (apply #'jsonrpc--async-request-1 proc method params args))
+
+(cl-defun jsonrpc--async-request-1 (proc
+method
+params
+&rest args
+&key success-fn error-fn timeout-fn
+(timeout jrpc-default-request-timeout)
+(deferred nil))
+  "Does actual work for `jsonrpc-async-request'.
+
 Return a list (ID TIMER). ID is the new request's ID, or nil if
 the request was deferred. TIMER is a timer object set (or nil, if
-TIMEOUT is nil)"
+TIMEOUT is nil)."
   (let* ((id (jsonrpc--next-request-id))
  (timer nil)
  (make-timer
@@ -604,7 +616,7 @@ DEFERRED is passed to `jsonrpc-async-request', which see."
   (catch tag
 (setq
  id-and-timer
- (jsonrpc-async-request
+ (jsonrpc--async-request-1
   proc method params
   :success-fn (lambda (result) (throw tag `(done ,result)))
   :error-fn



[elpa] externals/eglot fab7f8b 44/69: Improve Makefile test targets

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit fab7f8bcdae2419494996938ea2787950edfde5e
Author: João Távora 
Commit: João Távora 

Improve Makefile test targets

* Makefile (eglot-check): new target.
(jsonrpc-check): Use SELECTOR.
(check): Calle eglot-check  and jsonrpc-check
---
 Makefile | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index 6b95f9c..df15914 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
 # Variables
 #
 EMACS=emacs
+SELECTOR=t
 
 LOAD_PATH=-L .
 
@@ -20,15 +21,17 @@ compile: $(ELCFILES)
 
 # Automated tests
 #
-check: compile jsonrpc-check
+eglot-check: compile 
$(EMACS) -Q --batch $(LOAD_PATH)\
-l eglot-tests  \
-   -f ert-run-tests-batch-and-exit \
+   --eval '(ert-run-tests-batch-and-exit (quote $(SELECTOR)))'
 
 jsonrpc-check: jsonrpc.elc jsonrpc-tests.elc
$(EMACS) -Q --batch $(LOAD_PATH)\
-l jsonrpc-tests\
-   -f ert-run-tests-batch-and-exit \
+   --eval '(ert-run-tests-batch-and-exit (quote $(SELECTOR)))'
+
+check: eglot-check jsonrpc-check
 
 # Cleanup
 #



[elpa] externals/eglot 44e9647 46/69: Simplify JSONRPC connection shutdown

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 44e9647ea63b9706437e9562b9847f520e47fb8d
Author: João Távora 
Commit: João Távora 

Simplify JSONRPC connection shutdown

* eglot.el (eglot--process): Delete.
(eglot-shutdown): Use jsonrpc-shutdown.
(eglot--on-shutdown): Simplify.
(eglot-reconnect): Simplify.
(eglot--connect): Simplify.

* jsonrpc-tests.el (jsonrpc--with-emacsrpc-fixture): Simplify.

* jsonrpc.el (jsonrpc-process-type, jsonrpc-running-p)
(jsonrpc-shutdown): New methods.

* eglot-tests.el (auto-reconnect): Use jsonrpc--process.
(eglot--call-with-dirs-and-files): Use jsonrpc-running-p.
---
 eglot-tests.el   | 10 --
 eglot.el | 29 ++---
 jsonrpc-tests.el | 12 ++--
 jsonrpc.el   | 22 ++
 4 files changed, 38 insertions(+), 35 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index a78069f..d085532 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -68,8 +68,7 @@
   (unwind-protect
   (let ((eglot-autoreconnect nil))
 (mapc #'eglot-shutdown
-  (cl-remove-if-not (lambda (server) (process-live-p 
(eglot--process server)))
-new-servers)))
+  (cl-remove-if-not #'jsonrpc-running-p new-servers)))
 (mapc #'kill-buffer (mapcar #'jsonrpc--events-buffer new-servers))
 (dolist (buf new-buffers) ;; have to save otherwise will get prompted
   (with-current-buffer buf (save-buffer) (kill-buffer)))
@@ -217,13 +216,12 @@ Pass TIMEOUT to `eglot--with-timeout'."
   ;; In 1.2 seconds > `eglot-autoreconnect' kill servers. We
   ;; should have a automatic reconnection.
   (run-with-timer 1.2 nil (lambda () (delete-process
-  (eglot--process server
-  (while (process-live-p (eglot--process server))
-(accept-process-output nil 0.5))
+  (jsonrpc--process server
+  (while (jsonrpc-running-p server) (accept-process-output nil 0.5))
   (should (jsonrpc-current-connection))
   ;; Now try again too quickly
   (setq server (jsonrpc-current-connection))
-  (let ((proc (eglot--process server)))
+  (let ((proc (jsonrpc--process server)))
 (run-with-timer 0.5 nil (lambda () (delete-process proc)))
 (while (process-live-p proc) (accept-process-output nil 0.5)))
   (should (not (jsonrpc-current-connection
diff --git a/eglot.el b/eglot.el
index e1592ab..cdb1c5b 100644
--- a/eglot.el
+++ b/eglot.el
@@ -203,11 +203,6 @@ lasted more than that many seconds."
 (defvar eglot--servers-by-project (make-hash-table :test #'equal)
   "Keys are projects.  Values are lists of processes.")
 
-;; HACK: Do something to fix this in the jsonrpc API or here, but in
-;; the meantime concentrate the hack here.
-(defalias 'eglot--process 'jsonrpc--process
-  "An abuse of `jsonrpc--process', a jsonrpc.el internal.")
-
 (defun eglot-shutdown (server &optional _interactive)
   "Politely ask SERVER to quit.
 Forcefully quit it if it doesn't respond.  Don't leave this
@@ -218,16 +213,15 @@ function with the server still running."
   (progn
 (setf (eglot--shutdown-requested server) t)
 (jsonrpc-request server :shutdown nil :timeout 3)
-;; this one is supposed to always fail, hence ignore-errors
+;; this one is supposed to always fail, because it asks the
+;; server to exit itself. Hence ignore-errors.
 (ignore-errors (jsonrpc-request server :exit nil :timeout 1)))
 ;; Turn off `eglot--managed-mode' where appropriate.
 (dolist (buffer (eglot--managed-buffers server))
   (with-current-buffer buffer (eglot--managed-mode-onoff server -1)))
-(while (progn (accept-process-output nil 0.1)
-  (not (eq (eglot--shutdown-requested server) :sentinel-done)))
-  (eglot--warn "Sentinel for %s still hasn't run, brutally deleting it!"
-   (eglot--process server))
-  (delete-process (eglot--process server)
+;; Now ask jsonrpc.el to shutdown server (which in normal
+;; conditions should return immediately).
+(jsonrpc-shutdown server)))
 
 (defun eglot--on-shutdown (server)
   "Called by jsonrpc.el when SERVER is already dead."
@@ -243,7 +237,7 @@ function with the server still running."
 (delq server
   (gethash (eglot--project server) eglot--servers-by-project)))
   (cond ((eglot--shutdown-requested server)
- (setf (eglot--shutdown-requested server) :sentinel-done))
+ t)
 ((not (eglot--inhibit-autoreconnect server))
  (eglot--warn "Reconnecting after unexpected server exit.")
  (eglot-reconnect server))
@@ -337,8 +331,7 @@ INTERACTIVE is t if called interactively."
   (let* ((nickname (file-name-base (directory-file-name
  

[elpa] externals/eglot 0b474ec 63/69: Fix use of jsonrpc-message in tests

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 0b474ecc5819ba7c1b3cccdffae98f6d0bf2b230
Author: João Távora 
Commit: João Távora 

Fix use of jsonrpc-message in tests

* jsonrpc-tests.el
(jsonrpc--with-emacsrpc-fixture): Use jsonrpc--message.
---
 jsonrpc-tests.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/jsonrpc-tests.el b/jsonrpc-tests.el
index c2534e5..809e988 100644
--- a/jsonrpc-tests.el
+++ b/jsonrpc-tests.el
@@ -85,7 +85,7 @@
  (cl-loop do (delete-process ,listen-server)
   while (progn (accept-process-output nil 0.1)
(process-live-p ,listen-server))
-  do (jsonrpc-message
+  do (jsonrpc--message
   "test listen-server is still running, 
waiting"
 
 (ert-deftest returns-3 ()



[elpa] externals/eglot f730fff 48/69: Merge branch 'master' into jsonrpc-refactor

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit f730fff1d7164a33367fc4990f1b4f79cc8f7a9c
Merge: 2917214 935edcc
Author: João Távora 
Commit: João Távora 

Merge branch 'master' into jsonrpc-refactor
---
 eglot.el | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/eglot.el b/eglot.el
index 70d133b..60a0322 100644
--- a/eglot.el
+++ b/eglot.el
@@ -752,7 +752,7 @@ Uses THING, FACE, DEFS and PREPEND."
  (t  'eglot-note))
message `((eglot-lsp-diag . 
,diag-spec)
  into diags
- finally (cond (eglot--current-flymake-report-fn
+ finally (cond ((and flymake-mode eglot--current-flymake-report-fn)
 (funcall eglot--current-flymake-report-fn diags)
 (setq eglot--unreported-diagnostics nil))
(t
@@ -1303,6 +1303,18 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
 
 ;;; Dynamic registration
 ;;;
+(defun eglot--wildcard-to-regexp (wildcard)
+  "(Very lame attempt to) convert WILDCARD to a Elisp regexp."
+  (cl-loop
+   with substs = '(("{" . "(")
+   ("}" . ")")
+   ("," . "|"))
+   with string = (wildcard-to-regexp wildcard)
+   for (pattern . rep) in substs
+   for target = string then result
+   for result = (replace-regexp-in-string pattern rep target)
+   finally return result))
+
 (cl-defun eglot--register-workspace/didChangeWatchedFiles (server &key id 
watchers)
   "Handle dynamic registration of workspace/didChangeWatchedFiles"
   (eglot--unregister-workspace/didChangeWatchedFiles server :id id)
@@ -1316,7 +1328,7 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
  ((and (memq action '(created changed deleted))
(cl-find file globs
 :test (lambda (f glob)
-(string-match (wildcard-to-regexp
+(string-match (eglot--wildcard-to-regexp
(expand-file-name glob))
   f
   (jsonrpc-notify



[elpa] externals/eglot 481f16e 33/69: * eglot.el (eglot-eldoc-function): Remove spurious log message

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 481f16e39a52ed00eb168105c73c3d1a48815bf7
Author: João Távora 
Commit: João Távora 

* eglot.el (eglot-eldoc-function): Remove spurious log message
---
 eglot.el | 1 -
 1 file changed, 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 31ef081..64d06a3 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1126,7 +1126,6 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
(unless sig-showing
  (when-buffer-window
   (when-let (info (eglot--hover-info contents range))
-(eglot--message "OK so info is %S and %S" info 
(null info))
 (eldoc-message info)
  :deferred :textDocument/hover))
   (when (eglot--server-capable :documentHighlightProvider)



[elpa] externals/eglot 8fda30c 67/69: Merge master into jsonrpc-refactor (using imerge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 8fda30c8e2d4e44dfb40e91109893277ca683d25
Merge: 61d1276 04ef055
Author: João Távora 
Commit: João Távora 

Merge master into jsonrpc-refactor (using imerge)
---
 README.md  |  18 +--
 eglot-tests.el |  84 +
 eglot.el   | 145 +++--
 3 files changed, 179 insertions(+), 68 deletions(-)

diff --git a/README.md b/README.md
index 2ced833..a56d750 100644
--- a/README.md
+++ b/README.md
@@ -35,13 +35,22 @@ I'll add to this list as I test more servers. In the 
meantime you can
 customize `eglot-server-programs`:
 
 ```lisp
-(add-to-list 'eglot-server-programs '(fancy-mode . ("fancy-language-server" 
"--args"")))
+(add-to-list 'eglot-server-programs '(foo-mode . ("foo-language-server" 
"--args"")))
 ```
 
 Let me know how well it works and we can add it to the list.  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`.
 
+You can also do:
+
+```lisp
+  (add-hook 'foo-mode-hook 'eglot-ensure)
+```
+
+To attempt to start an eglot session automatically everytime a
+`foo-mode` buffer is visited.
+
 # Commands and keybindings
 
 Here's a summary of available commands:
@@ -52,7 +61,10 @@ Here's a summary of available commands:
 
 - `M-x eglot-shutdown` says bye-bye to the server;
 
-- `M-x eglot-rename` asks the server to rename the symbol at point;
+- `M-x eglot-rename` ask the server to rename the symbol at point;
+
+- `M-x eglot-format-buffer` ask the server to reformat the current
+  buffer.
 
 - `M-x eglot-code-actions` asks the server for any code actions at
   point. These may tipically be simple fixes, like deleting an unused
@@ -155,7 +167,7 @@ eglot-shutdown`.
 - [ ] documentLink/resolve
 - [ ] textDocument/documentColor
 - [ ] textDocument/colorPresentation (3.6.0)
-- [ ] textDocument/formatting 
+- [x] textDocument/formatting 
 - [ ] textDocument/rangeFormatting
 - [ ] textDocument/onTypeFormatting
 - [x] textDocument/rename
diff --git a/eglot-tests.el b/eglot-tests.el
index b57b949..048b1d3 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -158,6 +158,12 @@ Pass TIMEOUT to `eglot--with-timeout'."
(format "waiting for:\n%s" 
(pp-to-string body
  (let ((event
 (cl-loop thereis (cl-loop for json in ,events-sym
+  for method = (plist-get json :method)
+  when (keywordp method)
+  do (plist-put json :method
+(substring
+ (symbol-name method)
+ 1))
   when (funcall
 (jsonrpc-lambda ,args ,@body) json)
   return (cons json before)
@@ -252,7 +258,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (eglot--wait-for (s-requests 1)
   (&key id method &allow-other-keys)
 (setq register-id id)
-(string= method 'client/registerCapability))
+(string= method "client/registerCapability"))
   (eglot--wait-for (c-replies 1)
   (&key id error &allow-other-keys)
 (and (eq id register-id) (null error
@@ -260,7 +266,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (eglot--wait-for
 (c-notifs 3 "waiting for didChangeWatchedFiles notification")
 (&key method params &allow-other-keys)
-  (and (string= method 'workspace/didChangeWatchedFiles)
+  (and (string= method "workspace/didChangeWatchedFiles")
(cl-destructuring-bind (&key uri type)
(elt (plist-get params :changes) 0)
  (and (string= (eglot--path-to-uri "Cargo.toml") uri)
@@ -280,7 +286,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (eglot--tests-connect)
   (eglot--wait-for (s-notifs 1)
   (&key _id method &allow-other-keys)
-(string= method 'textDocument/publishDiagnostics))
+(string= method "textDocument/publishDiagnostics"))
   (flymake-start)
   (goto-char (point-min))
   (flymake-goto-next-error 1 '() t)
@@ -300,11 +306,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (eglot--find-file-noselect "hover-project/main.rs")
 (should (zerop (shell-command "cargo init")))
 (eglot--sniffing (
-  :server-notifications s-notifs
-  :server-requests s-requests
   :server-replies s-replies
-  :client-notifications c-notifs
-  :client-replies c-replies
   :

[elpa] externals/eglot 6c9d41e 38/69: Add reasonably sophisticated deferred action tests

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 6c9d41e6eba8b76c3b9500d05344936cd38533c7
Author: João Távora 
Commit: João Távora 

Add reasonably sophisticated deferred action tests

* jsonrpc-tests.el (jsonrpc-test-conn): New test class.
(jsonrpc--with-emacsrpc-fixture): Redesign.
(jsonrpc-connection-ready-p): New method for jsonrpc-test-conn.
(deferred-action): New test for deferred actions.
(jsonrpc-errors-with--32601, returns-3)
(signals-an--32603-JSONRPC-error, times-out)
(stretching-it-but-works, json-el-cant-serialize-this): Use local
var conn.
---
 jsonrpc-tests.el | 168 ---
 1 file changed, 134 insertions(+), 34 deletions(-)

diff --git a/jsonrpc-tests.el b/jsonrpc-tests.el
index a112063..33a7ae5 100644
--- a/jsonrpc-tests.el
+++ b/jsonrpc-tests.el
@@ -28,79 +28,179 @@
 
 (require 'ert)
 (require 'jsonrpc)
+(require 'eieio)
+
+(defclass jsonrpc-test-conn (jsonrpc-process-connection)
+  ((hold-deferred :initform t :accessor jsonrpc--hold-deferred)
+   (shutdown-complete-p :initform nil :accessor jsonrpc--shutdown-complete-p)))
 
 (cl-defmacro jsonrpc--with-emacsrpc-fixture ((endpoint-sym) &body body)
   (declare (indent 1) (debug t))
-  (let ((server (gensym)))
-`(let* ((,server (make-network-process
-  :name "Emacs RPC server" :server t :host "localhost" 
:service 4
-  :log (lambda (_server client _message)
- (jsonrpc-connect
-  (process-name client)
-  (make-instance 'jsonrpc-process-connection 
:process client)
-  (lambda (endpoint method id params)
-(unless (memq method '(+ - * / vconcat append 
sit-for))
-  (signal 'jsonrpc-error 
`((jsonrpc-error-message
-. "Sorry, this 
isn't allowed")
-   (jsonrpc-error-code 
. -32601
-(jsonrpc-reply endpoint id :result
-   (apply method (append params 
nil
+  (let ((server (gensym "server-")) (listen-server (gensym "listen-server-")))
+`(let* (,server
+(,listen-server
+ (make-network-process
+  :name "Emacs RPC server" :server t :host "localhost"
+  :service 4
+  :log (lambda (_server client _message)
+ (setq ,server
+   (jsonrpc-connect
+(process-name client)
+(make-instance 'jsonrpc-test-conn :process client)
+(lambda (endpoint method id params)
+  (unless (memq method '(+ - * / vconcat append
+   sit-for ignore))
+(signal 'jsonrpc-error
+`((jsonrpc-error-message
+   . "Sorry, this isn't allowed")
+  (jsonrpc-error-code . -32601
+  (jsonrpc-reply endpoint id :result
+ (apply method (append params 
nil
+(lambda (conn)
+  (setf (jsonrpc--shutdown-complete-p conn) 
t)))
 (,endpoint-sym (jsonrpc-connect
-"Emacs RPC client" '("localhost" 4)
+"Emacs RPC client"
+'(jsonrpc-test-conn "localhost" 4)
 (lambda (_endpoint method _id &rest _params)
-  (message "server wants to %s" method)
+  (message "server wants to %s" method))
+(lambda (conn)
+  (setf (jsonrpc--shutdown-complete-p conn) t)
(unwind-protect
-   ,@body
+   (progn
+ (cl-assert ,endpoint-sym)
+ ,@body
+ (kill-buffer (jsonrpc--events-buffer ,endpoint-sym))
+ (when ,server
+   (kill-buffer (jsonrpc--events-buffer ,server
  (unwind-protect
- (delete-process ,server)
-   (delete-process
-(jsonrpc--process ,endpoint-sym)))
+ (cl-loop do (delete-process (jsonrpc--process ,endpoint-sym))
+  while (progn (accept-process-output nil 0.1)
+   (not (jsonrpc--shutdown-complete-p 
,endpoint-sym)))
+  do (jsonrpc-message
+  "test client is still running, waiting"))
+   (unwind-protect
+   (cl-loop do (delete-process (jsonrpc--process ,server))
+   

[elpa] externals/eglot 1f09fd3 59/69: Review commentary section before another review cycle

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 1f09fd332efc0f202d0816005e133be11923debf
Author: João Távora 
Commit: João Távora 

Review commentary section before another review cycle

* jsonrpc.el (jsonrpc-connection-send): Send Content-Type header.
---
 jsonrpc.el | 36 +---
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index db99f16..0c38257 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -36,7 +36,7 @@
 ;; To model this agnosticism, jsonrpc.el uses objects derived from a
 ;; base `jsonrpc-connection' class, which is "abstract" or "virtual"
 ;; (in modern OO parlance) and represents the connection to the remote
-;; JSON endpoint.  We can define two interfaces:
+;; JSON endpoint.  Around thsi calss can define two interfaces:
 ;;
 ;; 1) A user interface to the JSONRPC _application_, whereby the
 ;; application uses the `jsonrpc-connection' object to communicate
@@ -57,25 +57,26 @@
 ;; forwarded instead.  A suitable error reponse is also sent if the
 ;; function error unexpectedly with any other error.
 ;;
-;; 2) A inheritance-based interface for building arbitrary JSONPRPC
-;; _transport implementations_.
+;; 2) A inheritance-based interface to the JSONPRPC _transport
+;; implementations_, whereby `jsonrpc-connection' is subclassed.
 ;;
-;; For initiating contacts to the endpoint and replying to it, a
-;; subclass of `jsonrpc-connection' must implement
+;; For initiating contacts to the endpoint and replying to it, that
+;; subclass `jsonrpc-connection' must implement
 ;; `jsonrpc-connection-send'.  Likewise, for handling remotely
 ;; initiated contacts, it must arrange for the dispatcher functions
 ;; held in `jsonrpc--request-dispatcher' and
 ;; `jsonrpc--notification-dispatcher' to be called when appropriate,
 ;; i.e. when noticing a new JSONRPC message on the wire.  Optionally
-;; it should implement `jsonrpc-shutdown' and `jsonrpc-running-p'.
+;; it should implement `jsonrpc-shutdown' and `jsonrpc-running-p' if
+;; these concepts apply to the transport.
 ;;
-;; For convenience, jsonrpc.el comes built-in with
+;; For convenience, jsonrpc.el comes built-in with a
 ;; `jsonrpc-process-connection' subclass for talking to local
 ;; subprocesses (through stdin/stdout) and TCP hosts using sockets.
 ;; This uses some basic HTTP-style enveloping headers for JSON objects
 ;; sent over the wire.  For an example of an application using this
-;; transport scheme on top of JSONRPC, see for example the Language
-;; Server Protocol
+;; transport scheme on top of JSONRPC, see the Language Server
+;; Protocol
 ;; (https://microsoft.github.io/language-server-protocol/specification).
 ;; `jsonrpc-process-connection' also implements `jsonrpc-shutdown',
 ;; `jsonrpc-running-p'.
@@ -170,7 +171,8 @@ notifications.  CONN, METHOD and PARAMS are the same as in
 
 ;;; API mandatory
 (cl-defgeneric jsonrpc-connection-send (conn &key id method params result 
error)
-  "Send a JSONRPC message to connection CONN.")
+  "Send a JSONRPC message to connection CONN.
+ID, METHOD, PARAMS, RESULT and ERROR. ")
 
 ;;; API optional
 (cl-defgeneric jsonrpc-shutdown (conn)
@@ -391,11 +393,15 @@ connection object, called when the process dies .")
  ,@(when params `(:params ,params))
  ,@(when result `(:result ,result))
  ,@(when error  `(:error  ,error
- (json (jsonrpc--json-encode message)))
-(process-send-string (jsonrpc--process connection)
- (format "Content-Length: %d\r\n\r\n%s"
- (string-bytes json)
- json))
+ (json (jsonrpc--json-encode message))
+ (headers
+  `(("Content-Length" . ,(string-bytes json))
+("Content-Type" . "application/vscode-jsonrpc; charset=utf-8"
+(process-send-string
+ (jsonrpc--process connection)
+ (cl-loop for (header . value) in headers
+  concat (concat header ": " value "\r\n") into header-section
+  finally return (format "%s\r\n%s" header-section json)))
 (jsonrpc--log-event connection message 'client)))
 
 (defun jsonrpc-process-type (conn)



[elpa] externals/eglot 10559a5 56/69: Shuffle definitions around again

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 10559a5535fb31369e59dbfe13d2f4e3dc7b0197
Author: João Távora 
Commit: João Távora 

Shuffle definitions around again
---
 jsonrpc.el | 279 +
 1 file changed, 151 insertions(+), 128 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index f5808fc..3e0bf8e 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -100,33 +100,8 @@
 (require 'array) ; xor
 
 
-;; Public stuff
-;;
-(defun jsonrpc-error (&rest args)
-  "Error out with FORMAT and ARGS.
-If invoked inside a dispatcher function, this function is suitable
-for replying to the remote endpoint with an error message.
-
-ARGS can be of the form (FORMAT-STRING . MOREARGS) for replying
-with a -32603 error code and a message formed by formatting
-FORMAT-STRING with MOREARGS.
-
-Alternatively ARGS can be plist representing a JSONRPC error
-object, using the keywords `:code', `:message' and `:data'."
-  (if (stringp (car args))
-  (let ((msg
- (apply #'format-message (car args) (cdr args
-(signal 'jsonrpc-error
-`(,msg
-  (jsonrpc-error-code . ,32603)
-  (jsonrpc-error-message . ,msg
-(cl-destructuring-bind (&key code message data) args
-  (signal 'jsonrpc-error
-  `(,(format "[jsonrpc] error ")
-(jsonrpc-error-code . ,code)
-(jsonrpc-error-message . ,message)
-(jsonrpc-error-data . ,data))
-
+;;; Public API
+;;;
 ;;;###autoload
 (defclass jsonrpc-connection ()
   ((name
@@ -180,47 +155,34 @@ arguments (CONN METHOD PARAMS) for handling JSONRPC
 notifications.  CONN, METHOD and PARAMS are the same as in
 :REQUEST-DISPATCHER.")
 
-;;;###autoload
-(defclass jsonrpc-process-connection (jsonrpc-connection)
-  ((-process
-:initarg :process :accessor jsonrpc--process
-:documentation "Process object wrapped by the this connection.")
-   (-expected-bytes
-:accessor jsonrpc--expected-bytes
-:documentation "How many bytes declared by server")
-   (-on-shutdown
-:accessor jsonrpc--on-shutdown
-:initform #'ignore
-:initarg :on-shutdown
-:documentation "Function run when the process dies."))
-  :documentation "A JSONRPC connection over an Emacs process.
-The following initargs are accepted:
+;;; API mandatory
+(cl-defgeneric jsonrpc-connection-send (conn &key id method params result 
error)
+  "Send a JSONRPC message to connection CONN.")
 
-:PROCESS (mandatory), a live running Emacs process object or a
-function of no arguments producing one such object.  The process
-represents either a pipe connection to locally running process or
-a stream connection to a network host.  The remote endpoint is
-expected to understand JSONRPC messages with basic HTTP-style
-enveloping headers such as \"Content-Length:\".
+;;; API optional
+(cl-defgeneric jsonrpc-shutdown (conn)
+  "Shutdown the JSONRPC connection CONN.")
 
-:ON-SHUTDOWN (optional), a function of one argument, the
-connection object, called when the process dies .")
+;;; API optional
+(cl-defgeneric jsonrpc-running-p (conn)
+  "Tell if the JSONRPC connection CONN is still running.")
 
-(cl-defmethod initialize-instance ((conn jsonrpc-process-connection) slots)
-  (cl-call-next-method)
-  (let* ((proc (plist-get slots :process))
- (proc (if (functionp proc) (funcall proc) proc))
- (buffer (get-buffer-create (format "*%s output*" (process-name 
proc
- (stderr (get-buffer-create (format "*%s stderr*" (process-name 
proc)
-(setf (jsonrpc--process conn) proc)
-(set-process-buffer proc buffer)
-(process-put proc 'jsonrpc-stderr stderr)
-(set-process-filter proc #'jsonrpc--process-filter)
-(set-process-sentinel proc #'jsonrpc--process-sentinel)
-(with-current-buffer (process-buffer proc)
-  (set-marker (process-mark proc) (point-min))
-  (let ((inhibit-read-only t)) (erase-buffer) (read-only-mode t) proc))
-(process-put proc 'jsonrpc-connection conn)))
+;;; API optional
+(cl-defgeneric jsonrpc-connection-ready-p (connection what)
+"Tell if CONNECTION is ready for WHAT in current buffer.
+If it isn't, a deferrable `jsonrpc-async-request' will be
+deferred to the future.  By default, all connections are ready
+for sending requests immediately."
+(:method (_s _what)   ;; by default all connections are ready
+ t))
+
+
+;;; Convenience
+;;;
+(cl-defmacro jsonrpc-lambda (cl-lambda-list &body body)
+  (declare (indent 1) (debug (sexp &rest form)))
+  (let ((e (gensym "jsonrpc-lambda-elem")))
+`(lambda (,e) (apply (cl-function (lambda ,cl-lambda-list ,@body)) ,e
 
 (defun jsonrpc-events-buffer (connection)
   "Get or create JSONRPC events buffer for CONNECTION."
@@ -237,74 +199,37 @@ connection object, called when the process dies .")
buffer
 buffer))
 
-(defun jsonrpc-stderr-buffer (connection)
-  "Get CONNECTION's stderr buffer, if any."
-  (process-ge

[elpa] externals/eglot 4525eca 43/69: Support json.c. API purely based on classes

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 4525eca32a10046484b5a6dd1f0647927aae2dd6
Author: João Távora 
Commit: João Távora 

Support json.c.  API purely based on classes

No more jsonrpc-connect.

This is a big commit because of a data loss problem. It should be at
least two separate commits (json.c-support and new API)

* eglot.el (eglot-server-programs): Rework docstring.
(eglot-handle-request): Don't take ID param
(eglot-lsp-server): No more initargs.
(eglot--interactive): Return 5 args.
(eglot): Take 5 args.
(eglot-reconnect): Pass 6 args to eglot--connect.
(eglot--dispatch): Remove.
(eglot--connect): Take 6 args. Rework.
(eglot-handle-notification): Change all specializations
to use a non-keyword symbol spec.
(eglot-handle-request): Remove ID param from all
specializations.  Don't pass ID to jsonrpc-reply.
(eglot--register-unregister): Don't take JSONRPC-ID arg.
Don't pass ID to jsonrpc-reply.

* jsonrpc-tests.el (returns-3, signals-an--32603-JSONRPC-error)
(times-out, stretching-it-but-works)
(json-el-cant-serialize-this, jsonrpc-connection-ready-p)
(deferred-action-intime, deferred-action-toolate)
(deferred-action-timeout): Pass JSON objects compatible with
json.c
(jsonrpc--test-client, jsonrpc--test-endpoint): New classes
(jsonrpc--with-emacsrpc-fixture): Don't use jsonrpc-connect.
(jsonrpc-connection-ready-p): Update signature.

* jsonrpc.el: Rewrite commentary.
(jsonrpc-connection): Rework class.
(jsonrpc-process-connection): Rework class.
(initialize-instance): New methods..
(jsonrpc--json-read, jsonrpc--json-encode): Reindent.
(jsonrpc-connect): Delete.
(jsonrpc--json-read, jsonrpc--json-encode):
New functions for working with json.c
(jsonrpc--process-filter): Call them.
(jsonrpc--unanswered-request-id): New variable.
(jsonrpc--connection-receive): Use jsonrpc--unanswered-request-id
(jsonrpc-connection-send): Take keyword params to build message
instead of message.
(jsonrpc-notify, jsonrpc--async-request-1): Use new
jsonrpc-connection-send.
(jsonrpc-reply): Simplify.

* eglot-tests.el (rls-watches-files, rls-basic-diagnostics)
(rls-hover-after-edit): Correctly compare using string= and
non-keyword symbols.
---
 eglot-tests.el   |   8 +-
 eglot.el | 171 --
 jsonrpc-tests.el |  65 +
 jsonrpc.el   | 429 ---
 4 files changed, 324 insertions(+), 349 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index af8cc37..bd9e2f3 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -250,7 +250,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (eglot--wait-for (s-requests 1)
   (&key id method &allow-other-keys)
 (setq register-id id)
-(string= method "client/registerCapability"))
+(string= method 'client/registerCapability))
   (eglot--wait-for (c-replies 1)
   (&key id error &allow-other-keys)
 (and (eq id register-id) (null error
@@ -258,7 +258,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (eglot--wait-for
 (c-notifs 3 "waiting for didChangeWatchedFiles notification")
 (&key method params &allow-other-keys)
-  (and (eq method :workspace/didChangeWatchedFiles)
+  (and (string= method 'workspace/didChangeWatchedFiles)
(cl-destructuring-bind (&key uri type)
(elt (plist-get params :changes) 0)
  (and (string= (eglot--path-to-uri "Cargo.toml") uri)
@@ -278,7 +278,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (apply #'eglot (eglot--interactive))
   (eglot--wait-for (s-notifs 1)
   (&key _id method &allow-other-keys)
-(string= method "textDocument/publishDiagnostics"))
+(string= method 'textDocument/publishDiagnostics))
   (flymake-start)
   (goto-char (point-min))
   (flymake-goto-next-error 1 '() t)
@@ -318,7 +318,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (eglot--wait-for (c-reqs)
 (&key id method &allow-other-keys)
   (setq pending-id id)
-  (string= method :textDocument/documentHighlight))
+  (string= method 'textDocument/documentHighlight))
 (eglot--wait-for (s-replies)
 (&key id &allow-other-keys)
   (eq id pending-id
diff --git a/eglot.el b/eglot.el
index d5498f9..e1592ab 100644
--- a/eglot.el
+++ b/eglot.el
@@ -79,8 +79,8 @@
 (php-mode . ("php" "vendor/felixfbecker/\
 language-server/bin/php-language-server.php")))
   "How the command `eglot' guesses the server to start.
-An association list of (MAJOR-MODE . SPEC) pair.  MAJOR-MODE is a
-

[elpa] externals/eglot 46e6107 54/69: Reshuffle definitions inside jsonrpc.el

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 46e610761fbcae755a8475e5dbb3e348ec4d4119
Author: João Távora 
Commit: João Távora 

Reshuffle definitions inside jsonrpc.el

Split between public and private
---
 jsonrpc.el | 436 +++--
 1 file changed, 221 insertions(+), 215 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 4c2140c..0537699 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -99,8 +99,9 @@
 (require 'ert) ; to escape a `condition-case-unless-debug'
 (require 'array) ; xor
 
-(define-error 'jsonrpc-error "jsonrpc-error")
-
+
+;; Public stuff
+;;
 (defun jsonrpc-error (&rest args)
   "Error out with FORMAT and ARGS.
 If invoked inside a dispatcher function, this function is suitable
@@ -126,23 +127,6 @@ object, using the keywords `:code', `:message' and 
`:data'."
 (jsonrpc-error-message . ,message)
 (jsonrpc-error-data . ,data))
 
-(defun jsonrpc--message (format &rest args)
-  "Message out with FORMAT with ARGS."
-  (message "[jsonrpc] %s" (apply #'format format args)))
-
-(defun jsonrpc--debug (server format &rest args)
-  "Debug message for SERVER with FORMAT and ARGS."
-  (jsonrpc-log-event
-   server (if (stringp format)`(:message ,(format format args)) format)))
-
-(defun jsonrpc--warn (format &rest args)
-  "Warning message with FORMAT and ARGS."
-  (apply #'jsonrpc--message (concat "(warning) " format) args)
-  (let ((warning-minimum-level :error))
-(display-warning 'jsonrpc
- (apply #'format format args)
- :warning)))
-
 ;;;###autoload
 (defclass jsonrpc-connection ()
   ((name
@@ -238,6 +222,174 @@ connection object, called when the process dies .")
   (let ((inhibit-read-only t)) (erase-buffer) (read-only-mode t) proc))
 (process-put proc 'jsonrpc-connection conn)))
 
+(defun jsonrpc-events-buffer (connection)
+  "Get or create JSONRPC events buffer for CONNECTION."
+  (let* ((probe (jsonrpc--events-buffer connection))
+ (buffer (or (and (buffer-live-p probe)
+  probe)
+ (let ((buffer (get-buffer-create
+(format "*%s events*"
+(jsonrpc-name connection)
+   (with-current-buffer buffer
+ (buffer-disable-undo)
+ (read-only-mode t)
+ (setf (jsonrpc--events-buffer connection) buffer))
+   buffer
+buffer))
+
+(defun jsonrpc-stderr-buffer (connection)
+  "Get CONNECTION's stderr buffer, if any."
+  (process-get (jsonrpc--process connection) 'jsonrpc-stderr))
+
+(cl-defmethod jsonrpc-connection-send ((connection jsonrpc-process-connection)
+   &rest args
+   &key
+   id
+   method
+   params
+   result
+   error)
+  "Send MESSAGE, a JSON object, to CONNECTION."
+  (let* ((method
+  (cond ((keywordp method)
+ (substring (symbol-name method) 1))
+((and method (symbolp method)) (symbol-name method))
+(t method)))
+ (message `(:jsonrpc "2.0"
+ ,@(when method `(:method ,method))
+ ,@(when id `(:id ,id))
+ ,@(when params `(:params ,params))
+ ,@(when result `(:result ,result))
+ ,@(when error  `(:error  ,error
+ (json (jsonrpc--json-encode message)))
+(process-send-string (jsonrpc--process connection)
+ (format "Content-Length: %d\r\n\r\n%s"
+ (string-bytes json)
+ json))
+(jsonrpc-log-event connection message 'client)))
+
+(cl-defmethod jsonrpc-process-type ((conn jsonrpc-process-connection))
+  "Return the process-type of JSONRPC connection CONN"
+  (let ((proc (jsonrpc--process conn))) (and (process-live-p proc) proc)))
+
+(cl-defmethod jsonrpc-running-p ((conn jsonrpc-process-connection))
+  "Return non-nil if JSONRPC connection CONN is running."
+  (process-live-p (jsonrpc--process conn)))
+
+(cl-defmethod jsonrpc-shutdown ((conn jsonrpc-process-connection))
+  "Shutdown the JSONRPC connection CONN."
+  (cl-loop
+   with proc = (jsonrpc--process conn)
+   do
+   (delete-process proc)
+   (accept-process-output nil 0.1)
+   while (not (process-get proc 'jsonrpc-sentinel-done))
+   do (jsonrpc--warn
+   "Sentinel for %s still hasn't run,  deleting it!" proc)))
+
+(defun jsonrpc-forget-pending-continuations (connection)
+  "Stop waiting for responses from the current JSONRPC CONNECTION."
+  (clrhash (jsonrpc--request-continuations connec

[elpa] externals/eglot 69a622a 64/69: Fix some typos

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 69a622a7a9d5df35ee92aa57d359794bc5985c21
Author: João Távora 
Commit: João Távora 

Fix some typos
---
 jsonrpc.el | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index f063870..0205015 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -36,7 +36,7 @@
 ;; To model this agnosticism, jsonrpc.el uses objects derived from a
 ;; base `jsonrpc-connection' class, which is "abstract" or "virtual"
 ;; (in modern OO parlance) and represents the connection to the remote
-;; JSON endpoint.  Around thsi calss can define two interfaces:
+;; JSON endpoint.  Around this class we can define two interfaces:
 ;;
 ;; 1) A user interface to the JSONRPC _application_, whereby the
 ;; application uses the `jsonrpc-connection' object to communicate
@@ -62,14 +62,17 @@
 ;;
 ;; For initiating contacts to the endpoint and replying to it, that
 ;; subclass `jsonrpc-connection' must implement
-;; `jsonrpc-connection-send'.  Likewise, for handling remotely
-;; initiated contacts, it must arrange for the dispatcher functions
-;; held in `jsonrpc--request-dispatcher' and
-;; `jsonrpc--notification-dispatcher' to be called when appropriate,
-;; i.e. when noticing a new JSONRPC message on the wire.  The function
-;; `jsonrpc-connection-receive' is a good way to do that.  Optionally
-;; it should implement `jsonrpc-shutdown' and `jsonrpc-running-p' if
-;; these concepts apply to the transport.
+;; `jsonrpc-connection-send'.
+;;
+;; Likewise, for handling remotely initiated contacts, it must arrange
+;; for the dispatcher functions held in `jsonrpc--request-dispatcher'
+;; and `jsonrpc--notification-dispatcher' to be called when
+;; appropriate, i.e. when noticing a new JSONRPC message on the wire.
+;; The function `jsonrpc-connection-receive' is a good way to do that.
+;;
+;; Finally, and optionally, the `jsonrpc-connection' subclass should
+;; implement `jsonrpc-shutdown' and `jsonrpc-running-p' if these
+;; concepts apply to the transport.
 ;;
 ;; For convenience, jsonrpc.el comes built-in with a
 ;; `jsonrpc-process-connection' subclass for talking to local
@@ -464,7 +467,7 @@ connection object, called when the process dies .")
"Sentinel for %s still hasn't run,  deleting it!" proc)))
 
 (defun jsonrpc-stderr-buffer (conn)
-  "Get CONN's stderr buffer, if any."
+  "Get CONN's standard error buffer, if any."
   (process-get (jsonrpc--process conn) 'jsonrpc-stderr))
 
 
@@ -688,7 +691,7 @@ TIMEOUT is nil)."
  :warning)))
 
 (defun jsonrpc--log-event (connection message &optional type)
-  "Log an jsonrpc-related event.
+  "Log a JSONRPC-related event.
 CONNECTION is the current connection.  MESSAGE is a JSON-like
 plist.  TYPE is a symbol saying if this is a client or server
 originated."



[elpa] externals/eglot 61d1276 66/69: Fix another bug in jsonrpc-connection-send

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 61d1276db33a33e7caa006268300b226b493e33a
Author: João Távora 
Commit: João Távora 

Fix another bug in jsonrpc-connection-send

* jsonrpc.el (jsonrpc-connection-send): Only send method if method
supplied.
---
 jsonrpc.el | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index caf46af..ef33a38 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -431,10 +431,10 @@ connection object, called when the process dies .")
_error
_partial)
   "Send MESSAGE, a JSON object, to CONNECTION."
-  (plist-put args :method
- (cond ((keywordp method) (substring (symbol-name method) 1))
-   ((and method (symbolp method)) (symbol-name method))
-   (t method)))
+  (when method
+(plist-put args :method
+   (cond ((keywordp method) (substring (symbol-name method) 1))
+ ((and method (symbolp method)) (symbol-name method)
   (let* ( (message `(:jsonrpc "2.0" ,@args))
   (json (jsonrpc--json-encode message))
   (headers



[elpa] externals/eglot 7371f68 57/69: * jsonrpc.el: Rewrite commentary.

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 7371f68639ac03adade8dc3ccfd275db449ea7b6
Author: João Távora 
Commit: João Távora 

* jsonrpc.el: Rewrite commentary.
---
 jsonrpc.el | 83 --
 1 file changed, 48 insertions(+), 35 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 3e0bf8e..db99f16 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -22,7 +22,7 @@
 
 ;;; Commentary:
 
-;; Originally extracted from eglot.el (Emacs LSP client)
+;; (Library originally extracted from eglot.el, an Emacs LSP client)
 ;;
 ;; This library implements the JSONRPC 2.0 specification as described
 ;; in http://www.jsonrpc.org/.  As the name suggests, JSONRPC is a
@@ -33,46 +33,59 @@
 ;; concepts can be used within the same process, over sockets, over
 ;; http, or in many various message passing environments."
 ;;
-;; To approach this agnosticism, jsonrpc.el uses objects derived from
-;; a base `jsonrpc-connection' class, which is "abstract" or "virtual"
+;; To model this agnosticism, jsonrpc.el uses objects derived from a
+;; base `jsonrpc-connection' class, which is "abstract" or "virtual"
 ;; (in modern OO parlance) and represents the connection to the remote
-;; JSON endpoint.  Equally abstract operations such as sending and
-;; receiving are modelled as generic functions, so JSONRPC
-;; applications operating over arbitrary transport infrastructures can
-;; specify a subclass of `jsonrpc-connection' and write specific
-;; methods for it.
+;; JSON endpoint.  We can define two interfaces:
 ;;
-;; The `jsonrpc-connection' constructor is the most generic entry
-;; point for these uses.  However, for convenience, jsonrpc.el comes
-;; built-in with `jsonrpc-process-connection' class for talking to
-;; local subprocesses (through stdin/stdout) and TCP hosts using
-;; sockets.  This uses some basic HTTP-style enveloping headers for
-;; JSON objects sent over the wire.  For an example of an application
-;; using this transport scheme on top of JSONRPC, see for example the
-;; Language Server Protocol
+;; 1) A user interface to the JSONRPC _application_, whereby the
+;; application uses the `jsonrpc-connection' object to communicate
+;; with the remote JSONRPC enpoint.
+;;
+;; Ignorant of how the object was obtained, the JSONRPC application
+;; passes this object to `jsonrpc-notify', `jsonrpc-request' and
+;; `jsonrpc-async-request' as a way of contacting the remote endpoint.
+;; Similarly, for handling remotely initiated contacts, applications
+;; should initialize these objects with `:request-dispatcher' and
+;; `:notification-dispatcher' initargs which are two functions
+;; receiving the connection object, a symbol naming the JSONRPC
+;; method, and a JSONRPC "params" object.
+;;
+;; The request dispatcher's local return value determines the success
+;; response to forward to the server.  The function can use
+;; `jsonrpc-error' to exit non-locally and send an error response is
+;; forwarded instead.  A suitable error reponse is also sent if the
+;; function error unexpectedly with any other error.
+;;
+;; 2) A inheritance-based interface for building arbitrary JSONPRPC
+;; _transport implementations_.
+;;
+;; For initiating contacts to the endpoint and replying to it, a
+;; subclass of `jsonrpc-connection' must implement
+;; `jsonrpc-connection-send'.  Likewise, for handling remotely
+;; initiated contacts, it must arrange for the dispatcher functions
+;; held in `jsonrpc--request-dispatcher' and
+;; `jsonrpc--notification-dispatcher' to be called when appropriate,
+;; i.e. when noticing a new JSONRPC message on the wire.  Optionally
+;; it should implement `jsonrpc-shutdown' and `jsonrpc-running-p'.
+;;
+;; For convenience, jsonrpc.el comes built-in with
+;; `jsonrpc-process-connection' subclass for talking to local
+;; subprocesses (through stdin/stdout) and TCP hosts using sockets.
+;; This uses some basic HTTP-style enveloping headers for JSON objects
+;; sent over the wire.  For an example of an application using this
+;; transport scheme on top of JSONRPC, see for example the Language
+;; Server Protocol
 ;; (https://microsoft.github.io/language-server-protocol/specification).
 ;; `jsonrpc-process-connection' also implements `jsonrpc-shutdown',
 ;; `jsonrpc-running-p'.
 ;;
-;; Whatever the method used to obtain a `jsonrpc-connection', it is
-;; given to `jsonrpc-notify', `jsonrpc-request' and
-;; `jsonrpc-async-request' as a way of contacting the connected remote
-;; endpoint.
-;;
-;; For handling remotely initiated contacts, `jsonrpc-connection'
-;; objects hold dispatcher functions that the application should pass
-;; to object's constructor if it is interested in those messages.  The
-;; request dispatcher's return value determines the success response
-;; to forward to the server.  Alternatively, if the function signals
-;; an error, a suitable error response is forwarded instead.
+ JSON object format:
 ;;
-;; The JSON objects are passed to the dispatcher after b

[elpa] externals/eglot bb60c0c 21/69: Rename jrpc.el to jsonrpc.el

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit bb60c0c89ca10fad5a820903bfbb566be89061ea
Author: João Távora 
Commit: João Távora 

Rename jrpc.el to jsonrpc.el

* eglot.el [everywhere]: jrpc -> jsonrpc everywhere.
Reindent.

* eglot-tests [everywhere]: jrpc -> jsonrpc everywhere.

* jsonrpc.el: New file.

* Makefile: jrpc.el -> jsonrpc.el
---
 Makefile  |   2 +-
 eglot-tests.el|  26 ++--
 eglot.el  | 359 ++-
 jrpc.el => jsonrpc.el | 414 ++
 4 files changed, 409 insertions(+), 392 deletions(-)

diff --git a/Makefile b/Makefile
index 2360136..41619fc 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ EMACS=emacs
 
 LOAD_PATH=-L .
 
-ELFILES := eglot.el jrpc.el eglot-tests.el
+ELFILES := eglot.el jsonrpc.el eglot-tests.el
 ELCFILES := $(ELFILES:.el=.elc)
 
 all: compile
diff --git a/eglot-tests.el b/eglot-tests.el
index 7a832dd..9359a78 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -78,7 +78,7 @@
   (let* ((tag (make-symbol "tag"))
  (timed-out (make-symbol "timeout"))
  (timer )
- (jrpc-request-timeout 1)
+ (jsonrpc-request-timeout 1)
  (retval))
 (unwind-protect
 (setq retval
@@ -112,22 +112,22 @@
   (let (proc)
 (eglot--with-test-timeout 2
   (eglot--with-dirs-and-files
-'(("project" . (("coiso.rs" . "bla")
-("merdix.rs" . "bla")))
-  ("anotherproject" . (("cena.rs" . "bla"
+  '(("project" . (("coiso.rs" . "bla")
+  ("merdix.rs" . "bla")))
+("anotherproject" . (("cena.rs" . "bla"
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
   (setq proc
 (eglot 'rust-mode `(transient . ,default-directory)
'("rls")))
-  (should (jrpc-current-process)))
+  (should (jsonrpc-current-process)))
 (with-current-buffer
 (eglot--find-file-noselect "project/merdix.rs")
-  (should (jrpc-current-process))
-  (should (eq (jrpc-current-process) proc)))
+  (should (jsonrpc-current-process))
+  (should (eq (jsonrpc-current-process) proc)))
 (with-current-buffer
 (eglot--find-file-noselect "anotherproject/cena.rs")
-  (should-error (jrpc-current-process-or-lose)))
+  (should-error (jsonrpc-current-process-or-lose)))
 
 (ert-deftest auto-reconnect ()
   "Start a server. Kill it. Watch it reconnect."
@@ -135,8 +135,8 @@
 (eglot-autoreconnect 1))
 (eglot--with-test-timeout 3
   (eglot--with-dirs-and-files
-'(("project" . (("coiso.rs" . "bla")
-("merdix.rs" . "bla"
+  '(("project" . (("coiso.rs" . "bla")
+  ("merdix.rs" . "bla"
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
   (setq proc
@@ -146,12 +146,12 @@
   ;; should have a automatic reconnection.
   (run-with-timer 1.2 nil (lambda () (delete-process proc)))
   (while (process-live-p proc) (accept-process-output nil 0.5))
-  (should (jrpc-current-process))
+  (should (jsonrpc-current-process))
   ;; Now try again too quickly
-  (setq proc (jrpc-current-process))
+  (setq proc (jsonrpc-current-process))
   (run-with-timer 0.5 nil (lambda () (delete-process proc)))
   (while (process-live-p proc) (accept-process-output nil 0.5))
-  (should (not (jrpc-current-process
+  (should (not (jsonrpc-current-process
 
 (provide 'eglot-tests)
 ;;; eglot-tests.el ends here
diff --git a/eglot.el b/eglot.el
index 81229a5..907c98b 100644
--- a/eglot.el
+++ b/eglot.el
@@ -59,7 +59,7 @@
 (require 'flymake)
 (require 'xref)
 (require 'subr-x)
-(require 'jrpc)
+(require 'jsonrpc)
 (require 'filenotify)
 
 
@@ -98,26 +98,26 @@ lasted more than that many seconds."
 (defvar eglot--processes-by-project (make-hash-table :test #'equal)
   "Keys are projects.  Values are lists of processes.")
 
-(jrpc-define-process-var eglot--major-mode nil
+(jsonrpc-define-process-var eglot--major-mode nil
   "The major-mode this server is managing.")
 
-(jrpc-define-process-var eglot--capabilities :unreported
+(jsonrpc-define-process-var eglot--capabilities :unreported
   "Holds list of capabilities that server reported")
 
-(jrpc-define-process-var eglot--project nil
+(jsonrpc-define-process-var eglot--project nil
   "The project the server belongs to.")
 
-(jrpc-define-process-var eglot--spinner `(nil nil t)
+(jsonrpc-define-process-var eglot--spinner `(nil nil t)
   "\"Spinner\" used by some servers.
 A list (ID WHAT DONE-P).")
 
-(jrpc-define-process-var eglot--moribund nil
+(jsonrpc-define-process-var eglot--moribund nil
   "Non-nil if server is about to exit")
 
-(jrpc-def

[elpa] externals/eglot b3c8b59 02/69: Refactor JSON-RPC lib jrpc.el from eglot.el

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit b3c8b59d4f5ed5470c28684f76431dd5c1882a47
Author: João Távora 
Commit: João Távora 

Refactor JSON-RPC lib jrpc.el from eglot.el

* eglot.el [too many to mention]: Move lower level functions to
jrpc.el. Hook onto jrpc's external interfaces.

* jrpc.el: New file
---
 eglot.el | 836 +--
 jrpc.el  | 502 ++
 2 files changed, 727 insertions(+), 611 deletions(-)

diff --git a/eglot.el b/eglot.el
index 4cb3bec..934270c 100644
--- a/eglot.el
+++ b/eglot.el
@@ -40,6 +40,7 @@
 (require 'flymake)
 (require 'xref)
 (require 'subr-x)
+(require 'jrpc)
 
 
 ;;; User tweakable stuff
@@ -58,12 +59,8 @@
   '((t (:inherit font-lock-constant-face :weight bold)))
   "Face for package-name in EGLOT's mode line.")
 
-(defcustom eglot-request-timeout 10
-  "How many seconds to wait for a reply from the server."
-  :type :integer)
-
 (defcustom eglot-autoreconnect 3
-  "Control EGLOT's ability to reconnect automatically.
+  "Control ability to reconnect automatically to the LSP server.
 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
@@ -77,114 +74,63 @@ lasted more than that many seconds."
 (defvar eglot--processes-by-project (make-hash-table :test #'equal)
   "Keys are projects.  Values are lists of processes.")
 
-(defun eglot--current-process ()
-  "The current logical EGLOT process."
-  (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."
-  (or (eglot--current-process)
-  (eglot--error "No current EGLOT process%s"
-(if (project-current) "" " (Also no current project)"
-
-(defmacro eglot--define-process-var
-(var-sym initval &optional doc)
-  "Define VAR-SYM as a generalized process-local variable.
-INITVAL is the default value.  DOC is the documentation."
-  (declare (indent 2))
-  `(progn
- (put ',var-sym 'function-documentation ,doc)
- (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 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")
-
-(eglot--define-process-var eglot--major-mode nil
+(jrpc-define-process-var eglot--major-mode nil
   "The major-mode this server is managing.")
 
-(eglot--define-process-var eglot--expected-bytes nil
-  "How many bytes declared by server")
-
-(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
-  "A buffer pretty-printing the EGLOT RPC events")
-
-(eglot--define-process-var eglot--capabilities :unreported
+(jrpc-define-process-var eglot--capabilities :unreported
   "Holds list of capabilities that server reported")
 
-(eglot--define-process-var eglot--moribund nil
-  "Non-nil if server is about to exit")
-
-(eglot--define-process-var eglot--project nil
+(jrpc-define-process-var eglot--project nil
   "The project the server belongs to.")
 
-(eglot--define-process-var eglot--spinner `(nil nil t)
+(jrpc-define-process-var eglot--spinner `(nil nil t)
   "\"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).")
+(jrpc-define-process-var eglot--moribund nil
+  "Non-nil if server is about to exit")
 
-(eglot--define-process-var eglot--inhibit-autoreconnect eglot-autoreconnect
+(jrpc-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
-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.
-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/%s)" name 
managed-major-mode))
- (buffer (ge

[elpa] externals/eglot 6f1ecc6 28/69: Merge branch use-eieio-server-defclass into jsonrpc-refactor

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 6f1ecc6521cc70015252749228e81d58163ed5f9
Merge: 0e44b27 89baadf
Author: João Távora 
Commit: João Távora 

Merge branch use-eieio-server-defclass into jsonrpc-refactor
---
 eglot-tests.el   |  55 +++--
 eglot.el | 600 ++-
 jsonrpc-tests.el |   6 +-
 jsonrpc.el   | 257 +---
 4 files changed, 502 insertions(+), 416 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index a19f121..8afbfa5 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -51,22 +51,24 @@
 
 (defun eglot--call-with-dirs-and-files (dirs fn)
   (let* ((default-directory (make-temp-file "eglot--fixture" t))
- new-buffers new-processes)
+ new-buffers new-servers)
 (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
+   (lambda (server) (push server new-servers
   (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)
+  (mapcar #'jsonrpc-name new-servers))
   (let ((eglot-autoreconnect nil))
 (mapc #'eglot-shutdown
-  (cl-remove-if-not #'process-live-p new-processes)))
+  (cl-remove-if-not
+   (lambda (server) (process-live-p (jsonrpc--process server)))
+   new-servers)))
   (dolist (buf new-buffers) ;; have to save otherwise will get prompted
 (with-current-buffer buf (save-buffer) (kill-buffer)))
   (delete-directory default-directory 'recursive
@@ -78,8 +80,7 @@
 (defun eglot--call-with-test-timeout (timeout fn)
   (let* ((tag (make-symbol "tag"))
  (timed-out (make-symbol "timeout"))
- (timer )
- (jsonrpc-request-timeout 1)
+ (timer)
  (retval))
 (unwind-protect
 (setq retval
@@ -112,7 +113,7 @@
 (ert-deftest auto-detect-running-server ()
   "Visit a file and M-x eglot, then visit a neighbour. "
   (skip-unless (executable-find "rls"))
-  (let (proc)
+  (let (server)
 (eglot--with-dirs-and-files
 '(("project" . (("coiso.rs" . "bla")
 ("merdix.rs" . "bla")))
@@ -120,42 +121,40 @@
   (eglot--with-test-timeout 2
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
-  (setq proc
-(eglot 'rust-mode `(transient . ,default-directory)
-   '("rls")))
-  (should (jsonrpc-current-process)))
+  (should (setq server (apply #'eglot (eglot--interactive
+  (should (jsonrpc-current-connection)))
 (with-current-buffer
 (eglot--find-file-noselect "project/merdix.rs")
-  (should (jsonrpc-current-process))
-  (should (eq (jsonrpc-current-process) proc)))
+  (should (jsonrpc-current-connection))
+  (should (eq (jsonrpc-current-connection) server)))
 (with-current-buffer
 (eglot--find-file-noselect "anotherproject/cena.rs")
-  (should-error (jsonrpc-current-process-or-lose)))
+  (should-error (jsonrpc-current-connection-or-lose)))
 
 (ert-deftest auto-reconnect ()
   "Start a server. Kill it. Watch it reconnect."
   (skip-unless (executable-find "rls"))
-  (let (proc
-(eglot-autoreconnect 1))
+  (let (server (eglot-autoreconnect 1))
 (eglot--with-dirs-and-files
 '(("project" . (("coiso.rs" . "bla")
 ("merdix.rs" . "bla"
   (eglot--with-test-timeout 3
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
-  (setq proc
-(eglot 'rust-mode `(transient . ,default-directory)
-   '("rls")))
+  (should (setq server (apply #'eglot (eglot--interactive
   ;; In 1.2 seconds > `eglot-autoreconnect' kill servers. We
   ;; should have a automatic reconnection.
-  (run-with-timer 1.2 nil (lambda () (delete-process proc)))
-  (while (process-live-p proc) (accept-process-output nil 0.5))
-  (should (jsonrpc-current-process))
+  (run-with-timer 1.2 nil (lambda () (delete-process
+  (jsonrpc--process server
+  (while (process-live-p (jsonrpc--process server))
+(accept-process-output nil 0.5))
+  (should (jsonrpc-current-connection))
   ;; Now try again too quickly
-  (setq proc (jsonrpc-current-process))
-  (run-with-timer 0.5 nil (lambda () (delete-process proc)))
-  (while (process-live-p proc) (accept-process-o

[elpa] externals/eglot 1ec47fb 51/69: Remove connection grabbing antics from jsonrpc.el

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 1ec47fb58d82362161a3f1bcdbb182e6403c987a
Author: João Távora 
Commit: João Távora 

Remove connection grabbing antics from jsonrpc.el

* eglot.el (eglot--managed-mode): Don't touch
jsonrpc-find-connection-functions.
(eglot--current-server-or-lose, eglot--current-server): New
functions (resuscitate).
(eglot-shutdown, eglot, eglot-reconnect)
(eglot--server-capable, eglot--maybe-activate-editing-mode)
(eglot-clear-status, eglot--mode-line-format)
(eglot--signal-textDocument/didChange)
(eglot--signal-textDocument/didOpen)
(eglot--signal-textDocument/didSave)
(xref-backend-identifier-completion-table)
(xref-backend-definitions, xref-backend-references)
(xref-backend-apropos, eglot-completion-at-point)
(eglot-help-at-point, eglot-eldoc-function, eglot-imenu)
(eglot-rename, eglot-code-actions): Use eglot--current-server and
eglot--current-server-or-lose.
(eglot-events-buffer, eglot-stderr-buffer)
(eglot-forget-pending-continuations): New commands.
(eglot--mode-line-format): Use eglot-stderr-buffer.

* jsonrpc.el (jsonrpc-find-connection-functions)
(jsonrpc-current-connection, jsonrpc-current-connection-or-lose):
Remove.
(jsonrpc-stderr-buffer, jsonrpc-events-buffer): Simplify.
(jsonrpc-forget-pending-continuations): No longer interactive.

* eglot-tests.el (auto-detect-running-server, auto-reconnect): Use
eglot--current-server.
---
 eglot-tests.el | 14 ++--
 eglot.el   | 72 +++---
 jsonrpc.el | 26 -
 3 files changed, 55 insertions(+), 57 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index d085532..40970a7 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -193,14 +193,14 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (with-current-buffer
 (eglot--find-file-noselect "project/coiso.rs")
   (should (setq server (apply #'eglot (eglot--interactive
-  (should (jsonrpc-current-connection)))
+  (should (eglot--current-server)))
 (with-current-buffer
 (eglot--find-file-noselect "project/merdix.rs")
-  (should (jsonrpc-current-connection))
-  (should (eq (jsonrpc-current-connection) server)))
+  (should (eglot--current-server))
+  (should (eq (eglot--current-server) server)))
 (with-current-buffer
 (eglot--find-file-noselect "anotherproject/cena.rs")
-  (should-error (jsonrpc-current-connection-or-lose)))
+  (should-error (eglot--current-server-or-lose)))
 
 (ert-deftest auto-reconnect ()
   "Start a server. Kill it. Watch it reconnect."
@@ -218,13 +218,13 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (run-with-timer 1.2 nil (lambda () (delete-process
   (jsonrpc--process server
   (while (jsonrpc-running-p server) (accept-process-output nil 0.5))
-  (should (jsonrpc-current-connection))
+  (should (eglot--current-server))
   ;; Now try again too quickly
-  (setq server (jsonrpc-current-connection))
+  (setq server (eglot--current-server))
   (let ((proc (jsonrpc--process server)))
 (run-with-timer 0.5 nil (lambda () (delete-process proc)))
 (while (process-live-p proc) (accept-process-output nil 0.5)))
-  (should (not (jsonrpc-current-connection
+  (should (not (eglot--current-server
 
 (ert-deftest rls-watches-files ()
   "Start RLS server.  Notify it when a critical file changes."
diff --git a/eglot.el b/eglot.el
index f8bd32c..32879ec 100644
--- a/eglot.el
+++ b/eglot.el
@@ -207,7 +207,7 @@ lasted more than that many seconds."
   "Politely ask SERVER to quit.
 Forcefully quit it if it doesn't respond.  Don't leave this
 function with the server still running."
-  (interactive (list (jsonrpc-current-connection-or-lose) t))
+  (interactive (list (eglot--current-server-or-lose) t))
   (eglot--message "Asking %s politely to terminate" (jsonrpc-name server))
   (unwind-protect
   (progn
@@ -330,7 +330,7 @@ INTERACTIVE is t if called interactively."
   (interactive (eglot--interactive))
   (let* ((nickname (file-name-base (directory-file-name
 (car (project-roots project)
- (current-server (jsonrpc-current-connection))
+ (current-server (eglot--current-server))
  (live-p (and current-server (jsonrpc-running-p current-server
 (if (and live-p
  interactive
@@ -352,7 +352,7 @@ managing `%s' buffers in project `%s'."
 (defun eglot-reconnect (server &optional interactive)
   "Reconnect to SERVER.
 INTERACTIVE is t if called interactively."
-  (interactive (list (jsonrpc-current-connection-or-lose) t))
+  (interactive (list (eglot--current-server-or-lose) t))
   (when (jsonrpc-running-p se

[elpa] externals/eglot e5120aa 08/69: Add jrpc.el to Makefile

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit e5120aa0cc77b2e31b2c301498d2740ffe794be1
Author: João Távora 
Commit: João Távora 

Add jrpc.el to Makefile

* Makefile (ELFILES): jrpc.el needs to be here, too.
---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 7b85351..2360136 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ EMACS=emacs
 
 LOAD_PATH=-L .
 
-ELFILES := eglot.el eglot-tests.el
+ELFILES := eglot.el jrpc.el eglot-tests.el
 ELCFILES := $(ELFILES:.el=.elc)
 
 all: compile



[elpa] externals/eglot 258e3b0 07/69: Merge master into jsonrpc-refactor (using imerge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 258e3b068c9715aa20eb7d5ec714069fd70eee87
Merge: 5cda0ec 1f8c238
Author: João Távora 
Commit: João Távora 

Merge master into jsonrpc-refactor (using imerge)
---
 README.md  |  38 +
 eglot-tests.el |   2 +-
 eglot.el   | 131 +++--
 jrpc.el|  16 +++
 4 files changed, 120 insertions(+), 67 deletions(-)

diff --git a/README.md b/README.md
index 7550a30..b87666c 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,10 @@ Eglot
 
 *E*macs Poly*glot*. An Emacs client to [Language Server Protocol][lsp] servers.
 
-```
-(add-to-list 'load-path "/path/to/eglot")
-(require 'eglot) ; Requires emacs 26!
+Eglot is [in ELPA][gnuelpa]. Installation is straightforward:
 
+```
+(package-install 'eglot) ; Requires Emacs 26!
 ;; Now find some source file, any source file
 M-x eglot
 ```
@@ -15,14 +15,15 @@ M-x eglot
 *That's it*. If you're lucky, this guesses the LSP executable to start
 for the language of your choice. Otherwise, it prompts you to enter one:
 
-`M-x eglot` currently guesses and works out-of-the-box with:
+`M-x eglot` can guess and work out-of-the-box with these servers:
 
 * Javascript's [javascript-typescript-stdio][javascript-typescript-langserver]
 * Rust's [rls][rls]
 * Python's [pyls][pyls]
 * Bash's [bash-language-server][bash-language-server]
+* PHP's [php-language-server][php-language-server]
 
-I'll add more as I test more features. In the meantime you can
+I'll add to this list as I test more servers. In the meantime you can
 customize `eglot-server-programs`:
 
 ```lisp
@@ -41,7 +42,9 @@ 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-shutdown` says bye-bye 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
@@ -60,6 +63,23 @@ either:
 (define-key eglot-mode-map (kbd "") 'xref-find-definitions)
 ```
 
+# How does this work exactly?
+
+`M-x eglot` starts a server via a shell-command guessed from
+`eglot-server-programs`, using the current major-mode (for whatever
+language you're programming in) as a hint.
+
+If the connection is successful, you see an `[eglot:]`
+indicator pop up in your mode-line.  More importantly, this means
+current *and future* file buffers of that major mode *inside your
+current project* automatically become \"managed\" by the LSP server,
+i.e.  information about their contents is exchanged periodically to
+provide enhanced code analysis via `xref-find-definitions`,
+`flymake-mode`, `eldoc-mode`, `completion-at-point`, among others.
+
+To "unmanage" these buffers, shutdown the server with `M-x
+eglot-shutdown`.
+
 # Supported Protocol features (3.6)
 
 ## General
@@ -104,7 +124,7 @@ either:
 - [x] textDocument/completion
 - [x] completionItem/resolve (works quite well with 
[company-mode][company-mode])
 - [x] textDocument/hover
-- [x] textDocument/signatureHelp (fancy stuff with Python's [pyls[pyls]])
+- [x] textDocument/signatureHelp (fancy stuff with Python's [pyls][pyls])
 - [x] textDocument/definition
 - [ ] textDocument/typeDefinition (3.6.0)
 - [ ] textDocument/implementation (3.6.0)
@@ -152,7 +172,7 @@ User-visible differences:

 Under the hood:
 
-- Message parser is much much simpler.
+- Message parser is much simpler.
 - Defers signature requests like `textDocument/hover` until server is
   ready. Also sends `textDocument/didChange` for groups of edits, not
   one per each tiny change.
@@ -169,10 +189,12 @@ Under the hood:
 [lsp]: https://microsoft.github.io/language-server-protocol/
 [rls]: https://github.com/rust-lang-nursery/rls
 [pyls]: https://github.com/palantir/python-language-server
+[gnuelpa]: https://elpa.gnu.org/packages/eglot.html
 [javascript-typescript-langserver]: 
https://github.com/sourcegraph/javascript-typescript-langserver
 [emacs-lsp]: https://github.com/emacs-lsp/lsp-mode
 [emacs-lsp-plugins]: https://github.com/emacs-lsp
 [bash-language-server]: https://github.com/mads-hartmann/bash-language-server
+[php-language-server]: https://github.com/felixfbecker/php-language-server
 [company-mode]: https://github.com/company-mode/company-mode
 

diff --git a/eglot-tests.el b/eglot-tests.el
index e0ed324..7a832dd 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
diff --git a/eglot.el b/eglot.el
index 11d048e..13c1b49 100644
--- a/eglot.el
+++ b/eglot.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2018 Free Software Foundation, Inc.
 
-;; Version: 0.1
+;; Version: 0.2
 ;; Author: João Távora 
 ;;

[elpa] externals/eglot 07359a2 15/69: Allow null timeouts and set default to 3 seconds

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 07359a2635ca2cd04e693bb8598e65a85e1d960c
Author: João Távora 
Commit: João Távora 

Allow null timeouts and set default to 3 seconds

* jrpc.el (jrpc-request-timeout): Allow nil.
(jrpc--process-sentinel): Handle no timeout.
(jrpc--async-request): Maybe make no timer.
---
 jrpc.el | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/jrpc.el b/jrpc.el
index eff941a..7303414 100644
--- a/jrpc.el
+++ b/jrpc.el
@@ -125,8 +125,9 @@
   :prefix "jrpc-"
   :group 'applications)
 
-(defcustom jrpc-request-timeout 10
-  "How many seconds to wait for a reply from the server."
+(defcustom jrpc-request-timeout 3
+  "How many seconds to wait for a JSONRPC from the server.
+If nil, don't use a timeout (not recommended)."
   :type :integer)
 
 (defvar jrpc-find-process-functions nil
@@ -297,7 +298,7 @@ type.
 ;; Cancel outstanding timers
 (maphash (lambda (_id triplet)
(pcase-let ((`(,_success ,_error ,timeout) triplet))
- (cancel-timer timeout)))
+ (when timeout (cancel-timer timeout
  (jrpc--request-continuations proc))
 (unwind-protect
 ;; Call all outstanding error handlers
@@ -529,15 +530,16 @@ Return the request ID, or nil, in case the request was 
deferred."
  (make-timeout
   (lambda ( )
 (or existing-timer
-(run-with-timer
- timeout nil
- (lambda ()
-   (remhash id (jrpc--request-continuations proc))
-   (funcall (or timeout-fn
-(lambda ()
-  (jrpc-log-event
-   proc `(:timed-out ,method :id id
- :params ,params)))
+(when timeout
+  (run-with-timer
+   timeout nil
+   (lambda ()
+ (remhash id (jrpc--request-continuations proc))
+ (funcall (or timeout-fn
+  (lambda ()
+(jrpc-log-event
+ proc `(:timed-out ,method :id id
+   :params 
,params
 (when deferred
   (let* ((buf (current-buffer))
  (existing (gethash (list deferred buf) (jrpc--deferred-actions 
proc



[elpa] externals/eglot 7f2e894 11/69: Merge branch 'master' into jsonrpc-refactor (using good ol' git merge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 7f2e894229fba7f829874de6c46ebe472f03b19d
Merge: 3265c1d 8e5acb1
Author: João Távora 
Commit: João Távora 

Merge branch 'master' into jsonrpc-refactor (using good ol' git merge)
---
 eglot.el | 53 +++--
 jrpc.el  |  3 ++-
 2 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/eglot.el b/eglot.el
index caf2e8c..b820dde 100644
--- a/eglot.el
+++ b/eglot.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2018 Free Software Foundation, Inc.
 
-;; Version: 0.2
+;; Version: 0.3
 ;; Author: João Távora 
 ;; Maintainer: João Távora 
 ;; URL: https://github.com/joaotavora/eglot
@@ -318,7 +318,7 @@ INTERACTIVE is t if called interactively."
   "Dispatcher passed to `jrpc-connect'.
 Builds a function from METHOD, passes it PROC, ID and PARAMS."
   (let* ((handler-sym (intern (concat "eglot--server-" method
-(if (functionp handler-sym)
+(if (functionp handler-sym) ;; FIXME: fails if params is array, not object
 (apply handler-sym proc (append params (if id `(:id ,id
   (jrpc-reply proc id
   :error (jrpc-obj :code -32601 :message "Unimplemented")
@@ -371,11 +371,11 @@ Builds a function from METHOD, passes it PROC, ID and 
PARAMS."
 ;;;
 (defun eglot--error (format &rest args)
   "Error out with FORMAT with ARGS."
-  (error (apply #'format format args)))
+  (error "[eglot] %s" (apply #'format format args)))
 
 (defun eglot--message (format &rest args)
   "Message out with FORMAT with ARGS."
-  (message (concat "[eglot] " (apply #'format format args
+  (message "[eglot] %s" (apply #'format format args)))
 
 (defun eglot--warn (format &rest args)
   "Warning message with FORMAT and ARGS."
@@ -406,14 +406,16 @@ Builds a function from METHOD, passes it PROC, ID and 
PARAMS."
   (point)))
 
 (defun eglot--path-to-uri (path)
-  "Urify PATH."
-  (url-hexify-string (concat "file://" (file-truename path))
- url-path-allowed-chars))
+  "URIfy PATH."
+  (url-hexify-string
+   (concat "file://" (if (eq system-type 'windows-nt) "/") (file-truename 
path))
+   url-path-allowed-chars))
 
 (defun eglot--uri-to-path (uri)
   "Convert URI to a file path."
   (when (keywordp uri) (setq uri (substring (symbol-name uri) 1)))
-  (url-filename (url-generic-parse-url (url-unhex-string uri
+  (let ((retval (url-filename (url-generic-parse-url (url-unhex-string uri)
+(if (eq system-type 'windows-nt) (substring retval 1) retval)))
 
 (defconst eglot--kind-names
   `((1 . "Text") (2 . "Method") (3 . "Function") (4 . "Constructor")
@@ -443,14 +445,10 @@ Builds a function from METHOD, passes it PROC, ID and 
PARAMS."
   "Determine if current server is capable of FEAT."
   (plist-get (eglot--capabilities (jrpc-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))
+(defun eglot--range-region (range)
+  "Return region (BEG . END) that represents LSP RANGE."
+  (cons (eglot--lsp-position-to-point (plist-get range :start))
+(eglot--lsp-position-to-point (plist-get range :end
 
 
 ;;; Minor modes
@@ -627,18 +625,14 @@ Uses THING, FACE, DEFS and PREPEND."
 (cl-defun eglot--server-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)))
-(cond
- (buffer
+  (if-let ((buffer (find-buffer-visiting (eglot--uri-to-path uri
   (with-current-buffer buffer
 (cl-loop
  for diag-spec across diagnostics
  collect (cl-destructuring-bind (&key range severity _group
   _code source message)
  diag-spec
-   (eglot--with-lsp-range (beg end) range
+   (pcase-let ((`(,beg . ,end) (eglot--range-region range)))
  (flymake-make-diagnostic (current-buffer)
   beg end
   (cond ((<= severity 1) :error)
@@ -650,9 +644,8 @@ Uses THING, FACE, DEFS and PREPEND."
 (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)
+(setq eglot--unreported-diagnostics

[elpa] externals/eglot 980f3e7 34/69: Fix another merge-related bug in eglot-eldoc-function

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 980f3e7feb717a66120950175cfd5cdf507a1462
Author: João Távora 
Commit: João Távora 

Fix another merge-related bug in eglot-eldoc-function

* eglot.el (eglot-eldoc-function): Correctly destructure
eglot--range-region.
---
 eglot.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eglot.el b/eglot.el
index 64d06a3..3f82c89 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1138,7 +1138,7 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
  (when-buffer-window
   (mapcar
(jsonrpc-lambda (&key range _kind _role)
- (pcase-let ((`(,beg ,end)
+ (pcase-let ((`(,beg . ,end)
   (eglot--range-region range)))
(let ((ov (make-overlay beg end)))
  (overlay-put ov 'face 'highlight)



[elpa] externals/eglot 9e9dc57 30/69: Merge branch 'master' into jsonrpc-refactor (using regular merge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 9e9dc573b6ed17f4c0fe00d7d4888e81b79108b8
Merge: 05ff697 0462130
Author: João Távora 
Commit: João Távora 

Merge branch 'master' into jsonrpc-refactor (using regular merge)

This increases the test coverage in the jsonrpc-branch
---
 .travis.yml|   2 +-
 eglot-tests.el | 206 +++--
 2 files changed, 186 insertions(+), 22 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 9b0a6d8..60a97fc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@ rust:
 
 env:
   global:
-- EGLOT_TESTING=t # For kicks, so I don't forget this syntax
+- TRAVIS_TESTING=t
   matrix:
 - EMACS_VERSION=26-prerelease
 
diff --git a/eglot-tests.el b/eglot-tests.el
index 777d2da..bdb8b21 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -64,22 +64,28 @@
   (mapconcat #'buffer-name new-buffers ", ")
   default-directory
   (mapcar #'jsonrpc-name new-servers))
-  (let ((eglot-autoreconnect nil))
-(mapc #'eglot-shutdown
-  (cl-remove-if-not
-   (lambda (server) (process-live-p (eglot--process server)))
-   new-servers)))
-  (dolist (buf new-buffers) ;; have to save otherwise will get prompted
-(with-current-buffer buf (save-buffer) (kill-buffer)))
-  (delete-directory default-directory 'recursive
-
-(cl-defmacro eglot--with-test-timeout (timeout &body body)
+  (unwind-protect
+  (let ((eglot-autoreconnect nil))
+(mapc #'eglot-shutdown
+  (cl-remove-if-not (lambda (server) (process-live-p 
(eglot--process server)))
+new-servers)))
+(mapc #'kill-buffer (mapcar #'jsonrpc--events-buffer new-servers))
+(dolist (buf new-buffers) ;; have to save otherwise will get prompted
+  (with-current-buffer buf (save-buffer) (kill-buffer)))
+(delete-directory default-directory 'recursive)
+
+(cl-defmacro eglot--with-timeout (timeout &body body)
   (declare (indent 1) (debug t))
-  `(eglot--call-with-test-timeout ,timeout (lambda () ,@body)))
+  `(eglot--call-with-timeout ',timeout (lambda () ,@body)))
 
-(defun eglot--call-with-test-timeout (timeout fn)
-  (let* ((tag (make-symbol "tag"))
+(defun eglot--call-with-timeout (timeout fn)
+  (let* ((tag (gensym "eglot-test-timeout"))
  (timed-out (make-symbol "timeout"))
+ (timeout-and-message
+  (if (listp timeout) timeout
+(list timeout "waiting for test to finish")))
+ (timeout (car timeout-and-message))
+ (message (cadr timeout-and-message))
  (timer)
  (retval))
 (unwind-protect
@@ -93,13 +99,81 @@
 (funcall fn)))
   (cancel-timer timer)
   (when (eq retval timed-out)
-(error "Test timeout!")
+(error "%s" (concat "Timed out " message))
 
 (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))
 
+(cl-defmacro eglot--sniffing ((&key server-requests
+server-notifications
+server-replies
+client-requests
+client-notifications
+client-replies)
+  &rest body)
+  "Run BODY saving LSP JSON messages in variables, most recent first."
+  (declare (indent 1) (debug (sexp &rest form)))
+  (let ((log-event-ad-sym (make-symbol "eglot--event-sniff")))
+`(unwind-protect
+ (let ,(delq nil (list server-requests
+   server-notifications
+   server-replies
+   client-requests
+   client-notifications
+   client-replies))
+   (advice-add
+#'jsonrpc-log-event :before
+(lambda (_proc message &optional type)
+  (cl-destructuring-bind (&key method id _error &allow-other-keys)
+  message
+(let ((req-p (and method id))
+  (notif-p method)
+  (reply-p id))
+  (cond
+   ((eq type 'server)
+(cond (req-p ,(when server-requests
+`(push message ,server-requests)))
+  (notif-p ,(when server-notifications
+  `(push message ,server-notifications)))
+  (reply-p ,(when server-replies
+  `(push message ,server-replies)
+   ((eq type 'client)
+(cond (req-p ,(when client-requests
+`(push message ,cl

[elpa] externals/eglot 47b957d 65/69: Let's not send Content-type for now.

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 47b957dadd06c0dd3c692079def786e65bc2d452
Author: João Távora 
Commit: João Távora 

Let's not send Content-type for now.

The LSP servers Eglot works with hate it

* jsonrpc.el (jsonrpc-connection-send): Don't send Content-type.
---
 jsonrpc.el | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 0205015..caf46af 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -439,7 +439,8 @@ connection object, called when the process dies .")
   (json (jsonrpc--json-encode message))
   (headers
`(("Content-Length" . ,(format "%d" (string-bytes json)))
- ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8"
+ ;; ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8")
+ )))
 (process-send-string
  (jsonrpc--process connection)
  (cl-loop for (header . value) in headers



[elpa] externals/eglot c790274 39/69: jsonrpc--next-request-id is a connection slot

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit c790274a8a9f20a1716e6980265fe6b19bba64db
Author: João Távora 
Commit: João Távora 

jsonrpc--next-request-id is a connection slot

* jsonrpc.el (jsonrpc-connection): Make jsonrpc--next-request-id a
slot.
(jsonrpc--next-request-id): Remove this variable.
(jsonrpc--async-request-1): Use slot.
---
 jsonrpc.el | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index beb3d01..a8c86d0 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -133,7 +133,7 @@
 (require 'subr-x)
 (require 'warnings)
 (require 'pcase)
-(require 'ert)
+(require 'ert) ; to escape a `condition-case-unless-debug'
 (require 'array) ; xor
 
 (defvar jsonrpc-find-connection-functions nil
@@ -206,7 +206,11 @@ FORMAT as the message."
 :accessor jsonrpc--deferred-actions
 :documentation "Map (DEFERRED BUF) to (FN TIMER ID).  FN is\
 a saved DEFERRED `async-request' from BUF, to be sent not later\
-than TIMER as ID.")))
+than TIMER as ID.")
+   (-next-request-id
+:initform 0
+:accessor jsonrpc--next-request-id
+:documentation "Next number used for a request")))
 
 (defclass jsonrpc-process-connection (jsonrpc-connection)
   ((-process
@@ -544,9 +548,6 @@ for sending requests immediately."
 (defconst jrpc-default-request-timeout 10
   "Time in seconds before timing out a JSONRPC request.")
 
-(defvar-local jsonrpc--next-request-id 0)
-
-
 (cl-defun jsonrpc-async-request (connection
  method
  params
@@ -593,7 +594,7 @@ TIMEOUT is nil)."
(`(,_ ,timer ,old-id)
 (and deferred (gethash (list deferred buf)
(jsonrpc--deferred-actions 
connection
-   (id (or old-id (cl-incf jsonrpc--next-request-id)))
+   (id (or old-id (cl-incf (jsonrpc--next-request-id connection
(make-timer
 (lambda ( )
   (when timeout



[elpa] externals/eglot 870c60a 04/69: Merge master into jsonrpc-refactor (using imerge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 870c60a581f07a2d25f8fde369e1f2d1c81d21d3
Merge: 2f1d76d 4c0bfc3
Author: João Távora 
Commit: João Távora 

Merge master into jsonrpc-refactor (using imerge)
---
 .travis.yml|   9 +-
 README.md  |  28 +++---
 eglot-tests.el | 129 +
 eglot.el   | 301 +++--
 jrpc.el|  10 +-
 5 files changed, 344 insertions(+), 133 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 4dfe0a6..7550a30 100644
--- a/README.md
+++ b/README.md
@@ -8,12 +8,12 @@ Eglot
 (add-to-list 'load-path "/path/to/eglot")
 (require 'eglot) ; Requires emacs 26!
 
-;; Now find some project file inside some Git-controlled dir
+;; Now find some source file, any source file
 M-x eglot
 ```
 
 *That's it*. If you're lucky, this guesses the LSP executable to start
-for the language of your choice, or it prompts you to enter one:
+for the language of your choice. Otherwise, it prompts you to enter one:
 
 `M-x eglot` currently guesses and works out-of-the-box with:
 
@@ -29,9 +29,9 @@ customize `eglot-server-programs`:
 (add-to-list 'eglot-server-programs '(fancy-mode . ("fancy-language-server" 
"--args"")))
 ```
 
-Let me know how well it works and I'll add it to the list, or submit a
-PR.  You can also enter a `server:port` pattern to connect to an LSP
-server. To skip the guess and always be prompted use `C-u M-x eglot`.
+Let me know how well it works and we can add it to the list.  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
 
@@ -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
@@ -76,23 +76,24 @@ 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/symbol
+- [x] workspace/didChangeWatchedFiles
+- [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
 
@@ -103,7 +104,7 @@ either:
 - [x] textDocument/completion
 - [x] completionItem/resolve (works quite well with 
[company-mode][company-mode])
 - [x] textDocument/hover
-- [ ] textDocument/signatureHelp
+- [x] textDocument/signatureHelp (fancy stuff with Python's [pyls[pyls]])
 - [x] textDocument/definition
 - [ ] textDocument/typeDefinition (3.6.0)
 - [ ] textDocument/implementation (3.6.0)
@@ -162,7 +163,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..e0ed324 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -24,9 +24,138 @@
 
 ;;; 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

[elpa] externals/eglot 7f4e273 31/69: Merge master into jsonrpc-refactor (using imerge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 7f4e27352c37dd2cbfb25d22caab6f4b57f91964
Merge: 9e9dc57 4211e0c
Author: João Távora 
Commit: João Távora 

Merge master into jsonrpc-refactor (using imerge)
---
 README.md  |   7 +
 eglot-tests.el |  48 +--
 eglot.el   | 423 +
 jsonrpc.el | 122 +
 4 files changed, 327 insertions(+), 273 deletions(-)

diff --git a/README.md b/README.md
index b87666c..c88f804 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,8 @@ for the language of your choice. Otherwise, it prompts you to 
enter one:
 * Python's [pyls][pyls]
 * Bash's [bash-language-server][bash-language-server]
 * PHP's [php-language-server][php-language-server]
+* [cquery][cquery] for C/C++
+
 
 I'll add to this list as I test more servers. In the meantime you can
 customize `eglot-server-programs`:
@@ -53,6 +55,9 @@ Here's a summary of available commands:
 - `M-x eglot-events-buffer` jumps to the events buffer for debugging
   communication with the server.
 
+- `M-x eglot-stderr-buffer` if the LSP server is printing useful debug
+information in stderr, jumps to a buffer with these contents.
+
 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,
@@ -196,5 +201,7 @@ Under the hood:
 [bash-language-server]: https://github.com/mads-hartmann/bash-language-server
 [php-language-server]: https://github.com/felixfbecker/php-language-server
 [company-mode]: https://github.com/company-mode/company-mode
+[cquery]: https://github.com/cquery-project/cquery
+
 

diff --git a/eglot-tests.el b/eglot-tests.el
index bdb8b21..c9cc3fd 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -234,11 +234,11 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (skip-unless (null (getenv "TRAVIS_TESTING")))
   (let ((eglot-autoreconnect 1))
 (eglot--with-dirs-and-files
-'(("project" . (("coiso.rs" . "bla")
-("merdix.rs" . "bla"
+'(("watch-project" . (("coiso.rs" . "bla")
+  ("merdix.rs" . "bla"
   (eglot--with-timeout 10
 (with-current-buffer
-(eglot--find-file-noselect "project/coiso.rs")
+(eglot--find-file-noselect "watch-project/coiso.rs")
   (should (zerop (shell-command "cargo init")))
   (eglot--sniffing (
 :server-requests s-requests
@@ -265,21 +265,22 @@ Pass TIMEOUT to `eglot--with-timeout'."
   (= type 3)))
 
 (ert-deftest rls-basic-diagnostics ()
-  "Hover and highlightChanges are tricky in RLS."
+  "Test basic diagnostics in RLS."
   (skip-unless (executable-find "rls"))
   (skip-unless (executable-find "cargo"))
   (eglot--with-dirs-and-files
-  '(("project" . (("main.rs" . "bla"
+  '(("diag-project" . (("main.rs" . "fn main() {\nprintfoo!(\"Hello, 
world!\");\n}"
 (eglot--with-timeout 3
   (with-current-buffer
-  (eglot--find-file-noselect "project/main.rs")
+  (eglot--find-file-noselect "diag-project/main.rs")
 (should (zerop (shell-command "cargo init")))
 (eglot--sniffing (:server-notifications s-notifs)
-  (insert "fn main() {\nprintfoo!(\"Hello, world!\");\n}")
   (apply #'eglot (eglot--interactive))
   (eglot--wait-for (s-notifs 1)
   (&key _id method &allow-other-keys)
 (string= method "textDocument/publishDiagnostics"))
+  (flymake-start)
+  (goto-char (point-min))
   (flymake-goto-next-error)
   (should (eq 'flymake-error (face-at-point
 
@@ -287,11 +288,14 @@ Pass TIMEOUT to `eglot--with-timeout'."
   "Hover and highlightChanges are tricky in RLS."
   (skip-unless (executable-find "rls"))
   (skip-unless (executable-find "cargo"))
+  (skip-unless (null (getenv "TRAVIS_TESTING")))
   (eglot--with-dirs-and-files
-  '(("project" . (("main.rs" . "bla"
+  '(("hover-project" .
+ (("main.rs" .
+   "fn test() -> i32 { let test=3; return te; }"
 (eglot--with-timeout 3
   (with-current-buffer
-  (eglot--find-file-noselect "project/main.rs")
+  (eglot--find-file-noselect "hover-project/main.rs")
 (should (zerop (shell-command "cargo init")))
 (eglot--sniffing (
   :server-notifications s-notifs
@@ -301,7 +305,6 @@ Pass TIMEOUT to `eglot--with-timeout'."
   :client-replies c-replies
   :client-requests c-reqs
   )
-  (insert "fn test() -> i32 { let test=3; return te; }")
   (apply #'eglot (eglot--interactive))
   (goto-char (point-min))
   (search-forward "return te")
@@ -320,6 +323,31 @@ Pass TIMEOUT to `eglot--with-timeout'."
 (&key id &allow-other-

[elpa] externals/eglot f385d9c 69/69: Merge branch 'jsonrpc-refactor', bump version to 1.0

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit f385d9ce50f2da7e50d58e9f46fdf291f63af57a
Merge: 0176264 0f20fdf
Author: João Távora 
Commit: João Távora 

Merge branch 'jsonrpc-refactor', bump version to 1.0

* eglot.el (Version): Bump to 1.0
---
 Makefile |   17 +-
 README.md|6 +-
 eglot-tests.el   |   32 +-
 eglot.el | 1069 +++---
 jsonrpc-tests.el |  204 +++
 jsonrpc.el   |  722 
 6 files changed, 1335 insertions(+), 715 deletions(-)

diff --git a/Makefile b/Makefile
index 7b85351..df15914 100644
--- a/Makefile
+++ b/Makefile
@@ -3,10 +3,11 @@
 # Variables
 #
 EMACS=emacs
+SELECTOR=t
 
 LOAD_PATH=-L .
 
-ELFILES := eglot.el eglot-tests.el
+ELFILES := eglot.el jsonrpc.el eglot-tests.el jsonrpc-tests.el
 ELCFILES := $(ELFILES:.el=.elc)
 
 all: compile
@@ -20,13 +21,17 @@ compile: $(ELCFILES)
 
 # Automated tests
 #
-check: compile
-
-check: SELECTOR=t
-check: compile
+eglot-check: compile 
$(EMACS) -Q --batch $(LOAD_PATH)\
-l eglot-tests  \
-   -f ert-run-tests-batch-and-exit \
+   --eval '(ert-run-tests-batch-and-exit (quote $(SELECTOR)))'
+
+jsonrpc-check: jsonrpc.elc jsonrpc-tests.elc
+   $(EMACS) -Q --batch $(LOAD_PATH)\
+   -l jsonrpc-tests\
+   --eval '(ert-run-tests-batch-and-exit (quote $(SELECTOR)))'
+
+check: eglot-check jsonrpc-check
 
 # Cleanup
 #
diff --git a/README.md b/README.md
index a56d750..d3379d9 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ Here's a summary of available commands:
 - `M-x eglot-rename` ask the server to rename the symbol at point;
 
 - `M-x eglot-format-buffer` ask the server to reformat the current
-  buffer.
+  buffer;
 
 - `M-x eglot-code-actions` asks the server for any code actions at
   point. These may tipically be simple fixes, like deleting an unused
@@ -222,9 +222,7 @@ Under the hood:
 - Doesn't *require* anything other than Emacs 26, but will
   automatically upgrade to work with stuff outside Emacs, like
   `company`, `markdown-mode`, if you happen to have these installed.
-- Contained in one file
-- Has automated tests that check against actual LSP servers
-
+- 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 f56280e..048b1d3 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -50,7 +50,8 @@
(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))
+  (let* ((fixture-directory (make-temp-file "eglot--fixture" t))
+ (default-directory fixture-directory)
  new-buffers new-servers)
 (unwind-protect
 (let ((find-file-hook
@@ -63,16 +64,15 @@
   (eglot--message "Killing buffers %s,  deleting %s, killing %s"
   (mapconcat #'buffer-name new-buffers ", ")
   default-directory
-  (mapcar #'eglot--name new-servers))
+  (mapcar #'jsonrpc-name new-servers))
   (unwind-protect
   (let ((eglot-autoreconnect nil))
 (mapc #'eglot-shutdown
-  (cl-remove-if-not (lambda (server) (process-live-p 
(eglot--process server)))
-new-servers)))
-(mapc #'kill-buffer (mapcar #'eglot--events-buffer new-servers))
+  (cl-remove-if-not #'jsonrpc-running-p new-servers)))
+(mapc #'kill-buffer (mapcar #'jsonrpc--events-buffer new-servers))
 (dolist (buf new-buffers) ;; have to save otherwise will get prompted
   (with-current-buffer buf (save-buffer) (kill-buffer)))
-(delete-directory default-directory 'recursive)
+(delete-directory fixture-directory 'recursive)
 
 (cl-defmacro eglot--with-timeout (timeout &body body)
   (declare (indent 1) (debug t))
@@ -124,7 +124,7 @@
client-notifications
client-replies))
(advice-add
-#'eglot--log-event :before
+#'jsonrpc--log-event :before
 (lambda (_proc message &optional type)
   (cl-destructuring-bind (&key method id _error &allow-other-keys)
   message
@@ -148,7 +148,7 @@
   `(push message ,client-replies)
 '((name . ,log-event-ad-sym)))
,@body)
-   (advice-remove #'eglot--log-event ',log-event-ad-sym
+   (advice-remove #'jsonrpc--log-event ',log-event-ad-sym
 
 (cl-defmacro eglot--wait-for ((events-sym &optional

[elpa] externals/eglot 0f20fdf 68/69: Tiny README.md change

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 0f20fdfc30de8d8e72366eeefef270243b3ddf96
Author: João Távora 
Commit: João Távora 

Tiny README.md change
---
 README.md | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index a56d750..d3379d9 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ Here's a summary of available commands:
 - `M-x eglot-rename` ask the server to rename the symbol at point;
 
 - `M-x eglot-format-buffer` ask the server to reformat the current
-  buffer.
+  buffer;
 
 - `M-x eglot-code-actions` asks the server for any code actions at
   point. These may tipically be simple fixes, like deleting an unused
@@ -222,9 +222,7 @@ Under the hood:
 - Doesn't *require* anything other than Emacs 26, but will
   automatically upgrade to work with stuff outside Emacs, like
   `company`, `markdown-mode`, if you happen to have these installed.
-- Contained in one file
-- Has automated tests that check against actual LSP servers
-
+- 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



[elpa] externals/eglot 68c266e 45/69: Avoid more catastrophes

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 68c266e7e597c3fd91d2b32aed97cbe67aad859d
Author: João Távora 
Commit: João Távora 

Avoid more catastrophes

* eglot-tests.el (eglot--call-with-dirs-and-files): Use a
fixture-directory.
---
 eglot-tests.el | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/eglot-tests.el b/eglot-tests.el
index bd9e2f3..a78069f 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -50,7 +50,8 @@
(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))
+  (let* ((fixture-directory (make-temp-file "eglot--fixture" t))
+ (default-directory fixture-directory)
  new-buffers new-servers)
 (unwind-protect
 (let ((find-file-hook
@@ -72,7 +73,7 @@
 (mapc #'kill-buffer (mapcar #'jsonrpc--events-buffer new-servers))
 (dolist (buf new-buffers) ;; have to save otherwise will get prompted
   (with-current-buffer buf (save-buffer) (kill-buffer)))
-(delete-directory default-directory 'recursive)
+(delete-directory fixture-directory 'recursive)
 
 (cl-defmacro eglot--with-timeout (timeout &body body)
   (declare (indent 1) (debug t))



[elpa] externals/eglot d371f05 49/69: Request dispatcher's return value determines response

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit d371f058e2b0634f2593d372f45253ec9c9bf700
Author: João Távora 
Commit: João Távora 

Request dispatcher's return value determines response

No more jsonrpc-reply.

* eglot.el (eglot-handle-request window/showMessageRequest):
Simplify.
(eglot--register-unregister): Simplify.
(eglot-handle-request workspace/applyEdit): Simplify.
(eglot--apply-text-edits): Signal a jsonrpc-error.
(eglot--apply-workspace-edit): Simplify.

* jsonrpc-tests.el (jsonrpc--with-emacsrpc-fixture): Don't
jsonrpc--reply.

* jsonrpc.el (jsonrpc-error, jsonrpc-connection, jsonrpc-request):
Improve docstring.
(jsonrpc-error): Polymorphic args.
(jsonrpc--unanswered-request-id): Remove.
(jsonrpc--connection-receive): Rework and simplify.
(jsonrpc-reply): Simplify.
---
 eglot.el |  87 +--
 jsonrpc-tests.el |   5 +--
 jsonrpc.el   | 122 ++-
 3 files changed, 107 insertions(+), 107 deletions(-)

diff --git a/eglot.el b/eglot.el
index 60a0322..13413ab 100644
--- a/eglot.el
+++ b/eglot.el
@@ -707,24 +707,18 @@ Uses THING, FACE, DEFS and PREPEND."
   type message))
 
 (cl-defmethod eglot-handle-request
-  (server (_method (eql window/showMessageRequest)) &key type message actions)
+  (_server (_method (eql window/showMessageRequest)) &key type message actions)
   "Handle server request window/showMessageRequest"
-  (let (reply)
-(unwind-protect
-(setq reply
-  (completing-read
-   (concat
-(format (propertize "[eglot] Server reports (type=%s): %s"
-'face (if (<= type 1) 'error))
-type message)
-"\nChoose an option: ")
-   (or (mapcar (lambda (obj) (plist-get obj :title)) actions)
-   '("OK"))
-   nil t (plist-get (elt actions 0) :title)))
-  (if reply
-  (jsonrpc-reply server :result `(:title ,reply))
-(jsonrpc-reply server
-   :error `(:code -32800 :message "User cancelled"))
+  (or (completing-read
+   (concat
+(format (propertize "[eglot] Server reports (type=%s): %s"
+'face (if (<= type 1) 'error))
+type message)
+"\nChoose an option: ")
+   (or (mapcar (lambda (obj) (plist-get obj :title)) actions)
+   '("OK"))
+   nil t (plist-get (elt actions 0) :title))
+  (jsonrpc-error :code -32800 :message "User cancelled")))
 
 (cl-defmethod eglot-handle-notification
   (_server (_method (eql window/logMessage)) &key _type _message)
@@ -762,18 +756,13 @@ Uses THING, FACE, DEFS and PREPEND."
 (cl-defun eglot--register-unregister (server things how)
   "Helper for `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))
-server :id id registerOptions))
-  (unless (eq t (car retval))
-(cl-return-from eglot--register-unregister
-  (jsonrpc-reply
-   server
-   :error `(:code -32601 :message ,(or (cadr retval) 
"sorry")
-  (jsonrpc-reply server :result `(:message "OK")))
+  (cl-loop
+   for thing in (cl-coerce things 'list)
+   collect (cl-destructuring-bind (&key id method registerOptions) thing
+ (apply (intern (format "eglot--%s-%s" how method))
+server :id id registerOptions))
+   into results
+   finally return `(:ok ,@results)))
 
 (cl-defmethod eglot-handle-request
   (server (_method (eql client/registerCapability)) &key registrations)
@@ -787,14 +776,9 @@ THINGS are either registrations or unregisterations."
   (eglot--register-unregister server unregisterations 'unregister))
 
 (cl-defmethod eglot-handle-request
-  (server (_method (eql workspace/applyEdit)) &key _label edit)
+  (_server (_method (eql workspace/applyEdit)) &key _label edit)
   "Handle server request workspace/applyEdit"
-  (condition-case err
-  (progn (eglot--apply-workspace-edit edit 'confirm)
- (jsonrpc-reply server :result `(:applied )))
-(error (jsonrpc-reply server
-  :result `(:applied :json-false)
-  :error `(:code -32001 :message (format "%s" 
,err))
+  (eglot--apply-workspace-edit edit 'confirm))
 
 (defun eglot--TextDocumentIdentifier ()
   "Compute TextDocumentIdentifier object for current buffer."
@@ -1206,8 +1190,8 @@ If SKIP-SIGNATURE, don't try to send 
textDocument/signatureHelp."
 (defun eglot--apply-text-edits (edits &optional version)
   "Apply EDITS for current buffer if at VERSION, or if it's nil.

[elpa] externals/eglot a4441c6 37/69: Merge master into jsonrpc-refactor (using imerge)

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit a4441c656df1206b60a7df1f57b5ea4db9efc828
Merge: f594dd7 327119e
Author: João Távora 
Commit: João Távora 

Merge master into jsonrpc-refactor (using imerge)
---
 README.md   |  46 +--
 eglot-tests.el  |   2 +-
 eglot.el| 194 +---
 gif-examples/eglot-code-actions.gif | Bin 0 -> 24977 bytes
 gif-examples/eglot-completions.gif  | Bin 0 -> 63910 bytes
 gif-examples/eglot-diagnostics.gif  | Bin 0 -> 30912 bytes
 gif-examples/eglot-hover-on-symbol.gif  | Bin 0 -> 26701 bytes
 gif-examples/eglot-rename.gif   | Bin 0 -> 17781 bytes
 gif-examples/eglot-xref-find-definition.gif | Bin 0 -> 31143 bytes
 gif-examples/eglot-xref-find-references.gif | Bin 0 -> 46140 bytes
 10 files changed, 186 insertions(+), 56 deletions(-)

diff --git a/README.md b/README.md
index c88f804..2ced833 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,17 @@
 [![Build 
Status](https://travis-ci.org/joaotavora/eglot.png)](https://travis-ci.org/joaotavora/eglot)
+[![MELPA](http://melpa.org/packages/eglot-badge.svg)](http://melpa.org/#/eglot)
+
 Eglot
 -
 
-*E*macs Poly*glot*. An Emacs client to [Language Server Protocol][lsp] servers.
+*E*macs Poly*glot*. Emacs client to [Language Server Protocol][lsp]
+servers.  Scroll down this README for some
+[pretty gifs](#animated_gifs).
+
+# Installation and usage
 
-Eglot is [in ELPA][gnuelpa]. Installation is straightforward:
+Eglot is in both [ELPA][gnuelpa] and [MELPA][melpa]. Installation is
+straightforward:
 
 ```
 (package-install 'eglot) ; Requires Emacs 26!
@@ -24,7 +31,6 @@ for the language of your choice. Otherwise, it prompts you to 
enter one:
 * PHP's [php-language-server][php-language-server]
 * [cquery][cquery] for C/C++
 
-
 I'll add to this list as I test more servers. In the meantime you can
 customize `eglot-server-programs`:
 
@@ -48,6 +54,11 @@ Here's a summary of available commands:
 
 - `M-x eglot-rename` asks the server to rename the symbol at point;
 
+- `M-x eglot-code-actions` asks the server for any code actions at
+  point. These may tipically be simple fixes, like deleting an unused
+  variable, or fixing an import. Left click on diagnostics to check if
+  there are any there;
+
 - `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;
@@ -111,7 +122,8 @@ eglot-shutdown`.
 - [ ] workspace/didChangeConfiguration
 - [ ] workspace/configuration (3.6.0)
 - [x] workspace/didChangeWatchedFiles
-- [x] workspace/symbol is
+- [x] workspace/symbol
+- [x] workspace/executeCommand
 - [x] workspace/applyEdit
 
 ## Text Synchronization
@@ -136,7 +148,7 @@ eglot-shutdown`.
 - [x] textDocument/references
 - [x] textDocument/documentHighlight
 - [x] textDocument/documentSymbol
-- [ ] textDocument/codeAction
+- [x] textDocument/codeAction
 - [ ] textDocument/codeLens
 - [ ] codeLens/resolve
 - [ ] textDocument/documentLink
@@ -148,6 +160,17 @@ eglot-shutdown`.
 - [ ] textDocument/onTypeFormatting
 - [x] textDocument/rename
 
+
+# _Obligatory animated gif section_
+
+![eglot-code-actions](./gif-examples/eglot-code-actions.gif)
+![eglot-completions](./gif-examples/eglot-completions.gif)
+![eglot-diagnostics](./gif-examples/eglot-diagnostics.gif)
+![eglot-hover-on-symbol](./gif-examples/eglot-hover-on-symbol.gif)
+![eglot-rename](./gif-examples/eglot-rename.gif)
+![eglot-xref-find-definition](./gif-examples/eglot-xref-find-definition.gif)
+![eglot-xref-find-references](./gif-examples/eglot-xref-find-references.gif)
+
 # Differences to lsp-mode.el
 
 Eglot is **beta**. It may currently underperform
@@ -179,22 +202,23 @@ Under the hood:
 
 - Message parser is much simpler.
 - Defers signature requests like `textDocument/hover` until server is
-  ready. Also sends `textDocument/didChange` for groups of edits, not
+  ready.
+- 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
+- Doesn't *require* anything other than Emacs 26, but will
+  automatically upgrade to work with stuff outside Emacs, like
+  `company`, `markdown-mode`, if you happen to have these installed.
 - Contained in one file
 - 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
 [pyls]: https://github.com/palantir/python-language-server
 [gnuelpa]: https://elpa.gnu.org/packages/eglot.html
+[melpa]: http://melpa.org/#/eglot
 [javascript-typescript-langserver]: 
https://github.com/sourcegraph/javascript-typescrip

[elpa] tag 1.0 created (now f385d9c)

2018-06-22 Thread Jo�o T�vora
capitaomorte pushed a change to tag 1.0.

at  f385d9c   (commit)
This tag includes the following new commits:

   new  f4de5d7   Fix copyright header. Obviously not since 2003
   new  b3c8b59   Refactor JSON-RPC lib jrpc.el from eglot.el
   new  2f1d76d   Proper server shutdown when jrpc.el is used
   new  870c60a   Merge master into jsonrpc-refactor (using imerge)
   new  0e1a5f0   jrpc-connect is now passed a generic dispatching function
   new  5cda0ec   Fix a ridiculous bug when generating transient projects
   new  258e3b0   Merge master into jsonrpc-refactor (using imerge)
   new  e5120aa   Add jrpc.el to Makefile
   new  33ae871   More flexible jrpc.el and improve eglot.el's doc
   new  3265c1d   Simpler callback protocol for JSONRPC parameters and 
results
   new  7f2e894   Merge branch 'master' into jsonrpc-refactor (using good 
ol' git merge)
   new  7cd94b9   Improve jrpc.el's doc (and change jrpc-request's protocol 
a tiny bit)
   new  078a1a6   Add full "Commentary" section to jrpc.el
   new  e906d25   Overhaul JSON and JSRONRPC error handling
   new  07359a2   Allow null timeouts and set default to 3 seconds
   new  7769c07   Send message, then establish continuations
   new  67d8335   jrpc.el should know nothing of mode-line updates
   new  e5ba4f6   Automatically reply with error if dispatcher doesn't
   new  a2aa1ed   Robustify timer handling for jrpc-async-request
   new  5cea412   Fix typos and phrasing in commentary and docstrings
   new  bb60c0c   Rename jrpc.el to jsonrpc.el
   new  cef3c29   Heroically merge master into jsonrpc-refactor (using 
imerge)
   new  c30f0f3   Get rid of jsonrpc.el customization group and timeout
   new  489182d   New jsonrpc-error error type
   new  4bbf810   Don't return implementation details in 
jsonrpc-async-request
   new  5e8fe4c   Add jsonrpc-tests.el
   new  0e44b27   jsonrpc.el uses classes and generic functions
   new  6f1ecc6   Merge branch use-eieio-server-defclass into 
jsonrpc-refactor
   new  05ff697   Document current API breaches a bit
   new  9e9dc57   Merge branch 'master' into jsonrpc-refactor (using 
regular merge)
   new  7f4e273   Merge master into jsonrpc-refactor (using imerge)
   new  5874af9   Fix deferred actions (forgot the crucial non-local exit)
   new  481f16e   * eglot.el (eglot-eldoc-function): Remove spurious log 
message
   new  980f3e7   Fix another merge-related bug in eglot-eldoc-function
   new  c43dff4   On request timeout, clear it from the deferred actions
   new  f594dd7   jsonrpc-request also calls for deferred action cleanup
   new  a4441c6   Merge master into jsonrpc-refactor (using imerge)
   new  6c9d41e   Add reasonably sophisticated deferred action tests
   new  c790274   jsonrpc--next-request-id is a connection slot
   new  0ba7964   * jsonrpc.el (jsonrpc-log-event): Log time of event.
   new  dae1de1   Tweak Makefile to run both tests in a row
   new  d7e1b92   * jsonrpc.el (jsonrpc-message): Fix formatting bug.
   new  4525eca   Support json.c.  API purely based on classes
   new  fab7f8b   Improve Makefile test targets
   new  68c266e   Avoid more catastrophes
   new  44e9647   Simplify JSONRPC connection shutdown
   new  2917214   Merge master into jsonrpc-refactor
   new  f730fff   Merge branch 'master' into jsonrpc-refactor
   new  d371f05   Request dispatcher's return value determines response
   new  2da7d92   Simplify JSONRPC status setting
   new  1ec47fb   Remove connection grabbing antics from jsonrpc.el
   new  bf9c850   Get rid of jsonrpc-obj
   new  a65d3f4   Make message and warning helpers private
   new  46e6107   Reshuffle definitions inside jsonrpc.el
   new  d87f4bf   jsonrpc--log-event should also be private
   new  10559a5   Shuffle definitions around again
   new  7371f68   * jsonrpc.el: Rewrite commentary.
   new  6531c8b   Merge branch 'master' into jsonrpc-refactor
   new  1f09fd3   Review commentary section before another review cycle
   new  aaca7de   Fix ridiculous bug
   new  59cc3fb   jsonrpc-connection-receive is now a public convenience 
function
   new  856a224   Simplify jsonrpc-connection-send
   new  0b474ec   Fix use of jsonrpc-message in tests
   new  69a622a   Fix some typos
   new  47b957d   Let's not send Content-type for now.
   new  61d1276   Fix another bug in jsonrpc-connection-send
   new  8fda30c   Merge master into jsonrpc-refactor (using imerge)
   new  0f20fdf   Tiny README.md change
   new  f385d9c   Merge branch 'jsonrpc-refactor', bump version to 1.0




[elpa] externals/eglot 59cc3fb 61/69: jsonrpc-connection-receive is now a public convenience function

2018-06-22 Thread Jo�o T�vora
branch: externals/eglot
commit 59cc3fbb99bb1bc917dbfd4f8eac1a3f3fd61b8c
Author: João Távora 
Commit: João Távora 

jsonrpc-connection-receive is now a public convenience function

* jsonrpc.el (Commentary:) Mention jsonrpc-connection-receive.
(jsonrpc-connection-receive): Rename from
jsonrpc--connection-receive.
(jsonrpc--process-filter): Use jsonrpc-connection-receive.
---
 jsonrpc.el | 93 --
 1 file changed, 48 insertions(+), 45 deletions(-)

diff --git a/jsonrpc.el b/jsonrpc.el
index 9a90f33..cec16b7 100644
--- a/jsonrpc.el
+++ b/jsonrpc.el
@@ -66,7 +66,8 @@
 ;; initiated contacts, it must arrange for the dispatcher functions
 ;; held in `jsonrpc--request-dispatcher' and
 ;; `jsonrpc--notification-dispatcher' to be called when appropriate,
-;; i.e. when noticing a new JSONRPC message on the wire.  Optionally
+;; i.e. when noticing a new JSONRPC message on the wire.  The function
+;; `jsonrpc-connection-receive' is a good way to do that.  Optionally
 ;; it should implement `jsonrpc-shutdown' and `jsonrpc-running-p' if
 ;; these concepts apply to the transport.
 ;;
@@ -218,6 +219,50 @@ for sending requests immediately."
   "Stop waiting for responses from the current JSONRPC CONNECTION."
   (clrhash (jsonrpc--request-continuations connection)))
 
+(defun jsonrpc-connection-receive (connection message)
+  "Process MESSAGE just received from CONNECTION.
+This function will destructure MESSAGE and call the appropriate
+dispatcher in CONNECTION."
+  (cl-destructuring-bind (&key method id error params result _jsonrpc)
+  message
+(let (continuations)
+  (jsonrpc--log-event connection message 'server)
+  (setf (jsonrpc-last-error connection) error)
+  (cond
+   (;; A remote request
+(and method id)
+(let* ((debug-on-error (and debug-on-error (not (ert-running-test
+   (reply
+(condition-case-unless-debug _ignore
+(condition-case oops
+`(:result ,(funcall (jsonrpc--request-dispatcher 
connection)
+connection (intern method) params))
+  (jsonrpc-error
+   `(:error
+ (:code
+  ,(or (alist-get 'jsonrpc-error-code (cdr oops)) 
-32603)
+  :message ,(or (alist-get 'jsonrpc-error-message
+   (cdr oops))
+"Internal error")
+  (error
+   `(:error (:code -32603 :message "Internal error"))
+  (apply #'jsonrpc--reply connection id reply)))
+   (;; A remote notification
+method
+(funcall (jsonrpc--notification-dispatcher connection)
+ connection (intern method) params))
+   (;; A remote response
+(setq continuations
+  (and id (gethash id (jsonrpc--request-continuations 
connection
+(let ((timer (nth 2 continuations)))
+  (when timer (cancel-timer timer)))
+(remhash id (jsonrpc--request-continuations connection))
+(if error (funcall (nth 1 continuations) error)
+  (funcall (nth 0 continuations) result)))
+   (;; An abnormal situation
+id (jsonrpc--warn "No continuation for id %s" id)))
+  (jsonrpc--call-deferred connection
+
 
 ;;; Contacting the remote endpoint
 ;;;
@@ -544,8 +589,8 @@ connection object, called when the process dies .")
   ;; buffer, shielding proc buffer from
   ;; tamper
   (with-temp-buffer
-(jsonrpc--connection-receive connection
- 
json-message)
+(jsonrpc-connection-receive connection
+
json-message)
   (goto-char message-end)
   (delete-region (point-min) (point))
   (setq expected-bytes nil
@@ -557,48 +602,6 @@ connection object, called when the process dies .")
   ;;
   (setf (jsonrpc--expected-bytes connection) expected-bytes))
 
-(defun jsonrpc--connection-receive (connection message)
-  "Connection MESSAGE from CONNECTION."
-  (cl-destructuring-bind (&key method id error params result _jsonrpc)
-  message
-(let (continuations)
-  (jsonrpc--log-event connection message 'server)
-  (setf (jsonrpc-last-error connection) error)
-  (cond
-   (;; A remote request
-(and method id)
-(let* ((debug-on-error (and debug-on-error (not (ert-running-test
-   (reply
-(condition-case-unless-debug _ignore
-(condition-case