Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions lua/tirenvi/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ local defaults = {
monitor = true,
probe = false,
},
textobj = {
column = "l"
},
}

-----------------------------------------------------------------------
Expand All @@ -51,6 +54,13 @@ local function apply(opts)
end
end

---@param parser_map Parser[]
local function parse_version(parser_map)
for _, parser in pairs(parser_map) do
parser._iversion = M.version_to_integer(parser.required_version)
end
end

-----------------------------------------------------------------------
-- Public API
-----------------------------------------------------------------------
Expand All @@ -59,6 +69,21 @@ end
function M.setup(opts)
local merged = vim.tbl_deep_extend("force", {}, M, opts or {})
apply(merged)
parse_version(M.parser_map)
end

---@param version any
---@return integer|nil
function M.version_to_integer(version)
if type(version) ~= "string" then
return nil
end
local major, minor, patch = version:match("^(%d+)%.(%d+)%.?(%d*)$")
if not major then
return nil
end
local maj, min, pat = tonumber(major), tonumber(minor), tonumber(patch) or 0
return (maj * 100000 + min) * 100000 + pat
end

apply(vim.deepcopy(defaults))
Expand Down
3 changes: 2 additions & 1 deletion lua/tirenvi/core/flat_parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ local log = require("tirenvi.util.log")
local util = require("tirenvi.util.util")
local errors = require("tirenvi.util.errors")
local Blocks = require("tirenvi.core.blocks")
local config = require("tirenvi.config")

local fn = vim.fn

