Code Monkey home page Code Monkey logo

kak-lsp's Introduction

Kakoune Language Server Protocol Client

This is a Language Server Protocol client for the Kakoune editor.

Quick Start

Installing

Pre-built binaries

MacOS
Homebrew
brew install kakoune-lsp/kakoune-lsp/kakoune-lsp
Manual
curl -O -L https://github.com/kakoune-lsp/kakoune-lsp/releases/download/v17.0.1/kakoune-lsp-v17.0.1-x86_64-apple-darwin.tar.gz
tar xzvf kakoune-lsp-v17.0.1-x86_64-apple-darwin.tar.gz

# replace `~/.local/bin/` with something on your `$PATH`
mv kak-lsp ~/.local/bin/

# optional: if you want to use specific language servers
mkdir -p ~/.config/kak-lsp
mv kak-lsp.toml ~/.config/kak-lsp/
Linux
Package managers
  • Arch Linux: pacman -S kakoune-lsp or AUR/kak-lsp-git

  • Fedora Copr: sudo dnf copr enable atim/kakoune -y && sudo dnf install kakoune-lsp

  • Void Linux: xbps-install -S kak-lsp

Others
wget https://github.com/kakoune-lsp/kakoune-lsp/releases/download/v17.0.1/kakoune-lsp-v17.0.1-x86_64-unknown-linux-musl.tar.gz
tar xzvf kak-lsp-v17.0.1-x86_64-unknown-linux-musl.tar.gz

# replace `~/.local/bin/` with something on your `$PATH`
mv kak-lsp ~/.local/bin/

# optional: if you want to use specific language servers
mkdir -p ~/.config/kak-lsp
mv kak-lsp.toml ~/.config/kak-lsp/

From source

Generally, you need the latest stable version of Rust to build kakoune-lsp.

git clone https://github.com/kakoune-lsp/kakoune-lsp
cd kakoune-lsp

# this installs the kak-lsp binary to ~/.cargo/bin, which must be in your `$PATH`
cargo install --locked --force --path .

# optional: if you want to use specific language servers
mkdir -p ~/.config/kak-lsp
cp kak-lsp.toml ~/.config/kak-lsp/

With plug.kak

If you don’t mind using a plugin manager, you can install kakoune-lsp via plug.kak. Add this code to your kakrc:

plug "kakoune-lsp/kakoune-lsp" do %{
    cargo install --locked --force --path .
    # optional: if you want to use specific language servers
    mkdir -p ~/.config/kak-lsp
    cp -n kak-lsp.toml ~/.config/kak-lsp/
}

cargo install will install the kak-lsp binary to ~/.cargo/bin, which must be in your $PATH. Alternatively, you can replace cargo install with cargo build --release && ln -sf $PWD/target/release/kak-lsp ~/.local/bin/ where ~/.local/bin/ can be replaced with something in your $PATH.

Examples of configuration with plug.kak can be found at Wiki.

Install language servers for your desired languages

kakoune-lsp doesn’t manage installation of language servers, please install them by yourself for the languages you plan to use kakoune-lsp with. Please consult the How to install servers wiki page for quick installation of language servers supported by kakoune-lsp out of the box.

Configure Kakoune to enable LSP

To enable LSP support for configured languages (see Configuration) just add the following commands to your kakrc:

eval %sh{kak-lsp --kakoune -s $kak_session}  # Not needed if you load it with plug.kak.
lsp-enable

A bit more involved but recommended way is to enable LSP only for specific filetypes you need via lsp-enable-window, e.g.:

eval %sh{kak-lsp --kakoune -s $kak_session}  # Not needed if you load it with plug.kak.
hook global WinSetOption filetype=(rust|python|go|javascript|typescript|c|cpp) %{
    lsp-enable-window
}

Configure mappings

There are three default mappings in goto-mode: gd (lsp-definition), gy (lsp-type-definition) and gr (lsp-references). You can override them in your kakrc after this plugin is loaded.

Here are additional recommended mappings. See below for the meaning of each command.

map global user l %{:enter-user-mode lsp<ret>} -docstring "LSP mode"
map global insert <tab> '<a-;>:try lsp-snippets-select-next-placeholders catch %{ execute-keys -with-hooks <lt>tab> }<ret>' -docstring 'Select next snippet placeholder'
map global object a '<a-semicolon>lsp-object<ret>' -docstring 'LSP any symbol'
map global object <a-a> '<a-semicolon>lsp-object<ret>' -docstring 'LSP any symbol'
map global object f '<a-semicolon>lsp-object Function Method<ret>' -docstring 'LSP function or method'
map global object t '<a-semicolon>lsp-object Class Interface Struct<ret>' -docstring 'LSP class interface or struct'
map global object d '<a-semicolon>lsp-diagnostic-object --include-warnings<ret>' -docstring 'LSP errors and warnings'
map global object D '<a-semicolon>lsp-diagnostic-object<ret>' -docstring 'LSP errors'

Usage

