Skip to content

Instantly share code, notes, and snippets.

@Linell
Last active August 29, 2015 14:03
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Linell/00d3549127fbe47f7211 to your computer and use it in GitHub Desktop.
Save Linell/00d3549127fbe47f7211 to your computer and use it in GitHub Desktop.
My dotfile for Phoenix - (https://github.com/sdegutis/Phoenix).
/*
▄███████▄ ▄█ █▄ ▄██████▄ ▄████████ ███▄▄▄▄ ▄█ ▀████ ▐████▀
███ ███ ███ ███ ███ ███ ███ ███ ███▀▀▀██▄ ███ ███▌ ████▀
███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███▌ ███ ▐███
███ ███ ▄███▄▄▄▄███▄▄ ███ ███ ▄███▄▄▄ ███ ███ ███▌ ▀███▄███▀
▀█████████▀ ▀▀███▀▀▀▀███▀ ███ ███ ▀▀███▀▀▀ ███ ███ ███▌ ████▀██▄
███ ███ ███ ███ ███ ███ █▄ ███ ███ ███ ▐███ ▀███
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ▄███ ███▄
▄████▀ ███ █▀ ▀██████▀ ██████████ ▀█ █▀ █▀ ████ ███▄
Linell Bonnette - thelinell.com / @thelinell / github.com/Linell
This is my configuration for Phoenix <https://github.com/sdegutis/Phoenix>, a
super-lightweight OS X window manager that can be configured and scripted through
Javascript.
Inital version of this config came from carlo at
<https://github.com/carlo/bash-it/blob/master/dotfiles/.phoenix.js>. Most of my changes
focus on removing things that I did not find useful and adding better support for changing
back and forth between monitors.
*/
/*
* Mash (and it's variants) is the key combination used to activate certain commands.
*/
var mash = [ 'cmd', 'alt', 'ctrl' ],
monitorMash = ['cmd', 'shift']
appMash = ['cmd', 'alt'],
nudgePixels = 10,
padding = 4,
previousSizes = {};
api.bind('left', monitorMash, leftOneMonitor);
api.bind('right', monitorMash, rightOneMonitor);
// ### General key configurations
//
// My space key together with `Ctrl`+`Cmd`+`Alt` is toggling any window
// between full screen and its initial size and position.
api.bind( 'space', mash, function() {
Window.focusedWindow().toggleFullscreen();
});
// My keypad keys together with `Ctrl`+`Cmd`+`Alt` are set up to push any
// window to either 25% or 50%. I tried to match the letters to a sort-of
// corresponding position on the screen.
api.bind( 'p', mash, function() {
Window.focusedWindow().toNE();
});
api.bind( 'o', mash, function() {
Window.focusedWindow().toN();
});
api.bind( 'i', mash, function() {
Window.focusedWindow().toNW();
});
api.bind( 'l', mash, function() {
Window.focusedWindow().toE();
});
api.bind( 'k', mash, function() {
Window.focusedWindow().toW();
});
api.bind( 'm', mash, function() {
Window.focusedWindow().toSE();
});
api.bind( ',', mash, function() {
Window.focusedWindow().toS();
});
api.bind( 'n', mash, function() {
Window.focusedWindow().toSW();
});
api.bind( ';', mash, function() {
Window.focusedWindow().toGrid( 0.25, 0, 0.5, 1 );
});
// The cursor keys together with `Ctrl`+`Cmd`+`Alt` make any window occupy any
// half of the screen (N, E, S, W).
api.bind( 'up', mash, function() {
Window.focusedWindow().toN();
});
api.bind( 'right', mash, function() {
Window.focusedWindow().toE();
});
api.bind( 'down', mash, function() {
Window.focusedWindow().toS();
});
api.bind( 'left', mash, function() {
Window.focusedWindow().toW();
});
// ### Application Launching Commands
api.bind( 'v', appMash, function() { switchApp('MacVim'); });
// Window Size/Position Manipulations {{{
// --------------------------------------------------------------------------------
// ### Helper methods `Window`
//
// #### Window#toGrid()
//
// This method can be used to push a window to a certain position and size on
// the screen by using four floats instead of pixel sizes. Examples:
//
// // Window position: top-left; width: 25%, height: 50%
// someWindow.toGrid( 0, 0, 0.25, 0.5 );
//
// // Window position: 30% top, 20% left; width: 50%, height: 35%
// someWindow.toGrid( 0.3, 0.2, 0.5, 0.35 );
//
// The window will be automatically focussed. Returns the window instance.
Window.prototype.toGrid = function( x, y, width, height ) {
var screen = this.screen().frameWithoutDockOrMenu(),
newFrame = {
x: Math.round( x * screen.width ) + padding + screen.x,
y: Math.round( y * screen.height ) + padding + screen.y,
width: Math.round( width * screen.width ) - ( 2 * padding ),
height: Math.round( height * screen.height ) - ( 2 * padding )
};
// When setting the `height` to 1, the padding isn't applied at the bottom
// end of the frame. (I guess it's a bug.) Setting the frame to a height
// less than `1` first is a workaround to counter that behaviour.
if ( height === 1 ) {
this.setFrame(
_({}).extend( newFrame, { height: screen.height - 50 })
);
}
this.setFrame( newFrame );
this.focusWindow();
return this;
};
// #### Window#toFullScreen()
//
// Convenience method, doing exactly what it says. Returns the window
// instance.
Window.prototype.toFullScreen = function() {
return this.toGrid( 0, 0, 1, 1 );
};
// #### Window#toN()
//
// Convenience method, pushing the window to the top half of the screen.
// Returns the window instance.
Window.prototype.toN = function() {
return this.toGrid( 0, 0, 1, 0.5 );
};
// #### Window#toNE()
//
// Convenience method, pushing the window to the top-right quarter of the
// screen. Returns the window instance.
Window.prototype.toNE = function() {
return this.toGrid( 0.5, 0, 0.5, 0.5 );
};
// #### Window#toE()
//
// Convenience method, pushing the window to the right half of the screen.
// Returns the window instance.
Window.prototype.toE = function() {
return this.toGrid( 0.5, 0, 0.5, 1 );
};
// #### Window#toSE()
//
// Convenience method, pushing the window to the bottom-right quarter of the
// screen. Returns the window instance.
Window.prototype.toSE = function() {
return this.toGrid( 0.5, 0.5, 0.5, 0.5 );
};
// #### Window#toS()
//
// Convenience method, pushing the window to the bottom half of the screen.
// Returns the window instance.
Window.prototype.toS = function() {
return this.toGrid( 0, 0.5, 1, 0.5 );
};
// #### Window#toSW()
//
// Convenience method, pushing the window to the bottom-left quarter of the
// screen. Returns the window instance.
Window.prototype.toSW = function() {
return this.toGrid( 0, 0.5, 0.5, 0.5 );
};
// #### Window#toW()
//
// Convenience method, pushing the window to the left half of the screen.
// Returns the window instance.
Window.prototype.toW = function() {
return this.toGrid( 0, 0, 0.5, 1 );
};
// #### Window#toNW()
//
// Convenience method, pushing the window to the top-left quarter of the
// screen. Returns the window instance.
Window.prototype.toNW = function() {
return this.toGrid( 0, 0, 0.5, 0.5 );
};
// #### Window#toggleFullscreen()
//
// Stores the window position and size, then makes the window full screen.
// Should the window be full screen already, its original position and size
// is restored. Returns the window instance.
Window.prototype.toggleFullscreen = function() {
if ( previousSizes[ this ] ) {
this.setFrame( previousSizes[ this ] );
delete previousSizes[ this ];
}
else {
previousSizes[ this ] = this.frame();
this.toFullScreen();
}
return this;
};
// ### Helper methods `App`
//
// #### App.findByTitle()
//
// Finds the window with a certain title. Expects a string, returns a window
// instance or `undefined`. If there are several windows with the same title,
// the first found instance is returned.
App.findByTitle = function( title ) {
return _( this.runningApps() ).find( function( app ) {
if ( app.title() === title ) {
app.show();
return true;
}
});
};
// #### App#findWindowMatchingTitle()
//
// Finds the window whose title matches a regex pattern. Expects a string
// (the pattern), returns a window instance or `undefined`. If there are
// several matching windows, the first found instance is returned.
App.prototype.findWindowMatchingTitle = function( title ) {
var regexp = new RegExp( title );
return _( this.visibleWindows() ).find( function( win ) {
return regexp.test( win.title() );
});
};
// #### App#findWindowNotMatchingTitle()
//
// Finds the window whose title doesn't match a regex pattern. Expects a
// string (the pattern), returns a window instance or `undefined`. If there
// are several matching windows, the first found instance is returned.
App.prototype.findWindowNotMatchingTitle = function( title ) {
var regexp = new RegExp( title );
return _( this.visibleWindows() ).find( function( win ) {
return !regexp.test( win.title() );
});
};
// #### App#firstWindow()
//
// Returns the first visible window of the app or `undefined`.
App.prototype.firstWindow = function() {
return this.visibleWindows()[ 0 ];
};
// }}}
// Move Windows Between Monitors {{{
// --------------------------------------------------------------------------------
function moveToScreen(win, screen) {
if (!screen) { return; }
var frame = win.frame();
var oldScreenRect = win.screen().frameWithoutDockOrMenu();
var newScreenRect = screen.frameWithoutDockOrMenu();
var xRatio = newScreenRect.width / oldScreenRect.width;
var yRatio = newScreenRect.height / oldScreenRect.height;
win.setFrame({
x: (Math.round(frame.x - oldScreenRect.x) * xRatio) + newScreenRect.x,
y: (Math.round(frame.x - oldScreenRect.y) * yRatio) + newScreenRect.y,
width: Math.round(frame.width * xRatio),
height: Math.round(frame.height * yRatio)
});
}
function circularLookup(array, index) {
if (index < 0) { return array[array.length + (index % array.length)]; }
return array[index % array.length];
}
function rotateMonitors(offset) {
var win = Window.focusedWindow();
var currentScreen = win.screen();
var screens = [currentScreen];
for (var x = currentScreen.previousScreen(); x != win.screen(); x = x.previousScreen() ) {
screens.push(x);
}
screens = _(screens).sortBy(function(s) { return s.frameWithoutDockOrMenu().x });
var currentIndex = _(screens).indexOf(currentScreen);
moveToScreen(win, circularLookup(screens, currentIndex + offset));
}
function leftOneMonitor() {
rotateMonitors(-1);
}
function rightOneMonitor() {
rotateMonitors(1);
}
// }}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment