Implement refile heading
This commit is contained in:
parent
c2410a3723
commit
044a1eba41
83
lua/orgmode-telescope/utils.lua
Normal file
83
lua/orgmode-telescope/utils.lua
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
local entry_display = require("telescope.pickers.entry_display")
|
||||||
|
|
||||||
|
local orgmode = require('orgmode.api')
|
||||||
|
|
||||||
|
local utils = {}
|
||||||
|
|
||||||
|
utils.get_entries = function(opts)
|
||||||
|
|
||||||
|
local file_results = vim.tbl_map(function(file)
|
||||||
|
return { file = file, filename = file.filename }
|
||||||
|
end, orgmode.load())
|
||||||
|
|
||||||
|
if not opts.archived then
|
||||||
|
file_results = vim.tbl_filter(function(entry)
|
||||||
|
return not entry.file.is_archive_file
|
||||||
|
end, file_results)
|
||||||
|
end
|
||||||
|
|
||||||
|
if opts.max_depth == 0 then
|
||||||
|
return file_results
|
||||||
|
end
|
||||||
|
|
||||||
|
local results = {}
|
||||||
|
for _, file_entry in ipairs(file_results) do
|
||||||
|
local agenda_file = orgmode.load(file_entry.filename)
|
||||||
|
for _, headline in ipairs(agenda_file.headlines) do
|
||||||
|
|
||||||
|
local allowed_depth = opts.max_depth == nil or headline._section.level <= opts.max_depth
|
||||||
|
local allowed_archive = opts.archived or not headline._section:is_archived()
|
||||||
|
if allowed_depth and allowed_archive then
|
||||||
|
local entry = {
|
||||||
|
file = file_entry.file,
|
||||||
|
filename = file_entry.filename,
|
||||||
|
headline = headline
|
||||||
|
}
|
||||||
|
table.insert(results, entry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return results
|
||||||
|
end
|
||||||
|
|
||||||
|
utils.make_entry = function(opts)
|
||||||
|
|
||||||
|
local displayer = entry_display.create({
|
||||||
|
separator = ' ',
|
||||||
|
items = {
|
||||||
|
{ width = vim.F.if_nil(opts.location_width, 20) },
|
||||||
|
{ remaining = true }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
local function make_display(entry)
|
||||||
|
return displayer({ entry.location, entry.line })
|
||||||
|
end
|
||||||
|
|
||||||
|
return function(entry)
|
||||||
|
local headline = entry.headline
|
||||||
|
|
||||||
|
local lnum = nil
|
||||||
|
local location = vim.fn.fnamemodify(entry.filename, ':t')
|
||||||
|
local line = ""
|
||||||
|
|
||||||
|
if headline then
|
||||||
|
lnum = headline.position.start_line
|
||||||
|
location = string.format('%s:%i', location, lnum)
|
||||||
|
line = string.format('%s %s', string.rep('*', headline._section.level), headline.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
value = entry,
|
||||||
|
ordinal = location .. ' ' .. line,
|
||||||
|
filename = entry.filename,
|
||||||
|
lnum = lnum,
|
||||||
|
display = make_display,
|
||||||
|
location = location,
|
||||||
|
line = line
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return utils
|
@ -10,94 +10,9 @@ local conf = require("telescope.config").values
|
|||||||
-- TODO: add highlight groups
|
-- TODO: add highlight groups
|
||||||
-- TODO: add action to refile/capture
|
-- TODO: add action to refile/capture
|
||||||
|
|
||||||
local function get_entries(opts)
|
|
||||||
|
|
||||||
local file_results = vim.tbl_map(function(file)
|
|
||||||
return { file = file, filename = file.filename }
|
|
||||||
end, orgmode.load())
|
|
||||||
|
|
||||||
if not opts.archived then
|
|
||||||
file_results = vim.tbl_filter(function(entry)
|
|
||||||
return not entry.file.is_archive_file
|
|
||||||
end, file_results)
|
|
||||||
end
|
|
||||||
|
|
||||||
if opts.max_depth == 0 then
|
|
||||||
return file_results
|
|
||||||
end
|
|
||||||
|
|
||||||
local results = {}
|
|
||||||
for _, file_entry in ipairs(file_results) do
|
|
||||||
local agenda_file = orgmode.load(file_entry.filename)
|
|
||||||
for _, headline in ipairs(agenda_file.headlines) do
|
|
||||||
|
|
||||||
local allowed_depth = opts.max_depth == nil or headline._section.level <= opts.max_depth
|
|
||||||
local allowed_archive = opts.archived or not headline._section:is_archived()
|
|
||||||
if allowed_depth and allowed_archive then
|
|
||||||
local entry = {
|
|
||||||
file = file_entry.file,
|
|
||||||
filename = file_entry.filename,
|
|
||||||
headline = headline
|
|
||||||
}
|
|
||||||
table.insert(results, entry)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return results
|
|
||||||
end
|
|
||||||
|
|
||||||
local function search_headings(opts)
|
|
||||||
opts = opts or {}
|
|
||||||
|
|
||||||
local displayer = entry_display.create({
|
|
||||||
separator = ' ',
|
|
||||||
items = {
|
|
||||||
{ width = vim.F.if_nil(opts.location_width, 20) },
|
|
||||||
{ remaining = true }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
local function make_display(entry)
|
|
||||||
return displayer({ entry.location, entry.line })
|
|
||||||
end
|
|
||||||
|
|
||||||
pickers.new(opts, {
|
|
||||||
prompt_title = "Search Headings",
|
|
||||||
finder = finders.new_table {
|
|
||||||
results = get_entries(opts),
|
|
||||||
entry_maker = opts.entry_maker or function(entry)
|
|
||||||
|
|
||||||
local headline = entry.headline
|
|
||||||
|
|
||||||
local lnum = nil
|
|
||||||
local location = vim.fn.fnamemodify(entry.filename, ':t')
|
|
||||||
local line = ""
|
|
||||||
|
|
||||||
if headline then
|
|
||||||
lnum = headline.position.start_line
|
|
||||||
location = string.format('%s:%i', location, lnum)
|
|
||||||
line = string.format('%s %s', string.rep('*', headline._section.level), headline.title)
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
value = entry,
|
|
||||||
ordinal = location .. ' ' .. line,
|
|
||||||
filename = entry.filename,
|
|
||||||
lnum = lnum,
|
|
||||||
display = make_display,
|
|
||||||
location = location,
|
|
||||||
line = line
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
sorter = conf.generic_sorter(opts),
|
|
||||||
previewer = conf.grep_previewer(opts),
|
|
||||||
}):find()
|
|
||||||
end
|
|
||||||
|
|
||||||
return require("telescope").register_extension {
|
return require("telescope").register_extension {
|
||||||
exports = {
|
exports = {
|
||||||
search_headings = search_headings,
|
search_headings = require("telescope._extensions.orgmode.search_headings"),
|
||||||
|
refile_heading = require("telescope._extensions.orgmode.refile_heading")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
84
lua/telescope/_extensions/orgmode/refile_heading.lua
Normal file
84
lua/telescope/_extensions/orgmode/refile_heading.lua
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
local pickers = require("telescope.pickers")
|
||||||
|
local finders = require("telescope.finders")
|
||||||
|
local conf = require("telescope.config").values
|
||||||
|
local action_set = require("telescope.actions.set")
|
||||||
|
local actions = require("telescope.actions")
|
||||||
|
local action_state = require("telescope.actions.state")
|
||||||
|
|
||||||
|
local utils = require('orgmode-telescope.utils')
|
||||||
|
|
||||||
|
local Files = require('orgmode.parser.files')
|
||||||
|
local Capture = require('orgmode.capture')
|
||||||
|
|
||||||
|
return function(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
|
||||||
|
local src_file = Files.get_current_file()
|
||||||
|
local src_item = src_file:get_closest_headline()
|
||||||
|
local src_lines = src_file:get_headline_lines(src_item)
|
||||||
|
|
||||||
|
local function refile(prompt_bufnr)
|
||||||
|
local entry = action_state.get_selected_entry()
|
||||||
|
actions.close(prompt_bufnr)
|
||||||
|
|
||||||
|
local dst_file = entry.value.file
|
||||||
|
local dst_headline = entry.value.headline
|
||||||
|
if dst_headline then
|
||||||
|
-- NOTE: adapted from Capture:refile_to_headline
|
||||||
|
if src_item and src_item.level <= dst_headline._section.level then
|
||||||
|
-- Refiling in same file just moves the lines from one position
|
||||||
|
-- to another,so we need to apply demote instantly
|
||||||
|
local is_same_file = dst_file.filename == src_item.root.filename
|
||||||
|
src_lines = src_item:demote(dst_headline._section.level - src_item.level + 1, true, not is_same_file)
|
||||||
|
end
|
||||||
|
local refiled = Capture:_refile_to(dst_file.filename, src_lines, src_item, dst_headline.position.end_line)
|
||||||
|
if not refiled then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
--utils.echo_info(string.format('Wrote %s', dst_file.filename))
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return Capture:_refile_to_end(dst_file.filename, src_lines, src_item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local current_depth = opts.max_depth
|
||||||
|
local next_depth = nil
|
||||||
|
if current_depth ~= 0 then
|
||||||
|
next_depth = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local function depth_toggle(prompt_bufnr)
|
||||||
|
local current_picker = action_state.get_current_picker(prompt_bufnr)
|
||||||
|
|
||||||
|
-- TODO: use action_state to store these to allow easy rebinding by users
|
||||||
|
local aux = current_depth
|
||||||
|
current_depth = next_depth
|
||||||
|
next_depth = aux
|
||||||
|
|
||||||
|
opts.max_depth = current_depth
|
||||||
|
local new_finder = finders.new_table {
|
||||||
|
results = utils.get_entries(opts),
|
||||||
|
entry_maker = opts.entry_maker or utils.make_entry(opts),
|
||||||
|
}
|
||||||
|
|
||||||
|
current_picker:refresh(new_finder, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
pickers.new(opts, {
|
||||||
|
-- TODO: alter prompt title when depth is 0: Refile under file, Refile
|
||||||
|
-- under Headline
|
||||||
|
prompt_title = "Refile Destination",
|
||||||
|
finder = finders.new_table {
|
||||||
|
results = utils.get_entries(opts),
|
||||||
|
entry_maker = opts.entry_maker or utils.make_entry(opts),
|
||||||
|
},
|
||||||
|
sorter = conf.generic_sorter(opts),
|
||||||
|
previewer = conf.grep_previewer(opts),
|
||||||
|
attach_mappings = function(_, map)
|
||||||
|
action_set.select:replace(refile)
|
||||||
|
map("i", "<c-space>", depth_toggle)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}):find()
|
||||||
|
end
|
19
lua/telescope/_extensions/orgmode/search_headings.lua
Normal file
19
lua/telescope/_extensions/orgmode/search_headings.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
local pickers = require("telescope.pickers")
|
||||||
|
local finders = require("telescope.finders")
|
||||||
|
local conf = require("telescope.config").values
|
||||||
|
|
||||||
|
local utils = require('orgmode-telescope.utils')
|
||||||
|
|
||||||
|
return function(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
|
||||||
|
pickers.new(opts, {
|
||||||
|
prompt_title = "Search Headings",
|
||||||
|
finder = finders.new_table {
|
||||||
|
results = utils.get_entries(opts),
|
||||||
|
entry_maker = opts.entry_maker or utils.make_entry(opts),
|
||||||
|
},
|
||||||
|
sorter = conf.generic_sorter(opts),
|
||||||
|
previewer = conf.grep_previewer(opts),
|
||||||
|
}):find()
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user