We can now follow tags

This commit is contained in:
Rene Schallner
2021-12-09 05:40:53 +01:00
parent 0412051e74
commit 45eac53ecb
4 changed files with 258 additions and 26 deletions

View File

@@ -14,7 +14,6 @@ ignore = {
globals = { globals = {
"_", "_",
"vim",
"TelescopeGlobalState", "TelescopeGlobalState",
"_TelescopeConfigurationValues", "_TelescopeConfigurationValues",
"_TelescopeConfigurationPickers", "_TelescopeConfigurationPickers",

View File

@@ -1,5 +1,5 @@
return { return {
extension = { extension = {
['md'] = 'telekasten' ["md"] = "telekasten",
} },
} }

196
lua/taglinks/taglinks.lua Normal file
View File

@@ -0,0 +1,196 @@
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
while col >= 1 do
char = line:sub(col, col)
if seen_bracket then
if char == "[" then
return "link", col + 2
end
end
if char == "[" then
seen_bracket = 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
return "tag", col
end
if char == ":" and opts.tag_notation == ":tag:" then
return "tag", col
end
end
if char == " " or char == "\t" then
return nil, nil
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

View File

@@ -10,6 +10,7 @@ local previewers = require("telescope.previewers")
local make_entry = require("telescope.make_entry") local make_entry = require("telescope.make_entry")
local debug_utils = require("plenary.debug_utils") local debug_utils = require("plenary.debug_utils")
local filetype = require("plenary.filetype") local filetype = require("plenary.filetype")
local taglinks = require("taglinks/taglinks")
-- declare locals for the nvim api stuff to avoid more lsp warnings -- declare locals for the nvim api stuff to avoid more lsp warnings
local vim = vim local vim = vim
@@ -61,7 +62,11 @@ M.Cfg = {
}, },
close_after_yanking = false, close_after_yanking = false,
insert_after_inserting = true, insert_after_inserting = true,
install_syntax = true, install_syntax = true,
-- tag notation: '#tag', ':tag:', 'yaml-bare'
tag_notation = "#tag",
} }
local function file_exists(fname) local function file_exists(fname)
@@ -659,6 +664,13 @@ local function resolve_link(title)
return fexists, filename return fexists, filename
end end
-- local function check_for_link_or_tag()
local function check_for_link_or_tag()
local line = vim.api.nvim_get_current_line()
local col = vim.fn.col(".")
return taglinks.is_tag_or_link_at(line, col, M.Cfg)
end
-- --
-- FollowLink: -- FollowLink:
-- ----------- -- -----------
@@ -672,13 +684,29 @@ local function FollowLink(opts)
opts.close_after_yanking = opts.close_after_yanking opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking or M.Cfg.close_after_yanking
vim.cmd("normal yi]")
local title = vim.fn.getreg('"0')
title = title:gsub("^(%[)(.+)(%])$", "%2")
local search_mode = "files" local search_mode = "files"
local title
local filename = ""
local fexists
-- first: check if we're in a tag or a link
local kind, atcol = check_for_link_or_tag()
if kind == "tag" then
local tag = taglinks.get_tag_at(
vim.api.nvim_get_current_line(),
atcol,
M.Cfg
)
search_mode = "tag"
title = tag
else
-- we are in a link
vim.cmd("normal yi]")
title = vim.fn.getreg('"0')
title = title:gsub("^(%[)(.+)(%])$", "%2")
local parts = vim.split(title, "#") local parts = vim.split(title, "#")
local filename = ""
-- if there is a # -- if there is a #
if #parts ~= 1 then if #parts ~= 1 then
@@ -691,9 +719,6 @@ local function FollowLink(opts)
title = parts[2] title = parts[2]
end end
end end
local fexists
if #filename > 0 then if #filename > 0 then
fexists, filename = resolve_link(filename) fexists, filename = resolve_link(filename)
if fexists == false then if fexists == false then
@@ -701,6 +726,7 @@ local function FollowLink(opts)
filename = "" filename = ""
end end
end end
end
if search_mode == "files" then if search_mode == "files" then
-- check if fname exists anywhere -- check if fname exists anywhere
@@ -766,6 +792,16 @@ local function FollowLink(opts)
} }
end end
if search_mode == "tag" then
search_command = {
"rg",
"--vimgrep",
"-e",
prompt,
"--",
}
end
if #filename > 0 then if #filename > 0 then
table.insert(search_command, filename) table.insert(search_command, filename)
else else
@@ -1521,5 +1557,6 @@ M.find_friends = FindFriends
M.insert_img_link = InsertImgLink M.insert_img_link = InsertImgLink
M.preview_img = PreviewImg M.preview_img = PreviewImg
M.browse_media = BrowseImg M.browse_media = BrowseImg
M.taglinks = taglinks
return M return M