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

lsp-layer additions: configuration and building blocks for derived layers. #10486

Merged
merged 1 commit into from
Aug 23, 2018

Conversation

cormacc
Copy link
Contributor

@cormacc cormacc commented Mar 16, 2018

This adds some useful defaults to the lsp layer (in a new config.el), and adds some building block functions to facilitate development of derived layers.

It declares a number of major mode prefixes for typical classes of language server function, and provides the function spacemacs/lsp-bind-keys-for-mode which can be used by derived layers to provide a consistent set of keybindings common core language-server functions.

See README.org and the commit message for further details and a trail of the multiple amendments since initial submission.

A usage example can be found in the lsp-c-c++ layer, in my branch of the spacemacs repo:
https://github.com/cormacc/spacemacs/tree/lsp-c-c%2B%2B-layer
N.B. The lsp-c-c++ layer will not be the subject of a PR as is, but form the basis of a new PR against the c-c++ layer after this gets merged. Please do not provide any feedback relating to it in the discussion thread relating to this PR.

This is partially derived from @MaskRay's personal config and has benefited from some feedback from him and quite a number of other contributors to this discussion.

;;Format
"==" #'spacemacs/lsp-format-buffer
;;goto
"gi" #'imenu
Copy link
Contributor

@MaskRay MaskRay Mar 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imenu is already bound at SPC s j and SPC j i

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed...

;;goto
"gi" #'imenu
"gs" #'lsp-ui-find-workspace-symbol
"gf" #'spacemacs/lsp-ffap-no-prompt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ffap does not use LSP.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also removed. Originally included that a binding like this was appropriate in a general purpose lsp layer, but maybe there's a better idiomatic equivalent, i.e an lsp method that would jump to a header file when invoked on a c source #include, or the appropriate ruby source file when invoked on a 'require...' statement etc.?

@MaskRay
Copy link
Contributor

MaskRay commented Mar 16, 2018

Great job! Hope this can be merged soon.

@cormacc
Copy link
Contributor Author

cormacc commented Mar 16, 2018

Thanks Maskray -- amended the commit with your suggestions -- also some corrections to keybindings and file headers in line with CONVENTIONS.org.

You got any insight into the failing CI tests? They're all the same issue. Probably something daft I've done..

Test test-declare-layers--distribution-layer-is-second condition:
(ert-test-failed
((should
(eq 'spacemacs-base
(second configuration-layer--used-layers)))
:form
(eq spacemacs-base spacemacs-defaults)
:value nil))

@cormacc cormacc force-pushed the lsp-layer-improvements branch 2 times, most recently from 3fb4712 to 4c98a39 Compare March 16, 2018 14:35
@MaskRay
Copy link
Contributor

MaskRay commented Mar 16, 2018

No idea why CI fails... all recent PRs fail..

Regarding cquery, if the point is on a #include directive, you can invoke textDocument/definition (xref-find-definition, lsp-ui-peek-find-definitions, ...) to jump to the included file.

Implementation https://github.com/cquery-project/cquery/blob/master/src/messages/text_document_definition.cc#L116
Other cross reference candies https://github.com/cquery-project/cquery/wiki/FAQ#definitions

@sebastiencs
Copy link

I replied to @MaskRay in the comments, sorry for being late

@cormacc cormacc force-pushed the lsp-layer-improvements branch 2 times, most recently from 4d61649 to e65bc8d Compare March 22, 2018 15:14
@MaskRay
Copy link
Contributor

MaskRay commented Mar 23, 2018

I cannot see your comments in the web view but I remember I saw it somewhere...

For lsp-ui-peek performance issue, code bases of most languages wouldn't be large enough to have more than 1000 references and thus make Emacs slow. I think unfolding all files is a good default value.

@sebastiencs
Copy link

@MaskRay The issue is not the number of references but the number of files to open.
For each file it will call font-lock-ensure to fontify the whole file. With 10 big files it can takes +5 seconds to just open the peek view.

@bkchr
Copy link

bkchr commented Apr 9, 2018

@cormacc you are missing the spacemacs/lsp-format-buffer function. You declare a shortcut, but the function does not exist :)

@cormacc
Copy link
Contributor Author

