Practical tag search handles multi-tag intersections, e.g. Marijn Haverbeke's blog
Command
-- priority: 11
command.define {
name = "Navigate: Tags Picker",
key = "Ctrl-Alt-T",
run = function()
local allTags = query[[from index.tag "tag" select {name = _.name}]]
local selectedNames = {}
while true do
local availableOptions = {}
for _, tagObj in ipairs(allTags) do
if not table.includes(selectedNames, tagObj.name) then
table.insert(availableOptions, tagObj)
end
end
if #availableOptions == 0 then
break
end
local description = "Select a Tag"
local placeholder = "🔖 a Tag"
if #selectedNames > 0 then
description = "Selected Tags ⏺️:" .. table.concat(selectedNames, ", ") .. " ➕ (ESC to Go)"
placeholder = string.rep("🔖", #selectedNames) .. " a Tag"
end
local selection = editor.filterBox("🤏 Pick", availableOptions, description, placeholder)
if selection then
table.insert(selectedNames, selection.name)
else
if #selectedNames == 0 then
return
else
break
end
end
end
local targetPage = "tags:" .. table.concat(selectedNames, ",")
editor.navigate(targetPage)
end
}
Virtual Page
-- priority: 11
virtualPage.define {
pattern = "tags:(.+)",
run = function(inputString)
local rawTags = inputString:split(",")
local tags = {}
for _, t in ipairs(rawTags) do
local cleanTag = t:trim()
if cleanTag ~= "" then
table.insert(tags, cleanTag)
end
end
if #tags == 0 then return "No tags specified." end
local text = ""
local tagName = tags[1]
local allObjects = query[[
from index.tag(tagName)
order by ref
]]
if #tags == 1 then
text = "# Objects tagged with: " .. tagName .. "\n"
local tagParts = tagName:split("/")
local parentTags = {}
for i in ipairs(tagParts) do
local slice = table.pack(table.unpack(tagParts, 1, i))
if i ~= #tagParts then
table.insert(parentTags, {name=table.concat(slice, "/")})
end
end
if #parentTags > 0 then
text = text .. "## Parent tags\n"
.. template.each(parentTags, templates.tagItem)
end
local subTags = query[[
from index.tag "tag"
where string.startsWith(_.name, tagName .. "/")
select {name=_.name}
]]
if #subTags > 0 then
text = text .. "## Child tags\n"
.. template.each(subTags, templates.tagItem)
end
else
text = "# Objects tagged with: " .. table.concat(tags, ", ") .. "\n"
for i = 2, #tags do
allObjects = query[[
from allObjects
where table.includes(_.tags, tags[i])
]]
end
end
local taggedPages = {}
local taggedTasks = {}
local taggedItems = {}
local taggedData = {}
local taggedParagraphs = {}
-- improve performance
for _, obj in ipairs(allObjects) do
if obj.itags and table.includes(obj.itags, "page") then
table.insert(taggedPages, obj)
end
if obj.itags and table.includes(obj.itags, "task") then
table.insert(taggedTasks, obj)
end
if obj.itags and table.includes(obj.itags, "item") then
table.insert(taggedItems, obj)
end
if obj.itags and table.includes(obj.itags, "data") then
table.insert(taggedData, obj)
end
if obj.itags and table.includes(obj.itags, "paragraph") then
table.insert(taggedParagraphs, obj)
end
end
if #taggedPages > 0 then
text = text .. "## Pages\n"
.. template.each(taggedPages, templates.pageItem)
end
if #taggedTasks > 0 then
text = text .. "## Tasks\n"
.. template.each(taggedTasks, templates.taskItem)
end
if #taggedItems > 0 then
text = text .. "## Items\n"
.. template.each(taggedItems, templates.itemItem)
end
if #taggedData > 0 then
text = text .. "## Data\n"
.. markdown.objectsToTable(taggedData) .. "\n"
end
if #taggedParagraphs > 0 then
text = text .. "## Paragraphs\n"
.. template.each(taggedParagraphs, templates.paragraphItem)
end
return text
end
}
