diff --git a/README.md b/README.md index 152485b..a30fa34 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ A Neovim plugin to interact with [Memos](https://github.com/usememos/memos) righ - **Delete Memos**: Delete memos directly from the list. - **Customizable**: Configure API endpoints, keymaps, and more. - **First-time Setup**: On first launch, you will be prompted to enter your Memos host and token. You can choose to save these permanently. +- **Floating Window**: Optional LazyVim-style floating window for the memo list. ## 📦 Installation @@ -75,6 +76,13 @@ require("memos").setup({ -- Auto-save the memo when leaving insert mode or holding the cursor. auto_save = false, + -- Window configuration + window = { + enable_float = false, -- Set to true to open the list in a floating window + width = 0.85, -- Width ratio (0.0 to 1.0) + height = 0.85, -- Height ratio (0.0 to 1.0) + border = "rounded", -- Border style: "single", "double", "rounded", "solid", "shadow" + }, -- Set to false or nil to disable a keymap keymaps = { @@ -117,6 +125,7 @@ require("memos").setup({ - **删除 Memos**: 直接从列表中删除 memo。 - **可定制**: 可配置 API 地址、快捷键等。 - **首次启动引导**: 首次启动时会提示输入 Memos 的 host 和 token,并询问是否永久保存。 +- **浮动窗口**: 可选的 LazyVim 风格浮动窗口来展示 memo 列表。 ## 📦 安装 @@ -181,6 +190,13 @@ require("memos").setup({ -- 当离开插入模式或光标静止时,自动保存 memo。 auto_save = false, + -- 窗口配置 + window = { + enable_float = false, -- 设置为 true 以在浮动窗口中打开列表 + width = 0.85, -- 宽度比例 (0.0 到 1.0) + height = 0.85, -- 高度比例 (0.0 到 1.0) + border = "rounded", -- 边框样式: "single", "double", "rounded", "solid", "shadow" + }, -- 设置为 false 或 nil 可以禁用某个快捷键 keymaps = { diff --git a/doc/memos.nvim.txt b/doc/memos.nvim.txt index 5323b3a..83069f4 100644 --- a/doc/memos.nvim.txt +++ b/doc/memos.nvim.txt @@ -43,6 +43,13 @@ require("memos").setup({ -- Number of memos to fetch per page pageSize = 50, auto_save = false, + -- Window configuration + window = { + enable_float = false, -- Set to true to open the list in a floating window + width = 0.85, -- Width ratio (0.0 to 1.0) + height = 0.85, -- Height ratio (0.0 to 1.0) + border = "rounded", -- Border style: "single", "double", "rounded", "solid", "shadow" + }, -- Set to false or nil to disable a keymap keymaps = { -- Keymap to open the memos list. Default: mm diff --git a/lua/memos/init.lua b/lua/memos/init.lua index 7452395..e6e5d6e 100644 --- a/lua/memos/init.lua +++ b/lua/memos/init.lua @@ -1,29 +1,36 @@ local M = {} M.config = { - host = nil, - token = nil, - auto_save = false, - page_size = 50, - keymaps = { - start_memos = "mm", - -- 在列表窗口中的快捷键 - list = { - add_memo = 'a', - delete_memo = 'd', - delete_memo_visual = 'dd', - edit_memo = '', - vsplit_edit_memo = '', - search_memos = 's', - refresh_list = 'r', - next_page = '.', - quit = 'q' - }, - -- 在编辑和创建窗口中的快捷键 - buffer = { - save = 'ms' - } - } + host = nil, + token = nil, + auto_save = false, + page_size = 50, + -- 【新增】窗口配置 + window = { + enable_float = false, -- 默认为 false,设为 true 则开启浮动窗口 + width = 0.85, -- 宽度占屏幕比例 + height = 0.85, -- 高度占屏幕比例 + border = "rounded", -- 边框样式: "single", "double", "rounded", "solid", "shadow" + }, + keymaps = { + start_memos = "mm", + -- 在列表窗口中的快捷键 + list = { + add_memo = "a", + delete_memo = "d", + delete_memo_visual = "dd", + edit_memo = "", + vsplit_edit_memo = "", + search_memos = "s", + refresh_list = "r", + next_page = ".", + quit = "q", + }, + -- 在编辑和创建窗口中的快捷键 + buffer = { + save = "ms", + }, + }, } local config_dir = vim.fn.stdpath("data") .. "/memos.nvim" @@ -31,96 +38,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 - 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 + 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() + 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) - end - end + -- 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 - -- 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 diff --git a/lua/memos/ui.lua b/lua/memos/ui.lua index 4585440..e3e4963 100644 --- a/lua/memos/ui.lua +++ b/lua/memos/ui.lua @@ -193,25 +193,58 @@ function M.create_memo_in_buffer() M.setup_buffer_for_editing() end +-- 【新增】创建居中浮动窗口的辅助函数 +local function create_float_window(buf) + local width = math.floor(vim.o.columns * (config.window.width or 0.8)) + local height = math.floor(vim.o.lines * (config.window.height or 0.8)) + + -- 计算居中位置 + local row = math.floor((vim.o.lines - height) / 2) + local col = math.floor((vim.o.columns - width) / 2) + + local opts = { + relative = "editor", + row = row, + col = col, + width = width, + height = height, + style = "minimal", + border = config.window.border or "rounded", + title = " Memos ", + title_pos = "center", + } + + return vim.api.nvim_open_win(buf, true, opts) +end + function M.show_memos_list(filter) current_filter = filter local should_create_buf = true + + -- 检查 buffer 是否存在且有效 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) - vim.api.nvim_buf_set_name(buf_id, " Memos") + buf_id = vim.api.nvim_create_buf(false, true) -- 改为 false, true (unlisted, scratch) + vim.api.nvim_buf_set_name(buf_id, "MemosList") 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 + -- 检查该 buffer 是否已经在一个窗口中打开 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) + -- 【修改】根据配置决定打开方式 + if config.window and config.window.enable_float then + create_float_window(buf_id) + else + -- 传统方式:直接切换到该 buffer + vim.api.nvim_set_current_buf(buf_id) + end end vim.schedule(function()