Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin-2801: API endpoint for window.showTextDocument #3547

Merged
merged 1 commit into from
Nov 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/plugin-ext/src/api/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import { UriComponents } from '../common/uri-components';

// Should contains internal Plugin API types

export interface TextDocumentShowOptions {
selection?: Range;
}

export interface Range {
/**
* Line number on which the range starts (starts at 1).
Expand Down
5 changes: 3 additions & 2 deletions packages/plugin-ext/src/api/plugin-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ import {
Command,
TextEdit,
ReferenceContext,
Location
Location,
TextDocumentShowOptions
} from './model';

export interface PluginInitData {
Expand Down Expand Up @@ -627,7 +628,7 @@ export interface DocumentsExt {

export interface DocumentsMain {
$tryCreateDocument(options?: { language?: string; content?: string; }): Promise<UriComponents>;
$tryOpenDocument(uri: UriComponents): Promise<void>;
$tryOpenDocument(uri: UriComponents, options?: TextDocumentShowOptions): Promise<void>;
$trySaveDocument(uri: UriComponents): Promise<boolean>;
}

Expand Down
17 changes: 14 additions & 3 deletions packages/plugin-ext/src/main/browser/documents-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model
import { RPCProtocol } from '../../api/rpc-protocol';
import { EditorModelService } from './text-editor-model-service';
import { createUntitledResource } from './editor/untitled-resource';
import { EditorManager } from '@theia/editor/lib/browser';
import { EditorManager, EditorOpenerOptions } from '@theia/editor/lib/browser';
import URI from '@theia/core/lib/common/uri';
import { Saveable } from '@theia/core/lib/browser';
import { TextDocumentShowOptions } from '../../api/model';

export class DocumentsMainImpl implements DocumentsMain {

Expand Down Expand Up @@ -103,12 +104,22 @@ export class DocumentsMainImpl implements DocumentsMain {
return createUntitledResource(content, language);
}

async $tryOpenDocument(uri: UriComponents): Promise<void> {
async $tryOpenDocument(uri: UriComponents, options?: TextDocumentShowOptions): Promise<void> {
// Removing try-catch block here makes it not possible to handle errors.
// Following message is appeared in browser console
// - Uncaught (in promise) Error: Cannot read property 'message' of undefined.
try {
await this.editorManger.open(new URI(uri.external!));
let editorOpenerOptions: EditorOpenerOptions | undefined;
if (options && options.selection) {
const selection = options.selection;
editorOpenerOptions = {
selection: {
start: { line: selection.startLineNumber - 1, character: selection.startColumn - 1 },
end: { line: selection.endLineNumber - 1, character: selection.endColumn - 1 }
}
};
}
await this.editorManger.open(new URI(uri.external!), editorOpenerOptions);
} catch (err) {
throw new Error(err);
}
Expand Down
19 changes: 15 additions & 4 deletions packages/plugin-ext/src/plugin/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { DocumentDataExt, setWordDefinitionFor } from './document-data';
import { EditorsAndDocumentsExtImpl } from './editors-and-documents';
import * as Converter from './type-converters';
import { DisposableCollection } from '@theia/core/lib/common/disposable';
import { Range } from '../api/model';

export class DocumentsExtImpl implements DocumentsExt {
private toDispose = new DisposableCollection();
Expand Down Expand Up @@ -120,7 +121,7 @@ export class DocumentsExtImpl implements DocumentsExt {
return undefined;
}

async openDocument(uri: URI): Promise<DocumentDataExt | undefined> {
async openDocument(uri: URI, options?: theia.TextDocumentShowOptions): Promise<DocumentDataExt | undefined> {
const cached = this.editorsAndDocuments.getDocument(uri.toString());
if (cached) {
return cached;
Expand All @@ -135,7 +136,7 @@ export class DocumentsExtImpl implements DocumentsExt {

try {
// start opening document
const document = this.loadDocument(uri);
const document = this.loadDocument(uri, options);
// add loader to the map
this.loadingDocuments.set(uri.toString(), document);
// wait the document being opened
Expand All @@ -150,8 +151,18 @@ export class DocumentsExtImpl implements DocumentsExt {
}
}

private async loadDocument(uri: URI): Promise<DocumentDataExt | undefined> {
await this.proxy.$tryOpenDocument(uri);
private async loadDocument(uri: URI, options?: theia.TextDocumentShowOptions): Promise<DocumentDataExt | undefined> {
let range: Range | undefined;
if (options && options.selection) {
const { start, end } = options.selection;
range = {
startLineNumber: start.line,
startColumn: start.character,
endLineNumber: end.line,
endColumn: end.character
};
}
await this.proxy.$tryOpenDocument(uri, { selection: range });
return this.editorsAndDocuments.getDocument(uri.toString());
}

Expand Down
21 changes: 21 additions & 0 deletions packages/plugin-ext/src/plugin/plugin-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,27 @@ export function createAPIFactory(
onDidChangeTextEditorVisibleRanges(listener, thisArg?, disposables?) {
return editors.onDidChangeTextEditorVisibleRanges(listener, thisArg, disposables);
},
async showTextDocument(documentArg: theia.TextDocument | Uri,
optionsArg?: theia.TextDocumentShowOptions | theia.ViewColumn,
preserveFocus?: boolean
): Promise<theia.TextEditor> {
// Todo pass additional arguments to documents service, when the API will support them.
let documentOptions: theia.TextDocumentShowOptions | undefined;
const uri: Uri = documentArg instanceof Uri ? documentArg : documentArg.uri;
if (optionsArg) {
const optionsAny: any = optionsArg;
if (optionsAny.selection) {
documentOptions = optionsArg as theia.TextDocumentShowOptions;
}
}
await documents.openDocument(uri, documentOptions);
const textEditor = editors.getVisibleTextEditors().find(editor => editor.document.uri.toString() === uri.toString());
if (textEditor) {
return Promise.resolve(textEditor);
} else {
throw new Error(`Failed to show text document ${documentArg.toString()}`);
}
},
// tslint:disable-next-line:no-any
showQuickPick(items: any, options: theia.QuickPickOptions, token?: theia.CancellationToken): any {
if (token) {
Expand Down
64 changes: 64 additions & 0 deletions packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2365,6 +2365,40 @@ declare module '@theia/plugin' {
*/
export const onDidChangeTextEditorViewColumn: Event<TextEditorViewColumnChangeEvent>;

/**
* Show the given document in a text editor. A [column](#ViewColumn) can be provided
* to control where the editor is being shown. Might change the [active editor](#window.activeTextEditor).
*
* @param document A text document to be shown.
* @param column A view column in which the [editor](#TextEditor) should be shown. The default is the [active](#ViewColumn.Active), other values
* are adjusted to be `Min(column, columnCount + 1)`, the [active](#ViewColumn.Active)-column is not adjusted. Use [`ViewColumn.Beside`](#ViewColumn.Beside)
* to open the editor to the side of the currently active one.
* @param preserveFocus When `true` the editor will not take focus.
* @return A promise that resolves to an [editor](#TextEditor).
*/
export function showTextDocument(document: TextDocument, column?: ViewColumn, preserveFocus?: boolean): Thenable<TextEditor>;

/**
* Show the given document in a text editor. [Options](#TextDocumentShowOptions) can be provided
* to control options of the editor is being shown. Might change the [active editor](#window.activeTextEditor).
*
* @param document A text document to be shown.
* @param options [Editor options](#TextDocumentShowOptions) to configure the behavior of showing the [editor](#TextEditor).
* @return A promise that resolves to an [editor](#TextEditor).
*/
export function showTextDocument(document: TextDocument, options?: TextDocumentShowOptions): Thenable<TextEditor>;

/**
* A short-hand for `openTextDocument(uri).then(document => showTextDocument(document, options))`.
*
* @see [openTextDocument](#openTextDocument)
*
* @param uri A resource identifier.
* @param options [Editor options](#TextDocumentShowOptions) to configure the behavior of showing the [editor](#TextEditor).
* @return A promise that resolves to an [editor](#TextEditor).
*/
export function showTextDocument(uri: Uri, options?: TextDocumentShowOptions): Thenable<TextEditor>;

/**
* Shows a selection list.
* @param items
Expand Down Expand Up @@ -5463,4 +5497,34 @@ declare module '@theia/plugin' {
*/
export function registerDebugConfigurationProvider(debugType: string, provider: DebugConfigurationProvider): Disposable;
}

/**
* Represents options to configure the behavior of showing a [document](#TextDocument) in an [editor](#TextEditor).
*/
export interface TextDocumentShowOptions {
/**
* An optional view column in which the [editor](#TextEditor) should be shown.
* The default is the [active](#ViewColumn.Active), other values are adjusted to
* be `Min(column, columnCount + 1)`, the [active](#ViewColumn.Active)-column is
* not adjusted. Use [`ViewColumn.Beside`](#ViewColumn.Beside) to open the
* editor to the side of the currently active one.
*/
viewColumn?: ViewColumn;

/**
* An optional flag that when `true` will stop the [editor](#TextEditor) from taking focus.
*/
preserveFocus?: boolean;

/**
* An optional flag that controls if an [editor](#TextEditor)-tab will be replaced
* with the next editor or if it will be kept.
*/
preview?: boolean;

/**
* An optional selection to apply for the document in the [editor](#TextEditor).
*/
selection?: Range;
}
}