Skip to content

Commit 044a1eb

Browse files
committed
Implement refile heading
1 parent c2410a3 commit 044a1eb

File tree

4 files changed

+188
-87
lines changed

4 files changed

+188
-87
lines changed

lua/orgmode-telescope/utils.lua

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
local entry_display = require("telescope.pickers.entry_display")
2+
3+
local orgmode = require('orgmode.api')
4+
5+
local utils = {}
6+
7+
utils.get_entries = function(opts)
8+
9+
local file_results = vim.tbl_map(function(file)
10+
return { file = file, filename = file.filename }
11+
end, orgmode.load())
12+
13+
if not opts.archived then
14+
file_results = vim.tbl_filter(function(entry)
15+
return not entry.file.is_archive_file
16+
end, file_results)
17+
end
18+
19+
if opts.max_depth == 0 then
20+
return file_results
21+
end
22+
23+
local results = {}
24+
for _, file_entry in ipairs(file_results) do
25+
local agenda_file = orgmode.load(file_entry.filename)
26+
for _, headline in ipairs(agenda_file.headlines) do
27+
28+
local allowed_depth = opts.max_depth == nil or headline._section.level <= opts.max_depth
29+
local allowed_archive = opts.archived or not headline._section:is_archived()
30+
if allowed_depth and allowed_archive then
31+
local entry = {
32+
file = file_entry.file,
33+
filename = file_entry.filename,
34+
headline = headline
35+
}
36+
table.insert(results, entry)
37+
end
38+
end
39+
end
40+
41+
return results
42+
end
43+
44+
utils.make_entry = function(opts)
45+
46+
local displayer = entry_display.create({
47+
separator = ' ',
48+
items = {
49+
{ width = vim.F.if_nil(opts.location_width, 20) },
50+
{ remaining = true }
51+
}
52+
})
53+
54+
local function make_display(entry)
55+
return displayer({ entry.location, entry.line })
56+
end
57+
58+
return function(entry)
59+
local headline = entry.headline
60+
61+
local lnum = nil
62+
local location = vim.fn.fnamemodify(entry.filename, ':t')
63+
local line = ""
64+
65+
if headline then
66+
lnum = headline.position.start_line
67+
location = string.format('%s:%i', location, lnum)
68+
line = string.format('%s %s', string.rep('*', headline._section.level), headline.title)
69+
end
70+
71+
return {
72+
value = entry,
73+
ordinal = location .. ' ' .. line,
74+
filename = entry.filename,
75+
lnum = lnum,
76+
display = make_display,
77+
location = location,
78+
line = line
79+
}
80+
end
81+
end
82+
83+
return utils

lua/telescope/_extensions/orgmode/init.lua

Lines changed: 2 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -10,94 +10,9 @@ local conf = require("telescope.config").values
1010
-- TODO: add highlight groups
1111
-- TODO: add action to refile/capture
1212

