From f487c89b56e5fb4b86d50b5b136402089e0958c7 Mon Sep 17 00:00:00 2001 From: Steven Arcangeli Date: Tue, 11 Jan 2022 16:13:16 -0800 Subject: [PATCH] cleanup!: Remove prompt buffer implementation for ui.input The `prompt_buffer = true` option will no longer function. The only input modal implementation will use a normal scratch buffer. --- autoload/dressing.vim | 8 -- doc/dressing.txt | 15 --- doc/tags | 1 - lua/dressing/init.lua | 10 -- lua/dressing/input.lua | 55 +++-------- tests/input_spec.lua | 220 +++++++++++++++++++---------------------- 6 files changed, 120 insertions(+), 189 deletions(-) diff --git a/autoload/dressing.vim b/autoload/dressing.vim index ef89d13..4275527 100644 --- a/autoload/dressing.vim +++ b/autoload/dressing.vim @@ -1,11 +1,3 @@ -func! dressing#prompt_confirm(text) abort - call luaeval("require('dressing.input').confirm(_A)", a:text) -endfunc - -func! dressing#prompt_cancel() abort - lua require('dressing.input').confirm() -endfunc - function! dressing#fzf_run(labels, options, window) abort call fzf#run({ \ 'source': a:labels, diff --git a/doc/dressing.txt b/doc/dressing.txt index 3f38f4b..30f0f7b 100644 --- a/doc/dressing.txt +++ b/doc/dressing.txt @@ -119,21 +119,6 @@ dressing.get_config() *dressing_get_config() } }) -=============================================================================== - *dressing-prompt* -Vim has a mechanism that is built for getting input from the user: the -|prompt-buffer|. This is a specific |buftype| and comes with a lot of special -handling within vim. Neovim 0.6 and earlier has some bugs with the prompt -buffer (see https://github.com/stevearc/dressing.nvim/issues/2 and -https://github.com/neovim/neovim/issues/13715). For this reason, the default -implementation of |vim.ui.input| does NOT use the prompt buffer, and instead -mimics its behavior through other means. If you don't mind the bugs, or if -you're on a version of Neovim after 0.6 (nightly has the fixes now), you can -pass `prompt_buffer = true` to use that implementation. - -There are slight visual differences in where the "prompt" text in placed, but -otherwise they should be functionally identical. - =============================================================================== *dressing-format* Sometimes you may wish to change how choices are displayed for diff --git a/doc/tags b/doc/tags index d20ad4c..6d0b466 100644 --- a/doc/tags +++ b/doc/tags @@ -2,7 +2,6 @@ Dressing dressing.txt /*Dressing* dressing dressing.txt /*dressing* dressing-configuration dressing.txt /*dressing-configuration* dressing-format dressing.txt /*dressing-format* -dressing-prompt dressing.txt /*dressing-prompt* dressing.nvim dressing.txt /*dressing.nvim* dressing.txt dressing.txt /*dressing.txt* dressing_get_config() dressing.txt /*dressing_get_config()* diff --git a/lua/dressing/init.lua b/lua/dressing/init.lua index a8b8c23..2244cf5 100644 --- a/lua/dressing/init.lua +++ b/lua/dressing/init.lua @@ -4,16 +4,6 @@ local M = {} M.setup = function(opts) config.update(opts) - -- Wait until vim has fully started up before we show deprecation warnings - vim.defer_fn(function() - if config.input.prompt_buffer then - vim.notify( - "dressing.nvim option 'input.prompt_buffer = true' is deprecated and will be removed in a future version. If you want it to continue to be supported please file an issue with your use case: https://github.com/stevearc/dressing.nvim/issues/new", - vim.log.levels.WARN, - {} - ) - end - end, 100) end local original_input diff --git a/lua/dressing/input.lua b/lua/dressing/input.lua index bb8f2ca..c274992 100644 --- a/lua/dressing/input.lua +++ b/lua/dressing/input.lua @@ -15,7 +15,7 @@ local function close_completion_window() end end -M.confirm = function(text) +local function confirm(text) if not context.on_confirm then return end @@ -41,13 +41,13 @@ M.confirm = function(text) end, 5) end -M.confirm_non_prompt = function() +M.confirm = function() local text = vim.api.nvim_buf_get_lines(0, 0, 1, true)[1] - M.confirm(text) + confirm(text) end M.close = function() - M.confirm() + confirm() end M.highlight = function() @@ -88,11 +88,7 @@ M.completefunc = function(findstart, base) return findstart == 1 and 0 or {} end if findstart == 1 then - if global_config.input.prompt_buffer then - return vim.api.nvim_strwidth(context.opts.prompt) - else - return 0 - end + return 0 else local completion = context.opts.completion local pieces = split(completion, ",") @@ -140,12 +136,7 @@ setmetatable(M, { -- Create or update the window local prompt = opts.prompt or config.default_prompt - local width - if config.prompt_buffer then - width = util.calculate_width(config.prefer_width + vim.api.nvim_strwidth(prompt), config) - else - width = util.calculate_width(config.prefer_width, config) - end + local width = util.calculate_width(config.prefer_width, config) local winopt = { relative = config.relative, anchor = config.anchor, @@ -187,27 +178,17 @@ setmetatable(M, { vim.api.nvim_buf_set_keymap(bufnr, "i", "", close_rhs, keyopts) end - if config.prompt_buffer then - vim.api.nvim_buf_set_option(bufnr, "buftype", "prompt") - vim.fn.prompt_setprompt(bufnr, prompt) - -- Would prefer to use v:lua directly here, but it doesn't work :( - vim.fn.prompt_setcallback(bufnr, "dressing#prompt_confirm") - vim.fn.prompt_setinterrupt(bufnr, "dressing#prompt_cancel") - else - local confirm_rhs = "lua require('dressing.input').confirm_non_prompt()" - -- If we're not using the prompt buffer, we need to put the prompt into a - -- separate title window that will appear in the input window border - vim.api.nvim_buf_set_keymap(bufnr, "i", "", close_rhs, keyopts) - vim.api.nvim_buf_set_keymap(bufnr, "i", "", confirm_rhs, keyopts) - vim.api.nvim_buf_set_keymap(bufnr, "n", "", confirm_rhs, keyopts) - vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { opts.default or "" }) - -- Disable nvim-cmp if installed - local ok, cmp = pcall(require, "cmp") - if ok then - cmp.setup.buffer({ enabled = false }) - end - util.add_title_to_win(winid, string.gsub(prompt, "^%s*(.-)%s*$", "%1"), { align = "left" }) + local confirm_rhs = "lua require('dressing.input').confirm()" + vim.api.nvim_buf_set_keymap(bufnr, "i", "", close_rhs, keyopts) + vim.api.nvim_buf_set_keymap(bufnr, "i", "", confirm_rhs, keyopts) + vim.api.nvim_buf_set_keymap(bufnr, "n", "", confirm_rhs, keyopts) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, { opts.default or "" }) + -- Disable nvim-cmp if installed + local ok, cmp = pcall(require, "cmp") + if ok then + cmp.setup.buffer({ enabled = false }) end + util.add_title_to_win(winid, string.gsub(prompt, "^%s*(.-)%s*$", "%1"), { align = "left" }) vim.cmd([[ aug DressingHighlight @@ -237,10 +218,6 @@ setmetatable(M, { ]]) vim.cmd("startinsert!") - if opts.default and config.prompt_buffer then - vim.api.nvim_feedkeys(opts.default, "n", false) - end - close_completion_window() M.highlight() end, diff --git a/tests/input_spec.lua b/tests/input_spec.lua index 4b87910..c5e4af3 100644 --- a/tests/input_spec.lua +++ b/tests/input_spec.lua @@ -17,133 +17,121 @@ local function run_input(keys, opts) return rx() end -for _, prompt_buffer in ipairs({ true, false }) do - a.describe( - string.format("input (%s)", prompt_buffer and "prompt buffer" or "normal floatwin"), - function() - before_each(function() - dressing.patch() - dressing.setup({ - input = { - prompt_buffer = prompt_buffer, - }, - }) - end) +a.describe("input modal", function() + before_each(function() + dressing.patch() + dressing.setup() + end) - after_each(function() - -- Clean up all floating windows so one test failure doesn't cascade - for _, winid in ipairs(vim.api.nvim_list_wins()) do - if vim.api.nvim_win_get_config(winid).relative ~= "" then - vim.api.nvim_win_close(winid, true) - end - end - end) + after_each(function() + -- Clean up all floating windows so one test failure doesn't cascade + for _, winid in ipairs(vim.api.nvim_list_wins()) do + if vim.api.nvim_win_get_config(winid).relative ~= "" then + vim.api.nvim_win_close(winid, true) + end + end + end) - a.it("accepts input", function() - local ret = run_input({ - "my text", - "", - }) - assert(ret == "my text", string.format("Got '%s' expected 'my text'", ret)) - end) + a.it("accepts input", function() + local ret = run_input({ + "my text", + "", + }) + assert(ret == "my text", string.format("Got '%s' expected 'my text'", ret)) + end) - a.it("Cancels input on ", function() - local ret = run_input({ - "my text", - "", - }) - assert(ret == nil, string.format("Got '%s' expected nil", ret)) - end) + a.it("Cancels input on ", function() + local ret = run_input({ + "my text", + "", + }) + assert(ret == nil, string.format("Got '%s' expected nil", ret)) + end) - a.it("cancels input when leaving the window", function() - local ret = run_input({ - "my text", - }, { - after_fn = function() - vim.cmd([[wincmd p]]) - end, - }) - assert(ret == nil, string.format("Got '%s' expected nil", ret)) - end) + a.it("cancels input when leaving the window", function() + local ret = run_input({ + "my text", + }, { + after_fn = function() + vim.cmd([[wincmd p]]) + end, + }) + assert(ret == nil, string.format("Got '%s' expected nil", ret)) + end) - a.it("cancels on when insert_only = true", function() - require("dressing.config").input.insert_only = true - local ret = run_input({ - "my text", - "", - }) - assert(ret == nil, string.format("Got '%s' expected nil", ret)) - end) + a.it("cancels on when insert_only = true", function() + require("dressing.config").input.insert_only = true + local ret = run_input({ + "my text", + "", + }) + assert(ret == nil, string.format("Got '%s' expected nil", ret)) + end) - a.it("does not cancel on when insert_only = false", function() - require("dressing.config").input.insert_only = false - local ret = run_input({ - "my text", - "", - "", - }) - assert(ret == "my text", string.format("Got '%s' expected 'my text'", ret)) - end) + a.it("does not cancel on when insert_only = false", function() + require("dressing.config").input.insert_only = false + local ret = run_input({ + "my text", + "", + "", + }) + assert(ret == "my text", string.format("Got '%s' expected 'my text'", ret)) + end) - a.it("cancels first callback if second input is opened", function() - local tx, rx = channel.oneshot() - vim.ui.input({}, tx) - util.feedkeys({ - "i", -- HACK have to do this because :startinsert doesn't work in tests, - "my text", - }) - vim.ui.input({}, function() end) - local ret = rx() - assert(ret == nil, string.format("Got '%s' expected nil", ret)) - end) + a.it("cancels first callback if second input is opened", function() + local tx, rx = channel.oneshot() + vim.ui.input({}, tx) + util.feedkeys({ + "i", -- HACK have to do this because :startinsert doesn't work in tests, + "my text", + }) + vim.ui.input({}, function() end) + local ret = rx() + assert(ret == nil, string.format("Got '%s' expected nil", ret)) + end) - -- TODO can't get this working in the prompt buffer test - if not prompt_buffer then - a.it("supports completion", function() - vim.opt.completeopt = { "menu", "menuone", "noselect" } - vim.cmd([[ + a.it("supports completion", function() + vim.opt.completeopt = { "menu", "menuone", "noselect" } + vim.cmd([[ function! CustomComplete(arglead, cmdline, cursorpos) return "first\nsecond\nthird" endfunction ]]) - local ret = run_input({ - "", -- Using tab twice to test both versions of the mapping - }, { - completion = "custom,CustomComplete", - }) - assert(ret == "second", string.format("Got '%s' expected 'second'", ret)) - assert(vim.fn.pumvisible() == 0, "Popup menu should not be visible after leaving modal") - end) + local ret = run_input({ + "", -- Using tab twice to test both versions of the mapping + }, { + completion = "custom,CustomComplete", + }) + assert(ret == "second", string.format("Got '%s' expected 'second'", ret)) + assert(vim.fn.pumvisible() == 0, "Popup menu should not be visible after leaving modal") + end) - a.it("can cancel out when popup menu is open", function() - vim.opt.completeopt = { "menu", "menuone", "noselect" } - local ret = run_input({ - "", - "", - }, { - completion = "command", - }) - assert(ret == nil, string.format("Got '%s' expected nil", ret)) - assert(vim.fn.pumvisible() == 0, "Popup menu should not be visible after leaving modal") - end) + a.it("can cancel out when popup menu is open", function() + vim.opt.completeopt = { "menu", "menuone", "noselect" } + local ret = run_input({ + "", + "", + }, { + completion = "command", + }) + assert(ret == nil, string.format("Got '%s' expected nil", ret)) + assert(vim.fn.pumvisible() == 0, "Popup menu should not be visible after leaving modal") + end) - a.it("doesn't delete text in original buffer", function() - -- This is a regression test for weird behavior I was seeing with the - -- completion popup menu - vim.api.nvim_buf_set_lines(0, 0, 1, true, { "some text" }) - vim.api.nvim_win_set_cursor(0, { 1, 4 }) - vim.opt.completeopt = { "menu", "menuone", "noselect" } - local ret = run_input({ - "", - "", - }, { - completion = "command", - }) - assert(ret == nil, string.format("Got '%s' expected nil", ret)) - local line = vim.api.nvim_buf_get_lines(0, 0, 1, true)[1] - assert(line == "some text", "Doing with popup menu open deleted buffer text o.0") - end) - end - end - ) -end + a.it("doesn't delete text in original buffer", function() + -- This is a regression test for weird behavior I was seeing with the + -- completion popup menu + vim.api.nvim_buf_set_lines(0, 0, 1, true, { "some text" }) + vim.api.nvim_win_set_cursor(0, { 1, 4 }) + vim.opt.completeopt = { "menu", "menuone", "noselect" } + local ret = run_input({ + "", + "", + }, { + completion = "command", + }) + assert(ret == nil, string.format("Got '%s' expected nil", ret)) + local line = vim.api.nvim_buf_get_lines(0, 0, 1, true)[1] + assert(line == "some text", "Doing with popup menu open deleted buffer text o.0") + end) +end)