-
Notifications
You must be signed in to change notification settings - Fork 0
/
mjomatic.lua
154 lines (132 loc) · 4.58 KB
/
mjomatic.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
--- === mjolnir.7bits.mjomatic ===
---
--- tmuxomatic-like window management
---
--- Usage:
--- ~~~lua
--- local mjomatic = require "mjolnir.7bits.mjomatic"
--- ~~~
local mjomatic = {}
local alert = require 'mjolnir.alert'
local appfinder = require 'mjolnir.cmsj.appfinder'
local screen = require 'mjolnir.screen'
alert.show('mjomatic loaded')
local gridh
local gridw
local function resizetogrid(window, coords)
-- alert.show(string.format('move window %q to %d,%d-%d,%d', window:title(), coords.r1, coords.c1, coords.r2, coords.c2), 20)
-- collect screen dimensions
local frame = screen.mainscreen():fullframe()
local framew = screen.mainscreen():frame()
local h = framew.h
local w = frame.w
local x = framew.x
local y = framew.y
-- alert.show(string.format('screen dimensions %d,%d at %d,%d', h, w, x, y))
local hdelta = h / gridh
local wdelta = w / gridw
-- alert.show('hdelta='..hdelta, 5)
-- alert.show('wdelta='..wdelta, 5)
local newframe = {}
newframe.x = (coords.c1-1) * wdelta + x
newframe.y = (coords.r1-1) * hdelta + y
newframe.h = (coords.r2-coords.r1+1) * hdelta
newframe.w = (coords.c2-coords.c1+1) * wdelta
window:setframe(newframe)
-- alert.show(string.format('new frame for %q is %d*%d at %d,%d', window:title(), newframe.w, newframe.h, newframe.x, newframe.y), 20)
end
--- mjolnir.7bits.mjomatic.go(cfg)
--- Function
--- takes a config as a list of strings, configures your windows as stated.
---
--- Example:
--- ~~~lua
--- mjomatic.go({
--- "CCCCCCCCCCCCCiiiiiiiiiii # <-- The windowgram, it defines the shapes and positions of windows",
--- "CCCCCCCCCCCCCiiiiiiiiiii",
--- "SSSSSSSSSSSSSiiiiiiiiiii",
--- "SSSSSSSSSSSSSYYYYYYYYYYY",
--- "SSSSSSSSSSSSSYYYYYYYYYYY",
--- "",
--- "C Google Chrome # <-- window C has application():title() 'Google Chrome'",
--- "i iTerm",
--- "Y YoruFukurou",
--- "S Sublime Text 2"})
--- ~~~
function mjomatic.go(cfg)
-- alert.show('mjomatic is go')
local grid = {}
local map = {}
local target = grid
-- FIXME move gsub stuff to separate function (iterator wrapper around io.lines?)
-- then do parsing in two loops so we don't need to muck about with target
-- and do some parsing inline
for i,l in ipairs(cfg) do
l = l:gsub('#.*','') -- strip comments
l = l:gsub('%s*$','') -- strip trailing whitespace
-- alert.show(l)
if l:len() == 0 then
if #grid > 0 then
if target == grid then
target = map
elseif #map > 0 then
error('config has more than two chunks')
end
end
else
table.insert(target, l)
end
end
-- alert.show('grid size '..#grid)
-- alert.show('map size '..#map)
gridh = #grid
gridw = nil
local windows = {}
local titlemap = {}
for i, v in ipairs(map) do
local key = v:sub(1,1)
local title = v:sub(3)
-- alert.show(string.format('%s=%s', key, title))
titlemap[title] = key
end
for row, v in ipairs(grid) do
if gridw then
if gridw ~= v:len() then
error('inconsistent grid width')
end
else
gridw=v:len()
end
for column = 1, #v do
local char = v:sub(column, column)
if not windows[char] then
-- new window, create it with size 1x1
windows[char] = {r1=row, c1=column, r2=row, c2=column}
else
-- expand it
windows[char].r2=row
windows[char].c2=column
end
end
end
-- alert.show('grid h='..gridh..' w='..gridw)
-- alert.show('windows:')
for char, window in pairs(windows) do
-- alert.show(string.format('window %s: top left %d,%d bottom right %d,%d', char, window.r1, window.c1, window.r2, window.c2))
end
for title, key in pairs(titlemap) do
-- alert.show(string.format("title %s key %s", title, key))
if not windows[key] then
error(string.format('no window found for application %s (%s)', title, key))
end
local app = appfinder.app_from_name(title)
local window = app:mainwindow()
-- alert.show(string.format('application title for %q is %q, main window %q', title, app:title(), window:title()))
if window then
resizetogrid(window, windows[key])
else
alert.show(string.format('application %s has no main window', app:title()))
end
end
end
return mjomatic