dex-termux-cli 0.3.0-beta.3 → 0.3.0-beta.5

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/README.md CHANGED
@@ -7,12 +7,12 @@
7
7
  <h1 align="center">Dex Termux CLI</h1>
8
8
 
9
9
  <p align="center">
10
- CLI visual para Termux y Linux con busqueda guiada, tree legible, contexto de proyecto, version visible y flujos seguros para Python, Node y PHP.
10
+ CLI visual para Termux y Linux con busqueda guiada, tree legible, contexto de proyecto, version visible y flujos seguros para Python, Node, PHP, Ruby, Go, Rust y Java.
11
11
  </p>
12
12
 
13
13
  <p align="center">
14
14
  <img alt="platform" src="https://img.shields.io/badge/platform-Termux%20%7C%20Linux-111111?style=flat-square&labelColor=F97316&color=1F2937">
15
- <img alt="safe-mode" src="https://img.shields.io/badge/safe%20mode-Python%20%7C%20Node%20%7C%20PHP-111111?style=flat-square&labelColor=2563EB&color=1F2937">
15
+ <img alt="safe-mode" src="https://img.shields.io/badge/safe%20mode-7%20languages-111111?style=flat-square&labelColor=2563EB&color=1F2937">
16
16
  <img alt="channel" src="https://img.shields.io/badge/channel-beta-111111?style=flat-square&labelColor=B45309&color=1F2937">
17
17
  </p>
18
18
 
@@ -20,7 +20,9 @@
20
20
  <strong>Explorar.</strong> <strong>Entender.</strong> <strong>Instalar.</strong> <strong>Entrar al modo seguro.</strong>
21
21
  </p>
22
22
 
23
- > Estado actual: beta `0.3.0-beta.1` con soporte seguro para Python, Node y PHP, contexto de proyecto y modo de plataforma `auto | termux | linux`.
23
+ > Estado actual: beta `0.3.0-beta.5` muy temprana. La base principal ya funciona, pero Dex sigue en una etapa de ajuste fuerte y aun hay partes incompletas o inestables.
24
+
25
+ > Importante: la base de sesiones y apertura de nuevas terminales (`dex sessions`) sigue sin terminar. Existe trabajo inicial, pero no debe considerarse lista, estable ni parte cerrada de esta beta.
24
26
 
25
27
  ## Vision general
26
28
 
@@ -77,12 +79,16 @@ El modo actual se guarda en `~/.config/dex/config.json`.
77
79
 
78
80
  ## Estado real de la beta
79
81
 
82
+ - esta release sigue en fase muy beta y no debe leerse como build final o pulida
80
83
  - `dex -m`, `-a`, `-b`, `-t`, `-v`, `-c` y `--prompt-context` funcionan
81
84
  - `dex -a` ahora abre una shell de acceso rapido con prompt propio y atajos. En Termux apunta a Android storage y en Linux apunta a HOME
82
85
  - `dex -i` funciona en proyectos validos y ahora usa el root detectado del proyecto aunque entres desde una subcarpeta
83
86
  - `dex -r` funciona para proyectos soportados, hereda mejor el root del proyecto y en Termux exige Android storage
84
87
  - el modo seguro real ya cubre Python, Node, PHP, Ruby, Go, Rust y Java
88
+ - `dex -t` usa por defecto la vista maxima y acepta presets `--mini`, `--med/--medio` y `--max/--maximo`
89
+ - la deteccion del contexto prioriza el proyecto mas cercano para evitar falsos padres al navegar por subcarpetas
85
90
  - `dex -e` ya resuelve su data interna sin depender del directorio actual
91
+ - `dex sessions` sigue en desarrollo y no debe usarse como funcion estable: falta endurecer estado, attach/detach, persistencia y flujo real de nuevas terminales
86
92
 
87
93
  ## Roadmap inmediato