13-
local function get_entries(opts)
14-
15-
local file_results = vim.tbl_map(function(file)
16-
return { file = file, filename = file.filename }
17-
end, orgmode.load())
18-
19-
if not opts.archived then
20-
file_results = vim.tbl_filter(function(entry)
21-
return not entry.file.is_archive_file
22-
end, file_results)
23-
end
24-
25-
if opts.max_depth == 0 then
26-
return file_results
27-
end
28-
29-
local results = {}
30-
for _, file_entry in ipairs(file_results) do
31-
local agenda_file = orgmode.load(file_entry.filename)
32-
for _, headline in ipairs(agenda_file.headlines) do
33-
34-
local allowed_depth = opts.max_depth == nil or headline._section.level <= opts.max_depth
35-
local allowed_archive = opts.archived or not headline._section:is_archived()
36-
if allowed_depth and allowed_archive then
37-
local entry = {
38-
file = file_entry.file,
39-
filename = file_entry.filename,
40-
headline = headline
41-
}
42-
table.insert(results, entry)
43-
end
44-
end
45-
end
46-
47-
return results
48-
end
49-
50-
local function search_headings(opts)
51-
opts = opts or {}
52-
53-
local displayer = entry_display.create({
54-
separator = ' ',
55-
items = {
56-
{ width = vim.F.if_nil(opts.location_width, 20) },
57-
{ remaining = true }
58-
}
59-
})
60-
61-
local function make_display(entry)
62-
return displayer({ entry.location, entry.line })
63-
end
64-
65-
pickers.new(opts, {
66-
prompt_title = "Search Headings",
67-
finder = finders.new_table {
68-
results = get_entries(opts),
69-
entry_maker = opts.entry_maker or function(entry)
70-
71-
local headline = entry.headline
72-
73-
local lnum = nil
74-
local location = vim.fn.fnamemodify(entry.filename, ':t')
75-
local line = ""
76-
77-
if headline then
78-
lnum = headline.position.start_line
79-
location = string.format('%s:%i', location, lnum)
80-
line = string.format('%s %s', string.rep('*', headline._section.level), headline.title)
81-
end
82-
83-
return {
84-
value = entry,
85-
ordinal = location .. ' ' .. line,
86-
filename = entry.filename,
87-
lnum = lnum,
88-
display = make_display,
89-
location = location,
90-
line = line
91-
}
92-
end,
93-
},
94-
sorter = conf.generic_sorter(opts),
95-
previewer = conf.grep_previewer(opts),
96-
}):find()
97-
end
98-
9913
return require("telescope").register_extension {
10014
exports = {
101-
search_headings = search_headings,
15+
search_headings = require("telescope._extensions.orgmode.search_headings"),
16+
refile_heading = require("telescope._extensions.orgmode.refile_heading")
10217
},
10318
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
local pickers = require("telescope.pickers")
2+
local finders = require("telescope.finders")
3+
local conf = require("telescope.config").values
4+
local action_set = require("telescope.actions.set")
5+
local actions = require("telescope.actions")
6+
local action_state = require("telescope.actions.state")
7+
8+
local utils = require('orgmode-telescope.utils')
9+
10+
local Files = require('orgmode.parser.files')
11+
local Capture = require('orgmode.capture')
12+
13+
return function(opts)
14+
opts = opts or {}
15+
16+
local src_file = Files.get_current_file()
17+
local src_item = src_file:get_closest_headline()
18+
local src_lines = src_file:get_headline_lines(src_item)
19+
20+
local function refile(prompt_bufnr)
21+
local entry = action_state.get_selected_entry()
22+
actions.close(prompt_bufnr)
23+
24+
local dst_file = entry.value.file
25+
local dst_headline = entry.value.headline
26+
if dst_headline then
27+
-- NOTE: adapted from Capture:refile_to_headline
28+
if src_item and src_item.level <= dst_headline._section.level then
29+
-- Refiling in same file just moves the lines from one position
30+
-- to another,so we need to apply demote instantly
31+
local is_same_file = dst_file.filename == src_item.root.filename
32+
src_lines = src_item:demote(dst_headline._section.level - src_item.level + 1, true, not is_same_file)
33+
end
34+
local refiled = Capture:_refile_to(dst_file.filename, src_lines, src_item, dst_headline.position.end_line)
35+
if not refiled then
36+
return false
37+
end
38+
--utils.echo_info(string.format('Wrote %s', dst_file.filename))
39+
return true
40+
else
41+
return Capture:_refile_to_end(dst_file.filename, src_lines, src_item)
42+
end
43+
end
44+
45+
local current_depth = opts.max_depth
46+
local next_depth = nil
47+
if current_depth ~= 0 then
48+
next_depth = 0
49+
end
50+
51+
local function depth_toggle(prompt_bufnr)
52+
local current_picker = action_state.get_current_picker(prompt_bufnr)
53+
54+
-- TODO: use action_state to store these to allow easy rebinding by users
55+
local aux = current_depth
56+
current_depth = next_depth
57+
next_depth = aux
58+
59+
opts.max_depth = current_depth
60+
local new_finder = finders.new_table {
61+
results = utils.get_entries(opts),
62+
entry_maker = opts.entry_maker or utils.make_entry(opts),
63+
}
64+
65+
current_picker:refresh(new_finder, opts)
66+
end
67+
68+
pickers.new(opts, {
69+
-- TODO: alter prompt title when depth is 0: Refile under file, Refile
70+
-- under Headline
71+
prompt_title = "Refile Destination",
72+
finder = finders.new_table {
73+
results = utils.get_entries(opts),
74+
entry_maker = opts.entry_maker or utils.make_entry(opts),
75+
},
76+
sorter = conf.generic_sorter(opts),
77+
previewer = conf.grep_previewer(opts),
78+
attach_mappings = function(_, map)
79+
action_set.select:replace(refile)
80+
map("i", "<c-space>", depth_toggle)
81+
return true
82+
end,
83+
}):find()
84+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
local pickers = require("telescope.pickers")
2+
local finders = require("telescope.finders")
3+
local conf = require("telescope.config").values
4+
5+
local utils = require('orgmode-telescope.utils')
6+
7+
return function(opts)
8+
opts = opts or {}
9+
10+
pickers.new(opts, {
11+
prompt_title = "Search Headings",
12+
finder = finders.new_table {
13+
results = utils.get_entries(opts),
14+
entry_maker = opts.entry_maker or utils.make_entry(opts),
15+
},
16+
sorter = conf.generic_sorter(opts),
17+
previewer = conf.grep_previewer(opts),
18+
}):find()
19+
end

0 commit comments

Comments
 (0)