cormacc commented Apr 9, 2018

@bkchr Thanks -- corrected in an amendment to the commit (stripped the incorrect 'spacemacs/' prefix, which I must have added at some stage while refactoring the various changes between this PR and the new cquery layer). I haven't actually been using this keybinding, as believe cquery (the only lsp server I'm using) only includes the functionality if built using the --use-clang-cxx option, which the aur cquery-git package doesn't do out of the box.

https://github.com/cquery-project/cquery/wiki/Formatting
https://github.com/cquery-project/cquery/wiki/Build-%28Waf%29

@bkchr
Copy link

bkchr commented Apr 9, 2018

@cormacc Yeah thanks :) I'm using your changes with the rust language server and I wondered why it does not work. Today I finally got time to look into it :D

@cormacc
Copy link
Contributor Author

cormacc commented Apr 10, 2018

Saw a recent commit to lsp-mode added lsp-goto-type-definition and lsp-goto-implementation so added bindings for these. Moved all the symbol browser type bindings under 'j' (jump), as 'g' was getting fairly crowded. So loose rule is that anything with a single target should go under g, whereas those with multiple targets (lsp-ui-imenu, lsp-ui-peek bindings) goes under j.

Amended my personal new-cquery-layer branch in the same way.
https://github.com/cormacc/spacemacs/tree/new-cquery-layer

@bkchr I've also raised a new PR against lsp-mode that adds a capability check to the lsp-format-buffer call. If that gets merged, you'll see an appropriate signal if the language server doesn't support the functionality.

@bkchr
Copy link

bkchr commented Apr 10, 2018

@cormacc, nice.

@franksn
Copy link

franksn commented Apr 11, 2018

@cormacc can you set default cquery-sem-highlight-method to nil?
As people won't likely use it unless their theme support it, and the default spacemacs-theme hasn't supported it either.

@cormacc
Copy link
Contributor Author

cormacc commented Apr 13, 2018

@franksn Semantic highlighting appears to me to work using the standard spacemacs theme -- at least with mode set to either 'font-lock or 'overlay I get colour coded tokens etc. -- or have I set my expectations too low? :)

@shuwens
Copy link
Contributor

shuwens commented May 14, 2018

@cormacc Looks like we are blocked here for a while, any plan to move forward? If it is the problem in circleci, can we get some help from the spacemacs community? I assume we can gently ask for help in the gitter chat room?

@cormacc
Copy link
Contributor Author

cormacc commented May 14, 2018

I think (purely on the basis of eyeballing recent commit history) that the principal spacemacs developers have been working on a large-ish reorganisation of the core layers and that's whats causing the circle CI failures and holding up the merge of all/most recent PRs. Seem to have merged this work to develop ?today? -- anyway I've just rebased my branch on the latest commit to develop and all the circle CI tests are passing now.

As a heads-up, the recent upstream change-set renamed spacemacs/lsp-set-default-jump-handlers to spacemacs//setup-lsp-jump-handler (note the double forward-slash), so you'll need to update any derived layers accordingly.

@syl20bnr syl20bnr self-assigned this May 15, 2018
@cormacc
Copy link
Contributor Author

cormacc commented May 15, 2018

@syl20bnr Just rebased this branch on latest commit on develop (i.e. 7aca5ae) before seeing you'd started work on it.

@cormacc
Copy link
Contributor Author

cormacc commented Aug 20, 2018

@myrgy Incorporated your and @MaskRay's suggestions. Also tidied up some hasty crap left in Friday. Thank you both

@cormacc
Copy link
Contributor Author

cormacc commented Aug 20, 2018

Greatly reduced the duplication between configuration for cquery and ccls backends by introducing a couple of helper functions at the top of funcs.el

I've a couple of niggly bits annoying me -- see the excerpt from funcs.el below. The two commented out regions of lsp-c-c++//common-config are more elegant/concise, but result in the errors mentioned in the comments. Any ideas?
edit resolved the issue with evil-make-overriding-map using (symbol value ...)
edit d'oh -- commas in a lisp list :)

