mirror of
https://github.com/tiennm99/ccstatusline.git
synced 2026-10-13 14:15:55 +00:00
Add descriptive error handling to CustomCommand, update README, fix Uninstall Emoji that was rendering incorrectly, fix Item Editor line color for consistency, fix version number display
This commit is contained in:
1 parent
990fdf3d54
commit
7782e8b455
7 files changed
+91
-13
No files matched your search
@@ -200,7 +200,7 @@ Execute shell commands and display their output dynamically:
|
||||
|
||||
### 🔗 Integration Example: ccusage
|
||||
|
||||
[ccusage](https://github.com/samuelint/ccusage) is a tool that tracks and displays Claude Code usage metrics. You can integrate it directly into your status line:
|
||||
[ccusage](https://github.com/ryoppippi/ccusage) is a tool that tracks and displays Claude Code usage metrics. You can integrate it directly into your status line:
|
||||
|
||||
1. Add a Custom Command widget
|
||||
2. Set command: `npx -y ccusage statusline`
|
||||
@@ -325,6 +325,16 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
||||
|
||||
---
|
||||
|
||||
## Star History
|
||||
|
||||
<a href="https://www.star-history.com/#sirmalloc/ccstatusline&Timeline">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=sirmalloc/ccstatusline&type=Timeline" />
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<div align="center">
|
||||
|
||||
### 🌟 Show Your Support
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ccstatusline",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"description": "A customizable status line formatter for Claude Code CLI",
|
||||
"module": "src/ccstatusline.ts",
|
||||
"type": "module",
|
||||
@@ -13,6 +13,7 @@
|
||||
"statusline": "bun run src/ccstatusline.ts",
|
||||
"patch": "patch-package",
|
||||
"build": "bun run patch && rm -rf dist/* && bun build src/ccstatusline.ts --target=node --outfile=dist/ccstatusline.js --target-version=14",
|
||||
"postbuild": "bun run scripts/replace-version.ts",
|
||||
"prepublishOnly": "bun run build",
|
||||
"lint": "bun tsc --noEmit; eslint . --config eslint.config.js --max-warnings=999999 --fix"
|
||||
},
|
||||
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bun
|
||||
|
||||
import {
|
||||
readFileSync,
|
||||
writeFileSync
|
||||
} from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
interface PackageJson {
|
||||
version: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
// Read package.json to get version
|
||||
const packageJson = JSON.parse(readFileSync('package.json', 'utf-8')) as PackageJson;
|
||||
const version = packageJson.version;
|
||||
|
||||
// Read the bundled file
|
||||
const bundledFilePath = join('dist', 'ccstatusline.js');
|
||||
let bundledContent = readFileSync(bundledFilePath, 'utf-8');
|
||||
|
||||
// Replace the placeholder with the actual version
|
||||
bundledContent = bundledContent.replace(/__PACKAGE_VERSION__/g, version);
|
||||
|
||||
// Write back the modified content
|
||||
writeFileSync(bundledFilePath, bundledContent);
|
||||
|
||||
console.log(`✓ Replaced version placeholder with ${version}`);
|
||||
@@ -372,8 +372,8 @@ export const ItemsEditor: React.FC<ItemsEditorProps> = ({ widgets, onUpdate, onB
|
||||
{' '}
|
||||
{lineNumber}
|
||||
{' '}
|
||||
{moveMode && <Text color='yellow'>[MOVE MODE]</Text>}
|
||||
</Text>
|
||||
{moveMode && <Text color='blue'>[MOVE MODE]</Text>}
|
||||
{(settings.powerline.enabled || Boolean(settings.defaultSeparator)) && (
|
||||
<Box marginLeft={2}>
|
||||
<Text color='yellow'>
|
||||
@@ -412,7 +412,7 @@ export const ItemsEditor: React.FC<ItemsEditorProps> = ({ widgets, onUpdate, onB
|
||||
return (
|
||||
<Box key={widget.id}>
|
||||
<Text>
|
||||
<Text color={isSelected ? (moveMode ? 'yellow' : 'blue') : undefined}>
|
||||
<Text color={isSelected ? (moveMode ? 'blue' : 'green') : undefined}>
|
||||
{isSelected ? (moveMode ? '◆ ' : '▶ ') : ' '}
|
||||
{` ${index + 1}. ${displayText || getWidgetDisplay(widget)}`}
|
||||
</Text>
|
||||
|
||||
@@ -30,7 +30,7 @@ export const MainMenu: React.FC<MainMenuProps> = ({ onSelect, isClaudeInstalled,
|
||||
{ label: '💻 Terminal Options', value: 'terminalConfig', selectable: true },
|
||||
{ label: '🌐 Global Overrides', value: 'globalOverrides', selectable: true },
|
||||
{ label: '', value: '_gap2', selectable: false }, // Visual gap
|
||||
{ label: isClaudeInstalled ? '🗑️ Uninstall from Claude Code' : '📦 Install to Claude Code', value: 'install', selectable: true }
|
||||
{ label: isClaudeInstalled ? '🔌 Uninstall from Claude Code' : '📦 Install to Claude Code', value: 'install', selectable: true }
|
||||
];
|
||||
|
||||
if (hasChanges) {
|
||||
|
||||
+25
-6
@@ -3,14 +3,33 @@ import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
// Get package version
|
||||
// __PACKAGE_VERSION__ will be replaced at build time
|
||||
const PACKAGE_VERSION = '__PACKAGE_VERSION__';
|
||||
|
||||
export function getPackageVersion(): string {
|
||||
try {
|
||||
const packageJsonPath = path.join(__dirname, '..', '..', 'package.json');
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as { version?: string };
|
||||
return packageJson.version ?? '';
|
||||
} catch {
|
||||
return '';
|
||||
// If we have the build-time replaced version, use it (check if it looks like a version)
|
||||
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
||||
return PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
// Fallback for development mode
|
||||
const possiblePaths = [
|
||||
path.join(__dirname, '..', '..', 'package.json'), // Development: dist/utils/ -> root
|
||||
path.join(__dirname, '..', 'package.json') // Production: dist/ -> root (bundled)
|
||||
];
|
||||
|
||||
for (const packageJsonPath of possiblePaths) {
|
||||
try {
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as { version?: string };
|
||||
return packageJson.version ?? '';
|
||||
}
|
||||
} catch {
|
||||
// Continue to next path
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
// Get terminal width
|
||||
|
||||
@@ -60,7 +60,8 @@ export class CustomCommandWidget implements Widget {
|
||||
encoding: 'utf8',
|
||||
input: jsonInput,
|
||||
timeout: timeout,
|
||||
stdio: ['pipe', 'pipe', 'ignore']
|
||||
stdio: ['pipe', 'pipe', 'ignore'],
|
||||
env: process.env
|
||||
}).trim();
|
||||
|
||||
// Strip ANSI codes if preserveColors is false
|
||||
@@ -74,7 +75,26 @@ export class CustomCommandWidget implements Widget {
|
||||
}
|
||||
|
||||
return output || null;
|
||||
} catch {
|
||||
} catch (error) {
|
||||
// Provide more specific error messages
|
||||
if (error instanceof Error) {
|
||||
const execError = error as Error & {
|
||||
code?: string;
|
||||
signal?: string;
|
||||
status?: number;
|
||||
};
|
||||
if (execError.code === 'ENOENT') {
|
||||
return '[Cmd not found]';
|
||||
} else if (execError.code === 'ETIMEDOUT') {
|
||||
return '[Timeout]';
|
||||
} else if (execError.code === 'EACCES') {
|
||||
return '[Permission denied]';
|
||||
} else if (execError.signal) {
|
||||
return `[Signal: ${execError.signal}]`;
|
||||
} else if (execError.status !== undefined) {
|
||||
return `[Exit: ${execError.status}]`;
|
||||
}
|
||||
}
|
||||
return '[Error]';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user