or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

extension-points.mdindex.mdworkspace-commands.mdworkspace-file-handling.mdworkspace-preferences.mdworkspace-server.mdworkspace-service.md

workspace-commands.mddocs/

0

# Workspace Commands

1

2

The workspace commands module provides all command definitions, handlers, and menu contributions for workspace operations. It includes file management, workspace opening/closing, and folder operations with comprehensive event handling and extensibility points.

3

4

## Capabilities

5

6

### Command Definitions

7

8

All workspace-related command constants with their definitions.

9

10

```typescript { .api }

11

namespace WorkspaceCommands {

12

// File/Workspace Opening Commands

13

const OPEN: Command & { dialogLabel: string };

14

const OPEN_FILE: Command & { dialogLabel: string };

15

const OPEN_FOLDER: Command & { dialogLabel: string };

16

const OPEN_WORKSPACE: Command & { dialogLabel: string };

17

const OPEN_RECENT_WORKSPACE: Command;

18

const CLOSE: Command;

19

20

// File Operations Commands

21

const NEW_FILE: Command;

22

const NEW_FOLDER: Command;

23

const FILE_RENAME: Command;

24

const FILE_DELETE: Command;

25

const FILE_DUPLICATE: Command;

26

const FILE_COMPARE: Command;

27

const COPY_RELATIVE_FILE_PATH: Command;

28

29

// Workspace Management Commands

30

const ADD_FOLDER: Command;

31

const REMOVE_FOLDER: Command;

32

const SAVE_WORKSPACE_AS: Command;

33

const OPEN_WORKSPACE_FILE: Command;

34

}

35

```

36

37

**Usage Example:**

38

39

```typescript

40

import { WorkspaceCommands } from "@theia/workspace/lib/browser";

41

import { CommandRegistry } from "@theia/core/lib/common";

42

43

// Execute workspace commands programmatically

44

registry.executeCommand(WorkspaceCommands.NEW_FILE.id);

45

registry.executeCommand(WorkspaceCommands.OPEN_WORKSPACE.id, workspaceUri);

46

registry.executeCommand(WorkspaceCommands.SAVE_WORKSPACE_AS.id);

47

```

48

49

### Command Contribution

50

51

Main contribution class that registers all workspace commands and handles their execution.

52

53

```typescript { .api }

54

class WorkspaceCommandContribution implements CommandContribution {

55

/**

56

* Event fired when a new file is created

57

*/

58

readonly onDidCreateNewFile: Event<DidCreateNewResourceEvent>;

59

60

/**

61

* Event fired when a new folder is created

62

*/

63

readonly onDidCreateNewFolder: Event<DidCreateNewResourceEvent>;

64

65

/**

66

* Register all workspace commands with the command registry

67

*/

68

registerCommands(registry: CommandRegistry): void;

69

70

/**

71

* Validate file name for creation operations

72

* @param name - Proposed file name

73

* @param parent - Parent directory

74

* @param allowNested - Whether to allow nested path creation

75

*/

76

protected validateFileName(name: string, parent: FileStat, allowNested?: boolean): Promise<string>;

77

}

78

```

79

80

**Usage Example:**

81

82

```typescript

83

import { injectable, inject } from "@theia/core/shared/inversify";

84

import { WorkspaceCommandContribution, DidCreateNewResourceEvent } from "@theia/workspace/lib/browser";

85

import { Disposable } from "@theia/core";

86

87

@injectable()

88

export class MyWorkspaceListener {

89

90

@inject(WorkspaceCommandContribution)

91

protected readonly workspaceCommands: WorkspaceCommandContribution;

92

93

protected readonly disposables = new DisposableCollection();

94

95

@postConstruct()

96

initialize(): void {

97

// Listen to file creation events

98

this.disposables.push(

99

this.workspaceCommands.onDidCreateNewFile(event => {

100

console.log(`New file created: ${event.uri}`);

101

console.log(`In directory: ${event.parent}`);

102

})

103

);

104

105

// Listen to folder creation events

106

this.disposables.push(

107

this.workspaceCommands.onDidCreateNewFolder(event => {

108

console.log(`New folder created: ${event.uri}`);

109

this.indexNewFolder(event.uri);

110

})

111

);

112

}

113

114

private indexNewFolder(uri: URI): void {

115

// Custom logic for handling new folders

116

}

117

}

118

```

119

120

### File Operation Handlers

121

122

Specialized handlers for file operations with built-in validation and user interaction.

