@@ -2,33 +2,87 @@ local Files = require('orgmode.parser.files')
2
2
local utils = require (' orgmode.utils' )
3
3
local Hyperlinks = {}
4
4
5
- function Hyperlinks .find_by_custom_id_property (base , skip_mapping )
6
- local headlines = Files .get_current_file ():find_headlines_with_property_matching (' CUSTOM_ID' , base :sub (2 ))
7
- if skip_mapping then
5
+ local function get_file_from_context (ctx )
6
+ return (
7
+ ctx .hyperlinks and ctx .hyperlinks .filepath and Files .get (ctx .hyperlinks .filepath , true )
8
+ or Files .get_current_file ()
9
+ )
10
+ end
11
+
12
+ local function update_hyperlink_ctx (ctx )
13
+ if not ctx .line then
14
+ return
15
+ end
16
+
17
+ -- TODO: Support text search, see here [https://orgmode.org/manual/External-Links.html]
18
+ local hyperlinks_ctx = {
19
+ filepath = false ,
20
+ headline = false ,
21
+ custom_id = false ,
22
+ }
23
+
24
+ local file_match = ctx .line :match (' file:(.-)::' )
25
+ file_match = file_match and vim .fn .fnamemodify (file_match , ' :p' ) or file_match
26
+
27
+ if file_match and Files .get (file_match ) then
28
+ hyperlinks_ctx .filepath = Files .get (file_match ).filename
29
+ hyperlinks_ctx .headline = ctx .line :match (' file:.-::(%*.-)$' )
30
+
31
+ if not hyperlinks_ctx .headline then
32
+ hyperlinks_ctx .custom_id = ctx .line :match (' file:.-::(#.-)$' )
33
+ end
34
+
35
+ ctx .base = hyperlinks_ctx .headline or hyperlinks_ctx .custom_id or ctx .base
36
+ end
37
+
38
+ ctx .hyperlinks = hyperlinks_ctx
39
+ end
40
+
41
+ function Hyperlinks .find_by_filepath (ctx )
42
+ local filenames = Files .filenames ()
43
+ local file_base = ctx .base :gsub (' ^file:' , ' ' )
44
+ if vim .trim (file_base ) ~= ' ' then
45
+ filenames = vim .tbl_filter (function (f )
46
+ return f :find (' ^' .. file_base )
47
+ end , filenames )
48
+ end
49
+
50
+ -- Outer checks already filter cases where `ctx.skip_add_prefix` is truthy,
51
+ -- so no need to check it here
52
+ return vim .tbl_map (function (path )
53
+ return ' file:' .. path
54
+ end , filenames )
55
+ end
56
+
57
+ function Hyperlinks .find_by_custom_id_property (ctx )
58
+ local file = get_file_from_context (ctx )
59
+ local headlines = file :find_headlines_with_property_matching (' CUSTOM_ID' , ctx .base :sub (2 ))
60
+ if ctx .skip_add_prefix then
8
61
return headlines
9
62
end
10
63
return vim .tbl_map (function (headline )
11
64
return ' #' .. headline .properties .items .CUSTOM_ID
12
65
end , headlines )
13
66
end
14
67
15
- function Hyperlinks .find_by_title_pointer (base , skip_mapping )
16
- local headlines = Files .get_current_file ():find_headlines_by_title (base :sub (2 ))
17
- if skip_mapping then
68
+ function Hyperlinks .find_by_title_pointer (ctx )
69
+ local file = get_file_from_context (ctx )
70
+ local headlines = file :find_headlines_by_title (ctx .base :sub (2 ))
71
+ if ctx .skip_add_prefix then
18
72
return headlines
19
73
end
20
74
return vim .tbl_map (function (headline )
21
75
return ' *' .. headline .title
22
76
end , headlines )
23
77
end
24
78
25
- function Hyperlinks .find_by_dedicated_target (base , skip_mapping )
26
- if not base or base == ' ' then
79
+ function Hyperlinks .find_by_dedicated_target (ctx )
80
+ if not ctx . base or ctx . base == ' ' then
27
81
return {}
28
82
end
29
- local term = string.format (' <<<?(%s[^>]*)>>>?' , base ):lower ()
83
+ local term = string.format (' <<<?(%s[^>]*)>>>?' , ctx . base ):lower ()
30
84
local headlines = Files .get_current_file ():find_headlines_matching_search_term (term , true )
31
- if skip_mapping then
85
+ if ctx . skip_add_prefix then
32
86
return headlines
33
87
end
34
88
local targets = {}
@@ -45,32 +99,39 @@ function Hyperlinks.find_by_dedicated_target(base, skip_mapping)
45
99
return targets
46
100
end
47
101
48
- function Hyperlinks .find_by_title (base , skip_mapping )
49
- if not base or base == ' ' then
102
+ function Hyperlinks .find_by_title (ctx )
103
+ if not ctx . base or ctx . base == ' ' then
50
104
return {}
51
105
end
52
- local headlines = Files .get_current_file ():find_headlines_by_title (base )
53
- if skip_mapping then
106
+ local headlines = Files .get_current_file ():find_headlines_by_title (ctx . base )
107
+ if ctx . skip_add_prefix then
54
108
return headlines
55
109
end
56
110
return vim .tbl_map (function (headline )
57
111
return headline .title
58
112
end , headlines )
59
113
end
60
114
61
- function Hyperlinks .find_matching_links (base , skip_mapping )
62
- base = vim .trim (base )
63
- local prefix = base :sub (1 , 1 )
64
- if prefix == ' #' then
65
- return Hyperlinks .find_by_custom_id_property (base , skip_mapping )
115
+ function Hyperlinks .find_matching_links (ctx )
116
+ ctx = ctx or {}
117
+ ctx .base = ctx .base and vim .trim (ctx .base ) or nil
118
+
119
+ update_hyperlink_ctx (ctx )
120
+
121
+ if ctx .base :find (' ^file:' ) and not ctx .skip_add_prefix then
122
+ return Hyperlinks .find_by_filepath (ctx )
66
123
end
67
124
125
+ local prefix = ctx .base :sub (1 , 1 )
126
+ if prefix == ' #' then
127
+ return Hyperlinks .find_by_custom_id_property (ctx )
128
+ end
68
129
if prefix == ' *' then
69
- return Hyperlinks .find_by_title_pointer (base , skip_mapping )
130
+ return Hyperlinks .find_by_title_pointer (ctx )
70
131
end
71
132
72
- local results = Hyperlinks .find_by_dedicated_target (base , skip_mapping )
73
- local all = utils .concat (results , Hyperlinks .find_by_title (base , skip_mapping ))
133
+ local results = Hyperlinks .find_by_dedicated_target (ctx )
134
+ local all = utils .concat (results , Hyperlinks .find_by_title (ctx ))
74
135
return all
75
136
end
76
137
0 commit comments