github.com/japiotr123/go-tmux@v0.0.0-20231125144807-6c27c6cf74ba/session.go (about) 1 // The MIT License (MIT) 2 // Copyright (C) 2019-2023 Georgiy Komarov <jubnzv@gmail.com> 3 4 package tmux 5 6 import ( 7 "errors" 8 "fmt" 9 "regexp" 10 "strconv" 11 "strings" 12 ) 13 14 // Represents a tmux session: 15 // https://github.com/tmux/tmux/wiki/Getting-Started#sessions-windows-and-panes 16 type Session struct { 17 Id int // Session id 18 Name string // Session name 19 StartDirectory string // Path to window start directory 20 Windows []Window // List of windows used on session initialization 21 } 22 23 // Creates a new session object. 24 func NewSession(id int, name, startDirectory string, windows []Window) *Session { 25 return &Session{ 26 Id: id, 27 Name: name, 28 StartDirectory: startDirectory, 29 Windows: windows, 30 } 31 } 32 33 // Checks tmux rules for sessions naming. Reference: 34 // https://github.com/tmux/tmux/blob/5489796737108cb9bba01f831421e531a50b946b/session.c#L238 35 func checkSessionName(name string) bool { 36 if len(name) == 0 { 37 return false 38 } 39 if strings.Contains(name, ":") { 40 return false 41 } 42 if strings.Contains(name, ".") { 43 return false 44 } 45 return true 46 } 47 48 // Adds the window to the session configuration. This will change only 49 // in-library session representation. Used for initial configuration before 50 // creating a new session. 51 func (s *Session) AddWindow(window Window) { 52 s.Windows = append(s.Windows, window) 53 } 54 55 // Lists all windows in the current session. 56 func (s *Session) ListWindows() ([]Window, error) { 57 args := []string{ 58 "list-windows", 59 "-t", s.Name, 60 "-F", "#{window_id}:#{window_name}:#{pane_current_path}"} 61 62 out, _, err := RunCmd(args) 63 if err != nil { 64 return nil, err 65 } 66 67 outLines := strings.Split(out, "\n") 68 windows := []Window{} 69 re := regexp.MustCompile(`@([0-9]+):(.+):(.+)`) 70 for _, line := range outLines { 71 result := re.FindStringSubmatch(line) 72 if len(result) < 4 { 73 continue 74 } 75 id, err_atoi := strconv.Atoi(result[1]) 76 if err_atoi != nil { 77 return nil, err_atoi 78 } 79 80 windows = append(windows, Window{ 81 Name: result[2], 82 Id: id, 83 StartDirectory: result[3], 84 SessionName: s.Name, 85 SessionId: s.Id}) 86 } 87 88 return windows, nil 89 } 90 91 // Attach to existing tmux session. 92 func (s *Session) AttachSession() error { 93 args := []string{} 94 // If run inside tmux, switch the current session to the new one. 95 if !IsInsideTmux() { 96 args = append(args, "attach-session", "-t", s.Name) 97 } else { 98 args = append(args, "switch-client", "-t", s.Name) 99 } 100 101 if err := ExecCmd(args); err != nil { 102 return err 103 } 104 105 return nil 106 } 107 108 // Detaches from the current session. 109 // Detaching from the tmux session means that the client exits and detaches 110 // from the outside terminal. 111 // See: https://github.com/tmux/tmux/wiki/Getting-Started#attaching-and-detaching 112 func (s *Session) DettachSession() error { 113 args := []string{ 114 "detach-client", 115 "-s", s.Name} 116 if err := ExecCmd(args); err != nil { 117 return err 118 } 119 return nil 120 } 121 122 // Creates a new window inside this session. 123 func (s *Session) NewWindow(name string) (window Window, err error) { 124 args := []string{ 125 "new-window", 126 "-d", 127 "-t", fmt.Sprintf("%s:", s.Name), 128 "-n", name, 129 "-F", "#{window_id}:#{window_name}", "-P"} 130 out, _, err_exec := RunCmd(args) 131 if err_exec != nil { 132 return window, err_exec 133 } 134 135 re := regexp.MustCompile(`@([0-9]+):(.+)`) 136 result := re.FindStringSubmatch(out) 137 if len(result) < 3 { 138 return window, errors.New("Error creating new window") 139 } 140 id, err_atoi := strconv.Atoi(result[1]) 141 if err_atoi != nil { 142 return window, err_atoi 143 } 144 145 pane := Pane{ 146 SessionId: s.Id, 147 SessionName: s.Name, 148 WindowId: id, 149 WindowName: result[2], 150 WindowIndex: 0} 151 new_window := Window{ 152 Name: result[2], 153 Id: id, 154 SessionName: s.Name, 155 SessionId: s.Id, 156 Panes: []Pane{pane}} 157 return new_window, nil 158 } 159 160 // Returns list with all panes for this session. 161 func (s *Session) ListPanes() ([]Pane, error) { 162 return ListPanes([]string{"-s", "-t", s.Name}) 163 } 164 165 // Returns a name of the attached tmux session. 166 func GetAttachedSessionName() (string, error) { 167 args := []string{ 168 "display-message", 169 "-p", "#S"} 170 out, _, err := RunCmd(args) 171 if err != nil { 172 return "", err 173 } 174 175 // Remove trailing CR 176 out = out[:len(out)-1] 177 178 return out, nil 179 }