Last active
August 19, 2019 19:46
-
-
Save sennah911/10012494 to your computer and use it in GitHub Desktop.
My config file 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
// This is my attempt at making Phoenix as vim-like as possible. A good chunk | |
// of the code comes from https://gist.github.com/teetrinkers/9435065 | |
// | |
// Command mode is activated with shift-ctrl-alt-command-space | |
// When we are in command mode, we can do things like: | |
// "h" to move current window to the left side of the screen | |
// "mh" to move the current window a nudge | |
// "mH" moves the window all the way to the left | |
// "34m" moves the window to the imaginary grid position 3:4 | |
// "10mh" to move the current window 10 nudges | |
// "4gk" to grow the window 4 times from the top side | |
// "2389g" set the current window to span the imaginary grids located at 2:3 and 8:9 | |
// "pq" set the window to preset q position/size (there are also "pA", "pd", "pC" and so on...) | |
// "sl" to shrink the window from the right side | |
// "." to repeat last command | |
// "q[a-z]" starts recording of temporary macros | |
// "q" then stops it | |
// "@[a-z]" plays back specified register | |
// "shift-2" executes the macro | |
// and lots lots more... | |
// | |
// | |
// Find me at https://github.com/sennah911 | |
var mNone = [], | |
mCmd = ['cmd'], | |
mShift = ['shift'], | |
nudgePixels = 10, | |
largeGridNum = 10; | |
smallGridNum = 40; | |
menuHeight = 20; | |
padding = 0, | |
previousSizes = {}; | |
// Remembers hotkey bindings. | |
var keys = []; | |
function bind(key, mods, callback) { | |
keys.push(api.bind(key, mods, callback)); | |
} | |
// ############################################################################ | |
// Modal activation - curtesy of teetrinkers | |
// ############################################################################ | |
// Modal activator | |
// This hotkey enables/disables all other hotkey | |
api.bind('space', ['cmd','shift','alt','ctrl'], function() { | |
if (!active) { | |
enableKeys(); | |
} else { | |
disableKeys(); | |
} | |
}); | |
api.bind('n', ['cmd','shift','alt','ctrl'], function() { | |
Window.focusedWindow().focusNextWindowOnSameScreen(); | |
}); | |
var buffer = ""; | |
var lastBuffer = ""; | |
var macros = {}; | |
var isRecording = false; | |
var recordingToRegister = ""; | |
var showingOverlay = false; | |
function interperateKeystroke(key) { | |
api.alert(key); | |
if (key != ".") { | |
buffer += key; | |
} | |
if (isRecording && key !== "q") { | |
macros[recordingToRegister] += key; | |
} | |
var command = parser.parse(buffer); | |
if(command.description in commands) { | |
lastBuffer = buffer; | |
commands[command.description](command.value); | |
} | |
} | |
function interperateKeystrokes(keys) { | |
for (var i = 0; i < keys.length; i++) { | |
var c = keys.charAt(i); | |
interperateKeystroke(c); | |
} | |
lastBuffer = keys; | |
} | |
bind('.', mNone, function() { interperateKeystrokes(lastBuffer) }); | |
bind('3', mShift, function() { | |
showingOverlay = !showingOverlay; | |
api.overlay(showingOverlay, "/Users/hannesremahl/Desktop/grid.png"); | |
}); | |
bind('escape', mNone, function() { | |
if (buffer === "") { | |
disableKeys(); | |
} else { | |
buffer = ""; | |
} | |
}); | |
// All of vim is not needed, but keeping it like this for now... | |
var opTest = new RegExp('\(\.\*\?\)\(S\|s\|f\|m\|c\|d\|y\|~\|g~\|gu\|gU\|!\|=\|gg\|g\\?\|>\|<\|zf\|g@\)$'); | |
var motions = ['g', 'H', 'J', 'K', 'L', 'n', 'p[a-z\|A-Z]', '@@', '@[a-z]', 'q', 'q[a-z]', 'h', '%', 'l','0','\\$','\\^','g_','\\|','\(?:\'\|`\)\(\?\:[a-z]\)','\(?:F\|t\|T\)\(\?\:.\)',';',',','k','j','\\+','-','_','(?:[1-9]+[0-9]*|)G','e','E','w','W','b','B','ge','gE','\\(','\\)','\\{','\\}','\\]\\]','\\]\\[','\\[\\[','\\[\\]','(?:\\?|\\/)(?:\\S+)\\n']; | |
var motionTest = new RegExp('\(\.\*\?\)\(' + motions.join('\|') + '\)\$'); | |
var positions = { | |
'a': [0, 0, 0.4, 1], | |
'A': [0, 0, 0.6, 1], | |
'd': [0.6, 0, 0.4, 1], | |
'D': [0.4, 0, 0.6, 1], | |
'x': [0, 0.6, 1, 0.4], | |
'X': [0, 0.4, 1, 0.6], | |
'w': [0, 0, 1, 0.4], | |
'W': [0, 0, 1, 0.6], | |
'q': [0, 0, 0.4, 0.6], | |
'Q': [0, 0, 0.6, 0.6], | |
'e': [0.6, 0, 0.4, 0.6], | |
'E': [0.4, 0, 0.6, 0.6], | |
'c': [0.6, 0.6, 0.4, 0.4], | |
'C': [0.4, 0.4, 0.6, 0.4], | |
'z': [0, 0.6, 0.4, 0.4], | |
'Z': [0, 0.6, 0.6, 0.4], | |
'f': [0, 0, 1, 1] | |
} | |
var commands = { | |
'{count}{motion}': function(commandValue) { | |
var count = commandValue[0]; | |
var motion = commandValue[1]; | |
if (motion === "g") { | |
var countStr = ('000000000' + count).substr(-4); | |
var thousands = parseInt(countStr.charAt(0)); | |
var hundreds = parseInt(countStr.charAt(1)); | |
var tens = parseInt(countStr.charAt(2)); | |
var ones = parseInt(countStr.charAt(3)); | |
Window.focusedWindow().toGrid(thousands/10, hundreds/10, (tens+1-thousands)/10, (ones+1-hundreds)/10); | |
buffer = ""; | |
} else { | |
while(count--) { | |
commands['{motion}']([motion]); | |
} | |
} | |
}, | |
'{motion}': function(commandValue) { | |
var motion = commandValue[0]; | |
if (motion === "h") { | |
Window.focusedWindow().toGrid(0, 0, 0.5, 1); | |
buffer = ""; | |
} else if (motion === "j") { | |
Window.focusedWindow().toGrid(0, 0.5, 1, 0.5); | |
buffer = ""; | |
} else if (motion === "k") { | |
Window.focusedWindow().toGrid(0, 0, 1, 0.5); | |
buffer = ""; | |
} else if (motion === "l") { | |
Window.focusedWindow().toGrid(0.5, 0, 0.5, 1); | |
buffer = ""; | |
} else if (motion.charAt(0) === "q") { | |
if (!isRecording && motion.length == 2) { | |
api.alert("recording to register " + motion.charAt(1)); | |
recordingToRegister = motion.charAt(1); | |
macros[recordingToRegister] = ""; | |
isRecording = true; | |
buffer = ""; | |
} else if (isRecording && motion.length == 1) { | |
api.alert("Stopped recording to register " + recordingToRegister); | |
isRecording = false; | |
api.alert(macros[recordingToRegister]); | |
recordingToRegister = ""; | |
buffer = ""; | |
} | |
} else if (motion.charAt(0) == "@") { | |
if (motion === "@@") { | |
//todo | |
} else { | |
buffer = ""; | |
interperateKeystrokes(macros[motion.charAt(1)]); | |
} | |
} else if (motion.charAt(0) === "p") { | |
//move to position | |
var position = positions[motion.charAt(1)]; | |
Window.focusedWindow().toGrid(position[0], position[1], position[2], position[3]); | |
buffer = ""; | |
} else if (motion === "n") { | |
Window.focusedWindow().focusNextWindowOnSameScreen(); | |
buffer = ""; | |
} | |
}, | |
'{count}{operator}': function(commandValue) { | |
count = commandValue[0]; | |
operator = commandValue[1]; | |
if (operator === "m") { | |
//Moving to grid | |
var countStr = ('000000000' + count).substr(-2); | |
var tens = parseInt(countStr.charAt(0)); | |
var ones = parseInt(countStr.charAt(1)); | |
var win = Window.focusedWindow(); | |
var frame = win.frame(); | |
var screenFrame = win.screen().frameWithoutDockOrMenu(); | |
frame.x = tens * screenFrame.width / largeGridNum; | |
frame.y = ones * screenFrame.height / largeGridNum + menuHeight; | |
win.setFrame(frame); | |
buffer = ""; | |
} | |
}, | |
'{count}{operator}{motion}': function(commandValue) { | |
count = commandValue[0]; | |
operator = commandValue[1]; | |
motion = commandValue[2]; | |
if (operator === "S") { | |
// Split with count % | |
count /= 100.0; | |
if (motion === "h") { | |
Window.focusedWindow().splitLeft(count); | |
} else if (motion === "j") { | |
Window.focusedWindow().splitDown(count); | |
} else if (motion === "k") { | |
Window.focusedWindow().splitUp(count); | |
} else if (motion === "l") { | |
Window.focusedWindow().splitRight(count); | |
} | |
buffer = ""; | |
} else { | |
while(count--) { | |
commands['{operator}{motion}']([operator, motion]); | |
} | |
} | |
}, | |
'{operator}{count}{motion}': function(commandValue) { | |
operator = commandValue[0]; | |
count = commandValue[1]; | |
motion = commandValue[2]; | |
while(count--) { | |
commands['{operator}{motion}']([operator, motion]); | |
} | |
}, | |
'{operator}{motion}': function(commandValue) { | |
operator = commandValue[0]; | |
motion = commandValue[1]; | |
if (operator === "m") { | |
if (motion === "h") { | |
Window.focusedWindow().nudgeLeft( 5 ); | |
buffer = ""; | |
} else if (motion === "j") { | |
Window.focusedWindow().nudgeDown( 5 ); | |
buffer = ""; | |
} else if (motion === "k") { | |
Window.focusedWindow().nudgeUp( 5 ); | |
buffer = ""; | |
} else if (motion === "l") { | |
Window.focusedWindow().nudgeRight( 5 ); | |
buffer = ""; | |
} else if (motion === "H") { | |
Window.focusedWindow().pushLeft(); | |
buffer = ""; | |
} else if (motion === "J") { | |
Window.focusedWindow().pushDown(); | |
buffer = ""; | |
} else if (motion === "K") { | |
Window.focusedWindow().pushUp(); | |
buffer = ""; | |
} else if (motion === "L") { | |
Window.focusedWindow().pushRight(); | |
buffer = ""; | |
} | |
} else if (operator === ">") { | |
if (motion === "h") { | |
Window.focusedWindow().growLeft(); | |
buffer = ""; | |
} else if (motion === "j") { | |
Window.focusedWindow().growBottom(); | |
buffer = ""; | |
} else if (motion === "k") { | |
Window.focusedWindow().growTop(); | |
buffer = ""; | |
} else if (motion === "l") { | |
Window.focusedWindow().growRight(); | |
buffer = ""; | |
} | |
} else if (operator === "<") { | |
if (motion === "h") { | |
Window.focusedWindow().shrinkLeft(); | |
buffer = ""; | |
} else if (motion === "j") { | |
Window.focusedWindow().shrinkBottom(); | |
buffer = ""; | |
} else if (motion === "k") { | |
Window.focusedWindow().shrinkTop(); | |
buffer = ""; | |
} else if (motion === "l") { | |
Window.focusedWindow().shrinkRight(); | |
buffer = ""; | |
} | |
} else if (operator === "f") { | |
if (motion === "h") { | |
Window.focusedWindow().focusWindowLeft(); | |
buffer = ""; | |
} else if (motion === "j") { | |
Window.focusedWindow().focusWindowDown(); | |
buffer = ""; | |
} else if (motion === "k") { | |
Window.focusedWindow().focusWindowUp(); | |
buffer = ""; | |
} else if (motion === "l") { | |
Window.focusedWindow().focusWindowRight(); | |
buffer = ""; | |
} | |
} else if (operator === "s") { | |
if (motion === "h") { | |
Window.focusedWindow().splitLeft(0.5); | |
buffer = ""; | |
} else if (motion === "j") { | |
Window.focusedWindow().splitDown(0.5); | |
buffer = ""; | |
} else if (motion === "k") { | |
Window.focusedWindow().splitUp(0.5); | |
buffer = ""; | |
} else if (motion === "l") { | |
Window.focusedWindow().splitRight(0.5); | |
buffer = ""; | |
} | |
} | |
} | |
}; | |
// These keys end Phoenix mode. bind('escape', [], function() { disableKeys(); }); bind('return', [], function() { disableKeys(); }); | |
// Bind all the keys | |
bind("`", mNone, function() { interperateKeystroke("`"); }); | |
bind('1', mNone, function() { interperateKeystroke("1"); }); | |
bind('2', mNone, function() { interperateKeystroke("2"); }); | |
bind('3', mNone, function() { interperateKeystroke("3"); }); | |
bind('4', mNone, function() { interperateKeystroke("4"); }); | |
bind('5', mNone, function() { interperateKeystroke("5"); }); | |
bind('6', mNone, function() { interperateKeystroke("6"); }); | |
bind('7', mNone, function() { interperateKeystroke("7"); }); | |
bind('8', mNone, function() { interperateKeystroke("8"); }); | |
bind('9', mNone, function() { interperateKeystroke("9"); }); | |
bind('0', mNone, function() { interperateKeystroke("0"); }); | |
bind('-', mNone, function() { interperateKeystroke("-"); }); | |
bind('=', mNone, function() { interperateKeystroke("="); }); | |
bind('q', mNone, function() { interperateKeystroke("q"); }); | |
bind('w', mNone, function() { interperateKeystroke("w"); }); | |
bind('e', mNone, function() { interperateKeystroke("e"); }); | |
bind('r', mNone, function() { interperateKeystroke("r"); }); | |
bind('t', mNone, function() { interperateKeystroke("t"); }); | |
bind('y', mNone, function() { interperateKeystroke("y"); }); | |
bind('u', mNone, function() { interperateKeystroke("u"); }); | |
bind('i', mNone, function() { interperateKeystroke("i"); }); | |
bind('o', mNone, function() { interperateKeystroke("o"); }); | |
bind('p', mNone, function() { interperateKeystroke("p"); }); | |
bind('[', mNone, function() { interperateKeystroke("["); }); | |
bind(']', mNone, function() { interperateKeystroke("]"); }); | |
bind("\\", mNone, function() { interperateKeystroke("\\"); }); | |
bind('a', mNone, function() { interperateKeystroke("a"); }); | |
bind('s', mNone, function() { interperateKeystroke("s"); }); | |
bind('d', mNone, function() { interperateKeystroke("d"); }); | |
bind('f', mNone, function() { interperateKeystroke("f"); }); | |
bind('g', mNone, function() { interperateKeystroke("g"); }); | |
bind('h', mNone, function() { interperateKeystroke("h"); }); | |
bind('j', mNone, function() { interperateKeystroke("j"); }); | |
bind('k', mNone, function() { interperateKeystroke("k"); }); | |
bind('l', mNone, function() { interperateKeystroke("l"); }); | |
bind(';', mNone, function() { interperateKeystroke(";"); }); | |
bind("'", mNone, function() { interperateKeystroke("'"); }); | |
bind('z', mNone, function() { interperateKeystroke("z"); }); | |
bind('x', mNone, function() { interperateKeystroke("x"); }); | |
bind('c', mNone, function() { interperateKeystroke("c"); }); | |
bind('v', mNone, function() { interperateKeystroke("v"); }); | |
bind('b', mNone, function() { interperateKeystroke("b"); }); | |
bind('n', mNone, function() { interperateKeystroke("n"); }); | |
bind('m', mNone, function() { interperateKeystroke("m"); }); | |
bind(',', mNone, function() { interperateKeystroke(","); }); | |
bind('.', mNone, function() { interperateKeystroke("."); }); | |
bind('/', mNone, function() { interperateKeystroke("/"); }); | |
bind("`", mShift, function() { interperateKeystroke("~"); }); | |
bind('1', mShift, function() { interperateKeystroke("!"); }); | |
bind('2', mShift, function() { interperateKeystroke("@"); }); | |
bind('3', mShift, function() { interperateKeystroke("#"); }); | |
bind('4', mShift, function() { interperateKeystroke("$"); }); | |
bind('5', mShift, function() { interperateKeystroke("%"); }); | |
bind('6', mShift, function() { interperateKeystroke("^"); }); | |
bind('7', mShift, function() { interperateKeystroke("&"); }); | |
bind('8', mShift, function() { interperateKeystroke("*"); }); | |
bind('9', mShift, function() { interperateKeystroke("("); }); | |
bind('0', mShift, function() { interperateKeystroke(")"); }); | |
bind('_', mShift, function() { interperateKeystroke("_"); }); | |
bind('+', mShift, function() { interperateKeystroke("+"); }); | |
bind('q', mShift, function() { interperateKeystroke("Q"); }); | |
bind('w', mShift, function() { interperateKeystroke("W"); }); | |
bind('e', mShift, function() { interperateKeystroke("E"); }); | |
bind('r', mShift, function() { interperateKeystroke("R"); }); | |
bind('t', mShift, function() { interperateKeystroke("T"); }); | |
bind('y', mShift, function() { interperateKeystroke("Y"); }); | |
bind('u', mShift, function() { interperateKeystroke("U"); }); | |
bind('i', mShift, function() { interperateKeystroke("I"); }); | |
bind('o', mShift, function() { interperateKeystroke("O"); }); | |
bind('p', mShift, function() { interperateKeystroke("P"); }); | |
bind('[', mShift, function() { interperateKeystroke("{"); }); | |
bind(']', mShift, function() { interperateKeystroke("}"); }); | |
bind("\\", mShift, function() { interperateKeystroke("|"); }); | |
bind('a', mShift, function() { interperateKeystroke("A"); }); | |
bind('s', mShift, function() { interperateKeystroke("S"); }); | |
bind('d', mShift, function() { interperateKeystroke("D"); }); | |
bind('f', mShift, function() { interperateKeystroke("F"); }); | |
bind('g', mShift, function() { interperateKeystroke("G"); }); | |
bind('h', mShift, function() { interperateKeystroke("H"); }); | |
bind('j', mShift, function() { interperateKeystroke("J"); }); | |
bind('k', mShift, function() { interperateKeystroke("K"); }); | |
bind('l', mShift, function() { interperateKeystroke("L"); }); | |
bind(';', mShift, function() { interperateKeystroke(":"); }); | |
bind("'", mShift, function() { interperateKeystroke('"'); }); | |
bind('z', mShift, function() { interperateKeystroke("Z"); }); | |
bind('x', mShift, function() { interperateKeystroke("X"); }); | |
bind('c', mShift, function() { interperateKeystroke("C"); }); | |
bind('v', mShift, function() { interperateKeystroke("V"); }); | |
bind('b', mShift, function() { interperateKeystroke("B"); }); | |
bind('n', mShift, function() { interperateKeystroke("N"); }); | |
bind('m', mShift, function() { interperateKeystroke("M"); }); | |
bind(',', mShift, function() { interperateKeystroke("<"); }); | |
bind('.', mShift, function() { interperateKeystroke(">"); }); | |
bind('/', mShift, function() { interperateKeystroke("?"); }); | |
// ############################################################################ | |
// Helpers - mostly curtesy of teetrinkers | |
// ############################################################################ | |
// Disables all remembered keys. | |
function disableKeys() { | |
active = false; | |
_(keys).each(function(key) { | |
key.disable(); | |
}); | |
api.alert("done", 0.5); | |
mode = "normal"; | |
count = 0; | |
api.setTint([0,1],[0,1],[0,1]); | |
api.overlay(false, "/Users/hannesremahl/Desktop/grid.png"); | |
//args = new Array("-v", "victoria", "Off"); | |
//api.runCommand("/usr/bin/say", args); | |
} | |
// Enables all remembered keys. | |
function enableKeys() { | |
active = true; | |
_(keys).each(function(key) { | |
key.enable(); | |
}); | |
api.alert("Phoenix", 0.5); | |
api.setTint([0, 1], [0, 1], [0, 0.4]); | |
api.overlay(showingOverlay, "/Users/hannesremahl/Desktop/grid.png"); | |
//args = new Array("-v", "victoria", "On"); | |
//api.runCommand("/usr/bin/say", args); | |
} | |
function windowToGrid(window, x, y, width, height) { | |
var screen = window.screen().frameWithoutDockOrMenu(); | |
window.setFrame({ | |
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 ) | |
}); | |
window.focusWindow(); | |
return window; | |
} | |
function toGrid(x, y, width, height) { | |
windowToGrid(Window.focusedWindow(), x, y, width, height); | |
} | |
Window.prototype.toGrid = function(x, y, width, height) { | |
windowToGrid(this, x, y, width, height); | |
}; | |
// Convenience method, doing exactly what it says. Returns the window | |
// instance. | |
Window.prototype.toFullScreen = function() { | |
return this.toGrid( 0, 0, 1, 1 ); | |
}; | |
Window.prototype.focusNextWindowOnSameScreen = function() { | |
var currentWindow = Window.focusedWindow(); | |
var windows = currentWindow.otherWindowsOnSameScreen(); | |
windows.push(currentWindow); | |
windows = _.chain(windows).sortBy(function(window) { return window.hash()}).value(); | |
windows[(_.indexOf(windows, currentWindow) + 1) % windows.length].focusWindow(); | |
}; | |
// 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 ); | |
}; | |
// 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 ); | |
}; | |
// 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 ); | |
}; | |
// 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 ); | |
}; | |
// 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; | |
}; | |
Window.prototype.pushLeft = function() { | |
var win = this, | |
frame = win.frame(); | |
frame.x = 0; | |
win.setFrame(frame); | |
} | |
Window.prototype.pushDown = function() { | |
var win = this, | |
screen = win.screen().frameWithoutDockOrMenu(); | |
win.nudgeDown(screen.height); | |
} | |
Window.prototype.pushUp = function() { | |
var win = this, | |
frame = win.frame(); | |
frame.y = 0; | |
win.setFrame(frame); | |
} | |
Window.prototype.pushRight = function() { | |
var win = this, | |
screen = win.screen().frameWithoutDockOrMenu(); | |
win.nudgeRight(screen.width); | |
} | |
Window.prototype.splitLeft = function(amount) { | |
var win = this, | |
frame = win.frame(); | |
amount = 1 - amount; | |
frame.width *= amount; | |
frame.x = win.frame().x; | |
win.setFrame(frame); | |
} | |
Window.prototype.splitRight = function(amount) { | |
var win = this, | |
frame = win.frame(); | |
amount = 1 - amount; | |
frame.width *= amount; | |
win.setFrame(frame); | |
} | |
Window.prototype.splitDown = function(amount) { | |
var win = this, | |
frame = win.frame(); | |
amount = 1 - amount; | |
var newy = frame.y + (frame.height - frame.height * amount); | |
frame.height *= amount; | |
frame.y = newy; | |
win.setFrame(frame); | |
} | |
Window.prototype.splitUp = function(amount) { | |
var win = this, | |
frame = win.frame(); | |
amount = 1 - amount; | |
frame.height *= amount; | |
win.setFrame(frame); | |
} | |
Window.prototype.splitRight = function(amount) { | |
var win = this, | |
frame = win.frame(); | |
amount = 1 - amount; | |
var newx = frame.x + (frame.width - frame.width * amount); | |
frame.width *= amount; | |
frame.x = newx; | |
win.setFrame(frame); | |
} | |
// Move the currently focussed window left by [`nudgePixel`] pixels. | |
Window.prototype.nudgeLeft = function( factor ) { | |
var win = this, | |
frame = win.frame(), | |
pixels = win.screen().frameIncludingDockAndMenu().width / smallGridNum; | |
if (frame.x >= pixels) { | |
frame.x -= pixels; | |
} else { | |
frame.x = 0; | |
} | |
win.setFrame( frame ); | |
}; | |
// Move the currently focussed window right by [`nudgePixel`] pixels. | |
Window.prototype.nudgeRight = function( factor ) { | |
var win = this, | |
frame = win.frame(), | |
maxLeft = win.screen().frameIncludingDockAndMenu().width - frame.width, | |
pixels = win.screen().frameIncludingDockAndMenu().width / smallGridNum; | |
if (frame.x < maxLeft - pixels) { | |
frame.x += pixels; | |
} else { | |
frame.x = maxLeft; | |
} | |
win.setFrame( frame ); | |
}; | |
// Move the currently focussed window left by [`nudgePixel`] pixels. | |
Window.prototype.nudgeUp = function( factor ) { | |
var win = this, | |
frame = win.frame(), | |
pixels = win.screen().frameIncludingDockAndMenu().height / smallGridNum; | |
if (frame.y >= pixels) { | |
frame.y -= pixels; | |
} else { | |
frame.y = 0; | |
} | |
win.setFrame( frame ); | |
}; | |
// Move the currently focussed window right by [`nudgePixel`] pixels. | |
Window.prototype.nudgeDown = function( factor ) { | |
var win = this, | |
frame = win.frame(), | |
maxTop = win.screen().frameIncludingDockAndMenu().height - frame.height, | |
pixels = win.screen().frameIncludingDockAndMenu().height / smallGridNum; | |
if (frame.y < maxTop - pixels) { | |
frame.y += pixels; | |
} else { | |
frame.y = maxTop; | |
} | |
win.setFrame( frame ); | |
}; | |
// #### Functions for growing / shrinking the focussed window. | |
Window.prototype.growTop = function() { | |
this.nudgeUp(6); | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameIncludingDockAndMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().height / smallGridNum; | |
if (frame.height < screenFrame.height - pixels) { | |
frame.height += pixels; | |
} else { | |
frame.height = screenFrame.height; | |
} | |
win.setFrame(frame); | |
}; | |
Window.prototype.growBottom = function() { | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameIncludingDockAndMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().height / smallGridNum; | |
if (frame.height < screenFrame.height - pixels) { | |
frame.height += pixels; | |
} else { | |
frame.height = screenFrame.height; | |
} | |
win.setFrame(frame); | |
}; | |
Window.prototype.growLeft = function() { | |
this.nudgeLeft(6); | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameIncludingDockAndMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().width / smallGridNum; | |
if (frame.width < screenFrame.width - pixels) { | |
frame.width += pixels; | |
} else { | |
frame.width = screenFrame.width; | |
} | |
win.setFrame(frame); | |
}; | |
Window.prototype.growRight = function() { | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameIncludingDockAndMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().width / smallGridNum; | |
if (frame.width < screenFrame.width - pixels) { | |
frame.width += pixels; | |
} else { | |
frame.width = screenFrame.width; | |
} | |
win.setFrame(frame); | |
}; | |
Window.prototype.shrinkTop = function() { | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameWithoutDockOrMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().height / smallGridNum; | |
if (frame.height >= pixels * 2) { | |
frame.height -= pixels; | |
} else { | |
frame.height = pixels; | |
} | |
win.setFrame(frame); | |
this.nudgeDown(6); | |
}; | |
Window.prototype.shrinkBottom = function() { | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameWithoutDockOrMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().height / smallGridNum; | |
if (frame.height >= pixels * 2) { | |
frame.height -= pixels; | |
} else { | |
frame.height = pixels; | |
} | |
win.setFrame(frame); | |
}; | |
Window.prototype.shrinkLeft = function() { | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameIncludingDockAndMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().width / smallGridNum; | |
if (frame.width >= pixels * 2) { | |
frame.width -= pixels; | |
} else { | |
frame.width = pixels; | |
} | |
win.setFrame(frame); | |
this.nudgeRight(6); | |
}; | |
Window.prototype.shrinkRight = function() { | |
var win = this, | |
frame = win.frame(), | |
screenFrame = win.screen().frameIncludingDockAndMenu(), | |
pixels = win.screen().frameIncludingDockAndMenu().width / smallGridNum; | |
if (frame.width >= pixels * 2) { | |
frame.width -= pixels; | |
} else { | |
frame.width = pixels; | |
} | |
win.setFrame(frame); | |
}; | |
// ### Helper methods `App` | |
// | |
// 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; | |
} | |
}); | |
}; | |
// 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() ); | |
}); | |
}; | |
// 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() ); | |
}); | |
}; | |
// Returns the first visible window of the app or `undefined`. | |
App.prototype.firstWindow = function() { | |
return this.visibleWindows()[ 0 ]; | |
}; | |
// ############################################################################ | |
// Init | |
// ############################################################################ | |
// Initially disable all hotkeys | |
disableKeys(); | |
// ############################################################################ | |
// The following code comes from https://github.com/itsjoesullivan/js-vim-command | |
// ############################################################################ | |
var Parser = function() {}; | |
/** Parse a command | |
input: string of text | |
output: object containing the interpreted string and an array with each element | |
*/ | |
Parser.prototype.parse = function(command) { | |
var motion = this.getLastMotion(command); | |
var prefix = command; | |
var command = { | |
description: '', | |
value: [] | |
}; | |
var next; | |
while(prefix.length) { | |
next = this.getLastCount(prefix) || this.getLastMotion(prefix) || this.getLastOperator(prefix); | |
if(!next) break | |
prefix = next.prefix; | |
command.description = next.description + command.description; | |
command.value.unshift(next.value); | |
command.prefix = next.prefix; | |
} | |
return command.description.length ? command : false; | |
var x = this.getLastCount(command) || this.getLastMotion(command) || this.getLastOperator(command); | |
/* | |
{count} | |
{count}{op}{motion} | |
{op}{count}{motion} | |
{count}{op}{count}{motion} | |
{motion} | |
{ | |
*/ | |
}; | |
//Test for operator | |
/** Determines whether command is an operator, returning it if so */ | |
Parser.prototype.getLastOperator = function(command) { | |
var op = opTest.exec(command) | |
if(!op) return; | |
return { | |
description: '{operator}', | |
value: op[2], | |
prefix: op[1] | |
}; | |
}; | |
/** Get motions, of which there are a variety | |
h l 0 ^ g_ | (f|F|t|T){char} ; , k j - + _ G | |
word motions: | |
e E w W b B ge gE | |
text object motions: | |
( ) { } ]] [] [[ [] | |
*/ | |
Parser.prototype.getLastMotion = function(command) { | |
var motion = motionTest.exec(command); | |
if(!motion) return; | |
return { | |
description: '{motion}', | |
value: motion[2], | |
prefix: motion[1] | |
} | |
}; | |
var countTest = /(.*?)([0-9]+[0-9]*)$/ | |
Parser.prototype.getLastCount = function(command) { | |
var countResult = countTest.exec(command); | |
if(!countResult) return; | |
return { | |
description: '{count}', | |
value: parseInt(countResult[2]), | |
prefix: countResult[1] | |
}; | |
}; | |
parser = new Parser(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could you link to the grid.png?