feat: visual block mode support

This commit is contained in:
Chen Asraf
2023-05-18 02:22:11 +03:00
parent bcb5ee3704
commit 5765e3d721
8 changed files with 73 additions and 50 deletions

View File

@@ -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 |
| -------------- | --------------------------- | -------- |

View File

@@ -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()*

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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" },
},
}