diff --git a/README.md b/README.md index 0621e856..3d037f01 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ _Note:_ sync is disabled when doing multiline replacement (`--multiline` flag) _Note:_ if you would like sync to work when doing a replacement with empty string, please add `--replace=` to the flags. -### Going to / Opening Result Location +### Going to / Opening / Previewing Result Location When the cursor is placed on a result file path, you can go to that file by pressing `` in normal mode (`Goto` action default keybind). When it's placed over a result match line, you will be taken to the file/line/column of the match. By default, the file buffer is opened in the last window you were in before opening grug-far, which is typically the other vertical split. @@ -156,6 +156,8 @@ _Note:_ for both `Goto` and `Open` actions, if a `` is entered beforehand In order to smoothly `Open` each result location in sequence, you can use the `Open Next` and `Open Prev` actions. +If you would like to keep the buffers layout, you can use the `Preview` action instead, which will open location in a floating window. + ### Opening result lines in quickfix list Result lines can be opened in the quickfix list. Deleting result lines will cause them not to be included. diff --git a/lua/grug-far/actions/previewLocation.lua b/lua/grug-far/actions/previewLocation.lua new file mode 100644 index 00000000..1f4ed499 --- /dev/null +++ b/lua/grug-far/actions/previewLocation.lua @@ -0,0 +1,40 @@ +local resultsList = require('grug-far/render/resultsList') + +local function previewLocation(params) + local api = vim.api + local fn = vim.fn + local buf = params.buf + local context = params.context + local grugfar_win = fn.bufwinid(buf) + local cursor_row = unpack(api.nvim_win_get_cursor(grugfar_win)) + local location = resultsList.getResultLocation(cursor_row - 1, buf, context) + if location == nil then + return + end + + local width = api.nvim_win_get_width(0) + local height = api.nvim_win_get_height(0) + local opts = { + relative = 'win', + border = 'rounded', + width = width, + height = math.floor(height / 3), + bufpos = { fn.line('.') - 1, fn.col('.') }, + focusable = true, + win = grugfar_win, + style = 'minimal', + } + + local w = api.nvim_open_win(0, true, opts) + local bufnr = fn.bufnr(location.filename) + if bufnr == -1 then + fn.win_execute(w, 'e ' .. vim.fn.fnameescape(location.filename), true) + else + api.nvim_win_set_buf(w, bufnr) + end + api.nvim_win_set_cursor(w, { location.lnum, location.col - 1 }) + local b = fn.winbufnr(w) + api.nvim_set_option_value('bufhidden', 'wipe', { buf = b }) +end + +return previewLocation diff --git a/lua/grug-far/farBuffer.lua b/lua/grug-far/farBuffer.lua index 1a51967d..f786212c 100644 --- a/lua/grug-far/farBuffer.lua +++ b/lua/grug-far/farBuffer.lua @@ -13,6 +13,7 @@ local historyOpen = require('grug-far/actions/historyOpen') local historyAdd = require('grug-far/actions/historyAdd') local toggleShowCommand = require('grug-far/actions/toggleShowCommand') local swapEngine = require('grug-far/actions/swapEngine') +local previewLocation = require('grug-far/actions/previewLocation') local utils = require('grug-far/utils') local resultsList = require('grug-far/render/resultsList') local inputs = require('grug-far/inputs') @@ -153,6 +154,14 @@ local function getActions(buf, context) toggleShowCommand({ buf = buf, context = context }) end, }, + { + text = 'Preview', + keymap = keymaps.previewLocation, + description = 'Preview location in floating window.', + action = function() + previewLocation({ buf = buf, context = context }) + end, + }, } end diff --git a/lua/grug-far/opts.lua b/lua/grug-far/opts.lua index df6a9396..eb9c9136 100644 --- a/lua/grug-far/opts.lua +++ b/lua/grug-far/opts.lua @@ -148,6 +148,7 @@ M.defaultOptions = { help = { n = 'g?' }, toggleShowCommand = { n = 'p' }, swapEngine = { n = 'e' }, + previewLocation = { n = 'i' }, }, -- separator between inputs and results, default depends on nerdfont @@ -306,6 +307,7 @@ M.defaultOptions = { ---@field abort KeymapDef ---@field help KeymapDef ---@field swapEngine KeymapDef +---@field previewLocation KeymapDef ---@class KeymapsOverride ---@field replace? KeymapDef @@ -326,6 +328,7 @@ M.defaultOptions = { ---@field abort? KeymapDef ---@field help? KeymapDef ---@field swapEngine? KeymapDef +---@field previewLocation KeymapDef ---@class AutoSaveTable ---@field enabled boolean diff --git a/lua/grug-far/test/helpers.lua b/lua/grug-far/test/helpers.lua index c6b4681f..829e0b26 100644 --- a/lua/grug-far/test/helpers.lua +++ b/lua/grug-far/test/helpers.lua @@ -139,6 +139,7 @@ function M.getSetupOptions() pickHistoryEntry = { n = '' }, toggleShowCommand = { n = ',p' }, swapEngine = { n = ',e' }, + previewLocation = { n = ',i' }, }, history = { historyDir = vim.uv.cwd() .. '/temp_history_dir', diff --git a/tests/base/test_preview.lua b/tests/base/test_preview.lua new file mode 100644 index 00000000..bb73d1aa --- /dev/null +++ b/tests/base/test_preview.lua @@ -0,0 +1,45 @@ +local MiniTest = require('mini.test') +local helpers = require('grug-far/test/helpers') +local keymaps = helpers.getKeymaps() + +---@type NeovimChild +local child = MiniTest.new_child_neovim() + +local T = MiniTest.new_set({ + hooks = { + pre_case = function() + helpers.initChildNeovim(child) + end, + -- Stop once all test cases are finished + post_once = child.stop, + }, +}) + +T['can preview a given location'] = function() + helpers.writeTestFiles({ + { filename = 'file1.txt', content = [[ + grug walks + then grug swims + ]] }, + { + filename = 'file2.doc', + content = [[ + grug talks and grug drinks + then grug thinks + ]], + }, + }) + + helpers.childRunGrugFar(child, { + windowCreationCommand = 'vsplit', + prefills = { search = 'grug' }, + }) + helpers.childWaitForFinishedStatus(child) + + child.type_keys('10G') + child.type_keys('' .. keymaps.previewLocation.n) + helpers.childWaitForScreenshotText(child, '│ grug walks │') + helpers.childExpectScreenshot(child) +end + +return T diff --git a/tests/screenshots/tests-base-test_preview.lua---can-preview-a-given-location b/tests/screenshots/tests-base-test_preview.lua---can-preview-a-given-location new file mode 100644 index 00000000..45eb9eda --- /dev/null +++ b/tests/screenshots/tests-base-test_preview.lua---can-preview-a-given-location @@ -0,0 +1,51 @@ +--|---------|---------|---------|---------|---------|---------|---------|---------| +01|  Actions / Help ... │ +02| │~ +03|  Search: │~ +04| grug │~ +05|  Replace: │~ +06| │~ +07|  Files Filter: │~ +08| │~ +09| 󰮚 Flags: │~ +10| │~ +11|  Paths: │~ +12| │~ +13| │~ +14| STATUS_SUCCESS ⟪ ripgrep ⟫│~ +15| 5 ma╭────────────────────────────────────────╮ +16| │ │ +17| file│ grug walks │ +18|-2:8:│ then grug swims │ +19|│3:13│ │ +20| │ │ +21| file│ │ +22|-2:7:│ │ +23|Grug ╰────────────────────────────────────────╯me] 0,0-1 All +24| 2,8 All + +--|---------|---------|---------|---------|---------|---------|---------|---------| +01|01111111111111111111112222222222222222223222222222222222222222222222222222222222 +02|02222222222222222222222222222222222222223000000000000000000000000000000000000000 +03|44444444442222222222222222222222222222223000000000000000000000000000000000000000 +04|02222222222222222222222222222222222222223000000000000000000000000000000000000000 +05|44444444444222222222222222222222222222223000000000000000000000000000000000000000 +06|02222222222222222222222222222222222222223000000000000000000000000000000000000000 +07|44444444444444442222222222222222222222223000000000000000000000000000000000000000 +08|02222222222222222222222222222222222222223000000000000000000000000000000000000000 +09|44444444422222222222222222222222222222223000000000000000000000000000000000000000 +10|02222222222222222222222222222222222222223000000000000000000000000000000000000000 +11|44444444422222222222222222222222222222223000000000000000000000000000000000000000 +12|02222222222222222222222222222222222222223000000000000000000000000000000000000000 +13|22222222222222222222222222222222222222223000000000000000000000000000000000000000 +14|55555555555555555555555555555555555555553000000000000000000000000000000000000000 +15|55555666666666666666666666666666666666666666666000000000000000000000000000000000 +16|02222666666666666666666666666666666666666666666000000000000000000000000000000000 +17|07777666666666666666666666666666666666666666666000000000000000000000000000000000 +18|08282666666666666666666666666666666666666666666000000000000000000000000000000000 +19|08288666666666666666666666666666666666666666666000000000000000000000000000000000 +20|02222699999999999999999999999999999999999999996000000000000000000000000000000000 +21|07777699999999999999999999999999999999999999996000000000000000000000000000000000 +22|08282699999999999999999999999999999999999999996000000000000000000000000000000000 +23|:::::666666666666666666666666666666666666666666::::::::::::::::::::::::::::::::: +24|;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;