feat: experimental support for screen under scr command

This commit is contained in:
raj 2023-10-22 18:13:55 +05:30
parent 5ffa3d96d7
commit d3d90ddb05
3 changed files with 151 additions and 0 deletions

107
controller/screen.go Normal file
View File

@ -0,0 +1,107 @@
package controller
import (
"fmt"
"os/exec"
"strings"
"github.com/charmbracelet/log"
projectconfig "github.com/xrehpicx/pee/config"
)
// RunShellCommand executes a shell command and logs it.
func RunShellCommand(cmd *exec.Cmd) error {
log.Debug("Running command:", "command", cmd.String())
output, err := cmd.CombinedOutput()
if err != nil {
log.Error("Error running command:", "command", cmd.String(), "error", err)
log.Info("Command output:", "output", string(output))
return err
}
return nil
}
// CreateScreenSession creates a new screen session based on the given Configuration.
func CreateScreenSession(config *projectconfig.Configuration) error {
sessionName := config.SessionName
// Check if the session already exists
checkSessionCmd := exec.Command("screen", "-S", sessionName, "-Q", "windows")
_, err := checkSessionCmd.CombinedOutput()
if err == nil {
// If it exists, attach to the session
attachSessionCmd := exec.Command("screen", "-d", "-r", sessionName)
RunShellCommand(attachSessionCmd)
} else {
// If it doesn't exist, create the session
createSessionCmd := exec.Command("screen", "-S", sessionName, "-d", "-m")
RunShellCommand(createSessionCmd)
// Create and run commands for windows
for i, window := range config.Windows {
windowName := fmt.Sprintf("%s-%d", sessionName, i+1)
// Create a new window within the session
createWindowCmd := exec.Command("screen", "-S", sessionName, "-X", "screen", "-t", windowName)
RunShellCommand(createWindowCmd)
// Change the working directory for the window
changeDirCmd := exec.Command("screen", "-S", sessionName, "-p", fmt.Sprint(i), "-X", "chdir", config.WorkingDir)
RunShellCommand(changeDirCmd)
// Send commands to the window
sendCommandsCmd := exec.Command("screen", "-S", sessionName, "-p", fmt.Sprint(i), "-X", "stuff", strings.Join(window.Panes[0].ShellCommand, " && ")+"\n")
RunShellCommand(sendCommandsCmd)
// Rename the window to the specified name
renameWindowCmd := exec.Command("screen", "-S", sessionName, "-p", fmt.Sprint(i), "-X", "title", window.WindowName)
RunShellCommand(renameWindowCmd)
// warn user of compatibility issues using more than one pane with screen
if len(window.Panes) > 1 {
log.Warn("Screen does not support multiple panes. Only the first pane will be used.")
}
// Create and run commands for additional panes in the window
for _, pane := range window.Panes[1:] {
// Split the window vertically
splitPaneCmd := exec.Command("screen", "-S", sessionName, "-p", fmt.Sprint(i), "-X", "split")
RunShellCommand(splitPaneCmd)
// Select the new pane
selectPaneCmd := exec.Command("screen", "-S", sessionName, "-p", fmt.Sprint(i+1)) // Select the next pane
RunShellCommand(selectPaneCmd)
// Send commands to the new pane
sendCommandsCmd := exec.Command("screen", "-S", sessionName, "-X", "stuff", strings.Join(pane.ShellCommand, " && ")+"\n")
RunShellCommand(sendCommandsCmd)
}
if window.Layout != "" {
layoutCmd := exec.Command("screen", "-S", sessionName, "-p", fmt.Sprint(i), "-X", "layout", window.Layout)
RunShellCommand(layoutCmd)
}
}
if config.Attach {
// Attach to the session
attachSessionCmd := exec.Command("screen", "-d", "-r", sessionName)
RunShellCommand(attachSessionCmd)
}
}
return nil
}
// KillScreenSession kills a screen session by name.
func KillScreenSession(sessionName string) error {
// Kill the screen session
killSessionCmd := exec.Command("screen", "-S", sessionName, "-X", "quit")
err := killSessionCmd.Run()
if err != nil {
log.Error("Error killing screen session:", "sessionName", sessionName, "error", err)
return err
}
log.Info("Killed screen session:", "sessionName", sessionName)
return nil
}

View File

@ -12,6 +12,7 @@ func init() {
projectconfig.Init()
projectmanager.RootCmd.AddCommand(projectmanager.ListProjects)
projectmanager.RootCmd.AddCommand(projectmanager.InitCmd)
projectmanager.RootCmd.AddCommand(projectmanager.ScreenCmd)
}
func main() {

43
project-manager/screen.go Normal file
View File

@ -0,0 +1,43 @@
package projectmanager
import (
"github.com/charmbracelet/log"
"github.com/spf13/cobra"
projectconfig "github.com/xrehpicx/pee/config"
"github.com/xrehpicx/pee/controller"
)
var KillScreenCmd = &cobra.Command{
Use: "kill",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
controller.KillScreenSession(args[0])
},
}
var ScreenCmd = &cobra.Command{
Use: "scr",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
ExecuteProjectEnvUsingScreen(args[0])
},
}
func ExecuteProjectEnvUsingScreen(projectName string) {
config, err := projectconfig.GetProjectConfig(projectName)
if err != nil {
log.Error(err)
return
}
err = controller.CreateScreenSession(config)
if err != nil {
log.Error(err)
return
}
projectconfig.UpdateLastOpened(projectName)
log.Debug("Created tmux session", "name", config.SessionName)
}
func init() {
ScreenCmd.AddCommand(KillScreenCmd)
}