Skip to content

Commit e77c1c1

Browse files
committed
feat: Add create command
1 parent 129ba4e commit e77c1c1

File tree

5 files changed

+113
-9
lines changed

5 files changed

+113
-9
lines changed

cmd/sessionizer.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ func run(ctx context.Context, cmd *cli.Command) error {
4646
func runWithHandler(h handler.ISessionHandler, ctx context.Context, cmd *cli.Command) error {
4747
args := cmd.Args().Slice()
4848
if len(args) > 0 && args[0] == "list" {
49-
return h.GrabExistingSession()
49+
return h.GrabExistingSession(ctx)
50+
} else if len(args) > 0 && args[0] == "create" {
51+
return h.CreateNewProjectSession(ctx)
5052
} else if len(args) > 0 {
5153
return ErrNoSuchCmd
5254
} else {
53-
return h.NewSession()
55+
return h.NewSession(ctx)
5456
}
5557
}

cmd/sessionizer_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@ func newMockSessionHandler() handler.ISessionHandler {
2828
return &MockSessionHandler{}
2929
}
3030

31-
func (mh *MockSessionHandler) NewSession() error {
31+
func (mh *MockSessionHandler) NewSession(ctx context.Context) error {
3232
return nil
3333
}
3434

35-
func (mh *MockSessionHandler) GrabExistingSession() error {
35+
func (mh *MockSessionHandler) GrabExistingSession(ctx context.Context) error {
36+
return nil
37+
}
38+
39+
func (mh *MockSessionHandler) CreateNewProjectSession(ctx context.Context) error {
3640
return nil
3741
}
3842

go.mod

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@ module github.com/TlexCypher/my-tmux-sessionizer
33
go 1.24.0
44

55
require github.com/urfave/cli/v3 v3.0.0-beta1
6+
7+
require (
8+
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
9+
github.com/manifoldco/promptui v0.9.0 // indirect
10+
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b // indirect
11+
)

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
2+
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
3+
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
4+
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
15
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
26
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
8+
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
39
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
410
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
511
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
612
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
713
github.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg=
814
github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y=
15+
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b h1:MQE+LT/ABUuuvEZ+YQAMSXindAdUh7slEmAkup74op4=
16+
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
917
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1018
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

handler/handler.go

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@ package handler
33
import (
44
"bufio"
55
"bytes"
6+
"context"
67
"errors"
78
"fmt"
89
"io"
910
"os"
1011
"os/exec"
1112
"path/filepath"
1213
"strings"
14+
15+
"github.com/manifoldco/promptui"
1316
)
1417

18+
var configFiles = []string{"./.tmux-sessionizer", "~/.tmux-sessionizer"}
19+
1520
type ISessionHandler interface {
16-
NewSession() error
17-
GrabExistingSession() error
21+
NewSession(ctx context.Context) error
22+
GrabExistingSession(ctx context.Context) error
23+
CreateNewProjectSession(ctx context.Context) error
1824
}
1925

2026
type SessionHandler struct{}
@@ -47,7 +53,6 @@ func (sh *SessionHandler) newTmuxCmd(name string, args ...string) *exec.Cmd {
4753
}
4854

4955
func (sh *SessionHandler) readConfig() *config {
50-
configFiles := []string{"./.tmux-sessionizer", "~/.tmux-sessionizer"}
5156
for _, cf := range configFiles {
5257
config, err := sh.parseConfig(cf)
5358
if err == nil {
@@ -124,7 +129,7 @@ func (sh *SessionHandler) replaceHomeDir(fullpath string) (string, error) {
124129
return strings.Replace(fullpath, home, "~", 1), nil
125130
}
126131

127-
func (sh *SessionHandler) NewSession() error {
132+
func (sh *SessionHandler) NewSession(ctx context.Context) error {
128133
config := sh.readConfig()
129134
if config == nil {
130135
return errors.New("failed to create new project from projects")
@@ -209,7 +214,7 @@ func (sh *SessionHandler) toFzf(input bytes.Buffer) (bytes.Buffer, error) {
209214
return fzfOut, nil
210215
}
211216

212-
func (sh *SessionHandler) GrabExistingSession() error {
217+
func (sh *SessionHandler) GrabExistingSession(ctx context.Context) error {
213218
tmuxCmd := exec.Command("tmux", "list-sessions", "-F", "#{session_name}")
214219
var tmuxOut bytes.Buffer
215220
tmuxCmd.Stdout = &tmuxOut
@@ -230,6 +235,85 @@ func (sh *SessionHandler) GrabExistingSession() error {
230235
return nil
231236
}
232237

238+
func (sh *SessionHandler) CreateNewProjectSession(ctx context.Context) error {
239+
parentDirCandidatesSet := make(map[string]struct{}, 0)
240+
for _, configFile := range configFiles {
241+
path, err := sh.expandPath(configFile)
242+
if err != nil {
243+
return fmt.Errorf("failed to expand path: %w", err)
244+
}
245+
file, err := os.Open(path)
246+
if err != nil {
247+
return fmt.Errorf("failed to open config file: %w", err)
248+
}
249+
defer file.Close()
250+
251+
scanner := bufio.NewScanner(file)
252+
253+
for scanner.Scan() {
254+
line := scanner.Text()
255+
if strings.HasPrefix(line, "default=") {
256+
raw := strings.TrimPrefix(line, "default=")
257+
projects := strings.Split(raw, ",")
258+
for _, pr := range projects {
259+
trimmed := strings.TrimSpace(pr)
260+
parentDirCandidatesSet[trimmed] = struct{}{}
261+
}
262+
}
263+
}
264+
}
265+
266+
parentDirCandidates := make([]string, 0)
267+
for key, _ := range parentDirCandidatesSet {
268+
parentDirCandidates = append(parentDirCandidates, key)
269+
}
270+
271+
for {
272+
chooseParentDirPrompt := promptui.Select{
273+
Label: "Which project do you choose to create a new project (session) ?",
274+
Items: parentDirCandidates,
275+
}
276+
_, parentDir, err := chooseParentDirPrompt.Run()
277+
if err != nil {
278+
return fmt.Errorf("failed to choose a parent directory: %w", err)
279+
}
280+
281+
newProjectNamePrompt := promptui.Prompt{
282+
Label: "Enter a new project name",
283+
}
284+
newProjectName, err := newProjectNamePrompt.Run()
285+
if err != nil {
286+
return fmt.Errorf("failed to get a new project name: %w", err)
287+
}
288+
newProjectPath, err := sh.expandPath(filepath.Join(parentDir, fmt.Sprintf("%v/", newProjectName)))
289+
if err != nil {
290+
return fmt.Errorf("failed to expand path: %w", err)
291+
}
292+
_, err = os.Stat(newProjectPath)
293+
if err == nil {
294+
fmt.Printf("%v is already exist\n", newProjectPath)
295+
continue
296+
}
297+
if os.IsNotExist(err) {
298+
if err := exec.Command("mkdir", "-p", newProjectPath).Run(); err != nil {
299+
return fmt.Errorf("failed to create a new project: %w", err)
300+
}
301+
if sh.isInSession() {
302+
return sh.switchToNewClient(newProjectName, newProjectPath)
303+
}
304+
if err := sh.newTmuxCmd(
305+
"tmux", "new-session", "-s",
306+
newProjectName, "-c", newProjectPath).Run(); err != nil {
307+
return fmt.Errorf("failed to create new session %w: ", err)
308+
}
309+
break
310+
} else {
311+
return fmt.Errorf("failed to create a new project: %w", err)
312+
}
313+
}
314+
return nil
315+
}
316+
233317
func (sh *SessionHandler) isInSession() bool {
234318
return len(os.Getenv("TMUX")) > 0
235319
}

0 commit comments

Comments
 (0)