88
94
 
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import { main } from '../src/app/main.js';
3
+
4
+ const argv = process.argv.slice(2);
5
+
6
+ if (argv.includes('--root')) {
7
+ await main(['--prompt-project-root']);
8
+ } else if (argv.includes('--path')) {
9
+ await main(['--prompt-project-path']);
10
+ } else {
11
+ await main(['--prompt-context']);
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dex-termux-cli",
3
- "version": "0.3.0-beta.3",
3
+ "version": "0.3.0-beta.5",
4
4
  "type": "module",
5
5
  "description": "Visual CLI for Termux and Linux with guided search, readable tree views, project context, version checks, Android mode, and safe flows for Python, Node, PHP, Ruby, Go, Rust, and Java.",
6
6
  "keywords": [
@@ -19,7 +19,8 @@
19
19
  ],
20
20
  "license": "MIT",
21
21
  "bin": {
22
- "dex": "bin/dex"
22
+ "dex": "bin/dex",
23
+ "dex-project-context": "bin/dex-project-context"
23
24
  },
24
25
  "scripts": {
25
26
  "start": "node ./bin/dex",
@@ -29,6 +30,7 @@
29
30
  "author": "farllirs",
30
31
  "files": [
31
32
  "bin/dex",
33
+ "bin/dex-project-context",
32
34
  "src",
33
35
  "data/commands/explain.json",
34
36
  "README.md",
@@ -44,5 +46,9 @@
44
46
  },
45
47
  "engines": {
46
48
  "node": ">=18"
49
+ },
50
+ "dependencies": {
51
+ "figures": "^6.1.0",
52
+ "node-pty": "^1.1.0"
47
53
  }
48
54
  }
package/src/app/main.js CHANGED
@@ -7,6 +7,8 @@ import { runInstallCommand } from '../commands/install.js';
7
7
  import { runMenuCommand } from '../commands/menu.js';
8
8
  import { runSafeShellCommand } from '../commands/safe-shell.js';
9
9
  import { runSearchCommand } from '../commands/search.js';
10
+ import { runSessionsCommand } from '../commands/sessions.js';
11
+ import { runSessionsDaemonCommand } from '../commands/sessions-daemon.js';
10
12
  import { runTreeCommand } from '../commands/tree.js';
11
13
  import { runVersionCommand } from '../commands/version.js';
12
14
  import { printHelp, printProjectContextLine } from '../ui/output.js';
@@ -20,8 +22,9 @@ export async function main(argv = process.argv.slice(2)) {
20
22
  const isPromptOnly = parsed.command === 'prompt-context' || parsed.command === 'prompt-project-root' || parsed.command === 'prompt-project-path';
21
23
  const isContextOnly = parsed.command === 'context';
22
24
  const isVersionOnly = parsed.command === 'version';
25
+ const isDaemonOnly = parsed.command === 'sessions-daemon';
23
26
 
24
- if (config.features.projectBadge && !isPromptOnly && !isContextOnly && !isVersionOnly) {
27
+ if (config.features.projectBadge && !isPromptOnly && !isContextOnly && !isVersionOnly && !isDaemonOnly) {
25
28
  const context = await detectProjectContext();
26
29
  if (context) {
27
30
  printProjectContextLine(formatProjectContext(context));
@@ -73,6 +76,16 @@ export async function main(argv = process.argv.slice(2)) {
73
76
  return;
74
77
  }
75
78
 
79
+ if (parsed.command === 'sessions') {
80
+ await runSessionsCommand(parsed);
81
+ return;
82
+ }
83
+
84
+ if (parsed.command === 'sessions-daemon') {
85
+ await runSessionsDaemonCommand();
86
+ return;
87
+ }
88
+
76
89
  if (parsed.command === 'tree') {
77
90
  await runTreeCommand(parsed);
78
91
  return;
@@ -4,6 +4,8 @@ import path from 'node:path';
4
4
  import { spawn } from 'node:child_process';
5
5
  import { getUserConfigPath, loadUserConfig } from '../core/config.js';
6
6
  import { resolveInteractiveShell } from '../utils/shell.js';
7
+ import { buildShellSegmentIconFunction, getPromptIcon } from '../utils/path-icons.js';
8
+ import { getAccentColorCode, getLinuxSetupTheme, formatPromptBrand } from '../utils/prompt-theme.js';
7
9
  import {
8
10
  getQuickAccessAliases,
9
11
  getQuickAccessLabel,
@@ -38,7 +40,7 @@ export async function runAndroidShellCommand() {
38
40
  }
39
41
 
40
42
  const interactiveShell = await resolveAndroidInteractiveShell(platformMode);
41
- const shellSession = await createQuickAccessShellSession(platformMode, interactiveShell);
43
+ const shellSession = await createQuickAccessShellSession(platformMode, interactiveShell, getLinuxSetupTheme(config));
42
44
 
43
45
  console.log(getQuickAccessTitle(platformMode));
44
46
  console.log('');
@@ -107,7 +109,7 @@ async function resolveAndroidInteractiveShell(platformMode) {
107
109
  return interactiveShell;
108
110
  }
109
111
 
110
- async function createQuickAccessShellSession(platformMode, interactiveShell) {
112
+ async function createQuickAccessShellSession(platformMode, interactiveShell, promptTheme) {
111
113
  const tmpBase = await fs.mkdtemp(path.join(os.tmpdir(), 'dex-shell-'));
112
114
  const aliases = getQuickAccessAliases(platformMode);
113
115
  const root = getQuickAccessRoot(platformMode);
@@ -118,6 +120,7 @@ async function createQuickAccessShellSession(platformMode, interactiveShell) {
118
120
  label,
119
121
  shellName: interactiveShell.shellName,
120
122
  platformMode,
123
+ promptTheme,
121
124
  });
122
125
 
123
126
  if (interactiveShell.shellName === 'bash') {
@@ -153,67 +156,128 @@ async function createQuickAccessShellSession(platformMode, interactiveShell) {
153
156
  };
154
157
  }
155
158
 
156
- function buildShellRc({ aliases, root, label, shellName, platformMode }) {
157
- if (platformMode === 'termux') {
158
- return buildTermuxShellRc(shellName);
159
- }
160
-
161
- return buildLinuxShellRc({ aliases, root, label, shellName });
162
- }
163
-
164
- function buildTermuxShellRc(shellName) {
165
- const lines = [
166
- '# dex quick access shell',
167
- 'export PATH="$HOME/bin:$PATH"',
168
- ];
169
-
170
- if (shellName === 'zsh') {
171
- lines.push('[[ -f "$HOME/.zshrc" ]] && source "$HOME/.zshrc"');
172
- lines.push('printf "Dex: acceso rapido cargado en %s\\n" "$PWD"');
173
- return lines.join('\n') + '\n';
174
- }
175
-
176
- if (shellName === 'bash') {
177
- lines.push('[[ -f "$HOME/.bashrc" ]] && source "$HOME/.bashrc"');
178
- lines.push('printf "Dex: acceso rapido cargado en %s\\n" "$PWD"');
179
- return lines.join('\n') + '\n';
180
- }
181
-
182
- lines.push('printf "Dex: acceso rapido cargado en %s\\n" "$PWD"');
183
- return lines.join('\n') + '\n';
159
+ function buildShellRc({ aliases, root, label, shellName, platformMode, promptTheme }) {
160
+ return buildQuickAccessShellRc({ aliases, root, label, shellName, platformMode, promptTheme });
184
161
  }
185
162
 
186
- function buildLinuxShellRc({ aliases, root, label, shellName }) {
163
+ function buildQuickAccessShellRc({ aliases, root, label, shellName, platformMode, promptTheme }) {
187
164
  const aliasLines = Object.entries(aliases).map(([name, target]) => `alias ${name}='cd "${target}"'`);
165
+ const rootIcon = platformMode === 'termux' ? getPromptIcon('android') : getPromptIcon('home');
166
+ const promptMarker = getPromptIcon('prompt');
167
+ const isLinuxTheme = platformMode === 'linux';
168
+ const accentColorCode = isLinuxTheme ? getAccentColorCode(promptTheme.accentColor) : 45;
169
+ const promptBrand = isLinuxTheme ? formatPromptBrand(promptTheme) : `Dex@${platformMode}`;
170
+ const useIconPathStyle = !isLinuxTheme || promptTheme.pathStyle === 'icons';
171
+ const rootPrefix = !isLinuxTheme
172
+ ? `${rootIcon} ${label}`
173
+ : promptTheme.pathStyle === 'ascii'
174
+ ? '[home]'
175
+ : promptTheme.pathStyle === 'text'
176
+ ? label
177
+ : `${rootIcon} ${label}`;
188
178
  const commonLines = [
189
179
  '# dex quick access shell',
190
180
  'export PATH="$HOME/bin:$PATH"',
191
181
  `export DEX_QUICK_ROOT="${root}"`,
192
182
  `export DEX_QUICK_LABEL="${label}"`,
183
+ `export DEX_QUICK_ROOT_ICON="${rootIcon}"`,
184
+ `export DEX_QUICK_ROOT_PREFIX="${rootPrefix}"`,
193
185
  ...aliasLines,
186
+ buildShellSegmentIconFunction('_dex_quick_icon_for_segment'),
187
+ '_dex_quick_iconize_label() {',
188
+ ' input="$1"',
189
+ ' first_mode="$2"',
190
+ ' output=""',
191
+ ' remaining="$input"',
192
+ ' while [ -n "$remaining" ]; do',
193
+ ' segment="${remaining%%/*}"',
194
+ ' if [ "$remaining" = "$segment" ]; then',
195
+ ' remaining=""',
196
+ ' else',
197
+ ' remaining="${remaining#*/}"',
198
+ ' fi',
199
+ ' [ -z "$segment" ] && continue',
200
+ ' if [ -z "$output" ] && [ "$first_mode" = "project" ]; then',
201
+ useIconPathStyle ? ` icon="${getPromptIcon('project')}"` : ' icon=""',
202
+ ' else',
203
+ useIconPathStyle ? ' icon="$(_dex_quick_icon_for_segment "$segment")"' : ' icon=""',
204
+ ' fi',
205
+ ' if [ -n "$output" ]; then',
206
+ ' output="$output/"',
207
+ ' fi',
208
+ useIconPathStyle ? ' output="${output}${icon} ${segment}"' : ' output="${output}${segment}"',
209
+ ' done',
210
+ ' printf "%s" "$output"',
211
+ '}',
194
212
  ];
195
213
 
196
214
  if (shellName === 'zsh') {
197
215
  return [
198
216
  ...commonLines,
199
217
  '[[ -f "$HOME/.zshrc" ]] && source "$HOME/.zshrc"',
200
- '_dex_linux_project_badge_zsh() {',
201
- ' local dex_bin context',
202
- ' dex_bin="$(command -v dex 2>/dev/null)"',
203
- ' [[ -z "$dex_bin" ]] && return',
204
- ' context="$($dex_bin --prompt-context 2>/dev/null)"',
218
+ '_dex_quick_project_root() {',
219
+ ' local helper',
220
+ ' helper="$(command -v dex-project-context 2>/dev/null)"',
221
+ ' [[ -z "$helper" ]] && return',
222
+ ' "$helper" --root 2>/dev/null',
223
+ '}',
224
+ '_dex_quick_project_path() {',
225
+ ' local helper',
226
+ ' helper="$(command -v dex-project-context 2>/dev/null)"',
227
+ ' [[ -z "$helper" ]] && return',
228
+ ' "$helper" --path 2>/dev/null',
229
+ '}',
230
+ '_dex_quick_project_badge_zsh() {',
231
+ ' local helper context',
232
+ ' helper="$(command -v dex-project-context 2>/dev/null)"',
233
+ ' [[ -z "$helper" ]] && return',
234
+ ' context="$("$helper" 2>/dev/null)"',
205
235
  ' [[ -z "$context" ]] && return',
206
236
  ' print -n "%F{81}[$context]%f"',
207
237
  '}',
208
- '_dex_linux_prompt_zsh() {',
209
- ' local badge',
210
- ' badge="$(_dex_linux_project_badge_zsh)"',
211
- " PROMPT=$'%F{45}Dex@linux%f %F{117}%~%f\\n%F{45}>%f '",
238
+ '_dex_quick_path_label_zsh() {',
239
+ ' local project_name project_path current relative label rendered',
240
+ ' project_name="$(_dex_quick_project_root)"',
241
+ ' project_path="$(_dex_quick_project_path)"',
242
+ ' current="$PWD"',
243
+ ' if [[ -n "$project_name" && -n "$project_path" ]]; then',
244
+ ' project_name="${project_name##*/}"',
245
+ ' if [[ "$current" == "$project_path" ]]; then',
246
+ ' rendered="$(_dex_quick_iconize_label "$project_name" project)"',
247
+ ' print -r -- "${DEX_QUICK_ROOT_PREFIX}/${rendered}"',
248
+ ' return',
249
+ ' fi',
250
+ ' relative="${current#$project_path/}"',
251
+ ' if [[ "$relative" != "$current" ]]; then',
252
+ ' label="${project_name}/${relative}"',
253
+ ' rendered="$(_dex_quick_iconize_label "$label" project)"',
254
+ ' print -r -- "${DEX_QUICK_ROOT_PREFIX}/${rendered}"',
255
+ ' return',
256
+ ' fi',
257
+ ' fi',
258
+ ' if [[ "$current" == "$DEX_QUICK_ROOT" ]]; then',
259
+ ' print -r -- "${DEX_QUICK_ROOT_PREFIX}"',
260
+ ' return',
261
+ ' fi',
262
+ ' relative="${current#$DEX_QUICK_ROOT/}"',
263
+ ' if [[ "$relative" != "$current" ]]; then',
264
+ ' rendered="$(_dex_quick_iconize_label "$relative")"',
265
+ ' print -r -- "${DEX_QUICK_ROOT_PREFIX}/${rendered}"',
266
+ ' return',
267
+ ' fi',
268
+ ' rendered="$(_dex_quick_iconize_label "$current")"',
269
+ ' print -r -- "$rendered"',
270
+ '}',
271
+ '_dex_quick_prompt_zsh() {',
272
+ ' local badge path_label',
273
+ ' badge="$(_dex_quick_project_badge_zsh)"',
274
+ ' path_label="$(_dex_quick_path_label_zsh)"',
275
+ ` PROMPT=$'%F{38;5;${accentColorCode}m}${promptBrand}%f %F{117}'"\${path_label}"$'%f\\n%F{38;5;${accentColorCode}m}${promptMarker}%f '`,
212
276
  ' RPROMPT="$badge"',
213
277
  '}',
214
278
  'autoload -Uz add-zsh-hook 2>/dev/null || true',
215
- 'add-zsh-hook precmd _dex_linux_prompt_zsh 2>/dev/null || true',
216
- '_dex_linux_prompt_zsh',
279
+ 'add-zsh-hook precmd _dex_quick_prompt_zsh 2>/dev/null || true',
280
+ '_dex_quick_prompt_zsh',
217
281
  'printf "Dex: acceso rapido cargado en %s\\n" "$PWD"',
218
282
  ].join('\n') + '\n';
219
283
  }
@@ -221,28 +285,75 @@ function buildLinuxShellRc({ aliases, root, label, shellName }) {
221
285
  if (shellName === 'bash') {
222
286
  return [
223
287
  ...commonLines,
224
- '_dex_linux_project_badge_bash() {',
225
- ' local dex_bin context',
226
- ' dex_bin="$(command -v dex 2>/dev/null)"',
227
- ' [[ -z "$dex_bin" ]] && return',
228
- ' context="$($dex_bin --prompt-context 2>/dev/null)"',
288
+ '[[ -f "$HOME/.bashrc" ]] && source "$HOME/.bashrc"',
289
+ '_dex_quick_project_root() {',
290
+ ' local helper',
291
+ ' helper="$(command -v dex-project-context 2>/dev/null)"',
292
+ ' [[ -z "$helper" ]] && return',
293
+ ' "$helper" --root 2>/dev/null',
294
+ '}',
295
+ '_dex_quick_project_path() {',
296
+ ' local helper',
297
+ ' helper="$(command -v dex-project-context 2>/dev/null)"',
298
+ ' [[ -z "$helper" ]] && return',
299
+ ' "$helper" --path 2>/dev/null',
300
+ '}',
301
+ '_dex_quick_project_badge_bash() {',
302
+ ' local helper context',
303
+ ' helper="$(command -v dex-project-context 2>/dev/null)"',
304
+ ' [[ -z "$helper" ]] && return',
305
+ ' context="$("$helper" 2>/dev/null)"',
229
306
  ' [[ -z "$context" ]] && return',
230
307
  ' printf "\\[\\e[38;5;81m\\][%s]\\[\\e[0m\\]" "$context"',
231
308
  '}',
232
- '_dex_linux_prompt_bash() {',
233
- ' local badge',
234
- ' badge="$(_dex_linux_project_badge_bash)"',
235
- ' PS1="\\[\\e[38;5;45m\\]Dex@linux\\[\\e[0m\\] \\[\\e[38;5;117m\\]\\w\\[\\e[0m\\] ${badge}\\n\\[\\e[38;5;45m\\]>\\[\\e[0m\\] "',
309
+ '_dex_quick_path_label_bash() {',
310
+ ' local project_name project_path current relative label rendered',
311
+ ' project_name="$(_dex_quick_project_root)"',
312
+ ' project_path="$(_dex_quick_project_path)"',
313
+ ' current="$PWD"',
314
+ ' if [[ -n "$project_name" && -n "$project_path" ]]; then',
315
+ ' project_name="${project_name##*/}"',
316
+ ' if [[ "$current" == "$project_path" ]]; then',
317
+ ' rendered="$(_dex_quick_iconize_label "$project_name" project)"',
318
+ ' printf "%s" "${DEX_QUICK_ROOT_PREFIX}/${rendered}"',
319
+ ' return',
320
+ ' fi',
321
+ ' relative="${current#$project_path/}"',
322
+ ' if [[ "$relative" != "$current" ]]; then',
323
+ ' label="${project_name}/${relative}"',
324
+ ' rendered="$(_dex_quick_iconize_label "$label" project)"',
325
+ ' printf "%s" "${DEX_QUICK_ROOT_PREFIX}/${rendered}"',
326
+ ' return',
327
+ ' fi',
328
+ ' fi',
329
+ ' if [[ "$current" == "$DEX_QUICK_ROOT" ]]; then',
330
+ ' printf "%s" "${DEX_QUICK_ROOT_PREFIX}"',
331
+ ' return',
332
+ ' fi',
333
+ ' relative="${current#$DEX_QUICK_ROOT/}"',
334
+ ' if [[ "$relative" != "$current" ]]; then',
335
+ ' rendered="$(_dex_quick_iconize_label "$relative")"',
336
+ ' printf "%s" "${DEX_QUICK_ROOT_PREFIX}/${rendered}"',
337
+ ' return',
338
+ ' fi',
339
+ ' rendered="$(_dex_quick_iconize_label "$current")"',
340
+ ' printf "%s" "$rendered"',
341
+ '}',
342
+ '_dex_quick_prompt_bash() {',
343
+ ' local badge path_label',
344
+ ' badge="$(_dex_quick_project_badge_bash)"',
345
+ ' path_label="$(_dex_quick_path_label_bash)"',
346
+ ` PS1="\\[\\e[38;5;${accentColorCode}m\\]${promptBrand}\\[\\e[0m\\] \\[\\e[38;5;117m\\]\${path_label}\\[\\e[0m\\] \${badge}\\n\\[\\e[38;5;${accentColorCode}m\\]${promptMarker}\\[\\e[0m\\] "`,
236
347
  '}',
237
- 'PROMPT_COMMAND=_dex_linux_prompt_bash',
238
- '_dex_linux_prompt_bash',
348
+ 'PROMPT_COMMAND=_dex_quick_prompt_bash',
349
+ '_dex_quick_prompt_bash',
239
350
  'printf "Dex: acceso rapido cargado en %s\\n" "$PWD"',
240
351
  ].join('\n') + '\n';
241
352
  }
242
353
 
243
354
  return [
244
355
  ...commonLines,
245
- `export PS1='[dex ${label}] \\w \\$ '`,
356
+ `export PS1='[${promptBrand}] ${rootPrefix} ${promptMarker} '`,
246
357
  'printf "Dex: acceso rapido cargado en %s\\n" "$PWD"',
247
358
  ].join('\n') + '\n';
248
359
  }