mirror of
https://github.com/Ascyii/telekasten.nvim.git
synced 2026-01-01 06:14:23 -05:00
refactor: escape paths and titles, introduce pinfo
This commit is contained in:
@@ -103,6 +103,11 @@ local function file_exists(fname)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- escapes a string for use as exact pattern within gsub
|
||||||
|
local function escape(s)
|
||||||
|
return string.gsub(s, "[%%%]%^%-$().[*+?]", "%%%1")
|
||||||
|
end
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------
|
||||||
-- image stuff
|
-- image stuff
|
||||||
local function imgFromClipboard()
|
local function imgFromClipboard()
|
||||||
@@ -340,47 +345,74 @@ local function create_note_from_template(
|
|||||||
ofile:close()
|
ofile:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function num_path_elems(p)
|
--- Pinfo
|
||||||
return #vim.split(p, "/")
|
--- - fexists : true if file exists
|
||||||
|
--- - title : the title (filename including subdirs without extension)
|
||||||
|
--- - if opts.subdirs_in_links is false, no subdirs will be included
|
||||||
|
--- - filename : filename component only
|
||||||
|
--- - filepath : full path, identical to p
|
||||||
|
--- - root_dir : the root dir (home, dailies, ...)
|
||||||
|
--- - sub_dir : subdir if present, relative to root_dir
|
||||||
|
--- - is_daily_or_weekly : bool
|
||||||
|
local Pinfo = {
|
||||||
|
fexists = false,
|
||||||
|
title = "",
|
||||||
|
filename = "",
|
||||||
|
filepath = "",
|
||||||
|
root_dir = "",
|
||||||
|
sub_dir = "",
|
||||||
|
is_daily_or_weekly = false,
|
||||||
|
}
|
||||||
|
function Pinfo:new(o)
|
||||||
|
o = o or {}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
end
|
end
|
||||||
|
|
||||||
local function path_to_linkname(p, opts)
|
--- resolve_path(p, opts)
|
||||||
local ln
|
--- inspects the path and returns a Pinfo table
|
||||||
|
local function resolve_path(p, opts)
|
||||||
|
-- print("resolving path ", p)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
opts.subdirs_in_links = opts.subdirs_in_links or M.Cfg.subdirs_in_links
|
opts.subdirs_in_links = opts.subdirs_in_links or M.Cfg.subdirs_in_links
|
||||||
|
|
||||||
local special_dir = false
|
local pinfo = Pinfo:new()
|
||||||
if
|
pinfo.fexists = file_exists(p)
|
||||||
M.Cfg.dailies
|
pinfo.filepath = p
|
||||||
and num_path_elems(p:gsub(M.Cfg.dailies .. "/", "")) == 1
|
pinfo.root_dir = M.Cfg.home
|
||||||
then
|
pinfo.is_daily_or_weekly = false
|
||||||
ln = p:gsub(M.Cfg.dailies .. "/", "")
|
|
||||||
special_dir = true
|
-- strip all dirs to get filename
|
||||||
|
local pp = Path:new(p)
|
||||||
|
local p_splits = pp:_split()
|
||||||
|
pinfo.filename = p_splits[#p_splits]
|
||||||
|
pinfo.title = pinfo.filename:gsub(M.Cfg.extension, "")
|
||||||
|
|
||||||
|
if vim.startswith(p, M.Cfg.home) then
|
||||||
|
pinfo.root_dir = M.Cfg.home
|
||||||
|
end
|
||||||
|
if vim.startswith(p, M.Cfg.dailies) then
|
||||||
|
pinfo.root_dir = M.Cfg.dailies
|
||||||
|
pinfo.is_daily_or_weekly = true
|
||||||
|
end
|
||||||
|
if vim.startswith(p, M.Cfg.weeklies) then
|
||||||
|
pinfo.root_dir = M.Cfg.weeklies
|
||||||
|
pinfo.is_daily_or_weekly = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if
|
-- now work out subdir relative to root
|
||||||
M.Cfg.weeklies
|
pinfo.sub_dir = p
|
||||||
and num_path_elems(p:gsub(M.Cfg.weeklies .. "/", "")) == 1
|
:gsub(escape(pinfo.root_dir .. "/"), "")
|
||||||
then
|
:gsub(escape(pinfo.filename), "")
|
||||||
ln = p:gsub(M.Cfg.weeklies .. "/", "")
|
:gsub("/$", "")
|
||||||
special_dir = true
|
:gsub("^/", "")
|
||||||
|
|
||||||
|
if opts.subdirs_in_links and #pinfo.sub_dir > 0 then
|
||||||
|
pinfo.title = pinfo.sub_dir .. "/" .. pinfo.title
|
||||||
end
|
end
|
||||||
|
|
||||||
if special_dir == false then
|
return pinfo
|
||||||
ln = p:gsub(M.Cfg.home .. "/", "")
|
|
||||||
end
|
|
||||||
|
|
||||||
if not opts.subdirs_in_links then
|
|
||||||
-- strip all subdirs
|
|
||||||
local pp = Path:new(ln)
|
|
||||||
local splits = pp:_split()
|
|
||||||
ln = splits[#splits]
|
|
||||||
end
|
|
||||||
|
|
||||||
local title = vim.split(ln, M.Cfg.extension)
|
|
||||||
title = title[1]
|
|
||||||
return title
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function order_numeric(a, b)
|
local function order_numeric(a, b)
|
||||||
@@ -474,7 +506,7 @@ local function find_files_sorted(opts)
|
|||||||
local function iconic_display(display_entry)
|
local function iconic_display(display_entry)
|
||||||
local display_opts = {
|
local display_opts = {
|
||||||
path_display = function(_, e)
|
path_display = function(_, e)
|
||||||
return e:gsub(opts.cwd .. "/", "")
|
return e:gsub(escape(opts.cwd .. "/"), "")
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,8 +696,8 @@ function picker_actions.paste_link(opts)
|
|||||||
return function(prompt_bufnr)
|
return function(prompt_bufnr)
|
||||||
actions.close(prompt_bufnr)
|
actions.close(prompt_bufnr)
|
||||||
local selection = action_state.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
local fn = path_to_linkname(selection.value, opts)
|
local pinfo = resolve_path(selection.filename or selection.value, opts)
|
||||||
local title = "[[" .. fn .. "]]"
|
local title = "[[" .. pinfo.title .. "]]"
|
||||||
vim.api.nvim_put({ title }, "", true, true)
|
vim.api.nvim_put({ title }, "", true, true)
|
||||||
if opts.insert_after_inserting or opts.i then
|
if opts.insert_after_inserting or opts.i then
|
||||||
vim.api.nvim_feedkeys("A", "m", false)
|
vim.api.nvim_feedkeys("A", "m", false)
|
||||||
@@ -681,8 +713,8 @@ function picker_actions.yank_link(opts)
|
|||||||
actions.close(prompt_bufnr)
|
actions.close(prompt_bufnr)
|
||||||
end
|
end
|
||||||
local selection = action_state.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
local fn = path_to_linkname(selection.value, opts)
|
local pinfo = resolve_path(selection.filename or selection.value, opts)
|
||||||
local title = "[[" .. fn .. "]]"
|
local title = "[[" .. pinfo.title .. "]]"
|
||||||
vim.fn.setreg('"', title)
|
vim.fn.setreg('"', title)
|
||||||
print("yanked " .. title)
|
print("yanked " .. title)
|
||||||
end
|
end
|
||||||
@@ -693,7 +725,7 @@ function picker_actions.paste_img_link(opts)
|
|||||||
actions.close(prompt_bufnr)
|
actions.close(prompt_bufnr)
|
||||||
local selection = action_state.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
local fn = selection.value
|
local fn = selection.value
|
||||||
fn = fn:gsub(M.Cfg.home .. "/", "")
|
fn = fn:gsub(escape(M.Cfg.home .. "/"), "")
|
||||||
local imglink = ""
|
local imglink = ""
|
||||||
vim.api.nvim_put({ imglink }, "", true, true)
|
vim.api.nvim_put({ imglink }, "", true, true)
|
||||||
if opts.insert_after_inserting or opts.i then
|
if opts.insert_after_inserting or opts.i then
|
||||||
@@ -710,7 +742,7 @@ function picker_actions.yank_img_link(opts)
|
|||||||
end
|
end
|
||||||
local selection = action_state.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
local fn = selection.value
|
local fn = selection.value
|
||||||
fn = fn:gsub(M.Cfg.home .. "/", "")
|
fn = fn:gsub(escape(M.Cfg.home .. "/"), "")
|
||||||
local imglink = ""
|
local imglink = ""
|
||||||
vim.fn.setreg('"', imglink)
|
vim.fn.setreg('"', imglink)
|
||||||
print("yanked " .. imglink)
|
print("yanked " .. imglink)
|
||||||
@@ -828,8 +860,13 @@ local function InsertLink(opts)
|
|||||||
actions.select_default:replace(function()
|
actions.select_default:replace(function()
|
||||||
actions.close(prompt_bufnr)
|
actions.close(prompt_bufnr)
|
||||||
local selection = action_state.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
local fn = path_to_linkname(selection.value, opts)
|
local pinfo = resolve_path(selection.value, opts)
|
||||||
vim.api.nvim_put({ "[[" .. fn .. "]]" }, "", true, true)
|
vim.api.nvim_put(
|
||||||
|
{ "[[" .. pinfo.title .. "]]" },
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
)
|
||||||
if opts.i then
|
if opts.i then
|
||||||
vim.api.nvim_feedkeys("A", "m", false)
|
vim.api.nvim_feedkeys("A", "m", false)
|
||||||
end
|
end
|
||||||
@@ -847,47 +884,62 @@ local function InsertLink(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function resolve_link(title)
|
local function resolve_link(title)
|
||||||
local fexists = false
|
local pinfo = Pinfo:new()
|
||||||
local filename = title .. M.Cfg.extension
|
pinfo.fexists = false
|
||||||
filename = filename:gsub("^%./", "") -- strip potential leading ./
|
pinfo.filename = title .. M.Cfg.extension
|
||||||
local best_root = M.Cfg.home
|
pinfo.filename = pinfo.filename:gsub("^%./", "") -- strip potential leading ./
|
||||||
|
pinfo.root_dir = M.Cfg.home
|
||||||
|
pinfo.is_daily_or_weekly = false
|
||||||
|
|
||||||
if M.Cfg.weeklies and file_exists(M.Cfg.weeklies .. "/" .. filename) then
|
if
|
||||||
filename = M.Cfg.weeklies .. "/" .. filename
|
M.Cfg.weeklies and file_exists(M.Cfg.weeklies .. "/" .. pinfo.filename)
|
||||||
fexists = true
|
then
|
||||||
best_root = M.Cfg.weeklies
|
pinfo.filepath = M.Cfg.weeklies .. "/" .. pinfo.filename
|
||||||
|
pinfo.fexists = true
|
||||||
|
pinfo.root_dir = M.Cfg.weeklies
|
||||||
|
pinfo.is_daily_or_weekly = true
|
||||||
end
|
end
|
||||||
if M.Cfg.dailies and file_exists(M.Cfg.dailies .. "/" .. filename) then
|
if
|
||||||
filename = M.Cfg.dailies .. "/" .. filename
|
M.Cfg.dailies and file_exists(M.Cfg.dailies .. "/" .. pinfo.filename)
|
||||||
fexists = true
|
then
|
||||||
best_root = M.Cfg.dailies
|
pinfo.filepath = M.Cfg.dailies .. "/" .. pinfo.filename
|
||||||
|
pinfo.fexists = true
|
||||||
|
pinfo.root_dir = M.Cfg.dailies
|
||||||
|
pinfo.is_daily_or_weekly = true
|
||||||
end
|
end
|
||||||
if file_exists(M.Cfg.home .. "/" .. filename) then
|
if file_exists(M.Cfg.home .. "/" .. pinfo.filename) then
|
||||||
filename = M.Cfg.home .. "/" .. filename
|
pinfo.filepath = M.Cfg.home .. "/" .. pinfo.filename
|
||||||
fexists = true
|
pinfo.fexists = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if fexists == false then
|
if pinfo.fexists == false then
|
||||||
-- now search for it in all subdirs
|
-- now search for it in all subdirs
|
||||||
local subdirs = scan.scan_dir(M.Cfg.home, { only_dirs = true })
|
local subdirs = scan.scan_dir(M.Cfg.home, { only_dirs = true })
|
||||||
local tempfn
|
local tempfn
|
||||||
for _, folder in pairs(subdirs) do
|
for _, folder in pairs(subdirs) do
|
||||||
tempfn = folder .. "/" .. filename
|
tempfn = folder .. "/" .. pinfo.filename
|
||||||
-- [[testnote]]
|
-- [[testnote]]
|
||||||
if file_exists(tempfn) then
|
if file_exists(tempfn) then
|
||||||
filename = tempfn
|
pinfo.filepath = tempfn
|
||||||
fexists = true
|
pinfo.fexists = true
|
||||||
-- print("Found: " .. filename)
|
-- print("Found: " ..pinfo.filename)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if fexists == false then
|
if pinfo.fexists == false then
|
||||||
-- default fn for creation
|
-- default fn for creation
|
||||||
filename = M.Cfg.home .. "/" .. filename
|
pinfo.filepath = M.Cfg.home .. "/" .. pinfo.filename
|
||||||
end
|
end
|
||||||
return fexists, filename, best_root
|
|
||||||
|
-- now work out subdir relative to root
|
||||||
|
pinfo.sub_dir = pinfo.filepath
|
||||||
|
:gsub(escape(pinfo.root_dir .. "/"), "")
|
||||||
|
:gsub(escape(pinfo.filename), "")
|
||||||
|
:gsub("/$", "")
|
||||||
|
:gsub("^/", "")
|
||||||
|
return pinfo
|
||||||
end
|
end
|
||||||
|
|
||||||
-- local function check_for_link_or_tag()
|
-- local function check_for_link_or_tag()
|
||||||
@@ -935,11 +987,9 @@ local function FollowLink(opts)
|
|||||||
local search_mode = "files"
|
local search_mode = "files"
|
||||||
local title
|
local title
|
||||||
local filename = ""
|
local filename = ""
|
||||||
local fexists
|
|
||||||
|
|
||||||
-- first: check if we're in a tag or a link
|
-- first: check if we're in a tag or a link
|
||||||
local kind, atcol, tag
|
local kind, atcol, tag
|
||||||
local best_root
|
|
||||||
|
|
||||||
if opts.follow_tag ~= nil then
|
if opts.follow_tag ~= nil then
|
||||||
kind = "tag"
|
kind = "tag"
|
||||||
@@ -984,9 +1034,12 @@ local function FollowLink(opts)
|
|||||||
title = parts[2]
|
title = parts[2]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- if we cannot find the file, revert to global heading search by
|
||||||
|
-- setting filename to empty string
|
||||||
if #filename > 0 then
|
if #filename > 0 then
|
||||||
fexists, filename, _ = resolve_link(filename)
|
local pinfo = resolve_link(filename)
|
||||||
if fexists == false then
|
if pinfo.fexists == false then
|
||||||
-- print("error")
|
-- print("error")
|
||||||
filename = ""
|
filename = ""
|
||||||
end
|
end
|
||||||
@@ -995,9 +1048,9 @@ local function FollowLink(opts)
|
|||||||
|
|
||||||
if search_mode == "files" then
|
if search_mode == "files" then
|
||||||
-- check if fname exists anywhere
|
-- check if fname exists anywhere
|
||||||
fexists, filename, best_root = resolve_link(title)
|
local pinfo = resolve_link(filename)
|
||||||
if
|
if
|
||||||
(fexists ~= true)
|
(pinfo.fexists ~= true)
|
||||||
and (
|
and (
|
||||||
(opts.follow_creates_nonexisting == true)
|
(opts.follow_creates_nonexisting == true)
|
||||||
or M.Cfg.follow_creates_nonexisting == true
|
or M.Cfg.follow_creates_nonexisting == true
|
||||||
@@ -1005,16 +1058,16 @@ local function FollowLink(opts)
|
|||||||
then
|
then
|
||||||
create_note_from_template(
|
create_note_from_template(
|
||||||
title,
|
title,
|
||||||
filename,
|
pinfo.filepath,
|
||||||
M.note_type_templates.normal
|
M.note_type_templates.normal
|
||||||
)
|
)
|
||||||
opts.erase = true
|
opts.erase = true
|
||||||
opts.erase_file = filename
|
opts.erase_file = pinfo.filepath
|
||||||
end
|
end
|
||||||
|
|
||||||
find_files_sorted({
|
find_files_sorted({
|
||||||
prompt_title = "Follow link to note...",
|
prompt_title = "Follow link to note...",
|
||||||
cwd = best_root,
|
cwd = pinfo.best_root,
|
||||||
default_text = title,
|
default_text = title,
|
||||||
find_command = M.Cfg.find_command,
|
find_command = M.Cfg.find_command,
|
||||||
attach_mappings = function(_, map)
|
attach_mappings = function(_, map)
|
||||||
@@ -1044,7 +1097,7 @@ local function FollowLink(opts)
|
|||||||
local function iconic_display(display_entry)
|
local function iconic_display(display_entry)
|
||||||
local display_opts = {
|
local display_opts = {
|
||||||
path_display = function(_, e)
|
path_display = function(_, e)
|
||||||
return e:gsub(opts.cwd .. "/", "")
|
return e:gsub(escape(opts.cwd .. "/"), "")
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1475,7 +1528,9 @@ end
|
|||||||
-- Create and yank a [[link]] from the current note.
|
-- Create and yank a [[link]] from the current note.
|
||||||
--
|
--
|
||||||
local function YankLink()
|
local function YankLink()
|
||||||
local title = "[[" .. path_to_linkname(vim.fn.expand("%:p"), M.Cfg) .. "]]"
|
local title = "[["
|
||||||
|
.. resolve_path(vim.fn.expand("%:p"), M.Cfg).title
|
||||||
|
.. "]]"
|
||||||
vim.fn.setreg('"', title)
|
vim.fn.setreg('"', title)
|
||||||
print("yanked " .. title)
|
print("yanked " .. title)
|
||||||
end
|
end
|
||||||
@@ -1613,7 +1668,7 @@ local function InsertImgLink(opts)
|
|||||||
actions.close(prompt_bufnr)
|
actions.close(prompt_bufnr)
|
||||||
local selection = action_state.get_selected_entry()
|
local selection = action_state.get_selected_entry()
|
||||||
local fn = selection.value
|
local fn = selection.value
|
||||||
fn = fn:gsub(M.Cfg.home .. "/", "")
|
fn = fn:gsub(escape(M.Cfg.home .. "/"), "")
|
||||||
vim.api.nvim_put({ "" }, "", true, true)
|
vim.api.nvim_put({ "" }, "", true, true)
|
||||||
if opts.i then
|
if opts.i then
|
||||||
vim.api.nvim_feedkeys("A", "m", false)
|
vim.api.nvim_feedkeys("A", "m", false)
|
||||||
@@ -1675,7 +1730,7 @@ local function ShowBacklinks(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
|
||||||
|
|
||||||
local title = path_to_linkname(vim.fn.expand("%:p"), M.Cfg)
|
local title = resolve_path(vim.fn.expand("%:p"), M.Cfg).title
|
||||||
-- or vim.api.nvim_buf_get_name(0)
|
-- or vim.api.nvim_buf_get_name(0)
|
||||||
builtin.live_grep({
|
builtin.live_grep({
|
||||||
results_title = "Backlinks to " .. title,
|
results_title = "Backlinks to " .. title,
|
||||||
@@ -1951,13 +2006,13 @@ local function ToggleTodo(opts)
|
|||||||
if
|
if
|
||||||
vim.startswith(stripped, "- ") and not vim.startswith(stripped, "- [")
|
vim.startswith(stripped, "- ") and not vim.startswith(stripped, "- [")
|
||||||
then
|
then
|
||||||
repline = curline:gsub("- ", "- [ ] ", 1)
|
repline = curline:gsub("%- ", "- [ ] ", 1)
|
||||||
else
|
else
|
||||||
if vim.startswith(stripped, "- [ ]") then
|
if vim.startswith(stripped, "- [ ]") then
|
||||||
repline = curline:gsub("- %[ %]", "- [x]", 1)
|
repline = curline:gsub("%- %[ %]", "- [x]", 1)
|
||||||
else
|
else
|
||||||
if vim.startswith(stripped, "- [x]") then
|
if vim.startswith(stripped, "- [x]") then
|
||||||
repline = curline:gsub("- %[x%]", "-", 1)
|
repline = curline:gsub("%- %[x%]", "-", 1)
|
||||||
else
|
else
|
||||||
repline = curline:gsub("(%S)", "- [ ] %1", 1)
|
repline = curline:gsub("(%S)", "- [ ] %1", 1)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user