tabby-tabbyspaces 0.0.1 → 0.1.0
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/.claude/settings.local.json +28 -2
- package/CHANGELOG.md +46 -20
- package/CLAUDE.md +163 -15
- package/README.md +71 -61
- package/RELEASE.md +91 -0
- package/TEST_MCP.md +176 -0
- package/TODO.md +72 -0
- package/cdp-click.js +22 -0
- package/cdp-test.js +28 -0
- package/dist/components/paneEditor.component.d.ts +6 -1
- package/dist/components/paneEditor.component.d.ts.map +1 -1
- package/dist/components/splitPreview.component.d.ts +22 -7
- package/dist/components/splitPreview.component.d.ts.map +1 -1
- package/dist/components/workspaceEditor.component.d.ts +30 -4
- package/dist/components/workspaceEditor.component.d.ts.map +1 -1
- package/dist/components/workspaceList.component.d.ts +21 -9
- package/dist/components/workspaceList.component.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.LICENSE.txt +1 -1
- package/dist/index.js.map +1 -1
- package/dist/models/workspace.model.d.ts +4 -2
- package/dist/models/workspace.model.d.ts.map +1 -1
- package/dist/package.json +26 -0
- package/dist/providers/settings.provider.d.ts.map +1 -1
- package/dist/providers/toolbar.provider.d.ts +4 -1
- package/dist/providers/toolbar.provider.d.ts.map +1 -1
- package/dist/services/startupCommand.service.d.ts +20 -0
- package/dist/services/startupCommand.service.d.ts.map +1 -0
- package/dist/services/workspaceEditor.service.d.ts +11 -3
- package/dist/services/workspaceEditor.service.d.ts.map +1 -1
- package/docs/marketing_status.md +92 -0
- package/package.json +2 -7
- package/screenshots/editor.png +0 -0
- package/screenshots/pane-edit.png +0 -0
- package/scripts/build-prod.js +39 -0
- package/src/components/paneEditor.component.pug +2 -2
- package/src/components/paneEditor.component.ts +19 -1
- package/src/components/splitPreview.component.pug +45 -5
- package/src/components/splitPreview.component.scss +79 -22
- package/src/components/splitPreview.component.ts +91 -16
- package/src/components/workspaceEditor.component.pug +130 -70
- package/src/components/workspaceEditor.component.scss +205 -120
- package/src/components/workspaceEditor.component.ts +193 -6
- package/src/components/workspaceList.component.pug +31 -20
- package/src/components/workspaceList.component.scss +12 -6
- package/src/components/workspaceList.component.ts +116 -34
- package/src/index.ts +2 -0
- package/src/models/workspace.model.ts +33 -6
- package/src/providers/settings.provider.ts +2 -2
- package/src/providers/toolbar.provider.ts +41 -10
- package/src/services/startupCommand.service.ts +142 -0
- package/src/services/workspaceEditor.service.ts +70 -38
- package/test_cdp.py +50 -0
- package/RELEASE_PLAN.md +0 -161
- package/screenshots/workspace-edit.png +0 -0
|
@@ -34,6 +34,7 @@ export interface TabbyRecoveryToken {
|
|
|
34
34
|
tabTitle?: string;
|
|
35
35
|
tabCustomTitle?: string;
|
|
36
36
|
disableDynamicTitle?: boolean;
|
|
37
|
+
cwd?: string;
|
|
37
38
|
}
|
|
38
39
|
export interface TabbySplitLayoutProfile {
|
|
39
40
|
id: string;
|
|
@@ -65,12 +66,13 @@ export interface Workspace {
|
|
|
65
66
|
icon?: string;
|
|
66
67
|
color?: string;
|
|
67
68
|
root: WorkspaceSplit;
|
|
68
|
-
|
|
69
|
-
hotkey?: string;
|
|
69
|
+
launchOnStartup?: boolean;
|
|
70
70
|
}
|
|
71
71
|
export declare function isWorkspaceSplit(node: WorkspacePane | WorkspaceSplit): node is WorkspaceSplit;
|
|
72
72
|
export declare function createDefaultPane(): WorkspacePane;
|
|
73
73
|
export declare function createDefaultSplit(orientation?: 'horizontal' | 'vertical'): WorkspaceSplit;
|
|
74
|
+
export declare function getRandomColor(): string;
|
|
75
|
+
export declare function getRandomIcon(): string;
|
|
74
76
|
export declare function createDefaultWorkspace(name?: string): Workspace;
|
|
75
77
|
export declare function generateUUID(): string;
|
|
76
78
|
export declare function countPanes(node: WorkspacePane | WorkspaceSplit): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.model.d.ts","sourceRoot":"","sources":["../../src/models/workspace.model.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,mBAAmB,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,GAAG,GAAG,GAAG,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"workspace.model.d.ts","sourceRoot":"","sources":["../../src/models/workspace.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tabby-tabbyspaces",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Workspaces for Tabby - Visual split-layout workspace editor",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"tabby",
|
|
8
|
+
"tabby-plugin"
|
|
9
|
+
],
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"@angular/common": "^15.0.0",
|
|
12
|
+
"@angular/core": "^15.0.0",
|
|
13
|
+
"@angular/forms": "^15.0.0",
|
|
14
|
+
"tabby-core": "*",
|
|
15
|
+
"tabby-local": "*",
|
|
16
|
+
"tabby-settings": "*",
|
|
17
|
+
"tabby-terminal": "*"
|
|
18
|
+
},
|
|
19
|
+
"author": "Igor Halilovic",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"tabbyPlugin": {
|
|
22
|
+
"name": "tabbyspaces",
|
|
23
|
+
"displayName": "TabbySpaces",
|
|
24
|
+
"description": "Workspaces for Tabby - Visual split-layout workspace editor"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.provider.d.ts","sourceRoot":"","sources":["../../src/providers/settings.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAIpD,qBACa,+BAAgC,SAAQ,mBAAmB;IACtE,EAAE,SAAa;IACf,IAAI,
|
|
1
|
+
{"version":3,"file":"settings.provider.d.ts","sourceRoot":"","sources":["../../src/providers/settings.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAIpD,qBACa,+BAAgC,SAAQ,mBAAmB;IACtE,EAAE,SAAa;IACf,IAAI,SAA+B;IACnC,KAAK,SAAe;IAEpB,gBAAgB,IAAI,GAAG;CAGxB"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { ToolbarButtonProvider, ToolbarButton, ProfilesService, AppService } from 'tabby-core';
|
|
2
2
|
import { WorkspaceEditorService } from '../services/workspaceEditor.service';
|
|
3
|
+
import { StartupCommandService } from '../services/startupCommand.service';
|
|
3
4
|
export declare class WorkspaceToolbarProvider extends ToolbarButtonProvider {
|
|
4
5
|
private workspaceService;
|
|
5
6
|
private profilesService;
|
|
6
7
|
private app;
|
|
7
|
-
|
|
8
|
+
private startupService;
|
|
9
|
+
constructor(workspaceService: WorkspaceEditorService, profilesService: ProfilesService, app: AppService, startupService: StartupCommandService);
|
|
10
|
+
private launchStartupWorkspaces;
|
|
8
11
|
provide(): ToolbarButton[];
|
|
9
12
|
private showWorkspaceSelector;
|
|
10
13
|
private openSettings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolbar.provider.d.ts","sourceRoot":"","sources":["../../src/providers/toolbar.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC9F,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;
|
|
1
|
+
{"version":3,"file":"toolbar.provider.d.ts","sourceRoot":"","sources":["../../src/providers/toolbar.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC9F,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAgB1E,qBACa,wBAAyB,SAAQ,qBAAqB;IAE/D,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,cAAc;gBAHd,gBAAgB,EAAE,sBAAsB,EACxC,eAAe,EAAE,eAAe,EAChC,GAAG,EAAE,UAAU,EACf,cAAc,EAAE,qBAAqB;YAYjC,uBAAuB;IASrC,OAAO,IAAI,aAAa,EAAE;YAWZ,qBAAqB;IAkCnC,OAAO,CAAC,YAAY;YAIN,aAAa;CAgB5B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AppService } from 'tabby-core';
|
|
2
|
+
export interface PendingCommand {
|
|
3
|
+
paneId: string;
|
|
4
|
+
command?: string;
|
|
5
|
+
originalTitle: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class StartupCommandService {
|
|
8
|
+
private app;
|
|
9
|
+
private pendingCommands;
|
|
10
|
+
private subscription;
|
|
11
|
+
constructor(app: AppService);
|
|
12
|
+
registerCommands(commands: PendingCommand[]): void;
|
|
13
|
+
private onTabOpened;
|
|
14
|
+
private processChildTabs;
|
|
15
|
+
private processTerminalTab;
|
|
16
|
+
private buildFullCommand;
|
|
17
|
+
private clearProfileArgs;
|
|
18
|
+
ngOnDestroy(): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=startupCommand.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startupCommand.service.d.ts","sourceRoot":"","sources":["../../src/services/startupCommand.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAuC,MAAM,YAAY,CAAA;AAI5E,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,qBACa,qBAAqB;IAIpB,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,YAAY,CAAc;gBAEd,GAAG,EAAE,UAAU;IAInC,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,IAAI;IAOlD,OAAO,CAAC,WAAW;IAoBnB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,kBAAkB;IA+D1B,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,gBAAgB;IAUxB,WAAW,IAAI,IAAI;CAGpB"}
|
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
import { ConfigService, NotificationsService, ProfilesService } from 'tabby-core';
|
|
2
2
|
import { Workspace, TabbyProfile, TabbySplitLayoutProfile } from '../models/workspace.model';
|
|
3
|
+
import { PendingCommand } from './startupCommand.service';
|
|
3
4
|
export declare class WorkspaceEditorService {
|
|
4
5
|
private config;
|
|
5
6
|
private notifications;
|
|
6
7
|
private profilesService;
|
|
8
|
+
private cachedProfiles;
|
|
7
9
|
constructor(config: ConfigService, notifications: NotificationsService, profilesService: ProfilesService);
|
|
10
|
+
private cacheProfiles;
|
|
8
11
|
getWorkspaces(): Workspace[];
|
|
9
12
|
saveWorkspaces(workspaces: Workspace[]): Promise<boolean>;
|
|
10
13
|
addWorkspace(workspace: Workspace): Promise<void>;
|
|
11
14
|
updateWorkspace(workspace: Workspace): Promise<void>;
|
|
12
15
|
deleteWorkspace(workspaceId: string): Promise<void>;
|
|
13
16
|
getAvailableProfiles(): Promise<TabbyProfile[]>;
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Cleanup orphaned profiles from previous plugin versions.
|
|
19
|
+
* Call this once on plugin init.
|
|
20
|
+
*/
|
|
21
|
+
cleanupOrphanedProfiles(): void;
|
|
22
|
+
generateTabbyProfile(workspace: Workspace): Promise<TabbySplitLayoutProfile>;
|
|
16
23
|
private generateRecoveryToken;
|
|
17
24
|
private generatePaneToken;
|
|
18
25
|
duplicateWorkspace(workspace: Workspace): Workspace;
|
|
19
26
|
private regenerateIds;
|
|
20
27
|
private sanitizeForProfileId;
|
|
21
28
|
private getProfileById;
|
|
22
|
-
|
|
29
|
+
collectStartupCommands(workspace: Workspace): PendingCommand[];
|
|
30
|
+
private collectCommandsFromNode;
|
|
23
31
|
private saveConfig;
|
|
24
32
|
}
|
|
25
33
|
//# sourceMappingURL=workspaceEditor.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaceEditor.service.d.ts","sourceRoot":"","sources":["../../src/services/workspaceEditor.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjF,OAAO,EACL,SAAS,EAKT,YAAY,EAEZ,uBAAuB,EACxB,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"workspaceEditor.service.d.ts","sourceRoot":"","sources":["../../src/services/workspaceEditor.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjF,OAAO,EACL,SAAS,EAKT,YAAY,EAEZ,uBAAuB,EACxB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAEzD,qBACa,sBAAsB;IAI/B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,eAAe;IALzB,OAAO,CAAC,cAAc,CAAqB;gBAGjC,MAAM,EAAE,aAAa,EACrB,aAAa,EAAE,oBAAoB,EACnC,eAAe,EAAE,eAAe;YAG5B,aAAa;IAI3B,aAAa,IAAI,SAAS,EAAE;IAItB,cAAc,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAQzD,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpD,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnD,oBAAoB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IASrD;;;OAGG;IACH,uBAAuB,IAAI,IAAI;IAczB,oBAAoB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAiBlF,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,iBAAiB;IA4DzB,kBAAkB,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS;IASnD,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,cAAc;IAYtB,sBAAsB,CAAC,SAAS,EAAE,SAAS,GAAG,cAAc,EAAE;IAM9D,OAAO,CAAC,uBAAuB;YAiBjB,UAAU;CAUzB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# TabbySpaces Marketing Status
|
|
2
|
+
|
|
3
|
+
Track promotion results. Update after each submission.
|
|
4
|
+
|
|
5
|
+
## How to Log
|
|
6
|
+
|
|
7
|
+
Add entry when submitted. Update when results change.
|
|
8
|
+
|
|
9
|
+
### Reddit Posts
|
|
10
|
+
|
|
11
|
+
```markdown
|
|
12
|
+
### r/{subreddit} - {date}
|
|
13
|
+
- **Link**: {url}
|
|
14
|
+
- **Status**: posted / removed / archived
|
|
15
|
+
- **Upvotes**: {number}
|
|
16
|
+
- **Comments**: {number}
|
|
17
|
+
- **Notes**: {any observations}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### GitHub PRs
|
|
21
|
+
|
|
22
|
+
```markdown
|
|
23
|
+
### {list-name} - {date}
|
|
24
|
+
- **PR**: {url}
|
|
25
|
+
- **Status**: submitted / merged / rejected / closed
|
|
26
|
+
- **Notes**: {feedback, requirements not met, etc}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Directory Sites
|
|
30
|
+
|
|
31
|
+
```markdown
|
|
32
|
+
### {site-name} - {date}
|
|
33
|
+
- **Link**: {url if public listing}
|
|
34
|
+
- **Status**: submitted / approved / pending / rejected
|
|
35
|
+
- **Backlink**: yes / no / pending
|
|
36
|
+
- **Notes**: {approval time, featured, etc}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Log
|
|
42
|
+
|
|
43
|
+
*Add entries below, newest first.*
|
|
44
|
+
|
|
45
|
+
### r/ClaudeCode - 2026-01-03
|
|
46
|
+
- **Link**: https://www.reddit.com/r/ClaudeCode/comments/1q2vmqx/i_let_claude_code_write_an_entire_tabby_plugin/
|
|
47
|
+
- **Status**: posted
|
|
48
|
+
- **Upvotes**: 0
|
|
49
|
+
- **Comments**: 0
|
|
50
|
+
- **Notes**: "I let Claude Code write an entire Tabby plugin"
|
|
51
|
+
|
|
52
|
+
### r/SideProject - 2026-01-03
|
|
53
|
+
- **Link**: https://www.reddit.com/r/SideProject/comments/1q2vlby/i_work_with_6_terminal_splits_daily_too_lazy_to/
|
|
54
|
+
- **Status**: posted
|
|
55
|
+
- **Upvotes**: 0
|
|
56
|
+
- **Comments**: 0
|
|
57
|
+
- **Notes**: "I work with 6 terminal splits daily, too lazy to..."
|
|
58
|
+
|
|
59
|
+
### r/commandline - 2026-01-03
|
|
60
|
+
- **Link**: https://www.reddit.com/r/commandline/comments/1q2vhcs/tabbyspaces_visual_workspace_editor_for_tabby/
|
|
61
|
+
- **Status**: posted
|
|
62
|
+
- **Upvotes**: 0
|
|
63
|
+
- **Comments**: 0
|
|
64
|
+
- **Notes**: TabbySpaces announcement
|
|
65
|
+
|
|
66
|
+
### dev.to - 2026-01-03
|
|
67
|
+
- **Link**: https://dev.to/igor_halilovic_3fa0baa977/tabbyspaces-visual-workspace-editor-for-tabby-terminal-2ig6
|
|
68
|
+
- **Status**: posted
|
|
69
|
+
- **Notes**: "TabbySpaces: Visual Workspace Editor for Tabby Terminal"
|
|
70
|
+
|
|
71
|
+
### r/ClaudeAI - 2026-01-03
|
|
72
|
+
- **Link**: https://www.reddit.com/r/ClaudeAI/comments/1q2v0xh/i_let_claude_code_write_an_entire_tabby_plugin/
|
|
73
|
+
- **Status**: posted
|
|
74
|
+
- **Upvotes**: 0
|
|
75
|
+
- **Comments**: 0
|
|
76
|
+
- **Notes**: "I let Claude Code write an entire Tabby plugin"
|
|
77
|
+
|
|
78
|
+
### Uneed - 2026-01-03
|
|
79
|
+
- **Link**: https://www.uneed.best/edit/waiting-line/21145
|
|
80
|
+
- **Status**: pending
|
|
81
|
+
- **Backlink**: pending
|
|
82
|
+
- **Notes**: Waiting for approval
|
|
83
|
+
|
|
84
|
+
### awesome-productivity - 2026-01-03
|
|
85
|
+
- **PR**: https://github.com/jyguyomarch/awesome-productivity/pull/149
|
|
86
|
+
- **Status**: submitted
|
|
87
|
+
- **Notes**: Task Automation section, no star requirements
|
|
88
|
+
|
|
89
|
+
### terminals-are-sexy - 2026-01-03
|
|
90
|
+
- **PR**: https://github.com/k4m4/terminals-are-sexy/pull/346
|
|
91
|
+
- **Status**: submitted
|
|
92
|
+
- **Notes**: Waiting for community endorsement
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tabby-tabbyspaces",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Workspaces for Tabby - Visual split-layout workspace editor",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tabby",
|
|
@@ -8,14 +8,9 @@
|
|
|
8
8
|
],
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"type": "commonjs",
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"tabby-core": "^1.0.197-nightly.1",
|
|
13
|
-
"tabby-settings": "^1.0.197-nightly.1",
|
|
14
|
-
"tabby-terminal": "^1.0.197-nightly.1"
|
|
15
|
-
},
|
|
16
11
|
"typings": "dist/index.d.ts",
|
|
17
12
|
"scripts": {
|
|
18
|
-
"build": "
|
|
13
|
+
"build": "node scripts/build-prod.js",
|
|
19
14
|
"build:dev": "node scripts/build-dev.js",
|
|
20
15
|
"watch": "webpack --mode development --watch",
|
|
21
16
|
"watch:dev": "webpack --mode development --watch --env dev --output-path dist-dev"
|
package/screenshots/editor.png
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const { execSync } = require('child_process')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
5
|
+
const rootDir = path.resolve(__dirname, '..')
|
|
6
|
+
const distDir = path.join(rootDir, 'dist')
|
|
7
|
+
|
|
8
|
+
// 1. Clean dist
|
|
9
|
+
if (fs.existsSync(distDir)) {
|
|
10
|
+
fs.rmSync(distDir, { recursive: true })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// 2. Run webpack
|
|
14
|
+
console.log('Building production version...')
|
|
15
|
+
execSync('npx webpack --mode production', {
|
|
16
|
+
cwd: rootDir,
|
|
17
|
+
stdio: 'inherit'
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// 3. Create package.json
|
|
21
|
+
const pkg = require(path.join(rootDir, 'package.json'))
|
|
22
|
+
const prodPkg = {
|
|
23
|
+
name: pkg.name,
|
|
24
|
+
version: pkg.version,
|
|
25
|
+
description: pkg.description,
|
|
26
|
+
main: 'index.js',
|
|
27
|
+
keywords: pkg.keywords,
|
|
28
|
+
peerDependencies: pkg.peerDependencies,
|
|
29
|
+
author: pkg.author,
|
|
30
|
+
license: pkg.license,
|
|
31
|
+
tabbyPlugin: pkg.tabbyPlugin
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fs.writeFileSync(
|
|
35
|
+
path.join(distDir, 'package.json'),
|
|
36
|
+
JSON.stringify(prodPkg, null, 2)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
console.log('Production build complete: dist/')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
.pane-editor-overlay((click)='
|
|
2
|
-
.pane-editor-modal(
|
|
1
|
+
.pane-editor-overlay((click)='onOverlayClick($event)')
|
|
2
|
+
.pane-editor-modal(#modal)
|
|
3
3
|
.modal-header
|
|
4
4
|
h4 Edit Pane
|
|
5
5
|
button.btn.btn-link.close-btn(type='button', (click)='onCancel()')
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'
|
|
1
|
+
import { Component, Input, Output, EventEmitter, OnInit, HostListener, ElementRef, ViewChild } from '@angular/core'
|
|
2
2
|
import { WorkspacePane, TabbyProfile } from '../models/workspace.model'
|
|
3
3
|
|
|
4
4
|
@Component({
|
|
@@ -11,13 +11,31 @@ export class PaneEditorComponent implements OnInit {
|
|
|
11
11
|
@Input() profiles: TabbyProfile[] = []
|
|
12
12
|
@Output() save = new EventEmitter<WorkspacePane>()
|
|
13
13
|
@Output() cancel = new EventEmitter<void>()
|
|
14
|
+
@ViewChild('modal', { static: true }) modalRef!: ElementRef<HTMLElement>
|
|
14
15
|
|
|
15
16
|
editedPane!: WorkspacePane
|
|
17
|
+
private pointerDownInsideModal = false
|
|
16
18
|
|
|
17
19
|
ngOnInit(): void {
|
|
18
20
|
this.editedPane = { ...this.pane }
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
@HostListener('document:keydown.escape')
|
|
24
|
+
onEscapeKey(): void {
|
|
25
|
+
this.cancel.emit()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@HostListener('document:pointerdown', ['$event'])
|
|
29
|
+
onDocumentPointerDown(event: PointerEvent): void {
|
|
30
|
+
this.pointerDownInsideModal = this.modalRef.nativeElement.contains(event.target as Node)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
onOverlayClick(event: MouseEvent): void {
|
|
34
|
+
if (!this.pointerDownInsideModal && event.target === event.currentTarget) {
|
|
35
|
+
this.cancel.emit()
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
21
39
|
onSave(): void {
|
|
22
40
|
this.save.emit(this.editedPane)
|
|
23
41
|
}
|
|
@@ -1,25 +1,48 @@
|
|
|
1
|
-
.split-preview([class.horizontal]='split.orientation === "horizontal"', [class.vertical]='split.orientation === "vertical"')
|
|
1
|
+
.split-preview([class.horizontal]='split.orientation === "horizontal"', [class.vertical]='split.orientation === "vertical"', [class.nested]='depth > 0')
|
|
2
2
|
ng-container(*ngFor='let child of split.children; let i = index')
|
|
3
3
|
//- Pane
|
|
4
4
|
.preview-pane(
|
|
5
5
|
*ngIf='isPane(child)',
|
|
6
6
|
[style.flex-basis]='getFlexStyle(i)',
|
|
7
|
-
|
|
7
|
+
[class.selected]='asPane(child).id === selectedPaneId',
|
|
8
|
+
(click)='onPaneClick(asPane(child)); $event.stopPropagation()',
|
|
9
|
+
(dblclick)='onEditClick($event, asPane(child))',
|
|
8
10
|
(contextmenu)='onContextMenu($event, asPane(child))'
|
|
9
11
|
)
|
|
10
12
|
.pane-content
|
|
11
|
-
.pane-label
|
|
12
|
-
|
|
13
|
+
.pane-label
|
|
14
|
+
| {{ getPaneLabel(asPane(child)) }}
|
|
15
|
+
.pane-details
|
|
16
|
+
.pane-detail(*ngIf='asPane(child).cwd', [title]='asPane(child).cwd')
|
|
17
|
+
i.fas.fa-folder
|
|
18
|
+
span {{ truncate(asPane(child).cwd, 20) }}
|
|
19
|
+
.pane-detail(*ngIf='asPane(child).startupCommand', [title]='asPane(child).startupCommand')
|
|
20
|
+
i.fas.fa-terminal
|
|
21
|
+
span {{ truncate(asPane(child).startupCommand, 20) }}
|
|
22
|
+
|
|
23
|
+
button.pane-edit-btn(
|
|
24
|
+
type='button',
|
|
25
|
+
(click)='onEditClick($event, asPane(child))',
|
|
26
|
+
title='Edit pane'
|
|
27
|
+
)
|
|
28
|
+
i.fas.fa-pen
|
|
13
29
|
|
|
14
30
|
//- Nested split
|
|
15
31
|
split-preview(
|
|
16
32
|
*ngIf='isSplit(child)',
|
|
17
33
|
[split]='asSplit(child)',
|
|
18
34
|
[depth]='depth + 1',
|
|
35
|
+
[selectedPaneId]='selectedPaneId',
|
|
36
|
+
[profiles]='profiles',
|
|
19
37
|
[style.flex-basis]='getFlexStyle(i)',
|
|
20
|
-
(
|
|
38
|
+
(paneSelect)='onNestedPaneSelect($event)',
|
|
39
|
+
(paneEdit)='onNestedPaneEdit($event)',
|
|
21
40
|
(splitHorizontal)='onNestedSplitH($event)',
|
|
22
41
|
(splitVertical)='onNestedSplitV($event)',
|
|
42
|
+
(addLeft)='onNestedAddLeft($event)',
|
|
43
|
+
(addRight)='onNestedAddRight($event)',
|
|
44
|
+
(addTop)='onNestedAddTop($event)',
|
|
45
|
+
(addBottom)='onNestedAddBottom($event)',
|
|
23
46
|
(removePane)='onNestedRemove($event)'
|
|
24
47
|
)
|
|
25
48
|
|
|
@@ -33,6 +56,10 @@
|
|
|
33
56
|
[style.top.px]='contextMenuPosition.y',
|
|
34
57
|
(click)='$event.stopPropagation()'
|
|
35
58
|
)
|
|
59
|
+
button.context-menu-item(type='button', (click)='onEdit()')
|
|
60
|
+
i.fas.fa-pen
|
|
61
|
+
| Edit
|
|
62
|
+
.context-menu-divider
|
|
36
63
|
button.context-menu-item(type='button', (click)='onSplitH()')
|
|
37
64
|
i.fas.fa-arrows-alt-h
|
|
38
65
|
| Split Horizontal
|
|
@@ -40,6 +67,19 @@
|
|
|
40
67
|
i.fas.fa-arrows-alt-v
|
|
41
68
|
| Split Vertical
|
|
42
69
|
.context-menu-divider
|
|
70
|
+
button.context-menu-item(type='button', (click)='onAddLeft()')
|
|
71
|
+
i.fas.fa-caret-left
|
|
72
|
+
| Add Left
|
|
73
|
+
button.context-menu-item(type='button', (click)='onAddRight()')
|
|
74
|
+
i.fas.fa-caret-right
|
|
75
|
+
| Add Right
|
|
76
|
+
button.context-menu-item(type='button', (click)='onAddTop()')
|
|
77
|
+
i.fas.fa-caret-up
|
|
78
|
+
| Add Top
|
|
79
|
+
button.context-menu-item(type='button', (click)='onAddBottom()')
|
|
80
|
+
i.fas.fa-caret-down
|
|
81
|
+
| Add Bottom
|
|
82
|
+
.context-menu-divider
|
|
43
83
|
button.context-menu-item.danger(type='button', (click)='onRemove()')
|
|
44
84
|
i.fas.fa-trash
|
|
45
85
|
| Remove Pane
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
.split-preview {
|
|
2
2
|
display: flex;
|
|
3
3
|
width: 100%;
|
|
4
|
-
|
|
4
|
+
height: 140px;
|
|
5
5
|
gap: 4px;
|
|
6
|
-
border-radius:
|
|
6
|
+
border-radius: 6px;
|
|
7
7
|
overflow: hidden;
|
|
8
|
-
background: var(--theme-bg
|
|
8
|
+
background: var(--theme-bg);
|
|
9
9
|
border: 1px solid var(--theme-border);
|
|
10
10
|
|
|
11
11
|
&.horizontal {
|
|
@@ -15,48 +15,105 @@
|
|
|
15
15
|
&.vertical {
|
|
16
16
|
flex-direction: column;
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
&.nested {
|
|
20
|
+
height: auto;
|
|
21
|
+
border: 1px dashed var(--theme-fg-more);
|
|
22
|
+
background: rgba(255, 255, 255, 0.02);
|
|
23
|
+
padding: 4px;
|
|
24
|
+
border-radius: 4px;
|
|
25
|
+
}
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
.preview-pane {
|
|
21
29
|
display: flex;
|
|
22
30
|
align-items: center;
|
|
23
31
|
justify-content: center;
|
|
24
|
-
background: var(--theme-bg-more
|
|
32
|
+
background: var(--theme-bg-more);
|
|
25
33
|
border-radius: 4px;
|
|
34
|
+
border: 2px solid transparent;
|
|
26
35
|
cursor: pointer;
|
|
27
|
-
transition: all 0.
|
|
36
|
+
transition: all 0.15s;
|
|
28
37
|
position: relative;
|
|
29
|
-
min-height:
|
|
38
|
+
min-height: 50px;
|
|
30
39
|
|
|
31
40
|
&:hover {
|
|
32
|
-
background: var(--theme-
|
|
33
|
-
|
|
34
|
-
.pane-content {
|
|
35
|
-
color: white;
|
|
36
|
-
}
|
|
41
|
+
background: var(--theme-bg-more-more);
|
|
42
|
+
}
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
44
|
+
&.selected {
|
|
45
|
+
border-color: var(--theme-primary);
|
|
46
|
+
background: var(--theme-bg-more-more);
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
.pane-content {
|
|
45
51
|
text-align: center;
|
|
46
|
-
padding:
|
|
52
|
+
padding: 8px;
|
|
47
53
|
color: var(--theme-fg);
|
|
54
|
+
max-width: 100%;
|
|
55
|
+
overflow: hidden;
|
|
48
56
|
}
|
|
49
57
|
|
|
50
|
-
.pane-
|
|
51
|
-
|
|
58
|
+
.pane-title,
|
|
59
|
+
.pane-profile {
|
|
60
|
+
font-size: 0.8rem;
|
|
52
61
|
font-weight: 500;
|
|
53
|
-
margin-bottom:
|
|
62
|
+
margin-bottom: 2px;
|
|
63
|
+
white-space: nowrap;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
text-overflow: ellipsis;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.pane-details {
|
|
69
|
+
font-size: 0.7rem;
|
|
70
|
+
opacity: 0.7;
|
|
71
|
+
margin-top: 4px;
|
|
72
|
+
|
|
73
|
+
.pane-detail {
|
|
74
|
+
display: flex;
|
|
75
|
+
align-items: center;
|
|
76
|
+
justify-content: center;
|
|
77
|
+
gap: 4px;
|
|
78
|
+
|
|
79
|
+
i {
|
|
80
|
+
width: 12px;
|
|
81
|
+
text-align: center;
|
|
82
|
+
font-size: 0.65rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
span {
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
text-overflow: ellipsis;
|
|
88
|
+
white-space: nowrap;
|
|
89
|
+
max-width: 100px;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.pane-edit-btn {
|
|
95
|
+
position: absolute;
|
|
96
|
+
top: 4px;
|
|
97
|
+
right: 4px;
|
|
98
|
+
padding: 4px 6px;
|
|
99
|
+
background: var(--theme-bg);
|
|
100
|
+
border: 1px solid var(--theme-border);
|
|
101
|
+
border-radius: 4px;
|
|
102
|
+
color: var(--theme-fg);
|
|
103
|
+
cursor: pointer;
|
|
104
|
+
font-size: 0.7rem;
|
|
105
|
+
transition: all 0.15s;
|
|
106
|
+
opacity: 0;
|
|
107
|
+
|
|
108
|
+
&:hover {
|
|
109
|
+
background: var(--theme-primary);
|
|
110
|
+
color: white;
|
|
111
|
+
border-color: var(--theme-primary);
|
|
112
|
+
}
|
|
54
113
|
}
|
|
55
114
|
|
|
56
|
-
.pane-
|
|
57
|
-
|
|
58
|
-
opacity: 0.5;
|
|
59
|
-
transition: opacity 0.2s;
|
|
115
|
+
.preview-pane:hover .pane-edit-btn {
|
|
116
|
+
opacity: 1;
|
|
60
117
|
}
|
|
61
118
|
|
|
62
119
|
// Context menu
|