(defun lsp-c-c++//backend-string (prefix suffix) (concat prefix (symbol-name lsp-c-c++-backend) suffix))
(defun lsp-c-c++//backend-symbol (prefix suffix) (intern (lsp-c-c++//backend-string prefix suffix)))
(defun lsp-c-c++//call-backend-function (prefix suffix &rest args) (apply (lsp-c-c++//backend-symbol prefix suffix) args))
;; (defun lsp-c-c++//funcall-interactively (prefix suffix) (funcall-interactively (lsp-c-c++//backend-symbol prefix suffix)))
(defun lsp-c-c++//funcall-interactively (prefix suffix &rest args) (funcall-interactively (lsp-c-c++//backend-symbol prefix suffix) args))
(defun lsp-c-c++//funcall-interactively-no-args (prefix suffix) (funcall-interactively (lsp-c-c++//backend-symbol prefix suffix)))
(defun lsp-c-c++//set-backend-symbol (prefix suffix value) (set (lsp-c-c++//backend-symbol prefix suffix) (symbol-value value)))
(defun lsp-c-c++//set-backend-config (param prefix suffix) (when (symbol-value param) (lsp-c-c++//set-backend-symbol prefix suffix param)))
(defun lsp-c-c++//apply-backend-config (suffix)
  (lsp-c-c++//set-backend-config (intern (concat "lsp-c-c++-" suffix)) nil (concat "-" suffix)))

(defun lsp-c-c++//enable ()
  (condition-case nil
    (lsp-c-c++//call-backend-function "lsp-" "-enable")
    (user-error nil)))

(defun lsp-c-c++//common-config ()
  (lsp-c-c++//customise-lsp-ui-peek)
  (lsp-c-c++//wrap-backend-functions)
  (setq-default flycheck-disabled-checkers '(c/c++-clang c/c++-gcc))

  (dolist (param '("executable" "extra-init-params" "cache-dir" "project-whitelist" "project-blacklist" "sem-highlight-method"))
    (lsp-c-c++//apply-backend-config param))
  (when lsp-c-c++-sem-highlight-rainbow
    (lsp-c-c++//call-backend-function nil "-use-default-rainbow-sem-highlight"))

  (dolist (mode c-c++-modes)
    (spacemacs/lsp-bind-keys-for-mode mode)
    (lsp-c-c++//bind-keys-for-mode mode))

  (evil-set-initial-state '(lsp-c-c++//backend-symbol nil "-tree-mode") 'emacs)
  ;;evil-record-macro keybinding clobbers q in cquery-tree-mode-map for some reason?
  (evil-make-overriding-map (symbol-value (lsp-c-c++//backend-symbol nil "-tree-mode-map"))))

@cormacc cormacc force-pushed the lsp-layer-improvements branch 2 times, most recently from b4721eb to 0f1a581 Compare August 21, 2018 00:36
@rcoacci
Copy link

rcoacci commented Aug 21, 2018

Is there anything preventing this from being merged?
Anything we can do to help?

@sdwolfz
Copy link
Collaborator

sdwolfz commented Aug 21, 2018

This PR is a bit overwhelming due to it's size, both code and thread, but I feel like I can focus my effort on it and guide you to how to get it merged.

The main thing I want is to have the lsp functionality inside the current c-c++ layer, instead of having another layer.

Let me know if there are other changes or PRs I can focus on that will simplify your work on this one and I will get right to it (to the limits of my ability).

@cormacc
Copy link
Contributor Author

cormacc commented Aug 21, 2018

@sdwolfz That would be great. This PR contained just the lsp layer additions for most of its life -- I'd been maintaining the lsp-c-c++ layer in a branch of my own fork of the spacemacs repo, but added it recently as I was wondering whether the lack of a usage example was (one of) the reason(s) it wasn't getting any love.

The intent with the lsp-layer improvements was to provide a consistent set of of prefixes for core keybindings for all/most of the lsp layers for different languages. And a few of the other guys/gals working on lsp-based layers seem to think that's useful. So how does this sound as a plan of action...

  1. Remove the lsp-c-c++ layer from this PR and work with you on getting the lsp layer changes merged
  2. Integrate the lsp-c-c++ layer with the c-c++ layer and raise a new PR. This should (famous last words) be pretty straightforward as lsp-c-c++ is pretty orthogonal to c-c++, which it declares as a layer dependency anyway

This sound like a reasonable approach?

Re. 2 -- my original reason for creating a separate layer rather than taking this route originally were some responses to @MaskRay 's original suggestion of adding cquery to the c-c++ layer here: #10143
@quicknir was working on a some tidy-up of the c-c++ layer at the time and appeared to have progressed quite a bit, but don't know what the current status of that work is.

@sdwolfz
Copy link
Collaborator

sdwolfz commented Aug 21, 2018

@cormacc sounds like a good plan.

I recently merged the lsp support for Golang and Java so you can take a look there for hints on how to add your changes to the c-c++ layer.

Let me know when you are ready and I will start reviewing the code.

@cormacc
Copy link
Contributor Author

cormacc commented Aug 21, 2018

@sdwolfz OK - that latest commit amendment has stripped all the c-c++ stuff from this PR. So anyone who's actually using the lsp-c-c++ layer shouldn't pull this update :)

edit I've moved the lsp-c-c++ layer into a new branch of my own fork, here: https://github.com/cormacc/spacemacs/tree/lsp-c-c%2B%2B-layer

N.B. this branch won't receive any updates -- just a placeholder til we get the lsp-layer PR merged and I can rework lsp-c-c++ as a PR against the c-c++ layer.

@cormacc cormacc force-pushed the lsp-layer-improvements branch 3 times, most recently from a6ed57c to 7550c07 Compare August 22, 2018 11:53
;;format
"=b" #'lsp-format-buffer
;;execute
"ea" #'lsp-execute-code-action
Copy link
Collaborator

@sdwolfz sdwolfz Aug 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CONVENTIONS.org file requires the SPC m e prefix to contain code evaluation functionality. Is this what lsp-execute-code-action does? As far as I can tell it's a different thing.
Here's the definition of the SPC m e prefix:

Live evaluation of code is under the prefix ~SPC m e~.

| Key     | Description                                   |
|---------+-----------------------------------------------|
| ~m e $~ | put point at the end of the line and evaluate |
| ~m e b~ | evaluate buffer                               |
| ~m e e~ | evaluate last expression                      |
| ~m e f~ | evaluate function                             |
| ~m e l~ | evaluate line                                 |
| ~m e r~ | evaluate region                               |

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep -- added that one at someone else's suggestion. Perhaps @yyoncho? Believe it does things like syntax corrections etc. if suggested by language server. Support seems to be pretty recent in cquery, though was able to execute a code action of some description during my brief time playing with ccls.

I've moved it under m l e for now, though open to other suggestions...

Copy link
Contributor

@yyoncho yyoncho Aug 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Execute code action is applying quick fix, e. g. if you are on a string a potential code action is "Extract constant". Possible bindin is "mrea", which will stands for Refactoring -> Execute Action.

;;hierarchy
"hh" #'lsp-describe-thing-at-point
;;jump
"ja" #'spacemacs/lsp-avy-document-symbol
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between jump and goto? I feel like all the jump keybindings should go under goto.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're right. At some point I felt goto was in danger of getting overcrowded and made an artificial distinction between actions with only one possible target (goto) and those with multiple potential targets (jump - lsp-ui-peek). Moved all the j bindings back under g (had to rebind lsp-imenu under m g m as m g i was already bound to goto implementation).

@cormacc cormacc force-pushed the lsp-layer-improvements branch 2 times, most recently from 811f72a to e500b60 Compare August 23, 2018 21:38
See README.org for details

<<amendment 1>>
Updated some keybindings based on CONVENTIONS doc
Corrected file headers
Incorporated some immediate feedback from MaskRay

<<amendment 2>>
Corrected keybindings in README.org

<<amendment 3>>
Eliminated stray org-mode tag at table foot in README.org
Eliminated new 'l' prefix and moved bindings under 'g'

<<amendment 4>>
Updated defaults in config.el based on feedback from sebastiencs (lsp/lsp-ui dev)
- lsp-ui-sideline enabled by default
- lsp-ui-peek-expand-by-default disabled

<<amendment 5 09/04/18>>
Removed 'spacemacs/' prefix from lsp-format-buffer binding

<<amendment 6 09/04/18>>
Moved lsp-ui-peek bindings under j (jump)
Added goto bindings for new lsp-mode functions goto type definition and goto implementation

<<amendment 7 31/05/18>>
Corrected layer title in file headers
Rebased on dev tip (390462e)

<<amendment 8 03/07/18>>
Added keybindings for lsp-describe-thing-at-point,
lsp-workspace-restart, lsp-execute-code-action suggested by Yyoncho (LSP
Java)
Added avy keyboard navigation function provided by MaskRay
Reverted lsp-ui-peek to expand by default after an upstream change that
restricts expansion to current document, addressing the previous
performance issue.

<<amendment 9 04/07/18>>
Corrected keybinding for lsp-describe-thing-at-point

<<amendment 10 19/07/18>>
Rebound lsp-restart-workspace under mlq
Declared 'lsp' prefix (myrgy)
Added evil-set-command-property fix suggested by Yyoncho
Moved lsp-c-c++ layer from private branch to this PR after spending too
many hours of my life rebasing after circle CI picks up a formatting
error :)

<<amendment 11 25/07/18>>
Rebased
Bound cquery-freshen-index under lf
Bound cquery-preprocess-file under lp

<<amendment 12 01/08/18>>
Rebased
(c-c++ layer) moved semantic refactor refactor-at-point binding from mr
to mrp to prevent key binding error when semantic layer enabled

<<amendment 13 17/08/18>>
Added option to select ccls or cquery backend based on work by myrgy
Rebased on current upstream develop

<<amendment 14 20/08/18>>
Incorporated feedback from myrgy and maskray.
Corrected some duplication/inconsistencies.
Rebased.

<<amendment 15 21/08/18>>
Reduced duplication in backend config

<<amendment 16 22/08/18>>
Removed lsp-c-c++ layer example -- to be merged with c-c++ layer once
this PR is sorted

<<amendment 17 23/08/18>>
Added CHANGELOG.develop entry as per updated contribution guidelines.

<<amendment 18 24/08/18>>
Moved some keybindings as per feedback from sdwolfz
@cormacc
Copy link
Contributor Author

cormacc commented Aug 23, 2018

Made requested changes and rebased on develop branch tip.

@sdwolfz sdwolfz merged commit c122eb6 into syl20bnr:develop Aug 23, 2018
@sdwolfz
Copy link
Collaborator

sdwolfz commented Aug 23, 2018

Thank you ❤️!
Cherry-picked into develop branch, you can safely delete your branch.

@cormacc
Copy link
Contributor Author

cormacc commented Aug 23, 2018

Thanks @sdwolfz! Minor issue though - just realised a few minutes ago that moving the binding for spacemacs/lsp-avy-document-symbol from m j a to m g a was a bad idea, as it conflicts with the m g a standard for alternate file used in c layers. I'd pushed another commit amendment before noticing you'd already merged -- rebound under m g k (k for keyboard navigation). Can you pull that amendment across, or would you rather I raised a new PR?

@sdwolfz
Copy link
Collaborator

sdwolfz commented Aug 23, 2018

@cormacc It's better if you open up a new PR.

By the way it looks like you associated the commit with the cormaccannon user, is that intentional? There's no problem about it but you won't get credit for it in GitHub's statistics.

@cormacc
Copy link
Contributor Author

cormacc commented Aug 23, 2018

Grand -- raised #11203
No idea how I associated the commit with that other account. Had forgotten it existed (was empty), but I've deleted it now :)
Thanks for the help -- it'll be next week before I get back to the c-c++ layer -- house guests arriving tomorrow.

"Define key bindings for the specific MODE."
(spacemacs/declare-prefix-for-mode mode "m=" "format")
(spacemacs/declare-prefix-for-mode mode "mg" "goto")
(spacemacs/declare-prefix-for-mode mode "mh" "hierarchy")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this shouldn't be here since only small part of the LSP server provide hierarchy support. Also, as per CONVENTIONS.org "mh" stands for help. I am voting to remove this line out of base layer and maybe use "mH" for hierarchy in C++ mode. @sdwolfz what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've no objections, but maybe move this discussion over to #11203 (which I'll re-title) as this PR is now closed

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

Successfully merging this pull request may close these issues.