Skip to content

Commit

Permalink
Merge pull request #94 from krassowski/improve_rename_and_status
Browse files Browse the repository at this point in the history
Add message notifications to statusbar, tidy it up
  • Loading branch information
krassowski authored Nov 5, 2019
2 parents a53e071 + 8407292 commit b86cdb4
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { expect } from 'chai';
import { CodeMirrorAdapter } from './cm_adapter';
import { LSPConnection } from '../../connection';
import { IJupyterLabComponentsManager } from '../jupyterlab/jl_adapter';
import {
IJupyterLabComponentsManager,
StatusMessage
} from '../jupyterlab/jl_adapter';
import { IRootPosition } from '../../positioning';
import * as CodeMirror from 'codemirror';
import { CodeMirrorLSPFeature } from './feature';
Expand Down Expand Up @@ -41,7 +44,8 @@ describe('CodeMirrorAdapter', () => {
virtual_editor,
virtual_editor.virtual_document,
connection,
dummy_components_manager
dummy_components_manager,
new StatusMessage()
);

let adapter = new CodeMirrorAdapter(
Expand Down
22 changes: 15 additions & 7 deletions packages/jupyterlab-lsp/src/adapters/codemirror/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
IRootPosition,
IVirtualPosition
} from '../../positioning';
import { IJupyterLabComponentsManager } from '../jupyterlab/jl_adapter';
import {
IJupyterLabComponentsManager,
StatusMessage
} from '../jupyterlab/jl_adapter';

/// <reference path="../../../node_modules/@types/events/index.d.ts"/>
// this appears to break when @types/node is around
Expand Down Expand Up @@ -100,7 +103,8 @@ export class CodeMirrorLSPFeature implements ILSPFeature {
public virtual_editor: VirtualEditor,
public virtual_document: VirtualDocument,
public connection: LSPConnection,
public jupyterlab_components: IJupyterLabComponentsManager
public jupyterlab_components: IJupyterLabComponentsManager,
protected status_message: StatusMessage
) {
this.editor_handlers = new Map();
this.connection_handlers = new Map();
Expand Down Expand Up @@ -235,7 +239,9 @@ export class CodeMirrorLSPFeature implements ILSPFeature {
.markText(range.start, range.end, { className: class_name });
}

protected apply_edit(workspaceEdit: lsProtocol.WorkspaceEdit) {
protected async apply_edit(
workspaceEdit: lsProtocol.WorkspaceEdit
): Promise<number> {
console.log(workspaceEdit);
let current_uri = this.connection.getDocumentUri();
// Specs: documentChanges are preferred over changes
Expand All @@ -244,12 +250,12 @@ export class CodeMirrorLSPFeature implements ILSPFeature {
change => change as lsProtocol.TextDocumentEdit
)
: toDocumentChanges(workspaceEdit.changes);
let applied_changes = 0;
for (let change of changes) {
let uri = change.textDocument.uri;
if (uri !== current_uri) {
console.warn('Workspace-wide edits not implemented yet');
if (uri !== current_uri && uri !== '/' + current_uri) {
throw new Error('Workspace-wide edits not implemented yet');
} else {
// TODO: show "Renamed X to Y in {change.edits.length} places" in statusbar;
for (let edit of change.edits) {
let start = PositionConverter.lsp_to_cm(edit.range.start);
let end = PositionConverter.lsp_to_cm(edit.range.end);
Expand All @@ -261,13 +267,15 @@ export class CodeMirrorLSPFeature implements ILSPFeature {
end as IVirtualPosition
);
if (start_editor !== end_editor) {
console.log('Edits not implemented for notebooks yet');
throw new Error('Edits not implemented for notebooks yet');
} else {
applied_changes += 1;
let doc = start_editor.getDoc();
doc.replaceRange(edit.newText, start, end);
}
}
}
}
return applied_changes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ export class Rename extends CodeMirrorLSPFeature {
}

protected handleRename(workspaceEdit: lsProtocol.WorkspaceEdit) {
this.apply_edit(workspaceEdit);
this.apply_edit(workspaceEdit)
.catch(error => {
console.log(error);
this.status_message.set(`Rename failed: ${error}`);
})
.then(applied_changes => {
this.status_message.set(
`Renamed a variable in ${applied_changes} places`,
5 * 1000
);
})
.catch(console.warn);
}
}
8 changes: 6 additions & 2 deletions packages/jupyterlab-lsp/src/adapters/codemirror/testutils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { LSPConnection } from '../../connection';
import { CodeEditor } from '@jupyterlab/codeeditor';
import { VirtualFileEditor } from '../../virtual/editors/file_editor';
import { FreeTooltip } from '../jupyterlab/components/free_tooltip';
import { IJupyterLabComponentsManager } from '../jupyterlab/jl_adapter';
import {
IJupyterLabComponentsManager,
StatusMessage
} from '../jupyterlab/jl_adapter';

interface IFeatureTestEnvironment {
host: HTMLElement;
Expand Down Expand Up @@ -58,7 +61,8 @@ export class FeatureTestEnvironment implements IFeatureTestEnvironment {
this.virtual_editor,
this.virtual_editor.virtual_document,
connection,
dummy_components_manager
dummy_components_manager,
new StatusMessage()
);
this.connections.set(feature, connection);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class LSPStatus extends VDomRenderer<LSPStatus.Model> {
kind={'statusBar'}
/>
<TextItem source={this.model.short_message} />
<TextItem source={this.model.feature_message} />
</GroupItem>
);
}
Expand Down Expand Up @@ -111,6 +112,22 @@ function collect_languages(virtual_document: VirtualDocument): Set<string> {
return collected;
}

type StatusMap = Record<StatusCode, string>;

const iconByStatus: StatusMap = {
waiting: 'refresh',
initialized: 'running',
initializing: 'refresh',
connecting: 'refresh'
};

const shortMessageByStatus: StatusMap = {
waiting: 'Waiting...',
initialized: 'Fully initialized',
initializing: 'Fully connected & partially initialized',
connecting: 'Connecting...'
};

export namespace LSPStatus {
/**
* A VDomModel for the LSP of current file editor/notebook.
Expand Down Expand Up @@ -198,38 +215,18 @@ export namespace LSPStatus {
if (!this.adapter) {
return 'stop';
}
let status = this.status;

// TODO: associative array instead
if (status.status === 'waiting') {
return 'refresh';
} else if (status.status === 'initialized') {
return 'running';
} else if (status.status === 'initializing') {
return 'refresh';
} else if (status.status === 'connecting') {
return 'refresh';
}
return iconByStatus[this.status.status];
}

get short_message(): string {
if (!this.adapter) {
return 'not initialized';
}
let status = this.status;
return shortMessageByStatus[this.status.status];
}

let msg = '';
// TODO: associative array instead
if (status.status === 'waiting') {
msg = 'Waiting...';
} else if (status.status === 'initialized') {
msg = `Fully initialized`;
} else if (status.status === 'initializing') {
msg = `Fully connected & partially initialized`;
} else {
msg = `Connecting...`;
}
return msg;
get feature_message(): string {
return this.adapter ? this.adapter.status_message.message : '';
}

get long_message(): string {
Expand Down Expand Up @@ -276,6 +273,7 @@ export namespace LSPStatus {
get adapter(): JupyterLabWidgetAdapter | null {
return this._adapter;
}

set adapter(adapter: JupyterLabWidgetAdapter | null) {
const oldAdapter = this._adapter;
if (oldAdapter !== null) {
Expand All @@ -286,6 +284,7 @@ export namespace LSPStatus {
oldAdapter.connection_manager.documents_changed.disconnect(
this._onChange
);
oldAdapter.status_message.changed.connect(this._onChange);
}

let onChange = this._onChange.bind(this);
Expand All @@ -294,6 +293,7 @@ export namespace LSPStatus {
adapter.connection_manager.disconnected.connect(onChange);
adapter.connection_manager.closed.connect(onChange);
adapter.connection_manager.documents_changed.connect(onChange);
adapter.status_message.changed.connect(onChange);
this._adapter = adapter;
}

Expand Down
37 changes: 36 additions & 1 deletion packages/jupyterlab-lsp/src/adapters/jupyterlab/jl_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,38 @@ export interface IJupyterLabComponentsManager {
jumper: CodeJumper;
}

export class StatusMessage {
/**
* The text message to be shown on the statusbar
*/
message: string;
changed: Signal<StatusMessage, string>;

constructor() {
this.message = '';
this.changed = new Signal(this);
}

/**
* Set the text message and (optionally) the timeout to remove it.
* @param message
* @param timeout - number of ms to until the message is cleaned;
* -1 if the message should stay up indefinitely
*/
set(message: string, timeout?: number) {
this.message = message;
this.changed.emit('');
if (typeof timeout !== 'undefined' && timeout !== -1) {
setTimeout(this.cleanup.bind(this), timeout);
}
}

cleanup() {
this.message = '';
this.changed.emit('');
}
}

/**
* The values should follow the https://microsoft.github.io/language-server-protocol/specification guidelines
*/
Expand Down Expand Up @@ -82,6 +114,7 @@ export abstract class JupyterLabWidgetAdapter
protected abstract current_completion_connector: LSPConnector;
private _tooltip: FreeTooltip;
public connection_manager: DocumentConnectionManager;
public status_message: StatusMessage;

protected constructor(
protected app: JupyterFrontEnd,
Expand All @@ -90,6 +123,7 @@ export abstract class JupyterLabWidgetAdapter
invoke: string,
private server_root: string
) {
this.status_message = new StatusMessage();
this.widget.context.pathChanged.connect(this.reload_connection.bind(this));
this.invoke_command = invoke;
this.document_connected = new Signal(this);
Expand Down Expand Up @@ -299,7 +333,8 @@ export abstract class JupyterLabWidgetAdapter
this.virtual_editor,
virtual_document,
connection,
this
this,
this.status_message
);
adapter_features.push(feature);
}
Expand Down

0 comments on commit b86cdb4

Please sign in to comment.