Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workspace configuration example? #59

Closed
julienfantin opened this issue Aug 2, 2018 · 18 comments
Closed

Workspace configuration example? #59

julienfantin opened this issue Aug 2, 2018 · 18 comments

Comments

@julienfantin
Copy link

I'm trying to use eglot-workspace-configuration and eglot-signal-didChangeConfiguration to configure pyls as described here

Could you give an example of how to translate the setting pyls.configurationSources set to ['flake8'] to a valid config alist?

@joaotavora
Copy link
Owner

Indeed this is very lightly tested.
By try placing a file .dir-locals.el with the following contents in the root of your project:

((nil
  (eglot-workspace-configuration
   .
   ((pyls.configurationSources . ["flake8"] )))))

You can add more configuration parameters in parallel with pyls.configurationSources. Notice that the value you add for each parameter must be a valid JSON-serializable lisp expression. So [flake8] would be wrong here.

@julienfantin
Copy link
Author

julienfantin commented Aug 3, 2018

Unfortunately this doesn't seem to work for me. The eglot STDERR buffer shows this:

2018-08-03 10:42:17,071 UTC - ERROR - pyls.jsonrpc.endpoint - Failed to handle notification workspace/didChangeConfiguration: {'settings': ['pyls.configurationSources', ['flake8']]}
Traceback (most recent call last):
  File "/Users/jfantin/.virtualenvs/project/lib/python3.6/site-packages/pyls/jsonrpc/endpoint.py", line 142, in _handle_notification
    handler_result = handler(params)
  File "/Users/jfantin/.virtualenvs/project/lib/python3.6/site-packages/pyls/jsonrpc/dispatchers.py", line 23, in handler
    return method(**(params or {}))
  File "/Users/jfantin/.virtualenvs/project/lib/python3.6/site-packages/pyls/python_ls.py", line 273, in m_workspace__did_change_configuration
    self.config.update((settings or {}).get('pyls', {}))
AttributeError: 'list' object has no attribute 'get'

It seems like we're passing the settings as a list when the server expects a dictionary?

@joaotavora
Copy link
Owner

It seems like we're passing the settings as a list when the server expects a dictionary?

Right. Try this instead for .dir-locals

((nil
  (eglot-workspace-configuration
   .
   (:pyls.configurationSources ["flake8"] ))))

This uses a plist instead of an alist. If you were using the latest emacs it would probably work with the alist-based version I gave you before. If it works then this is a bug and eglot-workspace-configuration must be a plist instead of an alist.

@julienfantin
Copy link
Author

Ha that worked!

FYI my emacs version:

GNU Emacs 27.0.50 (build 1, x86_64-apple-darwin17.5.0, NS appkit-1561.40 Version 10.13.4 (Build 17E199)) of 2018-07-24

@julienfantin
Copy link
Author

Woops actually it errors:

Wrong type argument: listp, :pyls\.configurationSources

@joaotavora
Copy link
Owner

Woops actually it errors

Can we have a backtrace? use M-x toggle-debug-on-error

@julienfantin
Copy link
Author

