Coerce is a Neovim plugin that enables you to quickly change a keywordβs case. Coerceβs framework is also capable of any short-text, single-command text manipulation, e.g., turning selected text into its numeronym.
Install the plugin with your preferred package manager, such as Lazy:
{
"gregorias/coerce.nvim",
tag = 'v4.1.0',
config = true,
}
This plugin effectively replaces Abolishβs coercion functionality. If you wish to keep it for its other features, you can disable the coercion feature like so:
{
"tpope/vim-abolish",
init = function()
-- Disable coercion mappings. I use coerce.nvim for that.
vim.g.abolish_no_mappings = true
end,
}
You can use Coerce to coerce words into various cases using modes.
- A case is a function that changes a word into another word, e.g., the wordβs camel case version.
- A mode specifies how Coerce triggers, selects and transforms the word, e.g., select whatever is currently visually selected.
- Put the cursor inside a keyword.
- Press
crX
, whereX
stands for your desired case. Which key, if present, will show you hints.
Case | Key |
---|---|
camelCase | c |
dot.case | d |
kebab-case | k |
n12e | n |
PascalCase | p |
snake_case | s |
UPPER_CASE | u |
path/case | / |
space case | <space> |
Vim mode | Keymap prefix | Selector | Transformer |
---|---|---|---|
Normal | cr | current word | LSP rename/local |
Normal | gcr | motion selection | local |
Visual | gcr | visual selection | local |
The default visual prefix is gcr
and not cr
in order to avoid a conflict with
the default c
.
You may coerce a keyword in such a way that it stops being keyword, e.g., you
use the path case in most programming languages. In that case, just running
cr
again wonβt fully revert the case. Youβll need to visually select the word
to fix it.
To quickly select a changed keyword, you can configure a special keymap for doing that. For example, hereβs how I have it set up:
require"which-key".register({
g = {
p = {
-- "p" makes sense, gv selects the last Visual selection, so this one
-- selects the last pasted text.
function()
vim.api.nvim_feedkeys("`[" .. vim.fn.strpart(vim.fn.getregtype(), 0, 1) .. "`]", "n", false)
end,
"Switch to VISUAL using last paste/change",
},
},
})
With that, I can use gp
to select whatever I have just coerced.
The default configuration looks like so:
require"coerce".setup{
keymap_registry = require("coerce.keymap").keymap_registry(),
-- The notification function used during error conditions.
notify = function(...) return vim.notify(...) end,
default_mode_keymap_prefixes = {
normal_mode = "cr",
motion_mode = "gcr",
visual_mode = "gcr",
},
-- Set any field to false to disable that mode.
default_mode_mask = {
normal_mode = true,
motion_mode = true,
visual_mode = true,
},
-- If you donβt like the default cases and modes, you can override them.
cases = require"coerce".default_cases,
modes = require"coerce".get_default_modes(default_mode_mask, default_mode_keymap_prefixes),
}
You may freely modify the config parameters to your liking.
You can register a new case like so:
require"coerce".register_case{
keymap = "l",
case = function(str)
return vim.fn.tolower(str)
end,
description = "lowercase",
}
You can register a new mode like so:
require"coerce".register_mode{
vim_mode = "v",
keymap_prefix = "gc",
selector = function(cb)
local s, e = -- Your function that finds start and end points.
-- For example, returning {0, 0}, {0, 5} selects the first 6
-- characters of the current buffer.
local region_m = require"coerce.region"
cb(region_m(region_m.modes.INLINE, s, e))
end,
transformer = require"coerce.transformer".transform_local,
}
If you donβt like that the default normal mode binding uses LSP rename (e.g., because itβs too slow), you can provide your own implementation like so:
require"coerce".setup{
-- β¦
default_mode_mask = {
-- Disable the default `cr` binding.
normal_mode = false,
},
-- β¦
}
-- Register a custom `cr` binding that uses the local-only transformation.
require"coerce".register_mode{
vim_mode = "n",
keymap_prefix = "cr",
selector = require"coerce.selector".select_current_word,
transformer = require"coerce.transformer".transform_local,
}
Text-case is more feature-rich than Coerce, but if you just need to change case of the current keyword, Coerce is simpler.
Feature | Coerce | Text-case | Abolish |
---|---|---|---|
Full Unicode support | β | β | β |
Which Key integration | β | β | β |
nvim-notify integration | β | β | β |
Current keyword coerce | β | β | β |
Visual selection | β | β | β |
Motion selection | β | β | β |
LSP rename | β | β | β |
Kebab case | β | β | β |
Numeronym βcaseβ | β | β | β |
Dot repeat support | β | β | β |
Custom case support | β | β | β |
Custom mode support | β | β | β |
This plugin was inspired by Abolishβs coercion feature. I created this plugin to address Abolishβs shortcomings, which are:
- No integration with Which Key or Legendary.
- Little configurability. I couldnβt extend the plugin with new cases.
I used Text-caseβs source code to inform myself on how to do things in Neovim.
The logo is based on a fist SVG from SVG Repo.