123

124

```typescript { .api }

125

class WorkspaceDeleteHandler implements UriCommandHandler<URI[]> {

126

/**

127

* Check if delete operation is visible for given URIs

128

*/

129

isVisible(uris: URI[]): boolean;

130

131

/**

132

* Check if delete operation is enabled for given URIs

133

*/

134

isEnabled(uris: URI[]): boolean;

135

136

/**

137

* Execute delete operation for given URIs

138

*/

139

execute(uris: URI[]): Promise<void>;

140

}

141

142

class WorkspaceDuplicateHandler implements UriCommandHandler<URI[]> {

143

/**

144

* Check if duplicate operation is visible for given URIs

145

*/

146

isVisible(uris: URI[]): boolean;

147

148

/**

149

* Check if duplicate operation is enabled for given URIs

150

*/

151

isEnabled(uris: URI[]): boolean;

152

153

/**

154

* Execute duplicate operation for given URIs

155

*/

156

execute(uris: URI[]): Promise<void>;

157

}

158

159

class WorkspaceCompareHandler implements UriCommandHandler<URI[]> {

160

/**

161

* Check if compare operation is visible for given URIs

162

*/

163

isVisible(uris: URI[]): boolean;

164

165

/**

166

* Check if compare operation is enabled for given URIs

167

*/

168

isEnabled(uris: URI[]): boolean;

169

170

/**

171

* Execute compare operation for given URIs

172

*/

173

execute(uris: URI[]): Promise<void>;

174

}

175

```

176

177

**Usage Example:**

178

179

```typescript

180

import { injectable, inject } from "@theia/core/shared/inversify";

181

import { WorkspaceDeleteHandler, WorkspaceDuplicateHandler } from "@theia/workspace/lib/browser";

182

import URI from "@theia/core/lib/common/uri";

183

184

@injectable()

185

export class MyFileOperations {

186

187

@inject(WorkspaceDeleteHandler)

188

protected readonly deleteHandler: WorkspaceDeleteHandler;

189

190

@inject(WorkspaceDuplicateHandler)

191

protected readonly duplicateHandler: WorkspaceDuplicateHandler;

192

193

async deleteFiles(fileUris: URI[]): Promise<void> {

194

if (this.deleteHandler.isEnabled(fileUris)) {

195

await this.deleteHandler.execute(fileUris);

196

}

197

}

198

199

async duplicateFiles(fileUris: URI[]): Promise<void> {

200

if (this.duplicateHandler.isEnabled(fileUris)) {

201

await this.duplicateHandler.execute(fileUris);

202

}

203

}

204

}

205

```

206

207

### Menu Contributions

208

209

Menu contributions for file and edit menus with workspace-specific entries.

210

211

```typescript { .api }

212

class FileMenuContribution implements MenuContribution {

213

/**

214

* Register file menu entries for workspace operations

215

*/

216

registerMenus(registry: MenuModelRegistry): void;

217

}

218

219

class EditMenuContribution implements MenuContribution {

220

/**

221

* Register edit menu entries for workspace operations

222

*/

223

registerMenus(registry: MenuModelRegistry): void;

224

}

225

```

226

227

**Usage Example:**

228

229

```typescript

230

import { injectable } from "@theia/core/shared/inversify";

231

import { MenuContribution, MenuModelRegistry } from "@theia/core/lib/common";

232

import { WorkspaceCommands } from "@theia/workspace/lib/browser";

233

234

@injectable()

235

export class CustomWorkspaceMenuContribution implements MenuContribution {

236

237

registerMenus(registry: MenuModelRegistry): void {

238

// Add custom menu items to workspace menu

239

registry.registerMenuAction(CommonMenus.FILE_NEW, {

240

commandId: WorkspaceCommands.NEW_FILE.id,

241

label: 'New File...',

242

order: '10'

243

});

244

245

registry.registerMenuAction(['my-custom-menu'], {

246

commandId: WorkspaceCommands.SAVE_WORKSPACE_AS.id,

247

label: 'Save Workspace As...'

248

});

249

}

250

}

251

```

252

253

### Specialized Command Handlers

254

255

URI-aware command handlers for workspace-specific operations.

256

257

```typescript { .api }

258

class WorkspaceRootUriAwareCommandHandler extends UriAwareCommandHandler<URI> {

259

/**

260

* Check if command is enabled for current context

261

*/

262

isEnabled(...args: any[]): boolean;

263

264

/**

265

* Check if command is visible for current context

266

*/

267

isVisible(...args: any[]): boolean;

268

269

/**

270

* Get URI from command arguments

271

*/

272

protected getUri(...args: any[]): URI | undefined;

273

}

274

```

