detached 440f5c2

feat(theme): integrate bleu-theme repository for CLI tools

Replace hardcoded color configs with git-cloned bleu-theme repo during
first boot. Applies consistent Bleu color palette to all CLI tools.

Changes:
- Clone https://github.com/bnema/bleu-theme.git to ~/.local/share/archup/themes/bleu
- Create "current" theme symlink pattern for future theme switching
- Apply themes to starship, eza, bat, fzf, btop, and yazi
- Update BAT_THEME from "TwoDark" to "Bleu"
- Source FZF Bleu theme in shell environment
- Remove hardcoded starship.toml template (now from bleu-theme)

Benefits:
- Single source of truth for all CLI tool themes
- Consistent color palette across shell environment
- Easy theme updates via git pull
- Foundation for theme switching in archup-cli
commit
440f5c2df22938ceeea35794a890a126ef4963b9
author
bnema · · 2025-10-29 04:44 UTC
parent
c28bbce
signature
GPG Unverified2B82207D370127A0 The key is unknown
2 files · +103 -7
M install/configs/shell/envs +6 -1
@@ -1,11 +1,16 @@
11 # Bat configuration
22 if command -v bat &> /dev/null; then
3- export BAT_THEME="TwoDark"
3+ export BAT_THEME="Bleu"
44 fi
55
66 # FZF configuration
77 # Note: Do NOT add --preview to FZF_DEFAULT_OPTS as it breaks non-file operations
88 if command -v fzf &> /dev/null; then
9+ # Source FZF Bleu theme if available
10+ if [ -f "$HOME/.local/share/archup/current/theme/fzf/bleu.sh" ]; then
11+ source "$HOME/.local/share/archup/current/theme/fzf/bleu.sh"
12+ fi
13+
914 # CTRL-T file/directory picker options
1015 if command -v bat &> /dev/null; then
1116 export FZF_CTRL_T_OPTS="--preview 'bat -n --color=always {}' --preview-window right:60%:wrap"
@@ -1,11 +1,16 @@
1 # Bat configuration1 # Bat configuration
2 if command -v bat &> /dev/null; then2 if command -v bat &> /dev/null; then
3- export BAT_THEME="TwoDark"3+ export BAT_THEME="Bleu"
4 fi4 fi
5 5
6 # FZF configuration6 # FZF configuration
7 # Note: Do NOT add --preview to FZF_DEFAULT_OPTS as it breaks non-file operations7 # Note: Do NOT add --preview to FZF_DEFAULT_OPTS as it breaks non-file operations
8 if command -v fzf &> /dev/null; then8 if command -v fzf &> /dev/null; then
9+ # Source FZF Bleu theme if available
10+ if [ -f "$HOME/.local/share/archup/current/theme/fzf/bleu.sh" ]; then
11+ source "$HOME/.local/share/archup/current/theme/fzf/bleu.sh"
12+ fi
13+
9 # CTRL-T file/directory picker options14 # CTRL-T file/directory picker options
10 if command -v bat &> /dev/null; then15 if command -v bat &> /dev/null; then
11 export FZF_CTRL_T_OPTS="--preview 'bat -n --color=always {}' --preview-window right:60%:wrap"16 export FZF_CTRL_T_OPTS="--preview 'bat -n --color=always {}' --preview-window right:60%:wrap"
M internal/phases/postinstall.go +97 -6
@@ -468,6 +468,37 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
468468 return fmt.Errorf("failed to set ownership: %w", err)
469469 }
470470
471+ // Clone bleu-theme repository
472+ p.SendOutput(progressChan, "Cloning bleu-theme repository...")
473+ themesDir := filepath.Join(userHome, ".local", "share", "archup", "themes")
474+ bleuThemeDir := filepath.Join(themesDir, "bleu")
475+ currentDir := filepath.Join(userHome, ".local", "share", "archup", "current")
476+
477+ cloneCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && git clone https://github.com/bnema/bleu-theme.git %s'",
478+ username, themesDir, bleuThemeDir)
479+ switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cloneCmd); {
480+ case err != nil:
481+ p.SendOutput(progressChan, "[WARN] Failed to clone bleu-theme repository")
482+ default:
483+ p.SendOutput(progressChan, "[OK] Bleu-theme repository cloned")
484+ }
485+
486+ // Create current theme symlink
487+ symlinkCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && ln -snf %s %s/theme'",
488+ username, currentDir, bleuThemeDir, currentDir)
489+ switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, symlinkCmd); {
490+ case err != nil:
491+ p.SendOutput(progressChan, "[WARN] Failed to create theme symlink")
492+ }
493+
494+ // Apply themes to CLI tools
495+ p.SendOutput(progressChan, "Applying themes to CLI tools...")
496+ switch err := p.applyThemes(progressChan, username, userHome); {
497+ case err != nil:
498+ // Non-fatal, log and continue
499+ p.SendOutput(progressChan, "[WARN] Some themes failed to apply")
500+ }
501+
471502 // Configure git delta
472503 gitCommands := []string{
473504 fmt.Sprintf("su - %s -c 'git config --global core.pager delta'", username),
@@ -495,12 +526,12 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
495526 // copyShellTemplates copies shell config templates to user directory
496527 func (p *PostInstallPhase) copyShellTemplates(archupDefault, archupDefaultBash string) error {
497528 templates := map[string]string{
498- config.ShellConfigTemplate: filepath.Join(archupDefaultBash, "shell"),
499- config.ShellInitTemplate: filepath.Join(archupDefaultBash, "init"),
500- config.ShellAliasesTemplate: filepath.Join(archupDefaultBash, "aliases"),
501- config.ShellEnvsTemplate: filepath.Join(archupDefaultBash, "envs"),
502- config.ShellRcTemplate: filepath.Join(archupDefaultBash, "rc"),
503- config.StarshipConfigTemplate: filepath.Join(archupDefault, "starship.toml"),
529+ config.ShellConfigTemplate: filepath.Join(archupDefaultBash, "shell"),
530+ config.ShellInitTemplate: filepath.Join(archupDefaultBash, "init"),
531+ config.ShellAliasesTemplate: filepath.Join(archupDefaultBash, "aliases"),
532+ config.ShellEnvsTemplate: filepath.Join(archupDefaultBash, "envs"),
533+ config.ShellRcTemplate: filepath.Join(archupDefaultBash, "rc"),
534+ // Note: starship.toml is now copied from bleu-theme in applyThemes()
504535 }
505536
506537 for template, dest := range templates {
@@ -535,6 +566,66 @@ func (p *PostInstallPhase) setShellOwnership(userHome, username string) error {
535566 return p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, chownCmd)
536567 }
537568
569+// applyThemes applies bleu-theme to CLI tools
570+func (p *PostInstallPhase) applyThemes(progressChan chan<- ProgressUpdate, username, userHome string) error {
571+ themeDir := filepath.Join(userHome, ".local", "share", "archup", "current", "theme")
572+ archupDefault := filepath.Join(userHome, ".local", "share", "archup", "default")
573+
574+ // Starship theme - copy to archup default location
575+ p.SendOutput(progressChan, "Configuring starship theme...")
576+ starshipCmd := fmt.Sprintf("su - %s -c 'cp %s/starship/bleu.toml %s/starship.toml'",
577+ username, themeDir, archupDefault)
578+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, starshipCmd)
579+
580+ // Eza theme
581+ p.SendOutput(progressChan, "Configuring eza theme...")
582+ ezaConfigDir := fmt.Sprintf("%s/.config/eza", userHome)
583+ ezaCommands := []string{
584+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, ezaConfigDir),
585+ fmt.Sprintf("su - %s -c 'cp %s/eza/theme.yml %s/'", username, themeDir, ezaConfigDir),
586+ }
587+ for _, cmd := range ezaCommands {
588+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
589+ }
590+
591+ // Bat theme
592+ p.SendOutput(progressChan, "Configuring bat theme...")
593+ batThemeDir := fmt.Sprintf("%s/.config/bat/themes", userHome)
594+ batCommands := []string{
595+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, batThemeDir),
596+ fmt.Sprintf("su - %s -c 'cp %s/bat/bleu.tmTheme %s/'", username, themeDir, batThemeDir),
597+ fmt.Sprintf("su - %s -c 'bat cache --build'", username),
598+ }
599+ for _, cmd := range batCommands {
600+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
601+ }
602+
603+ // Btop theme
604+ p.SendOutput(progressChan, "Configuring btop theme...")
605+ btopThemeDir := fmt.Sprintf("%s/.config/btop/themes", userHome)
606+ btopCommands := []string{
607+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, btopThemeDir),
608+ fmt.Sprintf("su - %s -c 'cp %s/btop/bleu.theme %s/'", username, themeDir, btopThemeDir),
609+ }
610+ for _, cmd := range btopCommands {
611+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
612+ }
613+
614+ // Yazi theme
615+ p.SendOutput(progressChan, "Configuring yazi theme...")
616+ yaziFlavorDir := fmt.Sprintf("%s/.config/yazi/flavors/bleu", userHome)
617+ yaziCommands := []string{
618+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, yaziFlavorDir),
619+ fmt.Sprintf("su - %s -c 'cp %s/yazi/bleu.toml %s/flavor.toml'", username, themeDir, yaziFlavorDir),
620+ }
621+ for _, cmd := range yaziCommands {
622+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
623+ }
624+
625+ p.SendOutput(progressChan, "[OK] CLI themes configured")
626+ return nil
627+}
628+
538629 // verifyInstallation performs comprehensive verification
539630 func (p *PostInstallPhase) verifyInstallation(progressChan chan<- ProgressUpdate) error {
540631 p.SendOutput(progressChan, "Verifying installation components...")
@@ -468,6 +468,37 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
468 return fmt.Errorf("failed to set ownership: %w", err)468 return fmt.Errorf("failed to set ownership: %w", err)
469 }469 }
470 470
471+ // Clone bleu-theme repository
472+ p.SendOutput(progressChan, "Cloning bleu-theme repository...")
473+ themesDir := filepath.Join(userHome, ".local", "share", "archup", "themes")
474+ bleuThemeDir := filepath.Join(themesDir, "bleu")
475+ currentDir := filepath.Join(userHome, ".local", "share", "archup", "current")
476+
477+ cloneCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && git clone https://github.com/bnema/bleu-theme.git %s'",
478+ username, themesDir, bleuThemeDir)
479+ switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cloneCmd); {
480+ case err != nil:
481+ p.SendOutput(progressChan, "[WARN] Failed to clone bleu-theme repository")
482+ default:
483+ p.SendOutput(progressChan, "[OK] Bleu-theme repository cloned")
484+ }
485+
486+ // Create current theme symlink
487+ symlinkCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && ln -snf %s %s/theme'",
488+ username, currentDir, bleuThemeDir, currentDir)
489+ switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, symlinkCmd); {
490+ case err != nil:
491+ p.SendOutput(progressChan, "[WARN] Failed to create theme symlink")
492+ }
493+
494+ // Apply themes to CLI tools
495+ p.SendOutput(progressChan, "Applying themes to CLI tools...")
496+ switch err := p.applyThemes(progressChan, username, userHome); {
497+ case err != nil:
498+ // Non-fatal, log and continue
499+ p.SendOutput(progressChan, "[WARN] Some themes failed to apply")
500+ }
501+
471 // Configure git delta502 // Configure git delta
472 gitCommands := []string{503 gitCommands := []string{
473 fmt.Sprintf("su - %s -c 'git config --global core.pager delta'", username),504 fmt.Sprintf("su - %s -c 'git config --global core.pager delta'", username),
@@ -495,12 +526,12 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
495 // copyShellTemplates copies shell config templates to user directory526 // copyShellTemplates copies shell config templates to user directory
496 func (p *PostInstallPhase) copyShellTemplates(archupDefault, archupDefaultBash string) error {527 func (p *PostInstallPhase) copyShellTemplates(archupDefault, archupDefaultBash string) error {
497 templates := map[string]string{528 templates := map[string]string{
498- config.ShellConfigTemplate: filepath.Join(archupDefaultBash, "shell"),529+ config.ShellConfigTemplate: filepath.Join(archupDefaultBash, "shell"),
499- config.ShellInitTemplate: filepath.Join(archupDefaultBash, "init"),530+ config.ShellInitTemplate: filepath.Join(archupDefaultBash, "init"),
500- config.ShellAliasesTemplate: filepath.Join(archupDefaultBash, "aliases"),531+ config.ShellAliasesTemplate: filepath.Join(archupDefaultBash, "aliases"),
501- config.ShellEnvsTemplate: filepath.Join(archupDefaultBash, "envs"),532+ config.ShellEnvsTemplate: filepath.Join(archupDefaultBash, "envs"),
502- config.ShellRcTemplate: filepath.Join(archupDefaultBash, "rc"),533+ config.ShellRcTemplate: filepath.Join(archupDefaultBash, "rc"),
503- config.StarshipConfigTemplate: filepath.Join(archupDefault, "starship.toml"),534+ // Note: starship.toml is now copied from bleu-theme in applyThemes()
504 }535 }
505 536
506 for template, dest := range templates {537 for template, dest := range templates {
@@ -535,6 +566,66 @@ func (p *PostInstallPhase) setShellOwnership(userHome, username string) error {
535 return p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, chownCmd)566 return p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, chownCmd)
536 }567 }
537 568
569+// applyThemes applies bleu-theme to CLI tools
570+func (p *PostInstallPhase) applyThemes(progressChan chan<- ProgressUpdate, username, userHome string) error {
571+ themeDir := filepath.Join(userHome, ".local", "share", "archup", "current", "theme")
572+ archupDefault := filepath.Join(userHome, ".local", "share", "archup", "default")
573+
574+ // Starship theme - copy to archup default location
575+ p.SendOutput(progressChan, "Configuring starship theme...")
576+ starshipCmd := fmt.Sprintf("su - %s -c 'cp %s/starship/bleu.toml %s/starship.toml'",
577+ username, themeDir, archupDefault)
578+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, starshipCmd)
579+
580+ // Eza theme
581+ p.SendOutput(progressChan, "Configuring eza theme...")
582+ ezaConfigDir := fmt.Sprintf("%s/.config/eza", userHome)
583+ ezaCommands := []string{
584+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, ezaConfigDir),
585+ fmt.Sprintf("su - %s -c 'cp %s/eza/theme.yml %s/'", username, themeDir, ezaConfigDir),
586+ }
587+ for _, cmd := range ezaCommands {
588+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
589+ }
590+
591+ // Bat theme
592+ p.SendOutput(progressChan, "Configuring bat theme...")
593+ batThemeDir := fmt.Sprintf("%s/.config/bat/themes", userHome)
594+ batCommands := []string{
595+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, batThemeDir),
596+ fmt.Sprintf("su - %s -c 'cp %s/bat/bleu.tmTheme %s/'", username, themeDir, batThemeDir),
597+ fmt.Sprintf("su - %s -c 'bat cache --build'", username),
598+ }
599+ for _, cmd := range batCommands {
600+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
601+ }
602+
603+ // Btop theme
604+ p.SendOutput(progressChan, "Configuring btop theme...")
605+ btopThemeDir := fmt.Sprintf("%s/.config/btop/themes", userHome)
606+ btopCommands := []string{
607+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, btopThemeDir),
608+ fmt.Sprintf("su - %s -c 'cp %s/btop/bleu.theme %s/'", username, themeDir, btopThemeDir),
609+ }
610+ for _, cmd := range btopCommands {
611+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
612+ }
613+
614+ // Yazi theme
615+ p.SendOutput(progressChan, "Configuring yazi theme...")
616+ yaziFlavorDir := fmt.Sprintf("%s/.config/yazi/flavors/bleu", userHome)
617+ yaziCommands := []string{
618+ fmt.Sprintf("su - %s -c 'mkdir -p %s'", username, yaziFlavorDir),
619+ fmt.Sprintf("su - %s -c 'cp %s/yazi/bleu.toml %s/flavor.toml'", username, themeDir, yaziFlavorDir),
620+ }
621+ for _, cmd := range yaziCommands {
622+ p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cmd)
623+ }
624+
625+ p.SendOutput(progressChan, "[OK] CLI themes configured")
626+ return nil
627+}
628+
538 // verifyInstallation performs comprehensive verification629 // verifyInstallation performs comprehensive verification
539 func (p *PostInstallPhase) verifyInstallation(progressChan chan<- ProgressUpdate) error {630 func (p *PostInstallPhase) verifyInstallation(progressChan chan<- ProgressUpdate) error {
540 p.SendOutput(progressChan, "Verifying installation components...")631 p.SendOutput(progressChan, "Verifying installation components...")

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 0

    ↑↓ moveenter openesc close