feat(terminal): minor improvements for user experience (#2276)

## Description
I was trying to create a simple `select` picker to choose terminals to
open.

With the current implementation only the fields `cmd` and `id` are
exposed. `cwd` and `env` are not which are used to get the terminal id
as well.

`M.list()` uses `vim.tbl_filter` which turns `terminals` into a list
removing the keys terminal ids. Even if that was not the case (i.e using
a normal `for` loop to add to `terminals`) the keys would be a string
due to `vim.inspect` and one would have to use patterns to extract
information from them.

It's easier to just add `cwd` and `env` to `vim.b[buf].snacks_terminal`
to have that information available and be easier for users to manipulate
which terminal they want to choose and open.

Also added `opts.count` as an option to be able to programmatically
choose the terminal with exactly the same options when it was created,
so one can just do
```lua
local term = vim.b[buf].snacks_terminal
Snacks.terminal(term.cmd, { cwd = term.cwd, env = term.env, count = term.id })
```
to programmatically invoke a certain terminal.
<!-- Describe the big picture of your changes to communicate to the
maintainers
  why we should accept this pull request. -->

## Related Issue(s)
Solves my issue and #2271 as well.
<!--
  If this PR fixes any issues, please link to the issue here.
  - Fixes #<issue_number>
-->

## Screenshots

<!-- Add screenshots of the changes if applicable. -->
This commit is contained in:
Iordanis Petkakis 2025-10-17 22:14:56 +03:00 committed by GitHub
parent 4edf207bfe
commit 39b14c4006
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -22,6 +22,7 @@ local defaults = {
---@class snacks.terminal.Opts: snacks.terminal.Config
---@field cwd? string
---@field count? integer
---@field env? table<string, string>
---@field start_insert? boolean start insert mode when starting the terminal
---@field auto_insert? boolean start insert mode when entering the terminal buffer
@ -82,8 +83,8 @@ end
---@param cmd? string | string[]
---@param opts? snacks.terminal.Opts
function M.open(cmd, opts)
local id = vim.v.count1
opts = Snacks.config.get("terminal", defaults --[[@as snacks.terminal.Opts]], opts)
local id = opts.count or vim.v.count1
opts.win = Snacks.win.resolve("terminal", {
position = cmd and "float" or "bottom",
}, opts.win, { show = false })
@ -104,7 +105,7 @@ function M.open(cmd, opts)
---@param self snacks.terminal
opts.win.on_buf = function(self)
self.cmd = cmd
vim.b[self.buf].snacks_terminal = { cmd = cmd, id = id }
vim.b[self.buf].snacks_terminal = { cmd = cmd, id = id, cwd = opts.cwd, env = opts.env }
if on_buf then
on_buf(self)
end
@ -171,7 +172,7 @@ end
---@return snacks.win? terminal, boolean? created
function M.get(cmd, opts)
opts = opts or {}
local id = vim.inspect({ cmd = cmd, cwd = opts.cwd, env = opts.env, count = vim.v.count1 })
local id = vim.inspect({ cmd = cmd, cwd = opts.cwd, env = opts.env, count = opts.count or vim.v.count1 })
local created = false
if not (terminals[id] and terminals[id]:buf_valid()) and (opts.create ~= false) then
local ret = M.open(cmd, opts)