mirror of
https://github.com/chenasraf/text-transform.nvim.git
synced 2026-05-18 01:48:57 +00:00
feat: visual block mode support
This commit is contained in:
@@ -18,7 +18,13 @@ Transform the current word or selection between multiple case types. Need to eas
|
||||
with my_var or vice versa? This plugin is for you!
|
||||
|
||||
- Works on current word in **Normal Mode**
|
||||
- Will replace the current word selectable by <kbd>cw</kbd>
|
||||
- Works on selection in **Visual Mode**
|
||||
- Will replace only inside the selection
|
||||
- Works on column selections in **Visual Block Mode**
|
||||
- Will detect if the block is a single column or multiple columns
|
||||
- If it's a single column, will replace the word under each cursor
|
||||
- If it's a selection with length, will replace only inside the selection range
|
||||
|
||||
| Transformation | Example Inputs | Output |
|
||||
| -------------- | --------------------------- | -------- |
|
||||
|
||||
2
doc/tags
2
doc/tags
@@ -7,7 +7,7 @@ TextTransform.options text-transform.txt /*TextTransform.options*
|
||||
TextTransform.pascal_case() text-transform.txt /*TextTransform.pascal_case()*
|
||||
TextTransform.replace_at() text-transform.txt /*TextTransform.replace_at()*
|
||||
TextTransform.replace_columns() text-transform.txt /*TextTransform.replace_columns()*
|
||||
TextTransform.replace_selection() text-transform.txt /*TextTransform.replace_selection()*
|
||||
TextTransform.replace_cursor_range() text-transform.txt /*TextTransform.replace_cursor_range()*
|
||||
TextTransform.replace_word() text-transform.txt /*TextTransform.replace_word()*
|
||||
TextTransform.setup() text-transform.txt /*TextTransform.setup()*
|
||||
TextTransform.snake_case() text-transform.txt /*TextTransform.snake_case()*
|
||||
|
||||
@@ -78,11 +78,6 @@ Transforms a string into CONSTANT_CASE.
|
||||
`TextTransform.replace_at`({start_line}, {start_col}, {end_line}, {end_col}, {transform})
|
||||
Replaces the text at the given position with the given transform.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
*TextTransform.replace_selection()*
|
||||
`TextTransform.replace_selection`({transform})
|
||||
Replaces the current visual selection with the given transform.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
*TextTransform.replace_word()*
|
||||
`TextTransform.replace_word`({transform})
|
||||
@@ -91,7 +86,13 @@ Replaces the current word with the given transform.
|
||||
------------------------------------------------------------------------------
|
||||
*TextTransform.replace_columns()*
|
||||
`TextTransform.replace_columns`({transform})
|
||||
Replaces each column selection with the given transform.
|
||||
Replaces each column in visual block mode selection with the given transform.
|
||||
Assumes that the each selection is 1 character and operates on the whole word under each cursor.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
*TextTransform.replace_cursor_range()*
|
||||
`TextTransform.replace_cursor_range`({line}, {start_col}, {end_col}, {transform})
|
||||
Replaces each cursor selection range with the given transform.
|
||||
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
@@ -65,11 +65,7 @@ function TextTransform._setup()
|
||||
local v = map[k]
|
||||
vim.cmd("amenu TransformsWord." .. k .. " :lua TextTransform.replace_word('" .. v .. "')<CR>")
|
||||
vim.cmd(
|
||||
"amenu TransformsSelection."
|
||||
.. k
|
||||
.. " :lua TextTransform.replace_selection('"
|
||||
.. v
|
||||
.. "')<CR>"
|
||||
"amenu TransformsSelection." .. k .. " :lua TextTransform.replace_columns('" .. v .. "')<CR>"
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ end
|
||||
TextTransform.into_words = M.into_words
|
||||
TextTransform.replace_word = M.replace_word
|
||||
TextTransform.replace_selection = M.replace_selection
|
||||
TextTransform.replace_columns = M.replace_columns
|
||||
|
||||
TextTransform.camel_case = M.camel_case
|
||||
TextTransform.snake_case = M.snake_case
|
||||
|
||||
@@ -46,35 +46,44 @@ function TextTransform.disable()
|
||||
return S
|
||||
end
|
||||
|
||||
local function trim(s)
|
||||
return s:match("^%s*(.-)%s*$")
|
||||
end
|
||||
|
||||
--- Splits a string into words.
|
||||
function TextTransform.into_words(str)
|
||||
local words = {}
|
||||
local word = ""
|
||||
str = trim(str)
|
||||
|
||||
local previous_is_split_token = false
|
||||
for i = 1, #str do
|
||||
local char = str:sub(i, i)
|
||||
local is_upper = char:match("%u")
|
||||
local is_num = char:match("%d")
|
||||
local is_separator = char:match("[%_%-%s%.]")
|
||||
local is_split_token = is_upper or is_num
|
||||
-- split on uppercase letters or numbers
|
||||
if char:match("%u") or char:match("%d") and not previous_is_split_token then
|
||||
if is_split_token and not previous_is_split_token then
|
||||
if word ~= "" then
|
||||
table.insert(words, word)
|
||||
table.insert(words, trim(str):lower())
|
||||
end
|
||||
previous_is_split_token = true
|
||||
previous_is_split_token = is_split_token
|
||||
word = char
|
||||
-- split on underscores, hyphens, and spaces
|
||||
elseif char:match("[%_%-%s%.]") then
|
||||
elseif is_separator then
|
||||
if word ~= "" then
|
||||
table.insert(words, word)
|
||||
previous_is_split_token = false
|
||||
table.insert(words, trim(str):lower())
|
||||
previous_is_split_token = is_split_token
|
||||
end
|
||||
word = ""
|
||||
else
|
||||
word = word .. char
|
||||
previous_is_split_token = char:match("%u") or char:match("%d")
|
||||
previous_is_split_token = is_split_token
|
||||
end
|
||||
end
|
||||
if word ~= "" then
|
||||
table.insert(words, word)
|
||||
table.insert(words, trim(str):lower())
|
||||
previous_is_split_token = false
|
||||
end
|
||||
return words
|
||||
@@ -201,19 +210,6 @@ function TextTransform.replace_at(start_line, start_col, end_line, end_col, tran
|
||||
end
|
||||
end
|
||||
|
||||
--- Replaces the current visual selection with the given transform.
|
||||
function TextTransform.replace_selection(transform)
|
||||
-- get the current visual selection, and transform the line, only replacing the selected text itself
|
||||
local _, start_line, start_col = unpack(vim.fn.getpos("'<"))
|
||||
local _, end_line, end_col = unpack(vim.fn.getpos("'>"))
|
||||
|
||||
-- transform all included lines
|
||||
TextTransform.replace_at(start_line, start_col, end_line, end_col, transform)
|
||||
|
||||
-- move the cursor to the end of the transformed text
|
||||
vim.fn.cursor(end_line, end_col)
|
||||
end
|
||||
|
||||
--- Replaces the current word with the given transform.
|
||||
function TextTransform.replace_word(transform)
|
||||
local word = vim.fn.expand("<cword>")
|
||||
@@ -221,24 +217,40 @@ function TextTransform.replace_word(transform)
|
||||
vim.cmd("normal ciw" .. transformed)
|
||||
end
|
||||
|
||||
--- Replaces each column selection with the given transform.
|
||||
--- Replaces each column in visual block mode selection with the given transform.
|
||||
--- Assumes that the each selection is 1 character and operates on the whole word under each cursor.
|
||||
function TextTransform.replace_columns(transform)
|
||||
-- get each cursor position and apply to each cursor's word
|
||||
local cursors = vim.fn.getpos("'<")
|
||||
-- get all the multiple cursor positions
|
||||
local _, start_line, start_col = unpack(vim.fn.getpos("'<"))
|
||||
local _, end_line = unpack(vim.fn.getpos("'>"))
|
||||
|
||||
for _, cursor in ipairs(cursors) do
|
||||
-- unpack the cursor values
|
||||
local start_line, start_col, end_line, end_col = unpack(cursor)
|
||||
local line = vim.fn.getline(start_line)
|
||||
D.tprint({ start_line, start_col, end_line })
|
||||
|
||||
if start_col == end_col then
|
||||
-- if the cursor is one length, get the word under the cursor
|
||||
local word = line:match("%w+", start_col)
|
||||
TextTransform.replace_at(start_line, start_col, start_line, start_col + #word, transform)
|
||||
else
|
||||
-- otherwise, get the word between the cursors
|
||||
TextTransform.replace_at(start_line, start_col, end_line, end_col, transform)
|
||||
end
|
||||
-- for each cursor start_col, find the word under the cursor and transform it
|
||||
for line_num = start_line, end_line do
|
||||
-- get the line of this cursor
|
||||
local line = vim.fn.getline(line_num)
|
||||
-- match the surrounding word using start_col
|
||||
local word = line:match("[%w%_%-%s%.]+", start_col)
|
||||
-- replace the word with the transformed word
|
||||
TextTransform.replace_cursor_range(line_num, start_col, start_col + #word - 1, transform)
|
||||
end
|
||||
end
|
||||
|
||||
--- Replaces each cursor selection range with the given transform.
|
||||
function TextTransform.replace_cursor_range(line, start_col, end_col, transform)
|
||||
return TextTransform.replace_at(line, start_col, line, end_col, transform)
|
||||
end
|
||||
|
||||
function TextTransform.replace_selection(transform)
|
||||
-- determine if cursor is a 1-length column or a normal selection
|
||||
local is_column = vim.fn.getpos("'<")[2] == vim.fn.getpos("'>")[2]
|
||||
|
||||
if is_column then
|
||||
TextTransform.replace_columns(transform)
|
||||
else
|
||||
local _, start_line, start_col, end_col = unpack(vim.fn.getpos("'<"))
|
||||
TextTransform.replace_cursor_range(start_line, start_col, end_col, transform)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ T["into_words()"]["should split two words with no spaces"] = function()
|
||||
child.lua([[result = require('text-transform').into_words("helloWorld")]])
|
||||
eq_type_global(child, "result", "table")
|
||||
eq_global(child, "result[1]", "hello")
|
||||
eq_global(child, "result[2]", "World")
|
||||
eq_global(child, "result[2]", "world")
|
||||
end
|
||||
|
||||
T["into_words()"]["should split two words with dots"] = function()
|
||||
@@ -53,7 +53,7 @@ T["into_words()"]["should split two words with a number inside"] = function()
|
||||
child.lua([[result = require('text-transform').into_words("helloWorld123")]])
|
||||
eq_type_global(child, "result", "table")
|
||||
eq_global(child, "result[1]", "hello")
|
||||
eq_global(child, "result[2]", "World")
|
||||
eq_global(child, "result[2]", "world")
|
||||
eq_global(child, "result[3]", "123")
|
||||
end
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ local map = {
|
||||
{ "hello.world", "helloWorld" },
|
||||
{ "hello", "hello" },
|
||||
{ "helloWorld123", "helloWorld123" },
|
||||
{ "HELLO_WORLD", "helloWorld" },
|
||||
},
|
||||
["snake_case"] = {
|
||||
{ "helloWorld", "hello_world" },
|
||||
@@ -46,6 +47,7 @@ local map = {
|
||||
{ "hello.world", "hello_world" },
|
||||
{ "hello", "hello" },
|
||||
{ "helloWorld123", "hello_world_123" },
|
||||
{ "HELLO_WORLD", "hello_world" },
|
||||
},
|
||||
["pascal_case"] = {
|
||||
{ "hello_world", "HelloWorld" },
|
||||
@@ -54,6 +56,7 @@ local map = {
|
||||
{ "hello.world", "HelloWorld" },
|
||||
{ "hello", "Hello" },
|
||||
{ "helloWorld123", "HelloWorld123" },
|
||||
{ "HELLO_WORLD", "HelloWorld" },
|
||||
},
|
||||
["kebab_case"] = {
|
||||
{ "helloWorld", "hello-world" },
|
||||
@@ -62,6 +65,7 @@ local map = {
|
||||
{ "hello.world", "hello-world" },
|
||||
{ "hello", "hello" },
|
||||
{ "helloWorld123", "hello-world-123" },
|
||||
{ "HELLO_WORLD", "hello-world" },
|
||||
},
|
||||
["dot_case"] = {
|
||||
{ "helloWorld", "hello.world" },
|
||||
@@ -70,6 +74,7 @@ local map = {
|
||||
{ "hello.world", "hello.world" },
|
||||
{ "hello", "hello" },
|
||||
{ "helloWorld123", "hello.world.123" },
|
||||
{ "HELLO_WORLD", "hello.world" },
|
||||
},
|
||||
["const_case"] = {
|
||||
{ "helloWorld", "HELLO_WORLD" },
|
||||
@@ -78,6 +83,7 @@ local map = {
|
||||
{ "hello.world", "HELLO_WORLD" },
|
||||
{ "hello", "HELLO" },
|
||||
{ "helloWorld123", "HELLO_WORLD_123" },
|
||||
{ "HELLO_WORLD", "HELLO_WORLD" },
|
||||
},
|
||||
["title_case"] = {
|
||||
{ "helloWorld", "Hello World" },
|
||||
@@ -86,6 +92,7 @@ local map = {
|
||||
{ "hello.world", "Hello World" },
|
||||
{ "hello", "Hello" },
|
||||
{ "helloWorld123", "Hello World 123" },
|
||||
{ "HELLO_WORLD", "Hello World" },
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user