Skip to content

fix: cmdline config merge priority and mapping registration#2214

Open
divramod wants to merge 1 commit intohrsh7th:mainfrom
divramod:fix-cmdline-config-priority
Open

fix: cmdline config merge priority and mapping registration#2214
divramod wants to merge 1 commit intohrsh7th:mainfrom
divramod:fix-cmdline-config-priority

Conversation

@divramod
Copy link

Summary

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 too late - 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.

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

  • Set keyword_length = 4 in cmdline config, verify it uses 4 not global value
  • Add custom Tab mapping in cmdline config, verify it triggers
  • Verify normal insert mode completion still works correctly

🤖 Generated with Claude Code

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.
Copilot AI review requested due to automatic review settings January 31, 2026 10:00
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 CmdlineEnter handling 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.

Comment on lines 90 to +91
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))
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
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))

Copilot uses AI. Check for mistakes.
Comment on lines 105 to +106
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))
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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))

Copilot uses AI. Check for mistakes.
Comment on lines 123 to +126
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))
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment on lines +367 to +375
-- 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
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant