├── README.md ├── assets ├── Screenshot 2016-03-10 00.39.46.png ├── battery-charging.pdf ├── battery-charging.svg ├── battery.png ├── lightbulb_off.pdf ├── lightbulb_off.png └── lightbulb_on.png ├── battery.lua ├── battigayo.lua ├── cheatsheets.lua ├── init.lua ├── random.lua └── windows.lua /README.md: -------------------------------------------------------------------------------- 1 | # hammerspoon-config 2 | My configuration files for [Hammerspoon](http://www.hammerspoon.org "Hammerspoon"). 3 | * Mostly random codes here and there, some of them are copied other are actually written by me. Battery configuration is done. Cheatsheet copycat is on progress, nearly done, few things to fix here and there. Windows configurations work great too. Others are not really finalized. 4 | 5 | ![Cheatsheet copycat Screenshot](https://github.com/dharmapoudel/hammerspoon-config/blob/master/assets/Screenshot%202016-03-10%2000.39.46.png) 6 | -------------------------------------------------------------------------------- /assets/Screenshot 2016-03-10 00.39.46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dharmapoudel/hammerspoon-config/a3b596673ca04ffffd53006cb0a2295c347dec29/assets/Screenshot 2016-03-10 00.39.46.png -------------------------------------------------------------------------------- /assets/battery-charging.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dharmapoudel/hammerspoon-config/a3b596673ca04ffffd53006cb0a2295c347dec29/assets/battery-charging.pdf -------------------------------------------------------------------------------- /assets/battery-charging.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dharmapoudel/hammerspoon-config/a3b596673ca04ffffd53006cb0a2295c347dec29/assets/battery.png -------------------------------------------------------------------------------- /assets/lightbulb_off.pdf: -------------------------------------------------------------------------------- 1 | %PDF-1.2 2 | 1 0 obj 3 | << /Type /Catalog 4 | /Outlines 2 0 R 5 | /Pages 3 0 R 6 | >> 7 | endobj 8 | 2 0 obj 9 | << /Type /Outlines 10 | /Count 0 11 | >> 12 | endobj 13 | 3 0 obj 14 | << /Type /Pages 15 | /Kids [4 0 R] 16 | /Count 1 17 | >> 18 | endobj 19 | 4 0 obj 20 | << /Type /Page 21 | /Parent 3 0 R 22 | /MediaBox [0 0 260 260] 23 | /Contents 5 0 R 24 | /Resources << /ProcSet 6 0 R >> 25 | >> 26 | endobj 27 | 5 0 obj 28 | << /Length 3053 >> 29 | stream 30 | 1.000 1.000 1.000 rg 31 | 0 260 m 32 | 0 0 l 33 | 260 0 l 34 | 260 260 l 35 | 0 260 l 36 | f 37 | h 38 | 0.000 0.000 0.000 rg 39 | 122 211.572 m 40 | 83 206 58.822 167.742 68.478 130 c 41 | 72 116 80.805 107 89.320 96 c 42 | 94.642 89 98 81.427 100 73 c 43 | 100.702 70.570 100.960 65.872 104.184 65.466 c 44 | 108.536 64.919 108.611 70 108.231 73 c 45 | 107 81.293 103.971 88.866 99.691 96 c 46 | 89.206 113.472 74.754 123.749 74 146 c 47 | 72.717 187.504 119.269 217.256 156 197.880 c 48 | 182.233 184 194.574 151 182 124 c 49 | 177.377 113.724 168.359 107 162.206 97.996 c 50 | 158.316 92.209 156.794 78.784 151.686 74.938 c 51 | 148 72.167 141.395 71.725 137 70.627 c 52 | 126.375 67.970 115.501 65.766 105 62.607 c 53 | 101.220 61.464 96.742 55.967 103 54.524 c 54 | 107 53.634 112.212 55.926 116 56.873 c 55 | 126 59.379 135.977 62 146 64.627 c 56 | 150 65.640 157.279 66 160 69.513 c 57 | 164.553 75 164.328 85.482 168.548 92 c 58 | 177.478 105.794 190 114.934 193.550 132 c 59 | 202.467 175.539 167.651 218 122 211.572 c 60 | 155 176 m 61 | 148.872 178.597 142.544 178 136 178 c 62 | 123 178 l 63 | 115 178 l 64 | 112.354 177.996 100 176.969 106.337 171.854 c 65 | 109.356 169.369 114.376 170 118 170 c 66 | 126.831 169.997 151.873 165.608 155 176 c 67 | 112 162.427 m 68 | 108.936 161.471 106 157.519 110.244 155.603 c 69 | 117.552 152.195 131.962 154.999 140 155 c 70 | 142.776 155 147 154.257 149.522 156 c 71 | 154.312 159.587 146.833 162.657 143.999 162.906 c 72 | 134.916 163.703 120.777 165 112 162.427 c 73 | 116 146.427 m 74 | 112.537 145.321 110.683 140.644 115 139.318 c 75 | 120.996 137.581 138.224 137 143.756 139.603 c 76 | 148.488 141.812 144.305 146 140.985 146.772 c 77 | 134.381 148 122.483 148.447 116 146.427 c 78 | 120 120 m 79 | 128.197 111.660 129.525 112.367 139 118 c 80 | 136.991 109.236 125.197 77 140 76 c 81 | 142 87.409 141.756 98.758 145.344 110 c 82 | 146.658 114 150.996 121.477 149.353 125.772 c 83 | 148.360 128.370 145.453 128.865 142.999 128.655 c 84 | 138.685 128.285 135 125.212 131 124.772 c 85 | 125.979 124.241 114 133.615 110.272 126.682 c 86 | 108.197 122.964 112 116.589 113.329 113 c 87 | 116.740 102.637 114.772 87.535 119.588 78.319 c 88 | 124.520 68.880 126 89.703 125.910 92 c 89 | 125.660 95.657 125 99.394 124.386 103 c 90 | 123.333 108.797 121.323 114.283 120 120 c 91 | f 92 | h 93 | 1.000 1.000 1.000 rg 94 | 139 119 m 95 | 140 118 l 96 | 139 119 l 97 | f 98 | h 99 | 0.000 0.000 0.000 rg 100 | 154 56.532 m 101 | 138.923 54 123.804 49 109 45.373 c 102 | 106.184 44.663 95 39.547 103 36.694 c 103 | 107 35.335 113.208 38.178 117 39 c 104 | 147 46.627 l 105 | 150.776 47.571 156.594 47.977 159.547 50.727 c 106 | 164 54.994 157.518 57 154 56.532 c 107 | 154.996 38.492 m 108 | 140.183 36.728 124.462 30.919 110 27 c 109 | 107.677 26.505 94.814 22.262 102.319 18.604 c 110 | 106.188 16.719 112 19 116 20 c 111 | 146 27.627 l 112 | 150 28.635 156.318 29 159.551 31.853 c 113 | 163.810 35.541 158.943 38.961 154.996 38.492 c 114 | 143.985 17 m 115 | 138.593 15.502 135 11.597 129 12.200 c 116 | 124.984 12.596 117.190 18.694 113.619 15.954 c 117 | 109.772 13 115.600 8.258 118 6.999 c 118 | 124.823 3.451 132.961 3.213 140 6 c 119 | 142.946 7.300 147.257 9.271 148.712 12.321 c 120 | 150.330 15.714 147 18 143.985 17 c 121 | f 122 | endstream 123 | endobj 124 | 6 0 obj 125 | [/PDF] 126 | endobj 127 | xref 128 | 0 7 129 | 0000000000 65535 f 130 | 0000000009 00000 n 131 | 0000000092 00000 n 132 | 0000000150 00000 n 133 | 0000000225 00000 n 134 | 0000000374 00000 n 135 | 0000003481 00000 n 136 | trailer 137 | << /Size 7 138 | /Root 1 0 R 139 | >> 140 | startxref 141 | 3506 142 | %%EOF 143 | -------------------------------------------------------------------------------- /assets/lightbulb_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dharmapoudel/hammerspoon-config/a3b596673ca04ffffd53006cb0a2295c347dec29/assets/lightbulb_off.png -------------------------------------------------------------------------------- /assets/lightbulb_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dharmapoudel/hammerspoon-config/a3b596673ca04ffffd53006cb0a2295c347dec29/assets/lightbulb_on.png -------------------------------------------------------------------------------- /battery.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------------- 2 | --/ battery stuffs /-- 3 | ----------------------------------------------------------------------------------- 4 | 5 | local imagePath = os.getenv("HOME") .. '/.hammerspoon/assets/'; 6 | 7 | local battery = { 8 | rem = hs.battery.percentage(), 9 | source = hs.battery.powerSource(), 10 | icon = imagePath ..'battery-charging.pdf', 11 | title = "Battery Status", 12 | sound = "Sosumi", 13 | min = 50, 14 | showPercentage = false 15 | } 16 | 17 | 18 | -- notify when battery is full 19 | function notifyWhenBatteryFullyCharged() 20 | local currentPercentage = hs.battery.percentage() 21 | if currentPercentage == 100 and battery.rem ~= currentPercentage and battery.source == 'AC Power' then 22 | battery.rem = currentPercentage 23 | hs.notify.new({ 24 | title = battery.title, 25 | subTitle = 'Charged completely!', 26 | contentImage = battery.icon, 27 | soundName = battery.sound 28 | }):send() 29 | end 30 | end 31 | 32 | 33 | -- notify when battery is less than battery.min 34 | function notifyWhenBatteryLow() 35 | local currentPercentage = hs.battery.percentage() 36 | if currentPercentage <= battery.min and battery.rem ~= currentPercentage and (currentPercentage % 5 == 0 ) then 37 | battery.rem = currentPercentage 38 | hs.notify.new({ 39 | title = battery.title, 40 | informativeText = 'Battery left: '..battery.rem.."%\nPower Source: "..battery.source, 41 | contentImage = battery.icon, 42 | soundName = battery.sound 43 | }):send() 44 | end 45 | end 46 | 47 | 48 | 49 | -- alert battery source when it changes 50 | function alertPowerSource() 51 | local currentPowerSource= hs.battery.powerSource() 52 | if battery.source ~= currentPowerSource then 53 | battery.source = currentPowerSource 54 | hs.alert.show(battery.source); 55 | end 56 | end 57 | 58 | 59 | 60 | -- display battery percentage on menu bar 61 | function showPercentageonNavbar() 62 | local menuItem = hs.menubar.new(true) 63 | local currentPercentage = hs.battery.percentage() 64 | local remBatteryString = string.format("%.0f", currentPercentage) 65 | menuItem:setTitle(remBatteryString.."%") 66 | end 67 | 68 | 69 | 70 | function watchBattery() 71 | if battery.showPercentage then 72 | showPercentageonNavbar() 73 | end 74 | alertPowerSource() 75 | notifyWhenBatteryLow() 76 | notifyWhenBatteryFullyCharged() 77 | end 78 | 79 | 80 | -- start watching 81 | hs.battery.watcher.new(watchBattery):start() -------------------------------------------------------------------------------- /battigayo.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | --/ Battigayo Schedule /-- 3 | ----------------------------------------------------------------------------- 4 | 5 | local myGroup = 1; 6 | local triads = {"cmd", "alt", "ctrl"} 7 | local basePath = os.getenv("HOME") .. "/.hammerspoon/" 8 | local imagePath = basePath .. 'assets/'; 9 | 10 | -- function getScheule() 11 | -- local url = 'http://api.battigayo.com' 12 | -- hs.http.asyncGet(url, nil, function(status, body) 13 | -- local w = hs.json.decode(body) 14 | -- cachedWeather = w 15 | -- lastUpdate = os.time() 16 | -- end) 17 | -- end 18 | 19 | 20 | -- local chooserChoices = {"Choice 1", "Choice 2", "Choice 3", "Choice 4"} 21 | 22 | chooserChoices = { } 23 | 24 | 25 | function startBattigayo() 26 | createBattigayoMenu() 27 | end 28 | 29 | 30 | function createBattigayoMenu() 31 | local bgMenu = hs.menubar.new() 32 | bgMenu:setTitle("💡"):setTooltip("Battigayo") 33 | bgMenu:setClickCallback(selectGroup) 34 | end 35 | 36 | 37 | function selectGroup() 38 | test = hs.chooser.new(displayTest) 39 | :rows(7) 40 | test:choices(chooserChoices) 41 | test:show() 42 | end 43 | 44 | 45 | function displayTest(input) 46 | myGroup = input.uuid or myGroup 47 | hs.alert("Your group is set to "..myGroup, 2) 48 | end 49 | 50 | 51 | 52 | 53 | local status = nil 54 | local data = nil 55 | local headers = nil 56 | local weekday = os.date("%A") 57 | local lastUpdated = os.time() 58 | 59 | 60 | function fetchBattigayoData() 61 | status, data, headers = hs.http.get('http://api.battigayo.com') 62 | data = hs.json.decode(data)[1] 63 | return status, data, headers 64 | end 65 | 66 | 67 | function populateChoices() 68 | status, json, headers = fetchBattigayoData() 69 | for i = 1, 7 do 70 | local group = json["group_"..i] 71 | local day = group[string.lower(weekday)] 72 | local choice = { 73 | ["text"] = "Group ".. i, 74 | ["subText"] = "Morning: "..day.morning.. " Evening: "..day.evening, 75 | ["uuid"] = tostring(i) 76 | } 77 | table.insert(chooserChoices, i, choice) 78 | end 79 | 80 | end 81 | 82 | 83 | function showBattigayoNotification() 84 | local group = data["group_"..myGroup] 85 | local dayData = group[string.lower(weekday)] 86 | 87 | hs.notify.new({ 88 | title = "Group "..myGroup.." Schedule".." Last Updated: "..data.updated.english, 89 | informativeText = "Morning: "..dayData.morning.. "\nEvening: "..dayData.evening 90 | }):send() 91 | end 92 | 93 | populateChoices() 94 | startBattigayo() 95 | hs.hotkey.bind(triads, 'O', showBattigayoNotification) -------------------------------------------------------------------------------- /cheatsheets.lua: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------ 2 | --/ Cheatsheet Copycat /-- 3 | ------------------------------------------------------------------------ 4 | 5 | local commandEnum = { 6 | [0] = '⌘', 7 | [1] = '⇧ ⌘', 8 | [2] = '⌥ ⌘', 9 | [3] = '⌥ ⇧ ⌘', 10 | [4] = '⌃ ⌘', 11 | [5] = '⇧ ⌃ ⌘', 12 | [6] = '⌃ ⌥ ⌘', 13 | [7] = '', 14 | [8] = '⌦', 15 | [9] = '', 16 | [10] = '⌥', 17 | [11] = '⌥ ⇧', 18 | [12] = '⌃', 19 | [13] = '⌃ ⇧', 20 | [14] = '⌃ ⌥', 21 | } 22 | 23 | function getAllMenuItemsTable(t) 24 | local menu = {} 25 | for pos,val in pairs(t) do 26 | if(type(val)=="table") then 27 | if(val['AXRole'] =="AXMenuBarItem" and type(val['AXChildren']) == "table") then 28 | menu[pos] = {} 29 | menu[pos]['AXTitle'] = val['AXTitle'] 30 | menu[pos][1] = getAllMenuItems(val['AXChildren'][1]) 31 | elseif(val['AXRole'] =="AXMenuItem" and not val['AXChildren']) then 32 | if( val['AXMenuItemCmdModifiers'] ~='0' and val['AXMenuItemCmdChar'] ~='') then 33 | menu[pos] = {} 34 | menu[pos]['AXTitle'] = val['AXTitle'] 35 | menu[pos]['AXMenuItemCmdChar'] = val['AXMenuItemCmdChar'] 36 | menu[pos]['AXMenuItemCmdModifiers'] = val['AXMenuItemCmdModifiers'] 37 | end 38 | elseif(val['AXRole'] =="AXMenuItem" and type(val['AXChildren']) == "table") then 39 | menu[pos] = {} 40 | menu[pos][1] = getAllMenuItems(val['AXChildren'][1]) 41 | end 42 | end 43 | end 44 | return menu 45 | end 46 | 47 | 48 | function getAllMenuItems(t) 49 | local menu = "" 50 | for pos,val in pairs(t) do 51 | if(type(val)=="table") then 52 | -- do not include help menu for now until I find best way to remove menubar items with no shortcuts in them 53 | if(val['AXRole'] =="AXMenuBarItem" and type(val['AXChildren']) == "table") and val['AXTitle'] ~="Help" then 54 | menu = menu.."" 59 | elseif(val['AXRole'] =="AXMenuItem" and not val['AXChildren']) then 60 | if( val['AXMenuItemCmdModifiers'] ~='0' and val['AXMenuItemCmdChar'] ~='') then 61 | --print(val['AXMenuItemCmdModifiers'].." | "..val['AXTitle'].." | CmdChar: "..val['AXMenuItemCmdChar']) 62 | menu = menu.."
  • "..commandEnum[val['AXMenuItemCmdModifiers']].." "..val['AXMenuItemCmdChar'].."
    ".." "..val['AXTitle'].."
  • " 63 | end 64 | elseif(val['AXRole'] =="AXMenuItem" and type(val['AXChildren']) == "table") then 65 | menu = menu..getAllMenuItems(val['AXChildren'][1]) 66 | end 67 | 68 | end 69 | end 70 | return menu 71 | end 72 | 73 | function generateHtml() 74 | --local focusedApp= hs.window.frontmostWindow():application() 75 | local focusedApp = hs.application.frontmostApplication() 76 | local appTitle = focusedApp:title() 77 | local allMenuItems = focusedApp:getMenuItems(); 78 | local myMenuItems = getAllMenuItems(allMenuItems) 79 | 80 | local html = [[ 81 | 82 | 83 | 84 | 162 | 163 | 164 |
    165 |
    ]]..appTitle..[[
    166 |
    167 |
    168 |
    ]]..myMenuItems..[[
    169 | 170 | 178 | 179 | 187 | 188 | 189 | ]] 190 | 191 | return html 192 | end 193 | 194 | 195 | 196 | local myView = nil 197 | 198 | hs.hotkey.bind({"cmd", "alt", "ctrl"}, "C", function() 199 | if not myView then 200 | myView = hs.webview.new({x = 100, y = 100, w = 1080, h = 600}, { developerExtrasEnabled = true }) 201 | :windowStyle("utility") 202 | :closeOnEscape(true) 203 | :html(generateHtml()) 204 | :allowGestures(true) 205 | :windowTitle("CheatSheets") 206 | :show() 207 | --myView:asHSWindow():focus() 208 | --myView:asHSDrawing():setAlpha(.98):bringToFront() 209 | else 210 | myView:delete() 211 | myView=nil 212 | end 213 | end) -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------------- 2 | --/ initialize /-- 3 | ----------------------------------------------------------------------------------- 4 | local basePath = os.getenv("HOME") .. "/.hammerspoon/" 5 | local imagePath = basePath .. 'assets/'; 6 | 7 | 8 | require 'battery' 9 | require 'windows' 10 | --require 'battigayo' 11 | require 'cheatsheets' 12 | require 'random' 13 | 14 | 15 | -- reload configurations 16 | ---------------------------------------------------------- 17 | function reloadConfig() 18 | hs.alert.show("Config loaded") 19 | hs.reload() 20 | end 21 | 22 | hs.hotkey.bind({"cmd", "alt", "ctrl"}, "R", reloadConfig) 23 | hs.pathwatcher.new(basePath, reloadConfig):start() -------------------------------------------------------------------------------- /random.lua: -------------------------------------------------------------------------------- 1 | 2 | local mash = {"cmd", "alt", "ctrl"} 3 | 4 | ----------------------------------------------------------------------------------- 5 | --/ shortcut to open applications /-- 6 | ----------------------------------------------------------------------------------- 7 | local appList = { 8 | a = 'Activity Monitor', 9 | f = "Finder", 10 | s = 'Sublime Text 2' 11 | } 12 | 13 | for key, app in pairs(appList) do 14 | hs.hotkey.bind(mash, key, function() hs.application.launchOrFocus(app) end) 15 | end 16 | 17 | 18 | ------------------------------------------------------------------------------------ 19 | --/ wifi stuffs /-- 20 | ------------------------------------------------------------------------------------ 21 | 22 | local homeWifi = "HOME-2172" 23 | local urlToLoad = "https://www.twitter.com" 24 | local browser = "Safari" 25 | 26 | hs.wifi.watcher.new(function() 27 | local ssid = hs.wifi.currentNetwork() 28 | 29 | -- alert when internet is connected/disconnected 30 | if not ssid then 31 | hs.alert.show("wifi disconnected") 32 | else 33 | hs.alert.show("wifi connected") 34 | end 35 | 36 | -- load the url when home wifi is connected 37 | if ssid == homeWifi then 38 | -- wait for few seconds 39 | hs.timer.doAfter(2, function() 40 | -- load the url 41 | hs.execute("open "..urlToLoad) 42 | -- lunch or focus the app 43 | hs.application.launchOrFocus(browser) 44 | end) 45 | end 46 | 47 | end):start() 48 | 49 | --toggle wifi 50 | hs.hotkey.bind(mash, "W", function() 51 | if hs.wifi.currentNetwork() == nil then 52 | os.execute("networksetup -setairportpower en1 on") 53 | else 54 | os.execute("networksetup -setairportpower en1 off") 55 | end 56 | end) 57 | 58 | ------------------------------------------------------------------------------------ 59 | 60 | -- alert wifi up/down speed if speed goes below x% 61 | --function speedDroppedCallback() 62 | -- ssid = hs.wifi.currentNetwork() 63 | --end 64 | 65 | 66 | -- for key, app in pairs(hs.application.runningApplications()) do 67 | -- --print("* "..app:title()) 68 | -- for key, window in pairs(app:visibleWindows()) do 69 | -- --print(" --"..window:title()) 70 | -- end 71 | -- end 72 | 73 | --print(hs.application.frontmostApplication()) 74 | ----------------------------------------------------------------------------- 75 | 76 | 77 | ----------------------------------------------------------------------------- 78 | 79 | ----------------------------------------------------------------------------- 80 | -- get all apps 81 | 82 | -- Debug: for trying out snippets of code 83 | -- function dbg() 84 | -- apps = hs.application.runningApplications() 85 | -- for appIndex=1,#apps do 86 | -- app = apps[appIndex] 87 | -- print( app:pid() .. ' ' .. app:title() ) 88 | -- end 89 | -- end 90 | 91 | -- dbg() 92 | -- function listApps() 93 | -- print('-- Listing Running Apps --'); 94 | -- hs.fnutils.each(hs.application.runningApplications(), function(app) print(app:bundleID(), app:title()) end) 95 | -- print('------------'); 96 | -- end 97 | 98 | 99 | 100 | border = nil 101 | 102 | function drawBorder() 103 | if border then 104 | border:delete() 105 | end 106 | 107 | local win = hs.window.focusedWindow() 108 | if win == nil then return end 109 | 110 | local f = win:frame() 111 | local fx = f.x - 2 112 | local fy = f.y - 2 113 | local fw = f.w + 4 114 | local fh = f.h + 4 115 | 116 | border = hs.drawing.rectangle(hs.geometry.rect(fx, fy, fw, fh)) 117 | border:setStrokeWidth(4) 118 | --border:setFillColor({["red"]=1,["blue"]=0,["green"]=0,["alpha"]=01}) 119 | border:setStrokeColor({["red"]=0,["blue"]=0,["green"]=1,["alpha"]=1}) 120 | border:setRoundedRectRadii(6.0, 6.0) 121 | border:setStroke(true):setFill(false) 122 | border:sendToBack():show() 123 | end 124 | 125 | -- drawBorder() 126 | 127 | -- windows = hs.window.filter.new(nil) 128 | -- windows:subscribe(hs.window.filter.windowCreated, function () drawBorder() end) 129 | -- windows:subscribe(hs.window.filter.windowFocused, function () drawBorder() end) 130 | -- windows:subscribe(hs.window.filter.windowMoved, function () drawBorder() end) 131 | -- windows:subscribe(hs.window.filter.windowUnfocused, function () drawBorder() end) 132 | 133 | 134 | 135 | 136 | -- Lets draw the bar, on as many screens as we have, across the top 137 | function drawBottonBar() 138 | local activeWindow = hs.window.frontmostWindow() 139 | local frame = activeWindow:frame() 140 | local box = hs.drawing.rectangle(hs.geometry.rect(frame.x, frame.h+3, frame.w, 20)) 141 | 142 | box:setFillColor({["red"]=0.1,["blue"]=0.1,["green"]=0.1,["alpha"]=0.5}):setFill(true):show() 143 | box:setRoundedRectRadii(1.0, 1.0) 144 | 145 | -- Create the iTunes box 146 | local text = hs.drawing.text(hs.geometry.rect(frame.x , frame.h+3, frame.w, 20), "Test") 147 | -- Set the text color 148 | text:setTextColor({["red"]=1,["blue"]=1,["green"]=1,["alpha"]=1}) 149 | -- Set the font size and font type 150 | text:setTextSize(14) 151 | text:setTextFont('Tamzen7x14') 152 | text:setClickCallback() 153 | text:show() 154 | 155 | box:setLevel(hs.drawing.windowLevels["floating"]) 156 | end 157 | 158 | --drawBottonBar() 159 | 160 | --hammerspoon://test1?someParam=hello 161 | hs.urlevent.bind("test", function(eventName, params) 162 | if params["someParam"] then 163 | hs.alert.show(params["someParam"]) 164 | else 165 | hs.alert.show("test") 166 | end 167 | end) 168 | 169 | --hs.hotkey.bind(mash, '.', hs.hints.windowHints) 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /windows.lua: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------------ 2 | --/ window management /-- 3 | ------------------------------------------------------------------------------------ 4 | 5 | local cmdalt = {"cmd", "alt"} 6 | local mash = {"cmd", "alt", "ctrl"} 7 | local mashshift = {"cmd", "alt", "ctrl", "shift" } 8 | 9 | -- disable animations 10 | hs.window.animationDuration = 0.01 11 | 12 | local appwindow = nil 13 | local frameCache = {} 14 | 15 | --split windows based on 8 variables 16 | ---------------------------------------------------------- 17 | --x, y, w, h, l, r, t, b 18 | function splitWindow(coords) 19 | return function() 20 | appwindow = hs.window.frontmostWindow() 21 | 22 | local f = appwindow:frame() 23 | local max = appwindow:screen():frame() 24 | 25 | f.x = max.x + (max.w * coords[1]) + coords[5] 26 | f.y = max.y + (max.h * coords[2]) + coords[7] 27 | f.w = (max.w * coords[3]) - coords[5] - coords[6] 28 | f.h = (max.h * coords[4]) - coords[7] - coords[8] 29 | 30 | frameCache[appwindow:id()] = f 31 | appwindow:setFrame(f) 32 | end 33 | end 34 | 35 | --x, y, w, h, l, r, t, b 36 | local halfWindowFrames = { 37 | Left = {0.0, 0.0, 0.5, 1.0, 00, 2.5, 00, 00}, 38 | Right = {0.5, 0.0, 0.5, 1.0, 2.5, 00, 00, 00}, 39 | Up = {0.0, 0.0, 1.0, 0.5, 00, 00, 00, 2.5}, 40 | Down = {0.0, 0.5, 1.0, 0.5, 00, 00, 2.5, 00} 41 | } 42 | 43 | 44 | for key, frame in pairs(halfWindowFrames) do 45 | hs.hotkey.bind(mash, key, splitWindow(frame)) 46 | end 47 | 48 | --x, y, w, h, l, r, t, b 49 | local quarterWindowFrames = { 50 | Up = {0.0, 0.0, 0.5, 0.5, 00, 2.5, 00, 2.5}, 51 | Right = {0.5, 0.0, 0.5, 0.5, 2.5, 00, 00, 2.5}, 52 | Down = {0.5, 0.5, 0.5, 0.5, 2.5, 00, 2.5, 00}, 53 | Left = {0.0, 0.5, 0.5, 0.5, 00, 2.5, 2.5, 00}, 54 | --{0.25, 0.25, 0.5, 0.5, 00, 00, 00, 00} 55 | } 56 | 57 | for key, frame in pairs(quarterWindowFrames) do 58 | hs.hotkey.bind(cmdalt, key, splitWindow(frame)) 59 | end 60 | 61 | hs.hotkey.bind( mash, ",", splitWindow({0.0, 0.0, 0.3, 1.0, 00, 05, 00, 00})) 62 | hs.hotkey.bind( mash, ".", splitWindow({0.3, 0.0, 0.7, 1.0, 05, 00, 00, 00})) 63 | 64 | 65 | 66 | 67 | -- toggle window between normal size and max size 68 | ---------------------------------------------------------- 69 | function maximizeWindow() 70 | appwindow = hs.window.frontmostWindow() 71 | 72 | if frameCache[appwindow:id()] then 73 | appwindow:setFrame(frameCache[appwindow:id()]) 74 | frameCache[appwindow:id()] = nil 75 | else 76 | frameCache[appwindow:id()] = appwindow:frame() 77 | appwindow:maximize() 78 | end 79 | end 80 | 81 | 82 | hs.hotkey.bind( mashshift, "Up", maximizeWindow) 83 | 84 | 85 | -- un/minimize window 86 | ---------------------------------------------------------- 87 | function toggleMinimize() 88 | appwindow = hs.window.focusedWindow() 89 | 90 | if not appwindow then 91 | appwindow = hs.window.frontmostWindow() 92 | end 93 | 94 | if appwindow:isMinimized() then 95 | appwindow:unminimize() 96 | else 97 | appwindow:minimize() 98 | end 99 | 100 | end 101 | 102 | hs.hotkey.bind( mashshift, "Down", toggleMinimize) 103 | 104 | 105 | -- toggle fullscreen 106 | ---------------------------------------------------------- 107 | function toggleFullscreen() 108 | appwindow = hs.window.frontmostWindow() 109 | appwindow:toggleFullScreen() 110 | end 111 | 112 | hs.hotkey.bind( mashshift, "Right", toggleFullscreen) 113 | 114 | 115 | -- toggle between windows 116 | ---------------------------------------------------------- 117 | function toggleAppWindows() 118 | local win = hs.window.focusedWindow() 119 | if not win then 120 | return 121 | end 122 | win:application():hide() 123 | end 124 | 125 | hs.hotkey.bind( mashshift, "Left", toggleAppWindows) 126 | 127 | 128 | -- close window 129 | ---------------------------------------------------------- 130 | function quitApp() 131 | appwindow = hs.window.frontmostWindow() 132 | appwindow:close() 133 | end 134 | 135 | hs.hotkey.bind( mash, "X", quitApp) 136 | 137 | 138 | ----------------------------------------------------------- 139 | 140 | --[[local frameIndex = 1; 141 | function rotateWindow(windowFrames) 142 | return function() 143 | appwindow = hs.window.frontmostWindow() 144 | 145 | local f = appwindow:frame() 146 | local max = appwindow:screen():frame() 147 | 148 | f.x = max.x + (max.w * windowFrames[frameIndex][1]) + windowFrames[frameIndex][5] 149 | f.y = max.y + (max.h * windowFrames[frameIndex][2]) + windowFrames[frameIndex][7] 150 | f.w = (max.w * windowFrames[frameIndex][3]) - windowFrames[frameIndex][5] - windowFrames[frameIndex][6] 151 | f.h = (max.h * windowFrames[frameIndex][4]) - windowFrames[frameIndex][7] - windowFrames[frameIndex][8] 152 | 153 | frameCache[appwindow:id()] = f 154 | appwindow:setFrame(f) 155 | frameIndex = (frameIndex % #windowFrames) + 1 156 | end 157 | end]] 158 | --------------------------------------------------------------------------------