doomemacs / doomemacs/core

Running (lsp-update-servers) as a doomscript?

Open
#6,899 0 comments 0 reactions 0 assignees View on GitHub
is:bug needs-triage
Dominant language
Emacs Lisp
Stars
22.7k
Forks
3.1k
Avg merge
10h 46m
Merged PRs (30d)
4

Description

### I confirm that...

- [X] I have searched the [issue tracker](https://github.com/doomemacs/doomemacs/issues), [documentation](https://docs.doomemacs.org), [FAQ](https://docs.doomemacs.org/-/faq), [Discourse](https://discourse.doomemacs.org), and [Google](https://google.com), in case this issue has already been reported/resolved.

- [X] I have read "[How to Debug Issues](https://doomemacs.org/d/how2debug)", and will use it to provide as much information about this issue as possible.

- [X] The issue can be reproduced on the **latest** available commit of Doom.

- [X] The issue can be reproduced on a stable release of Emacs, such as 27 or 28. *(Doom does not support development builds like 29+ or any version ending in .50 or .9x)*

### Expected behavior

Hi,
I'm trying to run `(lsp-update-servers)` from a bash script.

I first tried with `emacs --batch` mode, then discovered doomscript from comment here:
https://github.com/doomemacs/doomemacs/issues/6494#issuecomment-1162483877
I expected that simply replacing the content of the script by `(lsp-update-servers)`(of course preceeded by `(require 'doom-start)`) would work.
It doesn't, and my guess is that it's because the `lsp-update-servers` function is "async". I read a few docs about DoomScript, but I cannot figure out how to make my script work.

### Current behavior

What I wrote:
```
#!/usr/bin/env doomscript

(require 'doom-start) ; load your user config
(lsp-update-servers) ; upgrade LSP servers
```
Which results in:
```
$ doomscript doom-upgrade-simple.dscript
Local Ispell dictionary set to british
Starting new Ispell process aspell with british dictionary... \
Starting new Ispell process aspell with british dictionary...done
Eager macro-expansion failure: (wrong-number-of-arguments (1 . 1) 0)
LSP :: Download mspyls started.
LSP :: Downloading Microsoft Python Language Server...
Contacting host: pvsc.blob.core.windows.net:443
Contacting host: pvsc.blob.core.windows.net:443
LSP :: Download ansible-ls started.
LSP :: Download bash-ls started.
LSP :: Download clangd started.
LSP :: Download css-ls started.
LSP :: Download dockerfile-ls started.
LSP :: Download emmet-ls started.
LSP :: Download eslint started.
LSP :: Download jsts-ls started.
LSP :: Download json-ls started.
LSP :: Download metals started.
LSP :: Download iph started.
LSP :: Download rust-analyzer started.
LSP :: Download html-ls started.
LSP :: Download xmlls started.
LSP :: Download yamlls started.
LSP :: Download svelte-ls started.
```
This seems to work (`lsp-update-servers` is called), but lsp-server is being updated.
My guess is that it's because the `lsp-update-servers` function is "async", thus the script closes right after launching the subfunctions (those that upgrade each lsp-server independently), thus killing everything right before each subfunction gets executed.

I also tried with the exact format for the doomscript used in the cited GH comment:
```
#!/usr/bin/env doomscript

(defcli! my-upgrade (&args files)
(require 'doom-start) ; load your user config
(lsp-update-servers) ; upgrade LSP servers
)

(run! "my-upgrade" (cdr (member "--" argv)))
```

Which results in:
```
$ doomscript doom-upgrade.dscript
x There was an unexpected runtime error
Message: Assertion failed
Details: (((seq-every-p (apply-partially ...) command) "Invalid command list"))
Backtrace:
(cl--assertion-failed (seq-every-p (apply-partially #'stringp) command) "Invalid command list" nil nil)
(lsp-resolve-final-function #[0 "\30!\206 \303\304! B\207" [lsp-marksman-server-command lsp-marksman-server-command-args executable-find lsp-package-path marksman] 2])
(#[0 "\301\302\300!!\207" [#[0 "\30!\206 \303\304! B\207" [lsp-marksman-server-command lsp-marksman-server-command-args executable-find lsp-package-path marksman] 2] lsp-server-present\? lsp-r...
(lsp--server-binary-present\? #s(lsp--client nil nil (:connect #[1028 "\303\300!\304!\305!\306\307\"\310 �\311\312\313\314\315\306\316 \"\317\320\321\f\322\323\324\325\326&...
(apply lsp--server-binary-present\? #s(lsp--client nil nil (:connect #[1028 "\303\300!\304!\305!\306\307\"\310 �\311\312\313\314\315\306\316 \"\317\320\321\f\322\323\324\325...
(#[128 "\301\300\302\303\203\"\242\262\304\"\211\262\203\"T\262A\262\202\266\207" [(#[128 "\301\300\"?\207" [lsp--client-download-in-progress\? apply] 4 "\n\n(fn &rest A...
(-filter #[128 "\301\300\302\303\203\"\242\262\304\"\211\262\203\"T\262A\262\202\266\207" [(#[128 "\301\300\"?\207" [lsp--client-download-in-progress\? apply] 4 "\n\n(fn...
(lsp-update-servers)
(let ((files (cdr (assq 'files alist)))) (require 'doom-start) (lsp-update-servers))
((lambda (cli alist) (let ((files (cdr (assq 'files alist)))) (require 'doom-start) (lsp-update-servers))) #s(doom-cli ("my-upgrade") nil nil nil nil nil ((&args files)) (:hide nil) (lambda (cli alist) (...
(funcall (lambda (cli alist) (let ((files (cdr (assq 'files alist)))) (require 'doom-start) (lsp-update-servers))) #s(doom-cli ("my-upgrade") nil nil nil nil nil ((&args files)) (:hide nil) (lambda (cli ...
(doom-cli-execute #s(doom-cli ("my-upgrade") nil nil nil nil nil ((&args files)) (:hide nil) (lambda (cli alist) (let ((files (cdr (assq 'files alist)))) (require 'doom-start) (lsp-update-servers)))) ((f...
! Wrote extended backtrace to ~/.emacs.d/.local/logs/cli.my-upgrade.221017144954.1010692.error
```
Again, my guess is that it's because the `lsp-update-servers` function is "async" and the way each subfunction returns its stdout/stderr misleads the doomscript.

Then I've read the comment below about running async functions from emacs batch mode:
https://stackoverflow.com/questions/6578373/sleep-in-emacs-lisp/74044304#74044304
Adding `sleep-for` (or `sit-for`) with a long delay makes the script work, but the amount of time might depend on the number of lsp-servers to upgrade and internet connection speed, so this is just a hacky work-around, not the correct solution.
I couldn't make the solution with a `process-sentinel` work either. I'm not sure it it's because I'm a newbie in elisp and don't really understand what I'm doing here :( or if the way `lsp-update-servers` is "async" and that would not correspond to what a "process sentinel" expects?

### Steps to reproduce

You can try the scripts in the sections above you'll most probably get the same errors I did.

I would be glad if anyone could give me hints on running `lsp-update-servers` (or any "async" function) from an Emacs/Doom script.

PS: I find the order of the items to fill in the "bug report" type of issue quite disturbing: I would argue that starting by stating "what I did" (= "steps to reproduce"), followed by "what occurred" (= "Current behavior"), then "what should have occurred" (= "Expected behavior") would be more logical... (or the two latter inverted).

### System Information

https://pastebin.com/TvBaW7Zp

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.