Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions bin/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env node

import cac from 'cac';
import { script, Completion } from '../src/index.js';
import tab from '../src/cac.js';

import { setupCompletionForPackageManager } from './completion-handlers';

const packageManagers = ['npm', 'pnpm', 'yarn', 'bun'];
const shells = ['zsh', 'bash', 'fish', 'powershell'];

const cli = cac('tab');

cli
.command(
'<packageManager> complete',
'Process completion requests from shell'
)
.allowUnknownOptions()
Comment thread
AmirSa12 marked this conversation as resolved.
Outdated
.action(async (packageManager) => {
if (!packageManagers.includes(packageManager)) {
console.error(`Error: Unsupported package manager "${packageManager}"`);
console.error(
`Supported package managers: ${packageManagers.join(', ')}`
);
process.exit(1);
}

const dashIndex = process.argv.indexOf('--');
if (dashIndex !== -1) {
const completion = new Completion();
setupCompletionForPackageManager(packageManager, completion);
const toComplete = process.argv.slice(dashIndex + 1);
await completion.parse(toComplete);
process.exit(0);
} else {
console.error(`Error: Expected '--' followed by command to complete`);
console.error(
`Example: npx @bombsh/tab ${packageManager} complete -- command-to-complete`
);
process.exit(1);
}
});

cli
.command(
'<packageManager> <shell>',
'Generate shell completion script for a package manager'
)
.action(async (packageManager, shell) => {
if (shell === 'complete') {
Comment thread
AmirSa12 marked this conversation as resolved.
Outdated
const dashIndex = process.argv.indexOf('--');
Comment thread
AmirSa12 marked this conversation as resolved.
Outdated
if (dashIndex !== -1) {
const completion = new Completion();
setupCompletionForPackageManager(packageManager, completion);
const toComplete = process.argv.slice(dashIndex + 1);
await completion.parse(toComplete);
process.exit(0);
} else {
console.error(`Error: Expected '--' followed by command to complete`);
console.error(
`Example: npx @bombsh/tab ${packageManager} complete -- command-to-complete`
);
process.exit(1);
}
return;
}

if (!packageManagers.includes(packageManager)) {
console.error(`Error: Unsupported package manager "${packageManager}"`);
console.error(
`Supported package managers: ${packageManagers.join(', ')}`
);
process.exit(1);
}

if (!shells.includes(shell)) {
console.error(`Error: Unsupported shell "${shell}"`);
console.error(`Supported shells: ${shells.join(', ')}`);
process.exit(1);
}

generateCompletionScript(packageManager, shell);
});

const completion = tab(cli);

Check failure on line 86 in bin/cli.ts

View workflow job for this annotation

GitHub Actions / Lint and Type Check

'completion' is declared but its value is never read.

cli.parse();

function generateCompletionScript(packageManager: string, shell: string) {
const name = packageManager;
const executable = process.env.npm_execpath
? `${packageManager} exec @bombsh/tab ${packageManager}`
: `node ${process.argv[1]} ${packageManager}`;
script(shell as any, name, executable);
}
64 changes: 64 additions & 0 deletions bin/completion-handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Completion } from '../src/index.js';

export function setupCompletionForPackageManager(
packageManager: string,
completion: Completion
) {
if (packageManager === 'pnpm') {
setupPnpmCompletions(completion);
} else if (packageManager === 'npm') {
setupNpmCompletions(completion);
} else if (packageManager === 'yarn') {
setupYarnCompletions(completion);
} else if (packageManager === 'bun') {
setupBunCompletions(completion);
}
}

export function setupPnpmCompletions(completion: Completion) {
completion.addCommand('add', 'Install a package', [], async () => []);
Comment thread
AmirSa12 marked this conversation as resolved.
completion.addCommand('remove', 'Remove a package', [], async () => []);
completion.addCommand(
'install',
'Install all dependencies',
[],
async () => []
);
completion.addCommand('update', 'Update packages', [], async () => []);
completion.addCommand('exec', 'Execute a command', [], async () => []);
completion.addCommand('run', 'Run a script', [], async () => []);
completion.addCommand('publish', 'Publish package', [], async () => []);
completion.addCommand('test', 'Run tests', [], async () => []);
completion.addCommand('build', 'Build project', [], async () => []);
}

export function setupNpmCompletions(completion: Completion) {
completion.addCommand('install', 'Install a package', [], async () => []);
completion.addCommand('uninstall', 'Uninstall a package', [], async () => []);
completion.addCommand('run', 'Run a script', [], async () => []);
completion.addCommand('test', 'Run tests', [], async () => []);
completion.addCommand('publish', 'Publish package', [], async () => []);
completion.addCommand('update', 'Update packages', [], async () => []);
completion.addCommand('start', 'Start the application', [], async () => []);
completion.addCommand('build', 'Build project', [], async () => []);
}

export function setupYarnCompletions(completion: Completion) {
completion.addCommand('add', 'Add a package', [], async () => []);
completion.addCommand('remove', 'Remove a package', [], async () => []);
completion.addCommand('run', 'Run a script', [], async () => []);
completion.addCommand('test', 'Run tests', [], async () => []);
completion.addCommand('publish', 'Publish package', [], async () => []);
completion.addCommand('install', 'Install dependencies', [], async () => []);
completion.addCommand('build', 'Build project', [], async () => []);
}

export function setupBunCompletions(completion: Completion) {
completion.addCommand('add', 'Add a package', [], async () => []);
completion.addCommand('remove', 'Remove a package', [], async () => []);
completion.addCommand('run', 'Run a script', [], async () => []);
completion.addCommand('test', 'Run tests', [], async () => []);
completion.addCommand('install', 'Install dependencies', [], async () => []);
completion.addCommand('update', 'Update packages', [], async () => []);
completion.addCommand('build', 'Build project', [], async () => []);
}
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
{
"name": "tab",
"name": "@bombsh/tab",
"version": "0.0.0",
"description": "",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
"bin": {
"tab": "./dist/bin/cli.js"
},
"scripts": {
"test": "vitest",
"type-check": "tsc --noEmit",
"format": "prettier --write .",
"format:check": "prettier --check .",
"build": "tsdown",
"prepare": "pnpm build",
"lint": "eslint src \"./*.ts\""
"lint": "eslint src \"./*.ts\"",
"test-cli": "tsx bin/cli.ts"
},
"files": [
"dist"
Expand Down
9 changes: 8 additions & 1 deletion tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { defineConfig } from 'tsdown';

export default defineConfig({
entry: ['src/index.ts', 'src/citty.ts', 'src/cac.ts', 'src/commander.ts'],
entry: [
'src/index.ts',
'src/citty.ts',
'src/cac.ts',
'src/commander.ts',
'bin/cli.ts',
'bin/completion-handlers.ts',
Comment thread
AmirSa12 marked this conversation as resolved.
Outdated
],
format: ['esm'],
dts: true,
clean: true,
Expand Down
Loading