Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions lua/sidekick/cli/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ end
function M.toggle(opts)
opts = filter_opts(opts)
State.with(function(state, attached)
if not state.terminal then
return
end
if not attached then
if state.terminal and not attached then
state.terminal:toggle()
end
if state.terminal:is_open() and opts.focus ~= false then
state.terminal:focus()
if opts.focus == false then
return
end
if state.external or (state.terminal and state.terminal:is_open()) then
state.session:focus()
end
end, {
attach = true,
Expand All @@ -121,13 +121,10 @@ end
function M.focus(opts)
opts = filter_opts(opts)
State.with(function(state)
if not state.terminal then
return
end
if state.terminal:is_focused() then
state.terminal:blur()
if state.session:is_focused() then
state.session:blur()
else
state.terminal:focus()
state.session:focus()
end
end, {
attach = true,
Expand Down
12 changes: 12 additions & 0 deletions lua/sidekick/cli/session/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ function B:attach() end
--- Detach from an existing session
function B:detach() end

--- Focus the session
function B:focus() end

--- Whether the session currently has user focus
---@return boolean
function B:is_focused()
return false
end

--- Move focus away from the session
function B:blur() end

--- Start a new session
--- If the backend returns a Cmd, a new terminal session will be spawned
---@return sidekick.cli.terminal.Cmd?
Expand Down
43 changes: 43 additions & 0 deletions lua/sidekick/cli/session/tmux.lua
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,47 @@ function M:dump()
return ret
end

---Focus the tmux pane
function M:focus()
local pane_id = self:pane_id()
if not pane_id then
return
end
-- select-window first so create="window" switches the client to the pane's window;
-- no-op for create="split" where the pane is already in the current window.
Util.exec({ "tmux", "select-window", "-t", pane_id })
Util.exec({ "tmux", "select-pane", "-t", pane_id })
end

---Whether this tmux pane is the active pane of the calling client
---@return boolean
function M:is_focused()
local pane_id = self:pane_id()
if not pane_id then
return false
end
local lines = Util.exec({
"tmux",
"display-message",
"-p",
"-t",
pane_id,
"#{==:#{client_active_pane},#{pane_id}}",
}, { notify = false })
return lines ~= nil and lines[1] == "1"
end

---Send focus back to the editor pane (identified via $TMUX_PANE)
function M:blur()
if not self:is_focused() then
return
end
local editor_pane = vim.env.TMUX_PANE
if not editor_pane then
return
end
Util.exec({ "tmux", "select-window", "-t", editor_pane }, { notify = false })
Util.exec({ "tmux", "select-pane", "-t", editor_pane }, { notify = false })
end

return M
16 changes: 8 additions & 8 deletions lua/sidekick/cli/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,14 @@ function M.attach(state, opts)

state = M.get_state(session) -- update state
local terminal = state.terminal
if terminal then
if opts.show then
terminal:show()
if opts.focus ~= false and terminal:is_running() then
terminal:focus()
end
end
elseif attached then
if terminal and opts.show then
terminal:show()
end
local visible = state.external or (terminal and terminal:is_running())
if opts.show and opts.focus ~= false and visible then
session:focus()
end
if not terminal and attached then
Util.info("Attached to `" .. state.tool.name .. "`")
end
return state, attached
Expand Down