--- Personal lua config files for NeoVim. -- Last Changed: 2019-01-27 -- Author: Federico Igne -- License: This file is placed in the public domain. --- Poor man's popup terminal -- -- At the moment only one popup terminal is allowed at any time (do I -- really need more?), and the same buffer is reused if it exists. This -- should not interfere with normal terminal buffers. local terminal = {} local api = vim.api --- Compute size of popup window -- -- The window will be 3/4 and 2/3 of the total width and height -- respectively, with a minimum size of 80x24. Alternatively the -- terminal will take up the whole window. local function get_size(opts, cols, rows) local w = math.min(cols, math.max(80, math.floor(3*cols/4))) local h = math.min(rows, math.max(24, math.floor(2*rows/3))) opts['col'] = math.floor((cols - w) / 2) opts['row'] = math.floor((rows - h) / 2) opts['width'] = w opts['height'] = h end --- Open a popup window with a terminal buffer in it. -- -- If the terminal buffer exists already, it is used instead of creating -- a new one. If the buffer exists but there is no terminal attached, a -- new terminal instance is created. -- -- @param opts a dictionary containing the following fields: -- cmd: command executed in the terminal (`:h jobstart()`) -- job: options passed to the job creation function (`:h jobstart()`) -- win: options passed to the window creation function (`:h nvim_open_win()`) local function open(opts) -- Get buffer or create a new one local buf = vim.g.termbuf if not buf or not api.nvim_buf_is_loaded(buf) then buf = api.nvim_create_buf(false, true) end -- Setup new window opts.win.relative = 'editor' -- global window get_size(opts.win, vim.o.columns, vim.o.lines) local win = api.nvim_open_win(buf, true, opts.win) api.nvim_win_set_option(win, 'winhighlight', 'Normal:Normal') --api.nvim_win_set_option(win, 'winblend', 20) api.nvim_win_set_var(win, 'is_popup_term', 1) -- Start a new terminal instance, if necessary -- N.B. `termopen()` won't succede if a proper buffer is shown. local ok,_ = pcall(vim.fn.termopen, opts.cmd, opts.job) if ok then vim.g.termbuf = buf end end --- Close the current window. -- -- Here we are assuming that we are focusing a terminal popup window. -- -- @see terminal.toggle() local function close() api.nvim_win_close(0, false) end --- Toggle popup terminal window. -- -- @param opts a dictionary containing the following fields: -- cmd: command executed in the terminal (`:h jobstart()`) -- job: options passed to the job creation function (`:h jobstart()`) -- win: options passed to the window creation function (`:h nvim_open_win()`) function terminal.toggle(opts) local opts = vim.tbl_extend("keep", opts, { cmd = vim.env.SHELL, job = vim.empty_dict(), win = {} }) if pcall(api.nvim_win_get_var, 0, "is_popup_term") then close() else open(opts) end end return terminal