mirror of
https://github.com/chenasraf/tx.git
synced 2026-05-18 01:29:08 +00:00
158 lines
4.4 KiB
Go
158 lines
4.4 KiB
Go
package tmux
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
|
|
"github.com/chenasraf/tx/internal/config"
|
|
"github.com/chenasraf/tx/internal/exec"
|
|
)
|
|
|
|
// CreateFromConfig creates a tmux session from a parsed config.
|
|
// If background is true, the session is created but not attached to.
|
|
func CreateFromConfig(opts exec.Opts, tmuxConfig config.ParsedTmuxConfigItem, background bool) error {
|
|
root := tmuxConfig.Root
|
|
windows := tmuxConfig.Windows
|
|
sessionName := config.NameFix(tmuxConfig.Name)
|
|
|
|
exec.Log(opts, "Config:", tmuxConfig)
|
|
exec.Log(opts, "Session name:", sessionName)
|
|
|
|
// Check if session already exists
|
|
if SessionExists(opts, sessionName) {
|
|
if background {
|
|
exec.Log(opts, fmt.Sprintf("tmux session %s already exists (background mode, not attaching)", sessionName))
|
|
return nil
|
|
}
|
|
exec.Log(opts, fmt.Sprintf("tmux session %s already exists, attaching...", sessionName))
|
|
return AttachToSession(opts, sessionName)
|
|
}
|
|
|
|
exec.Log(opts, fmt.Sprintf("tmux session %s does not exist, creating...", sessionName))
|
|
|
|
var commands []string
|
|
|
|
// Create the session
|
|
commands = append(commands, fmt.Sprintf(
|
|
"tmux -f ~/.config/tmux/conf.tmux new-session -d -s %s -n general -c %s; sleep 1",
|
|
sessionName, root,
|
|
))
|
|
|
|
// Create all windows
|
|
for i, window := range windows {
|
|
dir := window.Cwd
|
|
windowName := window.Name
|
|
if windowName == "" {
|
|
windowName = config.NameFix(filepath.Base(dir))
|
|
}
|
|
|
|
exec.Log(opts, "Creating window:", windowName)
|
|
|
|
// Create the window
|
|
commands = append(commands, fmt.Sprintf(
|
|
"tmux new-window -t %s:%d -n %s -c %s",
|
|
sessionName, i+1, windowName, dir,
|
|
))
|
|
|
|
// Get pane commands - paneIndex starts at 0 for the window's initial pane
|
|
paneIndex := 0
|
|
paneCommands, timePanes := getPaneCommands(opts, window.Layout, sessionName, windowName, root, &paneIndex)
|
|
commands = append(commands, paneCommands...)
|
|
|
|
// Execute clock-mode for panes that have Time: true
|
|
for _, paneIdx := range timePanes {
|
|
commands = append(commands, fmt.Sprintf("tmux clock-mode -t %s:%s.%d", sessionName, windowName, paneIdx))
|
|
}
|
|
|
|
// Select first pane
|
|
commands = append(commands, fmt.Sprintf("tmux select-pane -t %s:%s.0", sessionName, windowName))
|
|
}
|
|
|
|
// Select initial window
|
|
commands = append(commands, fmt.Sprintf("tmux select-window -t %s:%d", sessionName, tmuxConfig.InitialWindow))
|
|
|
|
// Execute all commands
|
|
for _, command := range commands {
|
|
if err := exec.RunCommand(opts, command); err != nil {
|
|
return fmt.Errorf("failed to execute: %s: %w", command, err)
|
|
}
|
|
}
|
|
|
|
// Attach to the session unless background mode
|
|
if background {
|
|
return nil
|
|
}
|
|
return AttachToSession(opts, sessionName)
|
|
}
|
|
|
|
// getPaneCommands generates tmux commands for pane layout
|
|
// Returns the commands and a list of pane indices that should show time (clock-mode)
|
|
func getPaneCommands(opts exec.Opts, pane config.TmuxPaneLayout, sessionName, windowName, rootDir string, paneIndex *int) ([]string, []int) {
|
|
var commands []string
|
|
var timePanes []int
|
|
|
|
currentPane := *paneIndex
|
|
|
|
// Check if this pane should show time
|
|
if pane.Clock {
|
|
timePanes = append(timePanes, currentPane)
|
|
}
|
|
|
|
// Send command if specified
|
|
if pane.Cmd != "" {
|
|
cmd := TransformCmdToTmuxKeys(pane.Cmd)
|
|
if cmd != "" {
|
|
exec.Log(opts, "Sending keys:", cmd)
|
|
commands = append(commands, fmt.Sprintf(
|
|
"tmux send-keys -t %s:%s %s Enter",
|
|
sessionName, windowName, cmd,
|
|
))
|
|
}
|
|
}
|
|
|
|
// Handle splits
|
|
if pane.Split != nil {
|
|
direction := pane.Split.Direction
|
|
if direction == "" {
|
|
direction = "h"
|
|
}
|
|
|
|
cwd := pane.Cwd
|
|
if cwd == "" {
|
|
cwd = rootDir
|
|
}
|
|
|
|
exec.Log(opts, "Splitting pane:", pane.Split, "direction:", direction)
|
|
|
|
// Increment pane index for the new pane created by split
|
|
*paneIndex++
|
|
|
|
splitCmd := fmt.Sprintf(
|
|
"tmux split-window -%s -t %s:%s -c %s",
|
|
direction, sessionName, windowName, cwd,
|
|
)
|
|
if pane.Split.Size > 0 && pane.Split.Size <= 100 {
|
|
splitCmd += fmt.Sprintf(" -p %d", pane.Split.Size)
|
|
}
|
|
commands = append(commands, splitCmd)
|
|
|
|
// Handle child pane
|
|
if pane.Split.Child != nil {
|
|
exec.Log(opts, "Handling child pane:", pane.Split.Child)
|
|
childCommands, childTimePanes := getPaneCommands(opts, *pane.Split.Child, sessionName, windowName, rootDir, paneIndex)
|
|
commands = append(commands, childCommands...)
|
|
timePanes = append(timePanes, childTimePanes...)
|
|
}
|
|
|
|
// Handle zoom
|
|
if pane.Zoom {
|
|
commands = append(commands, fmt.Sprintf(
|
|
"tmux resize-pane -t %s:%s -Z",
|
|
sessionName, windowName,
|
|
))
|
|
}
|
|
}
|
|
|
|
return commands, timePanes
|
|
}
|