Skip to content

Commit 956897b

Browse files
fix(refile): Autocomplete nested paths (#835)
1 parent 73f3263 commit 956897b

File tree

2 files changed

+47
-17
lines changed

2 files changed

+47
-17
lines changed

lua/orgmode/capture/init.lua

+27-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local utils = require('orgmode.utils')
2+
local fs = require('orgmode.utils.fs')
23
local config = require('orgmode.config')
34
local Templates = require('orgmode.capture.templates')
45
local Template = require('orgmode.capture.template')
@@ -363,12 +364,13 @@ function Capture:get_destination()
363364
local valid_destinations = self:_get_autocompletion_files()
364365

365366
local destination = vim.fn.OrgmodeInput('Enter destination: ', '', function(arg_lead)
366-
return self:autocomplete_refile(arg_lead)
367+
return self:autocomplete_refile(arg_lead, valid_destinations)
367368
end)
368369

369-
destination = vim.split(destination, '/', { plain = true })
370+
local path = destination:match('^.*%.org/')
371+
local headline_title = path and destination:sub(#path + 1) or ''
370372

371-
if not valid_destinations[destination[1]] then
373+
if not valid_destinations[path] then
372374
utils.echo_error(
373375
('"%s" is not a is not a file specified in the "org_agenda_files" setting. Refiling cancelled.'):format(
374376
destination[1]
@@ -377,11 +379,10 @@ function Capture:get_destination()
377379
return {}
378380
end
379381

380-
local destination_file = valid_destinations[destination[1]]
382+
local destination_file = valid_destinations[path]
381383
local result = {
382384
file = destination_file,
383385
}
384-
local headline_title = table.concat({ unpack(destination, 2) }, '/')
385386

386387
if not headline_title or vim.trim(headline_title) == '' then
387388
return result
@@ -406,24 +407,24 @@ function Capture:get_destination()
406407
end
407408

408409
---@param arg_lead string
410+
---@param files table<string, OrgFile>
409411
---@return string[]
410-
function Capture:autocomplete_refile(arg_lead)
411-
local valid_files = self:_get_autocompletion_files(true)
412-
412+
function Capture:autocomplete_refile(arg_lead, files)
413413
if not arg_lead or #arg_lead == 0 then
414-
return vim.tbl_keys(valid_files)
414+
return vim.tbl_keys(files)
415415
end
416416

417-
local filename = vim.split(arg_lead, '/', { plain = true })[1]
418-
local selected_file = valid_files[filename .. '/']
417+
local filename = arg_lead:match('^.*%.org/')
418+
419+
local selected_file = filename and files[filename]
419420

420421
if not selected_file then
421-
return vim.fn.matchfuzzy(vim.tbl_keys(valid_files), filename)
422+
return vim.fn.matchfuzzy(vim.tbl_keys(files), filename or arg_lead)
422423
end
423424

424425
local headlines = selected_file:get_opened_unfinished_headlines()
425426
local result = vim.tbl_map(function(headline)
426-
return string.format('%s/%s', vim.fn.fnamemodify(headline.file.filename, ':t'), headline:get_title())
427+
return string.format('%s%s', filename, headline:get_title())
427428
end, headlines)
428429

429430
return vim.tbl_filter(function(item)
@@ -597,16 +598,25 @@ function Capture:_create_menu_items(templates)
597598
end
598599

599600
---@private
600-
---@param add_slash_suffix? boolean
601601
---@return table<string, OrgFile>
602-
function Capture:_get_autocompletion_files(add_slash_suffix)
602+
function Capture:_get_autocompletion_files()
603603
local valid_destinations = {}
604+
local filenames = {}
604605
for _, file in ipairs(self.files:all()) do
605606
if not file:is_archive_file() then
606-
valid_destinations[vim.fn.fnamemodify(file.filename, ':t') .. (add_slash_suffix and '/' or '')] = file
607+
table.insert(valid_destinations, file)
608+
table.insert(filenames, file.filename)
607609
end
608610
end
609-
return valid_destinations
611+
612+
filenames = fs.trim_common_root(filenames)
613+
local result = {}
614+
615+
for i, filename in ipairs(filenames) do
616+
result[filename .. '/'] = valid_destinations[i]
617+
end
618+
619+
return result
610620
end
611621

612622
---@private

lua/orgmode/utils/fs.lua

+20
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,24 @@ function M.get_current_file_dir()
4343
return current_dir or ''
4444
end
4545

46+
---@param paths string[]
47+
---@return string[]
48+
function M.trim_common_root(paths)
49+
local filepaths = vim.deepcopy(paths)
50+
table.sort(filepaths, function(a, b)
51+
local _, count_a = a:gsub('/', '')
52+
local _, count_b = b:gsub('/', '')
53+
return count_a < count_b
54+
end)
55+
56+
local result = {}
57+
local root = vim.pesc(vim.fn.fnamemodify(filepaths[1], ':h')) .. '/'
58+
59+
for _, path in ipairs(paths) do
60+
local relative_path = path:sub(#root + 1)
61+
table.insert(result, relative_path)
62+
end
63+
return result
64+
end
65+
4666
return M

0 commit comments

Comments
 (0)