275

276

**Usage Example:**

277

278

```typescript

279

import { injectable, inject } from "@theia/core/shared/inversify";

280

import { WorkspaceRootUriAwareCommandHandler, WorkspaceService } from "@theia/workspace/lib/browser";

281

import { SelectionService } from "@theia/core/lib/common";

282

283

@injectable()

284

export class MyCustomCommandHandler extends WorkspaceRootUriAwareCommandHandler {

285

286

constructor(

287

@inject(WorkspaceService) workspaceService: WorkspaceService,

288

@inject(SelectionService) selectionService: SelectionService

289

) {

290

super(workspaceService, selectionService, {

291

execute: (uri: URI) => this.executeCustomCommand(uri),

292

isEnabled: (uri: URI) => this.isCustomCommandEnabled(uri),

293

isVisible: (uri: URI) => this.isCustomCommandVisible(uri)

294

});

295

}

296

297

private executeCustomCommand(uri: URI): void {

298

console.log(`Executing custom command on workspace root: ${uri}`);

299

}

300

301

private isCustomCommandEnabled(uri: URI): boolean {

302

return this.workspaceService.areWorkspaceRoots([uri]);

303

}

304

305

private isCustomCommandVisible(uri: URI): boolean {

306

return true;

307

}

308

}

309

```

310

311

### Workspace Utilities

312

313

Utility functions for workspace operations and validation.

314

315

```typescript { .api }

316

class WorkspaceUtils {

317

/**

318

* Determine if root directory exists for a given array of URIs

319

* @param uris - Array of URIs to check

320

*/

321

containsRootDirectory(uris: URI[]): boolean;

322

}

323

```

324

325

**Usage Example:**

326

327

```typescript

328

import { injectable, inject } from "@theia/core/shared/inversify";

329

import { WorkspaceUtils } from "@theia/workspace/lib/browser";

330

import URI from "@theia/core/lib/common/uri";

331

332

@injectable()

333

export class MyWorkspaceValidator {

334

335

@inject(WorkspaceUtils)

336

protected readonly workspaceUtils: WorkspaceUtils;

337

338

validateSelection(uris: URI[]): boolean {

339

// Check if selection contains workspace root directories

340

if (this.workspaceUtils.containsRootDirectory(uris)) {

341

console.log("Selection contains workspace root directories");

342

return false; // May want to prevent certain operations on roots

343

}

344

return true;

345

}

346

}

347

```

348

349

### Input Dialog

350

351

Specialized dialog for workspace file/folder creation with path validation.

352

353

```typescript { .api }

354

class WorkspaceInputDialog extends SingleTextInputDialog {

355

constructor(

356

props: WorkspaceInputDialogProps,

357

labelProvider: LabelProvider

358

);

359

360

/**

361

* Append parent path information to dialog

362

*/

363

protected appendParentPath(): void;

364

}

365

366

class WorkspaceInputDialogProps extends SingleTextInputDialogProps {

367

/**

368

* The parent URI for the selection present in the explorer.

369

* Used to display the path in which the file/folder is created at.

370

*/

371

parentUri: URI;

372

}

373

```

374

375

## Types

376

377

```typescript { .api }

378

interface DidCreateNewResourceEvent {

379

/** The URI of the created resource */

380

uri: URI;

381

/** The URI of the parent directory */

382

parent: URI;

383

}

384

385

enum WorkspaceStates {

386

/** The state is `empty` when no workspace is opened */

387

empty = 'empty',

388

/** The state is `workspace` when a workspace is opened */

389

workspace = 'workspace',

390

/** The state is `folder` when a folder is opened (1 folder) */

391

folder = 'folder'

392

}

393

394

type WorkspaceState = keyof typeof WorkspaceStates;

395

type WorkbenchState = keyof typeof WorkspaceStates;

396

397

interface Command {

398

id: string;

399

category?: string;

400

label?: string;

401

iconClass?: string;

402

tooltip?: string;

403

}

404

405

interface UriCommandHandler<T> {

406

execute(uri: T, ...args: any[]): any;

407

isVisible?(uri: T, ...args: any[]): boolean;

408

isEnabled?(uri: T, ...args: any[]): boolean;

409

}

410

```