From b3c4ff340bed8bb88dc87f054334d67e47aae492 Mon Sep 17 00:00:00 2001 From: Steven Arcangeli Date: Sat, 21 Jan 2023 15:06:05 -0800 Subject: [PATCH] feat: more actions for interacting with preview window (#41) --- .github/generate.py | 39 ++++++++++++++++++------ README.md | 5 ++-- doc/oil.txt | 62 ++++++++++++++++++++++++++++++++++++-- lua/oil/actions.lua | 73 +++++++++++++++++++++++++++++++++++++++++++-- lua/oil/config.lua | 5 ++-- lua/oil/init.lua | 1 + 6 files changed, 166 insertions(+), 19 deletions(-) diff --git a/.github/generate.py b/.github/generate.py index 4dbbbae..8477266 100755 --- a/.github/generate.py +++ b/.github/generate.py @@ -1,19 +1,13 @@ import os -from dataclasses import dataclass, field import os.path import re -from functools import lru_cache +from dataclasses import dataclass, field from typing import List -from nvim_doc_tools.vimdoc import format_vimdoc_params from nvim_doc_tools import ( - Command, LuaParam, Vimdoc, VimdocSection, - commands_from_json, - format_md_commands, - format_vimdoc_commands, generate_md_toc, indent, leftright, @@ -25,6 +19,7 @@ from nvim_doc_tools import ( replace_section, wrap, ) +from nvim_doc_tools.vimdoc import format_vimdoc_params HERE = os.path.dirname(__file__) ROOT = os.path.abspath(os.path.join(HERE, os.path.pardir)) @@ -81,7 +76,13 @@ class ColumnDef: params: List["LuaParam"] = field(default_factory=list) -HL = [LuaParam("highlight", "string|fun(value: string): string", "Highlight group, or function that returns a highlight group")] +HL = [ + LuaParam( + "highlight", + "string|fun(value: string): string", + "Highlight group, or function that returns a highlight group", + ) +] TIME = [ LuaParam("format", "string", "Format string (see :help strftime)"), ] @@ -141,6 +142,25 @@ def get_highlights_vimdoc() -> "VimdocSection": return section +def get_actions_vimdoc() -> "VimdocSection": + section = VimdocSection("Actions", "oil-actions", ["\n"]) + section.body.extend( + wrap( + "These are actions that can be used in the `keymaps` section of config options." + ) + ) + section.body.append("\n") + actions = read_nvim_json('require("oil.actions")._get_actions()') + actions.sort(key=lambda a: a["name"]) + for action in actions: + name = action["name"] + desc = action["desc"] + section.body.append(leftright(name, f"*actions.{name}*")) + section.body.extend(wrap(desc, 4)) + section.body.append("\n") + return section + + def get_columns_vimdoc() -> "VimdocSection": section = VimdocSection("Columns", "oil-columns", ["\n"]) section.body.extend( @@ -148,7 +168,7 @@ def get_columns_vimdoc() -> "VimdocSection": 'Columns can be specified as a string to use default arguments (e.g. `"icon"`), or as a table to pass parameters (e.g. `{"size", highlight = "Special"}`)' ) ) - section.body.append('\n') + section.body.append("\n") for col in COL_DEFS: section.body.append(leftright(col.name, f"*column-{col.name}*")) section.body.extend(wrap(f"Adapters: {col.adapters}", 4)) @@ -170,6 +190,7 @@ def generate_vimdoc(): get_options_vimdoc(), VimdocSection("API", "oil-api", render_vimdoc_api("oil", funcs)), get_columns_vimdoc(), + get_actions_vimdoc(), get_highlights_vimdoc(), ] ) diff --git a/README.md b/README.md index bc5dbba..9b52722 100644 --- a/README.md +++ b/README.md @@ -136,9 +136,10 @@ require("oil").setup({ skip_confirm_for_simple_edits = false, -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) - -- Additionally, if it is a string that matches "action.", - -- it will use the mapping at require("oil.action"). + -- Additionally, if it is a string that matches "actions.", + -- it will use the mapping at require("oil.actions"). -- Set to `false` to remove a keymap + -- See :help oil-actions for a list of all available actions keymaps = { ["g?"] = "actions.show_help", [""] = "actions.select", diff --git a/doc/oil.txt b/doc/oil.txt index 2fa1f71..450087b 100644 --- a/doc/oil.txt +++ b/doc/oil.txt @@ -6,7 +6,8 @@ CONTENTS *oil-content 1. Options.....................................................|oil-options| 2. Api.............................................................|oil-api| 3. Columns.....................................................|oil-columns| - 4. Highlights...............................................|oil-highlights| + 4. Actions.....................................................|oil-actions| + 5. Highlights...............................................|oil-highlights| -------------------------------------------------------------------------------- OPTIONS *oil-options* @@ -40,9 +41,10 @@ OPTIONS *oil-option skip_confirm_for_simple_edits = false, -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) - -- Additionally, if it is a string that matches "action.", - -- it will use the mapping at require("oil.action"). + -- Additionally, if it is a string that matches "actions.", + -- it will use the mapping at require("oil.actions"). -- Set to `false` to remove a keymap + -- See :help oil-actions for a list of all available actions keymaps = { ["g?"] = "actions.show_help", [""] = "actions.select", @@ -224,6 +226,60 @@ birthtime *column-birthtim function that returns a highlight group {format} `string` Format string (see :help strftime) +-------------------------------------------------------------------------------- +ACTIONS *oil-actions* + +These are actions that can be used in the `keymaps` section of config options. + +cd *actions.cd* + :cd to the current oil directory + +close *actions.close* + Close oil and restore original buffer + +open_cmdline *actions.open_cmdline* + Open vim cmdline with current entry as an argument + +open_cwd *actions.open_cwd* + Open oil in Neovim's current working directory + +open_terminal *actions.open_terminal* + Open a terminal in the current directory + +parent *actions.parent* + Navigate to the parent path + +preview *actions.preview* + Open the entry under the cursor in a preview window, or close the preview + window if already open + +preview_scroll_down *actions.preview_scroll_down* + Scroll down in the preview window + +preview_scroll_up *actions.preview_scroll_up* + Scroll up in the preview window + +refresh *actions.refresh* + Refresh current directory list + +select *actions.select* + Open the entry under the cursor + +select_split *actions.select_split* + Open the entry under the cursor in a horizontal split + +select_vsplit *actions.select_vsplit* + Open the entry under the cursor in a vertical split + +show_help *actions.show_help* + Show default keymaps + +tcd *actions.tcd* + :tcd to the current oil directory + +toggle_hidden *actions.toggle_hidden* + Toggle hidden files and directories + -------------------------------------------------------------------------------- HIGHLIGHTS *oil-highlights* diff --git a/lua/oil/actions.lua b/lua/oil/actions.lua index 88ae755..967e68d 100644 --- a/lua/oil/actions.lua +++ b/lua/oil/actions.lua @@ -29,13 +29,65 @@ M.select_split = { end, } +---@return nil|integer +local function get_preview_win() + for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if vim.api.nvim_win_is_valid(winid) and vim.api.nvim_win_get_option(winid, "previewwindow") then + return winid + end + end +end + M.preview = { - desc = "Open the entry under the cursor in a preview window", + desc = "Open the entry under the cursor in a preview window, or close the preview window if already open", callback = function() + local entry = oil.get_cursor_entry() + if not entry then + vim.notify("Could not find entry under cursor", vim.log.levels.ERROR) + return + end + local winid = get_preview_win() + if winid then + local cur_id = vim.w[winid].oil_entry_id + if entry.id == cur_id then + vim.api.nvim_win_close(winid, true) + return + end + end oil.select({ preview = true }) end, } +M.preview_scroll_down = { + desc = "Scroll down in the preview window", + callback = function() + local winid = get_preview_win() + if winid then + vim.api.nvim_win_call(winid, function() + vim.cmd.normal({ + args = { vim.api.nvim_replace_termcodes("", true, true, true) }, + bang = true, + }) + end) + end + end, +} + +M.preview_scroll_up = { + desc = "Scroll up in the preview window", + callback = function() + local winid = get_preview_win() + if winid then + vim.api.nvim_win_call(winid, function() + vim.cmd.normal({ + args = { vim.api.nvim_replace_termcodes("", true, true, true) }, + bang = true, + }) + end) + end + end, +} + M.parent = { desc = "Navigate to the parent path", callback = oil.open, @@ -71,7 +123,7 @@ M.tcd = { } M.open_cwd = { - desc = "Open oil in Neovim's cwd", + desc = "Open oil in Neovim's current working directory", callback = function() oil.open(vim.fn.getcwd()) end, @@ -95,7 +147,7 @@ M.open_terminal = { } M.refresh = { - desc = "Refresh directory", + desc = "Refresh current directory list", callback = function() if vim.bo.modified then local ok, choice = pcall(vim.fn.confirm, "Discard changes?", "No\nYes") @@ -134,4 +186,19 @@ M.open_cmdline = { end, } +---List actions for documentation generation +---@private +M._get_actions = function() + local ret = {} + for name, action in pairs(M) do + if type(action) == "table" and action.desc then + table.insert(ret, { + name = name, + desc = action.desc, + }) + end + end + return ret +end + return M diff --git a/lua/oil/config.lua b/lua/oil/config.lua index f9c0098..2bc1342 100644 --- a/lua/oil/config.lua +++ b/lua/oil/config.lua @@ -26,9 +26,10 @@ local default_config = { skip_confirm_for_simple_edits = false, -- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap -- options with a `callback` (e.g. { callback = function() ... end, desc = "", nowait = true }) - -- Additionally, if it is a string that matches "action.", - -- it will use the mapping at require("oil.action"). + -- Additionally, if it is a string that matches "actions.", + -- it will use the mapping at require("oil.actions"). -- Set to `false` to remove a keymap + -- See :help oil-actions for a list of all available actions keymaps = { ["g?"] = "actions.show_help", [""] = "actions.select", diff --git a/lua/oil/init.lua b/lua/oil/init.lua index c7c6545..f9108c9 100644 --- a/lua/oil/init.lua +++ b/lua/oil/init.lua @@ -407,6 +407,7 @@ M.select = function(opts) }) if opts.preview then vim.api.nvim_win_set_option(0, "previewwindow", true) + vim.api.nvim_win_set_var(0, "oil_entry_id", entry.id) vim.api.nvim_set_current_win(prev_win) end -- Set opts.split so that for every entry after the first, we do a split