@laabroms/alias-cli 0.1.2 → 0.1.4

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.
Files changed (2) hide show
  1. package/dist/cli.js +51 -27
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -13,6 +13,7 @@ import { render } from "ink";
13
13
  // src/App.tsx
14
14
  import React8, { useState as useState4, useEffect, useCallback } from "react";
15
15
  import { Box as Box8, Text as Text8, useInput as useInput5, useApp } from "ink";
16
+ import fs2 from "fs";
16
17
  import os2 from "os";
17
18
 
18
19
  // src/aliases.ts
@@ -53,7 +54,8 @@ function loadAliases() {
53
54
  try {
54
55
  const configPath = getShellConfigPath();
55
56
  const content = fs.readFileSync(configPath, "utf-8");
56
- return parseAliases(content);
57
+ const allAliases = parseAliases(content);
58
+ return allAliases.filter((a) => a.name !== "alias-cli");
57
59
  } catch (error) {
58
60
  console.error("Failed to load aliases:", error);
59
61
  return [];
@@ -67,14 +69,15 @@ function saveAliases(aliases) {
67
69
  content = fs.readFileSync(configPath, "utf-8");
68
70
  }
69
71
  const lines = content.split("\n");
70
- const nonAliasLines = lines.filter((line) => {
72
+ const MARKER = "# Aliases managed by alias-cli";
73
+ const filteredLines = lines.filter((line) => {
71
74
  const trimmed = line.trim();
72
- return !trimmed.startsWith("alias ");
75
+ return !trimmed.startsWith("alias ") && trimmed !== MARKER;
73
76
  });
74
77
  const newContent = [
75
- ...nonAliasLines,
78
+ ...filteredLines,
76
79
  "",
77
- "# Aliases managed by alias-cli",
80
+ MARKER,
78
81
  serializeAliases(aliases)
79
82
  ].join("\n");
80
83
  const backupPath = `${configPath}.backup`;
@@ -142,10 +145,11 @@ function AliasList({ aliases, selectedIndex, isSearchMode }) {
142
145
  import React4, { useState } from "react";
143
146
  import { Box as Box4, Text as Text4, useInput } from "ink";
144
147
  import TextInput from "ink-text-input";
145
- function AddAliasModal({ onSave, onCancel }) {
148
+ function AddAliasModal({ onSave, onCancel, existingAliases }) {
146
149
  const [name, setName] = useState("");
147
150
  const [command, setCommand] = useState("");
148
151
  const [focusedField, setFocusedField] = useState("name");
152
+ const isDuplicate = name && existingAliases.some((a) => a.name === name);
149
153
  useInput((input, key) => {
150
154
  if (key.tab || key.downArrow) {
151
155
  setFocusedField((prev) => prev === "name" ? "command" : "name");
@@ -153,7 +157,7 @@ function AddAliasModal({ onSave, onCancel }) {
153
157
  setFocusedField((prev) => prev === "command" ? "name" : "command");
154
158
  } else if (key.escape) {
155
159
  onCancel();
156
- } else if (key.return && name && command) {
160
+ } else if (key.return && name && command && !isDuplicate) {
157
161
  onSave(name, command);
158
162
  }
159
163
  });
@@ -168,7 +172,7 @@ function AddAliasModal({ onSave, onCancel }) {
168
172
  width: 50
169
173
  },
170
174
  isFocusedName ? /* @__PURE__ */ React4.createElement(TextInput, { value: name, onChange: setName, placeholder: "e.g., gc" }) : /* @__PURE__ */ React4.createElement(Text4, { color: name ? "white" : "gray" }, name || "e.g., gc")
171
- )), /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Box4, { marginBottom: 0 }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: isFocusedCommand ? "cyan" : "gray" }, isFocusedCommand && "\u25B6 ", "Command:")), /* @__PURE__ */ React4.createElement(
175
+ ), isDuplicate && /* @__PURE__ */ React4.createElement(Box4, { marginTop: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "red" }, "\u26A0 Alias '", name, "' already exists"))), /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column" }, /* @__PURE__ */ React4.createElement(Box4, { marginBottom: 0 }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: isFocusedCommand ? "cyan" : "gray" }, isFocusedCommand && "\u25B6 ", "Command:")), /* @__PURE__ */ React4.createElement(
172
176
  Box4,
173
177
  {
174
178
  borderStyle: "round",
@@ -328,7 +332,7 @@ function App() {
328
332
  );
329
333
  } else if (input === "a") {
330
334
  setMode("add");
331
- } else if (input === "e" && filteredAliases.length > 0) {
335
+ } else if ((input === "e" || key.return) && filteredAliases.length > 0) {
332
336
  setMode("edit");
333
337
  } else if ((input === "d" || key.delete) && filteredAliases.length > 0) {
334
338
  setMode("delete");
@@ -341,28 +345,39 @@ function App() {
341
345
  const configPath = getShellConfigPath();
342
346
  const fileName = configPath.replace(os2.homedir(), "~");
343
347
  const sourceCommand = `source ${fileName}`;
348
+ const configContent = fs2.readFileSync(configPath, "utf-8");
349
+ const hasAutoReload = configContent.includes("alias-cli()") && configContent.includes("command alias-cli");
344
350
  exit();
345
- console.log("\n\x1B[32m\u2728 Changes saved!\x1B[0m\n");
346
- console.log("\x1B[33m\u{1F4CB} To apply your aliases, run:\x1B[0m");
347
- console.log(` \x1B[36;1m${sourceCommand}\x1B[0m
351
+ console.log("\n\x1B[32;1m\u2728 Changes saved!\x1B[0m\n");
352
+ if (hasAutoReload) {
353
+ console.log(
354
+ "\x1B[2;32m\u26A1 Auto-reload is set up! Your aliases are now applied.\x1B[0m\n"
355
+ );
356
+ } else {
357
+ console.log("\x1B[2m\u{1F4CB} To apply your aliases, run:\x1B[0m");
358
+ console.log(`\x1B[7;36;1m ${sourceCommand} \x1B[0m
348
359
  `);
349
- try {
350
- const { execSync } = __require("child_process");
351
360
  try {
352
- execSync(`echo '${sourceCommand}' | pbcopy`, { stdio: "ignore" });
353
- console.log("\x1B[2m\u2713 Copied to clipboard! Just paste and run.\x1B[0m\n");
361
+ const { execSync } = __require("child_process");
362
+ try {
363
+ execSync(`echo '${sourceCommand}' | pbcopy`, { stdio: "ignore" });
364
+ console.log("\x1B[2;32m\u2713 Copied to clipboard!\x1B[0m\n");
365
+ } catch {
366
+ execSync(`echo '${sourceCommand}' | xclip -selection clipboard`, {
367
+ stdio: "ignore"
368
+ });
369
+ console.log("\x1B[2;32m\u2713 Copied to clipboard!\x1B[0m\n");
370
+ }
354
371
  } catch {
355
- execSync(`echo '${sourceCommand}' | xclip -selection clipboard`, { stdio: "ignore" });
356
- console.log("\x1B[2m\u2713 Copied to clipboard! Just paste and run.\x1B[0m\n");
357
372
  }
358
- } catch {
373
+ console.log(
374
+ "\x1B[2m\u26A1 Want aliases to auto-reload when you quit? Run this once:\x1B[0m\n"
375
+ );
376
+ console.log(
377
+ `\x1B[7;36m echo '\\nalias-cli() { command alias-cli; ${sourceCommand}; }' >> ${fileName} && ${sourceCommand} \x1B[0m
378
+ `
379
+ );
359
380
  }
360
- console.log("\x1B[33m\u26A1 Want auto-reload on quit?\x1B[0m");
361
- console.log(`\x1B[2m Add this wrapper to your ${fileName}:\x1B[0m`);
362
- console.log(`\x1B[2m alias-cli-reload() { command alias-cli && [ -f ~/.alias-cli-reload ] && source "$(cat ~/.alias-cli-reload)" && rm ~/.alias-cli-reload; }\x1B[0m`);
363
- console.log(`\x1B[2m alias alias-cli='alias-cli-reload'\x1B[0m`);
364
- console.log(`\x1B[2m Then run: source ${fileName}\x1B[0m
365
- `);
366
381
  } else {
367
382
  exit();
368
383
  }
@@ -420,7 +435,9 @@ function App() {
420
435
  if (direction === "up") {
421
436
  setSelectedIndex((prev) => Math.max(0, prev - 1));
422
437
  } else {
423
- setSelectedIndex((prev) => Math.min(filteredAliases.length - 1, prev + 1));
438
+ setSelectedIndex(
439
+ (prev) => Math.min(filteredAliases.length - 1, prev + 1)
440
+ );
424
441
  }
425
442
  },
426
443
  [filteredAliases.length]
@@ -462,7 +479,14 @@ function App() {
462
479
  }
463
480
  );
464
481
  case "add":
465
- return /* @__PURE__ */ React8.createElement(AddAliasModal, { onSave: handleAdd, onCancel: handleCancel });
482
+ return /* @__PURE__ */ React8.createElement(
483
+ AddAliasModal,
484
+ {
485
+ onSave: handleAdd,
486
+ onCancel: handleCancel,
487
+ existingAliases: aliases
488
+ }
489
+ );
466
490
  case "edit":
467
491
  return filteredAliases[selectedIndex] ? /* @__PURE__ */ React8.createElement(
468
492
  EditAliasModal,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laabroms/alias-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Interactive TUI for managing shell aliases",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",