fix: cmdline config merge priority and mapping registration#2214
fix: cmdline config merge priority and mapping registration#2214divramod wants to merge 1 commit intohrsh7th:mainfrom
Conversation
Two related fixes for cmdline completion: 1. Config merge priority order was backwards - global config was merged LAST, causing it to override more specific configs (cmdline, filetype, buffer). Fixed merge order so cmdline-specific settings (like keyword_length) properly override global defaults. 2. Cmdline mappings were registered via debounce_next_tick, which caused them to be registered after mode detection became unreliable. Now calling prepare() directly on CmdlineEnter ensures mappings are registered while is_cmdline_mode() still returns true. These fixes together resolve issues with custom cmdline mappings and settings not being applied correctly.
There was a problem hiding this comment.
Pull request overview
Fixes cmdline completion behavior by adjusting configuration precedence and ensuring cmdline mappings are registered early enough during CmdlineEnter to be detected reliably.
Changes:
- Replaces debounced
CmdlineEnterhandling with an immediate handler to register cmdline mappings while still in cmdline mode. - Modifies config merge ordering for onetime/cmdline/default scopes to change which config takes precedence.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| lua/cmp/init.lua | Registers cmdline mappings immediately on CmdlineEnter instead of deferring to next tick. |
| lua/cmp/config.lua | Changes merge order for global/onetime/cmdline/filetype/buffer configs (currently alters precedence). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| local c = {} | ||
| c = misc.merge(c, config.normalize(onetime_config)) | ||
| c = misc.merge(c, config.normalize(global_config)) | ||
| c = misc.merge(c, config.normalize(onetime_config)) |
There was a problem hiding this comment.
misc.merge(tbl1, tbl2) gives precedence to tbl1 (see lua/cmp/utils/misc.lua:92-120 and lua/cmp/utils/misc_spec.lua:58-66, where a non-table value in tbl1 overrides tbl2). With the current order, global_config is merged into c first and then c is merged into onetime_config, which makes the already-populated c (global) override oneshot values. To make oneshot config take priority over global defaults, merge the oneshot config as the first argument (or revert to the previous merge order).
| c = misc.merge(c, config.normalize(global_config)) | |
| c = misc.merge(c, config.normalize(onetime_config)) | |
| -- Ensure oneshot config takes precedence over global defaults. | |
| c = misc.merge(config.normalize(onetime_config), config.normalize(global_config)) |
| local c = {} | ||
| c = misc.merge(c, config.normalize(cmdline_config)) | ||
| c = misc.merge(c, config.normalize(global_config)) | ||
| c = misc.merge(c, config.normalize(cmdline_config)) |
There was a problem hiding this comment.
In the cmdline branch, the new merge order makes global_config override cmdline_config because misc.merge prefers values from its first argument. This will cause cmp.setup.cmdline() settings (e.g. keyword_length, cmdline mappings) to be ignored again. Swap the merge order (or swap merge arguments) so cmdline config has higher precedence than global.
| c = misc.merge(c, config.normalize(global_config)) | |
| c = misc.merge(c, config.normalize(cmdline_config)) | |
| c = misc.merge(c, config.normalize(cmdline_config)) | |
| c = misc.merge(c, config.normalize(global_config)) |
| local c = {} | ||
| c = misc.merge(config.normalize(c), config.normalize(buffer_config)) | ||
| c = misc.merge(config.normalize(c), config.normalize(filetype_config)) | ||
| c = misc.merge(config.normalize(c), config.normalize(global_config)) | ||
| c = misc.merge(config.normalize(c), config.normalize(filetype_config)) | ||
| c = misc.merge(config.normalize(c), config.normalize(buffer_config)) |
There was a problem hiding this comment.
In the default (buffer/filetype) branch, merging global_config first and then repeatedly calling misc.merge(c, filetype_config) / misc.merge(c, buffer_config) results in c (global) overriding filetype/buffer settings (since misc.merge prefers its first argument). To keep the intended precedence (buffer > filetype > global), merge the more-specific configs as the first argument (or restore the previous merge sequence).
| -- Separate handler for CmdlineEnter that doesn't debounce | ||
| -- This ensures we register cmdline mappings immediately while still in cmdline mode | ||
| local on_cmdline_enter = function() | ||
| if config.enabled() then | ||
| cmp.config.compare.scopes:update() | ||
| cmp.config.compare.locality:update() | ||
| cmp.core:prepare() | ||
| cmp.core:on_change('InsertEnter') | ||
| end |
There was a problem hiding this comment.
on_cmdline_enter duplicates on_insert_enter’s body. To reduce maintenance risk (future changes needing to be kept in sync), consider extracting the shared body into a helper and calling it from both handlers, or reusing on_insert_enter directly for CmdlineEnter (without debounce).
Summary
Two related fixes for cmdline completion:
Config merge priority order was backwards - global config was merged LAST, causing it to override more specific configs (cmdline, filetype, buffer). Fixed merge order so cmdline-specific settings (like
keyword_length) properly override global defaults.Cmdline mappings were registered too late - mappings were registered via
debounce_next_tick, which caused them to be registered after mode detection became unreliable. Now callingprepare()directly onCmdlineEnterensures mappings are registered whileis_cmdline_mode()still returns true.Problem
When configuring cmdline completion with
cmp.setup.cmdline(':', {...}), the settings were being ignored because global config was merged last and overrode them. Additionally, custom cmdline mappings weren't being registered because the timing was off.Test plan
keyword_length = 4in cmdline config, verify it uses 4 not global value🤖 Generated with Claude Code