Files
telekasten.nvim/lua/taglinks/taglinks.lua
2022-04-17 20:39:51 +02:00

213 lines
5.3 KiB
Lua

local M = {}
M.is_tag_or_link_at = function(line, col, opts)
opts = opts or {}
local initial_col = col
local char
local is_tagline = opts.tag_notation == "yaml-bare"
and line:sub(1, 4) == "tags"
local seen_bracket = false
local seen_parenthesis = false
local cannot_be_tag = false
while col >= 1 do
char = line:sub(col, col)
if seen_bracket then
if char == "[" then
return "link", col + 2
end
end
if seen_parenthesis then
-- Media link, currently identified by not link nor tag
if char == "]" then
return nil, nil
end
end
if char == "[" then
seen_bracket = true
elseif char == "(" then
seen_parenthesis = true
end
if is_tagline == true then
if char == " " or char == "\t" or char == "," or char == ":" then
if col ~= initial_col then
return "tag", col + 1
end
end
else
if char == "#" and opts.tag_notation == "#tag" then
if not cannot_be_tag then
return "tag", col
end
end
if char == ":" and opts.tag_notation == ":tag:" then
if not cannot_be_tag then
return "tag", col
end
end
end
if char == " " or char == "\t" then
cannot_be_tag = true
end
col = col - 1
end
return nil, nil
end
M.get_tag_at = function(line, col, opts)
-- we ignore the rule: no tags begin with a numeric digit
local endcol = col + 1
local pattern = "[%w-_/]"
local char
while endcol <= #line do
char = line:sub(endcol, endcol)
if char:match(pattern) == nil then
if opts.tag_notation == ":tag:" then
if char == ":" then
local tag = line:sub(col, endcol)
return tag
end
else
return line:sub(col, endcol - 1)
end
end
endcol = endcol + 1
end
-- we exhausted the line
return line:sub(col, endcol)
end
-------------
-- testing --
-------------
local function _eval(line, col, opts)
local kind, newcol = M.is_tag_or_link_at(line, col, opts)
return { kind = kind, col = newcol, line = line }
end
local function _print_debug(x, prefix)
prefix = prefix or ""
for k, v in pairs(x) do
print(prefix .. k .. ": " .. tostring(v))
end
end
local function _expect(x, y)
for k, v in pairs(y) do
if x[k] ~= v then
print("expected:")
_print_debug(y, " ")
print("got:")
_print_debug(x, " ")
assert(false)
end
end
end
M._testme = function()
local line = ""
local col = 10
local opts = {}
local tag
local ret
assert(_eval(line, col, opts).kind == nil)
-- #tags
opts.tag_notation = "#tag"
line = "this is a #tag in a line"
-- lets find it
col = 13
_expect(_eval(line, col, opts), { col = 11, kind = "tag" })
ret = _eval(line, col, opts)
tag = M.get_tag_at(line, ret.col, opts)
-- print('tag .. `' .. tag .. '`')
assert(tag == "#tag")
-- lets be in the space after
col = 15
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- lets be in the next word
col = 16
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- lets be in the prev word
col = 9
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- lets change the tag notation but hit the tag col
col = 13
opts.tag_notation = ":tag:"
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- :tags:
opts.tag_notation = ":tag:"
line = "this is a :tag: in a line"
-- lets find it
col = 13
_expect(_eval(line, col, opts), { col = 11, kind = "tag" })
ret = _eval(line, col, opts)
tag = M.get_tag_at(line, ret.col, opts)
assert(tag == ":tag:")
-- lets be in the space after
col = 16
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- lets be in the next word
col = 17
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- lets be in the prev word
col = 9
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- lets change the tag notation but hit the tag col
col = 13
opts.tag_notation = "#tag"
_expect(_eval(line, col, opts), { col = nil, kind = nil })
-- tagline
line = "tags: [ first, second, third]"
opts.tag_notation = "yaml-bare"
col = 13
_expect(_eval(line, col, opts), { col = 9, kind = "tag" })
ret = _eval(line, col, opts)
tag = M.get_tag_at(line, ret.col, opts)
assert(tag == "first")
col = 9
_expect(_eval(line, col, opts), { col = 9, kind = "tag" })
col = 14
_expect(_eval(line, col, opts), { col = nil, kind = nil })
col = 18
_expect(_eval(line, col, opts), { col = 16, kind = "tag" })
--
line = "this is a [[link]] line"
col = 13
_expect(_eval(line, col, opts), { col = 13, kind = "link" })
line = "this is a [[link]] line"
col = 15
_expect(_eval(line, col, opts), { col = 13, kind = "link" })
end
return M