From 2f7271120e5b3996aaf5cc67a6eb0bb799ecaf61 Mon Sep 17 00:00:00 2001 From: Elflare <271374942@qq.com> Date: Sun, 6 Jul 2025 14:58:30 +0800 Subject: [PATCH] add auto_save and fix bugs --- README.md | 4 +- lua/memos/init.lua | 140 ++++++++------- lua/memos/ui.lua | 434 ++++++++++++++++++++++++++------------------- 3 files changed, 329 insertions(+), 249 deletions(-) diff --git a/README.md b/README.md index d4d3d32..a403cc1 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ require("memos").setup({ -- Number of memos to fetch per page pageSize = 50, - + auto_save = false, -- Set to false or nil to disable a keymap keymaps = { -- Keymap to open the memos list. Default: mm @@ -176,7 +176,7 @@ require("memos").setup({ -- 每页获取的 memo 数量 pageSize = 50, - + auto_save = false, -- 设置为 false 或 nil 可以禁用某个快捷键 keymaps = { -- 用于打开 Memos 列表的快捷键。默认值: mm diff --git a/lua/memos/init.lua b/lua/memos/init.lua index 4702358..51379ce 100644 --- a/lua/memos/init.lua +++ b/lua/memos/init.lua @@ -3,10 +3,11 @@ local M = {} M.config = { host = nil, token = nil, + auto_save = false, pageSize = 50, keymaps = { start_memos = "mm", - -- 在列表窗口中的快捷键 + -- 在列表窗口中的快捷键 list = { add_memo = 'a', delete_memo = 'd', @@ -18,7 +19,7 @@ M.config = { next_page = '.', quit = 'q' }, - -- 在编辑和创建窗口中的快捷键 + -- 在编辑和创建窗口中的快捷键 buffer = { save = 'ms' } @@ -30,89 +31,96 @@ local config_file_path = config_dir .. "/memos_config.json" -- 【修改】全新的、能处理 host 和 token 的交互式配置函数 local function prompt_for_config() - local function prompt_for_token() - vim.ui.input({ prompt = "Memos Access Token:", hide = true }, function(token) - if token and token ~= "" then - M.config.token = token - local choice = vim.fn.confirm("Save host and token for future sessions?", "&Yes\n&No", 2) - if choice == 1 then - vim.fn.mkdir(config_dir, "p") - -- 将 host 和 token 一起存入 JSON 文件 - local config_to_save = { host = M.config.host, token = M.config.token } - vim.fn.writefile({ vim.json.encode(config_to_save) }, config_file_path) - vim.notify("Host and token saved permanently.", vim.log.levels.INFO) - end - else - vim.notify("No token entered. Memos plugin will not work.", vim.log.levels.ERROR) - end - end) - end + local function prompt_for_token() + vim.ui.input({ + prompt = "Memos Access Token:", + hide = true + }, function(token) + if token and token ~= "" then + M.config.token = token + local choice = vim.fn.confirm("Save host and token for future sessions?", "&Yes\n&No", 2) + if choice == 1 then + vim.fn.mkdir(config_dir, "p") + -- 将 host 和 token 一起存入 JSON 文件 + local config_to_save = { + host = M.config.host, + token = M.config.token + } + vim.fn.writefile({vim.json.encode(config_to_save)}, config_file_path) + vim.notify("Host and token saved permanently.", vim.log.levels.INFO) + end + else + vim.notify("No token entered. Memos plugin will not work.", vim.log.levels.ERROR) + end + end) + end - if not M.config.host then - vim.ui.input({ prompt = "Memos Host URL (e.g., http://127.0.0.1:5230):" }, function(host) - if host and host ~= "" then - M.config.host = host - -- 获取到 host 后,接着获取 token + if not M.config.host then + vim.ui.input({ + prompt = "Memos Host URL (e.g., http://127.0.0.1:5230):" + }, function(host) + if host and host ~= "" then + M.config.host = host + -- 获取到 host 后,接着获取 token + prompt_for_token() + else + vim.notify("No host entered. Memos plugin will not work.", vim.log.levels.ERROR) + end + end) + else + -- 如果 host 已存在,只获取 token prompt_for_token() - else - vim.notify("No host entered. Memos plugin will not work.", vim.log.levels.ERROR) - end - end) - else - -- 如果 host 已存在,只获取 token - prompt_for_token() - end + end end - function M.setup(opts) - -- 1. 先加载默认配置 - local final_config = vim.deepcopy(M.config) + -- 1. 先加载默认配置 + local final_config = vim.deepcopy(M.config) - -- 2. 加载文件中的配置 - if vim.fn.filereadable(config_file_path) == 1 then - local file_content = vim.fn.readfile(config_file_path) - if file_content and #file_content > 0 and file_content[1] ~= "" then - local saved_config = vim.json.decode(file_content[1]) - final_config = vim.tbl_deep_extend("force", final_config, saved_config) + -- 2. 加载文件中的配置 + if vim.fn.filereadable(config_file_path) == 1 then + local file_content = vim.fn.readfile(config_file_path) + if file_content and #file_content > 0 and file_content[1] ~= "" then + local saved_config = vim.json.decode(file_content[1]) + final_config = vim.tbl_deep_extend("force", final_config, saved_config) + end end - end - -- 3. 加载环境变量 (优先级高于文件) - local token_from_env = os.getenv('MEMOS_TOKEN') - if token_from_env and token_from_env ~= "" then - final_config.token = token_from_env - end - local host_from_env = os.getenv('MEMOS_HOST') - if host_from_env and host_from_env ~= "" then - final_config.host = host_from_env - end + -- 3. 加载环境变量 (优先级高于文件) + local token_from_env = os.getenv('MEMOS_TOKEN') + if token_from_env and token_from_env ~= "" then + final_config.token = token_from_env + end + local host_from_env = os.getenv('MEMOS_HOST') + if host_from_env and host_from_env ~= "" then + final_config.host = host_from_env + end - -- 4. 加载用户在 setup() 中直接提供的配置 (优先级最高) - final_config = vim.tbl_deep_extend("force", final_config, opts or {}) + -- 4. 加载用户在 setup() 中直接提供的配置 (优先级最高) + final_config = vim.tbl_deep_extend("force", final_config, opts or {}) - M.config = final_config + M.config = final_config end -- 【修改】确保在执行任何操作前,配置是完整的 local function ensure_config(callback) - if M.config.host and M.config.token then - callback() - else - prompt_for_config() - end + if M.config.host and M.config.token then + callback() + else + prompt_for_config() + end end function M.create_memo() - ensure_config(function() - require('memos.ui').create_memo_in_buffer() - end) + ensure_config(function() + require('memos.ui').create_memo_in_buffer() + end) end function M.show_list() - ensure_config(function() - require('memos.ui').show_memos_list() - end) + ensure_config(function() + require('memos.ui').show_memos_list() + end) end -return M \ No newline at end of file +return M diff --git a/lua/memos/ui.lua b/lua/memos/ui.lua index 7e51ed2..e56c670 100644 --- a/lua/memos/ui.lua +++ b/lua/memos/ui.lua @@ -16,74 +16,123 @@ local current_filter = nil -- 渲染 Memos 列表到 buffer local function render_memos(data, append) - vim.schedule(function() - if not buf_id or not vim.api.nvim_buf_is_valid(buf_id) then return end - local new_memos = data.memos or {} - current_page_token = data.nextPageToken or "" - if append then - memos_cache = vim.list_extend(memos_cache, new_memos) - else - memos_cache = new_memos - end - local lines = {} - local k = config.keymaps.list - if #memos_cache == 0 then - local help = string.format("No memos found. Press '%s' to refresh, '%s' to add, or '%s' to quit.", - k.refresh_list, k.add_memo, k.quit) - table.insert(lines, help) - else - for i, memo in ipairs(memos_cache) do - local first_line = memo.content:match("^[^\n]*") - local display_time = memo.displayTime:sub(1, 10) - table.insert(lines, string.format("%d. [%s] %s", i, display_time, first_line)) - end - end - if current_page_token ~= "" then - table.insert(lines, "...") - table.insert(lines, string.format("(Press '%s' to load more)", k.next_page)) - end - vim.api.nvim_buf_set_option(buf_id, 'modifiable', true) - vim.api.nvim_buf_set_lines(buf_id, 0, -1, false, lines) - vim.api.nvim_buf_set_option(buf_id, 'modifiable', false) - end) + vim.schedule(function() + if not buf_id or not vim.api.nvim_buf_is_valid(buf_id) then + return + end + local new_memos = data.memos or {} + current_page_token = data.nextPageToken or "" + if append then + memos_cache = vim.list_extend(memos_cache, new_memos) + else + memos_cache = new_memos + end + local lines = {} + local k = config.keymaps.list + if #memos_cache == 0 then + local help = string.format("No memos found. Press '%s' to refresh, '%s' to add, or '%s' to quit.", + k.refresh_list, k.add_memo, k.quit) + table.insert(lines, help) + else + for i, memo in ipairs(memos_cache) do + local first_line = memo.content:match("^[^\n]*") + local display_time = memo.displayTime:sub(1, 10) + table.insert(lines, string.format("%d. [%s] %s", i, display_time, first_line)) + end + end + if current_page_token ~= "" then + table.insert(lines, "...") + table.insert(lines, string.format("(Press '%s' to load more)", k.next_page)) + end + vim.api.nvim_buf_set_option(buf_id, 'modifiable', true) + vim.api.nvim_buf_set_lines(buf_id, 0, -1, false, lines) + vim.api.nvim_buf_set_option(buf_id, 'modifiable', false) + end) end -- 设置编辑 buffer 的通用函数 local function setup_buffer_for_editing() - vim.bo.buftype = 'nofile' - vim.bo.bufhidden = 'wipe' - vim.bo.swapfile = false - vim.bo.buflisted = true + vim.bo.buftype = 'nofile' + vim.bo.bufhidden = 'wipe' + vim.bo.swapfile = false + vim.bo.buflisted = true + vim.bo.filetype = 'markdown' - vim.bo.filetype = 'markdown' - - local save_key_string = "" - if config.keymaps.buffer.save and config.keymaps.buffer.save ~= "" then - save_key_string = string.format(" or %s", config.keymaps.buffer.save) - end + local save_key_string = "" + if config.keymaps.buffer.save and config.keymaps.buffer.save ~= "" then + save_key_string = string.format(" or %s", config.keymaps.buffer.save) + end - if vim.b.memos_memo_name then - vim.notify("Editing memo. Use :MemosSave" .. save_key_string .. " to save.") - else - vim.notify("📝 New memo. Use :MemosSave" .. save_key_string .. " to create.") - end - - vim.api.nvim_buf_create_user_command(0, 'MemosSave', 'lua require("memos.ui").save_or_create_dispatcher()', {}) - if config.keymaps.buffer.save and config.keymaps.buffer.save ~= "" then - vim.api.nvim_buf_set_keymap(0, 'n', config.keymaps.buffer.save, 'MemosSave', { noremap = true, silent = true }) - end + if vim.b.memos_memo_name then + vim.notify("Editing memo. Use :MemosSave" .. save_key_string .. " to save.") + else + vim.notify("📝 New memo. Use :MemosSave" .. save_key_string .. " to create.") + end + + vim.api.nvim_buf_create_user_command(0, 'MemosSave', 'lua require("memos.ui").save_or_create_dispatcher()', {}) + if config.keymaps.buffer.save and config.keymaps.buffer.save ~= "" then + vim.api.nvim_buf_set_keymap(0, 'n', config.keymaps.buffer.save, 'MemosSave', { + noremap = true, + silent = true + }) + end + + -- 【修改】全新的、更可靠的自动保存逻辑 + if config.auto_save then + local group = vim.api.nvim_create_augroup('MemosAutoSave', { + clear = true + }) + + -- 1. 进入插入模式时,保存当前内容的快照 + vim.api.nvim_create_autocmd('InsertEnter', { + group = group, + buffer = 0, + callback = function() + vim.b.memos_original_content = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n') + end + }) + + -- 2. 离开插入模式时,比较内容是否发生变化 + vim.api.nvim_create_autocmd('InsertLeave', { + group = group, + buffer = 0, + callback = function() + local current_content = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n') + if vim.b.memos_original_content ~= current_content then + require('memos.ui').save_or_create_dispatcher() + end + end + }) + end end -- 打开一个已存在的 Memo local function open_memo_for_edit(memo, open_cmd) - vim.cmd(open_cmd) - local first_line = memo.content:match("^[^\n]*") - local buffer_name = "memos/" .. memo.name:gsub("memos/", "") .. "/" .. first_line:gsub("[/\\]", "_"):sub(1, 50) .. ".md" - - vim.api.nvim_buf_set_name(0, buffer_name) - vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(memo.content, '\n')) - vim.b.memos_memo_name = memo.name - setup_buffer_for_editing() + -- 1. 根据 memo 信息,构造一个唯一的 buffer 名称 + local first_line = memo.content:match("^[^\n]*") + local buffer_name = "memos/" .. memo.name:gsub("memos/", "") .. "/" .. first_line:gsub("[/\\]", "_"):sub(1, 50) .. + ".md" + + -- 2. 检查这个名字的 buffer 是否已经存在 + local existing_bufnr = vim.fn.bufnr(buffer_name) + + if existing_bufnr ~= -1 and vim.api.nvim_buf_is_loaded(existing_bufnr) then + -- 3. 如果已存在,则找到它所在的窗口并跳转过去 + local win_id = vim.fn.bufwinid(existing_bufnr) + if win_id ~= -1 then + vim.api.nvim_set_current_win(win_id) + else + -- 如果窗口已关闭但 buffer 仍在,则在当前窗口打开它 + vim.api.nvim_set_current_buf(existing_bufnr) + end + else + -- 4. 如果不存在,才执行我们之前的创建新窗口的逻辑 + vim.cmd(open_cmd) + vim.api.nvim_buf_set_name(0, buffer_name) + vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(memo.content, '\n')) + vim.b.memos_memo_name = memo.name + setup_buffer_for_editing() + end end -- =================================================================== @@ -92,160 +141,183 @@ end -- 【修正】将此函数移到 render_memos 定义之后,解决报错 function M.refresh_list_silently() - if not current_user or not current_user.name then return end - api.list_memos(current_user.name, current_filter, config.pageSize, nil, function(data) - render_memos(data, false) - end) + if not current_user or not current_user.name then + return + end + api.list_memos(current_user.name, current_filter, config.pageSize, nil, function(data) + render_memos(data, false) + end) end function M.save_or_create_dispatcher() - local memo_name = vim.b.memos_memo_name - local content = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n') + local memo_name = vim.b.memos_memo_name + local content = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n') - if content == '' then - vim.notify("Memo is empty, not sending.", vim.log.levels.WARN) - return - end - - if memo_name then - api.update_memo(memo_name, content, function(success) - if success then - vim.schedule(function() vim.notify("✅ Memo updated successfully!") end) - M.refresh_list_silently() - end - end) - else - api.create_memo(content, function(new_memo) - if new_memo and new_memo.name then - vim.schedule(function() - vim.notify("✅ Memo created successfully!") - vim.cmd('bdelete!') -- 强制关闭临时的 new_memo buffer - open_memo_for_edit(new_memo, 'enew') -- 用新 memo 的信息打开一个标准的编辑窗口 - M.refresh_list_silently() + if content == '' then + vim.notify("Memo is empty, not sending.", vim.log.levels.WARN) + return + end + + if memo_name then + api.update_memo(memo_name, content, function(success) + if success then + vim.schedule(function() + vim.notify("✅ Memo updated successfully!") + end) + M.refresh_list_silently() + end end) - else - vim.schedule(function() vim.notify("❌ Failed to create memo.", vim.log.levels.ERROR) end) - end - end) - end + else + api.create_memo(content, function(new_memo) + if new_memo and new_memo.name then + vim.schedule(function() + vim.notify("✅ Memo created successfully!") + vim.cmd('bdelete!') -- 强制关闭临时的 new_memo buffer + open_memo_for_edit(new_memo, 'enew') -- 用新 memo 的信息打开一个标准的编辑窗口 + M.refresh_list_silently() + end) + else + vim.schedule(function() + vim.notify("❌ Failed to create memo.", vim.log.levels.ERROR) + end) + end + end) + end end function M.create_memo_in_buffer() - vim.cmd('enew') - vim.b.memos_memo_name = nil - vim.api.nvim_buf_set_name(0, "memos/new_memo.md") - setup_buffer_for_editing() + vim.cmd('enew') + vim.b.memos_memo_name = nil + vim.api.nvim_buf_set_name(0, "memos/new_memo.md") + setup_buffer_for_editing() end function M.show_memos_list(filter) - current_filter = filter - local should_create_buf = true - if buf_id and vim.api.nvim_buf_is_valid(buf_id) then - should_create_buf = false - else - buf_id = vim.api.nvim_create_buf(true, true) -- listed = true, scratch = true - vim.api.nvim_buf_set_name(buf_id, " Memos") - vim.bo[buf_id].buftype = 'nofile' - vim.bo[buf_id].swapfile = false - vim.bo[buf_id].filetype = 'memos_list' - vim.bo[buf_id].modifiable = false - end - - -- 【修正】确保跳转到列表窗口,并且是在当前窗口打开 - local win_id = vim.fn.bufwinid(buf_id) - if win_id ~= -1 then - vim.api.nvim_set_current_win(win_id) - else - vim.api.nvim_set_current_buf(buf_id) - end - - vim.schedule(function() vim.notify("Getting user info...") end) - api.get_current_user(function(user) - if user and user.name then - current_user = user - vim.schedule(function() vim.notify("Fetching memos for " .. user.name .. "...") end) - api.list_memos(user.name, current_filter, config.pageSize, nil, function(data) - render_memos(data, false) - end) + current_filter = filter + local should_create_buf = true + if buf_id and vim.api.nvim_buf_is_valid(buf_id) then + should_create_buf = false else - vim.schedule(function() vim.notify("Could not get user, aborting fetch.", vim.log.levels.ERROR) end) + buf_id = vim.api.nvim_create_buf(true, true) -- listed = true, scratch = true + vim.api.nvim_buf_set_name(buf_id, " Memos") + vim.bo[buf_id].buftype = 'nofile' + vim.bo[buf_id].swapfile = false + vim.bo[buf_id].filetype = 'memos_list' + vim.bo[buf_id].modifiable = false end - end) - local function set_keymap(key, command) - if key and key ~= "" then - vim.api.nvim_buf_set_keymap(buf_id, 'n', key, command, { noremap = true, silent = true }) + -- 【修正】确保跳转到列表窗口,并且是在当前窗口打开 + local win_id = vim.fn.bufwinid(buf_id) + if win_id ~= -1 then + vim.api.nvim_set_current_win(win_id) + else + vim.api.nvim_set_current_buf(buf_id) + end + + vim.schedule(function() + vim.notify("Getting user info...") + end) + api.get_current_user(function(user) + if user and user.name then + current_user = user + vim.schedule(function() + vim.notify("Fetching memos for " .. user.name .. "...") + end) + api.list_memos(user.name, current_filter, config.pageSize, nil, function(data) + render_memos(data, false) + end) + else + vim.schedule(function() + vim.notify("Could not get user, aborting fetch.", vim.log.levels.ERROR) + end) + end + end) + + local function set_keymap(key, command) + if key and key ~= "" then + vim.api.nvim_buf_set_keymap(buf_id, 'n', key, command, { + noremap = true, + silent = true + }) + end + end + + if config.keymaps and config.keymaps.list then + local list_keymaps = config.keymaps.list + set_keymap(list_keymaps.edit_memo, 'lua require("memos.ui").edit_selected_memo()') + set_keymap(list_keymaps.vsplit_edit_memo, 'lua require("memos.ui").edit_selected_memo_in_vsplit()') + set_keymap(list_keymaps.quit, 'bdelete!') + set_keymap(list_keymaps.search_memos, 'lua require("memos.ui").search_memos()') + set_keymap(list_keymaps.refresh_list, 'lua require("memos.ui").show_memos_list()') + set_keymap(list_keymaps.next_page, 'lua require("memos.ui").load_next_page()') + set_keymap(list_keymaps.add_memo, 'lua require("memos.ui").create_memo_in_buffer()') + set_keymap(list_keymaps.delete_memo, 'lua require("memos.ui").confirm_delete_memo()') + set_keymap(list_keymaps.delete_memo_visual, 'lua require("memos.ui").confirm_delete_memo()') end - end - - if config.keymaps and config.keymaps.list then - local list_keymaps = config.keymaps.list - set_keymap(list_keymaps.edit_memo, 'lua require("memos.ui").edit_selected_memo()') - set_keymap(list_keymaps.vsplit_edit_memo, 'lua require("memos.ui").edit_selected_memo_in_vsplit()') - set_keymap(list_keymaps.quit, 'bdelete!') - set_keymap(list_keymaps.search_memos, 'lua require("memos.ui").search_memos()') - set_keymap(list_keymaps.refresh_list, 'lua require("memos.ui").show_memos_list()') - set_keymap(list_keymaps.next_page, 'lua require("memos.ui").load_next_page()') - set_keymap(list_keymaps.add_memo, 'lua require("memos.ui").create_memo_in_buffer()') - set_keymap(list_keymaps.delete_memo, 'lua require("memos.ui").confirm_delete_memo()') - set_keymap(list_keymaps.delete_memo_visual, 'lua require("memos.ui").confirm_delete_memo()') - end end function M.load_next_page() - if not current_page_token or current_page_token == "" then - vim.notify("No more pages to load.", vim.log.levels.INFO) - return - end - if not current_user or not current_user.name then - vim.notify("User info not available.", vim.log.levels.WARN) - return - end - vim.schedule(function() vim.notify("Loading next page...") end) - api.list_memos(current_user.name, current_filter, config.pageSize, current_page_token, function(data) - render_memos(data, true) - end) + if not current_page_token or current_page_token == "" then + vim.notify("No more pages to load.", vim.log.levels.INFO) + return + end + if not current_user or not current_user.name then + vim.notify("User info not available.", vim.log.levels.WARN) + return + end + vim.schedule(function() + vim.notify("Loading next page...") + end) + api.list_memos(current_user.name, current_filter, config.pageSize, current_page_token, function(data) + render_memos(data, true) + end) end function M.edit_selected_memo() - local line_num = vim.api.nvim_win_get_cursor(0)[1] - local selected_memo = memos_cache[line_num] - if selected_memo then - open_memo_for_edit(selected_memo, 'enew') - end + local line_num = vim.api.nvim_win_get_cursor(0)[1] + local selected_memo = memos_cache[line_num] + if selected_memo then + open_memo_for_edit(selected_memo, 'enew') + end end function M.edit_selected_memo_in_vsplit() - local line_num = vim.api.nvim_win_get_cursor(0)[1] - local selected_memo = memos_cache[line_num] - if selected_memo then - open_memo_for_edit(selected_memo, 'vsplit | enew') - end + local line_num = vim.api.nvim_win_get_cursor(0)[1] + local selected_memo = memos_cache[line_num] + if selected_memo then + open_memo_for_edit(selected_memo, 'vsplit | enew') + end end function M.confirm_delete_memo() - local line_num = vim.api.nvim_win_get_cursor(0)[1] - local selected_memo = memos_cache[line_num] - if not selected_memo then return end - local choice = vim.fn.confirm("Delete this memo?\n[" .. selected_memo.content:sub(1, 50) .. "...]", "&Yes\n&No", 2) - if choice == 1 then - api.delete_memo(selected_memo.name, function(success) - if success then - vim.schedule(function() - vim.notify("✅ Memo deleted.") - M.show_memos_list(current_filter) + local line_num = vim.api.nvim_win_get_cursor(0)[1] + local selected_memo = memos_cache[line_num] + if not selected_memo then + return + end + local choice = vim.fn.confirm("Delete this memo?\n[" .. selected_memo.content:sub(1, 50) .. "...]", "&Yes\n&No", 2) + if choice == 1 then + api.delete_memo(selected_memo.name, function(success) + if success then + vim.schedule(function() + vim.notify("✅ Memo deleted.") + M.show_memos_list(current_filter) + end) + else + vim.schedule(function() + vim.notify("❌ Failed to delete memo.", vim.log.levels.ERROR) + end) + end end) - else - vim.schedule(function() vim.notify("❌ Failed to delete memo.", vim.log.levels.ERROR) end) - end - end) - end + end end function M.search_memos() - vim.ui.input({ prompt = "Search Memos: " }, function(input) - M.show_memos_list(input or "") - end) + vim.ui.input({ + prompt = "Search Memos: " + }, function(input) + M.show_memos_list(input or "") + end) end return M