@icarusmx/creta 1.4.18 β 1.4.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli/index.js +6 -0
- package/lib/customizers/TerminalCustomizer.js +186 -15
- package/package.json +1 -1
package/lib/cli/index.js
CHANGED
|
@@ -46,6 +46,11 @@ async function customizeTerminal() {
|
|
|
46
46
|
await customizer.customize()
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
async function revertTerminal() {
|
|
50
|
+
const customizer = new TerminalCustomizer()
|
|
51
|
+
await customizer.revert()
|
|
52
|
+
}
|
|
53
|
+
|
|
49
54
|
const COMMANDS = new Map([
|
|
50
55
|
['enunciados', () => executeEnunciados()],
|
|
51
56
|
['sintaxis', () => executeSintaxis()],
|
|
@@ -54,6 +59,7 @@ const COMMANDS = new Map([
|
|
|
54
59
|
['code', () => runCodeSession()],
|
|
55
60
|
['reset', () => resetUserState()],
|
|
56
61
|
['icarus-terminal', () => customizeTerminal()],
|
|
62
|
+
['revert-terminal', () => revertTerminal()],
|
|
57
63
|
['help', () => showHelp()],
|
|
58
64
|
['ayuda', () => showHelp()]
|
|
59
65
|
])
|
|
@@ -2,16 +2,75 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import os from 'os';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
|
+
import { UserState } from '../utils/user-state.js';
|
|
5
6
|
|
|
6
7
|
class TerminalCustomizer {
|
|
7
8
|
constructor() {
|
|
8
9
|
this.homeDir = os.homedir();
|
|
9
10
|
this.zshrcPath = path.join(this.homeDir, '.zshrc');
|
|
10
11
|
this.icarusZshPath = path.join(this.homeDir, '.icarus-zsh');
|
|
12
|
+
this.tips = this.initializeTips();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
initializeTips() {
|
|
16
|
+
return {
|
|
17
|
+
'terminal-basico': [
|
|
18
|
+
'π‘ Usa "cd -" para volver al directorio anterior',
|
|
19
|
+
'π‘ "pwd" muestra tu ubicaciΓ³n actual en el sistema',
|
|
20
|
+
'π‘ "ls -la" muestra archivos ocultos y permisos',
|
|
21
|
+
'π‘ Usa Tab para autocompletar nombres de archivos'
|
|
22
|
+
],
|
|
23
|
+
'git-basico': [
|
|
24
|
+
'π‘ Siempre usa "git status" antes de hacer commit',
|
|
25
|
+
'π‘ "git log --oneline" muestra el historial compacto',
|
|
26
|
+
'π‘ "git diff" te muestra los cambios antes de commit',
|
|
27
|
+
'π‘ Commits frecuentes = mejor historial'
|
|
28
|
+
],
|
|
29
|
+
'piping-redireccion': [
|
|
30
|
+
'π‘ El pipe "|" conecta la salida de un comando con otro',
|
|
31
|
+
'π‘ ">" sobrescribe archivos, ">>" agrega al final',
|
|
32
|
+
'π‘ "grep" es tu mejor amigo para buscar en texto'
|
|
33
|
+
],
|
|
34
|
+
'bash-scripts': [
|
|
35
|
+
'π‘ Usa "chmod +x script.sh" para hacer ejecutable tu script',
|
|
36
|
+
'π‘ Siempre empieza con "#!/bin/bash" en la primera lΓnea',
|
|
37
|
+
'π‘ "$?" te dice el cΓ³digo de salida del ΓΊltimo comando'
|
|
38
|
+
],
|
|
39
|
+
'portafolio': [
|
|
40
|
+
'π‘ "npm run dev" para ver cambios en tiempo real',
|
|
41
|
+
'π‘ Tailwind CSS usa clases utilitarias, no CSS custom',
|
|
42
|
+
'π‘ Usa "md:" para breakpoints responsive en Tailwind',
|
|
43
|
+
'π‘ SvelteKit recarga automΓ‘ticamente al guardar cambios'
|
|
44
|
+
],
|
|
45
|
+
'general': [
|
|
46
|
+
'π‘ Lee los errores completos, suelen decirte quΓ© hacer',
|
|
47
|
+
'π‘ Google es tu amigo, pero StackOverflow mΓ‘s',
|
|
48
|
+
'π‘ Commits pequeΓ±os y frecuentes > commits gigantes',
|
|
49
|
+
'π‘ Comenta tu cΓ³digo como si fueras a olvidarlo maΓ±ana'
|
|
50
|
+
]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getContextualTip() {
|
|
55
|
+
const userState = UserState.get();
|
|
56
|
+
const recentLessons = userState.lessonsCompleted.slice(-3);
|
|
57
|
+
|
|
58
|
+
// Try to get a tip from recently completed lessons
|
|
59
|
+
for (const lesson of recentLessons.reverse()) {
|
|
60
|
+
const lessonId = typeof lesson === 'object' ? lesson.id : lesson;
|
|
61
|
+
if (this.tips[lessonId] && this.tips[lessonId].length > 0) {
|
|
62
|
+
const tips = this.tips[lessonId];
|
|
63
|
+
return tips[Math.floor(Math.random() * tips.length)];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Fallback to general tips
|
|
68
|
+
const generalTips = this.tips.general;
|
|
69
|
+
return generalTips[Math.floor(Math.random() * generalTips.length)];
|
|
11
70
|
}
|
|
12
71
|
|
|
13
72
|
async customize() {
|
|
14
|
-
console.log('\nποΈ Configurando tu terminal
|
|
73
|
+
console.log('\nποΈ Configurando tu terminal Creta...\n');
|
|
15
74
|
|
|
16
75
|
try {
|
|
17
76
|
// Backup existing .zshrc if it exists
|
|
@@ -33,7 +92,7 @@ class TerminalCustomizer {
|
|
|
33
92
|
// Apply changes instantly
|
|
34
93
|
this.applyChanges();
|
|
35
94
|
|
|
36
|
-
console.log('\nπ Β‘Terminal
|
|
95
|
+
console.log('\nπ Β‘Terminal Creta configurado exitosamente!');
|
|
37
96
|
console.log('π‘ Reinicia tu terminal o ejecuta: source ~/.zshrc\n');
|
|
38
97
|
|
|
39
98
|
} catch (error) {
|
|
@@ -43,34 +102,76 @@ class TerminalCustomizer {
|
|
|
43
102
|
}
|
|
44
103
|
|
|
45
104
|
createIcarusZsh() {
|
|
105
|
+
const tip = this.getContextualTip();
|
|
106
|
+
const roadmapHint = this.getRoadmapHint();
|
|
107
|
+
|
|
46
108
|
// Use template literal with escaped $ to prevent Node.js interpolation
|
|
47
109
|
const config = `# ========================================
|
|
48
|
-
# ποΈ
|
|
110
|
+
# ποΈ Creta Terminal Configuration
|
|
49
111
|
# ========================================
|
|
50
112
|
|
|
51
|
-
# Custom
|
|
113
|
+
# Custom prompt with color #007acc
|
|
52
114
|
autoload -U colors && colors
|
|
115
|
+
setopt PROMPT_SUBST
|
|
53
116
|
|
|
54
117
|
# Prompt color codes
|
|
55
|
-
|
|
118
|
+
CRETA_BLUE='%F{39}'
|
|
56
119
|
RESET='%f'
|
|
120
|
+
GIT_BRANCH_COLOR='%F{245}' # Gray for branch
|
|
121
|
+
|
|
122
|
+
# Git branch detection function
|
|
123
|
+
function git_branch_name() {
|
|
124
|
+
git symbolic-ref --short HEAD 2>/dev/null || echo ""
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function git_prompt_info() {
|
|
128
|
+
local branch=\$(git_branch_name)
|
|
129
|
+
if [[ -n "\$branch" ]]; then
|
|
130
|
+
echo " | \${branch}"
|
|
131
|
+
fi
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Custom prompt: [ποΈ creta | branch] ~/path $
|
|
135
|
+
PROMPT="\${CRETA_BLUE}[ποΈ creta\${GIT_BRANCH_COLOR}\$(git_prompt_info)\${CRETA_BLUE}]\${RESET} %~ $ "
|
|
136
|
+
|
|
137
|
+
# Welcome message function
|
|
138
|
+
function creta_welcome() {
|
|
139
|
+
print ""
|
|
140
|
+
print -P "\${CRETA_BLUE}βββββββββββββββββββββββββββββββββββ\${RESET}"
|
|
141
|
+
print -P "\${CRETA_BLUE} ποΈ Bienvenido a Creta Terminal\${RESET}"
|
|
142
|
+
print -P "\${CRETA_BLUE}βββββββββββββββββββββββββββββββββββ\${RESET}"
|
|
143
|
+
print ""
|
|
57
144
|
|
|
58
|
-
#
|
|
59
|
-
|
|
145
|
+
# Show contextual tip
|
|
146
|
+
echo "${tip.replace(/"/g, '\\"')}"
|
|
147
|
+
|
|
148
|
+
# Show roadmap hint if available
|
|
149
|
+
if [[ -f "roadmap.txt" ]]; then
|
|
150
|
+
local next_item=\$(grep -v "^#" roadmap.txt | head -n 1)
|
|
151
|
+
if [[ -n "\$next_item" ]]; then
|
|
152
|
+
echo ""
|
|
153
|
+
echo "π Siguiente en roadmap: \$next_item"
|
|
154
|
+
fi
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
print ""
|
|
158
|
+
}
|
|
60
159
|
|
|
61
|
-
#
|
|
62
|
-
|
|
63
|
-
print -P "\${ICARUS_BLUE}βββββββββββββββββββββββββββββββββββ\${RESET}"
|
|
64
|
-
print -P "\${ICARUS_BLUE} ποΈ Bienvenido a Icarus Terminal\${RESET}"
|
|
65
|
-
print -P "\${ICARUS_BLUE}βββββββββββββββββββββββββββββββββββ\${RESET}"
|
|
66
|
-
print ""
|
|
160
|
+
# Show welcome message
|
|
161
|
+
creta_welcome
|
|
67
162
|
`;
|
|
68
163
|
|
|
69
164
|
fs.writeFileSync(this.icarusZshPath, config, 'utf8');
|
|
70
165
|
}
|
|
71
166
|
|
|
167
|
+
getRoadmapHint() {
|
|
168
|
+
// This is a placeholder - actual parsing happens in the shell script
|
|
169
|
+
// We could potentially read roadmap.txt here if we want to customize the message
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
|
|
72
173
|
updateZshrc() {
|
|
73
|
-
const sourceLine = '\n# Source
|
|
174
|
+
const sourceLine = '\n# Source Creta terminal configuration\n[ -f ~/.icarus-zsh ] && source ~/.icarus-zsh\n';
|
|
74
175
|
|
|
75
176
|
// Create .zshrc if it doesn't exist
|
|
76
177
|
if (!fs.existsSync(this.zshrcPath)) {
|
|
@@ -81,7 +182,7 @@ print ""
|
|
|
81
182
|
// Check if already sourced
|
|
82
183
|
const currentContent = fs.readFileSync(this.zshrcPath, 'utf8');
|
|
83
184
|
if (currentContent.includes('source ~/.icarus-zsh') || currentContent.includes('. ~/.icarus-zsh')) {
|
|
84
|
-
console.log('β οΈ
|
|
185
|
+
console.log('β οΈ Creta ya estaba configurado en .zshrc (actualizando)');
|
|
85
186
|
return;
|
|
86
187
|
}
|
|
87
188
|
|
|
@@ -99,6 +200,76 @@ print ""
|
|
|
99
200
|
// User can manually source or restart terminal
|
|
100
201
|
}
|
|
101
202
|
}
|
|
203
|
+
|
|
204
|
+
async revert() {
|
|
205
|
+
console.log('\nπ Revirtiendo configuraciΓ³n de Creta Terminal...\n');
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
let changesMade = false;
|
|
209
|
+
|
|
210
|
+
// Remove ~/.icarus-zsh if it exists
|
|
211
|
+
if (fs.existsSync(this.icarusZshPath)) {
|
|
212
|
+
fs.unlinkSync(this.icarusZshPath);
|
|
213
|
+
console.log('β
Archivo ~/.icarus-zsh eliminado');
|
|
214
|
+
changesMade = true;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Remove source line from .zshrc
|
|
218
|
+
if (fs.existsSync(this.zshrcPath)) {
|
|
219
|
+
const currentContent = fs.readFileSync(this.zshrcPath, 'utf8');
|
|
220
|
+
|
|
221
|
+
if (currentContent.includes('source ~/.icarus-zsh') || currentContent.includes('. ~/.icarus-zsh')) {
|
|
222
|
+
// Remove the entire Creta block (comment + source line)
|
|
223
|
+
const cleanedContent = currentContent
|
|
224
|
+
.replace(/\n# Source Creta terminal configuration\n\[ -f ~\/\.icarus-zsh \] && source ~\/\.icarus-zsh\n/g, '')
|
|
225
|
+
.replace(/\n# Source Icarus terminal configuration\n\[ -f ~\/\.icarus-zsh \] && source ~\/\.icarus-zsh\n/g, '');
|
|
226
|
+
|
|
227
|
+
fs.writeFileSync(this.zshrcPath, cleanedContent, 'utf8');
|
|
228
|
+
console.log('β
ConfiguraciΓ³n eliminada de ~/.zshrc');
|
|
229
|
+
changesMade = true;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!changesMade) {
|
|
234
|
+
console.log('β οΈ No se encontrΓ³ configuraciΓ³n de Creta para revertir');
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Show available backups
|
|
239
|
+
this.showBackups();
|
|
240
|
+
|
|
241
|
+
console.log('\nπ Β‘ConfiguraciΓ³n revertida exitosamente!');
|
|
242
|
+
console.log('π‘ Reinicia tu terminal o ejecuta: source ~/.zshrc\n');
|
|
243
|
+
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error('β Error al revertir configuraciΓ³n:', error.message);
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
showBackups() {
|
|
251
|
+
try {
|
|
252
|
+
const backupFiles = fs.readdirSync(this.homeDir)
|
|
253
|
+
.filter(file => file.startsWith('.zshrc.backup.'))
|
|
254
|
+
.sort()
|
|
255
|
+
.reverse()
|
|
256
|
+
.slice(0, 5); // Show last 5 backups
|
|
257
|
+
|
|
258
|
+
if (backupFiles.length > 0) {
|
|
259
|
+
console.log('\nπ¦ Backups disponibles (ΓΊltimos 5):');
|
|
260
|
+
backupFiles.forEach((file, index) => {
|
|
261
|
+
const filepath = path.join(this.homeDir, file);
|
|
262
|
+
const stats = fs.statSync(filepath);
|
|
263
|
+
const date = stats.mtime.toLocaleString('es-MX');
|
|
264
|
+
console.log(` ${index + 1}. ${file} (${date})`);
|
|
265
|
+
});
|
|
266
|
+
console.log('\nπ‘ Para restaurar un backup manualmente:');
|
|
267
|
+
console.log(' cp ~/.zshrc.backup.TIMESTAMP ~/.zshrc');
|
|
268
|
+
}
|
|
269
|
+
} catch (error) {
|
|
270
|
+
// Silent fail - backups are optional
|
|
271
|
+
}
|
|
272
|
+
}
|
|
102
273
|
}
|
|
103
274
|
|
|
104
275
|
export default TerminalCustomizer;
|