Note
Contents below corresponds to the master branch HEAD and could be slightly out-of-sync with the version installed from pre-built binaries. The most common case is new commands being in a pre-release testing stage. Please refer to the README.asciidoc revision tagged with the version you use or the README.asciidoc from the release archive.

If you have followed above steps you get

  • completions

  • lsp-definition command to go to definition, mapped to gd by default

  • lsp-hover command to show hover info (including relevant diagnostics when available) in the info box.

    • lsp-hover-buffer command to show the same in a scratch buffer.

    • to automatically show hover when you move around, use lsp-auto-hover-enable or lsp-auto-hover-buffer-enable.

    • to show hover anchored to hovered position, use set global lsp_hover_anchor true

    • to exclude diagnostics, use set-option global lsp_show_hover_format 'printf %s "${lsp_info}"'

  • lsp-declaration command to jump to the declaration of the symbol under the main cursor

  • lsp-definition command to jump to the definition of the symbol under the main cursor

  • lsp-type-definition command to jump to the definition of the type of the symbol under the main cursor, mapped to gy by default

  • lsp-implementation command to find implementations for the symbol under the main cursor

  • lsp-references command to find references to the symbol under the main cursor, mapped to gr by default

    • for the previous five commands, the *goto* buffer has filetype lsp-goto, so you can press <ret> on a line or use the jump command

  • lsp-find-error command to jump to the next or previous error in the current file

    • lsp-selection-range command to quickly select interesting ranges around selections.

    • lsp-selection-range-select to navigate ranges fetched by lsp-selection-range.

    • A polyfill of Kakoune’s jump- commands to jump to the next or previous location listed in a buffer with the lsp-goto filetype. These also work for buffers \*grep, *lint* and *make*

  • lsp-highlight-references command to select (unless run in a hook context) all references to the symbol under the main cursor in the current buffer and highlight them with the Reference face (which is equal to the MatchingChar face by default)

  • lsp-document-symbol command to list the current buffer’s symbols in a buffer of type lsp-document-symbol

  • lsp-goto-document-symbol command to jump to one of the current buffer’s symbols

  • lsp-workspace-symbol command to list project-wide symbols matching the query

  • lsp-workspace-symbol-incr command to incrementally list project-wide symbols matching the query

    • *symbols* buffer has filetype lsp-goto so you can press <ret> on a line or use the jump command

  • lsp-diagnostics command to list project-wide diagnostics (current buffer determines project and language to collect diagnostics for)

    • *diagnostics* buffer has filetype lsp-diagnostics so you can press <ret> on a line or use the jump command

  • lsp-incoming-calls and lsp-outgoing-calls commands to list callers and callees of the function at the cursor.

    • *callers* and *callees* buffers have filetype lsp-goto so you can press <ret> on a line or use the jump command

  • lsp-signature-help command to show signature information of the function under the main cursor

    • To automatically show signature information in insert mode, use lsp-auto-signature-help-enable.

  • inline diagnostics highlighting using the DiagnosticError, DiagnosticHint, DiagnosticInfo and DiagnosticWarning faces; can be disabled with lsp-inline-diagnostics-disable command

  • flags in the left margin on lines with errors or other diagnostics; can be disabled with lsp-diagnostic-lines-disable command

  • for lines with code lenses, a > flag which can be customized via the lsp_code_lens_sign option

  • lsp-code-lens command to execute a code lens from the current selection

  • commands lsp-inlay-code-lenses-enable and lsp-inlay-code-lenses-disable to toggle rendering of code lenses.

  • You can change the code lenses' face with set-face global InlayCodeLens <face>.

  • lsp-formatting command to format current buffer, according to the tabstop and lsp_insert_spaces options

  • lsp-formatting-sync command to format current buffer synchronously, suitable for use with BufWritePre hook:

