-
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1f3cd5a
commit b4e6163
Showing
10 changed files
with
791 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
--- | ||
title: Source | ||
description: Type description of care.nvim config | ||
author: | ||
- max397574 | ||
categories: | ||
- docs, | ||
- types | ||
--- | ||
|
||
# General | ||
|
||
The config of care is used to configure the ui and care itself. | ||
|
||
There are two main parts to the config. The first one is the `ui` field and the second on is the | ||
rest of the configuration which is for configuring care itself. | ||
|
||
## UI | ||
|
||
In the ui field the completion menu, the docs view and the format of the entries are configured. | ||
There is also a field for configuring type icons. | ||
|
||
## Snippet expansion | ||
|
||
Here a function for expanding snippets is defined. By default this is the builtin | ||
`vim.snippet.expand()`. You can also use a plugin like luasnip for this like this: | ||
|
||
```lua | ||
snippet_expansion = function(body) | ||
require("luasnip").lsp_expand(body) | ||
end | ||
``` | ||
|
||
## Selection behavior | ||
|
||
With the selection behavior the user can determine what happens when selecting an entry. This can | ||
either be `"select"` or `"insert"`. Selecting will just select the entry and do nothing else. Insert | ||
will actually insert the text of the entry (this is not necessarily the whole text). | ||
|
||
## Keyword pattern | ||
|
||
Pattern used to determine keywords, used to determine what to use for filtering and what to | ||
remove if insert text is used. | ||
|
||
## Completion events | ||
|
||
The `completion_events` table is used to set events for completion. By default it just contains | ||
`"TextChangedI"`. You can set it to an empty table (`{}`) to disable autocompletion. | ||
|
||
## Sources | ||
|
||
TODO | ||
|
||
## Preselect | ||
|
||
Whether items should be preselected or not | ||
|
||
## Enabled | ||
|
||
This function can be used to disable care in certain contexts. By default this disables | ||
care in prompts. | ||
|
||
# UI | ||
|
||
The ui configuration is used to configure the whole ui of care. One of the main goals of | ||
this is to be as extensible as possible. This is especially important for the completion entries. | ||
Read more about that under [Configuraton of item display](./design.md#configuraton-of-item-display). | ||
|
||
The most important part for many users will be the `menu` field. It's used to configure the | ||
completion menu. | ||
|
||
You can also configure the documentation view just like the main menu. | ||
|
||
Lastly the users can also configure the icons which will be used for the different items. | ||
|
||
## Ghost text | ||
|
||
with this option the user can determine if ghost text should be displayed. Ghost text is just | ||
virtual text which shows a preview of the entry. | ||
|
||
You can use the `enabled` field to determine whether the ghost text should be enabled or not. | ||
The `position` can either be `"inline"` or `"overlay"`. Inline will add the text inline right | ||
where the cursor is. With the overlay position the text will overlap with existing text after the | ||
cursor. | ||
|
||
## Menu | ||
|
||
This configuration should allow you to completely adapt the completion menu to your likings. | ||
|
||
It includes some basic window properties like the border and the maximum height of the window. It | ||
also has a field to define the character used for the scrollbar. | ||
Set `scrollbar` to `nil` value to disable the scrollbar. | ||
|
||
## Position | ||
|
||
If the menu should be displayed on top, bottom or automatically | ||
|
||
Another field is `format_entry`. This is a function which recieves an entry of the completion | ||
menu and determines how it's formatted. For that a table with text-highlight chunks like | ||
`:h nvim_buf_set_extmarks()` is used. You can create sections which are represented by tables | ||
and can have a different alignment each. This is specified with another field which takes a table | ||
with the alignment of each section. | ||
|
||
For example you want to have the label of an entry in a red highlight and an icon in a entry-kind | ||
specific color left aligned first and then the source of the entry right aligned in blue. | ||
You could do that like this: | ||
|
||
```lua | ||
format_entry = function(entry) | ||
return { | ||
-- The first section with the two chunks for the label and the icon | ||
{ { entry.label .. " ", "MyRedHlGroup" }, { entry.kind, "HighlightKind" .. entry.kind } } | ||
-- The second section for the source | ||
{ { entry.source, "MyBlueHlGroup" } } | ||
} | ||
end, | ||
alignment = { "left", "right" } | ||
``` | ||
|
||
Notice that there are multiple differences between having one table containing the chunks for the | ||
label and kind and having them separately. The latter would require another entry in the `alignment` | ||
table. It would also change the style of the menu because the left sides of the icons would be | ||
aligned at the same column and not be next to the labels. In the example there also was some | ||
spacing added in between the two. | ||
|
||
## Documentation view | ||
|
||
This configuration allows you to configure the documentation view. | ||
It consists of some basic window properties like the border and the maximum height of the window. | ||
It also has a field to define the character used for the scrollbar. | ||
|
||
## Type Icons | ||
|
||
This is a table which defines the different icons. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
--- | ||
title: Design | ||
description: Design of care.nvim | ||
author: | ||
- max397574 | ||
categories: | ||
- docs | ||
--- | ||
|
||
# General | ||
|
||
There is the [care.nvim](https://github.com/max397574/care.nvim) plugin. This is | ||
the main module of the whole completion architecture. Then there are also sources, which is where | ||
the core gets it's completions from. | ||
|
||
## Care.nvim | ||
|
||
This is the core of the autocompletion. From here the sources are used to get completions which | ||
are then displayed in the [Completion Menu](#completion-menu) | ||
|
||
### Completion Menu | ||
|
||
The completion menu displays the current completions. | ||
Features that it should have: | ||
|
||
- Completely customizable display for every entry (with **text-highlight chunks** like extmark-api) | ||
- Customizable scrollbar | ||
- Customizable window properties | ||
- Border | ||
- Max height | ||
- Docview | ||
- Customizable | ||
- Try to get nicely concealed like in core or noice.nvim | ||
- Allow to send to e.g. quickfix or copy | ||
|
||
# Terms | ||
|
||
## Offset | ||
|
||
Offset always describes the distance between e.g. the start of an entry from the beginning of the | ||
line. | ||
|
||
# Architecture | ||
|
||
TODO: fancy ascii diagramms | ||
|
||
autocompletion: | ||
|
||
1. `TextChangedI` or `CursorMovedI` | ||
2. get the context (line before, cursor position etc) | ||
3. Check if context changed | ||
4. Check if character was a trigger character or completion was triggered manually | ||
5. Depending on ^^ decide what to do _for every source_: | ||
- Get new completions | ||
1. get completions from source based on context | ||
- sort completions | ||
1. Use characters found with `keyword_pattern` to fuzzy match and sort completions | ||
6. Collect all the completions | ||
7. Open menu to display thing | ||
1. if there is a selected one: | ||
- highlight selected one | ||
- show preview of selected completion | ||
- show docs | ||
|
||
When completing (e.g. `<cr>`): | ||
|
||
1. check if menu is open | ||
2. check if anything is selected (or autoselect option) | ||
3. complete | ||
1. insert text | ||
2. additional text edits (check core functions) | ||
3. snippet expansion (core or luasnip) | ||
4. close menu | ||
|
||
# Motivation | ||
|
||
## Nvim-cmp | ||
|
||
These days nvim-cmp is the most popular completion-engine for neovim. There are some mayor issues | ||
me and also other people in the community have with cmp. | ||
|
||
### Bad code/Documentation | ||
|
||
The code of nvim-cmp is often quite unreadable. Sometimes this might be due to optimizations | ||
and surely some of it has just grown historically. Also there are nearly no docs on how the | ||
whole completion engine works. The api for new sources is quite unclear and far from optimal. | ||
While this doesn't really matter to a user it definitely does to a potential contributor and | ||
developers of sources. | ||
|
||
### Legacy code/features | ||
|
||
There are a lot of things which grew just historically. The author of nvim-cmp is | ||
(understandable to a certain degree) afraid of making breaking changes and fixing them or just | ||
doesn't think changes are necessary. | ||
|
||
#### Configuration of item display | ||
|
||
One such example is the configuration of how items are displayed in the menu. This works with | ||
a function `formatting` which takes a completion item and is allowed to return an item where | ||
the three fields `menu`, `kind` and `abbr` and three more fields for highlights for those can | ||
be set. So apart from the background and border color of the menu you're limited to have three | ||
different fields and colors in your menu E.g. source name, kind name, kind icon and text isn't | ||
possible. It's also not possible to have round or half blocks around icons because you don't | ||
have enough colors. An example of an issue can be found [here](https://github.com/hrsh7th/nvim-cmp/issues/1599). | ||
You also can't add padding wherever you want and you can't align the fields as you want. | ||
|
||
#### Legacy code | ||
|
||
There is e.g. the whole "native menu" thing laying around in the codebase. Nowadays this isn't | ||
really needed anymore. Everything of it can be accomplished with the "custom menu". There is a | ||
lot of duplicate code because of that. | ||
|
||
### Mapping system | ||
|
||
The mapping system is quite confusing. It's a table in the config with keys to be mapped as keys | ||
and a call to `cmp.mapping()` with a callback to the actual functionality as value. | ||
Users should able to just use normal mappings or functions with `vim.keymap.set`. | ||
|
||
### Custom solutions for builtin functionality | ||
|
||
An example for this is the [Mapping system](#mapping-system). Another example would be the `cmp.event.on` | ||
which could just be done with User autocmds. | ||
|
||
### Why not contribute? | ||
|
||
The maintainer is in general quite conservative. There were pull-requests for many features open | ||
which were liked by the community (seen by reactions and comments). But they were abandoned | ||
because the maintainer saw no reason to add it. There was for example a pull-request to fix the | ||
issue with the limited fields in the configuration [here](https://github.com/hrsh7th/nvim-cmp/pull/1238). | ||
This pull request was closed because _No specific use cases have emerged at this stage._ | ||
according to the author. Even though there was clearly a problem described and what the pr would | ||
allow (this pr allowed custom fields which still isn't nice but fixed the obvious problems). | ||
There were also some features (in particular the custom scrollbars) removed because there were | ||
some issues with it which apparently weren't worth fixing for the feature. | ||
So it's not really motivating to try to contribute new things. It's also quite hard because of | ||
the messy code with lots of legacy code. | ||
|
||
# Goals | ||
|
||
## Use nvim-cmp sources | ||
|
||
We should be able to use nvim-cmp sources. This should be possible by adding a `package.loaders` | ||
where we can redirect calls to `cmp.register_source` (which happens in most sources auto- | ||
matically) to our own plugin. We **don't want to adapt to cmp's apis** for this though. We won't | ||
extend our own formats e.g. for entries or sources to match cmps. Even when it's complicated we | ||
will just convert between the different formats. | ||
|
||
## Native things | ||
|
||
Use as many native things as possible. This includes setting mappings with `vim.keymap.set` or | ||
add events as user autocmd events. | ||
|
||
# Non-Goals | ||
|
||
## Different views | ||
|
||
Nvim-cmp has different views. At the moment wild-menu, native menu and custom menu. There is a | ||
lot of code duplication because of this. We'd like to avoid having multiple views. The native | ||
one isn't needed anyway (it likely is just in cmp for historical reasons). | ||
In the future we'd like to allow injecting custom views via config where you just get the | ||
entries and do things with them yourself. This is mostly to avoid code duplication in core. | ||
|
||
## Commandline completion | ||
|
||
At the moment no command line completion is planned. This is because the author thinks it's not | ||
really needed because builtin completion is already quite good and there is little value added | ||
by adding commandline completion. Also it doesn't really make sense in my opinion to combine | ||
commandline completion and autocompletion for buffer contents in the same plugin. Especially if | ||
you try to share things in between like nvim-cmp does. | ||
|
||
# Types used | ||
|
||
The types should minimally be the lsp things (for the context passed to source, for response and | ||
for entries). Everything additionally is mostly optional. | ||
|
||
# Code style | ||
|
||
## Object-Orientation | ||
|
||
Most of the modules are written object oriented. This decision was made because it's way easier | ||
to create new instances of the things and associate data with them. | ||
|
||
## Functions | ||
|
||
You should always write functions in the form of `[local] function <name>(<parameters>)` as | ||
opposed to `[local <name> = function(<parameters>)`. The first notation provides the advantage | ||
that you can directly jump to it's definition and you won't get multiple results (the name and | ||
the anonymous function). | ||
|
||
## Comments and annotations | ||
|
||
Add annotations to **every** public function of a module (e.g. with neogen) and add comments | ||
explaining what the code does. We'd like to have code which would be understandable for outsiders. | ||
Also try to add annotations and descriptions to local functions but this isn't as important as | ||
public ones | ||
|
||
### Format | ||
|
||
For The annotations we use [LuaCATS](https://luals.github.io/wiki/annotations/) style. For types | ||
don't use a space after the `---` marker. For comments you should. Check the annotations in | ||
`lua/care/types/` for examples. | ||
|
||
## Types | ||
|
||
We have files for types which are tangled from a norg file (this one?) using lua-ls annotations. | ||
They are prefixed with `care.`. | ||
As often as possible we should try to use the `lsp.*` types which are in neovim core. | ||
|
||
The types are documented in the `docs/` folder and are tangled to lua type files with [neorg](https://github.com/nvim-neorg/neorg). | ||
So if you want to change a type annotation you should change the `.norg` file and tangle it again. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
--- | ||
title: Index | ||
description: Type description of context | ||
author: | ||
- max397574 | ||
categories: | ||
- docs, | ||
- types | ||
--- | ||
|
||
This is a class representing the current state. It includes buffer number and cursor position. It | ||
is passed to completion sources to get completions. | ||
|
||
# Methods | ||
|
||
## Changed | ||
|
||
Whether the context changed in comparison to the previous one. This is used to check whether to | ||
get new completions or not. | ||
|
||
## New | ||
|
||
Create a new context. This takes the previous one as argument. This one is stored to determine if | ||
the context changed or not when completing. | ||
The previous context of the previous one is deleted so this data structure doesn't grow really | ||
large. | ||
|
||
# Fields | ||
|
||
## Previous | ||
|
||
The previous context which is used to determine whether the context changed or not. | ||
|
||
## Cursor | ||
|
||
The cursor positon. | ||
|
||
## Bufnr | ||
|
||
Number of the buffer. | ||
|
||
## Reason | ||
|
||
Reason for triggering completion. | ||
|
||
## Current line | ||
|
||
The current line. | ||
|
||
## Line before cursor | ||
|
||
Part of the current line which is before the cursor. |
Oops, something went wrong.