Skip to content

Commit

Permalink
feat!: match built-in cmdline behavior by default (#1314)
Browse files Browse the repository at this point in the history
* feat!: match built-in cmdline behavior by default

* docs: remove references to `ctx.mode`

* docs: further clarification

* docs: misc clarifications
  • Loading branch information
Saghen authored Feb 25, 2025
1 parent 5b7915b commit 54091b6
Show file tree
Hide file tree
Showing 16 changed files with 296 additions and 195 deletions.
7 changes: 7 additions & 0 deletions doc/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ export default defineConfig({
{ text: 'Reference', link: '/configuration/reference' },
],
},
{
text: 'Modes',
items: [
{ text: 'Cmdline', link: '/modes/cmdline' },
{ text: 'Terminal', link: '/modes/term' },
],
},
{
text: 'Development',
items: [
Expand Down
6 changes: 3 additions & 3 deletions doc/configuration/completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ You may use the `show_and_insert` keymap to show the completion menu and select
Video: https://github.com/user-attachments/assets/4658b61d-1b95-404a-b6b5-3a4afbfb8112
-->

To control the selection behavior per mode, pass a function to `selection.preselect/auto_insert`:
To control the selection behavior dynamically, pass a function to `selection.preselect/auto_insert`:

```lua
completion.list.selection = {
Expand All @@ -222,9 +222,9 @@ completion.list.selection = {

-- or a function
preselect = function(ctx)
return ctx.mode ~= 'cmdline' and not require('blink.cmp').snippet_active({ direction = 1 })
return not require('blink.cmp').snippet_active({ direction = 1 })
end,
-- auto_insert = function(ctx) return ctx.mode ~= 'cmdline' end,
auto_insert = function(ctx) return vim.bo.filetype ~= 'markdown' end,
}
```

Expand Down
4 changes: 3 additions & 1 deletion doc/configuration/fuzzy.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Blink uses a SIMD fuzzy matcher called [frizbee](https://github.com/saghen/frizb

### Prebuilt binaries (default on a release tag)

By default, Blink will download a prebuilt binary from the latest release, when you're on a release tag (via `version = '*'` on `lazy.nvim` for example). If you're not on a release tag, you may force a specific version via `fuzzy.prebuilt_binaries.force_version`. See [the latest release](https://github.com/saghen/blink.cmp/releases/latest) for supported systems. See `prebuilt_binaries` section of the [reference configuration](./reference.md#prebuilt-binaries) for more options.
By default, Blink will download a prebuilt binary from the latest release, when you're on a release tag (via `version = '*'` on `lazy.nvim` for example). If you're not on a release tag, you may force a specific version via `fuzzy.prebuilt_binaries.force_version`. See [the latest release](https://github.com/saghen/blink.cmp/releases/latest) for supported systems. See `prebuilt_binaries` section of the [reference configuration](./reference.md#fuzzy) for more options.

You may instead install the prebuilt binaries manually by downloading the appropriate binary from the [latest release](https://github.com/saghen/blink.cmp/releases/latest) and placing it at `$data/lazy/blink.cmp/target/release/libblink_cmp_fuzzy.$ext`. Get the `$data` path via `:echo stdpath('data')`. Use `.so` for linux, `.dylib` for mac, and `.dll` for windows. If you're unsure whether you want `-musl` or `-gnu` for linux, you very likely want `-gnu`.

Expand All @@ -25,6 +25,8 @@ You may instead install the prebuilt binaries manually by downloading the approp

When on `main`, it's highly recommended to build from source via `cargo build --release` (via `build = '...'` on `lazy.nvim` for example). This requires a nightly rust toolchain, which will be automatically downloaded when using `rustup`.

You may also build with nix via `nix run .#build-plugin`.

## Configuration

See the [fuzzy section of the reference configuration](./reference.md#fuzzy)
4 changes: 2 additions & 2 deletions doc/configuration/general.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ For more common configurations, see the [recipes](../recipes.md).

-- Don't select by default, auto insert on selection
list = { selection = { preselect = false, auto_insert = true } },
-- or set either per mode via a function
list = { selection = { preselect = function(ctx) return ctx.mode ~= 'cmdline' end } },
-- or set via a function
list = { selection = { preselect = function(ctx) return vim.bo.filetype ~= 'markdown' end } },

menu = {
-- Don't automatically show the completion menu
Expand Down
22 changes: 5 additions & 17 deletions doc/configuration/keymap.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,7 @@ keymap = {

## Cmdline and Terminal

You may set a separate keymap for cmdline and terminal by defining `cmdline.keymap` and `term.keymap`, with an identical structure to `keymap`. When using `accept_and_enter`, you may want to use [to disable completions for the first couple characters](../recipes.md#set-minimum-keyword-length-for-command-only-in-cmdline), to avoid accepting a completion on abbreviations like `:wq`.

```lua
cmdline.keymap = {
preset = 'enter',

-- OPTIONAL: sets <CR> to accept the item and run the command immediately
-- use `select_accept_and_enter` to accept the item or the first item if none are selected
['<CR>'] = { 'accept_and_enter', 'fallback' },

...
},
term.keymap = {
preset = 'super-tab',
...
}
```
See the respective [cmdline documentation](../modes/cmdline.md) and [terminal documentation](../modes/term.md) for more information.

## Presets

Expand All @@ -108,6 +92,10 @@ Set the preset to `none` to disable the presets
['<C-k>'] = { 'show_signature', 'hide_signature', 'fallback' },
```

### `cmdline`

See the [cmdline documentation](../modes/cmdline.md)

### `super-tab`

You may want to set `completion.trigger.show_in_snippet = false` or use `completion.list.selection.preselect = function(ctx) return not require('blink.cmp').snippet_active({ direction = 1 }) end`. See more info in: https://cmp.saghen.dev/configuration/completion.html#list
Expand Down
37 changes: 24 additions & 13 deletions doc/configuration/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ completion.list = {
selection = {
-- When `true`, will automatically select the first item in the completion list
preselect = true,
-- preselect = function(ctx) return ctx.mode ~= 'cmdline' end,
-- preselect = function(ctx) return vim.bo.filetype ~= 'markdown' end,

-- When `true`, inserts the completion item automatically when selecting it
-- You may want to bind a key to the `cancel` command (default <C-e>) when using this option,
-- which will both undo the selection and hide the completion menu
auto_insert = true,
-- auto_insert = function(ctx) return ctx.mode ~= 'cmdline' end
-- auto_insert = function(ctx) return vim.bo.filetype ~= 'markdown' end
},

cycle = {
Expand Down Expand Up @@ -570,7 +570,7 @@ You may set configurations which will override the default configuration, specif
```lua
cmdline = {
enabled = true,
keymap = nil, -- Inherits from top level `keymap` config when not set
keymap = { preset = 'cmdline' },
sources = function()
local type = vim.fn.getcmdtype()
-- Search forward and backward
Expand All @@ -582,15 +582,20 @@ cmdline = {
completion = {
trigger = {
show_on_blocked_trigger_characters = {},
show_on_x_blocked_trigger_characters = nil, -- Inherits from top level `completion.trigger.show_on_blocked_trigger_characters` config when not set
show_on_x_blocked_trigger_characters = {},
},
menu = {
auto_show = nil, -- Inherits from top level `completion.menu.auto_show` config when not set
draw = {
columns = { { 'label', 'label_description', gap = 1 } },
list = {
selection = {
-- When `true`, will automatically select the first item in the completion list
preselect = true,
-- When `true`, inserts the completion item automatically when selecting it
auto_insert = true,
},
},
ghost_text = { enabled = nil }
-- Whether to automatically show the window when new completion items are available
menu = { auto_show = false },
-- Displays a preview of the selected item on the current line
ghost_text = { enabled = true }
}
}
```
Expand All @@ -611,12 +616,18 @@ term = {
show_on_blocked_trigger_characters = {},
show_on_x_blocked_trigger_characters = nil, -- Inherits from top level `completion.trigger.show_on_blocked_trigger_characters` config when not set
},
menu = {
auto_show = nil, -- Inherits from top level `completion.menu.auto_show` config when not set
draw = {
columns = { { 'label', 'label_description', gap = 1 } },
-- Inherits from top level config options when not set
list = {
selection = {
-- When `true`, will automatically select the first item in the completion list
preselect = nil,
-- When `true`, inserts the completion item automatically when selecting it
auto_insert = nil,
},
},
-- Whether to automatically show the window when new completion items are available
menu = { auto_show = nil },
-- Displays a preview of the selected item on the current line
ghost_text = { enabled = nil }
}
}
106 changes: 106 additions & 0 deletions doc/modes/cmdline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Command line (cmdline)

By default, blink.cmp enabled cmdline completions (`cmdline.enabled = true`), matchiing the behavior of the built-in `cmdline` completion:

- Menu will not show automatically (`cmdline.completion.menu.auto_show = false`)
- Pressing `<Tab>` will show the completion menu and insert the first item
- Subsequent `<Tab>`s will select the next item, `<S-Tab>` for previous item
- `<C-n>` for next item, `<C-p>` for previous item
- `<C-y>` accepts the current item
- `<C-e>` cancels the completion
- When [noice.nvim](https://github.com/folke/noice.nvim) is detected, ghost text will be shown, see the [ghost text](#ghost-text) section below

See the [reference configuration](../configuration/reference.md#cmdline) for the complete list of options.

## Keymap preset

Set via `cmdline.keymap.preset = 'cmdline'`, which is the default. Set to `'none'` to disable the preset. See the [keymap documentation](../configuration/keymap.md) for more information on defining your own.

```lua
{
['<Tab>'] = {
function(cmp)
if cmp.is_ghost_text_visible() and not cmp.is_menu_visible() then return cmp.accept() end
end,
'show_and_insert',
'select_next',
},
['<S-Tab>'] = { 'show_and_insert', 'select_prev' },

['<C-n>'] = { 'select_next' },
['<C-p>'] = { 'select_prev' },

['<C-y>'] = { 'select_and_accept' },
['<C-e>'] = { 'cancel' },
}
```

## Ghost text

When [noice.nvim](https://github.com/folke/noice.nvim) is detected, ghost text will be shown, likely similar to your terminal shell completions. Pressing `<Tab>` while ghost text is visible will accept the completion. When not visible, `<Tab>` will open the menu and insert the first item as per usual.

<img src="https://github.com/user-attachments/assets/b2fa6f41-4937-47bf-86b3-d82e9ec86b12">

```lua
cmdline = { completion = { ghost_text = { enabled = true } } }
```

## Show menu automatically

By default, the completion menu will not be shown automatically. You may set `cmdline.completion.menu.auto_show = true` to have it appear automatically.

```lua
cmdline = {
keymap = {
-- recommended, as the default keymap will only show and select the next item
['<Tab>'] = { 'show', 'accept' },
},
completion = { menu = { auto_show = true } },
}
```

However, you may want to only show the menu only when writing commands, and not when searching or using other input menus.

```lua
cmdline = {
keymap = {
-- recommended, as the default keymap will only show and select the next item
['<Tab>'] = { 'show', 'accept' },
},
completion = {
menu = {
auto_show = function(ctx)
return vim.fn.getcmdtype() == ':'
-- enable for inputs as well, with:
-- or vim.fn.getcmdtype() == '@'
end,
},
}
}
```

## Enter keymap

When using `<Enter>` (`<CR>`) to accept the current item, you may want to accept the completion item and immediately execute the command. You can achieve this via the `accept_and_enter` command. However, when writing abbreviations like `:wq`, with the menu automatically showing, you may end up accidentally accepting a completion item. Thus, you may disable the completions when the keyword, for the first argument, is less than 3 characters.

```lua
cmdline = {
keymap = {
['<Tab>'] = { 'accept' },
['<CR>'] = { 'accept_and_enter', 'fallback' },
},
-- (optionally) automatically show the menu
completion = { menu = { auto_show = true } }
},
sources = {
providers = {
cmdline = {
min_keyword_length = function(ctx)
-- when typing a command, only show when the keyword is 3 characters or longer
if ctx.mode == 'cmdline' and string.find(ctx.line, ' ') == nil then return 3 end
return 0
end
}
}
}
```
5 changes: 5 additions & 0 deletions doc/modes/term.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Terminal (term)

See the [reference configuration](../configuration/reference.md#term) for the complete list of options.

TODO
51 changes: 4 additions & 47 deletions doc/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,39 +41,6 @@ completion = {
signature = { window = { border = 'single' } },
```

### Change selection type per mode

```lua
completion = {
list = {
selection = {
preselect = function(ctx) return ctx.mode ~= 'cmdline' end,
auto_insert = function(ctx) return ctx.mode ~= 'cmdline' end
}
}
}
```

### Don't show completion menu automatically in cmdline mode

```lua
completion = {
menu = { auto_show = function(ctx) return ctx.mode ~= 'cmdline' end }
}
```

### Don't show completion menu automatically when searching

```lua
completion = {
menu = {
auto_show = function(ctx)
return ctx.mode ~= "cmdline" or not vim.tbl_contains({ '/', '?' }, vim.fn.getcmdtype())
end,
},
}
```

### Select Nth item from the list

Here's an example configuration that allows you to select the nth item from the list, based on [#382](https://github.com/Saghen/blink.cmp/issues/382):
Expand Down Expand Up @@ -128,6 +95,10 @@ vim.api.nvim_create_autocmd('User', {

### Show on newline, tab and space

::: warning
This may not be working as expected at the moment. Please see [#836](https://github.com/Saghen/blink.cmp/issues/836)
:::

Note that you may want to add the override to other sources as well, since if the LSP doesnt return any items, we won't show the menu if it was triggered by any of these three characters.

```lua
Expand Down Expand Up @@ -299,20 +270,6 @@ sources.min_keyword_length = function()
end
```

### Set minimum keyword length for command only in cmdline

If you'd prefer the menu doesn't popup when typing abbreviations like `wq`, you may set the minimum keyword length to 2 when typing the command.

```lua
sources = {
min_keyword_length = function(ctx)
-- only applies when typing a command, doesn't apply to arguments
if ctx.mode == 'cmdline' and string.find(ctx.line, ' ') == nil then return 2 end
return 0
end
}
```

### Path completion from `cwd` instead of current buffer's directory

It's common to run code from the root of your repository, in which case relative paths will start from that directory. In that case, you may want path completions to be relative to your current working directory rather than the default, which is the current buffer's parent directory.
Expand Down
6 changes: 6 additions & 0 deletions doc/vimdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ doc/configuration/sources.md
doc/configuration/reference.md
```

# Modes
```{.include shift-heading-level-by=1}
doc/modes/cmdline.md
doc/modes/term.md
```

# Development
```{.include shift-heading-level-by=1}
doc/development/architecture.md
Expand Down
2 changes: 2 additions & 0 deletions lua/blink/cmp/config/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ function M.apply_mode_specific(cfg)

apply_mode_specific_at_path({ 'completion', 'trigger', 'show_on_blocked_trigger_characters' })
apply_mode_specific_at_path({ 'completion', 'trigger', 'show_on_x_blocked_trigger_characters' })
apply_mode_specific_at_path({ 'completion', 'list', 'selection', 'preselect' })
apply_mode_specific_at_path({ 'completion', 'list', 'selection', 'auto_insert' })
apply_mode_specific_at_path({ 'completion', 'menu', 'auto_show' })
apply_mode_specific_at_path({ 'completion', 'menu', 'draw', 'columns' })
apply_mode_specific_at_path({ 'completion', 'ghost_text', 'enabled' })
Expand Down
Loading

0 comments on commit 54091b6

Please sign in to comment.