statusbar-quick-actions 0.0.10
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.
- package/.github/FUNDING.yml +3 -0
- package/.vscodeignore +11 -0
- package/CLAUDE.md +230 -0
- package/LICENSE +21 -0
- package/README.md +529 -0
- package/assets/icon.png +0 -0
- package/bun.lock +908 -0
- package/docs/PERFORMANCE_OPTIMIZATIONS.md +240 -0
- package/docs/PRESET_AND_DYNAMIC_LABELS.md +536 -0
- package/docs/SAMPLE-CONFIGURATIONS.md +973 -0
- package/eslint.config.mjs +41 -0
- package/package.json +605 -0
- package/src/config-cli.ts +1287 -0
- package/src/configuration.ts +530 -0
- package/src/dynamic-label.ts +360 -0
- package/src/executor.ts +406 -0
- package/src/extension.ts +1754 -0
- package/src/history.ts +175 -0
- package/src/material-icons.ts +388 -0
- package/src/notifications.ts +189 -0
- package/src/output-panel.ts +403 -0
- package/src/preset-manager.ts +406 -0
- package/src/theme.ts +318 -0
- package/src/types.ts +368 -0
- package/src/utils/debounce.ts +91 -0
- package/src/visibility.ts +283 -0
- package/tsconfig.dev.json +10 -0
- package/tsconfig.json +19 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript type definitions for StatusBar Quick Actions Extension
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as vscode from "vscode";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Button command configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface ButtonCommand {
|
|
11
|
+
type:
|
|
12
|
+
| "npm"
|
|
13
|
+
| "yarn"
|
|
14
|
+
| "pnpm"
|
|
15
|
+
| "bun"
|
|
16
|
+
| "shell"
|
|
17
|
+
| "github"
|
|
18
|
+
| "vscode"
|
|
19
|
+
| "task"
|
|
20
|
+
| "bunx"
|
|
21
|
+
| "npx"
|
|
22
|
+
| "pnpx"
|
|
23
|
+
| "detect";
|
|
24
|
+
script?: string;
|
|
25
|
+
command?: string;
|
|
26
|
+
args?: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Icon configuration
|
|
31
|
+
*/
|
|
32
|
+
export interface IconConfig {
|
|
33
|
+
id: string;
|
|
34
|
+
animation?: "spin" | "pulse" | null;
|
|
35
|
+
library?: "vscode" | "material";
|
|
36
|
+
variant?: "outlined" | "filled" | "rounded" | "sharp" | "two-tone";
|
|
37
|
+
size?: "small" | "medium" | "large";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Button colors
|
|
42
|
+
*/
|
|
43
|
+
export interface ButtonColors {
|
|
44
|
+
foreground?: string;
|
|
45
|
+
background?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Execution behavior configuration
|
|
50
|
+
*/
|
|
51
|
+
export interface ExecutionConfig {
|
|
52
|
+
foreground?: boolean;
|
|
53
|
+
showProgress?: boolean;
|
|
54
|
+
timeout?: number;
|
|
55
|
+
notifications?: {
|
|
56
|
+
showSuccess?: boolean;
|
|
57
|
+
showError?: boolean;
|
|
58
|
+
showOutput?: boolean;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Visibility condition
|
|
64
|
+
*/
|
|
65
|
+
export interface VisibilityCondition {
|
|
66
|
+
type: "fileType" | "fileExists" | "gitStatus" | "workspaceFolder";
|
|
67
|
+
patterns?: string[];
|
|
68
|
+
path?: string;
|
|
69
|
+
status?: "repository" | "clean" | "dirty" | "ahead" | "behind";
|
|
70
|
+
folders?: string[];
|
|
71
|
+
invert?: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Visibility configuration
|
|
76
|
+
*/
|
|
77
|
+
export interface VisibilityConfig {
|
|
78
|
+
conditions: VisibilityCondition[];
|
|
79
|
+
debounceMs?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* History tracking configuration
|
|
84
|
+
*/
|
|
85
|
+
export interface HistoryConfig {
|
|
86
|
+
enabled?: boolean;
|
|
87
|
+
maxEntries?: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Output panel configuration
|
|
92
|
+
*/
|
|
93
|
+
export interface OutputPanelConfig {
|
|
94
|
+
enabled: boolean;
|
|
95
|
+
mode: "per-button" | "shared";
|
|
96
|
+
format: "raw" | "formatted" | "ansi";
|
|
97
|
+
clearOnRun: boolean;
|
|
98
|
+
showTimestamps: boolean;
|
|
99
|
+
preserveHistory: boolean;
|
|
100
|
+
maxLines: number;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Performance configuration
|
|
105
|
+
*/
|
|
106
|
+
export interface PerformanceConfig {
|
|
107
|
+
visibilityDebounceMs: number;
|
|
108
|
+
enableVirtualization: boolean;
|
|
109
|
+
cacheResults: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Theme color configuration
|
|
114
|
+
*/
|
|
115
|
+
export interface ThemeColorConfig {
|
|
116
|
+
foreground: string;
|
|
117
|
+
background: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Theme configuration
|
|
122
|
+
*/
|
|
123
|
+
export interface ThemeConfig {
|
|
124
|
+
mode: "auto" | "dark" | "light" | "highContrast";
|
|
125
|
+
dark: {
|
|
126
|
+
button: ThemeColorConfig;
|
|
127
|
+
executing: ThemeColorConfig;
|
|
128
|
+
error: ThemeColorConfig;
|
|
129
|
+
};
|
|
130
|
+
light: {
|
|
131
|
+
button: ThemeColorConfig;
|
|
132
|
+
executing: ThemeColorConfig;
|
|
133
|
+
error: ThemeColorConfig;
|
|
134
|
+
};
|
|
135
|
+
highContrast: {
|
|
136
|
+
button: ThemeColorConfig;
|
|
137
|
+
executing: ThemeColorConfig;
|
|
138
|
+
error: ThemeColorConfig;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Notification configuration
|
|
144
|
+
*/
|
|
145
|
+
export interface NotificationConfig {
|
|
146
|
+
showSuccess: boolean;
|
|
147
|
+
showError: boolean;
|
|
148
|
+
showProgress: boolean;
|
|
149
|
+
position: "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
150
|
+
duration: number;
|
|
151
|
+
includeOutput: boolean;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Button state interface
|
|
156
|
+
*/
|
|
157
|
+
export interface ButtonState {
|
|
158
|
+
item: vscode.StatusBarItem;
|
|
159
|
+
config: StatusBarButtonConfig;
|
|
160
|
+
isExecuting: boolean;
|
|
161
|
+
lastResult?: ExecutionResult;
|
|
162
|
+
history: ExecutionResult[];
|
|
163
|
+
accessibility: {
|
|
164
|
+
role: string;
|
|
165
|
+
ariaLabel: string;
|
|
166
|
+
focusOrder: number;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* StatusBar button configuration
|
|
172
|
+
*/
|
|
173
|
+
export interface StatusBarButtonConfig {
|
|
174
|
+
id: string;
|
|
175
|
+
text: string;
|
|
176
|
+
tooltip?: string;
|
|
177
|
+
icon?: IconConfig;
|
|
178
|
+
command: ButtonCommand;
|
|
179
|
+
enabled?: boolean;
|
|
180
|
+
alignment?: "left" | "right";
|
|
181
|
+
priority?: number;
|
|
182
|
+
colors?: ButtonColors;
|
|
183
|
+
execution?: ExecutionConfig;
|
|
184
|
+
visibility?: VisibilityConfig;
|
|
185
|
+
workingDirectory?: string;
|
|
186
|
+
environment?: Record<string, string>;
|
|
187
|
+
history?: HistoryConfig;
|
|
188
|
+
dynamicLabel?: DynamicLabelField; // Dynamic label configuration
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Extension configuration
|
|
193
|
+
*/
|
|
194
|
+
export interface ExtensionConfig {
|
|
195
|
+
buttons: StatusBarButtonConfig[];
|
|
196
|
+
theme?: ThemeConfig;
|
|
197
|
+
notifications?: NotificationConfig;
|
|
198
|
+
history: boolean;
|
|
199
|
+
autoDetect: boolean;
|
|
200
|
+
settings?: {
|
|
201
|
+
debug?: boolean;
|
|
202
|
+
accessibility?: {
|
|
203
|
+
keyboardNavigation?: boolean;
|
|
204
|
+
highContrast?: boolean;
|
|
205
|
+
};
|
|
206
|
+
output?: OutputPanelConfig;
|
|
207
|
+
performance?: PerformanceConfig;
|
|
208
|
+
icons?: {
|
|
209
|
+
library: "vscode" | "material";
|
|
210
|
+
defaultVariant: string;
|
|
211
|
+
defaultSize: string;
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Command execution result
|
|
218
|
+
*/
|
|
219
|
+
export interface ExecutionResult {
|
|
220
|
+
code: number;
|
|
221
|
+
stdout: string;
|
|
222
|
+
stderr: string;
|
|
223
|
+
duration: number;
|
|
224
|
+
timestamp: Date;
|
|
225
|
+
command: string;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Command history entry
|
|
230
|
+
*/
|
|
231
|
+
export interface CommandHistoryEntry {
|
|
232
|
+
id: string;
|
|
233
|
+
buttonId: string;
|
|
234
|
+
result: ExecutionResult;
|
|
235
|
+
command: string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Execution options
|
|
240
|
+
*/
|
|
241
|
+
export interface ExecutionOptions {
|
|
242
|
+
workingDirectory?: string;
|
|
243
|
+
environment?: Record<string, string>;
|
|
244
|
+
timeout?: number;
|
|
245
|
+
streaming?: {
|
|
246
|
+
enabled: boolean;
|
|
247
|
+
onStdout?: (data: string) => void;
|
|
248
|
+
onStderr?: (data: string) => void;
|
|
249
|
+
onProgress?: (percent: number) => void;
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Visibility context
|
|
255
|
+
*/
|
|
256
|
+
export interface VisibilityContext {
|
|
257
|
+
activeFile?: vscode.Uri;
|
|
258
|
+
activeFileName?: string;
|
|
259
|
+
activeFileExtension?: string;
|
|
260
|
+
workspaceFolders?: vscode.WorkspaceFolder[];
|
|
261
|
+
gitStatus?: {
|
|
262
|
+
repository: boolean;
|
|
263
|
+
clean: boolean;
|
|
264
|
+
ahead: boolean;
|
|
265
|
+
behind: boolean;
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Notification types
|
|
271
|
+
*/
|
|
272
|
+
export type NotificationType =
|
|
273
|
+
| "success"
|
|
274
|
+
| "error"
|
|
275
|
+
| "warning"
|
|
276
|
+
| "info"
|
|
277
|
+
| "progress";
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Progress notification data
|
|
281
|
+
*/
|
|
282
|
+
export interface ProgressNotification {
|
|
283
|
+
increment?: number;
|
|
284
|
+
message?: string;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Configuration validation result
|
|
289
|
+
*/
|
|
290
|
+
export interface ValidationResult {
|
|
291
|
+
isValid: boolean;
|
|
292
|
+
errors: string[];
|
|
293
|
+
warnings: string[];
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Menu category for nested settings
|
|
298
|
+
*/
|
|
299
|
+
export interface MenuCategory {
|
|
300
|
+
id: string;
|
|
301
|
+
label: string;
|
|
302
|
+
icon: string;
|
|
303
|
+
description: string;
|
|
304
|
+
items: MenuCategoryItem[];
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Menu category item
|
|
309
|
+
*/
|
|
310
|
+
export interface MenuCategoryItem {
|
|
311
|
+
id: string;
|
|
312
|
+
label: string;
|
|
313
|
+
description?: string;
|
|
314
|
+
action: () => Promise<void>;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Button event types
|
|
319
|
+
*/
|
|
320
|
+
export type ButtonEvent = "click" | "hover" | "focus" | "blur";
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Dynamic label field configuration
|
|
324
|
+
*/
|
|
325
|
+
export interface DynamicLabelField {
|
|
326
|
+
type: "time" | "url" | "env" | "git" | "custom";
|
|
327
|
+
format?: string; // For time: date-time format string
|
|
328
|
+
url?: string; // For url: URL to fetch from
|
|
329
|
+
envVar?: string; // For env: environment variable name
|
|
330
|
+
gitInfo?: "branch" | "status" | "remote"; // For git: git information type
|
|
331
|
+
customFunction?: string; // For custom: function name to evaluate
|
|
332
|
+
refreshInterval?: number; // Refresh interval in milliseconds (0 = no auto-refresh)
|
|
333
|
+
fallback?: string; // Fallback value if evaluation fails
|
|
334
|
+
template?: string; // Template string with ${placeholder} syntax
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Preset configuration for button sets
|
|
339
|
+
*/
|
|
340
|
+
export interface PresetConfig {
|
|
341
|
+
id: string;
|
|
342
|
+
name: string;
|
|
343
|
+
description?: string;
|
|
344
|
+
buttons: StatusBarButtonConfig[];
|
|
345
|
+
theme?: ThemeConfig;
|
|
346
|
+
metadata?: {
|
|
347
|
+
created: Date;
|
|
348
|
+
modified: Date;
|
|
349
|
+
author?: string;
|
|
350
|
+
tags?: string[];
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Preset application mode
|
|
356
|
+
*/
|
|
357
|
+
export type PresetApplicationMode = "replace" | "merge" | "append";
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Dynamic label state
|
|
361
|
+
*/
|
|
362
|
+
export interface DynamicLabelState {
|
|
363
|
+
fieldConfig: DynamicLabelField;
|
|
364
|
+
lastValue: string;
|
|
365
|
+
lastUpdated: Date;
|
|
366
|
+
refreshTimer?: NodeJS.Timeout;
|
|
367
|
+
error?: string;
|
|
368
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debounce utility for StatusBar Quick Actions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a debounced function that delays invoking func until after wait milliseconds
|
|
7
|
+
* have elapsed since the last time the debounced function was invoked
|
|
8
|
+
*/
|
|
9
|
+
export function debounce<T extends (...args: unknown[]) => unknown>(
|
|
10
|
+
func: T,
|
|
11
|
+
wait: number,
|
|
12
|
+
): (...args: Parameters<T>) => void {
|
|
13
|
+
let timeout: NodeJS.Timeout | null = null;
|
|
14
|
+
|
|
15
|
+
return function executedFunction(...args: Parameters<T>) {
|
|
16
|
+
const later = () => {
|
|
17
|
+
timeout = null;
|
|
18
|
+
func(...args);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
if (timeout) {
|
|
22
|
+
clearTimeout(timeout);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
timeout = setTimeout(later, wait);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Manages debounced visibility checks for buttons
|
|
31
|
+
*/
|
|
32
|
+
export class DebouncedVisibilityChecker {
|
|
33
|
+
private debouncedChecks: Map<string, (...args: unknown[]) => void>;
|
|
34
|
+
private defaultDelay: number;
|
|
35
|
+
|
|
36
|
+
constructor(defaultDelay: number) {
|
|
37
|
+
this.debouncedChecks = new Map();
|
|
38
|
+
this.defaultDelay = defaultDelay;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get or create a debounced check function for a button
|
|
43
|
+
*/
|
|
44
|
+
public getDebouncedCheck(
|
|
45
|
+
buttonId: string,
|
|
46
|
+
checkFn: () => void,
|
|
47
|
+
customDelay?: number,
|
|
48
|
+
): () => void {
|
|
49
|
+
const key = buttonId;
|
|
50
|
+
if (!this.debouncedChecks.has(key)) {
|
|
51
|
+
const delay = customDelay ?? this.defaultDelay;
|
|
52
|
+
this.debouncedChecks.set(key, debounce(checkFn, delay));
|
|
53
|
+
}
|
|
54
|
+
return this.debouncedChecks.get(key)!;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Remove a debounced check function for a button
|
|
59
|
+
*/
|
|
60
|
+
public removeDebouncedCheck(buttonId: string): void {
|
|
61
|
+
this.debouncedChecks.delete(buttonId);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Clear all debounced check functions
|
|
66
|
+
*/
|
|
67
|
+
public clear(): void {
|
|
68
|
+
this.debouncedChecks.clear();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Dispose of all resources
|
|
73
|
+
*/
|
|
74
|
+
public dispose(): void {
|
|
75
|
+
this.clear();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get the number of registered debounced checks
|
|
80
|
+
*/
|
|
81
|
+
public size(): number {
|
|
82
|
+
return this.debouncedChecks.size;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if a debounced check exists for a button
|
|
87
|
+
*/
|
|
88
|
+
public has(buttonId: string): boolean {
|
|
89
|
+
return this.debouncedChecks.has(buttonId);
|
|
90
|
+
}
|
|
91
|
+
}
|