package main import ( "fmt" "log" "os/exec" "runtime" "github.com/charmbracelet/bubbles/progress" "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) type specialSoftwareModel struct { items []string index int spinner spinner.Model progress progress.Model done bool sudoPassword string } func newSpecialSoftwareModel(sudoPassword string) specialSoftwareModel { items := []string{"oh-my-posh", "golang", "rust"} p := progress.New( progress.WithDefaultGradient(), progress.WithWidth(40), progress.WithoutPercentage(), ) s := spinner.New() s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("63")) return specialSoftwareModel{ items: items, spinner: s, progress: p, sudoPassword: sudoPassword, } } func (m specialSoftwareModel) Init() tea.Cmd { return tea.Batch(m.installItemCmd(m.items[m.index]), m.spinner.Tick) } func (m specialSoftwareModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "ctrl+c", "esc", "q": return m, tea.Quit } case installedItemMsg: if m.index >= len(m.items)-1 { m.done = true return m, tea.Quit } m.index++ progressCmd := m.progress.SetPercent(float64(m.index) / float64(len(m.items))) return m, tea.Batch( progressCmd, tea.Printf("%s %s", checkMark, m.items[m.index-1]), m.installItemCmd(m.items[m.index]), ) case spinner.TickMsg: var cmd tea.Cmd m.spinner, cmd = m.spinner.Update(msg) return m, cmd } return m, nil } func (m specialSoftwareModel) View() string { if m.done { return doneStyle.Render("Spezielle Software Installation abgeschlossen!\n") } spin := m.spinner.View() + " " prog := m.progress.View() info := fmt.Sprintf("Installiere %s", m.items[m.index]) return spin + info + " " + prog } func (m specialSoftwareModel) installItemCmd(item string) tea.Cmd { return func() tea.Msg { switch item { case "oh-my-posh": if _, err := exec.LookPath("oh-my-posh"); err == nil { return installedItemMsg(item) } err := executeShellCommand("curl -s https://ohmyposh.dev/install.sh | bash -s") if err != nil { log.Printf("Fehler bei der Installation von oh-my-posh: %v\n", err) } case "golang": if _, err := exec.LookPath("go"); err == nil { return installedItemMsg(item) } golangVersion := "1.23.4" if err := downloadGolang(golangVersion); err != nil { log.Printf("Fehler beim Herunterladen von Go: %v", err) } golangCommand := fmt.Sprintf("sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go%s.linux-%s.tar.gz", golangVersion, runtime.GOARCH) if err := installPackage(golangCommand, "", m.sudoPassword); err != nil { log.Printf("Fehler beim Installieren von Go: %v", err) } case "rust": if _, err := exec.LookPath("rustc"); err == nil { if _, err := exec.LookPath("cargo"); err == nil { return installedItemMsg(item) } } err := executeShellCommand("curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -q -y") if err != nil { log.Printf("Fehler bei der Installation von rustup: %v\n", err) } } return installedItemMsg(item) } } func executeShellCommand(command string) error { cmd := exec.Command("bash", "-c", command) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("befehl fehlgeschlagen: %v\nAusgabe: %s", err, output) } return nil }