Skip to content

Commit 85daf32

Browse files
author
neo451
committed
more logical module layout
1 parent fd58026 commit 85daf32

File tree

4 files changed

+170
-159
lines changed

4 files changed

+170
-159
lines changed

lua/obsidian/search/init.lua

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ local async = require "obsidian.async"
55

66
local M = {}
77

8-
local Opts = require "obsidian.search.opts"
8+
local Opts = require "obsidian.search.opts" -- general class to handle options
9+
local Ripgrep = require "obsidian.search.ripgrep" -- could have other backends in the future...
910

10-
M.build_find_cmd = Opts.build_find_cmd
11-
M.build_search_cmd = Opts.build_search_cmd
12-
M.build_grep_cmd = Opts.build_grep_cmd
11+
M.build_find_cmd = Ripgrep.build_find_cmd
12+
M.build_search_cmd = Ripgrep.build_search_cmd
13+
M.build_grep_cmd = Ripgrep.build_grep_cmd
1314

1415
---@alias obsidian.search.RefTypes
1516
---| "Wiki"
@@ -251,7 +252,7 @@ end
251252
---@param on_match fun(match: MatchData)
252253
---@param on_exit fun(exit_code: integer)|?
253254
M.search_async = function(dir, term, opts, on_match, on_exit)
254-
local cmd = Opts.build_search_cmd(dir, term, opts)
255+
local cmd = M.build_search_cmd(dir, term, opts)
255256
async.run_job_async(cmd, function(line)
256257
local data = vim.json.decode(line)
257258
if data["type"] == "match" then
@@ -274,7 +275,7 @@ end
274275
---@param on_exit fun(exit_code: integer)|?
275276
M.find_async = function(dir, term, opts, on_match, on_exit)
276277
local norm_dir = Path.new(dir):resolve { strict = true }
277-
local cmd = Opts.build_find_cmd(tostring(norm_dir), term, opts)
278+
local cmd = M.build_find_cmd(tostring(norm_dir), term, opts)
278279
async.run_job_async(cmd, on_match, function(code)
279280
if on_exit ~= nil then
280281
on_exit(code)

lua/obsidian/search/opts.lua

Lines changed: 0 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
local Path = require "obsidian.path"
2-
local compat = require "obsidian.compat"
3-
41
--- TODO: a bit weird to have these two...
52

63
---@class obsidian.SearchOpts
@@ -24,10 +21,6 @@ local compat = require "obsidian.compat"
2421

2522
local M = {}
2623

27-
M._BASE_CMD = { "rg", "--no-config", "--type=md" }
28-
M._SEARCH_CMD = compat.flatten { M._BASE_CMD, "--json" }
29-
M._FIND_CMD = compat.flatten { M._BASE_CMD, "--files" }
30-
3124
local as_tbl = function(self)
3225
local fields = {}
3326
for k, v in pairs(self) do
@@ -56,46 +49,6 @@ local add_exclude = function(opts, path)
5649
opts.exclude[#opts.exclude + 1] = path
5750
end
5851

59-
---@param opts obsidian.search.SearchOpts
60-
---@return string[]
61-
M.to_ripgrep_opts = function(opts)
62-
-- vim.validate("opts.exclude", opts.exclude, "table", true)
63-
64-
local ret = {}
65-
66-
if opts.sort_by ~= nil then
67-
local sort = "sortr" -- default sort is reverse
68-
if opts.sort_reversed == false then
69-
sort = "sort"
70-
end
71-
ret[#ret + 1] = "--" .. sort .. "=" .. opts.sort_by
72-
end
73-
74-
if opts.fixed_strings then
75-
ret[#ret + 1] = "--fixed-strings"
76-
end
77-
78-
if opts.ignore_case then
79-
ret[#ret + 1] = "--ignore-case"
80-
end
81-
82-
if opts.smart_case then
83-
ret[#ret + 1] = "--smart-case"
84-
end
85-
86-
if opts.exclude ~= nil then
87-
for _, path in ipairs(opts.exclude) do
88-
ret[#ret + 1] = "-g!" .. path
89-
end
90-
end
91-
92-
if opts.max_count_per_file ~= nil then
93-
ret[#ret + 1] = "-m=" .. opts.max_count_per_file
94-
end
95-
96-
return ret
97-
end
98-
9952
local search_defaults = {
10053
sort = false,
10154
include_templates = false,
@@ -132,105 +85,4 @@ M._prepare = function(opts, additional_opts)
13285
return search_opts
13386
end
13487

135-
---@param dir string|obsidian.Path
136-
---@param term string|string[]
137-
---@param opts obsidian.search.SearchOpts|?
138-
---
139-
---@return string[]
140-
M.build_search_cmd = function(dir, term, opts)
141-
opts = opts and opts or {}
142-
143-
local search_terms
144-
if type(term) == "string" then
145-
search_terms = { "-e", term }
146-
else
147-
search_terms = {}
148-
for _, t in ipairs(term) do
149-
search_terms[#search_terms + 1] = "-e"
150-
search_terms[#search_terms + 1] = t
151-
end
152-
end
153-
154-
local path = tostring(Path.new(dir):resolve { strict = true })
155-
if opts.escape_path then
156-
path = assert(vim.fn.fnameescape(path))
157-
end
158-
159-
return compat.flatten {
160-
M._SEARCH_CMD,
161-
M.to_ripgrep_opts(opts),
162-
search_terms,
163-
path,
164-
}
165-
end
166-
167-
--- Build the 'rg' command for finding files.
168-
---
169-
---@param path string|?
170-
---@param term string|?
171-
---@param opts obsidian.search.SearchOpts|?
172-
---
173-
---@return string[]
174-
M.build_find_cmd = function(path, term, opts)
175-
opts = opts and opts or {}
176-
opts = vim.tbl_extend("keep", opts, {
177-
sort_by = Obsidian.opts.search.sort_by,
178-
sort_reversed = Obsidian.opts.search.sort_reversed,
179-
ignore_case = true,
180-
})
181-
182-
local additional_opts = {}
183-
184-
if term ~= nil then
185-
if opts.include_non_markdown then
186-
term = "*" .. term .. "*"
187-
elseif not vim.endswith(term, ".md") then
188-
term = "*" .. term .. "*.md"
189-
else
190-
term = "*" .. term
191-
end
192-
additional_opts[#additional_opts + 1] = "-g"
193-
additional_opts[#additional_opts + 1] = term
194-
end
195-
196-
if opts.ignore_case then
197-
additional_opts[#additional_opts + 1] = "--glob-case-insensitive"
198-
end
199-
200-
if path ~= nil and path ~= "." then
201-
if opts.escape_path then
202-
path = assert(vim.fn.fnameescape(tostring(path)))
203-
end
204-
additional_opts[#additional_opts + 1] = path
205-
end
206-
207-
return compat.flatten { M._FIND_CMD, M.to_ripgrep_opts(opts), additional_opts }
208-
end
209-
210-
--- Build the 'rg' grep command for pickers.
211-
---
212-
---@param opts obsidian.search.SearchOpts|?
213-
---
214-
---@return string[]
215-
M.build_grep_cmd = function(opts)
216-
opts = opts and opts or {}
217-
218-
opts = vim.tbl_extend("keep", opts, {
219-
sort_by = Obsidian.opts.search.sort_by,
220-
sort_reversed = Obsidian.opts.search.sort_reversed,
221-
smart_case = true,
222-
fixed_strings = true,
223-
})
224-
225-
return compat.flatten {
226-
M._BASE_CMD,
227-
M.to_ripgrep_opts(opts),
228-
"--column",
229-
"--line-number",
230-
"--no-heading",
231-
"--with-filename",
232-
"--color=never",
233-
}
234-
end
235-
23688
return M

lua/obsidian/search/ripgrep.lua

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
local Path = require "obsidian.path"
2+
local compat = require "obsidian.compat"
3+
4+
local M = {}
5+
6+
local BASE_CMD = { "rg", "--no-config", "--type=md" }
7+
local SEARCH_CMD = compat.flatten { BASE_CMD, "--json" }
8+
local FIND_CMD = compat.flatten { BASE_CMD, "--files" }
9+
10+
---@param opts obsidian.search.SearchOpts
11+
---@return string[]
12+
local generate_args = function(opts)
13+
-- vim.validate("opts.exclude", opts.exclude, "table", true)
14+
15+
local ret = {}
16+
17+
if opts.sort_by ~= nil then
18+
local sort = "sortr" -- default sort is reverse
19+
if opts.sort_reversed == false then
20+
sort = "sort"
21+
end
22+
ret[#ret + 1] = "--" .. sort .. "=" .. opts.sort_by
23+
end
24+
25+
if opts.fixed_strings then
26+
ret[#ret + 1] = "--fixed-strings"
27+
end
28+
29+
if opts.ignore_case then
30+
ret[#ret + 1] = "--ignore-case"
31+
end
32+
33+
if opts.smart_case then
34+
ret[#ret + 1] = "--smart-case"
35+
end
36+
37+
if opts.exclude ~= nil then
38+
for _, path in ipairs(opts.exclude) do
39+
ret[#ret + 1] = "-g!" .. path
40+
end
41+
end
42+
43+
if opts.max_count_per_file ~= nil then
44+
ret[#ret + 1] = "-m=" .. opts.max_count_per_file
45+
end
46+
47+
return ret
48+
end
49+
50+
M._generate_args = generate_args
51+
52+
---@param dir string|obsidian.Path
53+
---@param term string|string[]
54+
---@param opts obsidian.search.SearchOpts|?
55+
---
56+
---@return string[]
57+
M.build_search_cmd = function(dir, term, opts)
58+
opts = opts and opts or {}
59+
60+
local search_terms
61+
if type(term) == "string" then
62+
search_terms = { "-e", term }
63+
else
64+
search_terms = {}
65+
for _, t in ipairs(term) do
66+
search_terms[#search_terms + 1] = "-e"
67+
search_terms[#search_terms + 1] = t
68+
end
69+
end
70+
71+
local path = tostring(Path.new(dir):resolve { strict = true })
72+
if opts.escape_path then
73+
path = assert(vim.fn.fnameescape(path))
74+
end
75+
76+
return compat.flatten {
77+
SEARCH_CMD,
78+
generate_args(opts),
79+
search_terms,
80+
path,
81+
}
82+
end
83+
84+
--- Build the 'rg' command for finding files.
85+
---
86+
---@param path string|?
87+
---@param term string|?
88+
---@param opts obsidian.search.SearchOpts|?
89+
---
90+
---@return string[]
91+
M.build_find_cmd = function(path, term, opts)
92+
opts = opts and opts or {}
93+
opts = vim.tbl_extend("keep", opts, {
94+
sort_by = Obsidian.opts.search.sort_by,
95+
sort_reversed = Obsidian.opts.search.sort_reversed,
96+
ignore_case = true,
97+
})
98+
99+
local additional_opts = {}
100+
101+
if term ~= nil then
102+
if opts.include_non_markdown then
103+
term = "*" .. term .. "*"
104+
elseif not vim.endswith(term, ".md") then
105+
term = "*" .. term .. "*.md"
106+
else
107+
term = "*" .. term
108+
end
109+
additional_opts[#additional_opts + 1] = "-g"
110+
additional_opts[#additional_opts + 1] = term
111+
end
112+
113+
if opts.ignore_case then
114+
additional_opts[#additional_opts + 1] = "--glob-case-insensitive"
115+
end
116+
117+
if path ~= nil and path ~= "." then
118+
if opts.escape_path then
119+
path = assert(vim.fn.fnameescape(tostring(path)))
120+
end
121+
additional_opts[#additional_opts + 1] = path
122+
end
123+
124+
return compat.flatten {
125+
FIND_CMD,
126+
generate_args(opts),
127+
additional_opts,
128+
}
129+
end
130+
131+
--- Build the 'rg' grep command for pickers.
132+
---
133+
---@param opts obsidian.search.SearchOpts|?
134+
---
135+
---@return string[]
136+
M.build_grep_cmd = function(opts)
137+
opts = opts and opts or {}
138+
139+
opts = vim.tbl_extend("keep", opts, {
140+
sort_by = Obsidian.opts.search.sort_by,
141+
sort_reversed = Obsidian.opts.search.sort_reversed,
142+
smart_case = true,
143+
fixed_strings = true,
144+
})
145+
146+
return compat.flatten {
147+
BASE_CMD,
148+
generate_args(opts),
149+
"--column",
150+
"--line-number",
151+
"--no-heading",
152+
"--with-filename",
153+
"--color=never",
154+
}
155+
end
156+
157+
return M

tests/search/test_search_opts.lua

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
local M = require "obsidian.search.opts"
1+
local M = require "obsidian.search.ripgrep"
2+
local Opts = require "obsidian.search.opts"
23

34
local new_set, eq = MiniTest.new_set, MiniTest.expect.equality
45

@@ -14,18 +15,18 @@ T["should initialize from a raw table and resolve to ripgrep options"] = functio
1415
exclude = { "templates" },
1516
max_count_per_file = 1,
1617
}
17-
eq(M.to_ripgrep_opts(opts), { "--sortr=modified", "--fixed-strings", "--ignore-case", "-g!templates", "-m=1" })
18+
eq(M._generate_args(opts), { "--sortr=modified", "--fixed-strings", "--ignore-case", "-g!templates", "-m=1" })
1819
end
1920

2021
T["should not include any options with defaults"] = function()
21-
eq(M.to_ripgrep_opts {}, {})
22+
eq(M._generate_args {}, {})
2223
end
2324

2425
T["should merge with another SearchOpts instance"] = function()
2526
local opts1 = { fixed_strings = true, max_count_per_file = 1 }
2627
local opts2 = { fixed_strings = false, ignore_case = true }
27-
local opt = M._merge(opts1, opts2)
28-
eq(M.to_ripgrep_opts(opt), { "--ignore-case", "-m=1" })
28+
local opt = Opts._merge(opts1, opts2)
29+
eq(M._generate_args(opt), { "--ignore-case", "-m=1" })
2930
end
3031

3132
return T

0 commit comments

Comments
 (0)