Skip to content

Commit

Permalink
feat(core): enhance org-insert-link, add completion for ~/ prefix. (n…
Browse files Browse the repository at this point in the history
…vim-orgmode#749)

* feat(core): enhance org-insert-link, add completion for relative path or ~/

_squash: keep Url.path, and add a realpath filed

fix: make sure realpath and path's ends are matched

e.g.
  /path/to/me ../to/me
  /path/to/me/ ../to/me/

refactor: remove unused flag

refactor: add comments on trailing slash

_fix

* test: add unit test for relative dirs

---------

Co-authored-by: fanyunqian <fanyunqian@sensetime.com>
  • Loading branch information
PannenetsF and fanyunqian authored Jul 4, 2024
1 parent 3bf4345 commit dea6555
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 13 deletions.
15 changes: 4 additions & 11 deletions lua/orgmode/org/hyperlinks/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,13 @@ function Hyperlinks.find_by_filepath(url)
return {}
end
--TODO integrate with orgmode.utils.fs or orgmode.objects.url
local file_base_no_start_path = vim.pesc(file_base:gsub('^%./', '') .. '')
local is_relative_path = file_base:match('^%./')
local current_file_directory = vim.pesc(fs.get_current_file_dir())
local valid_filenames = {}
for _, f in ipairs(filenames) do
if is_relative_path then
local match = f:match('^' .. current_file_directory .. '/(' .. file_base_no_start_path .. '.*%.org)$')
if match then
table.insert(valid_filenames, './' .. match)
end
else
if f:find('^' .. file_base) then
table.insert(valid_filenames, f)
if f:find('^' .. file_base) then
if url.realpath then
f = f:gsub(file_base, url.path)
end
table.insert(valid_filenames, f)
end
end

Expand Down
9 changes: 7 additions & 2 deletions lua/orgmode/org/hyperlinks/url.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local fs = require('orgmode.utils.fs')
---@alias OrgUrlPathType 'file' | 'headline' | 'custom-id' | 'id' | 'external-url' | 'plain' | nil
---@alias OrgUrlTargetType 'headline' | 'custom-id' | 'line-number' | 'unknown' | nil

Expand Down Expand Up @@ -116,7 +117,7 @@ function Url:get_file()
if not self:is_file() then
return nil
end
return self.path
return self.realpath or self.path
end

---@return string | nil
Expand Down Expand Up @@ -246,8 +247,12 @@ function Url:_parse_path_type()
return
end

if first_char == '.' and (self.path:sub(1, 3) == '../' or self.path:sub(1, 2) == './') then
if
(first_char == '.' and (self.path:sub(1, 3) == '../' or self.path:sub(1, 2) == './'))
or (first_char == '~' and self.path:sub(2, 2) == '/')
then
self.path_type = 'file'
self.realpath = fs.get_real_path(self.path) or self.path
return
end

Expand Down
4 changes: 4 additions & 0 deletions lua/orgmode/utils/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ function M.get_real_path(filepath)
return false
end
local real = vim.loop.fs_realpath(substituted)
if filepath:sub(-1, -1) == '/' then
-- make sure if filepath gets a trailing slash, the realpath gets one, too.
real = real .. '/'
end
return real or false
end

Expand Down
30 changes: 30 additions & 0 deletions tests/plenary/helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,38 @@ local function create_file_instance(lines, filename)
return file
end

---@return table
local function create_agenda_files(filenames, contents)
-- NOTE: content is only 1 line for 1 file
local temp_fname = vim.fn.tempname()
local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h')
-- clear temp dir
vim.fn.delete(temp_dir .. '/*', 'rf')
local files = {}
local agenda_files = {}
for i, filename in ipairs(filenames) do
local fname = temp_dir .. '/' .. filename
fname = vim.fn.fnamemodify(fname, ':p')
if fname then
local dir = vim.fn.fnamemodify(fname, ':p:h')
vim.fn.mkdir(dir, 'p')
vim.fn.writefile({ contents[i] }, fname)
files[filename] = fname
table.insert(agenda_files, fname)
end
end
local cfg = vim.tbl_extend('force', {
org_agenda_files = agenda_files,
}, {})
local org = orgmode.setup(cfg)
org:init()
return files
end

return {
load_file = load_file,
create_file = create_file,
create_file_instance = create_file_instance,
create_agenda_file = create_agenda_file,
create_agenda_files = create_agenda_files,
}
33 changes: 33 additions & 0 deletions tests/plenary/org/autocompletion_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,39 @@ describe('Autocompletion', function()
{ menu = '[Org]', word = 'Title without anchor' },
}, result)
end)

it('should work on relative paths', function()
local files = helpers.create_agenda_files({
'a.org',
'b/c.org',
}, {
'[[./ ',
'[[../ ',
})
helpers.load_file(files['b/c.org'])
vim.fn.cursor({ 1, 6 })

assert.are.same({
{ menu = '[Org]', word = '../a.org' },
{ menu = '[Org]', word = '../b/c.org' },
}, org.completion:omnifunc(0, '../'))
end)
it('should work on relative paths', function()
local files = helpers.create_agenda_files({
'a.org',
'b/c.org',
}, {
'[[./ ',
'[[../ ',
})
helpers.load_file(files['a.org'])
vim.fn.cursor({ 1, 5 })

assert.are.same({
{ menu = '[Org]', word = './a.org' },
{ menu = '[Org]', word = './b/c.org' },
}, org.completion:omnifunc(0, './'))
end)
end)
end)
end)

0 comments on commit dea6555

Please sign in to comment.