diff --git a/CHANGELOG.md b/CHANGELOG.md index fd984b136..8085c2f85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `opts.follow_img_func` option for customizing how to handle image paths. - Added better handling for undefined template fields, which will now be prompted for. -- Added `:ObsidianAliases` command. +- Added `:ObsidianTitles` command. ### Changed diff --git a/README.md b/README.md index 25661b9b0..7bf5613b1 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ _Keep in mind this plugin is not meant to replace Obsidian, but to complement it - `:ObsidianTags [TAG ...]` for getting a picker list of all occurrences of the given tags. -- `:ObsidianAliases` for getting a picker list of aliases of all notes in the vault. +- `:ObsidianTitles` for getting a picker list of titles and aliases of all notes in the vault. - `:ObsidianToday [OFFSET]` to open/create a new daily note. This command also takes an optional offset in days, e.g. use `:ObsidianToday -1` to go to yesterday's note. Unlike `:ObsidianYesterday` and `:ObsidianTomorrow` this command does not differentiate between weekdays and weekends. diff --git a/doc/obsidian.txt b/doc/obsidian.txt index ffbefdc2e..60a0d0b5b 100644 --- a/doc/obsidian.txt +++ b/doc/obsidian.txt @@ -76,8 +76,8 @@ COMMANDS *obsidian-commands* buffer. - `:ObsidianTags [TAG ...]` for getting a picker list of all occurrences of the given tags. -- `:ObsidianAliases` for getting a picker list of aliases of all notes in the - vault. +- `:ObsidianTitles` for getting a picker list of titles and aliases of all notes + in the vault. - `:ObsidianToday [OFFSET]` to open/create a new daily note. This command also takes an optional offset in days, e.g. use `:ObsidianToday -1` to go to yesterday’s note. Unlike `:ObsidianYesterday` and `:ObsidianTomorrow` this diff --git a/lua/obsidian/commands/aliases.lua b/lua/obsidian/commands/aliases.lua deleted file mode 100644 index 0d2d0bd8c..000000000 --- a/lua/obsidian/commands/aliases.lua +++ /dev/null @@ -1,62 +0,0 @@ -local log = require "obsidian.log" -local util = require "obsidian.util" - ----@param client obsidian.Client ----@param callback fun(alias_to_notes: table) -local find_alias = function(client, callback) - client:find_notes_async("", function(notes) - local alias_to_notes = {} - for _, note in ipairs(notes) do - for _, alias in ipairs(note.aliases) do - alias_to_notes[alias] = alias_to_notes[alias] or {} - table.insert(alias_to_notes[alias], note) - end - end - callback(alias_to_notes) - end) -end - ----@param note obsidian.Note ---- ----@return obsidian.PickerEntry -local function convert_note_to_picker_entry(note) - return { - value = note, - display = note:display_name(), - ordinal = note:display_name(), - filename = tostring(note.path), - } -end - ----@param client obsidian.Client -return function(client) - local picker = client:picker() - if not picker then - log.err "No picker configured" - return - end - - find_alias(client, function(alias_to_notes) - vim.schedule(function() - picker:pick(vim.tbl_keys(alias_to_notes), { - prompt_title = "Aliases", - callback = function(alias) - local notes = alias_to_notes[alias] - if #notes == 1 then - util.open_buffer(notes[1].path) - else - local entries = vim.tbl_map(convert_note_to_picker_entry, notes) - vim.schedule(function() - picker:pick(entries, { - prompt_title = alias, - callback = function(note) - util.open_buffer(note.path) - end, - }) - end) - end - end, - }) - end) - end) -end diff --git a/lua/obsidian/commands/init.lua b/lua/obsidian/commands/init.lua index 7e5c4e0b2..9b06d0121 100644 --- a/lua/obsidian/commands/init.lua +++ b/lua/obsidian/commands/init.lua @@ -13,7 +13,7 @@ local command_lookups = { ObsidianBacklinks = "obsidian.commands.backlinks", ObsidianSearch = "obsidian.commands.search", ObsidianTags = "obsidian.commands.tags", - ObsidianAliases = "obsidian.commands.aliases", + ObsidianTitles = "obsidian.commands.titles", ObsidianTemplate = "obsidian.commands.template", ObsidianNewFromTemplate = "obsidian.commands.new_from_template", ObsidianQuickSwitch = "obsidian.commands.quick_switch", @@ -150,7 +150,7 @@ M.register("ObsidianBacklinks", { opts = { nargs = 0, desc = "Collect backlinks" M.register("ObsidianTags", { opts = { nargs = "*", range = true, desc = "Find tags" } }) -M.register("ObsidianAliases", { opts = { nargs = "*", range = true, desc = "Find aliases" } }) +M.register("ObsidianTitles", { opts = { nargs = 0, desc = "Collect titles and aliases" } }) M.register("ObsidianSearch", { opts = { nargs = "?", desc = "Search vault" } }) diff --git a/lua/obsidian/commands/titles.lua b/lua/obsidian/commands/titles.lua new file mode 100644 index 000000000..907998c40 --- /dev/null +++ b/lua/obsidian/commands/titles.lua @@ -0,0 +1,74 @@ +local log = require "obsidian.log" +local util = require "obsidian.util" + +---@param note obsidian.Note +--- +---@return obsidian.PickerEntry +local function convert_note_to_picker_entry(note) + return { + value = note, + display = note:display_name(), + ordinal = note:display_name(), + filename = tostring(note.path), + } +end + +---@param notes obsidian.Note[] +--- +---@return table +local function map_title_to_notes(notes) + local title_to_notes = {} + for _, note in ipairs(notes) do + local title = note.title + if title then + title_to_notes[title] = title_to_notes[title] or {} + table.insert(title_to_notes[title], note) + end + for _, alias in ipairs(note.aliases) do + if alias ~= title then + title_to_notes[alias] = title_to_notes[alias] or {} + table.insert(title_to_notes[alias], note) + end + end + end + + for title, notes_share_title in pairs(title_to_notes) do + title_to_notes[title] = util.tbl_unique(notes_share_title) + end + + return title_to_notes +end + +---@param client obsidian.Client +return function(client) + local picker = client:picker() + if not picker then + log.err "No picker configured" + return + end + + client:find_notes_async("", function(notes) + local title_to_notes = map_title_to_notes(notes) + vim.schedule(function() + picker:pick(vim.tbl_keys(title_to_notes), { + prompt_title = "Titles", + callback = function(title) + local selected_notes = title_to_notes[title] + if #selected_notes == 1 then + util.open_buffer(selected_notes[1].path) + else + local entries = vim.tbl_map(convert_note_to_picker_entry, selected_notes) + vim.schedule(function() + picker:pick(entries, { + prompt_title = title, + callback = function(value) + util.open_buffer(value.path) + end, + }) + end) + end + end, + }) + end) + end) +end