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
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1a28d2a
npm: add .npmrc with save-exact=true
ekmartin Jul 24, 2016
02c3f60
split panes: create initial implementation
ekmartin Aug 10, 2016
67669b0
split panes: suport closing tabs and individual panes
ekmartin Aug 18, 2016
beb2037
split panes: ensure new splits are placed at the correct index
ekmartin Aug 31, 2016
72fb7d7
split panes: add explicit dependency to uuid
ekmartin Sep 5, 2016
3af3dd9
split panes: implement split pane cycling
ekmartin Sep 5, 2016
4ec7892
split panes: move activeSessionUid to its own object
ekmartin Sep 6, 2016
f2e10ca
split panes: make sure closing the last split pane exits the app
ekmartin Sep 8, 2016
eb0d7b3
split panes: fix a crash after closing specific panes
ekmartin Sep 8, 2016
2beb9ba
split panes: fix a bug that caused initial session sizing to be wrong
ekmartin Sep 8, 2016
60f0e6b
Merge branch 'master' into splits
rauchg Sep 19, 2016
c74c664
fix all our focus / blur issues in one fell swoop :O (famous last words)
rauchg Sep 19, 2016
2b18af8
get rid of react warning
rauchg Sep 19, 2016
a431504
hterm: make sure not to lose focus when VT listens on clicks
rauchg Sep 19, 2016
6ec526b
term: restore onactive callback
rauchg Sep 19, 2016
034a7b6
add missing `return` to override (just in case)
rauchg Sep 20, 2016
2ae9e3a
split pane: new split pane implementation
rauchg Oct 2, 2016
080c394
goodbye react-split-pane
rauchg Oct 2, 2016
1b0e598
added term group resizing action and reducer
rauchg Oct 2, 2016
f95a548
terms: supply border color so that we can use it for splits
rauchg Oct 2, 2016
519a0f8
term-group: add resizing hook
rauchg Oct 2, 2016
7591901
term-groups: add resizing constant
rauchg Oct 2, 2016
86906ab
remove split pane css side-effect
rauchg Oct 2, 2016
c4a6fdf
split panes: pass existing hterm instances to Term
ekmartin Sep 27, 2016
77257b3
split panes: add keybindings for split pane cycling
ekmartin Sep 30, 2016
cd0b51b
split panes: remove unused action
ekmartin Oct 2, 2016
eb22454
split panes: remove unused styling
ekmartin Oct 2, 2016
cd4100e
split-pane: remove `console.log`
rauchg Oct 2, 2016
cc59137
split-pane: remove `console.log`
rauchg Oct 2, 2016
c0c6a21
split panes: rebalance sizes on insert/removal
ekmartin Oct 2, 2016
86dbb5a
split panes: pass existing hterm instances to Term
ekmartin Sep 27, 2016
856baa0
split panes: add keybindings for split pane cycling
ekmartin Sep 30, 2016
ffff36f
split panes: remove unused action
ekmartin Oct 2, 2016
4c79c90
split panes: remove unused styling
ekmartin Oct 2, 2016
93a9d45
split panes: rebalance sizes on insert/removal
ekmartin Oct 2, 2016
9d26e9c
split panes: set a minimum size for resizing
ekmartin Oct 3, 2016
860624c
split-pane: fix vertical splits
rauchg Oct 3, 2016
620f8ca
css :|
rauchg Oct 3, 2016
9939645
package: bump electron
rauchg Oct 3, 2016
07df51d
Merge branch 'add/splits' into splits
ekmartin Oct 3, 2016
e0a8581
split panes: attach onFocus listener to webviews
ekmartin Oct 3, 2016
5191cf2
1.4.1 and 1.4.2 are broken. they have the following regression:
rauchg Oct 3, 2016
b2ca957
split panes: handle PTY exits
ekmartin Oct 3, 2016
fea7e79
split panes: add linux friendly keybindings
ekmartin Oct 4, 2016
9bcc15c
Merge branch 'master' into splits
ekmartin Oct 4, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmrc
@@ -0,0 +1 @@
save-exact=true
1 change: 1 addition & 0 deletions app/.npmrc
@@ -0,0 +1 @@
save-exact=true
14 changes: 8 additions & 6 deletions app/index.js
Expand Up @@ -155,7 +155,7 @@ app.on('ready', () => installDevExtensions(isDev).then(() => {
// If no callback is passed to createWindow,
// a new session will be created by default.
if (!fn) {
fn = win => win.rpc.emit('session add req');
fn = win => win.rpc.emit('termgroup add req');
}

// app.windowCallback is the createWindow callback
Expand All @@ -173,14 +173,17 @@ app.on('ready', () => installDevExtensions(isDev).then(() => {
}
});

rpc.on('new', ({rows = 40, cols = 100, cwd = process.env.HOME}) => {
rpc.on('new', ({rows = 40, cols = 100, cwd = process.env.HOME, splitDirection}) => {
const shell = cfg.shell;
const shellArgs = cfg.shellArgs && Array.from(cfg.shellArgs);

initSession({rows, cols, cwd, shell, shellArgs}, (uid, session) => {
sessions.set(uid, session);
rpc.emit('session add', {
rows,
cols,
uid,
splitDirection,
shell: session.shell,
pid: session.pty.pid
});
Expand Down Expand Up @@ -242,10 +245,9 @@ app.on('ready', () => installDevExtensions(isDev).then(() => {
win.maximize();
});

rpc.on('resize', ({cols, rows}) => {
sessions.forEach(session => {
session.resize({cols, rows});
});
rpc.on('resize', ({uid, cols, rows}) => {
const session = sessions.get(uid);
session.resize({cols, rows});
});

rpc.on('data', ({uid, data}) => {
Expand Down
46 changes: 44 additions & 2 deletions app/menu.js
Expand Up @@ -73,7 +73,7 @@ module.exports = function createMenu({createWindow, updatePlugins}) {
accelerator: 'CmdOrCtrl+T',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.rpc.emit('session add req');
focusedWindow.rpc.emit('termgroup add req');
} else {
createWindow();
}
Expand All @@ -82,12 +82,33 @@ module.exports = function createMenu({createWindow, updatePlugins}) {
{
type: 'separator'
},
{
label: 'Split Vertically',
accelerator: 'Ctrl+Shift+E',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.rpc.emit('split request vertical');
}
}
},
{
label: 'Split Horizontally',
accelerator: 'Ctrl+Shift+O',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.rpc.emit('split request horizontal');
}
}
},
{
type: 'separator'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.rpc.emit('session close req');
focusedWindow.rpc.emit('termgroup close req');
}
}
},
Expand Down Expand Up @@ -264,6 +285,27 @@ module.exports = function createMenu({createWindow, updatePlugins}) {
{
type: 'separator'
},
{
label: 'Select Next Pane',
accelerator: 'Ctrl+Alt+Tab',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.rpc.emit('next pane req');
}
}
},
{
label: 'Select Previous Pane',
accelerator: 'Ctrl+Shift+Alt+Tab',
click(item, focusedWindow) {
if (focusedWindow) {
focusedWindow.rpc.emit('prev pane req');
}
}
},
{
type: 'separator'
},
{
role: 'front'
},
Expand Down
7 changes: 3 additions & 4 deletions lib/actions/header.js
@@ -1,16 +1,15 @@
import {CLOSE_TAB, CHANGE_TAB} from '../constants/tabs';
import {UI_WINDOW_MAXIMIZE, UI_WINDOW_UNMAXIMIZE} from '../constants/ui';
import rpc from '../rpc';

import {userExitSession, setActiveSession} from './sessions';
import {userExitTermGroup, setActiveGroup} from './term-groups';

export function closeTab(uid) {
return dispatch => {
dispatch({
type: CLOSE_TAB,
uid,
effect() {
dispatch(userExitSession(uid));
dispatch(userExitTermGroup(uid));
}
});
};
Expand All @@ -22,7 +21,7 @@ export function changeTab(uid) {
type: CHANGE_TAB,
uid,
effect() {
dispatch(setActiveSession(uid));
dispatch(setActiveGroup(uid));
}
});
};
Expand Down
76 changes: 32 additions & 44 deletions lib/actions/sessions.js
@@ -1,6 +1,7 @@
import rpc from '../rpc';
import getURL from '../utils/url-command';
import {keys} from '../utils/object';
import {findBySession} from '../utils/term-groups';
import {
SESSION_ADD,
SESSION_RESIZE,
Expand All @@ -9,7 +10,6 @@ import {
SESSION_PTY_DATA,
SESSION_PTY_EXIT,
SESSION_USER_EXIT,
SESSION_USER_EXIT_ACTIVE,
SESSION_SET_ACTIVE,
SESSION_CLEAR_ACTIVE,
SESSION_USER_DATA,
Expand All @@ -19,13 +19,18 @@ import {
SESSION_SET_PROCESS_TITLE
} from '../constants/sessions';

export function addSession(uid, shell, pid) {
return dispatch => {
export function addSession({uid, shell, pid, cols, rows, splitDirection}) {
return (dispatch, getState) => {
const {sessions} = getState();
dispatch({
type: SESSION_ADD,
uid,
shell,
pid
pid,
cols,
rows,
splitDirection,
activeUid: sessions.activeUid
});
};
}
Expand Down Expand Up @@ -72,33 +77,16 @@ export function addSessionData(uid, data) {
};
}

export function sessionExit(uid) {
return (dispatch, getState) => {
function createExitAction(type) {
return uid => (dispatch, getState) => {
return dispatch({
type: SESSION_PTY_EXIT,
type,
uid,
effect() {
// we reiterate the same logic as below
// for SESSION_USER_EXIT since the exit
// could happen pty side or optimistic
const sessions = keys(getState().sessions.sessions);
if (!sessions.length) {
window.close();
if (type === SESSION_USER_EXIT) {
rpc.emit('exit', {uid});
}
}
});
};
}

// we want to distinguish an exit
// that's UI initiated vs pty initiated
export function userExitSession(uid) {
return (dispatch, getState) => {
return dispatch({
type: SESSION_USER_EXIT,
uid,
effect() {
rpc.emit('exit', {uid});
const sessions = keys(getState().sessions.sessions);
if (!sessions.length) {
window.close();
Expand All @@ -108,17 +96,10 @@ export function userExitSession(uid) {
};
}

export function userExitActiveSession() {
return (dispatch, getState) => {
dispatch({
type: SESSION_USER_EXIT_ACTIVE,
effect() {
const uid = getState().sessions.activeUid;
dispatch(userExitSession(uid));
}
});
};
}
// we want to distinguish an exit
// that's UI initiated vs pty initiated
export const userExitSession = createExitAction(SESSION_USER_EXIT);
export const ptyExitSession = createExitAction(SESSION_PTY_EXIT);

export function setActiveSession(uid) {
return (dispatch, getState) => {
Expand Down Expand Up @@ -163,13 +144,20 @@ export function setSessionXtermTitle(uid, title) {
}

export function resizeSession(uid, cols, rows) {
return {
type: SESSION_RESIZE,
cols,
rows,
effect() {
rpc.emit('resize', {cols, rows});
}
return (dispatch, getState) => {
const {termGroups} = getState();
const group = findBySession(termGroups, uid);
const isStandaloneTerm = !group.parentUid && !group.children.length;
dispatch({
type: SESSION_RESIZE,
uid,
cols,
rows,
isStandaloneTerm,
effect() {
rpc.emit('resize', {uid, cols, rows});
}
});
};
}

Expand Down