diff --git a/lua/core/horiz.lua b/lua/core/horiz.lua deleted file mode 100644 index 55c0ea9..0000000 --- a/lua/core/horiz.lua +++ /dev/null @@ -1,106 +0,0 @@ -local M = {} - --- Moves the character under the cursor to the left or right --- Updates the cursor position. -M.horzChar = function(dir) - -- sRow and col: current cursor position - local sRow, col = unpack(vim.api.nvim_win_get_cursor(0)) - - local line = vim.api.nvim_get_current_line() - - local target = '' - local prefix = '' - local suffix = '' - local result = {} - local line_res = '' - - -- Checks line limits with the direction - if dir < 0 and col < 1 then - return - end - - local selected = string.sub(line, col + 1, col + 1) - - -- Put a space if the character reaches the end of the line - if col == line:len() - 1 and dir > 0 then - target = ' ' - else - target = string.sub(line, col + 1 + dir, col + 1 + dir) - end - - prefix = string.sub(line, 1, col + (dir > 0 and 0 or -1)) - suffix = string.sub(line, col + (dir > 0 and 3 or 2)) - - -- Remove trailing spaces before putting into the table - line_res = prefix..(dir > 0 and target..selected or selected..target)..suffix - line_res = line_res:gsub('%s+$', '') - - table.insert(result, line_res) - - -- Update the line with the new one and update cursor position - vim.api.nvim_buf_set_lines(0, sRow - 1, sRow, true, result) - vim.api.nvim_win_set_cursor(0, { sRow, col + dir }) -end - --- Moves the visual area left or right --- and keeps it selected -M.horzBlock = function(dir) - -- Get the boundries (cols) of the visual area - local sCol = vim.fn.col("'<") - local eCol = vim.fn.col("'>") - - -- The current line of the cursor will be the last line - -- of the visual area and eRow will be the first line - local sRow, col = unpack(vim.api.nvim_win_get_cursor(0)) - local eRow = vim.fn.line("'>") - - local lines = vim.api.nvim_buf_get_lines(0, sRow - 1, eRow, true) - local line = '' - local selected = '' - local prefix = '' - local suffix = '' - local results = {} - - -- Iterates over the lines of the visual area - for _, v in ipairs(lines) do - local target = '' - - if dir > 0 then - if eCol == v:len() then - target = ' ' - else - target = string.sub(v, eCol + 1 , eCol + 1) - end - - selected = string.sub(v, sCol, eCol) - prefix = string.sub(v, 1, sCol - 1) - suffix = string.sub(v, eCol + 2) - else - if col == 0 then - return - end - - target = string.sub(v, sCol - 1, sCol - 1) - selected = string.sub(v, sCol, eCol) - prefix = string.sub(v, 1, sCol - 2) - suffix = string.sub(v, eCol + 1) - end - -- Remove trailing spaces from the lines before - -- inserting them into the results table - line = prefix..(dir > 0 and target..selected or selected..target)..suffix - line = line:gsub('%s+$', '') - - table.insert(results, line) - end - - vim.api.nvim_buf_set_lines(0, sRow - 1, eRow, true, results) - vim.api.nvim_win_set_cursor(0, { sRow, (sCol - 1) + dir }) - - -- Update the visual area with the new position of the characters - vim.cmd('execute "normal! \\e\\e"') - local cmd_suffix = (eCol - sCol > 0 and (eCol - sCol)..'l' or '') - cmd_suffix = cmd_suffix..(eRow - sRow > 0 and (eRow - sRow)..'j' or '') - vim.cmd('execute "normal! \\'..cmd_suffix..'"') -end - -return M diff --git a/lua/move/core/horiz.lua b/lua/move/core/horiz.lua new file mode 100644 index 0000000..ad48971 --- /dev/null +++ b/lua/move/core/horiz.lua @@ -0,0 +1,149 @@ +local utils = require('move.utils') + +local M = {} + +-- Moves the character under the cursor to the left or right +-- Updates the cursor position. +M.horzChar = function(dir) + -- sRow and col: current cursor position + local sRow, col = unpack(vim.api.nvim_win_get_cursor(0)) + + local line = vim.api.nvim_get_current_line() + + local target = '' + local prefix = '' + local suffix = '' + local result = {} + local line_res = '' + local selected = '' + + local sChar = '' + local tChar = '' + + -- Checks line limits with the direction + if dir < 0 and col < 1 then + return + end + + -- Default + prefix = string.sub(line, 1, col + (dir > 0 and 0 or dir)) + + -- Unicode or tilde character + sChar = utils.curUnicodeOrTilde() + selected = utils.getChar() + + -- Check if target is unicode or tilde + -- move cursor to get the character + if dir < 0 then + vim.cmd(':normal! h') + end + tChar = utils.curUnicodeOrTilde() + + -- Put a space if the character reaches the end of the line + -- Default + target = utils.getChar() + suffix = string.sub(line, col + (dir > 0 and 3 or 2)) + + -- Character under cursor is unicode or tilde + if utils.isTilde(sChar) or utils.isUnicode(sChar) then + if utils.isUnicode(sChar) then + suffix = utils.suffixUnicode(tChar, sChar, line, col, dir) + else + suffix = utils.suffixTilde(tChar, sChar, line, col, dir) + end + else + -- Target character is tilde or unicode + if utils.isTilde(tChar) or utils.isUnicode(tChar) then + if utils.isUnicode(tChar) then + suffix = utils.suffixUnicode(tChar, sChar, line, col, dir) + else + suffix = utils.suffixTilde(tChar, sChar, line, col, dir) + end + end + end + + if utils.isTilde(tChar) or utils.isUnicode(tChar) then + if utils.isUnicode(tChar) then + prefix = string.sub(line, 1, col + (dir < 0 and -3 or 0)) + else + prefix = string.sub(line, 1, col + (dir < 0 and -2 or 0)) + end + end + + -- Return cursor position to original + vim.api.nvim_win_set_cursor(0, { sRow, col }) + + if dir > 0 then + if col == line:len() - utils.calc_eolOffset(sChar) then + target = ' ' + end + end + + -- Remove trailing spaces before putting into the table + line_res = prefix .. (dir > 0 and target .. selected or selected .. target) .. suffix + line_res = line_res:gsub('%s+$', '') + + table.insert(result, line_res) + + -- Update the line with the new one and update cursor position + vim.api.nvim_buf_set_lines(0, sRow - 1, sRow, true, result) + vim.api.nvim_win_set_cursor(0, { sRow, col + utils.cursor_offset(tChar, sChar, dir) }) +end + + +-- Moves the visual area left or right +-- and keeps it selected +M.horzBlock = function(dir) + -- Get the boundries (cols) of the visual area + local sCol = vim.fn.col("'<") + local eCol = vim.fn.col("'>") + + -- The current line of the cursor will be the last line + -- of the visual area and eRow will be the first line + local sRow, col = unpack(vim.api.nvim_win_get_cursor(0)) + local eRow = vim.fn.line("'>") + + -- Checks line limits with the direction + if dir < 0 and col < 1 then + vim.cmd('execute "normal! \\' .. (eCol - sCol) .. 'l' .. (eRow - sRow) .. 'j' .. '"') + return + end + + local offset_composite = 0 + vim.api.nvim_win_set_cursor(0, { sRow, sCol - 1 }) + + local i = sCol + + while i < eCol + 1 do + local comp = utils.isCharComposite() + if comp then + local char = utils.getCharNew() + local offset = utils.getSize(char) + offset_composite = offset_composite + utils.getSize(char) - 1 + print('col '..i, 'offComp '..offset_composite, 'offset '..offset, 'char '..char) + i = i + offset + else + i = i + 1 + end + vim.api.nvim_win_set_cursor(0, { sRow, i - 1 }) + end + + vim.api.nvim_win_set_cursor(0, { sRow, sCol - 1 }) + vim.cmd('execute "normal! \\' .. (eCol - sCol - offset_composite) .. 'l' .. (eRow - sRow) .. 'j' .. '"') + vim.cmd(':normal! x') + + if dir > 0 then + vim.cmd(':normal! p') + else + vim.api.nvim_win_set_cursor(0, { sRow, sCol - 2 }) + vim.cmd(':normal! P') + end + + -- Update the visual area with the new position of the characters + vim.cmd('execute "normal! \\e\\e"') + local cmd_suffix = (eCol - sCol > 0 and (eCol - sCol - offset_composite) .. 'l' or '') + cmd_suffix = cmd_suffix .. (eRow - sRow > 0 and (eRow - sRow) .. 'j' or '') + vim.cmd('execute "normal! \\' .. cmd_suffix .. '"') +end + +return M diff --git a/lua/core/vert.lua b/lua/move/core/vert.lua similarity index 98% rename from lua/core/vert.lua rename to lua/move/core/vert.lua index beb578b..546d6ee 100644 --- a/lua/core/vert.lua +++ b/lua/move/core/vert.lua @@ -1,4 +1,4 @@ -local utils = require('utils') +local utils = require('move.utils') local M = {} diff --git a/lua/move.lua b/lua/move/init.lua similarity index 61% rename from lua/move.lua rename to lua/move/init.lua index dee6b75..41d3a79 100644 --- a/lua/move.lua +++ b/lua/move/init.lua @@ -1,5 +1,5 @@ -local move_vert = require('core.vert') -local move_hor = require('core.horiz') +local move_hor = require('move.core.horiz') +local move_vert = require('move.core.vert') return { MoveLine = move_vert.moveLine, diff --git a/lua/utils/init.lua b/lua/move/utils/init.lua similarity index 58% rename from lua/utils/init.lua rename to lua/move/utils/init.lua index 2405b93..e3993cf 100644 --- a/lua/utils/init.lua +++ b/lua/move/utils/init.lua @@ -113,7 +113,147 @@ M.indent = function(amount, sLine, eLine) elseif diff > 0 then vim.cmd('silent! '..cRow..','..eRow..string.rep('>', diff)) end +end + +M.calc_eolOffset = function(char) + local eolOffset = 1 + + if M.isUnicode(char) then + eolOffset = 3 + elseif M.isTilde(char) then + eolOffset = 2 + end + + return eolOffset +end + +M.cursor_offset = function(tChar, sChar, dir) + local offset = 0 + + if M.isUnicode(tChar) then + offset = 3 + (M.isUnicode(sChar) and dir < 0 and -2 or 0) + elseif M.isTilde(tChar) then + offset = 2 + (M.isTilde(sChar) and dir < 0 and -1 or 0) + else + offset = 1 + end + + return offset * dir +end + +M.isTilde = function(char) + return char:len() > 2 +end + +M.isUnicode = function(char) + return char:len() > 5 +end + +M.isCharComposite = function() + local char = vim.api.nvim_exec(':normal! g8', true) + char = string.gsub(char, '%s+$', '') + return char:len() > 2 +end + +M.getChar = function() + vim.cmd(':normal! x') + return vim.fn.getreg('"0') +end + +M.getCharNew = function() + local char = vim.api.nvim_exec(':normal! g8', true) + char = string.gsub(char, '%s+$', '') + return char +end + +M.getVisualChar = function(sCol, eCol) + vim.cmd(':normal! v'..(eCol - sCol)..'l') + vim.cmd(':normal! x') + return vim.fn.getreg('"0') +end + +M.curUnicodeOrTilde = function() + local uni = '' + + uni = vim.api.nvim_exec(':normal! g8', true) + uni = string.gsub(uni, '%s+$', '') + return uni +end + +M.suffixUnicode = function(tChar, sChar, line, col, dir) + local suffix = '' + local offset = 0 + + if dir > 0 then + if M.isUnicode(tChar) then + if M.isUnicode(sChar) then + offset = 7 + else + offset = 5 + end + elseif M.isTilde(tChar) then + if M.isUnicode(sChar) then + offset = 6 + end + else + offset = 5 + end + else + if M.isUnicode(tChar) then + if M.isUnicode(sChar) then + offset = 4 + else + offset = 2 + end + else + offset = 4 + end + end + + suffix = string.sub(line, col + offset) + + return suffix +end + +M.suffixTilde = function(tChar, sChar, line, col, dir) + local suffix = '' + local offset = 0 + + if dir > 0 then + if M.isTilde(sChar) then + if M.isUnicode(tChar) then + offset = 6 + elseif M.isTilde(tChar) then + offset = 5 + else + offset = 4 + end + else + if M.isTilde(tChar) then + offset = 4 + end + end + else + if M.isTilde(sChar) then + offset = 3 + elseif M.isTilde(tChar) then + offset = 2 + end + end + + suffix = string.sub(line, col + offset) + + return suffix +end + +M.getSize = function(char) + local t = {} + + for w in string.gmatch(char, "%w+") do + table.insert(t, w) + end + return #t end return M