Skip to content

Fix debounce and add onData listener#31155

Merged
Tyriar merged 10 commits intomasterfrom
amqi/update-window-shellname
Jul 28, 2017
Merged

Fix debounce and add onData listener#31155
Tyriar merged 10 commits intomasterfrom
amqi/update-window-shellname

Conversation

@Lixire
Copy link
Contributor

@Lixire Lixire commented Jul 20, 2017

  • Now listens to enter and onData (fires if the event has not been called for at least 100ms)

Refer to #30152 for details

Copy link
Member

@Tyriar Tyriar left a comment

Choose a reason for hiding this comment

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

Please link the issue on the PR, it has a description of the timer system we want for onData

debounceEvent(this._onCheckWindowsShell.event, (l, e) => e, 100, true)(() => {
this.checkWindowShell();
});
this.onData(() => this._onCheckWindowsShell.fire());
Copy link
Member

Choose a reason for hiding this comment

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

I think we need a new mechanism for onData. Currently if a command runs for 10 seconds, it will launch 10/0.1=100 processes during its lifetimes. Instead of debounce like on enter we need something that will go off when the output has finished coming in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doesn't debounce reset the timer whenever the function gets called again?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm 90% sure it does

Copy link
Member

Choose a reason for hiding this comment

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

You're right I got a little confused there. But doesn't that mean it will not fire at the beginning if output is returned within 100ms because onEnter is being debounced on the same event? We might actually want to throttle onEnter (fire immediate, but no more than every 100ms), and debounce onData (fire when output stops for 100ms).

It also occurs to me that onData will fire when you press any key while typing in the prompt which probably isn't what we want. Imagine typing "a" (wait 150ms) "b" (wait 150ms) "c": that would fire 3 processes because of the onData handler.

A more efficient approach could be to hook into when a new line is started in the terminal, this would require some new API in xterm.js though. You could probably test out the approach by monkey patching xterm.js temporarily to see if it does what we want. Something like this:

const originalLineFeed = (<any>this._xterm).inputHandler.lineFeed;
(<any>this._xterm).inputHandler.lineFeed = function () {
  // ...fire event...
  originalLineFeed();
}

@Tyriar Tyriar added this to the July 2017 milestone Jul 20, 2017
Tyriar added a commit that referenced this pull request Jul 25, 2017
Bring in lineFeed event for #30152, #31155
@Lixire Lixire force-pushed the amqi/update-window-shellname branch from e39e0a5 to 1929b35 Compare July 25, 2017 20:58
@Lixire Lixire requested a review from roblourens July 27, 2017 22:56
debounceEvent(this._onCheckWindowsShell.event, (l, e) => e, 200, true)(() => {
setTimeout(() => {
this.checkWindowShell();
}, 50);
Copy link
Member

Choose a reason for hiding this comment

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

I think you explained why there was a setTimeout inside the debounce, but I forget why, a comment would be nice

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I gotchu

@roblourens
Copy link
Member

roblourens commented Jul 28, 2017

Not sure whether the CI ❌ 's are from your changes? Can you try to get it back to ✅ ?

@Lixire
Copy link
Contributor Author

Lixire commented Jul 28, 2017

Fixed the tests, @roblourens

@Tyriar
Copy link
Member

Tyriar commented Jul 28, 2017

The current failure looks unrelated.

this._createProcess(this._shellLaunchConfig);
this._createXterm();
if (this._shellLaunchConfig) {
this.setTitle(path.basename(this._shellLaunchConfig.executable), true);
Copy link
Member

Choose a reason for hiding this comment

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

If this._shellLaunchConfig.name is set, we do not want to do this.

Also this applies to Linux/macOS too, I don't think we use basename for non-Windows yet. This also doesn't strip .exe, we should rely on the basename/.exe strip code inside setTitle.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True

this.checkWindowShell();
});
this._xterm.on('lineFeed', () => this._onCheckWindowsShell.fire());
this._xterm.on('keypress', () => this._onCheckWindowsShell.fire());
Copy link
Member

Choose a reason for hiding this comment

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

If we're doing this here we still need the enter check and the this._messageTitleListener check.

Copy link
Contributor Author

@Lixire Lixire Jul 28, 2017

Choose a reason for hiding this comment

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

Actually, I check this._messageTitleListener in the method. For the keypress, won't lineFeed suffice? I think for the enter spam, the debounced event will suffice?

this.setTitle(path.basename(this._shellLaunchConfig.executable), true);
}

if (platform.isWindows) {
Copy link
Member

Choose a reason for hiding this comment

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

This is getting very large, can we instead pass this._xterm to WindowsShellHelper and do everything in there? Encapsulating all this logic into WindowsShellHelper would be best as it's Windows specific and TerminalInstance is already quite large and complex.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This solves the blank flickering that appears on Mac as well as the undefined in Windows.

Copy link
Member

Choose a reason for hiding this comment

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

But if mac's executable is set to /bin/bash, it might be bash -> /bin/bash (some time in the future)?

Copy link
Member

Choose a reason for hiding this comment

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

But that's more for the comment above. This one is pointing at the if (platform.Windows) section being too large

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh, fair

Copy link
Member

@Tyriar Tyriar left a comment

Choose a reason for hiding this comment

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

Just a few more small comments and good to go!

private _onDataForApi: Emitter<{ instance: ITerminalInstance, data: string }>;
private _onProcessIdReady: Emitter<TerminalInstance>;
private _onTitleChanged: Emitter<string>;
private _onCheckWindowsShell: Emitter<TPromise<string>>;
Copy link
Member

Choose a reason for hiding this comment

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

Can be removed

import * as platform from 'vs/base/common/platform';
import * as dom from 'vs/base/browser/dom';
import Event, { Emitter } from 'vs/base/common/event';
import Event, { Emitter, debounceEvent } from 'vs/base/common/event';
Copy link
Member

Choose a reason for hiding this comment

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

Can be removed

this._createProcess(this._shellLaunchConfig);
this._createXterm();

if (this._shellLaunchConfig && !this._shellLaunchConfig.name) {
Copy link
Member

Choose a reason for hiding this comment

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

Let's move this into _createProcess, just before this._messageTitleListener is set. That way it's right next to the part that sets it for _shellLaunchConfig.name.

private _rootProcessId: number;
private _terminalInstance: ITerminalInstance;
private _onCheckShell: Emitter<TPromise<string>>;
private _xterm: any;
Copy link
Member

Choose a reason for hiding this comment

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

Pull in the type using import XTermTerminal = require('xterm');

@Tyriar Tyriar merged commit 2746e2f into master Jul 28, 2017
@Tyriar Tyriar deleted the amqi/update-window-shellname branch July 28, 2017 21:27
@github-actions github-actions bot locked and limited conversation to collaborators Mar 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants