---@return vim.api.keyset.win_config local function get_winopts() local horiz = vim.opt.fillchars:get().horiz or "─" local height = math.ceil(vim.o.lines * 0.3) local offset = vim.o.cmdheight + 1 return { relative = "editor", col = 0, row = vim.o.lines - height - offset - 1, height = height, width = vim.o.columns, style = "minimal", border = { horiz, horiz, horiz, "", "", "", "", "" }, } end ---@class jamjar.Terminal.proto ---@field cmd? string ---@field cwd? string ---@field winoptsfn? fun(): vim.api.keyset.win_config ---@field on_open? fun(self: jamjar.Terminal) ---@class jamjar.Terminal : jamjar.Terminal.proto ---@field cmd string ---@field buf integer ---@field win? integer local Terminal = {} Terminal.__index = Terminal local function get_defaultopts() return { cmd = vim.o.shell, on_open = function(self) vim.api.nvim_set_option_value( "winhighlight", "Normal:Normal,NormalNC:NormalNC,FloatBorder:WinSeparator", { win = self.win } ) end, } end ---@param opts? jamjar.Terminal.proto function Terminal:new(opts) return setmetatable(vim.tbl_extend("force", get_defaultopts(), opts or {}), self) end function Terminal:init() self.buf = vim.api.nvim_create_buf(true, true) vim.api.nvim_set_option_value("buftype", "nofile", { buf = self.buf }) vim._with({ buf = self.buf }, function() vim.fn.jobstart(self.cmd, { term = true, cwd = self.cwd, on_exit = function() self:delete() end, }) end) end function Terminal:toggle() if not self.win then self:open() return end local wcfg = vim.api.nvim_win_get_config(self.win) local hidden = wcfg.hide if hidden then self:open() else self:close() end end function Terminal:open() if not self.win then if not self.buf then self:init() end self.win = vim.api.nvim_open_win(self.buf, true, self.winoptsfn and self.winoptsfn() or get_winopts()) vim.api.nvim_set_option_value("signcolumn", "no", { win = self.win }) vim.api.nvim_set_option_value("foldcolumn", "0", { win = self.win }) self.on_open(self) else vim.api.nvim_win_set_config(self.win, { hide = false, }) vim.api.nvim_set_current_win(self.win) end end function Terminal:close() if self.win then vim.api.nvim_win_set_config(self.win, { hide = true, }) if vim.api.nvim_get_current_win() == self.win then vim.cmd.wincmd("p") end end end function Terminal:quit() if self.win then vim.api.nvim_win_close(self.win, true) self.win = nil end end function Terminal:delete() self:quit() if self.buf and vim.api.nvim_buf_is_valid(self.buf) then vim.bo[self.buf].buflisted = false vim.api.nvim_buf_delete(self.buf, { unload = true }) self.buf = nil end end return Terminal