summaryrefslogtreecommitdiff
path: root/start/lspconfig-0.1.3/doc/lspconfig.txt
blob: d1d9103c5b931afc02771ea31b5b62b8c6b8cb31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
*lspconfig.txt*         For Nvim version 0.6.1+          Last change: 2021 Nov 7
==============================================================================
TABLE OF CONTENTS                                                *lspconfig-toc*

1.  Introduction               (|lspconfig|)
2.  LSP overview               (|lspconfig-lsp|)
3.  Quickstart                 (|lspconfig-quickstart|)
4.  Setup {}                   (|lspconfig-setup|)
5.  Global defaults            (|lspconfig-global-defaults|)
6.  Server configurations      (|lspconfig-configurations|)
      6a.  Adding servers      (|lspconfig-adding-servers|)
7.  Root directories           (|lspconfig-root-detection|)
      7a. Advanced detection   (|lspconfig-root-advanced|)
      7b. Single file support  (|lspconfig-single-file-support|)
8.  Commands                   (|lspconfig-commands|)
9.  Keybindings                (|lspconfig-keybindings|)
10. Completion                 (|lspconfig-completion|)
11. Debugging                  (|lspconfig-debugging|)
12. Logging                    (|lspconfig-logging|)
13. Scope                      (|lspconfig-scope|)

==============================================================================
INTRODUCTION                                                         *lspconfig*

`lspconfig` is a collection of community contributed configurations for the
built-in language server client in Neovim core. This plugin provides four
primary functionalities:

 - default launch commands, initialization options, and settings for each
   server
 - a root directory resolver which attempts to detect the root of your project
 - an autocommand mapping that either launches a new language server or
   attempts to attach a language server to each opened buffer if it falls
   under a tracked project
 - utility commands such as LspInfo, LspStart, LspStop, and LspRestart for
   managing language server instances

`lspconfig` is not required to use the built-in client, it is only one front-end
interface for when a language server specific plugin is not available.

See |lspconfig-server-configurations| by typing `K` over it for the complete
list of language servers configurations.

==============================================================================
LSP OVERVIEW                                                     *lspconfig-lsp*

Nvim supports the Language Server Protocol (LSP) via the built-in language
server client. LSP facilitates many features, some of which include:

- go-to-definition
- find-references
- hover
- completion
- rename
- format
- refactor

These features are implemented in Neovim core, not `lspconfig`. See `:help lsp`
for more details.

NOTE: Feature availability depends on the implementation details of the
server. A server may implement only a subset of these features. Always
consult the server documentation before filing a bug report on a missing
feature.

==============================================================================
QUICKSTART                                                *lspconfig-quickstart*

- ensure the server is installed and executable from the command line

- enable the server in your Neovim configuration (Lua example):
>
    require'lspconfig'.clangd.setup{}
<
- create a new project, ensure that it contains a root marker which matches the
  server requirements specified in |lspconfig-server-configurations|.

- open a file within that project, such as `main.c`.

- If you need more information about a server configuration, read the corresponding
  entry in |lspconfig-server-configurations|.

==============================================================================
THE SETUP METAMETHOD                                           *lspconfig-setup*

`lspconfig` consists of a collection of language server configurations. Each
configuration exposes a `setup {}` metamethod which makes it easy to directly
use the default configuration or selectively override the defaults. 
`setup {}` is the primary interface by which users interact with `lspconfig`.

Using the default configuration for a server is simple:
>
    require'lspconfig'.clangd.setup{}
<
The available server names are listed in |lspconfig-server-configurations| and
match the server name in `config.SERVER_NAME` defined in each configuration's
source file.

The purpose of `setup{}` is to wrap the call to Nvim's built-in 
`vim.lsp.start_client()` with an autocommand that automatically launch a 
language server.

This autocommand calls `start_client()` or `vim.lsp.buf_attach_client()` 
depending on whether the current file belongs to a project with a currently
running client. See |lspconfig-root-detection| for more details.

The `setup{}` function takes a table which contains a superset of the keys
listed in `:help vim.lsp.start_client()` with the following unique entries:

