|
|
|
@ -12,22 +12,16 @@ import ( |
|
|
|
|
tea "github.com/charmbracelet/bubbletea" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Enum for the different launch types (browsers and CLI's)
|
|
|
|
|
const ( |
|
|
|
|
BrowserSessions int = iota |
|
|
|
|
Commands |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type commandChoice struct { |
|
|
|
|
displayString string |
|
|
|
|
command *exec.Cmd |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type Choices []commandChoice |
|
|
|
|
type choices []commandChoice |
|
|
|
|
|
|
|
|
|
type model struct { |
|
|
|
|
cursor int |
|
|
|
|
choices Choices |
|
|
|
|
choices choices |
|
|
|
|
selected map[int]struct{} |
|
|
|
|
status string |
|
|
|
|
} |
|
|
|
@ -37,8 +31,6 @@ type statusMsg string |
|
|
|
|
var selection map[int]struct{} |
|
|
|
|
|
|
|
|
|
func getBrowserSessions() []commandChoice { |
|
|
|
|
// 1. List files in $XDG_DATA_HOME/qutebrowser/sessions/ (N.B.:
|
|
|
|
|
// UserConfigDir() in os)
|
|
|
|
|
userConfigDir, err := os.UserConfigDir() |
|
|
|
|
if err != nil { |
|
|
|
|
log.Printf("Error finding user configuration directory: %v", err) |
|
|
|
@ -52,8 +44,6 @@ func getBrowserSessions() []commandChoice { |
|
|
|
|
log.Printf("Error reading browser sessions directory: %v", err) |
|
|
|
|
return []commandChoice{} |
|
|
|
|
} |
|
|
|
|
// 2. Exclude non-YAML files
|
|
|
|
|
// 3. Wrangle them into this struct array
|
|
|
|
|
result := make([]commandChoice, 0) |
|
|
|
|
for _, entry := range fileList { |
|
|
|
|
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".yml") { |
|
|
|
@ -64,7 +54,6 @@ func getBrowserSessions() []commandChoice { |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// log.Printf("result: %v", result)
|
|
|
|
|
return result |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -75,7 +64,7 @@ func initialModel() model { |
|
|
|
|
getBrowserSessions(), |
|
|
|
|
commandChoice{ |
|
|
|
|
displayString: "bottom", |
|
|
|
|
command: exec.Command("xterm", "-maximized", "-e", "btm", "--group", "--battery", "--color", "gruvbox-light"), |
|
|
|
|
command: exec.Command("xterm", "-maximized", "-e", "btm", "--battery", "--color", "gruvbox-light"), |
|
|
|
|
}, |
|
|
|
|
commandChoice{ |
|
|
|
|
displayString: "broot", |
|
|
|
@ -103,7 +92,7 @@ func launch(m model) tea.Cmd { |
|
|
|
|
var result statusMsg |
|
|
|
|
for q, item := range m.choices { |
|
|
|
|
if _, ok := m.selected[q]; ok { |
|
|
|
|
log.Printf("launching: %v\n", item.displayString) |
|
|
|
|
log.Printf("Launching: %v\n", item.displayString) |
|
|
|
|
result += statusMsg(fmt.Sprintf("Launching command: %v\n", item.displayString)) |
|
|
|
|
err := item.command.Start() |
|
|
|
|
if err != nil { |
|
|
|
@ -112,9 +101,7 @@ func launch(m model) tea.Cmd { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
time.Sleep(2000 * time.Millisecond) |
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -173,7 +160,6 @@ func (m model) View() string { |
|
|
|
|
} |
|
|
|
|
s += "\n\n" |
|
|
|
|
|
|
|
|
|
// s += fmt.Sprintf("\n%+v", m.selected) // debug
|
|
|
|
|
s += fmt.Sprintf("%s\n", m.status) |
|
|
|
|
s += "Press enter to launch.\n" |
|
|
|
|
s += "Press q to quit.\n" |
|
|
|
@ -182,13 +168,12 @@ func (m model) View() string { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func main() { |
|
|
|
|
// Logging example from the Bubbletea "simple" example. For some
|
|
|
|
|
// reason there's no file variable, and hence no file to `.Close()`.
|
|
|
|
|
logfilePath := os.Getenv("BUBBLETEA_LOG") |
|
|
|
|
if logfilePath != "" { |
|
|
|
|
if _, err := tea.LogToFile(logfilePath, "DEBUG"); err != nil { |
|
|
|
|
log.Fatal(err) |
|
|
|
|
} |
|
|
|
|
logfilePath := os.Getenv("BREAKFAST_LOG") |
|
|
|
|
if logfilePath == "" { |
|
|
|
|
logfilePath = fmt.Sprintf("/tmp/%s_breakfast.log", time.Now().Local().Format("20060102150405-0700")) |
|
|
|
|
} |
|
|
|
|
if _, err := tea.LogToFile(logfilePath, "DEBUG"); err != nil { |
|
|
|
|
log.Fatal(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p := tea.NewProgram(initialModel()) |
|
|
|
|