Last active
August 29, 2015 14:03
-
-
Save Linell/00d3549127fbe47f7211 to your computer and use it in GitHub Desktop.
My dotfile for Phoenix - (https://github.com/sdegutis/Phoenix).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
▄███████▄ ▄█ █▄ ▄██████▄ ▄████████ ███▄▄▄▄ ▄█ ▀████ ▐████▀ | |
███ ███ ███ ███ ███ ███ ███ ███ ███▀▀▀██▄ ███ ███▌ ████▀ | |
███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███▌ ███ ▐███ | |
███ ███ ▄███▄▄▄▄███▄▄ ███ ███ ▄███▄▄▄ ███ ███ ███▌ ▀███▄███▀ | |
▀█████████▀ ▀▀███▀▀▀▀███▀ ███ ███ ▀▀███▀▀▀ ███ ███ ███▌ ████▀██▄ | |
███ ███ ███ ███ ███ ███ █▄ ███ ███ ███ ▐███ ▀███ | |
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ▄███ ███▄ | |
▄████▀ ███ █▀ ▀██████▀ ██████████ ▀█ █▀ █▀ ████ ███▄ | |
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