Skip to content

Commit

Permalink
Plugin-2801: API endpoint for window.showTextDocument
Browse files Browse the repository at this point in the history
Signed-off-by: Igor Vinokur <ivinokur@redhat.com>
  • Loading branch information
vinokurig committed Nov 21, 2018
1 parent 96ed159 commit 67d5876
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 9 deletions.
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;
}
}

0 comments on commit 67d5876

Please sign in to comment.