Skip to content

Commit

Permalink
Codicon color and URI support for TerminalOptions (#13413)
Browse files Browse the repository at this point in the history
Co-authored-by: FernandoAscencio <[email protected]>
Co-authored-by: Mark Sujew <[email protected]>
  • Loading branch information
3 people committed Jun 27, 2024
1 parent ba62f96 commit 9ae7640
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 157 deletions.
11 changes: 11 additions & 0 deletions packages/core/src/browser/style/tabs.css
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,17 @@
padding-right: 8px;
}

.p-TabBar.theia-app-centers .p-TabBar-tabIcon[class*="plugin-icon-"],
.p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon[class*="plugin-icon-"] {
background: none;
height: var(--theia-icon-size);
}

.p-TabBar.theia-app-centers .p-TabBar-tabIcon[class*="plugin-icon-"]::before,
.p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon[class*="plugin-icon-"]::before {
display: inline-block;
}

/* codicons */
.p-TabBar.theia-app-centers .p-TabBar-tabIcon.codicon,
.p-TabBar-tab.p-mod-drag-image .p-TabBar-tabIcon.codicon {
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/common/quick-pick-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import * as fuzzy from 'fuzzy';
import { Event } from './event';
import { KeySequence } from './keys';
import { CancellationToken } from './cancellation';
import { URI as Uri } from 'vscode-uri';

export const quickPickServicePath = '/services/quickPick';
export const QuickPickService = Symbol('QuickPickService');
Expand Down Expand Up @@ -53,7 +52,6 @@ export interface QuickPickItem {
description?: string;
detail?: string;
keySequence?: KeySequence;
iconPath?: { light?: Uri; dark: Uri };
iconClasses?: string[];
alwaysShow?: boolean;
highlights?: QuickPickItemHighlights;
Expand Down Expand Up @@ -94,7 +92,6 @@ export interface QuickPickValue<V> extends QuickPickItem {
}

export interface QuickInputButton {
iconPath?: { light?: Uri; dark: Uri };
iconClass?: string;
tooltip?: string;
/**
Expand Down
4 changes: 4 additions & 0 deletions packages/monaco/src/browser/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@
text-align: left;
}

.quick-input-list .monaco-icon-label::before {
height: 22px;
}

.codicon-file.default-file-icon.file-icon {
padding-left: 2px;
height: 22px;
Expand Down
22 changes: 12 additions & 10 deletions packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ export interface TerminalServiceMain {
* Create new Terminal with Terminal options.
* @param options - object with parameters to create new terminal.
*/
$createTerminal(id: string, options: theia.TerminalOptions, parentId?: string, isPseudoTerminal?: boolean): Promise<string>;
$createTerminal(id: string, options: TerminalOptions, parentId?: string, isPseudoTerminal?: boolean): Promise<string>;

/**
* Send text to the terminal by id.
Expand Down Expand Up @@ -469,6 +469,10 @@ export interface TerminalServiceMain {
$unregisterTerminalObserver(id: string): unknown;
}

export interface TerminalOptions extends theia.TerminalOptions {
iconUrl?: string | { light: string; dark: string } | ThemeIcon;
}

export interface AutoFocus {
autoFocusFirstEntry?: boolean;
// TODO
Expand Down Expand Up @@ -524,10 +528,10 @@ export interface QuickOpenExt {
$onDidChangeSelection(sessionId: number, handles: number[]): void;

/* eslint-disable max-len */
showQuickPick(itemsOrItemsPromise: Array<theia.QuickPickItem> | Promise<Array<theia.QuickPickItem>>, options: theia.QuickPickOptions & { canPickMany: true; },
showQuickPick(plugin: Plugin, itemsOrItemsPromise: Array<theia.QuickPickItem> | Promise<Array<theia.QuickPickItem>>, options: theia.QuickPickOptions & { canPickMany: true; },
token?: theia.CancellationToken): Promise<Array<theia.QuickPickItem> | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Promise<string[]>, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise<string | undefined>;
showQuickPick(itemsOrItemsPromise: Array<theia.QuickPickItem> | Promise<Array<theia.QuickPickItem>>, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise<theia.QuickPickItem | undefined>;
showQuickPick(plugin: Plugin, itemsOrItemsPromise: string[] | Promise<string[]>, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise<string | undefined>;
showQuickPick(plugin: Plugin, itemsOrItemsPromise: Array<theia.QuickPickItem> | Promise<Array<theia.QuickPickItem>>, options?: theia.QuickPickOptions, token?: theia.CancellationToken): Promise<theia.QuickPickItem | undefined>;

showInput(options?: theia.InputBoxOptions, token?: theia.CancellationToken): PromiseLike<string | undefined>;
// showWorkspaceFolderPick(options?: theia.WorkspaceFolderPickOptions, token?: theia.CancellationToken): Promise<theia.WorkspaceFolder | undefined>
Expand Down Expand Up @@ -651,7 +655,7 @@ export interface TransferQuickPickItem {
handle: number;
kind: 'item' | 'separator',
label: string;
iconPath?: UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon;
iconUrl?: string | { light: string; dark: string } | ThemeIcon;
description?: string;
detail?: string;
picked?: boolean;
Expand All @@ -675,7 +679,7 @@ export interface TransferQuickPickOptions<T extends TransferQuickPickItem> {

export interface TransferQuickInputButton {
handle?: number;
readonly iconPath: UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon;
readonly iconUrl?: string | { light: string; dark: string } | ThemeIcon;
readonly tooltip?: string | undefined;
}

Expand Down Expand Up @@ -1514,12 +1518,10 @@ export interface WorkspaceEditEntryMetadataDto {
needsConfirmation: boolean;
label: string;
description?: string;
iconPath?: {
id: string;
} | {
iconPath?: ThemeIcon | {
light: UriComponents;
dark: UriComponents;
} | ThemeIcon;
};
}

export interface WorkspaceFileEditDto {
Expand Down
68 changes: 23 additions & 45 deletions packages/plugin-ext/src/main/browser/quick-open-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,21 @@ import { DisposableCollection, Disposable } from '@theia/core/lib/common/disposa
import { CancellationToken } from '@theia/core/lib/common/cancellation';
import { MonacoQuickInputService } from '@theia/monaco/lib/browser/monaco-quick-input-service';
import { QuickInputButtons } from '../../plugin/types-impl';
import * as monaco from '@theia/monaco-editor-core';
import { UriComponents } from '../../common/uri-components';
import { URI } from '@theia/core/shared/vscode-uri';
import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables';
import { isUriComponents } from '@theia/monaco-editor-core/esm/vs/base/common/uri';
import { PluginSharedStyle } from './plugin-shared-style';
import { QuickPickSeparator } from '@theia/core';

export interface QuickInputSession {
input: QuickInput;
handlesToItems: Map<number, QuickPickItemOrSeparator>;
}

interface IconPath {
dark: URI,
light?: URI
};

export class QuickOpenMainImpl implements QuickOpenMain, Disposable {

private quickInputService: QuickInputService;
private proxy: QuickOpenExt;
private delegate: MonacoQuickInputService;
private sharedStyle: PluginSharedStyle;
private readonly items: Record<number, {
resolve(items: QuickPickItemOrSeparator[]): void;
reject(error: Error): void;
Expand All @@ -75,6 +68,7 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable {
this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.QUICK_OPEN_EXT);
this.delegate = container.get(MonacoQuickInputService);
this.quickInputService = container.get(QuickInputService);
this.sharedStyle = container.get(PluginSharedStyle);
}

dispose(): void {
Expand Down Expand Up @@ -111,25 +105,21 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable {
return item?.kind === 'item';
}

private normalizeIconPath(path: UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon | undefined): {
iconPath?: IconPath
iconClasses?: string[]
} {
let iconClasses;
private toIconClasses(path: { light: string; dark: string } | ThemeIcon | string | undefined): string[] {
const iconClasses: string[] = [];
if (ThemeIcon.isThemeIcon(path)) {
const codicon = codiconArray(path.id);
iconClasses = codicon;
}
let iconPath;
if (isUriComponents(path)) {
iconPath = { dark: URI.from(path) };
} else if (path && 'dark' in path) {
iconPath = { dark: URI.from(path.dark), light: URI.from(path.light) };
iconClasses.push(...codicon);
} else if (path) {
const iconReference = this.sharedStyle.toIconClass(path);
this.toDispose.push(iconReference);
iconClasses.push(iconReference.object.iconClass);
}
return {
iconPath,
iconClasses
};
return iconClasses;
}

private toIconClass(path: { light: string; dark: string } | ThemeIcon | string | undefined): string {
return this.toIconClasses(path).join(' ');
}

private toQuickPickItem(item: undefined): undefined;
Expand All @@ -146,13 +136,13 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable {
};
}
return {
...this.normalizeIconPath(item.iconPath),
type: 'item',
id: item.handle.toString(),
label: item.label,
description: item.description,
detail: item.detail,
alwaysShow: item.alwaysShow,
iconClasses: this.toIconClasses(item.iconUrl),
buttons: item.buttons ? this.convertToQuickInputButtons(item.buttons) : undefined
};
}
Expand Down Expand Up @@ -338,24 +328,12 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable {
if (button.handle === -1) {
return this.quickInputService.backButton;
}
const { iconPath, tooltip, handle } = button;
if ('id' in iconPath) {
return {
iconClass: ThemeIcon.asClassName(iconPath),
tooltip,
handle
};
} else {
const monacoIconPath = (iconPath as unknown as { light: monaco.Uri, dark: monaco.Uri });
return {
iconPath: {
dark: monaco.Uri.revive(monacoIconPath.dark),
light: monacoIconPath.light && monaco.Uri.revive(monacoIconPath.light)
},
tooltip,
handle
};
}
const { iconUrl, tooltip, handle } = button;
return {
tooltip,
handle,
iconClass: this.toIconClass(iconUrl)
};
});
} else {
(input as any)[param] = params[param];
Expand All @@ -381,7 +359,7 @@ export class QuickOpenMainImpl implements QuickOpenMain, Disposable {

private convertToQuickInputButtons(buttons: readonly TransferQuickInputButton[]): QuickInputButton[] {
return buttons.map((button, i) => ({
...this.normalizeIconPath(button.iconPath),
iconClass: this.toIconClass(button.iconUrl),
tooltip: button.tooltip,
handle: button === QuickInputButtons.Back ? -1 : i,
} as QuickInputButton));
Expand Down
32 changes: 26 additions & 6 deletions packages/plugin-ext/src/main/browser/terminal-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,22 @@
// *****************************************************************************

import { interfaces } from '@theia/core/shared/inversify';
import { ApplicationShell, WidgetOpenerOptions } from '@theia/core/lib/browser';
import { TerminalEditorLocationOptions, TerminalOptions } from '@theia/plugin';
import { ApplicationShell, WidgetOpenerOptions, codicon } from '@theia/core/lib/browser';
import { TerminalEditorLocationOptions } from '@theia/plugin';
import { TerminalLocation, TerminalWidget } from '@theia/terminal/lib/browser/base/terminal-widget';
import { TerminalProfileService } from '@theia/terminal/lib/browser/terminal-profile-service';
import { TerminalService } from '@theia/terminal/lib/browser/base/terminal-service';
import { TerminalServiceMain, TerminalServiceExt, MAIN_RPC_CONTEXT } from '../../common/plugin-api-rpc';
import { TerminalServiceMain, TerminalServiceExt, MAIN_RPC_CONTEXT, TerminalOptions } from '../../common/plugin-api-rpc';
import { RPCProtocol } from '../../common/rpc-protocol';
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
import { SerializableEnvironmentVariableCollection, ShellTerminalServerProxy } from '@theia/terminal/lib/common/shell-terminal-protocol';
import { TerminalLink, TerminalLinkProvider } from '@theia/terminal/lib/browser/terminal-link-provider';
import { URI } from '@theia/core/lib/common/uri';
import { getIconClass } from '../../plugin/terminal-ext';
import { PluginTerminalRegistry } from './plugin-terminal-registry';
import { CancellationToken } from '@theia/core';
import { CancellationToken, isObject } from '@theia/core';
import { HostedPluginSupport } from '../../hosted/browser/hosted-plugin';
import { PluginSharedStyle } from './plugin-shared-style';
import { ThemeIcon } from '@theia/core/lib/common/theme';
import debounce = require('@theia/core/shared/lodash.debounce');

interface TerminalObserverData {
Expand All @@ -49,6 +50,7 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
private readonly hostedPluginSupport: HostedPluginSupport;
private readonly shell: ApplicationShell;
private readonly extProxy: TerminalServiceExt;
private readonly sharedStyle: PluginSharedStyle;
private readonly shellTerminalServer: ShellTerminalServerProxy;
private readonly terminalLinkProviders: string[] = [];

Expand All @@ -60,6 +62,7 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
this.terminalProfileService = container.get(TerminalProfileService);
this.pluginTerminalRegistry = container.get(PluginTerminalRegistry);
this.hostedPluginSupport = container.get(HostedPluginSupport);
this.sharedStyle = container.get(PluginSharedStyle);
this.shell = container.get(ApplicationShell);
this.shellTerminalServer = container.get(ShellTerminalServerProxy);
this.extProxy = rpc.getProxy(MAIN_RPC_CONTEXT.TERMINAL_EXT);
Expand Down Expand Up @@ -153,7 +156,7 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
const terminal = await this.terminals.newTerminal({
id,
title: options.name,
iconClass: getIconClass(options),
iconClass: this.toIconClass(options),
shellPath: options.shellPath,
shellArgs: options.shellArgs,
cwd: options.cwd ? new URI(options.cwd) : undefined,
Expand Down Expand Up @@ -329,6 +332,23 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
}));
}

protected toIconClass(options: TerminalOptions): string | ThemeIcon | undefined {
const iconColor = isObject<{ id: string }>(options.color) && typeof options.color.id === 'string' ? options.color.id : undefined;
let iconClass: string;
if (options.iconUrl) {
if (typeof options.iconUrl === 'object' && 'id' in options.iconUrl) {
iconClass = codicon(options.iconUrl.id);
} else {
const iconReference = this.sharedStyle.toIconClass(options.iconUrl);
this.toDispose.push(iconReference);
iconClass = iconReference.object.iconClass;
}
} else {
iconClass = codicon('terminal');
}
return iconColor ? { id: iconClass, color: { id: iconColor } } : iconClass;
}

$unregisterTerminalObserver(id: string): void {
const observer = this.observers.get(id);
if (observer) {
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ export function createAPIFactory(
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
showQuickPick(items: any, options?: theia.QuickPickOptions, token?: theia.CancellationToken): any {
return quickOpenExt.showQuickPick(items, options, token);
return quickOpenExt.showQuickPick(plugin, items, options, token);
},
createQuickPick<T extends theia.QuickPickItem>(): theia.QuickPick<T> {
return quickOpenExt.createQuickPick(plugin);
Expand Down Expand Up @@ -564,7 +564,7 @@ export function createAPIFactory(
createTerminal(nameOrOptions: theia.TerminalOptions | theia.ExtensionTerminalOptions | theia.ExtensionTerminalOptions | (string | undefined),
shellPath?: string,
shellArgs?: string[] | string): theia.Terminal {
return terminalExt.createTerminal(nameOrOptions, shellPath, shellArgs);
return terminalExt.createTerminal(plugin, nameOrOptions, shellPath, shellArgs);
},
onDidChangeTerminalState,
onDidCloseTerminal,
Expand Down
7 changes: 5 additions & 2 deletions packages/plugin-ext/src/plugin/plugin-icon-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export type PluginIconPath = string | URI | {
dark: string | URI
};
export namespace PluginIconPath {
export function toUrl(iconPath: PluginIconPath | undefined, plugin: Plugin): IconUrl | undefined {
if (!iconPath) {
export function toUrl(iconPath: unknown, plugin: Plugin): IconUrl | undefined {
if (!is(iconPath)) {
return undefined;
}
if (typeof iconPath === 'object' && 'light' in iconPath) {
Expand All @@ -36,6 +36,9 @@ export namespace PluginIconPath {
}
return asString(iconPath, plugin);
}
export function is(item: unknown): item is PluginIconPath {
return typeof item === 'string' || item instanceof URI || typeof item === 'object' && !!item && 'light' in item && 'dark' in item;
}
export function asString(arg: string | URI, plugin: Plugin): string {
arg = arg instanceof URI && arg.scheme === 'file' ? arg.fsPath : arg;
if (typeof arg !== 'string') {
Expand Down
Loading

0 comments on commit 9ae7640

Please sign in to comment.