Expand Down Expand Up @@ -209,7 +210,7 @@ function M.check_command(parser)
})
return results
end
local installed = util.version_to_integer(installed_version)
local installed = config.version_to_integer(installed_version)
if not installed then
table.insert(results, {
status = "warn",
Expand Down
12 changes: 2 additions & 10 deletions lua/tirenvi/core/record.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local CONST = require("tirenvi.constants")
local config = require("tirenvi.config")
local Cell = require("tirenvi.core.cell")
local tir_vim = require("tirenvi.core.tir_vim")

local M = {}
M.plain = {}
Expand Down Expand Up @@ -44,15 +44,7 @@ end
---@return Record_grid
function M.grid.new_from_vi_line(vi_line)
vi_line = vi_line or ""
local pipe = config.marks.pipe
if vi_line:sub(1, #pipe) == pipe then
vi_line = vi_line:sub(#pipe + 1)
end

if vi_line:sub(- #pipe) == pipe then
vi_line = vi_line:sub(1, - #pipe - 1)
end
local cells = vim.split(vi_line, pipe, { plain = true })
local cells = tir_vim.get_cells(vi_line)
return grid_new(cells)
end

Expand Down
191 changes: 191 additions & 0 deletions lua/tirenvi/core/tir_vim.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
local config = require("tirenvi.config")
local log = require("tirenvi.util.log")

local pipe = config.marks.pipe
local plen = #pipe

local M = {}

-- private helpers

-- local function str_byteindex(line, char_index)
-- -- local char_index = vim.str_utfindex(str, byte_index)
-- -- vim.fn.strcharpart(str, start, len)
-- return vim.str_byteindex(line, char_index)
-- end

---@param line string
---@return boolean
local function start_with_pipe(line)
return line:sub(1, plen) == pipe
end

---@param line string
---@return boolean
local function end_with_pipe(line)
return line:sub(-plen) == pipe
end

---@param line string
---@return string
local function remove_start_pipe(line)
if start_with_pipe(line) then
line = line:sub(plen + 1)
end
return line
end

---@param line string
---@return string
local function remove_end_pipe(line)
if end_with_pipe(line) then
line = line:sub(1, -plen - 1)
end
return line
end

---@param base_pipe boolean
---@param target string
---@return boolean
local function same_block(base_pipe, target)
return base_pipe == M.has_pipe(target)
end

---@param lines string[]
---@param irow integer
---@param step integer -- -1 or 1
---@return integer
local function find_block_edge(lines, irow, step)
local base = lines[irow]
local base_pipe = M.has_pipe(base)
local index = irow + step
while index >= 1 and index <= #lines do
if not same_block(base_pipe, lines[index]) then
return index - step
end
index = index + step
end
return (step == -1) and 1 or #lines
end

-- public API

-----@param line string
-----@return integer[]
-- function M.get_cell_indexes(line)
-- local ndexes = {}
-- for ichar = 1, #line do
-- if line:sub(ichar, ichar + plen - 1) == pipe then
-- table.insert(ndexes, ichar)
-- end
-- end
-- return {}
-- end

---@param line string
---@return integer[]
function M.get_pipe_byte_position(line)
local indexes = {}
local index = 1
while index <= #line do
if line:sub(index, index + plen - 1) == pipe then
indexes[#indexes + 1] = index
index = index + plen
else
index = index + 1
end
end
if #indexes > 0 then
if indexes[1] ~= 1 then
table.insert(indexes, 1, 0)
end
end
return indexes
end

-----@param line string
-----@return integer[]
--function M.get_pipe_positions(line)
-- local indexes = M.get_pipe_indexes(line)
-- local positions = {}
-- for _, index in ipairs(indexes) do
-- positions[#positions + 1] = vim.str_utfindex(line, index - 1) + 1
-- end
-- return positions
--end

---@param byte_pos integer[]
---@param icol integer
---@return integer|nil
function M.get_current_col_index(byte_pos, icol)
for index, ibyte in ipairs(byte_pos) do
if icol < ibyte then
return index - 1
end
end
return nil
end

---@param lines string[]
---@param irow integer
---@return integer
function M.get_block_top_nrow(lines, irow)
return find_block_edge(lines, irow, -1)
end

---@param lines string[]
---@param irow integer
---@return integer
function M.get_block_bottom_nrow(lines, irow)
return find_block_edge(lines, irow, 1)
end

---@param count integer
---@return Range|nil
function M.get_block_range(count)
end

---@param line string
---@return string[]
function M.get_cells(line)
line = remove_start_pipe(line)
line = remove_end_pipe(line)
return vim.split(line, pipe, { plain = true })
end

---@param line string
---@return boolean
function M.has_pipe(line)
return line:find(pipe, 1, true) ~= nil
end

---@param lines string[]
---@param count integer
---@param is_around boolean
---@return Range|nil
function M.get_select(lines, count, is_around)
-- local mode = vim.fn.mode()
local irow, icol0 = unpack(vim.api.nvim_win_get_cursor(0))
local icol = icol0 + 1
local cline = vim.api.nvim_get_current_line()
local cbyte_pos = M.get_pipe_byte_position(cline)
if #cbyte_pos == 0 then
return nil
end
local colIndex = M.get_current_col_index(cbyte_pos, icol)
if not colIndex then
return nil
end
local trow = M.get_block_top_nrow(lines, irow)
local brow = M.get_block_bottom_nrow(lines, irow)
local tbyte_pos = M.get_pipe_byte_position(lines[trow])
local bbyte_pos = M.get_pipe_byte_position(lines[brow])
return {
start_row = trow,
end_row = brow,
start_col = tbyte_pos[colIndex] + (is_around and 0 or plen),
end_col = bbyte_pos[colIndex + 1] - 1
}
end

return M
3 changes: 2 additions & 1 deletion lua/tirenvi/core/vim_parser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local util = require("tirenvi.util.util")
local Blocks = require("tirenvi.core.blocks")
local Record = require("tirenvi.core.record")
local Attr = require("tirenvi.core.attr")
local tir_vim = require("tirenvi.core.tir_vim")
-- local log = require("tirenvi.util.log")

local M = {}
Expand Down Expand Up @@ -39,7 +40,7 @@ end
---@param vi_line string
---@return Record
local function tir_vim_to_ndjson(vi_line)
if util.has_pipe(vi_line) then
if tir_vim.has_pipe(vi_line) then
return Record.grid.new_from_vi_line(vi_line)
else
return Record.plain.new_from_vi_line(vi_line)
Expand Down
19 changes: 19 additions & 0 deletions lua/tirenvi/editor/motion.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
local config = require("tirenvi.config")
local buf_state = require("tirenvi.state.buf_state")
local tir_vim = require("tirenvi.core.tir_vim")

local M = {}

Expand Down Expand Up @@ -28,4 +29,22 @@ M.F = build_motion("F")
M.t = build_motion("t")
M.T = build_motion("T")

function M.g()
local bufnr = vim.api.nvim_get_current_buf()
local cursor = vim.api.nvim_win_get_cursor(0)
local row, col = cursor[1], cursor[2]
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
local top = tir_vim.get_block_top_nrow(lines, row)
vim.api.nvim_win_set_cursor(0, { top, col })
end

function M.G()
local bufnr = vim.api.nvim_get_current_buf()
local cursor = vim.api.nvim_win_get_cursor(0)
local row, col = cursor[1], cursor[2]
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
local bottom = tir_vim.get_block_bottom_nrow(lines, row)
vim.api.nvim_win_set_cursor(0, { bottom, col })
end

return M
45 changes: 45 additions & 0 deletions lua/tirenvi/editor/textobj.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
local tir_vim = require("tirenvi.core.tir_vim")
local buffer = require("tirenvi.state.buffer")
local config = require("tirenvi.config")
local log = require("tirenvi.util.log")

local M = {}

---@param is_around boolean|nil
local function setup_vl(is_around)
if vim.fn.mode() == "n" then
return
end
is_around = is_around or false
local count = vim.v.count1
local lines = buffer.get_lines(0, 0, -1, false)
local pos = tir_vim.get_select(lines, count, is_around)
if not pos then
return
end
vim.api.nvim_win_set_cursor(0, { pos.start_row, pos.start_col - 1, })
vim.api.nvim_feedkeys(vim.keycode("<C-v>"), "n", false)
vim.cmd("normal! o")
vim.api.nvim_win_set_cursor(0, { pos.end_row, pos.end_col - 1, })
end

function M.setup_vil()
setup_vl()
end

function M.setup_val()
setup_vl(true)
end

-- setup
function M.setup(opts)
vim.keymap.set({ "o", "x" }, "i" .. config.textobj.column, M.setup_vil, {
desc = "Inner column",
})

vim.keymap.set({ "o", "x" }, "a" .. config.textobj.column, M.setup_val, {
desc = "Around column",
})
end

return M
Loading
Loading