mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 15:45:08 +00:00
Customization rework
parent
7d3331477a
commit
1f66c28189
@ -1,151 +1,285 @@
|
|||||||
You need to configure your language client plugin to send initialization options to the ccls process (the language server).
|
There are four possible ways to customize the behavior of the `ccls` server.
|
||||||
|
|
||||||
Each language client has its own way to specify initialization options.
|
1. The `ccls` server [command line](#command-line).
|
||||||
ccls (server-side) supports the command line option `--init` to override client-side initialization options:
|
1. The [`.ccls` file](#ccls-file), if it exists.
|
||||||
|
1. The [`compile_commands.json` file](#compile_commandsjson-file), if it exists.
|
||||||
|
1. [Initialization options](#initialization-options)
|
||||||
|
|
||||||
* zsh: `--init='{"index": {"comments": 2}}'`
|
## Command Line
|
||||||
|
|
||||||
## `cacheDirectory`
|
By default, the `ccls` server will run as a daemon waiting for clients to send
|
||||||
|
requests. The `ccls` server will accept these command-line options:
|
||||||
|
|
||||||
|
#### `-h` / `--help`
|
||||||
|
|
||||||
|
Show help. The server is not started.
|
||||||
|
|
||||||
|
#### `--index=<root>`
|
||||||
|
|
||||||
|
Stand-alone mode: index the entire project at `<root>` then exit.
|
||||||
|
|
||||||
|
#### `--init=<json>`
|
||||||
|
|
||||||
|
A JSON string `<json>` containing [initialization options](#initialization-options).
|
||||||
|
|
||||||
|
#### `--log-file=<file>` / `--log-file-append=<file>`
|
||||||
|
|
||||||
|
Write logging to `<file>` / append logging to `<file>`
|
||||||
|
|
||||||
|
#### `-v=<N>`
|
||||||
|
|
||||||
|
Set the logging verbosity level to `<N>`. Currently only `1` is supported: it
|
||||||
|
will show the compiler arguments used to index files.
|
||||||
|
|
||||||
|
## Initialization Options
|
||||||
|
|
||||||
|
Each language client may have its own way to specify initialization options.
|
||||||
|
Also, initialization options can be specified on the `ccls` command line using
|
||||||
|
the [`--init` option](#--initjson).
|
||||||
|
|
||||||
|
#### `cacheDirectory`
|
||||||
|
|
||||||
Default: `".ccls-cache"`
|
Default: `".ccls-cache"`
|
||||||
|
|
||||||
If your project is `/a/b`, cache directories will be created at `/a/b/.ccls-cache/@a@b/` (files under the project root) `/a/b/.ccls-cache/@@a@b/` (files outside the project root, e.g. `/usr/include/stdio.h`).
|
If your project is `/a/b`, cache directories will be created at
|
||||||
|
`/a/b/.ccls-cache/@a@b/` (files under the project root)
|
||||||
|
`/a/b/.ccls-cache/@@a@b/` (files outside the project root,
|
||||||
|
e.g. `/usr/include/stdio.h`).
|
||||||
|
|
||||||
This can also be an absolute path. Because the project path is encoded with `@`, cache directories of different projects will not conflict. When ccls is started, it will try loading cache files if they are not stale (compile command line matches and timestamps of main source and its `#include` (direct and transitive) dependencies do not change).
|
This can also be an absolute path. Because the project path is encoded with
|
||||||
|
`@`, cache directories of different projects will not conflict.
|
||||||
|
|
||||||
If empty, cache will be stored in memory. Every time a file is re-indexed, the cache will be written to the disk. Use this if you don't want to write cache files.
|
When ccls is started, it will try loading cache files if they are not stale
|
||||||
|
(compile command line matches and timestamps of main source and its `#include`
|
||||||
|
(direct and transitive) dependencies do not change).
|
||||||
|
|
||||||
## `cacheFormat`: serialization format of cache files
|
If the argument is an empty string, the cache will be stored only in memory.
|
||||||
|
Use this if you don't want to write cache files.
|
||||||
|
|
||||||
Default: `"binary"`, a compact binary serialization format.
|
Example: `{"cacheDirectory": "/work/cache/ccls"}`
|
||||||
|
|
||||||
Use
|
#### `cacheFormat`
|
||||||
```javascript
|
|
||||||
{ "cacheFormat": "json" }
|
|
||||||
```
|
|
||||||
if you want to inspect the cache file (`IndexFile`), e.g. `jq . < /tmp/ccls/@tmp@c/a.cc.json`
|
|
||||||
|
|
||||||
## `clang.extraArgs` `clang.excludeArgs`
|
Default: `"binary"`
|
||||||
|
|
||||||
Additional arguments or excluded arguments for `compile_commands.json` entries.
|
Specify the format of the cached index files. Binary is a compact binary
|
||||||
You may use `clang.excludeArgs` to exclude GCC specific options that are unknown to clang.
|
serialization format.
|
||||||
|
|
||||||
## `clang.pathMappings`
|
If you would like to inspect the contents of the cache you can change this to
|
||||||
|
`"json"` then use a JSON formatter such as `jq . < /tmp/ccls/@tmp@c/a.cc.json`
|
||||||
|
to display it.
|
||||||
|
|
||||||
If cache files were built with project root `/tmp/container/proj`, and you want to reuse them with a different project root `/host/proj`:
|
Example: `{"cacheFormat": "json"}`
|
||||||
```javascript
|
|
||||||
{ "clang": { "pathMappings": ["/container/:/host/"] }
|
|
||||||
```
|
|
||||||
|
|
||||||
Copy cache files:
|
#### `clang.extraArgs` / `clang.excludeArgs`
|
||||||
```zsh
|
|
||||||
|
Default: _empty_
|
||||||
|
|
||||||
|
Additional arguments or excluded arguments for `compile_commands.json`
|
||||||
|
entries.
|
||||||
|
|
||||||
|
If your compiler is not Clang and it supports arguments which Clang doesn't
|
||||||
|
understand, then you can use `clang.excludeArgs` to remove those arguments
|
||||||
|
when indexing.
|
||||||
|
|
||||||
|
Conversely, you can add more arguments using `clang.extraArgs` (this could
|
||||||
|
also be done through the `.ccls` file).
|
||||||
|
|
||||||
|
Example: `{"clang": {"excludeArgs": "-frounding-math"}}`
|
||||||
|
|
||||||
|
#### `clang.pathMappings`
|
||||||
|
|
||||||
|
Default: _empty_
|
||||||
|
|
||||||
|
A list of `<src>:<dest>` path conversions used to remap the paths of files in
|
||||||
|
the project. This can be used to move a project to a new location without
|
||||||
|
re-indexing.
|
||||||
|
|
||||||
|
If cache files were built with project root `/tmp/container/proj`, and you
|
||||||
|
want to reuse them with a different project root `/tmp/host/proj` then copy the
|
||||||
|
cache:
|
||||||
|
|
||||||
|
```sh
|
||||||
rsync -a /tmp/ccls/@tmp@container@proj/ /tmp/ccls/@tmp@host@proj/ # files under project root
|
rsync -a /tmp/ccls/@tmp@container@proj/ /tmp/ccls/@tmp@host@proj/ # files under project root
|
||||||
rsync -a /tmp/ccls/@@tmp@container@proj/ /tmp/ccls/@@tmp@host@proj/ # files outside of project root
|
rsync -a /tmp/ccls/@@tmp@container@proj/ /tmp/ccls/@@tmp@host@proj/ # files outside of project root
|
||||||
```
|
```
|
||||||
|
|
||||||
Open `/tmp/host/proj/a.cc`, the cache file `/tmp/ccls/@tmp@host@proj/a.cc.blob` will be reused. When `a.cc` is saved (re-indexed), the newly generated `a.cc.blob` will not contain `/tmp/container` paths any more.
|
Then use the initialization option `{"clang": {"pathMappings":
|
||||||
|
["/container/:/host/"]}`
|
||||||
|
|
||||||
## `client.snippetSupport`
|
When `ccls` indexes `/tmp/host/proj/a.cc`, the cache file
|
||||||
|
`/tmp/ccls/@tmp@host@proj/a.cc.blob` will be reused. When `a.cc` is saved
|
||||||
|
(re-indexed), the newly generated `a.cc.blob` will not contain
|
||||||
|
`/tmp/container` paths any more.
|
||||||
|
|
||||||
LSP snippets in completion items are enabled if this option is true and the client announces that it supports it (`capabilities.textDocument.completionItem.snippetSupport`). If your client supports LSP snippets but you don't like them, set the option to false.
|
#### `clang.resourceDir`
|
||||||
|
|
||||||
## `diagnostics.onOpen: 0` `diagnostics.onChange: 1000` `diagnostics.onSave: 0`
|
Default: _empty_
|
||||||
|
|
||||||
Time to wait before computing diagnostics for `textDocument/{didOpen,didChange,didSave}`.
|
Use the path provided as the Clang resource directory rather the default. See
|
||||||
|
[Clang Resource Directory](Install#clang-resource-directory) for more
|
||||||
|
information.
|
||||||
|
|
||||||
By default:
|
#### `client.snippetSupport`
|
||||||
|
|
||||||
* `diagnostics.onOpen: 0`: diagnostics are emitted immediately when a document is opened.
|
Default: `true`
|
||||||
* `diagnostics.onChange: 1000`: after receiving a `textDocument/didChange`, wait up to 1000ms (1s). Changes in this period of time only lead to one computation.
|
|
||||||
* `diagnostics.onSave: 0`: diagnostics are emitted immediately when a document is save.
|
|
||||||
|
|
||||||
Diagnostics require parsing the document. If `diagnostics.onChange: 1000` makes you feel slow, consider:
|
LSP snippets in completion items are enabled if this option is true and the
|
||||||
|
client announces that it supports it
|
||||||
|
(`capabilities.textDocument.completionItem.snippetSupport`). If your client
|
||||||
|
supports LSP snippets but you don't like them, set the option to `false`.
|
||||||
|
|
||||||
```javascript
|
Example: `{"client": {"snippetSupport": false}}`
|
||||||
{ "diagnostics": { "onChange": -1, } }
|
|
||||||
```
|
|
||||||
|
|
||||||
## `index.threads`: number of indexer threads
|
#### `diagnostics.onOpen` / `diagnostics.onChange` / `diagnostics.onSave`
|
||||||
|
|
||||||
If `index.threads` is 0, use `std::thread::hardware_concurrency()`. If you want to control peak memory usage, set it to a small integer.
|
Default: `onOpen`: `0` / `onChange`: `1000` / `onSave`: `0`
|
||||||
|
|
||||||
## `index.comments`: index comments
|
Time (in milliseconds) to wait before computing diagnostics for
|
||||||
|
`textDocument/{didOpen,didChange,didSave}`.
|
||||||
|
|
||||||
- `0`, don't index comments
|
* `diagnostics.onOpen`: How long to wait before diagnostics are emitted when a
|
||||||
- `1`, index Doxygen comment markers
|
document is opened.
|
||||||
- `2`, default, use `-fparse-all-comments` and recognize plain `//` `/* */` besides Doxygen comment markers
|
* `diagnostics.onChange`: after receiving a `textDocument/didChange`, wait up
|
||||||
|
to this long before reporting diagnostics. Changes during this period of
|
||||||
|
time only lead to one computation.
|
||||||
|
* `diagnostics.onSave`: How long to wait before diagnostics are emitted after
|
||||||
|
a document is saved.
|
||||||
|
|
||||||
With the value larger than 0, ccls will index comments associated with functions/types/variables (macros are not handled).
|
Diagnostics require parsing the file. If `diagnostics.onChange: 1000` makes
|
||||||
|
you feel slow, consider `{"diagnostics": {"onChange": 1}}`.
|
||||||
|
|
||||||
This feature requires UI support as multi-line `textDocument/hover` results pose a problem to editors:
|
#### `index.threads`
|
||||||
|
|
||||||
|
Default: `0`
|
||||||
|
|
||||||
|
How many threads to start when indexing a project. `0` means use
|
||||||
|
`std::thread::hardware_concurrency()` (the number of cores the system has).
|
||||||
|
If you want to reduce peak CPU and memory usage, set it to a small integer.
|
||||||
|
|
||||||
|
Example: `{"index": {"threads": 2}}`
|
||||||
|
|
||||||
|
#### `index.comments`
|
||||||
|
|
||||||
|
Default: `2`
|
||||||
|
|
||||||
|
`ccls` can index the contents of comments associated with
|
||||||
|
functions/types/variables (macros are not handled). This value controls how
|
||||||
|
comments are indexed:
|
||||||
|
- `0`: don't index comments
|
||||||
|
- `1`: index Doxygen comment markers
|
||||||
|
- `2`: use `-fparse-all-comments` and recognize plain `//` `/* */` in addition
|
||||||
|
to Doxygen comment markers
|
||||||
|
|
||||||
|
This feature requires UI support as multi-line `textDocument/hover` results
|
||||||
|
pose a problem for some editors:
|
||||||
|
|
||||||
* Emacs
|
* Emacs
|
||||||
+ lsp-ui-doc https://github.com/emacs-lsp/lsp-ui
|
+ lsp-ui-doc https://github.com/emacs-lsp/lsp-ui
|
||||||
+ lsp-mode eldoc See https://github.com/emacs-lsp/lsp-mode/pull/224
|
+ lsp-mode eldoc See https://github.com/emacs-lsp/lsp-mode/pull/224
|
||||||
* Vim
|
* Vim
|
||||||
+ LanguageClient-neovim: preview window
|
+ LanguageClient-neovim: preview window
|
||||||
|
|
||||||
## `index.multiVersion`: index a file in each translation unit that includes it
|
Example: `{"index": {"comments": 1}}`
|
||||||
|
|
||||||
It is 0 by default which is sensible for common usage: it reduces memory footprint.
|
#### `index.multiVersion`
|
||||||
If both `a.cc` and `b.cc` include `a.h`, there is only one indexed version of `a.h`.
|
|
||||||
|
|
||||||
But for dependent name lookup, or references in headers that may change depending on other macros, etc,
|
Default: `0`
|
||||||
you may want to index a file multiple times to get every possible cross reference.
|
|
||||||
Set the option to 1 but be cautious that it may increase index file sizes a lot.
|
|
||||||
You usually want to use `index.multiVersionBlacklist` to exclude system headers.
|
|
||||||
|
|
||||||
```javascript
|
Index a file only once (`0`), or in each translation unit that includes it
|
||||||
{
|
(`1`).
|
||||||
"index": {
|
|
||||||
"multiVersion": 1,
|
|
||||||
"multiVersionBlacklist": ["^/usr/include"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `index.initialBlacklist`
|
The default is sensible for common usage: it reduces memory footprint. If
|
||||||
|
both `a.cc` and `b.cc` include `a.h`, there is only one indexed version of
|
||||||
|
`a.h`.
|
||||||
|
|
||||||
Files that should not be loaded on initialization, but will still be indexed after you open them.
|
But for dependent name lookup, or references in headers that may change
|
||||||
|
depending on other macros, etc, you may want to index a file multiple times to
|
||||||
|
get every possible cross reference. In that case set the option to `1` but be
|
||||||
|
aware that it may increase index file sizes significantly.
|
||||||
|
|
||||||
## `index.onChange`: re-index for every change
|
Also consider using `index.multiVersionBlacklist` to exclude system headers.
|
||||||
|
|
||||||
|
#### `index.multiVersionBlacklist`
|
||||||
|
|
||||||
|
Default: _empty_
|
||||||
|
|
||||||
|
A list of regular expressions matching files that should _not_ be indexed via
|
||||||
|
multi-version if that value is `1`.
|
||||||
|
|
||||||
|
Commonly this is used to avoid indexing system headers multiple times as this
|
||||||
|
is seldom useful.
|
||||||
|
|
||||||
|
Example: `{"index": {"multiVersion": 1, "multiVersionBlacklist": ["^/usr/include"]}}`
|
||||||
|
|
||||||
|
#### `index.initialBlacklist`
|
||||||
|
|
||||||
|
Default: _empty_
|
||||||
|
|
||||||
|
A list of regular expressions matching files that should not be indexed when
|
||||||
|
the `ccls` server starts up, but will still be indexed if a client opens them.
|
||||||
|
If there are areas of the project that you have no interest in indexing you
|
||||||
|
can use this to avoid it unless you visit those files.
|
||||||
|
|
||||||
|
This can also be set to match all files, which is helpful in avoiding massive
|
||||||
|
parsing operations when performing quick edits on large projects.
|
||||||
|
|
||||||
|
Be aware that you will not have access to full cross-referencing information
|
||||||
|
in this situation.
|
||||||
|
|
||||||
|
Example: `{"index": {"initialBlacklist": "."}}` (matches all files)
|
||||||
|
|
||||||
|
#### `index.onChange`
|
||||||
|
|
||||||
Default: `false`
|
Default: `false`
|
||||||
|
|
||||||
A document is re-indexed when saved, updating the global index incrementally.
|
If `false`, a file is re-indexed when saved, updating the global index
|
||||||
If set to `true`, a document is re-indexed for every (unsaved) change. The performance may suffer, but probably convenient for playground projects.
|
incrementally.
|
||||||
|
|
||||||
This is best used in conjunction with empty `cacheDirectory` to avoid writing cache files to disk:
|
If set to `true`, a document is re-indexed for every (unsaved) change.
|
||||||
```javascript
|
Performance may suffer, but it is convenient for playground projects.
|
||||||
{
|
Generally this is best used in conjunction with empty `cacheDirectory` to
|
||||||
"cacheDirectory": "",
|
avoid writing cache files to disk.
|
||||||
"index": {"onChange": true}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## `index.trackDependency`
|
Example: `{"cacheDirectory": "", "index": {"onChange": true}}`
|
||||||
|
|
||||||
Default: 2
|
#### `index.trackDependency`
|
||||||
|
|
||||||
This options controls whether a file should be re-indexed when any of its dependencies changes timestamp.
|
Default: `2`
|
||||||
|
|
||||||
If `a.h` has been changed, when you open `a.cc` which includes `a.h`, an index request will be sent.
|
Determine whether a file should be re-indexed when any of its dependencies
|
||||||
|
changes timestamp.
|
||||||
|
|
||||||
* 0: no re-indexing unless `a.cc` itself changes timestamp.
|
If `a.h` has been changed, when you open `a.cc` which includes `a.h` then if
|
||||||
* 2: the index of `a.cc` is considered stale and it should be re-indexed.
|
`trackDependency` is:
|
||||||
* 1: before the initial load, the behavior of 2 is used, otherwise the behavior of 0 is used.
|
* `0`: no re-indexing unless `a.cc` itself changes timestamp.
|
||||||
|
* `2`: the index of `a.cc` is considered stale and it should be re-indexed.
|
||||||
|
* `1`: before the initial load, the behavior of `2` is used, otherwise the
|
||||||
|
behavior of `0` is used.
|
||||||
|
|
||||||
## `completion.detailedLabel`
|
Example: `{"index": {"trackDependency": 1}}`
|
||||||
|
|
||||||
Default: true
|
#### `completion.detailedLabel`
|
||||||
|
|
||||||
When this option is enabled, `label` `detailed` are repurposed:
|
Default: `true`
|
||||||
|
|
||||||
|
When this option is enabled, `label` and `detailed` are re-purposed:
|
||||||
|
|
||||||
* `label`: detailed function signature, e.g. `foo(int a, int b) -> bool`
|
* `label`: detailed function signature, e.g. `foo(int a, int b) -> bool`
|
||||||
* `detailed`: the name of the parent context, e.g. in `S s; s.<complete>`, the parent context is `S`.
|
* `detailed`: the name of the parent context, e.g. in `S s; s.<complete>`, the
|
||||||
|
parent context is `S`.
|
||||||
|
|
||||||
## `completion.filterAndSort`: completion filtering and sorting
|
Example: `{"completion": {"detailedLabel": false}}`
|
||||||
|
|
||||||
ccls filters and sorts completions to try to be nicer to clients that can't handle big numbers of completion candidates. This behaviour can be disabled by specifying `false` for the option.
|
#### `completion.filterAndSort`
|
||||||
|
|
||||||
This option is the most useful for LSP clients that implement their own filtering and sorting logic.
|
Default: `true`
|
||||||
|
|
||||||
|
`ccls` filters and sorts completions to try to be nicer to clients that can't
|
||||||
|
handle big numbers of completion candidates. This behaviour can be disabled by
|
||||||
|
specifying `false` for the option.
|
||||||
|
|
||||||
|
This option is useful for LSP clients that implement their own filtering and
|
||||||
|
sorting logic.
|
||||||
|
|
||||||
|
Example: `{"completion": {"filterAndSort": false}}`
|
||||||
|
Loading…
Reference in New Issue
Block a user