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

GH-73: Implemented editor navigation history. #1649

Merged
merged 1 commit into from
Apr 11, 2018
Merged

GH-73: Implemented editor navigation history. #1649

merged 1 commit into from
Apr 11, 2018

Conversation

kittaakos
Copy link
Contributor

Notes:

  • Currently, a location does not get removed when the corresponding file resource is deleted. That would require introducing @theia/filesystem in @theia/editor.
  • When an editor has multiple selections, the navigation service handles only the first content change.

Closes #73.

Signed-off-by: Akos Kitta [email protected]

@kittaakos kittaakos requested a review from svenefftinge April 4, 2018 13:18
/**
* Checks whether the service can go [`forward`](#forward).
*/
canGoFroward(): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

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

Small typo! Froward -> Forward

}

async onStart(): Promise<void> {
this.restoreState();
Copy link
Member

Choose a reason for hiding this comment

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

await?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 We can do that; I left it out intentionally.

Copy link
Member

Choose a reason for hiding this comment

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

ok, i mostly was wondering whether it should have the same lifecycle as a layout. For example, in Atom there are hooks to store and restore data, we have it only for the layout. And Atom decides when it is a good time to store and restore. In our case it seems to be a responsibility of the extension developer. It could be bad in the long run for example if we change when the data should be stored on the shutdown then each extension should be updated. I will open an issue to discuss it separately.

Copy link
Member

Choose a reason for hiding this comment

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

In this case, would it make sense to store the state only onStop similar how we store the layout data?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great idea, thanks! I was also wondering if we could do something like this in the FrontendApplication#startContributions:

await Promise.all(this.contributions.getContributions().filter(c => !!c.onStart).map(c => c.onStart!(this)));

Instead of starting each contribution one by one and wait for them (if it is a Promise). We just need to handle errors properly, and not fail fast.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright, let's leave as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case, would it make sense to store the state only onStop similar how we store the layout data?

It raises a question; FrontendApplicationContribution#onStop says: Note that this is implemented using `window.unload` which doesn't allow any asynchronous code anymore.. Still, we call async code from onStop, for instance: WorkspaceService. Do we still want to go with this approach? It does not seem to be safe.

In a nutshell: this.storageService.setData is async and we should not call it from window.unload.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could have a sync API on the StorageService.

Copy link
Member

Choose a reason for hiding this comment

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

In a nutshell: this.storageService.setData is async and we should not call it from window.unload.

It is fine, it is implemented with LocalStorage which is synchronous. Maybe we should make StorageService synchronous as well. Let's keep the discussion in #1671. It is not in the scope of this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK.

@akosyakov
Copy link
Member

Currently, a location does not get removed when the corresponding file resource is deleted. That would require introducing @theia/filesystem in @theia/editor.

We have a change event on a resource already. We can refine it to provide a change kind so clients can react on it, like mark an editor as deleted and remove a history location. Let's tackle it separately.

import { NavigationLocationService } from './navigation/navigation-location-service';

@injectable()
export class EditorNavigationContribution implements Disposable, MenuContribution, CommandContribution, KeybindingContribution, FrontendApplicationContribution {
Copy link
Member

@akosyakov akosyakov Apr 9, 2018

Choose a reason for hiding this comment

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

We have EditorContribution. Would it make sense to merge this contribution into it? I think it is nice to have all constants for commands, menus provided by the extension in one place.

I don't mean to merge completely EditorContribution only registration of commands, menus and so on. Implementation can still live in something like EditorNavigationService and be called from EditorContribution.

What do you think?

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 am OK with both ways. If you prefer moving the editor navigation contribution there, we can do it.

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 up to you. My main concern is to avoid spreading extension constants.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 Sure, as I said, I am OK with both, if you feel it is better, we can do it. It's a minor work.

@akosyakov
Copy link
Member

I've tested it, not extensively, only for my cases. It works nicely for them. Code looks great as well.

svenefftinge
svenefftinge previously approved these changes Apr 9, 2018
@kittaakos
Copy link
Contributor Author

kittaakos commented Apr 9, 2018

TODOs before merge:

  • Fix typo.
  • Add await.
  • Move the navigation contribution to the editor contribution.
  • Rebase.
  • storing the state once on onStop lifecycle hook? - Anton

@kittaakos
Copy link
Contributor Author

I have made a few changes based on your feedback, the review is obsolete. Could someone please approve it again? Thanks!

@simark simark requested a review from MarkZ3 April 9, 2018 22:24
akosyakov
akosyakov previously approved these changes Apr 10, 2018
* Returns with the number of navigation locations that the application can handle and manage.
* When the number of locations exceeds this number, old locations will be erased.
*/
maxStackItems(): number {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just looked through the code again; this should be protected.

@kittaakos
Copy link
Contributor Author

@simark, you have requested another review, shall we wait for that or are we good with this state?

@simark
Copy link
Contributor

simark commented Apr 10, 2018

It was just because @MarkZ3 was actively waiting for this feature (if it is really what I think it is), so i thought he might want to give it a try. But if others are happy, go ahead, it's not like everything is set in stone after that.

@kittaakos
Copy link
Contributor Author

OK. I have pushed a small change so the review became stale. I have reduced the implicit public visibility to protected. Others have already reviewed and approved it. @MarkZ3, if you have time, please try it out and approve it.

You should be able to navigate back with Ctrl+- and forward with Ctrl+Shift+-, just like in VSCode.

We ignore navigation location changes if those happen within +- 10 lines to the previous location. (Just like in VSCode).

@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 10, 2018

@MarkZ3, if you have time, please try it out and approve it.

@kittaakos Sure, I'll give this a try in the next couple of hours.

@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 10, 2018

The keyboard binding for "back" doesn't seem to work in Electron: when I do Ctrl+-, it zooms out (as it should??). I also don't see the command in the command palette. I typed "previous" and "back". I ended up noticing it in the main menu, under "Go", there I see that there is no keyboard mapping for back but there is for forward. Indeed, "forward" seems to work with the keyboard, but "back" only works through the menu. This is on Ubuntu BTW.
Probably the menu items should be greyed out when you cannot go forward or backwards anymore.

In the browser version, the menu items gray out properly and both shortcut are displayed in the menu. But similarly, the back keyboard binding zooms out.

Very excited to be able to use this BTW!

@kittaakos
Copy link
Contributor Author

The keyboard binding for "back" doesn't seem to work in Electron: when I do Ctrl+-, it zooms out (as it should??).

I will verify this and will get rid of the keybinding collision on Ubuntu. Perhaps, the same problem present on Windows.

I also don't see the command in the command palette.

That is on purpose, but I can add it if you think it could be useful. Please do not take the current zoom in/out problem into account for now.

there is no keyboard mapping for back but there is for forward

That should be an electron bug; I will open a follow-up for that.

Probably the menu items should be greyed out when you cannot go forward or backwards anymore.

#446

Thanks for the review!

@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 10, 2018

That is on purpose, but I can add it if you think it could be useful.

I think it makes sense. I see back/forward at the same level of other navigation commands like "go to definition". That's how I tried to find them at first. They are in the command palette in VS code too.

BTW, I would think only the "keybinding collision" is really blocking, the rest can be addressed in different patches/issues.

@kittaakos
Copy link
Contributor Author

I think it makes sense.

Roger that. I will add it.

the "keybinding collision" is really blocking

I agree.

@kittaakos
Copy link
Contributor Author

The command label should be qualified:

  • Go Back and
  • Go Forward

just like in VSCode.

@kittaakos
Copy link
Contributor Author

We will go with Alt+ (to Go Back) and Alt+ (to Go Forward) for now.

@kittaakos
Copy link
Contributor Author

I have verified on OS X (both on electron and browser) and on Windows too:

screen shot 2018-04-11 at 15 27 41

screen shot 2018-04-11 at 15 00 03

screen shot 2018-04-11 at 14 59 38

@MarkZ3, could you please try it out on Linux? Thanks!

@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 11, 2018

@MarkZ3, could you please try it out on Linux? Thanks!

@kittaakos I just tested it and it seems to work well!

I'm personally not a big fan of how it works in VSCode because I think the history is a bit too detailed, and it seems to be similar here. But I would very much like to see this current proposal merged because it is very useful and later I can propose some tweaks or some preference.

@kittaakos
Copy link
Contributor Author

history is a bit too detailed

We could make it configurable from the preferences. The implementation should be straightforward.

I would very much like to see this current proposal merged

Then please approve it, and I push the button ;)

@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 11, 2018

I'm not 100% sure about the shortcut on macOS. Safari is option-leftarrow, VSCode is ctrl-cmd-leftarrow, and Xcode also. We can change later though.

@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 11, 2018

Then please approve it, and I push the button ;)

I'll haven't checked the code yet but it shouldn't take long.

@kittaakos
Copy link
Contributor Author

The code was reviewed and approved already twice. I have tested on OS X and Windows too. But it is your call.

@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 11, 2018

Ah ok. Sounds good!

@kittaakos
Copy link
Contributor Author

Furthermore, the browser's back/forward is bound to the Cmd+Left and Cmd+Right in both Chrome and Safari.

@kittaakos kittaakos merged commit 1d38488 into master Apr 11, 2018
@kittaakos kittaakos deleted the GH-73 branch April 11, 2018 15:23
@MarkZ3
Copy link
Contributor

MarkZ3 commented Apr 11, 2018

Furthermore, the browser's back/forward is bound to the Cmd+Left and Cmd+Right in both Chrome and Safari.

Woops, my bad. It is for me too. Got the keys mixed up :)

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.

6 participants