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 Panes #693

Merged
merged 45 commits into from Oct 4, 2016
Merged

Split Panes #693

merged 45 commits into from Oct 4, 2016

Conversation

ekmartin
Copy link
Contributor

@ekmartin ekmartin commented Sep 6, 2016

This adds an initial implementation of split panes, as shown in the screenshot below.
Split Panes

Features

  • Split panes can be created by hitting Cmd+D and Cmd+Shift+D (which are also accessible from the Window menu).
  • Split panes can be arbitrarily nested, and support tabs like you'd expect.
  • The active pane can be changed with mouse clicks, or by cycling through them using Show Next Pane/Show Previous Pane.
  • Panes can be closed with CmdOrCtrl+W.

How

There's definitely lots of ways to implement something like this, however I've opted for a pretty Redux heavy direction. The whole split pane structure is stored in a new reducer, term-groups.js, which reacts to create/remove/focus change actions and adapts the structure as needed.

Reducer Structure

The term-groups reducer maintains a tree like structure of the different tabs.
The split structure in the screenshot would resemble something like this:

   +-----+Root+----+
   |               |
   v               v
++Left++       ++Right++
|      |       |   +   |
v      v       v   v   v
S      S       S   S   S

Each term group would have the following properties:

  • uid - group identifier
  • parentUid - the parent's uid
  • sessionUid - if the group is a leaf node, conforms to the actual session's uid
  • direction - what direction the split is created in (only for internal nodes)
  • children - an array of uids of the term group's children.

Additionally, the reducer holds a mapping between each root term group and their respective active sessionUid, so that you can change tabs without losing the focus of the session you'd selected.

Caveats

To be able to create new term groups the SESSION_ADD action is hijacked, and the split direction (if it's a split that caused the new session to be created) is added here. This feels a bit dirty, and I'd love suggestions on how this could be improved (and suggestions on how to improve the data structure in general!).

Rendering

The actual split panes are rendered using react-split-pane at the moment, but this probably needs to be changed before this is ready for primetime. A few issues:

  • It doesn't support more than two split panes out of the box without nesting split panes (workaround).
  • The styling is a slightly awkward. This could be fixed with an upstream pull request to allow custom class names for the pane divider (resizer), so we could use it with Aphrodite.
  • Mouse resizing also seems a bit glitchy, but this might be an issue on our end as well - haven't spent too much time on it yet.

We could either look into fixing these issues upstream, or just implement our own flexbox heavy approach.

TODOs

✅ Preserving already created hterm instances

At the moment we're creating hterm instances at the bottom of the React hierarchy, in the Term component. This doesn't work very well with split panes, since Terms will be removed and recreated when the split pane structure is changed. That means the same happens to their respective hterm instances, which means that sessions lose their output when splitting (i.e. needs to be fixed before splits are usable).

One of the ways of solving this would be to create hterm instances at a higher level, and then pass them down to the Term component. This could either be in a React component such as Terms, or even in a Redux reducer. The latter may sound a bit crazy, but I think it might make sense together with the current reducer structure. I'm interested in more ideas around this though.

✅ Hotkeys

This definitely needs some bikeshedding. Even if we need a way of configuring hotkeys in the future, sane defaults will always be important. As mentioned splits are currently created with CtrlOrCmd+D and CtrlOrCmd+Shift+D. Cmd+D is definitely okay, but Ctrl+D obviously isn't 😙. Maybe we can change it based on the user's OS. What would be a decent hotkey set for Linux?

There also isn't a hotkey for rotating back and forth between your open split panes yet. iTerm defaults this to Cmd+[/Cmd+], however this doesn't work on a lot of European keyboards. Personally I'd prefer something like Ctrl+Tab/Ctrl+Shift+Tab, which we've currently set to changing tabs (afaik it doesn't work though, the combination is eaten by hterm).

EDIT: Cycling between split panes is currently bound to Ctrl+Alt+Tab and Ctrl+Shift+Alt+Tab.

In the future we should definitely also support changing panes based on direction (Cmd+Alt+Arrow in iTerm).

✅ Resizing

Drag and drop resizing of split panes sort of works at the moment, but it's really glitchy.

✅ Styling

Needs to support custom styling in the same way as the rest of HyperTerm. We could probably add some sort of indicator to show what pane is in focus (i.e. an overlay over the inactive panes, like iTerm) as well.

Bugs

  • Clicking to change focus doesn't work when applications such as vtop/htop are open.
  • Splitting panes will make git status output look funky (and probably other resizing issues) - screenshot.
  • A tab will sometimes crash after a pane is closed, needs more investigation.
  • Closing the last tab won't exit HyperTerm (regression).
  • Creating multiple horizontal splits is buggy.
  • Webviews don't respect focus changes as they should.

...and probably a lot more!

Binary

I really recommend pulling down the branch, however I've made a binary that can be downloaded here: https://github.com/ekmartin/hyperterm/releases/download/0.8.0-splits.5/mac.zip (updated 2016-10-02)

This allows users to split their Hyperterm terms into
multiple nested splits, both vertical and horizontal.

Fixes vercel#56
New split panes should be placed after the currently active
pane, not at the end like they were previously.
This adds menu buttons for moving back and forward between
open split panes in the currect terminal tab.
Doesn't add a hotkey yet, needs some bikeshedding.
It made little sense to have so many objects with `activeSessionUid`
set to `null` when it only mattered on the top level.
Now it's an object mapping term-group `uid` to `sessionUid` instead.
This was referenced Sep 6, 2016
@matheuss
Copy link
Member

matheuss commented Sep 6, 2016

THAT'S FREAKING AWESOME

@chabou
Copy link
Collaborator

chabou commented Sep 7, 2016

Great work !

I found a little bug when you reduce the height of a horizontally splitted tab, the bottom one keeps its original size.
But it seems to be a react-split-pane bug : if I add display: flexto the second Pane div, it fixes its size.
Maybe related to tomkp/react-split-pane#106

How can we help you with this PR ?

@ekmartin
Copy link
Contributor Author

ekmartin commented Sep 8, 2016

Thanks!

@chabou I think the main steps in moving forward will be deciding on what the correct direction to go regarding actions/reducers is, and what to do with the hterm instance issue I mentioned above.

I'm going to be looking into what to do with react-split-pane, probably by seeing if reimplementing some of the functionality directly in HyperTerm might be better than using it.

If you're interested in helping out with some of the bugs that need to be squashed before it's ready that would be helpful. Quick summary:

  • Clicking to change focus doesn't work when applications such as vtop/htop are open.
    Normally this is done by attaching a focus listener here, however this is never fired when you for example click on a term that has htop open.
  • A tab will sometimes crash after a pane is closed. (fixed)
  • Hotkeys for cycling back and forth between split panes.

@iamstarkov
Copy link
Contributor

@ekmartin @rauchg thank you for all the work done in this issue.
Can you share some news/plans on this pr?

@ekmartin
Copy link
Contributor Author

ekmartin commented Oct 3, 2016

@iamstarkov: We found a few bugs with multiple horizontal (Y-directional) split panes, we're looking into that now :)

@austinyearlykim
Copy link

It's crazy seeing a vital feature like this in progress in real time right now. I'M SO STOKED

Copy link
Contributor

@flybayer flybayer left a comment

Choose a reason for hiding this comment

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

Feedback from Ubuntu 14.04

  1. Running exit freezes HyperTerm
  2. I propose changing the new split keyboard shortcuts to these. I've been using these in Vim/Tmux for awhile and love it! Before, I could never remember which was vertical or horizontal.
    • Split vertically: Cmd/Ctrl + \
    • Split horizontally: Cmd/Ctrl + -

@flybayer
Copy link
Contributor

flybayer commented Oct 3, 2016

I just realized I'm testing zet:add/splits instead of ekmartin:splits. Which branch should we be testing?

@maxdeviant
Copy link
Contributor

maxdeviant commented Oct 3, 2016

@flybayer Doesn't Cmd/Ctrl + - conflict with zoom out?

@flybayer
Copy link
Contributor

flybayer commented Oct 3, 2016

@maxdeviant oops yes 😆 I guess I'm actually using Meta + - and Meta + \ and forgot the difference. Is Meta + - and Meta + \ a viable default for this?

@ekmartin
Copy link
Contributor Author

ekmartin commented Oct 3, 2016

@flybayer: the exit bug should be fixed with b2ca957 :)

@ekmartin
Copy link
Contributor Author

ekmartin commented Oct 4, 2016

@flybayer: I added the split hotkeys Ctrl+Shift+O (horizontal) and Ctrl+Shift+E (vertical) - stolen from Gnome Terminator. If there's better options we can open an issue and do some bikeshedding after this has been merged :)

@rauchg rauchg merged commit a7595c1 into vercel:master Oct 4, 2016
@ekmartin ekmartin deleted the splits branch October 4, 2016 02:50
@iamstarkov
Copy link
Contributor

🎉 yay 🎉

@iamstarkov
Copy link
Contributor

any plans to release?

@naim
Copy link

naim commented Oct 19, 2016

This would be really nice to get into mainline.

Edit: Nevermind! I missed the fact this actually was merged (just saw the labels).

@chabou
Copy link
Collaborator

chabou commented Oct 19, 2016

I think it is included in 0.8.1 release https://github.com/zeit/hyper/releases/tag/0.8.1

@iamstarkov
Copy link
Contributor

@naim @chabou thats true

@iamstarkov
Copy link
Contributor

@naim though you need to download hyper. before it was hyperterm and has been renamed

@chabou
Copy link
Collaborator

chabou commented Oct 19, 2016

In Progress and Review Needed labels seem confusing 😄

tylerong pushed a commit to tylerong/hyper that referenced this pull request Jul 3, 2017
* npm: add .npmrc with save-exact=true

* split panes: create initial implementation

This allows users to split their Hyperterm terms into
multiple nested splits, both vertical and horizontal.

Fixes vercel#56

* split panes: suport closing tabs and individual panes

* split panes: ensure new splits are placed at the correct index

New split panes should be placed after the currently active
pane, not at the end like they were previously.

* split panes: add explicit dependency to uuid

* split panes: implement split pane cycling

This adds menu buttons for moving back and forward between
open split panes in the currect terminal tab.
Doesn't add a hotkey yet, needs some bikeshedding.

* split panes: move activeSessionUid to its own object

It made little sense to have so many objects with `activeSessionUid`
set to `null` when it only mattered on the top level.
Now it's an object mapping term-group `uid` to `sessionUid` instead.

* split panes: make sure closing the last split pane exits the app

* split panes: fix a crash after closing specific panes

Sometimes the terminal would crash when a specific
split pane was closed, because the `activeSessions`
mapping wasn't updated correctly.

* split panes: fix a bug that caused initial session sizing to be wrong

* fix all our focus / blur issues in one fell swoop :O (famous last words)

* get rid of react warning

* hterm: make sure not to lose focus when VT listens on clicks

* term: restore onactive callback

* add missing `return` to override (just in case)

* split pane: new split pane implementation

* goodbye react-split-pane

* added term group resizing action and reducer

* terms: supply border color so that we can use it for splits

* term-group: add resizing hook

* term-groups: add resizing constant

* remove split pane css side-effect

* split panes: pass existing hterm instances to Term

* split panes: add keybindings for split pane cycling

* split panes: remove unused action

* split panes: remove unused styling

* split-pane: remove `console.log`

* split-pane: remove `console.log`

* split panes: rebalance sizes on insert/removal

* split panes: pass existing hterm instances to Term

* split panes: add keybindings for split pane cycling

* split panes: remove unused action

* split panes: remove unused styling

* split panes: rebalance sizes on insert/removal

* split panes: set a minimum size for resizing

* split-pane: fix vertical splits

* css :|

* package: bump electron

* split panes: attach onFocus listener to webviews

* 1.4.1 and 1.4.2 are broken. they have the following regression:
- open google.com on the main window
- open a new tab
- come back to previous tab. webview is gone :|

* split panes: handle PTY exits

* split panes: add linux friendly keybindings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👩‍🔬 Status: In Progress Issue or PR is currently active and work is in progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants