Skip to content

Commit c1492a6

Browse files
author
Sebastian Flügge
committed
refactor: move reusable functions into utils
To prepare an upcoming feature, methods from refile_heading are moved into utils to make them reusable. Because all files were touched, the code is also reformatted according to the stylua.conf.
1 parent 1d080c3 commit c1492a6

File tree

4 files changed

+191
-114
lines changed

4 files changed

+191
-114
lines changed

lua/telescope-orgmode/refile_heading.lua

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ local conf = require('telescope.config').values
44
local action_set = require('telescope.actions.set')
55
local actions = require('telescope.actions')
66
local action_state = require('telescope.actions.state')
7-
local state = require('telescope.state')
87

98
local utils = require('telescope-orgmode.utils')
109

11-
local api = require('orgmode.api')
10+
local OrgApi = require('orgmode.api')
1211

1312
local M = {}
1413

@@ -24,43 +23,18 @@ M.refile = function(prompt_bufnr)
2423
destination = entry.value.headline
2524
end
2625

27-
return api.refile({
26+
return OrgApi.refile({
2827
source = M.closest_headline,
2928
destination = destination,
3029
})
3130
end
3231

33-
M.gen_depth_toggle = function(opts, prompt_bufnr)
34-
local status = state.get_status(prompt_bufnr)
35-
status._ot_current_depth = opts.max_depth
36-
status._ot_next_depth = nil
37-
if status._ot_current_depth ~= 0 then
38-
status._ot_next_depth = 0
39-
end
40-
41-
return function()
42-
local current_picker = action_state.get_current_picker(prompt_bufnr)
43-
44-
local aux = status._ot_current_depth
45-
status._ot_current_depth = status._ot_next_depth
46-
status._ot_next_depth = aux
47-
48-
opts.max_depth = status._ot_current_depth
49-
local new_finder = finders.new_table({
50-
results = utils.get_entries(opts),
51-
entry_maker = opts.entry_maker or utils.make_entry(opts),
52-
})
53-
54-
current_picker:refresh(new_finder, opts)
55-
end
56-
end
57-
5832
M.closest_headline = nil
5933

6034
return function(opts)
6135
opts = opts or {}
6236

63-
M.closest_headline = api.current():get_closest_headline()
37+
M.closest_headline = OrgApi.current():get_closest_headline()
6438

6539
pickers
6640
.new(opts, {
@@ -75,7 +49,7 @@ return function(opts)
7549
previewer = conf.grep_previewer(opts),
7650
attach_mappings = function(prompt_bufnr, map)
7751
action_set.select:replace(M.refile)
78-
map('i', '<c-space>', M.gen_depth_toggle(opts, prompt_bufnr))
52+
map('i', '<c-space>', utils.gen_depth_toggle(opts, prompt_bufnr))
7953
return true
8054
end,
8155
})
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
local pickers = require("telescope.pickers")
2-
local finders = require("telescope.finders")
3-
local conf = require("telescope.config").values
1+
local pickers = require('telescope.pickers')
2+
local finders = require('telescope.finders')
3+
local conf = require('telescope.config').values
44

5-
local utils = require("telescope-orgmode.utils")
5+
local utils = require('telescope-orgmode.utils')
66

77
return function(opts)
8-
opts = opts or {}
8+
opts = opts or {}
99

10-
pickers
11-
.new(opts, {
12-
prompt_title = "Search Headings",
13-
finder = finders.new_table({
14-
results = utils.get_entries(opts),
15-
entry_maker = opts.entry_maker or utils.make_entry(opts),
16-
}),
17-
sorter = conf.generic_sorter(opts),
18-
previewer = conf.grep_previewer(opts),
19-
})
20-
:find()
10+
pickers
11+
.new(opts, {
12+
prompt_title = 'Search Headings',
13+
finder = finders.new_table({
14+
results = utils.get_entries(opts),
15+
entry_maker = opts.entry_maker or utils.make_entry(opts),
16+
}),
17+
sorter = conf.generic_sorter(opts),
18+
previewer = conf.grep_previewer(opts),
19+
})
20+
:find()
2121
end

lua/telescope-orgmode/typehints.lua

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
-- Type-hints copied from nvim-orgmode to simplify development
2+
3+
---@class OrgFileMetadata
4+
---@field mtime number
5+
---@field changedtick number
6+
7+
---@class OrgFileOpts
8+
---@field filename string
9+
---@field lines string[]
10+
---@field bufnr? number
11+
12+
---@class OrgFile
13+
---@field filename string
14+
---@field lines string[]
15+
---@field content string
16+
---@field metadata OrgFileMetadata
17+
---@field parser vim.treesitter.LanguageTree
18+
---@field root TSNode
19+
20+
---@class OrgApiFile
21+
---@field category string current file category name. By default it's only filename without extension unless defined differently via #+CATEGORY directive
22+
---@field filename string absolute path of the current file
23+
---@field headlines OrgApiHeadline[]
24+
---@field is_archive_file boolean
25+
---@field private _file OrgFile
26+
--
27+
---@class OrgRange
28+
---@field start_line number
29+
---@field start_col number
30+
---@field end_line number
31+
---@field end_col number
32+
33+
---@class OrgApiHeadline
34+
---@field title string headline title without todo keyword, tags and priority. Ex. `* TODO I am a headline :SOMETAG:` returns `I am a headline`
35+
---@field line string full headline line
36+
---@field level number headline level (number of asterisks). Example: 1
37+
---@field todo_value? string todo keyword of the headline (Example: TODO, DONE)
38+
---@field todo_type? 'TODO' | 'DONE' | ''
39+
---@field tags string[] List of own tags
40+
---@field deadline OrgDate|nil
41+
---@field scheduled OrgDate|nil
42+
---@field properties table<string, string> Table containing all properties. All keys are lowercased
43+
---@field closed OrgDate|nil
44+
---@field dates OrgDate[] List of all dates that are not "plan" dates
45+
---@field position OrgRange
46+
---@field all_tags string[] List of all tags (own + inherited)
47+
---@field file OrgApiFile
48+
---@field parent OrgApiHeadline|nil
49+
---@field priority string|nil
50+
---@field is_archived boolean headline marked with the `:ARCHIVE:` tag
51+
---@field headlines OrgApiHeadline[]
52+
--
53+
---@class OrgApiRefileOpts
54+
---@field source OrgApiHeadline
55+
---@field destination OrgApiFile | OrgApiHeadline
56+
57+
---@class OrgApi
58+
---@field load fun(name?: string|string[]): OrgApiFile|OrgApiFile[]
59+
---@field current fun(): OrgApiFile
60+
---@field refile fun(opts: OrgApiRefileOpts)
61+
---@field insert_link fun(link_location: string): boolean

lua/telescope-orgmode/utils.lua

Lines changed: 110 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,121 @@
1-
local entry_display = require("telescope.pickers.entry_display")
1+
require('telescope-orgmode.typehints')
22

3-
local orgmode = require("orgmode.api")
3+
local entry_display = require('telescope.pickers.entry_display')
4+
local finders = require('telescope.finders')
5+
local action_state = require('telescope.actions.state')
6+
local state = require('telescope.state')
7+
8+
local orgmode = require('orgmode.api')
49

510
local utils = {}
611

12+
---@class OrgEntry
13+
---@field file OrgApiFile
14+
---@field filename string
15+
---@field headline? OrgApiHeadline
16+
17+
---Fetches entrys from OrgApi and extracts the relevant information
18+
---@param opts any
19+
---@return OrgEntry[]
720
utils.get_entries = function(opts)
8-
local file_results = vim.tbl_map(function(file)
9-
return { file = file, filename = file.filename }
10-
end, orgmode.load())
11-
12-
if not opts.archived then
13-
file_results = vim.tbl_filter(function(entry)
14-
return not entry.file.is_archive_file
15-
end, file_results)
16-
end
17-
18-
if opts.max_depth == 0 then
19-
return file_results
20-
end
21-
22-
local results = {}
23-
for _, file_entry in ipairs(file_results) do
24-
for _, headline in ipairs(file_entry.file.headlines) do
25-
local allowed_depth = opts.max_depth == nil or headline.level <= opts.max_depth
26-
local allowed_archive = opts.archived or not headline.is_archived
27-
if allowed_depth and allowed_archive then
28-
local entry = {
29-
file = file_entry.file,
30-
filename = file_entry.filename,
31-
headline = headline,
32-
}
33-
table.insert(results, entry)
34-
end
35-
end
36-
end
37-
38-
return results
21+
---@type { file: OrgApiFile, filename: string }[]
22+
local file_results = vim.tbl_map(function(file)
23+
return { file = file, filename = file.filename }
24+
end, orgmode.load())
25+
26+
if not opts.archived then
27+
file_results = vim.tbl_filter(function(entry)
28+
return not entry.file.is_archive_file
29+
end, file_results)
30+
end
31+
32+
if opts.max_depth == 0 then
33+
return file_results
34+
end
35+
36+
local results = {}
37+
for _, file_entry in ipairs(file_results) do
38+
for _, headline in ipairs(file_entry.file.headlines) do
39+
local allowed_depth = opts.max_depth == nil or headline.level <= opts.max_depth
40+
local allowed_archive = opts.archived or not headline.is_archived
41+
if allowed_depth and allowed_archive then
42+
local entry = {
43+
file = file_entry.file,
44+
filename = file_entry.filename,
45+
headline = headline,
46+
}
47+
table.insert(results, entry)
48+
end
49+
end
50+
end
51+
52+
return results
3953
end
4054

55+
---Entry-Maker for Telescope
56+
---@param opts any
57+
---@return fun(entry: OrgEntry):MatchEntry
4158
utils.make_entry = function(opts)
42-
local displayer = entry_display.create({
43-
separator = " ",
44-
items = {
45-
{ width = vim.F.if_nil(opts.location_width, 20) },
46-
{ remaining = true },
47-
},
48-
})
49-
50-
local function make_display(entry)
51-
return displayer({ entry.location, entry.line })
52-
end
53-
54-
return function(entry)
55-
local headline = entry.headline
56-
57-
local lnum = nil
58-
local location = vim.fn.fnamemodify(entry.filename, ":t")
59-
local line = ""
60-
61-
if headline then
62-
lnum = headline.position.start_line
63-
location = string.format("%s:%i", location, lnum)
64-
line = string.format("%s %s", string.rep("*", headline.level), headline.title)
65-
end
66-
67-
return {
68-
value = entry,
69-
ordinal = location .. " " .. line,
70-
filename = entry.filename,
71-
lnum = lnum,
72-
display = make_display,
73-
location = location,
74-
line = line,
75-
}
76-
end
59+
local displayer = entry_display.create({
60+
separator = ' ',
61+
items = {
62+
{ width = vim.F.if_nil(opts.location_width, 20) },
63+
{ remaining = true },
64+
},
65+
})
66+
67+
local function make_display(entry)
68+
return displayer({ entry.location, entry.line })
69+
end
70+
71+
return function(entry)
72+
local headline = entry.headline
73+
74+
local lnum = nil
75+
local location = vim.fn.fnamemodify(entry.filename, ':t')
76+
local line = ''
77+
78+
if headline then
79+
lnum = headline.position.start_line
80+
location = string.format('%s:%i', location, lnum)
81+
line = string.format('%s %s', string.rep('*', headline.level), headline.title)
82+
end
83+
84+
return {
85+
value = entry,
86+
ordinal = location .. ' ' .. line,
87+
filename = entry.filename,
88+
lnum = lnum,
89+
display = make_display,
90+
location = location,
91+
line = line,
92+
}
93+
end
94+
end
95+
96+
utils.gen_depth_toggle = function(opts, prompt_bufnr)
97+
local status = state.get_status(prompt_bufnr)
98+
status._ot_current_depth = opts.max_depth
99+
status._ot_next_depth = nil
100+
if status._ot_current_depth ~= 0 then
101+
status._ot_next_depth = 0
102+
end
103+
104+
return function()
105+
local current_picker = action_state.get_current_picker(prompt_bufnr)
106+
107+
local aux = status._ot_current_depth
108+
status._ot_current_depth = status._ot_next_depth
109+
status._ot_next_depth = aux
110+
111+
opts.max_depth = status._ot_current_depth
112+
local new_finder = finders.new_table({
113+
results = utils.get_entries(opts),
114+
entry_maker = opts.entry_maker or utils.make_entry(opts),
115+
})
116+
117+
current_picker:refresh(new_finder, opts)
118+
end
77119
end
78120

79121
return utils

0 commit comments

Comments
 (0)