rust/docs/user
bors[bot] 232785251b
Merge #2061
2061: Theme loading and "editor.tokenColorCustomizations" support. r=matklad a=seivan

Fixes: [Issue#1294](https://github.com/rust-analyzer/rust-analyzer/issues/1294#issuecomment-497450325)

TODO: 
- [x] Load themes
- [x] Load existing `ralsp`-prefixed overrides from `"workbench.colorCustomizations"`.
- [x] Load overrides from `"editor.tokenColorCustomizations.textMateRules"`.
- [x] Use RA tags to load `vscode.DecorationRenderOptions` (colors) from theme & overrides.
- [x] Map RA tags to common TextMate scopes before loading colors.
- [x] Add default scope mappings in extension.
- [x] Cache mappings between settings updates. 
- [x] Add scope mapping configuration manifest in `package.json`
- [x] Load configurable scope mappings from settings.
- [x] Load JSON Scheme for text mate scope rules in settings.
- [x] Update [Readme](https://github.com/seivan/rust-analyzer/blob/feature/themes/docs/user/README.md#settings).

Borrowed the theme loading (`scopes.ts`) from `Tree Sitter` with some modifications to reading `"editor.tokenColorCustomizations"` for merging with loaded themes and had to remove the async portions to be able to load it from settings updates. 

~Just a PoC and an idea I toyed around with a lot of room for improvement.~
For starters, certain keywords aren't part of the standard TextMate grammar, so it still reads colors from the `ralsp` prefixed values in `"workbench.colorCustomizations"`. 

But I think there's more value making the extension work with existing themes by maping some of the decoration tags to existing key or keys. 

<img width="453" alt="Screenshot 2019-11-09 at 17 43 18" src="https://user-images.githubusercontent.com/55424/68531968-71b4e380-0318-11ea-924e-cdbb8d5eae06.png">
<img width="780" alt="Screenshot 2019-11-09 at 17 41 45" src="https://user-images.githubusercontent.com/55424/68531950-4b8f4380-0318-11ea-8f85-24a84efaf23b.png">
<img width="468" alt="Screenshot 2019-11-09 at 17 40 29" src="https://user-images.githubusercontent.com/55424/68531952-51852480-0318-11ea-800a-6ae9215f5368.png">


These will merge with the default ones coming with the extension, so you don't have to implement all of them and works well with overrides defined in settings. 

```jsonc
    "editor.tokenColorCustomizations": {
        "textMateRules": [
            {
                "scope": "keyword",
                "settings": {
                    "fontStyle": "bold",
                }
            },
        ]
    },
```


Edit: The idea is to work with 90% of the themes out there by working within existing scopes available that are generally styled. It's not to say I want to erase the custom Rust scopes - those should still remain and eventually worked into a custom grammar bundle for Rust specific themes that target those, I just want to make it work with generic themes offered on the market place for now. 

A custom grammar bundle and themes for Rust specific scopes is out of... scope for this PR. 
We'll make another round to tackle those issues. 


Current fallbacks implemented

```typescript
    [
        'comment',
        [
            'comment',
            'comment.block',
            'comment.line',
            'comment.block.documentation'
        ]
    ],
    ['string', ['string']],
    ['keyword', ['keyword']],
    ['keyword.control', ['keyword.control', 'keyword', 'keyword.other']],
    [
        'keyword.unsafe',
        ['storage.modifier', 'keyword.other', 'keyword.control', 'keyword']
    ],
    ['function', ['entity.name.function']],
    ['parameter', ['variable.parameter']],
    ['constant', ['constant', 'variable']],
    ['type', ['entity.name.type']],
    ['builtin', ['variable.language', 'support.type', 'support.type']],
    ['text', ['string', 'string.quoted', 'string.regexp']],
    ['attribute', ['keyword']],
    ['literal', ['string', 'string.quoted', 'string.regexp']],
    ['macro', ['support.other']],
    ['variable', ['variable']],
    ['variable.mut', ['variable', 'storage.modifier']],
    [
        'field',
        [
            'variable.object.property',
            'meta.field.declaration',
            'meta.definition.property',
            'variable.other'
        ]
    ],
    ['module', ['entity.name.section', 'entity.other']]
```


Co-authored-by: Seivan Heidari <seivan.heidari@icloud.com>
2019-12-29 16:49:40 +00:00
..
assists.md Fill in type params in 'add missing impl members' assist 2019-12-24 17:29:27 +01:00
features.md Add document in features.md 2019-11-20 01:09:15 +08:00
README.md Merge branch 'master' into feature/themes 2019-12-23 15:35:31 +01:00

The main interface to rust-analyzer is the LSP implementation. To install lsp server, clone the repository and then run cargo xtask install --server (which is shorthand for cargo install --path ./crates/ra_lsp_server). This will produce a binary named ra_lsp_server which you should be able to use it with any LSP-compatible editor. We use custom extensions to LSP, so special client-side support is required to take full advantage of rust-analyzer. This repository contains support code for VS Code and Emacs.

$ git clone git@github.com:rust-analyzer/rust-analyzer && cd rust-analyzer
$ cargo xtask install --server

Rust Analyzer needs sources of rust standard library to work, so you might also need to execute

$ rustup component add rust-src

See ./features.md document for a list of features that are available.

VS Code

Prerequisites:

In order to build the VS Code plugin, you need to have node.js and npm with a minimum version of 10 installed. Please refer to node.js and npm documentation for installation instructions.

You will also need the most recent version of VS Code: we don't try to maintain compatibility with older versions yet.

The experimental VS Code plugin can then be built and installed by executing the following commands:

$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
$ cd rust-analyzer
$ cargo xtask install

The automatic installation is expected to just work for common cases, if it doesn't, report bugs!

If you have an unusual setup (for example, code is not in the PATH), you should adapt these manual installation instructions:

$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
$ cd rust-analyzer
$ cargo install --path ./crates/ra_lsp_server/ --force --locked
$ cd ./editors/code
$ npm install
$ ./node_modules/vsce/out/vsce package
$ code --install-extension ./ra-lsp-0.0.1.vsix

It's better to remove existing Rust plugins to avoid interference.

Beyond basic LSP features, there are some extension commands which you can invoke via Ctrl+Shift+P or bind to a shortcut. See ./features.md for details.

For updates, pull the latest changes from the master branch, run cargo xtask install again, and restart VS Code instance. See microsoft/vscode#72308 for why a full restart is needed.

VS Code Remote

You can also use rust-analyzer with the Visual Studio Code Remote extensions (Remote SSH, Remote WSL, Remote Containers). In this case, however, you have to manually install the .vsix package:

  1. Build the extension on the remote host using the instructions above (ignore the error if code cannot be found in your PATH: VSCode doesn't need to be installed on the remote host).
  2. In Visual Studio Code open a connection to the remote host.
  3. Open the Extensions View (View > Extensions, keyboard shortcut: Ctrl+Shift+X).
  4. From the top-right kebab menu (···) select Install from VSIX...
  5. Inside the rust-analyzer directory find the editors/code subdirectory and choose the ra-lsp-0.0.1.vsix file.
  6. Restart Visual Studio Code and re-establish the connection to the remote host.

In case of errors please make sure that ~/.cargo/bin is in your PATH on the remote host.

Settings

  • rust-analyzer.highlightingOn: enables experimental syntax highlighting.
  • rust-analyzer.scopeMappings -- a scheme backed JSON object to tweak Rust Analyzer scopes to TextMate scopes.
     {
         //Will autocomplete keys to available RA scopes. 
         "keyword.unsafe": ["keyword", "keyword.control"],
         //Values are string | TextMateScope | [string | TextMateScope]
         "variable.mut": "variable"
     }
    
  • rust-analyzer.enableEnhancedTyping: by default, rust-analyzer intercepts Enter key to make it easier to continue comments. Note that it may conflict with VIM emulation plugin.
  • rust-analyzer.raLspServerPath: path to ra_lsp_server executable
  • rust-analyzer.enableCargoWatchOnStartup: prompt to install & enable cargo watch for live error highlighting (note, this does not use rust-analyzer)
  • rust-analyzer.excludeGlobs: a list of glob-patterns for exclusion (see globset docs for syntax). Note: glob patterns are applied to all Cargo packages and a rooted at a package root. This is not very intuitive and a limitation of a current implementation.
  • rust-analyzer.useClientWatching: use client provided file watching instead of notify watching.
  • rust-analyzer.cargo-watch.command: cargo-watch command. (e.g: clippy will run as cargo watch -x clippy )
  • rust-analyzer.cargo-watch.arguments: cargo-watch check arguments. (e.g: --features="shumway,pdf" will run as cargo watch -x "check --features="shumway,pdf"" )
  • rust-analyzer.cargo-watch.ignore: list of patterns for cargo-watch to ignore (will be passed as --ignore)
  • rust-analyzer.trace.server: enables internal logging
  • rust-analyzer.trace.cargo-watch: enables cargo-watch logging
  • RUST_SRC_PATH: environment variable that overwrites the sysroot
  • rust-analyzer.featureFlags -- a JSON object to tweak fine-grained behavior:
    {
        // Show diagnostics produced by rust-analyzer itself.
        "lsp.diagnostics": true,
        // Automatically insert `()` and `<>` when completing functions and types.
        "completion.insertion.add-call-parenthesis": true,
        // Enable completions like `.if`, `.match`, etc.
        "completion.enable-postfix": true,
        // Show notification when workspace is fully loaded
        "notifications.workspace-loaded": true,
    }
    

Emacs

Prerequisites:

emacs-lsp, dash and ht packages.

Installation:

  • add ra-emacs-lsp.el to load path and require it in init.el
  • run lsp in a rust buffer
  • (Optionally) bind commands like rust-analyzer-join-lines, rust-analyzer-extend-selection and rust-analyzer-expand-macro to keys, and enable rust-analyzer-inlay-hints-mode to get inline type hints

Vim and NeoVim (coc-rust-analyzer)

  • Install coc.nvim by following the instructions at coc.nvim (nodejs required)
  • Run :CocInstall coc-rust-analyzer to install coc-rust-analyzer, this extension implements most of the features supported in the VSCode extension:
    • same configurations as VSCode extension, rust-analyzer.raLspServerPath, rust-analyzer.enableCargoWatchOnStartup etc.
    • same commands too, rust-analyzer.analyzerStatus, rust-analyzer.startCargoWatch etc.
    • highlighting and inlay_hints are not implemented yet

Vim and NeoVim (LanguageClient-neovim)

  • Install LanguageClient-neovim by following the instructions here

    • The github project wiki has extra tips on configuration
  • Configure by adding this to your vim/neovim config file (replacing the existing rust specific line if it exists):

let g:LanguageClient_serverCommands = {
\ 'rust': ['ra_lsp_server'],
\ }

NeoVim (nvim-lsp)

NeoVim 0.5 (not yet released) has built in language server support. For a quick start configuration of rust-analyzer, use neovim/nvim-lsp. Once neovim/nvim-lsp is installed, you can use call nvim_lsp#setup("rust_analyzer", {}) or lua require'nvim_lsp'.rust_analyzer.setup({}) to quickly get set up.

Sublime Text 3

Prequisites:

LSP package.

Installation:

  • Invoke the command palette with Ctrl+Shift+P
  • Type LSP Settings to open the LSP preferences editor
  • Add the following LSP client definition to your settings:
"rust-analyzer": {
    "command": ["ra_lsp_server"],
    "languageId": "rust",
    "scopes": ["source.rust"],
    "syntaxes": [
        "Packages/Rust/Rust.sublime-syntax",
        "Packages/Rust Enhanced/RustEnhanced.sublime-syntax"
    ],
    "initializationOptions": {
      "featureFlags": {
      }
    },
}
  • You can now invoke the command palette and type LSP enable to locally/globally enable the rust-analyzer LSP (type LSP enable, then choose either locally or globally, then select rust-analyzer)

Setting up the PATH variable

On Unix systems, rustup adds ~/.cargo/bin to PATH by modifying the shell's startup file. Depending on your configuration, your Desktop Environment might not actually load it. If you find that rust-analyzer only runs when starting the editor from the terminal, you will have to set up your PATH variable manually.

There are a couple of ways to do that:

  • for Code, set rust-analyzer.raLspServerPath to ~/.cargo/bin (the ~ is automatically resolved by the extension)
  • copy the binary to a location that is already in PATH, e.g. /usr/local/bin
  • on Linux, use PAM to configure the PATH variable, by e.g. putting PATH DEFAULT=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:@{HOME}/.cargo/bin:@{HOME}/.local/bin in your ~/.pam_environment file; note that this might interfere with other defaults set by the system administrator via /etc/environment.