diff --git a/bun.lock b/bun.lock index 3399abe..e7f7b26 100644 --- a/bun.lock +++ b/bun.lock @@ -8,6 +8,7 @@ "chalk": "^5", "commander": "^13", "gray-matter": "^4", + "wrap-ansi": "^9.0.2", }, "devDependencies": { "@semantic-release/changelog": "^6.0.3", @@ -163,7 +164,7 @@ "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], @@ -1093,8 +1094,6 @@ "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - "@eslint/eslintrc/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "@semantic-release/github/aggregate-error/clean-stack": ["clean-stack@5.3.0", "", { "dependencies": { "escape-string-regexp": "5.0.0" } }, "sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg=="], @@ -1119,6 +1118,8 @@ "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "cli-highlight/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "cli-highlight/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], "cli-highlight/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -1145,6 +1146,8 @@ "env-ci/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="], + "eslint/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "npm/minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "npm/minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], @@ -1227,6 +1230,8 @@ "cli-highlight/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "cli-highlight/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "cli-highlight/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "pkg-conf/find-up/locate-path/p-locate/p-limit": ["p-limit@1.3.0", "", { "dependencies": { "p-try": "^1.0.0" } }, "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q=="], diff --git a/package.json b/package.json index cf2677e..3e1ed70 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "dependencies": { "chalk": "^5", "commander": "^13", - "gray-matter": "^4" + "gray-matter": "^4", + "wrap-ansi": "^9.0.2" } } diff --git a/src/commands/add.ts b/src/commands/add.ts index 2c1cba1..1771c3e 100644 --- a/src/commands/add.ts +++ b/src/commands/add.ts @@ -2,6 +2,7 @@ import chalk from 'chalk' import { findSkill, discoverSkills } from '../skills.ts' import { resolveAgents } from '../agents.ts' import { installSkill } from '../installer.ts' +import { wrapText } from '../format.ts' export function addCommand( skillNames: string[], @@ -57,7 +58,7 @@ export function addCommand( console.log() console.log(` ${chalk.bold('Installing:')} ${skill.name}`) - console.log(` ${chalk.dim('→')} ${skill.description}`) + console.log(wrapText(`${chalk.dim('→')} ${skill.description}`, 4)) console.log() for (const agent of targetAgents) { diff --git a/src/commands/info.ts b/src/commands/info.ts index 57f57df..cd2343c 100644 --- a/src/commands/info.ts +++ b/src/commands/info.ts @@ -1,5 +1,6 @@ import chalk from 'chalk' import { findSkill } from '../skills.ts' +import { wrapText } from '../format.ts' export function infoCommand(skillName: string): void { const skill = findSkill(skillName) @@ -15,7 +16,7 @@ export function infoCommand(skillName: string): void { console.log() console.log(chalk.bold(skill.name)) console.log() - console.log(` ${skill.description}`) + console.log(wrapText(skill.description, 2)) console.log() if (skill.metadata) { diff --git a/src/commands/list.ts b/src/commands/list.ts index 639eb64..7016a4c 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -16,7 +16,8 @@ export function listCommand(): void { const maxNameLen = Math.max(...skills.map((s) => s.name.length)) const indent = 2 const gap = 2 - const maxDescLen = 80 - indent - maxNameLen - gap + const termWidth = process.stdout.columns || 80 + const maxDescLen = termWidth - indent - maxNameLen - gap for (const skill of skills) { const name = chalk.cyan(skill.name.padEnd(maxNameLen + gap)) diff --git a/src/format.ts b/src/format.ts new file mode 100644 index 0000000..3534964 --- /dev/null +++ b/src/format.ts @@ -0,0 +1,12 @@ +import wrapAnsi from 'wrap-ansi' + +export function wrapText(text: string, indent: number): string { + const columns = process.stdout.columns || 80 + const width = Math.max(columns - indent, 20) + const wrapped = wrapAnsi(text, width, { hard: true }) + const pad = ' '.repeat(indent) + return wrapped + .split('\n') + .map((line) => `${pad}${line}`) + .join('\n') +}