From 57528bf9c58080ca891e8d362d0a578895c136ce Mon Sep 17 00:00:00 2001 From: Steven Arcangeli Date: Fri, 24 Jan 2025 15:09:36 -0800 Subject: [PATCH] feat: API to automatically open preview window after opening oil (#339) --- README.md | 4 ++-- doc/api.md | 36 +++++++++++++++++++---------- doc/oil.txt | 28 ++++++++++++++++++----- lua/oil/init.lua | 51 +++++++++++++++++++++++++++++++++--------- tests/preview_spec.lua | 42 ++++++++++++++++++++++++++++++++++ tests/test_util.lua | 5 +++++ 6 files changed, 135 insertions(+), 31 deletions(-) create mode 100644 tests/preview_spec.lua diff --git a/README.md b/README.md index 87a825d..ec3355b 100644 --- a/README.md +++ b/README.md @@ -372,9 +372,9 @@ Note that at the moment the ssh adapter does not support Windows machines, and i - [set_is_hidden_file(is_hidden_file)](doc/api.md#set_is_hidden_fileis_hidden_file) - [toggle_hidden()](doc/api.md#toggle_hidden) - [get_current_dir(bufnr)](doc/api.md#get_current_dirbufnr) -- [open_float(dir)](doc/api.md#open_floatdir) +- [open_float(dir, opts, cb)](doc/api.md#open_floatdir-opts-cb) - [toggle_float(dir)](doc/api.md#toggle_floatdir) -- [open(dir)](doc/api.md#opendir) +- [open(dir, opts, cb)](doc/api.md#opendir-opts-cb) - [close(opts)](doc/api.md#closeopts) - [open_preview(opts, callback)](doc/api.md#open_previewopts-callback) - [select(opts, callback)](doc/api.md#selectopts-callback) diff --git a/doc/api.md b/doc/api.md index 2f51cdd..3e6a3e6 100644 --- a/doc/api.md +++ b/doc/api.md @@ -10,9 +10,9 @@ - [set_is_hidden_file(is_hidden_file)](#set_is_hidden_fileis_hidden_file) - [toggle_hidden()](#toggle_hidden) - [get_current_dir(bufnr)](#get_current_dirbufnr) -- [open_float(dir)](#open_floatdir) +- [open_float(dir, opts, cb)](#open_floatdir-opts-cb) - [toggle_float(dir)](#toggle_floatdir) -- [open(dir)](#opendir) +- [open(dir, opts, cb)](#opendir-opts-cb) - [close(opts)](#closeopts) - [open_preview(opts, callback)](#open_previewopts-callback) - [select(opts, callback)](#selectopts-callback) @@ -92,14 +92,20 @@ Get the current directory | ----- | -------------- | ---- | | bufnr | `nil\|integer` | | -## open_float(dir) +## open_float(dir, opts, cb) -`open_float(dir)` \ +`open_float(dir, opts, cb)` \ Open oil browser in a floating window -| Param | Type | Desc | -| ----- | ------------- | ------------------------------------------------------------------------------------------- | -| dir | `nil\|string` | When nil, open the parent of the current buffer, or the cwd if current buffer is not a file | +| Param | Type | Desc | +| ------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| dir | `nil\|string` | When nil, open the parent of the current buffer, or the cwd if current buffer is not a file | +| opts | `nil\|oil.OpenOpts` | | +| >preview | `nil\|oil.OpenPreviewOpts` | When present, open the preview window after opening oil | +| >>vertical | `nil\|boolean` | Open the buffer in a vertical split | +| >>horizontal | `nil\|boolean` | Open the buffer in a horizontal split | +| >>split | `nil\|"aboveleft"\|"belowright"\|"topleft"\|"botright"` | Split modifier | +| cb | `nil\|fun()` | Called after the oil buffer is ready | ## toggle_float(dir) @@ -110,14 +116,20 @@ Open oil browser in a floating window, or close it if open | ----- | ------------- | ------------------------------------------------------------------------------------------- | | dir | `nil\|string` | When nil, open the parent of the current buffer, or the cwd if current buffer is not a file | -## open(dir) +## open(dir, opts, cb) -`open(dir)` \ +`open(dir, opts, cb)` \ Open oil browser for a directory -| Param | Type | Desc | -| ----- | ------------- | ------------------------------------------------------------------------------------------- | -| dir | `nil\|string` | When nil, open the parent of the current buffer, or the cwd if current buffer is not a file | +| Param | Type | Desc | +| ------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| dir | `nil\|string` | When nil, open the parent of the current buffer, or the cwd if current buffer is not a file | +| opts | `nil\|oil.OpenOpts` | | +| >preview | `nil\|oil.OpenPreviewOpts` | When present, open the preview window after opening oil | +| >>vertical | `nil\|boolean` | Open the buffer in a vertical split | +| >>horizontal | `nil\|boolean` | Open the buffer in a horizontal split | +| >>split | `nil\|"aboveleft"\|"belowright"\|"topleft"\|"botright"` | Split modifier | +| cb | `nil\|fun()` | Called after the oil buffer is ready | ## close(opts) diff --git a/doc/oil.txt b/doc/oil.txt index 1dd27d2..df8754b 100644 --- a/doc/oil.txt +++ b/doc/oil.txt @@ -304,12 +304,20 @@ get_current_dir({bufnr}): nil|string *oil.get_current_di Parameters: {bufnr} `nil|integer` -open_float({dir}) *oil.open_float* +open_float({dir}, {opts}, {cb}) *oil.open_float* Open oil browser in a floating window Parameters: - {dir} `nil|string` When nil, open the parent of the current buffer, or the - cwd if current buffer is not a file + {dir} `nil|string` When nil, open the parent of the current buffer, or + the cwd if current buffer is not a file + {opts} `nil|oil.OpenOpts` + {preview} `nil|oil.OpenPreviewOpts` When present, open the preview + window after opening oil + {vertical} `nil|boolean` Open the buffer in a vertical split + {horizontal} `nil|boolean` Open the buffer in a horizontal split + {split} `nil|"aboveleft"|"belowright"|"topleft"|"botright"` S + plit modifier + {cb} `nil|fun()` Called after the oil buffer is ready toggle_float({dir}) *oil.toggle_float* Open oil browser in a floating window, or close it if open @@ -318,12 +326,20 @@ toggle_float({dir}) *oil.toggle_floa {dir} `nil|string` When nil, open the parent of the current buffer, or the cwd if current buffer is not a file -open({dir}) *oil.open* +open({dir}, {opts}, {cb}) *oil.open* Open oil browser for a directory Parameters: - {dir} `nil|string` When nil, open the parent of the current buffer, or the - cwd if current buffer is not a file + {dir} `nil|string` When nil, open the parent of the current buffer, or + the cwd if current buffer is not a file + {opts} `nil|oil.OpenOpts` + {preview} `nil|oil.OpenPreviewOpts` When present, open the preview + window after opening oil + {vertical} `nil|boolean` Open the buffer in a vertical split + {horizontal} `nil|boolean` Open the buffer in a horizontal split + {split} `nil|"aboveleft"|"belowright"|"topleft"|"botright"` S + plit modifier + {cb} `nil|fun()` Called after the oil buffer is ready close({opts}) *oil.close* Restore the buffer that was present when oil was opened diff --git a/lua/oil/init.lua b/lua/oil/init.lua index 46fd69d..16a3dc9 100644 --- a/lua/oil/init.lua +++ b/lua/oil/init.lua @@ -241,18 +241,21 @@ M.get_buffer_parent_url = function(bufname, use_oil_parent) end end +---@class (exact) oil.OpenOpts +---@field preview? oil.OpenPreviewOpts When present, open the preview window after opening oil + ---Open oil browser in a floating window ----@param dir nil|string When nil, open the parent of the current buffer, or the cwd if current buffer is not a file -M.open_float = function(dir) +---@param dir? string When nil, open the parent of the current buffer, or the cwd if current buffer is not a file +---@param opts? oil.OpenOpts +---@param cb? fun() Called after the oil buffer is ready +M.open_float = function(dir, opts, cb) + opts = opts or {} local config = require("oil.config") local layout = require("oil.layout") local util = require("oil.util") local view = require("oil.view") local parent_url, basename = M.get_url_for_path(dir) - if not parent_url then - return - end if basename then view.set_last_cursor(parent_url, basename) end @@ -326,6 +329,14 @@ M.open_float = function(dir) vim.api.nvim_set_option_value("buflisted", config.buf_options.buflisted, { buf = 0 }) end + util.run_after_load(0, function() + if opts.preview then + M.open_preview(opts.preview, cb) + elseif cb then + cb() + end + end) + if vim.fn.has("nvim-0.9") == 0 then util.add_title_to_win(winid) end @@ -359,15 +370,15 @@ local function update_preview_window(oil_bufnr) end ---Open oil browser for a directory ----@param dir nil|string When nil, open the parent of the current buffer, or the cwd if current buffer is not a file -M.open = function(dir) +---@param dir? string When nil, open the parent of the current buffer, or the cwd if current buffer is not a file +---@param opts? oil.OpenOpts +---@param cb? fun() Called after the oil buffer is ready +M.open = function(dir, opts, cb) + opts = opts or {} local config = require("oil.config") local util = require("oil.util") local view = require("oil.view") local parent_url, basename = M.get_url_for_path(dir) - if not parent_url then - return - end if basename then view.set_last_cursor(parent_url, basename) end @@ -377,6 +388,14 @@ M.open = function(dir) vim.api.nvim_set_option_value("buflisted", config.buf_options.buflisted, { buf = 0 }) end + util.run_after_load(0, function() + if opts.preview then + M.open_preview(opts.preview, cb) + elseif cb then + cb() + end + end) + -- If preview window exists, update its content update_preview_window() end @@ -1104,6 +1123,7 @@ M.setup = function(opts) end local float = false local trash = false + local preview = false local i = 1 while i <= #args.fargs do local v = args.fargs[i] @@ -1113,6 +1133,11 @@ M.setup = function(opts) elseif v == "--trash" then trash = true table.remove(args.fargs, i) + elseif v == "--preview" then + -- In the future we may want to support specifying options for the preview window (e.g. + -- vertical/horizontal), but if you want that level of control maybe just use the API + preview = true + table.remove(args.fargs, i) elseif v == "--progress" then local mutator = require("oil.mutator") if mutator.is_mutating() then @@ -1136,12 +1161,16 @@ M.setup = function(opts) local method = float and "open_float" or "open" local path = args.fargs[1] + local opts = {} if trash then local url = M.get_url_for_path(path, false) local _, new_path = util.parse_url(url) path = "oil-trash://" .. new_path end - M[method](path) + if preview then + opts.preview = {} + end + M[method](path, opts) end, { desc = "Open oil file browser on a directory", nargs = "*", complete = "dir" }) local aug = vim.api.nvim_create_augroup("Oil", {}) diff --git a/tests/preview_spec.lua b/tests/preview_spec.lua new file mode 100644 index 0000000..b386001 --- /dev/null +++ b/tests/preview_spec.lua @@ -0,0 +1,42 @@ +require("plenary.async").tests.add_to_env() +local TmpDir = require("tests.tmpdir") +local oil = require("oil") +local test_util = require("tests.test_util") +local util = require("oil.util") + +a.describe("oil preview", function() + local tmpdir + a.before_each(function() + tmpdir = TmpDir.new() + end) + a.after_each(function() + if tmpdir then + tmpdir:dispose() + end + test_util.reset_editor() + end) + + a.it("opens preview window", function() + tmpdir:create({ "a.txt" }) + oil.open(tmpdir.path) + test_util.wait_oil_ready() + a.wrap(oil.open_preview, 2)() + local preview_win = util.get_preview_win() + assert.not_nil(preview_win) + assert(preview_win) + local bufnr = vim.api.nvim_win_get_buf(preview_win) + local preview_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + assert.are.same({ "a.txt" }, preview_lines) + end) + + a.it("opens preview window when open(preview={})", function() + tmpdir:create({ "a.txt" }) + a.wrap(oil.open, 3)(tmpdir.path, { preview = {} }) + local preview_win = util.get_preview_win() + assert.not_nil(preview_win) + assert(preview_win) + local bufnr = vim.api.nvim_win_get_buf(preview_win) + local preview_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + assert.are.same({ "a.txt" }, preview_lines) + end) +end) diff --git a/tests/test_util.lua b/tests/test_util.lua index 0076689..bb09524 100644 --- a/tests/test_util.lua +++ b/tests/test_util.lua @@ -1,6 +1,7 @@ require("plenary.async").tests.add_to_env() local cache = require("oil.cache") local test_adapter = require("oil.adapters.test") +local util = require("oil.util") local M = {} M.reset_editor = function() @@ -53,6 +54,10 @@ M.wait_for_autocmd = a.wrap(function(autocmd, cb) vim.api.nvim_create_autocmd(autocmd, opts) end, 2) +M.wait_oil_ready = a.wrap(function(cb) + util.run_after_load(0, vim.schedule_wrap(cb)) +end, 1) + ---@param actions string[] ---@param timestep integer M.feedkeys = function(actions, timestep)