Skip to content

Commit f310f0d

Browse files
committed
feat(direct shell access)
1 parent 675070f commit f310f0d

1 file changed

Lines changed: 57 additions & 43 deletions

File tree

internal/ui/views/containers/containers.go

Lines changed: 57 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -325,58 +325,72 @@ func Describe(app common.AppController, v *view.ResourceView) {
325325
}
326326

327327
func Shell(app common.AppController, id string) {
328-
items := []dialogs.PickerItem{
329-
{Description: "bash", Label: "Bash", Value: "bash", Shortcut: '1'},
330-
{Description: "sh", Label: "Sh", Value: "sh", Shortcut: '2'},
331-
}
328+
// Stop any background refresh to prevent UI updates interfering with the shell
329+
app.StopAutoRefresh()
330+
331+
// Still set paused flag as double safety for any lingering goroutines
332+
app.SetPaused(true)
332333

333-
dialogs.ShowPicker(app, "Shell Picker", items, func(shell string) {
334-
// Stop any background refresh to prevent UI updates interfering with the shell
335-
app.StopAutoRefresh()
336-
337-
// Still set paused flag as double safety for any lingering goroutines
338-
app.SetPaused(true)
334+
defer func() {
335+
app.SetPaused(false)
336+
app.StartAutoRefresh()
337+
}()
339338

339+
app.GetTviewApp().Suspend(func() {
340340
defer func() {
341-
app.SetPaused(false)
342-
app.StartAutoRefresh()
341+
if r := recover(); r != nil {
342+
fmt.Printf("Shell panic: %v\n", r)
343+
}
343344
}()
344345

345-
app.GetTviewApp().Suspend(func() {
346-
defer func() {
347-
if r := recover(); r != nil {
348-
fmt.Printf("Shell panic: %v\n", r)
349-
}
350-
}()
346+
fmt.Print("\033[H\033[2J")
347+
fmt.Printf("Detecting shell for %s...\n", id)
351348

352-
fmt.Print("\033[H\033[2J")
353-
fmt.Printf("Entering shell %s for %s (type 'exit' or CTRL+D to return)...\n", shell, id)
354-
355-
// Use proper PTY handling or simple command depending on platform
356-
// For basic usage, standard io connection is usually enough but Suspend/Restore is tricky
357-
// We MUST ensure tview is fully suspended
358-
359-
cmd := exec.Command("docker", "exec", "-it", id, shell)
360-
cmd.Stdin = os.Stdin
361-
cmd.Stdout = os.Stdout
362-
cmd.Stderr = os.Stderr
363-
364-
if err := cmd.Run(); err != nil {
365-
// If it's a legitimate exit (like 127 or 130), we might not want to pause
366-
// But usually if docker exec fails we want to see why
367-
fmt.Printf("\nError executing shell: %v\nPress Enter to continue...", err)
368-
fmt.Scanln()
349+
shells := []string{"bash", "zsh", "ash", "sh"}
350+
var selectedShell string
351+
352+
for _, shell := range shells {
353+
// Check if shell exists
354+
checkCmd := exec.Command("docker", "exec", id, shell, "-c", "exit 0")
355+
if err := checkCmd.Run(); err == nil {
356+
selectedShell = shell
357+
break
369358
}
370-
371-
// Clear again to ensure clean return
372-
fmt.Print("\033[H\033[2J")
373-
})
374-
375-
// Fix race conditions/glitches where screen isn't fully restored
376-
if app.GetScreen() != nil {
377-
app.GetScreen().Sync()
378359
}
360+
361+
if selectedShell == "" {
362+
fmt.Printf("No supported shell found (tried: %v)\nPress Enter to continue...", shells)
363+
fmt.Scanln()
364+
return
365+
}
366+
367+
fmt.Print("\033[H\033[2J")
368+
fmt.Printf("Entering shell %s for %s (type 'exit' or CTRL+D to return)...\n", selectedShell, id)
369+
370+
// Use proper PTY handling or simple command depending on platform
371+
// For basic usage, standard io connection is usually enough but Suspend/Restore is tricky
372+
// We MUST ensure tview is fully suspended
373+
374+
cmd := exec.Command("docker", "exec", "-it", id, selectedShell)
375+
cmd.Stdin = os.Stdin
376+
cmd.Stdout = os.Stdout
377+
cmd.Stderr = os.Stderr
378+
379+
if err := cmd.Run(); err != nil {
380+
// If it's a legitimate exit (like 127 or 130), we might not want to pause
381+
// But usually if docker exec fails we want to see why
382+
fmt.Printf("\nError executing shell: %v\nPress Enter to continue...", err)
383+
fmt.Scanln()
384+
}
385+
386+
// Clear again to ensure clean return
387+
fmt.Print("\033[H\033[2J")
379388
})
389+
390+
// Fix race conditions/glitches where screen isn't fully restored
391+
if app.GetScreen() != nil {
392+
app.GetScreen().Sync()
393+
}
380394
}
381395

382396
func RestartOrStart(app common.AppController, v *view.ResourceView) {

0 commit comments

Comments
 (0)