Skip to content

Commit 346b6aa

Browse files
authored
fix(hyperlinks): link-follow for "file:../" and "../" (#621)
Co-authored-by: Sebastian Flügge <[email protected]>
1 parent 5ef1141 commit 346b6aa

File tree

3 files changed

+32
-10
lines changed

3 files changed

+32
-10
lines changed

lua/orgmode/objects/url.lua

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function Url:is_org_link()
5050
end
5151

5252
function Url:is_file()
53-
return self.str:find('^file:') or self.str:find('^./') or self.str:find('^/')
53+
return self.str:find('^file:') or self.str:find('^%.%./') or self.str:find('^%./') or self.str:find('^/')
5454
end
5555

5656
function Url:is_file_plain()
@@ -79,11 +79,20 @@ end
7979
function Url:extract_path()
8080
local url = self
8181
if url:is_file_headline() or url:is_file_custom_id() then
82-
return url.str:match('^file:([^:]-)::') or url.str:match('^(./[^:]-)::') or url.str:match('^(/[^:]-)::')
82+
return url.str:match('^file:([^:]-)::')
83+
or url.str:match('^(%.%./[^:]-)::')
84+
or url.str:match('^(%./[^:]-)::')
85+
or url.str:match('^(/[^:]-)::')
8386
elseif url:is_file_line_number() then
84-
return url.str:match('^file:([^:]-) %+') or url.str:match('^(./[^:]-) %+') or url.str:match('^(/[^:]-) %+')
87+
return url.str:match('^file:([^:]-) %+')
88+
or url.str:match('^(%.%./[^:]-) %+')
89+
or url.str:match('^(%./[^:]-) %+')
90+
or url.str:match('^(/[^:]-) %+')
8591
elseif url:is_file_plain() then
86-
return url.str:match('^file:([^:]-)$') or url.str:match('^(./[^:]-)$') or url.str:match('^(/[^:]-)$')
92+
return url.str:match('^file:([^:]-)$')
93+
or url.str:match('^(%.%./[^:]-)$')
94+
or url.str:match('^(%./[^:]-)$')
95+
or url.str:match('^(/[^:]-)$')
8796
else
8897
return false
8998
end
@@ -98,15 +107,17 @@ end
98107
---@return string | false
99108
function Url:get_headline()
100109
return self.str:match('^file:[^:]+::%*(.-)$')
101-
or self.str:match('^./[^:]+::%*(.-)$')
110+
or self.str:match('^%.%./[^:]+::%*(.-)$')
111+
or self.str:match('^%./[^:]+::%*(.-)$')
102112
or self.str:match('^/[^:]+::%*(.-)$')
103113
or self.str:match('^%*(.-)$')
104114
end
105115

106116
---@return string | false
107117
function Url:get_custom_id()
108118
return self.str:match('^file:[^:]+::#(.-)$')
109-
or self.str:match('^./[^:]+::#(.-)$')
119+
or self.str:match('^%.%./[^:]+::#(.-)$')
120+
or self.str:match('^%./[^:]+::#(.-)$')
110121
or self.str:match('^/[^:]+::#(.-)$')
111122
or self.str:match('^#(.-)$')
112123
end
@@ -115,11 +126,13 @@ end
115126
function Url:get_linenumber()
116127
-- official orgmode convention
117128
return self.str:match('^file:[^:]+::(%d+)$')
118-
or self.str:match('^./[^:]+::(%d+)$')
129+
or self.str:match('^%.%./[^:]+::(%d+)$')
130+
or self.str:match('^%./[^:]+::(%d+)$')
119131
or self.str:match('^/[^:]+::(%d+)$')
120132
-- for backwards compatibility
121133
or self.str:match('^file:[^:]+ %+(%d+)$')
122-
or self.str:match('^./[^:]+ %+(%d+)$')
134+
or self.str:match('^%.%./[^:]+ %+(%d+)$')
135+
or self.str:match('^%./[^:]+ %+(%d+)$')
123136
or self.str:match('^/[^:]+ %+(%d+)$')
124137
end
125138

@@ -128,15 +141,19 @@ function Url:get_filepath()
128141
return
129142
-- for backwards compatibility
130143
self.str:match('^file:([^:]+) %+%d+')
144+
or self.str:match('^(%.%./[^:]+) %+%d+')
131145
or self.str:match('^(%./[^:]+) %+%d+')
132146
or self.str:match('^(/[^:]+) %+%d+')
133147
-- official orgmode convention
134148
or self.str:match('^file:([^:]+)::')
149+
or self.str:match('^(%.%./[^:]+)::')
135150
or self.str:match('^(%./[^:]+)::')
136151
or self.str:match('^(/[^:]+)::')
137152
or self.str:match('^file:([^:]+)$')
153+
or self.str:match('^(%.%./[^:]+)$')
138154
or self.str:match('^(%./[^:]+)$')
139155
or self.str:match('^(/[^:]+)$')
156+
or self.str:match('^(%.%./)$')
140157
or self.str:match('^(%./)$')
141158
or self.str:match('^(/)$')
142159
end

lua/orgmode/utils/fs.lua

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ function M.substitute_path(path_str)
1010
elseif path_str:match('^~/') then
1111
local home_path = os.getenv('HOME')
1212
return home_path and path_str:gsub('^~', home_path) or false
13-
elseif path_str:match('^./') then
13+
elseif path_str:match('^%./') then
1414
local base = vim.fn.fnamemodify(utils.current_file_path(), ':p:h')
15-
return base .. '/' .. path_str:gsub('^./', '')
15+
return base .. '/' .. path_str:gsub('^%./', '')
16+
elseif path_str:match('^%.%./') then
17+
local base = vim.fn.fnamemodify(utils.current_file_path(), ':p:h')
18+
return base .. '/' .. path_str
1619
else
1720
return false
1821
end

tests/plenary/object/url_spec.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ describe('Url', function()
6767
it('should handle different file paths', function()
6868
local filepath_examples = {
6969
{ url_str = 'file:./../some_file', exp = './../some_file' },
70+
{ url_str = 'file:../some_file', exp = '../some_file' },
7071
{ url_str = './../some_file.txt', exp = './../some_file.txt' },
72+
{ url_str = '../some_file.txt', exp = '../some_file.txt' },
7173
{ url_str = '/some/path/some_file', exp = '/some/path/some_file' },
7274
{ url_str = 'file:./../some_file.org::*headline', exp = './../some_file.org' },
7375
{ url_str = 'file:./../some_file.org::#custom_id', exp = './../some_file.org' },

0 commit comments

Comments
 (0)