hook global WinSetOption filetype=rust %{
    hook window BufWritePre .* lsp-formatting-sync
}
  • lsp-object command to select adjacent or surrounding syntax tree nodes in [object mode](https://github.com/mawww/kakoune/blob/master/doc/pages/modes.asciidoc#object-mode)

    • lsp-diagnostic-object does something similar but for inline diagnostics.

  • lsp-next-symbol and lsp-previous-symbol command to go to the buffer’s next and current/previous symbol.

  • lsp-hover-next-symbol and lsp-hover-previous-symbol to show hover of the buffer’s next and current/previous symbol.

  • lsp-rename <new_name> and lsp-rename-prompt commands to rename the symbol under the main cursor.

  • Breadcrumbs in the modeline indicating the symbol around the main cursor, like (somemodule > someclass > somefunction).

    • To implement this, kakoune-lsp adds %opt{lsp_modeline} ` to the front of your global `modelinefmt at load time.

  • An hourglass character (⌛) in the modeline whenever the language server indicates it’s busy.

    • To customize this behavior, override lsp-handle-progress.

  • If lsp_auto_show_code_actions is true, a lightbulb (💡) in the modeline whenever code actions are available at the main cursor position

    • To customize the lightbulb, you can override lsp-show-code-actions and lsp-hide-code-actions

  • lsp-code-actions to open a menu to choose a code action to run

    • To customize the menu, you can override lsp-perform-code-action

  • lsp-code-action to run the code action matching the given pattern.

  • lsp-code-action-sync to synchronously run that code action, suitable for use in a BufWritePre hook.

  • lsp_diagnostic_error_count, lsp_diagnostic_hint_count, lsp_diagnostic_info_count and lsp_diagnostic_warning_count options which contain the number of diagnostics of the respective level for the current buffer. For example, you can put it into your modeline to see at a glance if there are errors in the current file

  • starting new kak-lsp session when Kakoune session begins and stopping it when Kakoune session ends

  • lsp-execute-command command to execute server-specific commands (listed by lsp-capabilities).

  • Commands starting with either of ccls-, clangd-, ejdtls-, texlab- or rust-analyzer-, that provide server specific features.

Note
By default, kak-lsp exits when it doesn’t receive any request from Kakoune for 30 minutes, even if the Kakoune session is still up and running. Change server.timeout in kak-lsp.toml to tweak this duration, or set it to 0 to disable this behavior. In any scenario, a new request would spin up a fresh server if it is down.
  • lsp user mode with the following default mappings:

Binding Command

a

lsp-code-actions

c

lsp-capabilities

d

lsp-definition

e

lsp-diagnostics

f

lsp-formatting

h

lsp-hover

i

lsp-implementation

j

lsp-outgoing-calls

k

lsp-incoming-calls

l

lsp-code-lens

r

lsp-references

R

lsp-rename-prompt

s

lsp-goto-document-symbol

S

lsp-document-symbol

o

lsp-workspace-symbol-incr

n

lsp-find-error

p

lsp-find-error --previous

v

lsp-selection-range

y

lsp-type-definition

9

lsp-hover-previous-function

0

lsp-hover-next-function

&

lsp-highlight-references

(

lsp-previous-function

)

lsp-next-function

[

lsp-hover-previous-symbol

]

lsp-hover-next-symbol

{

lsp-previous-symbol

}

lsp-next-symbol

To know which subset of LSP commands is backed by the current buffer’s filetype’s language server use lsp-capabilities command.

Configuration

kakoune-lsp itself has configuration, but it also adds configuration options to Kakoune that affect the Kakoune integration.

Configuring kakoune-lsp

kakoune-lsp is configured via a configuration file in TOML format. By default it tries to read $XDG_CONFIG_HOME/kak-lsp/kak-lsp.toml (which defaults to ~/.config/kak-lsp/kak-lsp.toml) but you can override it with command-line option --config. Look into the default kak-lsp.toml, it should be quite self-explanatory. If you don’t need to change configuration then feel free to skip copying it anywhere as the default configuration is embedded into the kak-lsp binary.

Important: The configuration file does not extend the default configuration, but rather overrides it. This means that if you want to customize any of the configuration, you must copy the entire default configuration and then edit it.

In the language section of kak-lsp.toml, the roots parameter is a list of file globs. Whenever your editor session wants to send an LSP request, the first glob that matches a file in any of the current buffer’s parent directories will cause kakoune-lsp to set the project root to that parent directory.

You can define an environment variable like KAK_LSP_PROJECT_ROOT_RUST=/my/project to always use /my/project as root for Rust files inside /my/project. Substitute RUST with another capitalized language ID to do the same for other file types.

The environment variable KAK_LSP_FORCE_PROJECT_ROOT=/my/project will make kakoune-lsp always use /my/project as project root, even for files outside this directory. This avoids starting separate language servers for files outside /my/project, and ensures that your language server is aware of your project’s build configuration even when navigating library code.

If you are setting any server options via cli, do not forget to append them to %sh{kak-lsp --kakoune …​} in your kakrc. It’s not needed if you change options in ~/.config/kak-lsp/kak-lsp.toml.

Please let us know if you have any ideas about how to make the default config more sensible.

Server-specific configuration

Many servers accept configuration options that are not part of the LSP spec. The TOML table [language_server.<server_name>.settings] holds those configuration options. It has the same structure as the corresponding fragments from VSCode’s settings.json. For example:

[language_server.gopls]
...
settings_section = "gopls" # Optional, defaults to server name.
[language_server.gopls.settings.gopls]
"formatting.gofumpt" = true

During server initialization, kakoune-lsp sends either the section specified by settings_section, or the section with same name as the server; in this case {"formatting.gofumpt":true}. Whenever you change the Kakoune option lsp_config, the same section is sent via workspace/didChangeConfiguration. Additionally, kakoune-lsp will send arbitrary sections that are requested by the server in workspace/configuration.

Language ID ("languageId")

By default, the Kakoune filetype is sent to the server as LSP language ID. To send a different identifier for a given filetype, use the [language_ids] config option, see the example below.

Multiple language servers

It is possible to map more than one language server to a filetype. For example, if you want to set up TSServer and TailwindCSS to use in React projects:

[language_ids]
javascript = "javascriptreact"
typescript = "typescriptreact"

[language_server.tsserver]
filetypes = ["javascript", "typescript"]
roots = ["package.json", "tsconfig.json", "jsconfig.json", ".git", ".hg"]
command = "typescript-language-server"
args = ["--stdio"]

[language_server.tailwindcss]
filetypes = ["javascript", "typescript"]
roots = ["tailwind.config.ts", "tailwind.config.js"]
command = "tailwindcss-language-server"
args = ["--stdio"]
[language_server.tailwindcss.settings.tailwindcss]
editor = {}

Configuring Kakoune

kakoune-lsp declares the following Kakoune options:

  • lsp_completion_trigger (str): This option is set to a Kakoune command, which is executed every time the user pauses in insert mode. If the command succeeds, kakoune-lsp will send a completion request to the language server.

  • lsp_diagnostic_line_error_sign, lsp_diagnostic_line_hint_sign, lsp_diagnostic_line_info_sign, and lsp_diagnostic_line_warning_sign (str): When using lsp-diagnostic-lines-enable and the language server detects an error or another diagnostic, kakoune-lsp will add a flag to the left-most column of the window, using this string and one of the corresponding faces LineFlagError, LineFlagHint, LineFlagInfo or LineFlagWarning.

  • lsp_hover_anchor (bool): When using lsp-hover or lsp-auto-hover-enable, if this option is true then the hover information will be displayed next to the active selection. Otherwise, the information will be displayed in a box in the lower-right corner.

  • lsp_hover_max_info_lines (int): If greater than 0 then limit information in the hover box to the given number of lines. Default is 20.

  • lsp_hover_max_diagnostic_lines (int): If greater than 0 then limit diagnostics in the hover box to the given number of lines. Default is 20.

  • lsp_hover_insert_mode_trigger (str): This option is set to a Kakoune command. When using lsp-auto-hover-insert-mode-enable, this command is executed every time the user pauses in insert mode. If the command succeeds, kakoune-lsp will send a hover-information request for the text selected by the command.

  • lsp_insert_spaces (bool): When using lsp-formatting, if this option is true, kakoune-lsp will ask the language server to indent with spaces rather than tabs.

  • lsp_auto_highlight_references (bool): If this option is true then lsp-highlight-references is executed every time the user pauses in normal mode.

  • lsp_auto_show_code_actions (bool): If this option is true then lsp-code-actions is executed every time the user pauses in normal mode.

  • lsp_config (str): This is a TOML string of the same format as kak-lsp.toml, except it currently only supports one kind of configuration value:

    • [language_server.<server_name>.settings]: this works just like the static configuration of the same name in kak-lsp.toml, see the section about server-specific configuration. This will override the static configuration of the given language server.

For example, you can toggle an option dynamically with a command like this:

set-option global lsp_config %{
    [language_server.gopls.settings.gopls]
    "formatting.gofumpt" = true
}

Inlay hints

Inlay hints are a feature proposed for LSP 3.17 to show inferred types, parameter names in function calls, and the types of chained calls inline in the code. To enable support for it, add the following to your kakrc:

lsp-inlay-hints-enable global

You can change the hints' face with set-face global InlayHint <face>.

Semantic Tokens

kakoune-lsp supports the semanticTokens feature for semantic highlighting. If the language server supports it, you can enable it with:

hook global WinSetOption filetype=<language> %{
  hook window -group semantic-tokens BufReload .* lsp-semantic-tokens
  hook window -group semantic-tokens NormalIdle .* lsp-semantic-tokens
  hook window -group semantic-tokens InsertIdle .* lsp-semantic-tokens
  hook -once -always window WinSetOption filetype=.* %{
    remove-hooks window semantic-tokens
  }
}

The faces used for semantic tokens and modifiers can be modified in kak-lsp.toml, using the semantic_tokens.faces array, for example:

[semantic_tokens]
faces = [
    {face="const_variable_declaration", token="variable", modifiers=["constant", "declaration"]},
]

where face is the face that will be applied in Kakoune (you’ll want to define these in your theme/config), token is the token’s name as reported by the language server (see lsp-capabilities) and modifiers is an array of modifier names (also reported by the language server). modifiers may be omitted, but token and face are required.

You may create any arbitrary number of definitions with permutations between the token names and modifiers reported by the server. For an entry to match a token, all the entry’s modifiers must exist on the token. However, the token may have additional modifiers not assigned in the config entry.
kakoune-lsp will find the most specific matching configuration to apply, where specificity is defined as the number of matching modifiers. If multiple matching entries have the same number of modifiers, the one that was defined last in the configuration wins.

Example:

Assuming the following configuration,

[semantic_tokens]
faces = [
    {face="const_variable_declaration", token="variable", modifiers=["constant","declaration"]},
    {face="const_variable", token="variable", modifiers=["constant"]},
    {face="variable", token="variable"},
]

kakoune-lsp will perform these mappings:

Token Modifiers Face Comment

variable

constant, declaration

const_variable_declaration

First entry matches with 2 modifiers.

variable

constant

const_variable

First and second entry match with 1 modifier, second wins.

variable

declaration

variable

Only third entry matches. First entry doesn’t match, because constant is missing.

variable

variable

Third entry matches.

function

No entries match and no face is applied.

Inlay Diagnostics

kakoune-lsp supports showing diagnostics inline after their respective line, but this behavior can be somewhat buggy and must be enabled explicitly:

lsp-inlay-diagnostics-enable global

Markdown rendering in info box

kakoune-lsp shows some additional information provided by the language server in an info box. This information includes documentation for the token under the cursor (lsp-hover) and documentation for completion candidates. In both cases, the Language Server Protocol allows for both plain text and Markdown, and most servers do implement Markdown.

To make use of Markdown, kakoune-lsp transpiles it into Kakoune’s markup language, utilizing various faces for styling. These faces all default to the Information face, to ensure that the text in the info box works with any color scheme.

To enable Markdown highlighting, define some of the following faces in your theme or kakrc:

Face Usage

InfoDefault

The default text color. You’ll likely want to leave this at the default Information.

InfoBlock

The face used for code blocks. Language specific syntax highlighting for code blocks is not supported.

InfoBlockQuote

The face used for block quotes. The > Markdown syntax is still rendered.

InfoBullet

The face used to highlight the list symbol for both ordered and unordered lists. For list items' text, InfoDefault is used.

InfoHeader

The face used for headings. There is currently no distinction between different heading levels.

InfoLink

The face used to highlight link titles. Maybe some classic blue+u for this one?

InfoLinkMono

This face is assigned to inline code spans within link titles, such as in the following Markdown snippet. Here, the word format will receive the InfoLinkMono face.

[the `format` function](https://example.com)

InfoMono

The face used for inline code spans (backtick strings).

InfoRule

The face used for horizontal lines (rules).

InfoDiagnosticError

Used for error messages in the diagnostics inside hover info. This defaults to Kakoune’s built-in Error face.

InfoDiagnosticHint

Used for hints in the diagnostics inside hover info.

InfoDiagnosticInformation

Used for informational messages in the diagnostics inside hover info.

InfoDiagnosticWarning

Used for warnings in the diagnostics inside hover info.

For convenience, here is a snippet to paste into your theme/config:

face global InfoDefault               Information
face global InfoBlock                 Information
face global InfoBlockQuote            Information
face global InfoBullet                Information
face global InfoHeader                Information
face global InfoLink                  Information
face global InfoLinkMono              Information
face global InfoMono                  Information
face global InfoRule                  Information
face global InfoDiagnosticError       Information
face global InfoDiagnosticHint        Information
face global InfoDiagnosticInformation Information
face global InfoDiagnosticWarning     Information

Current limitations of this feature are:

  • Language specific syntax highlighting for code blocks is not supported.

  • For hyperlinks, only their title (the pretty name) is shown.

  • The original syntax for headings is retained to visualize their level.

Snippets

Snippets are completions that come with placeholders ("tabstops") in the places you likely want to insert text (for example function call arguments). The placeholders are highlighted with the two faces SnippetsNextPlaceholders and SnippetsOtherPlaceholders.

The lsp-snippets-select-next-placeholders command allows to jump to the next tabstop (like function call arguments). The suggested mapping uses <tab> (see Configure mappings). Here’s a way to bind it to <c-n> instead (might need to hide the completion menu with Kakoune’s <c-o> command):

map global insert <c-n> '<a-;>:lsp-snippets-select-next-placeholders<ret>' -docstring 'Select next snippet placeholder'
hook global InsertCompletionShow .* %{
  unmap global insert <c-n> '<a-;>:lsp-snippets-select-next-placeholders<ret>'
}
hook global InsertCompletionHide .* %{
  map global insert <c-n> '<a-;>:lsp-snippets-select-next-placeholders<ret>' -docstring 'Select next snippet placeholder'
}

Snippet support can be disabled by setting snippet_support = false at the top level of the config.

Limitations

workspace/didChangeWatchedFiles is disabled by default; use watch_file_support = true to enable it.

Encoding

kakoune-lsp works best with UTF-8 documents.

Position.character interpretation

The LSP spec says that column offsets (Position.character) are to be interpreted as UTF-16 code units. Many servers violate the spec. Please refer to microsoft/language-server-protocol#376 for some background.

kakoune-lsp adheres to the spec but will prefer UTF-8 offsets if the server advertises support for UTF-8 offsets via client capabilities general.positionEncodings or clangd protocol extension.

Troubleshooting

If kakoune-lsp fails try to put this line in your kakrc after kak-lsp --kakoune invocation:

set global lsp_cmd "kak-lsp -s %val{session} -vvv --log /tmp/kak-lsp.log"

to enable debug logging.

If it does not give enough insight to fix the problem or if the problem is a bug in kakoune-lsp itself please don’t hesitate to raise an issue.

Default configuration

Please also try to reproduce the issue with a minimal configuration. Sometimes the problem occurs only with specific settings in your ~/.config/kak-lsp/kak-lsp.toml and/or ~/.config/kak/. Use this command to start Kakoune with kakoune-lsp enabled, both with pristine settings.

env -u XDG_CONFIG_HOME HOME=$(mktemp -d) kak -e '
    eval %sh{kak-lsp --kakoune -s $kak_session}
    set global lsp_cmd "kak-lsp -s %val{session} -vvvv --log /tmp/kak-lsp.log"
    lsp-enable'
Note
Some Kakoune plugins could interfere with kakoune-lsp, particularly completions providers. E.g. racer.kak competes for autocompletion in Rust files.

Crashes

For troubleshooting crashes, you might like to run kakoune-lsp outside of Kakoune.

To do this:

  1. Before launching Kakoune, run kakoune-lsp with an arbitrary session ID (here foobar):

    kak-lsp -s foobar
  2. In a second terminal, run Kakoune with the same session ID:

    kak -s foobar

Versioning

kakoune-lsp follows SemVer with one notable difference from common practice: we don’t use 0 major version to indicate that product is not yet reached stability. Even for non-stable and not feature-complete product user should be clearly informed about breaking change. Therefore we start with major version 1 and increment it each time when upgrade requires user’s attention.

kak-lsp's People

Contributors

414owen avatar alexherbo2 avatar andreyorst avatar burniintree avatar daboross avatar delapouite avatar deviant avatar dmerejkowsky avatar igor-ramazanov avatar jjk96 avatar jtrees avatar krobelus avatar maximbaz avatar natsukagami avatar occivink avatar osiox avatar pantoofle avatar phlogistique avatar pickfire avatar raiguard avatar ricochet1k avatar rosuavio avatar sclu1034 avatar screwtapello avatar sidkshatriya avatar spferical avatar tadeokondrak avatar topisani avatar ul avatar vbauerster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kak-lsp's Issues

Automatically send textDocument/didOpen to language server

kak-lsp is not perfect and could crash from time to time and then being restarted. Or restarted deliberately during development of it. Or user can forget to fire up kak-lsp before starting work on project. It's very annoying to either re-open or execute lsp-did-open for files in Kakoune in both cases.

Because information about open files is already available in context, it should be easy to send didOpen to language server when it was not sent to it before for any reason.

Usage outside of kakoune

I'm wondering if it is possible to use kak-lsp outside of kakoune? I'd like to have a language server command-line client that I can use to test cquery. So far I've been working on my own solution, but it'd be a good idea not to duplicate the effort.

I need to browse the implementation more carefully, but I think cquery e2e testing has a few requirements:

  • send a message to the language server, wait for a reply
  • send an arbitrary (ie, not hard-coded in kak-lsp) message and wait for a reply
  • specify initialization options in the init message (though this can be worked around)

Any thoughts? If you're not interested in usage outside of kakoune that's completely okay :)

Add lsp-stop command

To exit kak-lsp session (as opposed to lsp-exit which shutdowns language servers associated with current Kakoune session, but keeps kak-lsp running (useful in TC single-server mode))

Handle KakEnd

...and gracefully exit attached language servers and dispatch/transport threads.

Could we/do we want to handle it more granular, per project?

Scheduled refactor

kak-lsp grows organically and requires gardening phase to keep it in shape and prevent from turning into bush.

Refactor should be done after #7 and include:

  • #5
  • Finer modularization
  • Consistent naming
  • No global state promiscuity. Context now plays role of mutable global variable. Though app require db-like global state, it should be organized (as db is). Worth moving context management into separate service running in dedicated thread.

Replace netcat with own implementation

We already hit problems with netcat platform-specific behaviour twice (see #24 and #14). It might be worth incorporating that functionality in kak-lsp itself to ensure consistent behaviour.

Remove hover option

And provide command to enable/disable it. In general, we should not provide options for things easily doable as Kakoune command.

Windows prebuilts

It'd be great to have prebuilts available for windows as well.

I'm investigating using kak-lsp as part of cquery e2e testing - ideally CI can just download the prebuilt (cquery CI runs on windows, macos, and linux).

Handle language server crash during request

I still get those when cquery crashes:

thread '' panicked at 'Failed to write message to language server: Os { code: 32, kind: > BrokenPipe, message: "Broken pipe" }', libcore/result.rs:945:5

Make installation easier

  • Publish releases at least for Mac OS and Linux (I need to setup cross-compilation for that)
  • Handle configuration copying (via Makefile?)

cargo build --release throws errors

I wasn't able to compile in macOS.

❯ cargo build --release
   Compiling kak-lsp v0.1.0 (file:///Users/vbauer/kakplug/kak-lsp)
error[E0554]: #![feature] may not be used on the stable release channel
 --> src/main.rs:1:1
  |
1 | #![feature(match_default_bindings)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0554]: #![feature] may not be used on the stable release channel
 --> src/main.rs:2:1
  |
2 | #![feature(try_trait)]
  | ^^^^^^^^^^^^^^^^^^^^^^

error[E0554]: #![feature] may not be used on the stable release channel
 --> src/main.rs:3:1
  |
3 | #![feature(getpid)]
  | ^^^^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors

error: Could not compile `kak-lsp`.

References

It'd be great if kak-lsp could show references (textDocument/references).

Random feedback: it took me a bit to get kak-lsp running since it requires GNU netcat. Debian seems to only have BSD netcat, so I had to build GNU netcat from source.

Make features easily configurable

It's already possible by manual tweak of kak-lsp --kakoune output being put into autoload but we need to provide easy way to perform basic operations like enable/disable without resorting to static .kak file (which is not bad by itself, but just tedious to keep in sync taking in account that kak-lsp is still in flux). Any thought on how should it look like and what configuration options should be implemented first?

Thoughts about inline diagnostics

Due to complaints from several users (me included) inline diagnostics has been disabled by default in a89a2e1. I think most users expect to have this enabled by default when using LSP and that disabling it provides a worse first experience.

Also I'd like to point that people most likely don't complain about the feature on itself but that diagnostics that are too visible. I think this is due to the choice of the faces used. For example Information is really annoying in a buffer when using the gruvbox theme since the face is the same than the one of the main cursor. I guess Information is more adapted for UI components like the info box than to display inline information.

The ideal solution UX-wise would be colored underline but this is pretty difficult to display in a terminal screen if not impossible. Testing with similar setups in other editors I found using only a foreground color to be the more adapted. Particularly with yellow for information and red for errors, a couple that work with most of color schemes.

In the end it would be useful to allow users to configure the faces used by kak-lsp, something like DiagnosticInfo and DiagError maybe? @mawww would it be overkill to add these as default faces in kakoune? That way it could be theme-specific.

Send requests from editor to kak-lsp only for relevant filetypes

It used to be that way and should be good for performance. I changed it to sending requests for all filetypes to make setup easier (no need to keep lsp.kak and kak-lsp.toml in sync, just single lsp-enable is enough; no need to manage scoped hooks, just set global ones).

Worth to optimize it back after #20 which will allow to keep setup simple while deriving lsp.kak dynamically from kak-lsp.toml.

Implement `textDocument/publishDiagnostics` support

Specification

It's the next feature to implement for two reasons:

  1. Completion, hover and definition removed overhead of switching to look into API docs or to grep project for many cases. Next huge overhead I'd like to remove is switching to cargo check (or flow or whatever).
  2. Implementation of this feature require solving routing back to editor something which lacks meta from editor request and will open gate for other server-initiated requests.

Consider using textEdit for completion

23-Wed 01:00:04 Franciman not sure it will be significant, but it may be useful. Do you remember the completion problem I had, and you said that you are keeping track of the offset. I found out that in the response to the textDocument/complete request, there can also be a textEdit which contains the range of text to apply the text transformation to (in layman's words write the completion :P)
23-Wed 01:01:08 Franciman so instead of keeping track of the offset you can use the start position of the range of the text edit. This has also the advantage of being able to support, in future, the use of the textEdit, when you select a completion, which may be useful
23-Wed 01:02:04 Franciman since insertText field is deprecated in favor of the textEdit, when the text to insert is different from the label

Decode path from DocumentUri

Apparently uri crate doesn't do it by default which leads to url-encoded paths to be sent to Kakoune (i.e. when doing goto definition)

Support narrower-scoped usage of kak-lsp

Currently, at least according to the Linux installation instructions, kak-lsp runs as a system service which seems sub-optimal:

  • it takes exclusive ownership of a TCP port on the loopback interface. While TCP ports are fairly plentiful, memorable port-numbers are less so, lots of tools want to use one and it's hard to handle collisions gracefully.
  • It's reasonable to have multiple versions of a compiler toolchain installed, and hence multiple LSP servers for a single language. Normally this is easy to handle by setting $PATH appropriately for each project, but since kak-lsp runs as a service it can't see $PATH changes.
  • I'm just uneasy about a long-running, unauthenticated service, even one limited to the loopback interface, that will accept file-paths and spit back information about them.

I would be much more comfortable with kak-lsp if it followed a model a little more like Kakoune or tmux:

  • kak-lsp requires a session identifier on the command-line; the Kakoune integration script might pick something like $kak_session so every Kakoune session gets its own LSP server.
  • kak-lsp connects to a long-running server listening on a Unix domain socket named after the session identifier, or starts such a server if needed
    • the Unix domain socket should be owned by the current user and mode 0600 for security
  • the long-running server starts and manages the relevant LSP servers, much as it already does, but since it's launched by kak-lsp it should automatically inherit the appropriate $PATH and other settings
  • the long-running server may exit automatically after a certain period of time has elapsed without receiving a query over the socket

Such a scheme should be just as convenient for the end-user as the current system (automatically starting the correct LSP server, automatically restarting after a crash, etc.), but should be more secure.

I understand this would be a big departure from kak-lsp's current architecture, but if you're open to the idea I'm willing to work on the implementation.

Restart language server if it crashes

Sometimes particular language server crashes and kak-lsp starts shouting into the void for server's route. It should restart that language server instead.

Handle all recoverable errors

At the moment code is littered with unwrap and expect. Though they are legitimate in several places (we can't do anything smart besides of exiting with an error message, and panic is okay for it), it's not the case for many others.

*diagnostics* buffer highlighting

Hi

First, here's a screenshot of a *diagnostics* buffer produced by the lsp-diagnostics command. (using flow but it's not relevant here):

image

As you can see that's a lot of cyan color. This buffer has the grep filetype so it uses the highlighters defined here: https://github.com/mawww/kakoune/blob/master/rc/core/grep.kak#L30-L34 . That's where the cyan and green colors come from.

What would be the better way to improve the readibility?

For instance I think lines containing diag-messages like - Either string [1] is incompatible with string literalarticle [2]. on the screenshot should simply be displayed with the Default face.

Should it be fixed in kakoune's grep.kak directly ? Or should kak-lsp provides a custom diagnostics filetype and related highlighters?

Send lsp.kak contents to editor

It could significantly ease installation and usage (no need to mess with user's ~/.config/kak/, no need to keep in sync port etc.)

Scenario is:

  1. instead of lsp-enable user adds `%sh{kak-lsp --enable}
  2. kak-lsp --enable returns current lsp.kak contents with proper lsp_cmd based on config. Some of sections could be made controllable by config options.

Needs project root to start

I tested for a python file test.py.

command:
kak-lsp -vvv

Printed "DEBG Unable to detect project root for file /tmp/test.py" every time.

When I added an empty requirements.txt next to the file it did work.

My suggestion would be to make project root optional since it does not contain information that is necessary for most functions.

[Feature request] Function signature hint

Language server can provide parameter names and documents while typing parameters, see signatureHelper.

Sample response from pyls

Context with cursor at position 3

bin(

Response

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "signatures": [
      {
        "label": "Return the binary representation of an integer.",
        "documentation": "Return the binary representation of an integer.\n\n>>> bin(2796202)\n0b1010101010101010101010",
        "parameters": [
          {
            "label": "number",
            "documentation": null
          }
        ]
      }
    ],
    "activeSignature": 0,
    "activeParameter": 0
  }
}

Indicate language server progress

Some of language servers take a long time to initialize. Most of them report progress and/or ready event. We need to indicate their progress somehow to prevent confusion like "why does 'go to definition' not work? is it broken?" during initialization.

I need help to understand what is the best way in Kakoune to communicate such kind of information. It should be non-intrusive and discoverable at the same time. Should it be echo or info (the former could be easily missed and the latter feels too noisy)? Ideal would be to show in status line (like echo) but persistent and update according to language server status change.

Zombies

Looks like some zombie processes are hanging around during kak-lsp work:

rprakapchuk      30716   0.0  0.0        0      0   ??  Z     8:00pm   0:00.00 (kak)
rprakapchuk      30706   0.0  0.0        0      0   ??  Z     8:00pm   0:00.00 (kak)
rprakapchuk      30693   0.0  0.0        0      0   ??  Z     8:00pm   0:00.00 (kak)
rprakapchuk      30658   0.0  0.0        0      0   ??  Z     8:00pm   0:00.00 (kak)

It could be because how netcat is used (timeout?) and requires further investigation.

Revise Kakoune -> kak-lsp message format

It's quite redundant (meta contains everything needed for text_document parameter in most cases). It's nice to have it mimicking LSP requests, but let's don't be fanatic about it.

Embed default config into binary

At the moment kak-lsp tries to read config from ~/.config/kak-lsp (which should be improved as well i.e. to respect XDG_CONFIG_HOME). If it fails then it tries to read config from the directory where binary is located. This is a workaround to have kak-lsp working without extra manual steps after installation from homebrew, because the latter doesn't allow writing to user's directory during installation.

This behaviour is not very nice because it demands putting configuration and binary in the same directory which violates wide-spread convention. Embedding default config is easy and clear solution for zero-conf installation.

Completion doesn't work with rls

Same behavior on linux and macOS with rust 1.26.

May 28 08:52:13.341 DEBG To server: {"jsonrpc":"2.0","method":"textDocument/completion","params":{"position":{"character":12,"line":21},"textDocument":{"uri":"file:///Users/casimir/dev/src/github.com/casimir/ced/core/src/main.rs"}},"id":65}, module: kak_lsp::language_server_transport:152
May 28 08:52:13.355 DEBG From server: {"jsonrpc":"2.0","id":65,"result":[{"label":"env","kind":9,"detail":"/Users/casimir/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/env.rs"}]}, module: kak_lsp::language_server_transport:124
May 28 08:52:13.359 DEBG To editor `58887`: eval -client unnamed0 %🦀set window lsp_completions %§22.10@11:env|/Users/casimir/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/src/libstd/env.rs

|env {MenuInfo}Module§
🦀, module: kak_lsp::editor_transport:71
May 28 08:52:14.094 DEBG From editor:
session   = "58887"
client    = "unnamed0"
buffile   = "/Users/casimir/dev/src/github.com/casimir/ced/core/src/main.rs"
version   = 11
method    = "textDocument/hover"
[params.position]
line      = 21
character = 12
, module: kak_lsp::editor_transport:26

Make it configurable

Mapping extension to language and language to language server command should be configurable via configuration file. Port should be configurable via config file and cli option. Having configurable address is not crucial, but would be nice to have.

Preferred format for configuration file is TOML.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.