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

Split terminal widget(browser) logic #4518

Closed
wants to merge 44 commits into from

Conversation

AndrienkoAleksandr
Copy link
Contributor

@AndrienkoAleksandr AndrienkoAleksandr commented Mar 10, 2019

Referenced issue:

#4523
eclipse-che/che#12609

Split terminal widget(browser) logic

Requested changes:

Split terminal widget logic into two components: TerminalWidget and TerminalClient:

  • TerminalWidget - contains logic to configure and create new terminal widget and methods to manipulate with this widget.
  • TerminalClient - create connection with terminal backend and manage terminal widget; encapsulate theia backend connection specific logic(to have ability simplier rebind terminal widget to non default back-end).
  1. Remove using in the extensions depracated method activateTerminal.
  2. Resolve an issue : task widget should display title with label task, not terminal!!!
  3. Simplify imports for @theia/terminal and @theia/xterm.js browser package.

Breaking stuff:

Depracate terminalWidget.start() method. This method has too tricky behavior. I think this methods does too much operations with too much cases. I propose to split this method onto two separated:

  1. createAndAttach()
  2. attach()

Benefits(or why do we need this...)

  1. Split code base.
  2. It's useful for terminal plugin api. We could provide in the plugin api method to create new terminal widget without connection to the Theia specific backend. And user could define own connection logic(to the own backend) in the Theia plugin.

Notice for future: this pull request it's a first step: split logic. Second step(next pull request): introduce ability to create terminal widget with help plugin api.

Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
Signed-off-by: Oleksandr Andriienko <[email protected]>
@akosyakov
Copy link
Member

akosyakov commented Mar 11, 2019

Don't you use xterm anymore? Why a new extension is created for it? It seems this PR is attempt to abstract away connection logic, not a concrete terminal implementation.

I've never liked a separation between TerminalWidget and TerminalWidgetImpl. This PR takes separation one step farther without any reasons. It could be as simple like TerminalWidget (one class with interface and implementation parts) -> Terminal (interface) if we wanted to abstract a concrete terminal.

cc @svenefftinge

* @param cols - amount displayed columns in the output frame.
* @param rows - amount displayed rows in the output frame.
*/
resize(size: TerminalSize): Promise<void>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is never used in TerminalWidget, why is it exposed?

/**
* Kill backend process.
*/
kill(): Promise<void>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's never used in TerminalWidget. Why is it exposed?

}
}));

this.toDispose.push(this.widget.onTerminalResize(size => this.resize(size)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not this code always be in TerminalWidget?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could You elaborate more information, please? You against dispose of resize subscription? Or Do you want that terminal widget call TerminalClient#resize?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akosyakov
Copy link
Member

We could provide in the plugin api method to create new terminal widget without connection to the Theia specific backend.

Could you elaborate on it? Do you want to connect to an alternative backend in Eclipse Che?

@benoitf
Copy link
Contributor

benoitf commented Mar 11, 2019

For now in Eclipse Che there is a fork of the Theia terminal extension. (To have multi remote terminal access). The idea is to move some logic to be re-used so it can work with different endpoints like endpoint = host running theia or a different endpoint (all containers in Eclipse Che).

@AndrienkoAleksandr
Copy link
Contributor Author

AndrienkoAleksandr commented Mar 11, 2019

Don't you use xterm anymore? Why a new extension is created for it? It seems this PR is attempt to abstract away connection logic, not a concrete terminal implementation.
I've never liked a separation between TerminalWidget and TerminalWidgetImpl. This PR takes separation one step farther without any reasons. It could be as simple like TerminalWidget (one class with interface and implementation parts) -> Terminal (interface) if we wanted to abstract a concrete terminal.
cc @svenefftinge

If you against this changes, I could revert it. But for me it's not bad if somebody with minimal changes could integrate some another terminal widget #1204 .

@AndrienkoAleksandr
Copy link
Contributor Author

It seems this PR is attempt to abstract away connection logic, not a concrete terminal implementation.

Yes, it's really "attempt" to split connection logic. And I didn't intergrate all wanted changes for better split, because for that I need change terminal restore logic, it's possible, but it could be buggy. So for this step I did minimal changes for split logic + moving xterm.js to the separated extension.

@AndrienkoAleksandr
Copy link
Contributor Author

Don't you use xterm anymore?

We still want to use xterm.js. It's nice widget, and it become better and better.

@akosyakov
Copy link
Member

akosyakov commented Mar 11, 2019

If you against this changes, I could revert it. But for me it's not bad if somebody with minimal changes could integrate some another terminal widget #1204 .

The point is that it should be done differently. TerminalWidget should be the same, there should be a new Terminal interface used by TerminalWidget. xterm/domtermn extensions should only implement Terminal interface. It is how it is done for editor. Not like in this PR.

Yes, it's really "attempt" to split connection logic.

please make this PR about it and revert all other unnecessary changes

Signed-off-by: Oleksandr Andriienko <[email protected]>
@AndrienkoAleksandr
Copy link
Contributor Author

please make this PR about it and revert all other unnecessary changes

Reverted xterm.js extension. Should I revert something else?

#4518 (comment) sorry, apply more information, please, I didn't understood what did you mean.


private terminalClient: TerminalClient;

protected readonly _onTerminalDidClose = new Emitter<TerminalWidget>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove, renaming protected properties is a breaking change, please keep names there it is possible.

protected init(): void {
this.toDispose.push(this.terminalWatcher.onTerminalError(({ terminalId, error }) => {
if (terminalId === this.terminalId) {
this.dispose();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before it will always fire close event, the same for onTerminalExit

@akosyakov
Copy link
Member

Reverted xterm.js extension. Should I revert something else?

the change should be minimal as possible with minimal breaking changes. terminal is quite central thing to break it.

* - resize backend output frame(in case if backend support it);
*/
export const TerminalClient = Symbol('TerminalClient');
export interface TerminalClient extends Disposable {
Copy link
Member

@akosyakov akosyakov Mar 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure about naming, TerminalClient is something which provide an access to a terminal, it is TerminalConnection to me, or TerminalServer

/**
* Terminal widget which is under TerminalClient control.
*/
readonly widget: TerminalWidget;
Copy link
Member

@akosyakov akosyakov Mar 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's very weird that there is a cycle dependency between TerminalClient and TerminalWidget

I would try to see whether one can get rid of a dependency to a terminal widget from the terminal client by changing the interface and moving code from a client to a widget.

/**
* Create new process and attach terminal widget to this process.
*/
createAndAttach(): Promise<number>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would call it launch, similar to debugging

* @param createNewTerminalOnFaill - spawn new process in case if
* target process was not found by terminalId or it's gone. NOTICE: False by default.
*/
attach(terminalId: number, createNewTerminalOnFail?: boolean): Promise<number>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would use an object as a second arg to provide extensible options

/*
* Send event on terminal resize.
*/
abstract onTerminalResize: Event<TerminalSize>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on[Did/Will]Verb(Noun)? is how events should be named

private terminalClient: TerminalClient;

protected readonly _onTerminalDidClose = new Emitter<TerminalWidget>();
protected readonly _onUserInput = new Emitter<string | undefined>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also please study naming conventions, we use _ only in some cases

@AndrienkoAleksandr
Copy link
Contributor Author

AndrienkoAleksandr commented Nov 20, 2019

Close like to much outdated and some time ago it was canceled due priority. And VSCode already has such thing like we wanted https://github.com/microsoft/vscode/blob/master/src/vs/vscode.d.ts#L7518

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants