Skip to content

Instantly share code, notes, and snippets.

@majman
Created October 22, 2015 19:23
Show Gist options
  • Select an option

  • Save majman/d901f2049dc9b077821f to your computer and use it in GitHub Desktop.

Select an option

Save majman/d901f2049dc9b077821f to your computer and use it in GitHub Desktop.
config for phoenix window manager
// Forked originally from @JasonM23’s config in literate coffee-script
// https://github.com/jasonm23/Phoenix-config/blob/master/Phoenix-config.litcoffee
// Released under MIT license - http://opensource.org/licenses/MIT
var forApp, key_binding, layouts, mash,
moveWindowLeftOneColumn, moveWindowRightOneColumn, moveWindowToNextScreen,
switchLayout,
windowDownOneRow, windowGrowOneGridColumn, windowGrowOneGridRow, windowShrinkOneGridColumn,
windowShrinkOneGridRow, windowToFullHeight, windowUpOneRow;
function debug(message) {
return api.alert(message, 8);
};
function testScreens(){
var screens = {};
var win;
win = Window.focusedWindow();
// win.screen().nextScreen()
var s = win.screen();
var rect1 = s.frameWithoutDockOrMenu();
var rect2 = s.frameIncludingDockAndMenu();
}
// testScreens();
MARGIN_X = 5;
MARGIN_Y = 5;
GRID_WIDTH = 20;
GRID_HEIGHT = 12;
// App Layouts
// app: Name of app
// x: 0 - 1 * Number of Screens (1st screen starts at 0, 2nd at 1, etc);
// y: 0 - 1 (0 top of screen)
// width: 1 is full width of a single screen
// height: 1 is full height of screen
// cascade: if more than one window open for app, stack them
var finderLayout = {
app: "Finder",
opts: {
x: 1,
y: 0.5,
width: 0.375,
height: 0.5
},
cascade: true
}
var slackLayout = {
app: "Slack",
opts: {
x: 1.625,
y: 0,
width: 0.375,
height: 0.5
}
}
var browserLayout = {
app: "Google Chrome",
opts: {
x: 0.1,
y: 0.05,
width: 0.8,
height: 0.9
},
cascade: true
};
var terminalLayout = {
app: "iTerm",
opts: {
x: 1,
y: 0.5,
width: 0.375,
height: 0.5
},
cascade: true
};
var editorLayout = {
app: "Sublime Text",
opts: {
x: 1.125,
y: 0,
width: 0.75,
height: 1
},
cascade: true
};
layouts = {
"maj": [
finderLayout,
slackLayout,
browserLayout,
terminalLayout,
editorLayout
],
"maj2": [
browserLayout,
editorLayout,
terminalLayout
]
};
function switchLayout(name) {
var visibleWindows = Window.visibleWindows();
var layoutApps = _.pluck(layouts[name], 'app');
var visibleApps = _.unique(_.map(visibleWindows, function(vw){
return vw.app().title();
}));
var diffApps = _.difference(visibleApps, layoutApps);
_.each(diffApps, function(appTitle){
var app;
app = App.byTitle(appTitle, true);
app.hide();
});
return _.each(layouts[name], function(config) {
var app;
App.focusOrStart(config.app);
app = App.byTitle(config.app);
var opts = config.opts;
if(config.cascade == true){
return _.each(app.visibleWindows(), function(win, i){
win.toGrid(Number(opts.x) + (i * 0.01), Number(opts.y) + (i * 0.02), opts.width, opts.height);
});
}else {
return app.firstWindow().toGrid(opts.x, opts.y, opts.width, opts.height);
}
});
};
Window.prototype.getGrid = function() {
var halfScreenHeight, screenRect, thirdScreenWidth, winFrame;
winFrame = this.frame();
screenRect = this.screen().frameWithoutDockOrMenu();
thirdScreenWidth = screenRect.width / GRID_WIDTH;
halfScreenHeight = screenRect.height / GRID_HEIGHT;
return {
x: Math.round((winFrame.x - screenRect.x) / thirdScreenWidth),
y: Math.round((winFrame.y - screenRect.y) / halfScreenHeight),
width: Math.max(1, Math.round(winFrame.width / thirdScreenWidth)),
height: Math.max(1, Math.round(winFrame.height / halfScreenHeight))
};
};
Window.prototype.setGrid = function(grid, screen) {
var halfScreenHeight, newFrame, screenRect, thirdScreenWidth;
screenRect = screen.frameWithoutDockOrMenu();
thirdScreenWidth = screenRect.width / GRID_WIDTH;
halfScreenHeight = screenRect.height / GRID_HEIGHT;
newFrame = {
x: (grid.x * thirdScreenWidth) + screenRect.x,
y: (grid.y * halfScreenHeight) + screenRect.y,
width: grid.width * thirdScreenWidth,
height: grid.height * halfScreenHeight
};
newFrame.x += MARGIN_X;
newFrame.y += MARGIN_Y;
newFrame.width -= MARGIN_X * 2.0;
newFrame.height -= MARGIN_Y * 2.0;
this.setFrame(newFrame);
return newFrame;
};
Window.prototype.snapToGrid = function() {
if (this.isNormalWindow()) {
return this.setGrid(this.getGrid(), this.screen());
}
};
Window.prototype.calculateGrid = function(x, y, width, height) {
var screen;
screen = this.screen().frameWithoutDockOrMenu();
if(x >= 1){
screen.x -= screen.width;
}
return {
x: Math.round(x * screen.width) + MARGIN_X + screen.x,
y: Math.round(y * screen.height) + MARGIN_Y + screen.y,
width: Math.round(width * screen.width) - 2.0 * MARGIN_X,
height: Math.round(height * screen.height) - 2.0 * MARGIN_Y
};
};
Window.prototype.toGrid = function(x, y, width, height) {
var rect;
rect = this.calculateGrid(x, y, width, height);
this.setFrame(rect);
return this;
};
Window.prototype.topRight = function() {
var f;
f = this.frame();
return {
x: f.x + f.width,
y: f.y
};
};
Window.prototype.toLeft = function() {
var p;
p = this.topLeft();
return _.chain(this.windowsToWest()).filter(function(win) {
return win.topLeft().x < p.x - 10;
}).value();
};
Window.prototype.toRight = function() {
var p;
p = this.topRight();
return _.chain(this.windowsToEast()).filter(function(win) {
return win.topRight().x > p.x + 10;
}).value();
};
Window.prototype.info = function() {
var f;
f = this.frame();
return "[" + (this.app().pid) + "] " + (this.app().title()) + " : " + (this.title()) + "\n{x:" + f.x + ", y:" + f.y + ", width:" + f.width + ", height:" + f.height + "}\n";
};
Window.sortByMostRecent = function(windows) {
var allVisible;
allVisible = Window.visibleWindowsMostRecentFirst();
return _.chain(windows).sortBy(function(win) {
return _.map(allVisible, function(w) {
return w.info();
}).indexOf(win.info());
}).value();
};
Window.prototype.toTopHalf = function() {
return this.toGrid(0, 0, 1, 0.5);
};
Window.prototype.toBottomHalf = function() {
return this.toGrid(0, 0.5, 1, 0.5);
};
Window.prototype.toLeftHalf = function() {
return this.toGrid(0, 0, 0.5, 1);
};
Window.prototype.toRightHalf = function() {
return this.toGrid(0.5, 0, 0.5, 1);
};
Window.prototype.toTopRight = function() {
return this.toGrid(0.5, 0, 0.5, 0.5);
};
Window.prototype.toBottomRight = function() {
return this.toGrid(0.5, 0.5, 0.5, 0.5);
};
Window.prototype.toTopLeft = function() {
return this.toGrid(0, 0, 0.5, 0.5);
};
Window.prototype.toBottomLeft = function() {
return this.toGrid(0, 0.5, 0.5, 0.5);
};
moveWindowToNextScreen = function() {
var win;
win = Window.focusedWindow();
return win.setGrid(win.getGrid(), win.screen().nextScreen());
};
moveWindowLeftOneColumn = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
if(frame.x == 0){
frame.width --;
}
frame.x = Math.max(frame.x - 1, 0);
return win.setGrid(frame, win.screen());
};
moveWindowRightOneColumn = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
if(frame.x + frame.width >= GRID_WIDTH){
frame.width --;
}
frame.x = Math.min(frame.x + 1, GRID_WIDTH - frame.width);
return win.setGrid(frame, win.screen());
};
windowGrowOneGridColumn = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
frame.width = Math.min(frame.width + 1, GRID_WIDTH - frame.x);
return win.setGrid(frame, win.screen());
};
windowShrinkOneGridColumn = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
frame.width = Math.max(frame.width - 1, 1);
return win.setGrid(frame, win.screen());
};
windowGrowOneGridRow = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
frame.height = Math.min(frame.height + 1, GRID_HEIGHT);
return win.setGrid(frame, win.screen());
};
windowShrinkOneGridRow = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
frame.height = Math.max(frame.height - 1, 1);
return win.setGrid(frame, win.screen());
};
windowDownOneRow = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
frame.y = Math.min(Math.floor(frame.y + 1), GRID_HEIGHT - 1);
return win.setGrid(frame, win.screen());
};
windowUpOneRow = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
frame.y = Math.max(Math.floor(frame.y - 1), 0);
return win.setGrid(frame, win.screen());
};
windowToFullHeight = function() {
var frame, win;
win = Window.focusedWindow();
frame = win.getGrid();
frame.y = 0;
frame.height = GRID_HEIGHT;
return win.setGrid(frame, win.screen());
};
App.prototype.firstWindow = function() {
return this.visibleWindows()[0];
};
App.byTitle = function(title, ignoreShow) {
var app, apps, i;
apps = this.runningApps();
i = 0;
while (i < apps.length) {
app = apps[i];
if (app.title() === title) {
if(ignoreShow){
return app;
}
app.show();
return app;
}
i++;
}
};
App.allWithTitle = function(title) {
return _(this.runningApps()).filter(function(app) {
if (app.title() === title) {
return true;
}
});
};
App.focusOrStart = function(title) {
var activeWindows, apps, windows;
apps = App.allWithTitle(title);
if (_.isEmpty(apps)) {
api.alert("Attempting to start " + title);
api.launch(title);
return;
}
windows = _.chain(apps).map(function(x) {
return x.allWindows();
}).flatten().value();
activeWindows = _(windows).reject(function(win) {
return win.isWindowMinimized();
});
if (_.isEmpty(activeWindows)) {
api.launch(title);
}
activeWindows.forEach(function(win) {
win.focusWindow();
});
};
forApp = function(title, fn) {
var app;
app = App.byTitle(title);
if (app) {
return _.each(app.visibleWindows(), fn);
}
};
/* KEY BINDINGS
*/
function key_binding(key, modifier, fn) {
return api.bind(key, modifier, fn);
};
mash = 'cmd+alt+ctrl'.split('+');
key_binding('0', mash, function() {
return switchLayout('maj');
});
key_binding('9', mash, function() {
return switchLayout('maj2');
});
// Convenience key bindings...
key_binding('up', mash, function() {
return windowUpOneRow();
});
key_binding('down', mash, function() {
return windowDownOneRow();
});
key_binding('left', mash, function() {
return moveWindowLeftOneColumn();
});
key_binding('right', mash, function() {
return moveWindowRightOneColumn();
});
key_binding('\\', mash, function() {
return moveWindowToNextScreen();
});
key_binding('-', mash, function() {
return windowShrinkOneGridRow();
});
key_binding('=', mash, function() {
return windowGrowOneGridRow();
});
key_binding('[', mash, function() {
return windowShrinkOneGridColumn();
});
key_binding(']', mash, function() {
return windowGrowOneGridColumn();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment