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

File Explorer Keyboard Navigation - Part 1 #1086

Merged

Conversation

glennsl
Copy link
Member

@glennsl glennsl commented Dec 19, 2019

This implements basic keyboard navigation (up arrow/down arrow) and selection (enter) within the file explorer. There's no way to use the keyboard to focus the file explorer, however, so it's not very useful for end-users yet. And because of the mechanism used to capture keyboard input it also blocks all keybindings. But it's useful for testing keyboard input and relatively self-contained, so I'm submitting this now to try to keep PRs manageable.

Addresses #528

@glennsl glennsl requested a review from bryphe December 19, 2019 13:03
@@ -4,16 +4,20 @@ type t = {
tree: option(FsTreeNode.t),
isOpen: bool,
scrollOffset: [ | `Start(float) | `Middle(float)],
focus: option(string) // path
active: option(string), // path
focus: option(string) // node id
Copy link
Member Author

Choose a reason for hiding this comment

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

Note to self: path, not id

Copy link
Member

Choose a reason for hiding this comment

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

That would be one nice thing about using a path library like Path/fp - we could have a type for it

type t = {
id: int,
Copy link
Member Author

Choose a reason for hiding this comment

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

I've removed id entirely in favor of using paths as identifiers instead. For a few reasons:

  • it's simpler.
  • Paths don't change (and if they do it's because their identity changes). No more stale ids, they're valid across workspace changes and can even be persisted.
  • Searching by path is most likely faster since nodes that aren't in the path can be eliminated from the search. Hashing also makes individual comparisons as fast as on ids.

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense to me!

path
|> String.split_on_char(Filename.dir_sep.[0])
|> List.map(Hashtbl.hash);
let equals = (a, b) => a.hash == b.hash && a.path == b.path;
Copy link
Member Author

Choose a reason for hiding this comment

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

Hashes aren't guaranteed to be unique, so use this instead of comparing hashes directly, and especially instead of comparing nodes structurally.

Comment on lines +127 to +151
let onNodeClick = node => {
Option.iter(Revery.UI.Focus.focus, containerRef);
onNodeClick(node);
};

let onKeyDown = (event: NodeEvents.keyEventParams) => {
switch (event.keycode) {
// Enter
| v when v == 13 =>
GlobalContext.current().dispatch(Actions.FileExplorer(Select))

// arrow up
| v when v == 1073741906 =>
GlobalContext.current().dispatch(Actions.FileExplorer(FocusPrev))

// arrow down
| v when v == 1073741905 =>
GlobalContext.current().dispatch(Actions.FileExplorer(FocusNext))

| _ => ()
};
};

<View
onKeyDown style=Styles.container ref={ref => setContainerRef(Some(ref))}>
Copy link
Member Author

Choose a reason for hiding this comment

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

This should all be removed in favor of handling input "bottom-up".

@glennsl
Copy link
Member Author

glennsl commented Dec 19, 2019

Woo! What is this new and amazing CI we got? Didn't even take 30 mins to finish! 🎉

Comment on lines +705 to +715
module Path = {
// Not very robust path-handling utilities.
// TODO: Make good

let toRelative = (~base, path) => {
let base = base == "/" ? base : base ++ Filename.dir_sep;
Str.replace_first(Str.regexp_string(base), "", path);
};

let explode = String.split_on_char(Filename.dir_sep.[0]);
};
Copy link
Member

Choose a reason for hiding this comment

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

We could consider using the Fp/Path library from reason-native: https://github.com/facebookexperimental/reason-native/tree/master/src/fp
(if it makes sense)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that looks pretty good. It doesn't seem to have any way of destructuring it like explode though. But we could contribute that.

@bryphe
Copy link
Member

bryphe commented Dec 19, 2019

There's no way to use the keyboard to focus the file explorer, however, so it's not very useful for end-users yet. And because of the mechanism used to capture keyboard input it also blocks all keybindings. But it's useful for testing keyboard input and relatively self-contained, so I'm submitting this now to try to keep PRs manageable.

I like the way you divided the work - seems like a good chunk to bring in. I tried it out and it's so nice to have some keyboard input in the file explorer!

@glennsl glennsl merged commit bdacaea into onivim:master Dec 19, 2019
@bryphe
Copy link
Member

bryphe commented Dec 19, 2019

Woo! What is this new and amazing CI we got? Didn't even take 30 mins to finish! 🎉

I tried to go through and fix most of the hangs / issues... hopefully it works better now 🤞

@JonDum
Copy link

JonDum commented Apr 1, 2020

This is awesome. Looking forward to part 2 and 3! Once it's "nerdtree-like" I will be able to use oni2 for real I think.

@gordonrust
Copy link

Any update on the 'nerdtree-like' behaviour. I am also eagerly waiting for this behaviour to switch to onivim2.
Also, if possible, could the panel in the bottom of the UI also behave like another hsplit window as is the behavoiur in vim. These two are the most important things that have halted my adoption of vscode. I have my hopes on oni2.

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.

4 participants