Skip to content

Commit 2df781d

Browse files
committed
feat: add view to activity bar
1 parent e160fd3 commit 2df781d

File tree

8 files changed

+134
-4
lines changed

8 files changed

+134
-4
lines changed

package.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,50 @@
1717
"command": "vscode-task.runTask",
1818
"title": "Run Task",
1919
"category": "Task"
20+
},
21+
{
22+
"command": "vscode-task.refreshTasks",
23+
"title": "Refresh Tasks",
24+
"category": "Task"
25+
}
26+
],
27+
"viewsContainers": {
28+
"activitybar": [
29+
{
30+
"id": "vscode-task",
31+
"title": "Task",
32+
"icon": "./res/task.svg"
33+
}
34+
]
35+
},
36+
"views": {
37+
"vscode-task": [
38+
{
39+
"id": "vscode-task.tasks",
40+
"name": "Tasks"
41+
}
42+
]
43+
},
44+
"colors": [
45+
{
46+
"id": "vscodetask.upToDate",
47+
"description": "Color for up-to-date tasks in the activity bar.",
48+
"defaults": {
49+
"dark": "#00AA00",
50+
"light": "#00AA00",
51+
"highContrast": "#00AA00",
52+
"highContrastLight": "#00AA00"
53+
}
54+
},
55+
{
56+
"id": "vscodetask.outOfDate",
57+
"description": "Color for out-of-date tasks in the activity bar.",
58+
"defaults": {
59+
"dark": "#AAAAAA",
60+
"light": "#AAAAAA",
61+
"highContrast": "#AAAAAA",
62+
"highContrastLight": "#AAAAAA"
63+
}
2064
}
2165
]
2266
},

src/elements/activityBar.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import * as vscode from 'vscode';
2+
import * as providers from '../providers';
3+
import * as models from '../models';
4+
5+
export class ActivityBar {
6+
private _provider: providers.Tasks;
7+
8+
constructor() {
9+
// Create the data provider
10+
this._provider = new providers.Tasks();
11+
12+
// Register the tree view with its data provider
13+
vscode.window.createTreeView('vscode-task.tasks', {
14+
treeDataProvider: this._provider,
15+
showCollapseAll: true
16+
});
17+
}
18+
19+
public refresh(taskfile?: models.Taskfile) {
20+
this._provider.refresh(taskfile);
21+
}
22+
}

src/elements/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './activityBar';

src/extension.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ export function activate(context: vscode.ExtensionContext) {
1010
taskExtension.registerCommands(context);
1111

1212
// Refresh the tasks list
13-
taskExtension.update().catch((err: string) => {
13+
taskExtension.update().then(() => {
14+
taskExtension.refresh();
15+
}).catch((err: string) => {
1416
console.error(err);
1517
});
1618
}

src/providers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './tasks';

src/providers/tasks.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import * as vscode from 'vscode';
2+
import * as models from '../models';
3+
4+
export class Tasks implements vscode.TreeDataProvider<TaskTreeItem> {
5+
private _onDidChangeTreeData: vscode.EventEmitter<TaskTreeItem | undefined> = new vscode.EventEmitter<TaskTreeItem | undefined>();
6+
readonly onDidChangeTreeData: vscode.Event<TaskTreeItem | undefined> = this._onDidChangeTreeData.event;
7+
private _taskfile?: models.Taskfile;
8+
9+
getTreeItem(element: TaskTreeItem): vscode.TreeItem {
10+
return element;
11+
}
12+
13+
getChildren(element?: TaskTreeItem): Thenable<TaskTreeItem[]> {
14+
var taskTreeItems: TaskTreeItem[] = [];
15+
this._taskfile?.tasks.forEach(task => {
16+
taskTreeItems.push(new TaskTreeItem(task, vscode.TreeItemCollapsibleState.None));
17+
});
18+
return Promise.resolve(taskTreeItems);
19+
}
20+
21+
refresh(taskfile?: models.Taskfile): void {
22+
this._taskfile = taskfile;
23+
this._onDidChangeTreeData.fire(undefined);
24+
}
25+
}
26+
27+
class TaskTreeItem extends vscode.TreeItem {
28+
constructor(
29+
private task: models.Task,
30+
public readonly collapsibleState: vscode.TreeItemCollapsibleState
31+
) {
32+
super(task.name, collapsibleState);
33+
this.tooltip = `${this.task.desc}`;
34+
this.description = this.task.desc;
35+
if (this.task.up_to_date) {
36+
this.iconPath = new vscode.ThemeIcon('debug-breakpoint-log-unverified', new vscode.ThemeColor('vscodetask.upToDate'));
37+
} else {
38+
this.iconPath = new vscode.ThemeIcon('debug-breakpoint-data-unverified', new vscode.ThemeColor('vscodetask.outOfDate'));
39+
}
40+
}
41+
}

src/services/taskfile.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class TaskfileService {
1717
public async read(): Promise<models.Taskfile> {
1818
return await new Promise((resolve, reject) => {
1919
let command = 'task --list-all --json';
20-
cp.exec(command, (err: cp.ExecException | null, stdout: string, stderr: string) => {
20+
cp.exec(command, { cwd: getWorkspaceFolder() }, (err: cp.ExecException | null, stdout: string, stderr: string) => {
2121
if (err) {
2222
console.log('error: ' + err);
2323
reject();
@@ -32,7 +32,7 @@ class TaskfileService {
3232
public async runTask(taskName: string): Promise<void> {
3333
return await new Promise((resolve, reject) => {
3434
let command = `task ${taskName}`;
35-
cp.exec(command, (err: cp.ExecException | null, stdout: string, stderr: string) => {
35+
cp.exec(command, { cwd: getWorkspaceFolder() }, (err: cp.ExecException | null, stdout: string, stderr: string) => {
3636
if (err) {
3737
console.log('error: ' + err);
3838
reject();
@@ -48,3 +48,10 @@ class TaskfileService {
4848
}
4949

5050
export const taskfile = TaskfileService.Instance;
51+
52+
function getWorkspaceFolder(): string | undefined {
53+
if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) {
54+
return undefined;
55+
}
56+
return vscode.workspace.workspaceFolders[0].uri.path;
57+
}

src/task.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,35 @@
11
import * as vscode from 'vscode';
22
import * as commands from './commands';
3+
import * as elements from './elements';
34
import * as services from './services';
45
import * as models from './models';
56

67
export class TaskExtension {
78
private _taskfile?: models.Taskfile;
9+
private _activityBar: elements.ActivityBar;
10+
11+
constructor() {
12+
this._activityBar = new elements.ActivityBar();
13+
}
814

915
public async update(): Promise<void> {
1016
await services.taskfile.read().then((taskfile: models.Taskfile) => {
1117
this._taskfile = taskfile;
1218
});
1319
}
1420

21+
public refresh(): void {
22+
this._activityBar.refresh(this._taskfile);
23+
}
24+
1525
public registerCommands(context: vscode.ExtensionContext): void {
1626
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.runTask', () => {
1727
commands.runTask(this._taskfile);
1828
}));
1929
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.refreshTasks', () => {
20-
this.update().catch((err: string) => {
30+
this.update().then(() => {
31+
this.refresh();
32+
}).catch((err: string) => {
2133
console.error(err);
2234
});
2335
}));

0 commit comments

Comments
 (0)