- {root_dir}

    `function(filename, bufnr)`

    Returns either a filepath (string) or nil. The language server will only
    start if the function returns a filepath.

    If a root directory (string) is returned which is unique from any
    previously returned root_dir, a new server will be spawned with that
    root directory. See |lspconfig-root-detection| for more details

- {name}

    `string`

    Defaults to the server's name (`clangd`, `pyright`, etc.).

- {filetypes}

    `list[string] | nil`

    Set of filetypes for which to attempt to resolve {root_dir}.

    May be empty, or server may specify a default value.

- {autostart}

    `bool` (default: true)

    Controls if the `FileType` autocommand that launches a language server is
    created. If `false`, allows for deferring language servers until manually
    launched with `:LspStart` (|lspconfig-commands|).

- {single_file_support}

    `bool` (default: nil)

    Determines if a server is started without a matching root directory.
    See |lspconfig-single-file-support|.

- {on_new_config}

    `function(new_config, new_root_dir)`

    Function executed after a root directory is detected. This is used to
    modify the server configuration (including `cmd` itself). Most commonly,
    this is used to inject additional arguments into `cmd`.

    If overriding `on_new_config`, ensure that you read the
    `on_new_config` defined in the source file of the default configuration
    in `lspconfig`. The original `on_new_config` snippet for a given server
    should likely be included in your new override. Some configurations
    use `on_new_config` to dynamically set or modify `cmd`.

Note: all entries passed to `setup {}` override the entry in the default
configuration. There is no composition.

All `config` elements described in `:help vim.lsp.start_client()` can
additionally be overridden via the `setup {}` call. The most commonly
passed overrides to `setup {}` are:

- {capabilities} `table <string, string|table|bool|function>`

  a table which represents the neovim client capabilities. Useful for
  broadcasting to the server additional functionality (snippets, off-protocol
  features) provided by plugins.

- {cmd} `list[string]`

  a list where each entry corresponds to the blankspace delimited part of
  the command that launches the server. The first entry is the binary used
  to run the language server. Additional entries are passed as arguments.

  The equivalent `cmd` for: 
>
  foo --bar baz
<
  is:
>
  {'foo', '--bar', 'baz}
<
- {handlers} `list[functions]`

  a list of handlers which override the function used to process a response
  from a given language server. Applied only to the server referenced by
  setup. See |lsp-handler|.

- {init_options} `table <string, string|table|bool>`

  a table passed during the initialization notification after launching
  a language server. Equivalent to the `initializationOptions` field found
  in `InitializeParams` in the LSP specification.

  See upstream server documentation for available initialization
  options.

- {on_attach} `function(client, bufnr)`

  Callback invoked by Nvim's built-in client when attaching a buffer to a
  language server. Often used to set Nvim (buffer or global) options or to
  override the Nvim client properties (`resolved_capabilities`) after a
  language server attaches. Most commonly used for settings buffer
  local keybindings. See |lspconfig-keybindings| for a usage example.

- {settings} `table <string, string|table|bool>`  

  The `settings` table is sent in `on_init` via a
  `workspace/didChangeConfiguration` notification from the Nvim client to
  the language server. These settings allow a user to change optional runtime
  settings of the language server. 

  As an example, to set the following settings found in the pyright
  documentation:

  `pyright.disableLanguageServices`: `boolean`
  `pyright.disableOrganizeImports`: `boolean`

  Nested keys need to be translated into a nested table and passed to
  the settings field in `setup {}` as follows:
>
  require('lspconfig').pyright.setup{
    settings = {
      pyright = {
          disableLanguageServices = true,
          disableOrganizeImports  = true,
        }
    }
  }
<
==============================================================================
OVERRIDING GLOBAL DEFAULTS                           *lspconfig-global-defaults*

The global defaults for all servers can be overridden by extending the
`default_config` table.

>
  local lspconfig = require'lspconfig'
  lspconfig.util.default_config = vim.tbl_extend(
    "force",
    lspconfig.util.default_config,
    {
      autostart = false,
      handlers = {
        ["window/logMessage"] = function(err, method, params, client_id)
            if params and params.type <= vim.lsp.protocol.MessageType.Log then
              vim.lsp.handlers["window/logMessage"](err, method, params, client_id)
            end
          end;
        ["window/showMessage"] = function(err, method, params, client_id)
            if params and params.type <= vim.lsp.protocol.MessageType.Warning.Error then
              vim.lsp.handlers["window/showMessage"](err, method, params, client_id)
            end
          end;
      }
    }
  )
<
`setup {}` can additionally override these defaults in subsequent calls.

==============================================================================
SERVER CONFIGURATIONS                                 *lspconfig-configurations*

See |lspconfig-server-configurations| by typing `K` over it for the complete
list of language servers configurations.

While the `setup {}` function is the primary interface to `lspconfig`, for
servers for which there is not a configuration, it is necessary to define a
configuration directly. This can be useful if there is an outstanding PR that
is in review, or when developing a language server that is unavailable
publicly. This can be done through the `configs` module.

The `configs` module is a singleton where configs are defined. The schema for
validating using `vim.validate` is:
>
    configs.SERVER_NAME = {
      default_config = {'t'};
      on_new_config = {'f', true};
      on_attach = {'f', true};
      commands = {'t', true};
      docs = {'t', true};
    }
<
where the structure of the docs table is as follows:
>
    docs = {
      description = {'s', true};
      default_config = {'t', true};
    }
<
`commands` is a map of `name:definition` key:value pairs, where `definition`
is a list whose first value is a function implementing the command, and the
rest are either array values which will be formed into flags for the command,
or special keys like `description`. Example:
>
  commands = {
    TexlabBuild = {
      function()
        buf_build(0)
      end;
      "-range";
      description = "Build the current buffer";
    };
  };
<
The `configs.__newindex` metamethod consumes the config definition and returns
an object with a `setup()` method, to be invoked by users:
>
    require'lspconfig'.SERVER_NAME.setup{}

After you set `configs.SERVER_NAME` you can add arbitrary language-specific
functions to it if necessary.

Example:

>
    configs.texlab.buf_build = buf_build
<
==============================================================================
ADDING NEW SERVERS                                    *lspconfig-adding-servers*

The three steps for adding and enabling a new server configuration are:

- load the `lspconfig` module (note that this is a stylistic choice)
>
   local lspconfig = require 'lspconfig'
<
- define the configuration

>
   local configs = require 'lspconfig.configs'

   -- Check if the config is already defined (useful when reloading this file)
   if not configs.foo_lsp then
     configs.foo_lsp = {
       default_config = {
         cmd = {'/home/neovim/lua-language-server/run.sh'};
         filetypes = {'lua'};
         root_dir = function(fname)
           return lspconfig.util.find_git_ancestor(fname)
         end;
         settings = {};
       };
     }
   end

- call `setup()` to enable the FileType autocmd
>
   lspconfig.foo_lsp.setup{}
<
==============================================================================
ROOT DETECTION                                        *lspconfig-root-detection*
                                                            *lspconfig-root-dir*

A project's `root_dir` is used by `lspconfig` to determine whether `lspconfig`
should start a new server, or attach a previous one, to the current file.

`lspconfig` automatically launches language servers by defining a filetype
autocommand based on the `filetypes` specified in the default configuration of
each server, optionally overridable by the `filetypes` table passed to
`setup`.

This autocommand triggers a search from the current file position in the
filesystem hierarchy up to the top level directory of your filesystem. The
`root_dir` entry of each configuration is a function that returns true if the
current directory in this traversal matches a given root pattern.

The following utility functions are provided by `lspconfig`. Each function call
below returns a function that takes as its argument the current buffer path.

- `util.root_pattern`: function which takes multiple arguments, each 
  corresponding to a different root pattern against which the contents of the
  current directory are matched using |vim.fin.glob()| while traversing up the
  filesystem.
>
   root_dir = util.root_pattern('pyproject.toml', 'requirements.txt')
<
- `util.find_git_ancestor`: a function that locates the first parent directory
  containing a `.git` directory.
>
   root_dir = util.find_git_ancestor

- `util.find_node_modules_ancestor`: a function that locates the first parent
  directory containing a `node_modules` directory.
>
   root_dir = util.find_node_modules_ancestor
<

- `util.find_package_json_ancestor`: a function that locates the first parent
  directory containing a `package.json`.
>
   root_dir = util.find_json_ancestor
<
Note: On Windows, `lspconfig` always assumes forward slash normalized paths with
capitalized drive letters.

==============================================================================
ADVANCED ROOT DIRECTORY DETECTION                      *lspconfig-root-advanced* 
                                                    *lspconfig-root-composition*

The `root_dir` key in `config` and `setup` can hold any function of the form
>
  function custom_root_dir(filename, bufnr)
  returns nil | string
>
This allows for rich composition of root directory patterns which is necessary
for some project structures. Example (for Kotlin):
>
  local root_files = {
    'settings.gradle', -- Gradle (multi-project)
    'settings.gradle.kts', -- Gradle (multi-project)
    'build.xml', -- Ant
    'pom.xml', -- Maven
  }

  local fallback_root_files = {
    'build.gradle', -- Gradle
    'build.gradle.kts', -- Gradle
  }
  root_dir = function(fname)
    local primary = util.root_pattern(unpack(root_files))(fname)
    local fallback = util.root_pattern(unpack(fallback_root_files))(fname)
    return primary or fallback
  end
<
Browsing the source of the default configurations is recommended.

==============================================================================
SINGLE FILE SUPPORT                              *lspconfig-single-file-support*

Language servers require each project to have a `root` in order to provide
features that require cross-file indexing. 

Some servers support not passing a root directory as a proxy for single file
mode under which cross-file features may be degraded.

`lspconfig` offers limited support for an implicit single-file mode by:

- first trying to resolve the root directory pattern
- then, if `single_file_support` is enabled for a given language server
  configuration, starting the server without sending `rootDirectory` or
  `workspaceFolders` during initialization.
- attaching subsequent files in the parent directory to the same server
  instance, depending on filetype.

Cross-file features (navigation, hover) may or may not work depending on the
language server. For a full feature-set, consider moving your files to a
directory with a project structure `lspconfig` can infer.

Note that in the event that the LSP specification is extended to support a
standard for single-file mode, lspconfig will adopt that standard.

==============================================================================
COMMANDS                                                    *lspconfig-commands*

- `:LspInfo` shows the status of active and configured language servers. Note
  that client id refers to the Nvim RPC instance connected to a given
  language server.

The following commands support tab-completion for all arguments. All commands
that require a client id can either leverage tab-completion or the info
contained in `:LspInfo`:

- `:LspStart <config_name>` launches the requested (configured) client, but only
  if it successfully resolves a root directory. Note: Defaults to all
  configured servers matching the current buffer filetype.
- `:LspStop <client_id>` stops the server with the given client id. Defaults to
  stopping all servers active on the current buffer.
- `:LspRestart <client_id>` restarts the client with the given client id, and
  will attempt to reattach to all previously attached buffers.

==============================================================================
EXAMPLE KEYBINDINGS                                      *lspconfig-keybindings*

`lspconfig`, and the core client, do not map any keybindings by default. The
following is an example Lua block which demonstrates how to leverage
`on-attach` to selectively apply keybindings after a language servers has
attached to a given buffer.
>
>
  -- Mappings.
  -- See `:help vim.diagnostic.*` for documentation on any of the below functions
  local opts = { noremap=true, silent=true }
  vim.api.nvim_set_keymap('n', '<space>e', '<cmd>lua vim.diagnostic.open_float()<CR>', opts)
  vim.api.nvim_set_keymap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
  vim.api.nvim_set_keymap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
  vim.api.nvim_set_keymap('n', '<space>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opts)

  -- Use an on_attach function to only map the following keys
  -- after the language server attaches to the current buffer
  local on_attach = function(client, bufnr)
    -- Enable completion triggered by <c-x><c-o>
    vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')

    -- Mappings.
    -- See `:help vim.lsp.*` for documentation on any of the below functions
    vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
    vim.api.nvim_buf_set_keymap(bufnr, 'n', '<space>f', '<cmd>lua vim.lsp.buf.formatting()<CR>', opts)
  end

  -- Use a loop to conveniently call 'setup' on multiple servers and
  -- map buffer local keybindings when the language server attaches
  local servers = { 'pyright', 'rust_analyzer', 'tsserver' }
  for _, lsp in pairs(servers) do
    require('lspconfig')[lsp].setup {
      on_attach = on_attach,
      flags = {
        -- This will be the default in neovim 0.7+
        debounce_text_changes = 150,
      }
    }
  end
<
Note: these keymappings are meant for illustration and override some
infrequently used default mappings.

==============================================================================
COMPLETION SUPPORT                                        *lspconfig-completion*

Manually triggered completion can be provided by Nvim's built-in omnifunc.
See `:help omnifunc` for more details.

For autocompletion, Nvim does not offer built-in functionality at this time.
Consult the `lspconfig` wiki, which provides configuration examples for using a
completion plugin with the built-in client

==============================================================================
DEBUGGING                                                  *lspconfig-debugging*

While using language servers should be easy, debugging issues can be
challenging. First, it is important to identify the source of the issue, which
is typically (in rough order):

- the language server itself
- a plugin
- overrides in a user configuration
- the built-in client in Nvim core
- `lspconfig`

The first step in debugging is to test with a minimal configuration (such as
`../test/minimal_init.lua`). Historically, many users problems are due to
plugins or misconfiguration.

Should that fail, identifying which component is the culprit is challenging.
The following are the only categories of bugs that pertain to `lspconfig`.

- The root directory inferred for your project is wrong, or it should be
  detected but is not due to a bug in the `lspconfig` path utilities.
- The server is launching, but you believe that the default settings,
  initialization options, or command arguments are suboptimal and should be
  replaced based on your understanding of the server documentation.

All bugs Nvim's built-in client should be reported to the Nvim core issue
tracker. All bugs pertaining to plugins should be reported to the respective
plugin. All missing features in a language server should be reported to the
upstream language server issue tracker.

For debugging `lspconfig` issues, the most common hurdles users face are:

  - The language server is not installed or is otherwise not executable.
    `lspconfig` does not install language servers for you. Ensure the `cmd`
    defined in `server_configurations.md` is executable from the command
    line. If the absolute path to the binary is not supplied in `cmd`, ensure
    it is on your PATH.
  - No root detected. `lspconfig` is built around the concept of projects. See
    |lspconfig-root-detection| for more details. Most of the time,
    initializing a git repo will suffice.
  - Misconfiguration. Often users will override `cmd`, `on_init`, or
    `handlers`. Ensure that you debug by using a stock configuration to ensure
    your customizations are not introducing issues.

|LspInfo| provides an overview of your active and configured language servers
which can be useful for debugging.

Note that it will not report any configuration changes applied in
`on_new_config`.

==============================================================================
LOGGING                                                      *lspconfig-logging*

When debugging language servers, it is helpful to enable additional logging in
the built-in client, specifically considering the RPC logs. Example:
>
  vim.lsp.set_log_level 'trace'
  if vim.fn.has 'nvim-0.5.1' == 1 then
    require('vim.lsp.log').set_format_func(vim.inspect)
  end
<
Attempt to run the language server, and open the log with:

>
    :lua vim.cmd('e'..vim.lsp.get_log_path())
<
Note that `ERROR` messages containing `stderr` only indicate that the log was
sent to `stderr`. Many servers counter-intuitively send harmless messages
via stderr.

==============================================================================
SCOPE                                                         *lspconfig-scope*

`lspconfig` is a community effort to create default configurations that fit
within the scope of an official plugin for Nvim. All features that are not
strictly providing default configurations for language servers will be removed
from `lspconfig` in time. The power of the Neovim LSP ecosystem is in the
composability and flexibility of integrating multiple plugins which maximizes
user choice and freedom.

`lspconfig` also opts to adhere strictly to the LSP specification, with some
small allowances when small modifications to a server configuration are
necessary to enable features critical to its usability. For more featureful
options, the `lspconfig` wiki lists community created plugins that build upon
the built-in client to provide functionality tailored to specific language
servers.

==============================================================================

vim:tw=78:ts=8:ft=help:norl: