1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
--- Personal lua config files for NeoVim.
-- Last Changed: 2019-01-27
-- Author: Federico Igne <git@federicoigne.com>
-- 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
|