@firstpick/pi-extension-bang-command-autocomplete 0.1.3 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +13 -2
  2. package/index.ts +33 -18
  3. package/package.json +6 -3
package/README.md CHANGED
@@ -2,10 +2,18 @@
2
2
 
3
3
  Autocomplete for `!<command>` in Pi.
4
4
 
5
+ ![Bang command autocomplete with common commands](images/Common_commands_v0.1.4.png)
6
+
7
+ Built-in suggestions for common shell commands appear as soon as you type `!`.
8
+
9
+ ![Learned full-line and current-session suggestions](images/Learned_Lines_v0.1.4.png)
10
+
11
+ Learned full command lines and commands from the current session surface next to each other while you refine a bang.
12
+
5
13
  ## What it does
6
14
 
7
15
  - Suggests command names while typing `!<command>`.
8
- - Uses a built-in common-command index out of the box.
16
+ - Uses a built-in common-command index out of the box (with platform-aware defaults).
9
17
  - Learns commands you run via `!`/`!!` and persists them across Pi sessions.
10
18
  - Learns full bang command lines (e.g. `!git add .`) and suggests them directly.
11
19
  - Learns flags used with those commands (e.g. `!rg -n`) and suggests them when you type `!<command> ` or `!<command> -...`.
@@ -22,7 +30,10 @@ pi install npm:@firstpick/pi-extension-bang-command-autocomplete
22
30
  ## Configuration
23
31
 
24
32
  - `PI_BANG_AUTOCOMPLETE_INCLUDE_HISTORY`
25
- - `1|true|yes|on`: include commands from `~/.bash_history` and fish history.
33
+ - `1|true|yes|on`: include commands from shell history.
34
+ - Bash: `~/.bash_history`
35
+ - Zsh: `~/.zsh_history`
36
+ - Fish: `$XDG_DATA_HOME/fish/fish_history` (fallback: `~/.local/share/fish/fish_history`)
26
37
  - unset/other: use built-in command list only (default).
27
38
  - `PI_BANG_AUTOCOMPLETE_RUNTIME_STORE_PATH`
28
39
  - optional absolute/relative file path for persisted learned commands.
package/index.ts CHANGED
@@ -1,25 +1,18 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
4
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
5
+ import { envFlag, getAgentDir } from "@firstpick/pi-utils";
5
6
 
6
7
  type CommandSource = "common" | "history" | "runtime";
7
8
 
8
9
  const DEFAULT_RUNTIME_STORE_PATH = path.join(
9
- os.homedir(),
10
- ".pi",
11
- "agent",
10
+ getAgentDir(),
12
11
  "state",
13
12
  "bang-command-autocomplete-runtime.json",
14
13
  );
15
14
 
16
- function envFlag(name: string, fallback: boolean): boolean {
17
- const raw = process.env[name]?.trim().toLowerCase();
18
- if (!raw) return fallback;
19
- return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
20
- }
21
-
22
- const COMMON_COMMANDS = [
15
+ const COMMON_COMMANDS_BASE = [
23
16
  "ls",
24
17
  "la",
25
18
  "ll",
@@ -51,10 +44,6 @@ const COMMON_COMMANDS = [
51
44
  "just",
52
45
  "docker",
53
46
  "docker-compose",
54
- "systemctl",
55
- "journalctl",
56
- "pacman",
57
- "yay",
58
47
  "curl",
59
48
  "wget",
60
49
  "ssh",
@@ -65,6 +54,17 @@ const COMMON_COMMANDS = [
65
54
  "btop",
66
55
  ] as const;
67
56
 
57
+ const COMMON_COMMANDS_UNIX = ["systemctl", "journalctl"] as const;
58
+ const COMMON_COMMANDS_LINUX = ["pacman", "yay"] as const;
59
+
60
+ function getCommonCommands(): string[] {
61
+ const platform = os.platform();
62
+ const commands = [...COMMON_COMMANDS_BASE];
63
+ if (platform !== "win32") commands.push(...COMMON_COMMANDS_UNIX);
64
+ if (platform === "linux") commands.push(...COMMON_COMMANDS_LINUX);
65
+ return commands;
66
+ }
67
+
68
68
  function parseCommandLine(commandLine: string): { executable?: string; flags: string[] } {
69
69
  const trimmed = commandLine.trim();
70
70
  if (!trimmed || trimmed.startsWith("#")) return { flags: [] };
@@ -95,7 +95,8 @@ function extractExecutable(commandLine: string): string | undefined {
95
95
  }
96
96
 
97
97
  function readFishHistoryExecutables(): string[] {
98
- const historyPath = path.join(os.homedir(), ".local", "share", "fish", "fish_history");
98
+ const fishDataHome = process.env.XDG_DATA_HOME?.trim() || path.join(os.homedir(), ".local", "share");
99
+ const historyPath = path.join(fishDataHome, "fish", "fish_history");
99
100
  if (!fs.existsSync(historyPath)) return [];
100
101
 
101
102
  const content = fs.readFileSync(historyPath, "utf8");
@@ -124,6 +125,20 @@ function readBashHistoryExecutables(): string[] {
124
125
  .filter((v): v is string => Boolean(v));
125
126
  }
126
127
 
128
+ function readZshHistoryExecutables(): string[] {
129
+ const historyPath = path.join(os.homedir(), ".zsh_history");
130
+ if (!fs.existsSync(historyPath)) return [];
131
+
132
+ const content = fs.readFileSync(historyPath, "utf8");
133
+ return content
134
+ .split(/\r?\n/)
135
+ .map((line) => {
136
+ const cleaned = line.includes(";") ? line.slice(line.indexOf(";") + 1) : line;
137
+ return extractExecutable(cleaned);
138
+ })
139
+ .filter((v): v is string => Boolean(v));
140
+ }
141
+
127
142
  function getRuntimeStorePath(): string {
128
143
  const configured = process.env.PI_BANG_AUTOCOMPLETE_RUNTIME_STORE_PATH?.trim();
129
144
  return configured ? path.resolve(configured) : DEFAULT_RUNTIME_STORE_PATH;
@@ -218,12 +233,12 @@ function writeRuntimeData(storePath: string, data: RuntimeStoreData): void {
218
233
  function buildCommandIndex(includeHistory: boolean): Array<{ command: string; source: CommandSource }> {
219
234
  const merged = new Map<string, CommandSource>();
220
235
 
221
- for (const command of COMMON_COMMANDS) {
236
+ for (const command of getCommonCommands()) {
222
237
  merged.set(command, "common");
223
238
  }
224
239
 
225
240
  if (includeHistory) {
226
- const historyExecutables = [...readFishHistoryExecutables(), ...readBashHistoryExecutables()];
241
+ const historyExecutables = [...readFishHistoryExecutables(), ...readBashHistoryExecutables(), ...readZshHistoryExecutables()];
227
242
  for (let i = historyExecutables.length - 1; i >= 0; i--) {
228
243
  const command = historyExecutables[i];
229
244
  if (!command) continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firstpick/pi-extension-bang-command-autocomplete",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Autocomplete for !<command> in Pi, with optional shell-history indexing.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -15,11 +15,14 @@
15
15
  ]
16
16
  },
17
17
  "peerDependencies": {
18
- "@mariozechner/pi-coding-agent": "*"
18
+ "@earendil-works/pi-coding-agent": "*"
19
19
  },
20
20
  "files": [
21
21
  "index.ts",
22
22
  "README.md",
23
23
  "LICENSE"
24
- ]
24
+ ],
25
+ "dependencies": {
26
+ "@firstpick/pi-utils": "^0.1.0"
27
+ }
25
28
  }