Skip to content

Commit ae67258

Browse files
committed
Enhance MySystem CLI with Zsh configuration support and documentation
- Integrated configuration management for Zsh, including installation checks for Oh My Zsh and Powerlevel10k. - Updated TUI to conditionally display Zsh configuration options based on core installation status. - Added a new method to retrieve packages from multiple categories in the installer service. - Introduced a new HTML documentation file outlining MySystem features and installation instructions. - Refactored wizard service to assume core components are pre-installed, simplifying user selections. - Improved test coverage for Zsh wizard and model interactions.
1 parent b9a41fe commit ae67258

13 files changed

Lines changed: 755 additions & 123 deletions

File tree

cmd/mysystem/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
tea "github.com/charmbracelet/bubbletea"
88
"github.com/jaime/mysystem/internal/app/services"
9+
"github.com/jaime/mysystem/internal/infrastructure/config"
910
"github.com/jaime/mysystem/internal/infrastructure/executor"
1011
"github.com/jaime/mysystem/internal/infrastructure/installer"
1112
"github.com/jaime/mysystem/internal/infrastructure/repository"
@@ -26,9 +27,11 @@ func main() {
2627
// Application layer
2728
scriptService := services.NewScriptService(scriptRepo, scriptExecutor)
2829
installerService := services.NewInstallerService(packageRepo, packageInstaller)
30+
configManager := config.NewFileConfigManager("")
31+
configService := services.NewConfigService(configManager)
2932

3033
// Presentation layer
31-
model := tui.NewModel(scriptService, installerService)
34+
model := tui.NewModel(scriptService, installerService, configService)
3235

3336
// Create the TUI program
3437
p := tea.NewProgram(

docs/index.html

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<!DOCTYPE html>
2+
<html lang="pt-BR">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>MySystem — Gerenciador de Sistema</title>
7+
<meta name="description" content="CLI para manter, configurar e migrar seu Linux. Limpeza, instaladores e wizard Zsh com Go e Charm.">
8+
<link rel="preconnect" href="https://fonts.googleapis.com">
9+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Space+Grotesk:wght@400;600;700&display=swap" rel="stylesheet">
11+
<style>
12+
:root {
13+
/* Cores do design MySystem (TUI Lipgloss) */
14+
--mysystem-magenta: #ff5faf; /* 205 - títulos, cursor */
15+
--mysystem-gray: #626262; /* 241 - subtítulos, ajuda */
16+
--mysystem-green: #00c853; /* 10 - sucesso, seleção */
17+
--mysystem-accent: #5f5faf; /* 63 - bordas, destaque */
18+
--mysystem-cream: #ffffd7; /* 230 - texto em destaque */
19+
--mysystem-bg: #0d1117;
20+
--mysystem-bg-soft: #161b22;
21+
--mysystem-border: #30363d;
22+
}
23+
24+
* {
25+
box-sizing: border-box;
26+
}
27+
28+
body {
29+
margin: 0;
30+
min-height: 100vh;
31+
background: var(--mysystem-bg);
32+
color: #c9d1d9;
33+
font-family: 'Space Grotesk', system-ui, sans-serif;
34+
font-size: 1.05rem;
35+
line-height: 1.6;
36+
}
37+
38+
.wrap {
39+
max-width: 720px;
40+
margin: 0 auto;
41+
padding: 2rem 1.5rem 4rem;
42+
}
43+
44+
header {
45+
text-align: center;
46+
padding: 4rem 0 3rem;
47+
border-bottom: 1px solid var(--mysystem-border);
48+
}
49+
50+
h1 {
51+
font-size: 2.25rem;
52+
font-weight: 700;
53+
color: var(--mysystem-magenta);
54+
margin: 0 0 0.5rem;
55+
letter-spacing: -0.02em;
56+
}
57+
58+
.tagline {
59+
color: var(--mysystem-gray);
60+
font-size: 1.15rem;
61+
margin: 0;
62+
}
63+
64+
.badge {
65+
display: inline-block;
66+
margin-top: 1rem;
67+
padding: 0.35rem 0.75rem;
68+
background: var(--mysystem-bg-soft);
69+
border: 1px solid var(--mysystem-accent);
70+
border-radius: 6px;
71+
color: var(--mysystem-cream);
72+
font-family: 'JetBrains Mono', monospace;
73+
font-size: 0.85rem;
74+
}
75+
76+
section {
77+
padding: 2.5rem 0;
78+
}
79+
80+
section h2 {
81+
font-size: 1.35rem;
82+
font-weight: 600;
83+
color: var(--mysystem-magenta);
84+
margin: 0 0 1rem;
85+
}
86+
87+
section p {
88+
margin: 0 0 1rem;
89+
color: #8b949e;
90+
}
91+
92+
ul.features {
93+
list-style: none;
94+
padding: 0;
95+
margin: 0;
96+
}
97+
98+
ul.features li {
99+
padding: 0.5rem 0;
100+
padding-left: 1.5rem;
101+
position: relative;
102+
color: #8b949e;
103+
}
104+
105+
ul.features li::before {
106+
content: '';
107+
position: absolute;
108+
left: 0;
109+
top: 0.75rem;
110+
width: 6px;
111+
height: 6px;
112+
background: var(--mysystem-green);
113+
border-radius: 50%;
114+
}
115+
116+
ul.features strong {
117+
color: var(--mysystem-cream);
118+
}
119+
120+
pre, code {
121+
font-family: 'JetBrains Mono', monospace;
122+
font-size: 0.9rem;
123+
}
124+
125+
pre {
126+
background: var(--mysystem-bg-soft);
127+
border: 1px solid var(--mysystem-border);
128+
border-radius: 8px;
129+
padding: 1rem 1.25rem;
130+
overflow-x: auto;
131+
margin: 1rem 0;
132+
}
133+
134+
code {
135+
color: var(--mysystem-magenta);
136+
padding: 0.15em 0.4em;
137+
border-radius: 4px;
138+
background: var(--mysystem-bg-soft);
139+
}
140+
141+
pre code {
142+
padding: 0;
143+
background: none;
144+
color: #c9d1d9;
145+
}
146+
147+
a {
148+
color: var(--mysystem-accent);
149+
text-decoration: none;
150+
}
151+
152+
a:hover {
153+
text-decoration: underline;
154+
}
155+
156+
footer {
157+
margin-top: 3rem;
158+
padding-top: 2rem;
159+
border-top: 1px solid var(--mysystem-border);
160+
text-align: center;
161+
color: var(--mysystem-gray);
162+
font-size: 0.9rem;
163+
}
164+
165+
footer a {
166+
color: var(--mysystem-magenta);
167+
}
168+
</style>
169+
</head>
170+
<body>
171+
<div class="wrap">
172+
<header>
173+
<h1>MySystem</h1>
174+
<p class="tagline">Gerenciador de sistema em terminal — limpeza, instaladores e configuração Zsh</p>
175+
<span class="badge">Go · Bubbletea · Charm</span>
176+
</header>
177+
178+
<section>
179+
<h2>O que é</h2>
180+
<p>
181+
MySystem reúne scripts de limpeza, instaladores de ferramentas e o assistente de configuração Zsh
182+
numa única interface no terminal. Pensado para manter a máquina em ordem e configurar o shell
183+
em poucos passos.
184+
</p>
185+
</section>
186+
187+
<section>
188+
<h2>Funcionalidades</h2>
189+
<ul class="features">
190+
<li><strong>Limpeza</strong> — Scripts para caches (Docker, npm, apt) e detecção de arquivos grandes</li>
191+
<li><strong>Monitoramento</strong> — Bateria e uso de memória</li>
192+
<li><strong>Instaladores</strong> — IDEs (Cursor, Claude Code) e ferramentas a partir de uma lista curada</li>
193+
<li><strong>Wizard Zsh</strong> — Passo a passo: Zsh, Oh My Zsh, Powerlevel10k, plugins e ferramentas (NVM, Bun, etc.)</li>
194+
<li><strong>TUI</strong> — Interface no terminal com Bubbletea e Lipgloss</li>
195+
</ul>
196+
</section>
197+
198+
<section>
199+
<h2>Instalação</h2>
200+
<p>Requisitos: Go 1.21+ e Linux (Ubuntu/Debian recomendado).</p>
201+
<pre><code>git clone https://github.com/yourusername/mysystem
202+
cd mysystem
203+
make install</code></pre>
204+
<p>Ou execute direto: <code>make run</code></p>
205+
</section>
206+
207+
<section>
208+
<h2>Uso rápido</h2>
209+
<p>↑/↓ ou j/k navegar · Espaço marcar · Enter confirmar · n ou → próximo · Esc voltar · q ou Ctrl+C sair</p>
210+
</section>
211+
212+
<footer>
213+
<p>
214+
Código no <a href="https://github.com/yourusername/mysystem">GitHub</a> ·
215+
Documentação em <a href="README.md">docs/</a> ·
216+
MIT
217+
</p>
218+
</footer>
219+
</div>
220+
</body>
221+
</html>

integration_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/jaime/mysystem/internal/app/services"
77
"github.com/jaime/mysystem/internal/domain/types"
8+
"github.com/jaime/mysystem/internal/infrastructure/config"
89
"github.com/jaime/mysystem/internal/infrastructure/executor"
910
"github.com/jaime/mysystem/internal/infrastructure/installer"
1011
"github.com/jaime/mysystem/internal/infrastructure/repository"
@@ -23,6 +24,10 @@ func TestIntegration_ScriptsAndTUI(t *testing.T) {
2324
packageInstaller := installer.NewDefaultPackageInstaller()
2425
installerService := services.NewInstallerService(packageRepo, packageInstaller)
2526

27+
// Create dependencies - Config
28+
configManager := config.NewFileConfigManager("")
29+
configService := services.NewConfigService(configManager)
30+
2631
// Get all scripts
2732
allScripts, err := scriptService.GetAllScripts()
2833
if err != nil {
@@ -34,7 +39,7 @@ func TestIntegration_ScriptsAndTUI(t *testing.T) {
3439
}
3540

3641
// Create TUI model
37-
model := tui.NewModel(scriptService, installerService)
42+
model := tui.NewModel(scriptService, installerService, configService)
3843

3944
// Verify model initializes correctly
4045
if model.Init() == nil {

internal/app/services/installer_service.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ func (s *InstallerService) GetPackagesByCategory(category types.PackageCategory)
4343
return packages, nil
4444
}
4545

46+
// GetPackagesByCategories returns packages from multiple categories (combined, no duplicates by ID)
47+
func (s *InstallerService) GetPackagesByCategories(categories []types.PackageCategory) ([]entities.Package, error) {
48+
seen := make(map[string]bool)
49+
var result []entities.Package
50+
for _, cat := range categories {
51+
packages, err := s.repo.FindByCategory(cat)
52+
if err != nil {
53+
return nil, fmt.Errorf("get packages by category %s: %w", cat, err)
54+
}
55+
for _, pkg := range packages {
56+
if !seen[pkg.ID] {
57+
seen[pkg.ID] = true
58+
result = append(result, pkg)
59+
}
60+
}
61+
}
62+
return result, nil
63+
}
64+
4665
// GetPackageByID returns a package by ID
4766
func (s *InstallerService) GetPackageByID(id string) (*entities.Package, error) {
4867
pkg, err := s.repo.FindByID(id)

internal/app/services/wizard_service.go

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,10 @@ type WizardStep struct {
2626
Required bool
2727
}
2828

29-
// NewWizardService creates a new wizard service
29+
// NewWizardService creates a new wizard service (core components are installed separately)
3030
func NewWizardService() *WizardService {
3131
return &WizardService{
3232
steps: []WizardStep{
33-
{
34-
Name: "Core Components",
35-
Description: "Select core shell components (Zsh, Oh My Zsh, theme)",
36-
Required: true,
37-
},
3833
{
3934
Name: "Plugins",
4035
Description: "Select Zsh plugins to install",
@@ -200,13 +195,8 @@ func (ws *WizardService) GeneratePreview(state *WizardState) string {
200195
return builder.String()
201196
}
202197

203-
// ValidateSelections validates the wizard selections
198+
// ValidateSelections validates the wizard selections (core is assumed installed when entering config wizard)
204199
func (ws *WizardService) ValidateSelections(state *WizardState) error {
205-
// Must have at least one core component
206-
if len(state.Selections.CoreComponents) == 0 {
207-
return fmt.Errorf("at least one core component must be selected")
208-
}
209-
210200
return nil
211201
}
212202

@@ -246,15 +236,6 @@ func (ws *WizardService) CanProceed(state *WizardState) bool {
246236
return false
247237
}
248238

249-
// If step is required, check if selections are valid
250-
if step.Required {
251-
// For first step (Core Components), must have at least one selection
252-
if state.CurrentStep == 0 {
253-
return len(state.Selections.CoreComponents) > 0
254-
}
255-
}
256-
257-
// Can always proceed from non-required steps
258239
return true
259240
}
260241

internal/app/services/wizard_service_test.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,23 +226,14 @@ func TestWizardService_GeneratePreview(t *testing.T) {
226226
}
227227
}
228228

229-
// TestWizardService_ValidateSelections tests validating wizard selections
229+
// TestWizardService_ValidateSelections tests validating wizard selections (config wizard assumes core installed)
230230
func TestWizardService_ValidateSelections(t *testing.T) {
231231
service := NewWizardService()
232232
wizard := service.CreateNewWizard()
233233

234-
// Empty selections should fail
235234
err := service.ValidateSelections(wizard)
236-
if err == nil {
237-
t.Error("Expected error for empty selections, got nil")
238-
}
239-
240-
// Add minimum required selections
241-
service.AddCoreComponent(wizard, "zsh")
242-
243-
err = service.ValidateSelections(wizard)
244235
if err != nil {
245-
t.Errorf("ValidateSelections() error = %v", err)
236+
t.Errorf("ValidateSelections() error = %v (empty is valid when core installed separately)", err)
246237
}
247238
}
248239

internal/domain/types/package_category.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ package types
44
type PackageCategory string
55

66
const (
7-
PackageCategoryIDE PackageCategory = "ide"
8-
PackageCategoryTool PackageCategory = "tool"
9-
PackageCategoryApp PackageCategory = "app"
7+
PackageCategoryIDE PackageCategory = "ide"
8+
PackageCategoryTool PackageCategory = "tool"
9+
PackageCategoryApp PackageCategory = "app"
10+
PackageCategoryZshCore PackageCategory = "zsh_core"
1011
)
1112

1213
// IsValid checks if the category is valid
1314
func (c PackageCategory) IsValid() bool {
1415
switch c {
15-
case PackageCategoryIDE, PackageCategoryTool, PackageCategoryApp:
16+
case PackageCategoryIDE, PackageCategoryTool, PackageCategoryApp, PackageCategoryZshCore:
1617
return true
1718
default:
1819
return false

0 commit comments

Comments
 (0)