Debugger entered--Lisp error: (wrong-type-argument listp :pyls\.configurationSources)
  eglot-signal-didChangeConfiguration(#<eglot-lsp-server eglot-lsp-server-43e0c7cc>)
  run-hook-with-args(eglot-signal-didChangeConfiguration #<eglot-lsp-server eglot-lsp-server-43e0c7cc>)
  eglot--connect(python-mode (vc . "~/src/project/") eglot-lsp-server ("pyls"))
  eglot(python-mode (vc . "~/src/project/") eglot-lsp-server ("pyls") t)
  funcall-interactively(eglot python-mode (vc . "~/src/project/") eglot-lsp-server ("pyls") t)
  call-interactively(eglot record nil)
  command-execute(eglot record)
  #f(compiled-function (cmd) #<bytecode 0x40677e91>)("eglot")
  #f(compiled-function (result) #<bytecode 0x40fe42d9>)("eglot")
  ivy-call()
  #f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a format string, normally ending in a colon and a\nspace; %d anywhere in the string is replaced by the current\nnumber of matching candidates.  For the literal % character,\nescape it with %%. See also `ivy-count-format'.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for `completing-read' compat.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected, i.e. custom text.\n\nIf INITIAL-INPUT is not nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nIf PRESELECT is not nil, then select the corresponding candidate\nout of the ones that match the INITIAL-INPUT.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the current candidate(s) is changed.\n\nWhen SORT is t, use `ivy-sort-functions-alist' for sorting.\n\nACTION is a lambda function to call after selecting a result.  It\ntakes a single string argument.\n\nUNWIND is a lambda function to call before exiting.\n\nRE-BUILDER is a lambda function to call to transform text into a\nregex pattern.\n\nMATCHER is to override matching.\n\nDYNAMIC-COLLECTION is a boolean to specify if the list of\ncandidates is updated after each input by calling COLLECTION.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x40d765c1>)("M-x " [lispy-brackets-auto-wrap 0 ansi-color-apply-overlay-face epg-context-signers -flatten-n 0 tramp-compat-exec-path vc-git-stash-snapshot gdb-script-syntax-propertize-function avy-words tramp-adb-parse-device-names tramp-find-user markdown-xhtml-body-preamble markdown-match-bold org-emphasis-regexp-components company-box--add-icon tramp-gvfs-handle-copy-file tramp-do-copy-or-rename-file-out-of-band want defun-prompt-regexp _message mixal dired-at-point avl-tree--stack-store--cmacro cl-print--preprocess -deferred-actions \(setf\ eglot--project-nickname\) edebug-clear-frequency-count -some\? vc-git-conflicted-files 0 0 checkdoc-package-keywords-flag chroma-hsl \" 0 dired-before-readin-hook test-command & \' counsel-projectile-switch-to-buffer-transformer lispy-braces-barf-to-point-or-jump-nostring :contents org-babel-results-keyword muletibetan-2 tramp-sh-handle-exec-path not-at-beginning-of-line log-edit-set-header lispy-bind-variable projectile-tags-file-name ...] :action #f(compiled-function (result) #<bytecode 0x40fe42d9>) :keymap (keymap (keymap (3 keymap (18 . #f(compiled-function () (interactive nil) #<bytecode 0x40fe4649>)))) keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :predicate commandp :require-match t :history counsel-M-x-history :action #f(compiled-function (cmd) #<bytecode 0x40677e91>) :sort t :keymap (keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :initial-input nil :caller counsel-M-x)
  apply(#f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a format string, normally ending in a colon and a\nspace; %d anywhere in the string is replaced by the current\nnumber of matching candidates.  For the literal % character,\nescape it with %%. See also `ivy-count-format'.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for `completing-read' compat.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected, i.e. custom text.\n\nIf INITIAL-INPUT is not nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nIf PRESELECT is not nil, then select the corresponding candidate\nout of the ones that match the INITIAL-INPUT.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the current candidate(s) is changed.\n\nWhen SORT is t, use `ivy-sort-functions-alist' for sorting.\n\nACTION is a lambda function to call after selecting a result.  It\ntakes a single string argument.\n\nUNWIND is a lambda function to call before exiting.\n\nRE-BUILDER is a lambda function to call to transform text into a\nregex pattern.\n\nMATCHER is to override matching.\n\nDYNAMIC-COLLECTION is a boolean to specify if the list of\ncandidates is updated after each input by calling COLLECTION.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x40d765c1>) "M-x " [lispy-brackets-auto-wrap 0 ansi-color-apply-overlay-face epg-context-signers -flatten-n 0 tramp-compat-exec-path vc-git-stash-snapshot gdb-script-syntax-propertize-function avy-words tramp-adb-parse-device-names tramp-find-user markdown-xhtml-body-preamble markdown-match-bold org-emphasis-regexp-components company-box--add-icon tramp-gvfs-handle-copy-file tramp-do-copy-or-rename-file-out-of-band want defun-prompt-regexp _message mixal dired-at-point avl-tree--stack-store--cmacro cl-print--preprocess -deferred-actions \(setf\ eglot--project-nickname\) edebug-clear-frequency-count -some\? vc-git-conflicted-files 0 0 checkdoc-package-keywords-flag chroma-hsl \" 0 dired-before-readin-hook test-command & \' counsel-projectile-switch-to-buffer-transformer lispy-braces-barf-to-point-or-jump-nostring :contents org-babel-results-keyword muletibetan-2 tramp-sh-handle-exec-path not-at-beginning-of-line log-edit-set-header lispy-bind-variable projectile-tags-file-name ...] (:action #f(compiled-function (result) #<bytecode 0x40fe42d9>) :keymap (keymap (keymap (3 keymap (18 . #f(compiled-function () (interactive nil) #<bytecode 0x40fe4649>)))) keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :predicate commandp :require-match t :history counsel-M-x-history :action #f(compiled-function (cmd) #<bytecode 0x40677e91>) :sort t :keymap (keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :initial-input nil :caller counsel-M-x))
  ivy-prescient-read(#f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a format string, normally ending in a colon and a\nspace; %d anywhere in the string is replaced by the current\nnumber of matching candidates.  For the literal % character,\nescape it with %%. See also `ivy-count-format'.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for `completing-read' compat.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected, i.e. custom text.\n\nIf INITIAL-INPUT is not nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nIf PRESELECT is not nil, then select the corresponding candidate\nout of the ones that match the INITIAL-INPUT.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the current candidate(s) is changed.\n\nWhen SORT is t, use `ivy-sort-functions-alist' for sorting.\n\nACTION is a lambda function to call after selecting a result.  It\ntakes a single string argument.\n\nUNWIND is a lambda function to call before exiting.\n\nRE-BUILDER is a lambda function to call to transform text into a\nregex pattern.\n\nMATCHER is to override matching.\n\nDYNAMIC-COLLECTION is a boolean to specify if the list of\ncandidates is updated after each input by calling COLLECTION.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x40d765c1>) "M-x " [lispy-brackets-auto-wrap 0 ansi-color-apply-overlay-face epg-context-signers -flatten-n 0 tramp-compat-exec-path vc-git-stash-snapshot gdb-script-syntax-propertize-function avy-words tramp-adb-parse-device-names tramp-find-user markdown-xhtml-body-preamble markdown-match-bold org-emphasis-regexp-components company-box--add-icon tramp-gvfs-handle-copy-file tramp-do-copy-or-rename-file-out-of-band want defun-prompt-regexp _message mixal dired-at-point avl-tree--stack-store--cmacro cl-print--preprocess -deferred-actions \(setf\ eglot--project-nickname\) edebug-clear-frequency-count -some\? vc-git-conflicted-files 0 0 checkdoc-package-keywords-flag chroma-hsl \" 0 dired-before-readin-hook test-command & \' counsel-projectile-switch-to-buffer-transformer lispy-braces-barf-to-point-or-jump-nostring :contents org-babel-results-keyword muletibetan-2 tramp-sh-handle-exec-path not-at-beginning-of-line log-edit-set-header lispy-bind-variable projectile-tags-file-name ...] :predicate commandp :require-match t :history counsel-M-x-history :action #f(compiled-function (cmd) #<bytecode 0x40677e91>) :sort t :keymap (keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :initial-input nil :caller counsel-M-x)
  apply(ivy-prescient-read #f(compiled-function (arg1 arg2 &rest rest) "Read a string in the minibuffer, with completion.\n\nPROMPT is a format string, normally ending in a colon and a\nspace; %d anywhere in the string is replaced by the current\nnumber of matching candidates.  For the literal % character,\nescape it with %%. See also `ivy-count-format'.\n\nCOLLECTION is either a list of strings, a function, an alist, or\na hash table.\n\nPREDICATE is applied to filter out the COLLECTION immediately.\nThis argument is for `completing-read' compat.\n\nWhen REQUIRE-MATCH is non-nil, only members of COLLECTION can be\nselected, i.e. custom text.\n\nIf INITIAL-INPUT is not nil, then insert that input in the\nminibuffer initially.\n\nHISTORY is a name of a variable to hold the completion session\nhistory.\n\nKEYMAP is composed with `ivy-minibuffer-map'.\n\nIf PRESELECT is not nil, then select the corresponding candidate\nout of the ones that match the INITIAL-INPUT.\n\nDEF is for compatibility with `completing-read'.\n\nUPDATE-FN is called each time the current candidate(s) is changed.\n\nWhen SORT is t, use `ivy-sort-functions-alist' for sorting.\n\nACTION is a lambda function to call after selecting a result.  It\ntakes a single string argument.\n\nUNWIND is a lambda function to call before exiting.\n\nRE-BUILDER is a lambda function to call to transform text into a\nregex pattern.\n\nMATCHER is to override matching.\n\nDYNAMIC-COLLECTION is a boolean to specify if the list of\ncandidates is updated after each input by calling COLLECTION.\n\nCALLER is a symbol to uniquely identify the caller to `ivy-read'.\nIt is used, along with COLLECTION, to determine which\ncustomizations apply to the current completion session." #<bytecode 0x40d765c1>) ("M-x " [lispy-brackets-auto-wrap 0 ansi-color-apply-overlay-face epg-context-signers -flatten-n 0 tramp-compat-exec-path vc-git-stash-snapshot gdb-script-syntax-propertize-function avy-words tramp-adb-parse-device-names tramp-find-user markdown-xhtml-body-preamble markdown-match-bold org-emphasis-regexp-components company-box--add-icon tramp-gvfs-handle-copy-file tramp-do-copy-or-rename-file-out-of-band want defun-prompt-regexp _message mixal dired-at-point avl-tree--stack-store--cmacro cl-print--preprocess -deferred-actions \(setf\ eglot--project-nickname\) edebug-clear-frequency-count -some\? vc-git-conflicted-files 0 0 checkdoc-package-keywords-flag chroma-hsl \" 0 dired-before-readin-hook test-command & \' counsel-projectile-switch-to-buffer-transformer lispy-braces-barf-to-point-or-jump-nostring :contents org-babel-results-keyword muletibetan-2 tramp-sh-handle-exec-path not-at-beginning-of-line log-edit-set-header lispy-bind-variable projectile-tags-file-name ...] :predicate commandp :require-match t :history counsel-M-x-history :action #f(compiled-function (cmd) #<bytecode 0x40677e91>) :sort t :keymap (keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :initial-input nil :caller counsel-M-x))
  ivy-read("M-x " [lispy-brackets-auto-wrap 0 ansi-color-apply-overlay-face epg-context-signers -flatten-n 0 tramp-compat-exec-path vc-git-stash-snapshot gdb-script-syntax-propertize-function avy-words tramp-adb-parse-device-names tramp-find-user markdown-xhtml-body-preamble markdown-match-bold org-emphasis-regexp-components company-box--add-icon tramp-gvfs-handle-copy-file tramp-do-copy-or-rename-file-out-of-band want defun-prompt-regexp _message mixal dired-at-point avl-tree--stack-store--cmacro cl-print--preprocess -deferred-actions \(setf\ eglot--project-nickname\) edebug-clear-frequency-count -some\? vc-git-conflicted-files 0 0 checkdoc-package-keywords-flag chroma-hsl \" 0 dired-before-readin-hook test-command & \' counsel-projectile-switch-to-buffer-transformer lispy-braces-barf-to-point-or-jump-nostring :contents org-babel-results-keyword muletibetan-2 tramp-sh-handle-exec-path not-at-beginning-of-line log-edit-set-header lispy-bind-variable projectile-tags-file-name ...] :predicate commandp :require-match t :history counsel-M-x-history :action #f(compiled-function (cmd) #<bytecode 0x40677e91>) :sort t :keymap (keymap (67108908 . counsel--info-lookup-symbol) (67108910 . counsel-find-symbol)) :initial-input nil :caller counsel-M-x)
  counsel-M-x()
  funcall-interactively(counsel-M-x)
  call-interactively(counsel-M-x nil nil)
  command-execute(counsel-M-x)

@joaotavora
Copy link
Owner

Woops actually it errors:

Argh, sorry, my bad.

Try with this third variation instead (just add a colon to the first version):

((nil
  (eglot-workspace-configuration
   .
   ((:pyls.configurationSources . ["flake8"] )))))

@julienfantin
Copy link
Author

Now I think this is what I had originally. This definitely doesn't error and this is what I get in the events buffer:

client-notification Fri Aug  3 15:55:20 2018:
(:jsonrpc "2.0" :method "workspace/didChangeConfiguration" :params
          (:settings
           (:pyls\.configurationSources
            ["flake8"])))

I don't see the setting properly reflected in the server's behavior after that, so I'm not sure whether the settings are not coming across in the expected format or if it's some other issue on the server.

@joaotavora
Copy link
Owner

Now I think this is what I had originally.

It's not, though. It's subtly different. But I will make it so that the first version also works (meaning there is something to change in Eglot, but only after I understand the problem)

Do you still get the python error in the eglot stderr buffer? If you don't then whatever python is seeing is now a dictionary, and the question is now server-specific.

@julienfantin
Copy link
Author

No more errors with the last config, but the server doesn't seem to take the settings into account, could be entirely pyls specific... I'll try to make a minimal repro.

@joaotavora
Copy link
Owner

I'll try to make a minimal repro.

Good idea. Tell me exactly what to install and what to look for in a minimal python project with and without the dir-locals file.

@mkcms
Copy link
Collaborator

mkcms commented Aug 3, 2018

Can we have a command which will read a name of configuration option and it's json value and append it to .dir-locals.el?

@joaotavora
Copy link
Owner

Can we have a command which will read a name of configuration option and it's json value and append it to .dir-locals.el?

You have M-x add-dir-local-variable though it doesn't really append, rather replace. You could build a more sophisticated command around a non-interactive version of that function or modify-dir-local-variable, but I wonder about the edge cases. The eglot-workspace-configuration variable can be set in many ways, including mode-local hooks. Exactly what would take precedence? Better let users get some experience with this solution before going down that rabbit hole.

Also, what we need really are project-local variables, something possibly worth proposing to Emacs.

@mkcms
Copy link
Collaborator

mkcms commented Aug 4, 2018

Exactly what would take precedence?

I don't get it. The command would be just modifying existing value of eglot-workspace-configuration and then saving it to .dir-locals.el. I think it would be useful, as the syntax can be difficult to remember, and some people who use emacs for e.g. python development don't want to write lisp code.

@joaotavora
Copy link
Owner

I don't get it.

Well you can set it via a hook as well. Wouldn't an eglot-specific command have to take that in account?

But if you want have a stab at it. Let's see how much more convenient you can make it than M-x add-dir-local-variable, perhaps I'm not seeing the full picture here.

joaotavora added a commit that referenced this issue Aug 6, 2018
* eglot.el (eglot-signal-didChangeConfiguration): Convert
alist keys into a json-compatible plist.
@julienfantin
Copy link
Author

julienfantin commented Aug 9, 2018

Anyone reading this for the pyls config part: took me a while to realize the settings as "documented" here are actually a short-form object notation, the server actually expects a nested object.

So in elisp, with the latest eglot changes, .dir-locals.el should look something like:

((nil (eglot-workspace-configuration . ((pyls . ((configurationSources . ["flake8"])))))))

bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 18, 2022
… be keywords

* eglot.el (eglot-signal-didChangeConfiguration): Convert
alist keys into a json-compatible plist.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
… be keywords

* eglot.el (eglot-signal-didChangeConfiguration): Convert
alist keys into a json-compatible plist.
bhankas pushed a commit to bhankas/emacs that referenced this issue Sep 19, 2022
* eglot.el (eglot-signal-didChangeConfiguration): Convert
alist keys into a json-compatible plist.

#59: joaotavora/eglot#59
jollaitbot pushed a commit to sailfishos-mirror/emacs that referenced this issue Oct 12, 2022
* eglot.el (eglot-signal-didChangeConfiguration): Convert
alist keys into a json-compatible plist.

GitHub-reference: per joaotavora/eglot#59
@buhtz
Copy link

buhtz commented Jan 7, 2024

Can I use this somehow to set --builtins="_" for flake8?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants