Skip to content

Commit a6596be

Browse files
committed
Make tag completion fuzzy
Relates to #359.
1 parent 8d7842e commit a6596be

File tree

2 files changed

+37
-26
lines changed

2 files changed

+37
-26
lines changed

lua/obsidian/client.lua

+34-25
Original file line numberDiff line numberDiff line change
@@ -571,9 +571,9 @@ end
571571
---@field tag_start integer|? The index within 'text' where the tag starts.
572572
---@field tag_end integer|? The index within 'text' where the tag ends.
573573

574-
--- Find all tags starting with the given term(s).
574+
--- Find all tags starting with the given search term(s).
575575
---
576-
---@param term string|string[]
576+
---@param term string|string[] The search term
577577
---@param opts obsidian.SearchOpts|boolean|? search options or a boolean indicating if sorting should be used
578578
---@param timeout integer|? Timeout in milliseconds.
579579
---
@@ -586,7 +586,7 @@ end
586586

587587
--- An async version of 'find_tags()'.
588588
---
589-
---@param term string|string[]
589+
---@param term string|string[] The search term
590590
---@param opts obsidian.SearchOpts|boolean|? search options or a boolean indicating if sorting should be used
591591
---@param callback fun(tags: obsidian.TagLocation[])
592592
Client.find_tags_async = function(self, term, opts, callback)
@@ -676,24 +676,18 @@ Client.find_tags_async = function(self, term, opts, callback)
676676
for match in iter(search.find_tags(line)) do
677677
local m_start, m_end, _ = unpack(match)
678678
local tag = string.sub(line, m_start + 1, m_end)
679-
for t in iter(terms) do
680-
-- NOTE: this works when 't' is an empty string too.
681-
if vim.startswith(string.lower(tag), t) then
682-
add_match(tag, path, note, match_data.line_number, line, m_start, m_end)
683-
n_matches = n_matches + 1
684-
break
685-
end
679+
if string.match(tag, "^" .. search.Patterns.TagCharsRequired .. "$") then
680+
add_match(tag, path, note, match_data.line_number, line)
686681
end
687682
end
688683

689684
-- check for tags in frontmatter
690685
if n_matches == 0 and note.tags ~= nil and (vim.startswith(line, "tags:") or string.match(line, "%s*- ")) then
691686
for tag in iter(note.tags) do
692687
tag = tostring(tag)
693-
for t in iter(terms) do
694-
if vim.startswith(string.lower(tag), t) then
688+
for _, t in ipairs(terms) do
689+
if string.len(t) == 0 or util.string_contains(tag, t) then
695690
add_match(tag, path, note, match_data.line_number, line)
696-
break
697691
end
698692
end
699693
end
@@ -706,13 +700,25 @@ Client.find_tags_async = function(self, term, opts, callback)
706700
local search_terms = {}
707701
for t in iter(terms) do
708702
if string.len(t) > 0 then
709-
search_terms[#search_terms + 1] = "#" .. t .. search.Patterns.TagCharsOptional -- tag in the wild
710-
search_terms[#search_terms + 1] = "\\s*- " .. t .. search.Patterns.TagCharsOptional -- frontmatter tag in multiline list
711-
search_terms[#search_terms + 1] = "tags: .*" .. t .. search.Patterns.TagCharsOptional -- frontmatter tag in inline list
703+
-- tag in the wild
704+
search_terms[#search_terms + 1] = "#" .. search.Patterns.TagCharsOptional .. t .. search.Patterns.TagCharsOptional
705+
-- frontmatter tag in multiline list
706+
search_terms[#search_terms + 1] = "\\s*- "
707+
.. search.Patterns.TagCharsOptional
708+
.. t
709+
.. search.Patterns.TagCharsOptional
710+
-- frontmatter tag in inline list
711+
search_terms[#search_terms + 1] = "tags: .*"
712+
.. search.Patterns.TagCharsOptional
713+
.. t
714+
.. search.Patterns.TagCharsOptional
712715
else
713-
search_terms[#search_terms + 1] = "#" .. search.Patterns.TagCharsRequired -- tag in the wild
714-
search_terms[#search_terms + 1] = "\\s*- " .. search.Patterns.TagCharsRequired -- frontmatter tag in multiline list
715-
search_terms[#search_terms + 1] = "tags: .*" .. search.Patterns.TagCharsRequired -- frontmatter tag in inline list
716+
-- tag in the wild
717+
search_terms[#search_terms + 1] = "#" .. search.Patterns.TagCharsRequired
718+
-- frontmatter tag in multiline list
719+
search_terms[#search_terms + 1] = "\\s*- " .. search.Patterns.TagCharsRequired
720+
-- frontmatter tag in inline list
721+
search_terms[#search_terms + 1] = "tags: .*" .. search.Patterns.TagCharsRequired
716722
end
717723
end
718724

@@ -766,14 +772,16 @@ Client.find_tags_async = function(self, term, opts, callback)
766772
end, callback)
767773
end
768774

769-
--- Gather a list of all tags in the vault.
775+
--- Gather a list of all tags in the vault. If 'term' is provided, only tags that partially match the search
776+
--- term will be included.
770777
---
771-
---@param timeout integer|? Timeout in milliseconds.
778+
---@param term string|? An optional search term to match tags
779+
---@param timeout integer|? Timeout in milliseconds
772780
---
773781
---@return string[]
774-
Client.list_tags = function(self, timeout)
782+
Client.list_tags = function(self, term, timeout)
775783
local tags = {}
776-
for _, tag_loc in ipairs(self:find_tags("", nil, timeout)) do
784+
for _, tag_loc in ipairs(self:find_tags(term and term or "", nil, timeout)) do
777785
tags[tag_loc.tag] = true
778786
end
779787
return vim.tbl_keys(tags)
@@ -782,8 +790,9 @@ end
782790
--- An async version of 'list_tags()'.
783791
---
784792
---@param callback fun(tags: string[])
785-
Client.list_tags_async = function(self, callback)
786-
self:find_tags_async("", nil, function(tag_locations)
793+
---@param term string|?
794+
Client.list_tags_async = function(self, callback, term)
795+
self:find_tags_async(term and term or "", nil, function(tag_locations)
787796
local tags = {}
788797
for _, tag_loc in ipairs(tag_locations) do
789798
tags[tag_loc.tag] = true

lua/obsidian/search.lua

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ M.RefTypes = {
2323

2424
---@enum obsidian.search.Patterns
2525
M.Patterns = {
26-
-- Miscellaneous
26+
-- Tags
2727
TagCharsOptional = "[A-Za-z0-9_/-]*",
2828
TagCharsRequired = "[A-Za-z]+[A-Za-z0-9_/-]*[A-Za-z0-9]+", -- assumes tag is at least 2 chars
29+
30+
-- Miscellaneous
2931
Highlight = "==[^=]+==", -- ==text==
3032

3133
-- References

0 commit comments

Comments
 (0)