Option To Let Blink-cmp Autocomplete Keep The Capitalization Of The Currently Typed Word.
Introduction
As a writer, using Neovim to write is quite popular, and one of the features that make it efficient is the autocomplete capability provided by blink-cmp. However, when using this feature, the buffer autocomplete often replaces the currently typed word with one that has a different capitalization. This can be frustrating, especially when typing words like "capitalization" where the correct capitalization is crucial. In this article, we will explore the option to let blink-cmp autocomplete keep the capitalization of the currently typed word.
The Problem
When using blink-cmp's autocomplete feature, the buffer autocomplete looks at the words in the buffer and provides auto-completion capabilities with those. However, it will replace the currently typed word with one that has a different capitalization, if the word in the buffer had that capitalization. This is what blink-cmp's documentation suggests. The case for this being built-in is that using Neovim to write is quite popular, and there are very few edge cases to decide not to enable this feature. The second reason is that the alternative solution (which we haven't gotten to work) would be ugly (as blink-cmp's example shows).
To provide an example use case of this issue, if we wanted to auto-complete the word however (used above), with the buffer being the text above, it would complete to However, not however. Especially with words like capitalization, typing it out is unnecessarily inefficient.
The Solution
We would like an option to enable the previously described functionality. We don't know what the ideal implementation details would be. However, we can explore the alternatives and see if we can find a solution that works.
Alternatives
Blink-cmp offers a bit of a hacky solution as described above. Here is my attempt of getting this to work. Does not work!
autocomplete = {
"blink-cmp" = {
enable = true;
friendly-snippets.enable = true;
sourcePlugins.spell.enable = true;
setupOpts = {
sources = {
# List your desired sources including 'buffer'
default = ["lsp" "snippets" "copilot" "path" "spell"];
# --- Provider Specific Settings ---
providers = {
# Settings for the 'buffer' provider
buffer = {
# Integrate the transform_items function here
transform_items = lib.generators.mkLuaInline ''
function (a, items)
local keyword = a.get_keyword()
local correct, case
-- Check if keyword starts with a lowercase letter
if keyword:match('^%l') then
correct = '^%u%l+{{content}}#39; -- Pattern for correcting: Uppercase followed by lowercase
case = string.lower -- Function to apply to the first letter
-- Check if keyword starts with an uppercase letter
elseif keyword:match('^%u') then
correct = '^%l+{{content}}#39; -- Pattern for correcting: All lowercase
case = string.upper -- Function to apply to the first letter
-- If keyword doesn't start with a letter, do nothing else
return items
end
-- Avoid duplicates introduced by the case correction
local seen = {}
local out = {}
for _, item in ipairs(items) do
local raw = item.insertText
-- If the item matches the pattern needing correction
if raw:match(correct) then
-- Apply the case change to the first letter
local text = case(raw:sub(1,1)) .. raw:sub(2)
item.insertText = text
item.label = text -- Update the label as well
end
-- Only add the item if we haven't seen this insertText before
if not seen[item.insertText] then
seen[item.insertText] = true
table.insert(out, item)
end
end
return out -- Return the potentially modified and de-duplicated list
end
'';
};
copilot = {
name = "copilot";
module = lib.mkForce "blink-cmp-copilot";
score_offset = 100;
async = true;
};
};
};
};
};
};
Additional Context
There is no additional context to provide.
Conclusion
Q: What is the current issue with blink-cmp's autocomplete feature?
A: The current issue with blink-cmp's autocomplete feature is that it replaces the currently typed word with one that has a different capitalization, if the word in the buffer had that capitalization. This can be frustrating, especially when typing words like "capitalization" where the correct capitalization is crucial.
Q: Why is this issue important?
A: This issue is important because it can affect the accuracy and efficiency of writing in Neovim. When the autocomplete feature replaces the currently typed word with one that has a different capitalization, it can lead to errors and inconsistencies in the text.
Q: What are the alternatives to this feature?
A: One alternative to this feature is to use a different autocomplete plugin that does not have this issue. However, this may not be a viable option for users who are already invested in using blink-cmp. Another alternative is to use a hacky solution, such as the one provided in the original feature request, but this may not be efficient or effective.
Q: Why is this feature important for writers?
A: This feature is important for writers because it can help them to write more efficiently and accurately. When the autocomplete feature keeps the capitalization of the currently typed word, it can help writers to avoid errors and inconsistencies in the text.
Q: How can users implement this feature?
A: Users can implement this feature by adding the following code to their Neovim configuration file:
autocomplete = {
"blink-cmp" = {
enable = true;
friendly-snippets.enable = true;
sourcePlugins.spell.enable = true;
setupOpts = {
sources = {
# List your desired sources including 'buffer'
default = ["lsp" "snippets" "copilot" "path" "spell"];
# --- Provider Specific Settings ---
providers = {
# Settings for the 'buffer' provider
buffer = {
# Integrate the transform_items function here
transform_items = lib.generators.mkLuaInline ''
function (a, items)
local keyword = a.get_keyword()
local correct, case
-- Check if keyword starts with a lowercase letter
if keyword:match('^%l') then
correct = '^%u%l+{{content}}#39; -- Pattern for correcting: Uppercase followed by lowercase
case = string.lower -- Function to apply to the first letter
-- Check if keyword starts with an uppercase letter
elseif keyword:match('^%u') then
correct = '^%l+{{content}}#39; -- Pattern for correcting: All lowercase
case = string.upper -- Function to apply to the first letter
-- If keyword doesn't start with a letter, do nothing else
return items
end
-- Avoid duplicates introduced by the case correction
local seen = {}
local out = {}
for _, item in ipairs(items) do
local raw = item.insertText
-- If item matches the pattern needing correction
if raw:match(correct) then
-- Apply the case change to the first letter
local text = case(raw:sub(1,1)) .. raw:sub(2)
item.insertText = text
item.label = text -- Update the label as well
end
-- Only add the item if we haven't seen this insertText before
if not seen[item.insertText] then
seen[item.insertText] = true
table.insert(out, item)
end
end
return out -- Return the potentially modified and de-duplicated list
end
'';
};
copilot = {
name = "copilot";
module = lib.mkForce "blink-cmp-copilot";
score_offset = 100;
async = true;
};
};
};
};
};
};
Q: Is this feature already implemented in blink-cmp?
A: No, this feature is not already implemented in blink-cmp. However, the code provided above is a possible implementation of this feature.
Q: Can this feature be used with other autocomplete plugins?
A: Yes, this feature can be used with other autocomplete plugins. However, the implementation may vary depending on the specific plugin being used.
Q: How can users provide feedback on this feature?
A: Users can provide feedback on this feature by submitting a feature request to the blink-cmp developers. They can also provide feedback on the Neovim community forums or by submitting a pull request to the blink-cmp repository.