package main import ( "fmt" "log" "os" "path/filepath" "strings" "github.com/charmbracelet/bubbles/progress" "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) type model struct { packages []string index int width int height int spinner spinner.Model progress progress.Model done bool sudoPassword string os OS } func (m model) installSpecialSoftware() error { if _, err := execLookPath("oh-my-posh"); err == nil { fmt.Println("Oh-my-posh ist bereits installiert") } else { poshCommand := "curl -s https://ohmyposh.dev/install.sh | bash -s" if err := installPackage(poshCommand, "", ""); err != nil { return err } } homeDir, err := os.UserHomeDir() if err != nil { return fmt.Errorf("Fehler beim Ermitteln des Home-Verzeichnisses: %v", err) } ohMyZshDir := filepath.Join(homeDir, ".oh-my-zsh") if _, err := os.Stat(ohMyZshDir); !os.IsNotExist(err) { fmt.Println("Oh My Zsh ist bereits installiert.") return nil } fmt.Println("Installiere Oh My Zsh...") err = executeShellCommand(`sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"`, "") if err != nil { log.Printf("Fehler bei der Installation von Oh My Zsh: %v\n", err) } plugins := []string{ "git clone https://github.com/zsh-users/zsh-autosuggestions.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions", "git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting", "git clone https://github.com/zdharma-continuum/fast-syntax-highlighting.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/fast-syntax-highlighting", "git clone --depth 1 -- https://github.com/marlonrichert/zsh-autocomplete.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autocomplete", } for _, plugin := range plugins { err := executeShellCommand(plugin, "") if err != nil { log.Printf("Fehler bei der Installation des Plugins: %v\n", err) } } fmt.Println("Oh My Zsh wurde erfolgreich installiert.") return nil } func newModel(packages []string, sudoPassword string, os *OS) model { p := progress.New( progress.WithDefaultGradient(), progress.WithWidth(40), progress.WithoutPercentage(), ) s := spinner.New() s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("63")) return model{ packages: packages, spinner: s, progress: p, sudoPassword: sudoPassword, os: *os, } } func (m model) Init() tea.Cmd { return tea.Batch(m.installPackageCmd(m.packages[m.index]), m.spinner.Tick) } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.width, m.height = msg.Width, msg.Height case tea.KeyMsg: switch msg.String() { case "ctrl+c", "esc", "q": return m, tea.Quit } case installedPkgMsg: pkg := m.packages[m.index] if m.index >= len(m.packages)-1 { m.done = true return m, tea.Sequence( tea.Printf("%s %s", checkMark, pkg), tea.Quit, ) } m.index++ progressCmd := m.progress.SetPercent(float64(m.index) / float64(len(m.packages))) return m, tea.Batch( progressCmd, tea.Printf("%s %s", checkMark, pkg), m.installPackageCmd(m.packages[m.index]), ) case spinner.TickMsg: var cmd tea.Cmd m.spinner, cmd = m.spinner.Update(msg) return m, cmd case progress.FrameMsg: newModel, cmd := m.progress.Update(msg) if newModel, ok := newModel.(progress.Model); ok { m.progress = newModel } return m, cmd } return m, nil } func (m model) View() string { n := len(m.packages) w := lipgloss.Width(fmt.Sprintf("%d", n)) if m.done { return doneStyle.Render(fmt.Sprintf("Done! Installed %d packages.\n", n)) } pkgCount := fmt.Sprintf(" %*d/%*d", w, m.index, w, n) spin := m.spinner.View() + " " prog := m.progress.View() cellsAvail := max(0, m.width-lipgloss.Width(spin+prog+pkgCount)) pkgName := currentPkgNameStyle.Render(m.packages[m.index]) info := lipgloss.NewStyle().MaxWidth(cellsAvail).Render("Installing " + pkgName) cellsRemaining := max(0, m.width-lipgloss.Width(spin+info+prog+pkgCount)) gap := strings.Repeat(" ", cellsRemaining) return spin + info + gap + prog + pkgCount } func (m model) installPackageCmd(pkg string) tea.Cmd { return func() tea.Msg { if err := installPackage(m.os.InstallCommand, pkg, m.sudoPassword); err != nil { log.Printf("Fehler beim Installieren von %s: %v", pkg, err) } return installedPkgMsg(pkg) } }