-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.lua
271 lines (252 loc) · 7.33 KB
/
init.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
---------------------------------------------------------------------------
--- Retain
--
-- @author Kevin Zander <[email protected]>
-- @copyright 2017 Kevin Zander
-- @module retain
---------------------------------------------------------------------------
-- External Dependencies:
-- lua-json (http://luaforge.net/projects/luajson/)
--
-- Description:
-- Retain works behind the scenes to save your tags and current layout for
-- each screen. When a screen is connected it will load with your previous
-- tags and last layout, or if it's new it will use a default set.
--
-- JSON Encoded format:
-- { "screenID" : {
-- "tag position" : {
-- "name" : "tag name",
-- "layout" : "layout name",
-- "mcount" : master count,
-- "ccount" : column count,
-- "mwf" : master width factor },
-- ...
-- },
-- ...
-- }
--
-- Decoded format:
-- { "screenID" = {
-- "tag position" = {
-- name = "tag name",
-- layout = "layout name",
-- mcount = master count,
-- ccount = column count,
-- mwf = master width factor
-- },
-- ...
-- },
-- ...
-- }
--
-- Usage:
-- In rc.lua add `local retain = require("retain")`.
--
-- After defining your awful.layout.layouts add `retain.tags.load()`.
--
-- The default fallback tags and layouts are awesome's defaults.
-- You can set your own by setting:
-- retain.tags.defaults.names = {"tag name", "tag name", ...}
-- retain.tags.defaults.layouts = {layout, layout, ...}
-- where names and layouts are acceptable parameters to awful.tag()
--
-- For example:
-- retain.tags.defaults.names = {"A", "B", "C"}
-- retain.tags.defaults.layouts = {l[2], l[4], l[6]}
-- where l = awful.layout.layouts
--
-- In the awful.screen.connect_for_each_screen function, change your
-- awful.tag() line to:
-- awful.tag(retain.tags.getnames(s), s, retain.tags.getlayouts(s))
--
-- The default save file is:
-- awful.util.get_configuration_dir() .. ".retained"
-- If you want to save to a different location, change
-- retain.tags.savefile
local json = require("json")
local awful = require("awful")
local gfs = require("gears.filesystem")
local naughty = require("naughty")
local retain = {tags={},layout={}}
retain.debug = false
retain.tags.savefile = gfs.get_configuration_dir() .. 'retain.json'
retain.tags.defaults = {
names={"1","2","3","4","5","6","7","8","9"},
layouts=awful.layout.suit.floating,
}
retain.tags._mytags = {}
retain.tags._loaded = nil
local function debug(txt)
if retain.debug then
print("RETAIN: " .. txt)
end
end
-- get the index of the screen
local function getScreenIndex(scr)
if type(scr) == "screen" then
return scr.sid
elseif type(scr) == "string" then
return screen[scr].sid
elseif type(scr) == "number" then
return scr
end
return nil
end
-- gather the tags of a screen by numeric index
local function gatherTags(scr)
debug("gatherTags()")
local tbl = {}
for i,v in ipairs(scr.tags) do
-- save tag as {tag index = {tag name, tag layout name}}
debug(v.name .. " " .. v.layout.name)
tbl[tostring(i)] = {name=v.name, layout=v.layout.name}
end
return tbl
end
-- find a layout by name
local function findLayout(name)
debug("findLayout()")
for _,l in ipairs(awful.layout.layouts) do
if l.name == name then
debug("found " .. name)
return l
end
end
return nil
end
-- convert _loaded to _mytags
local function convertLoadedTags(sid)
debug("convertLoadedTags()")
local sin = tonumber(sid)
debug("screen index " .. sid)
for tid,ttb in pairs(retain.tags._loaded[sid]) do
local tin = tonumber(tid)
debug("tag index " .. tid)
debug(ttb.name .. " " .. ttb.layout)
if not retain.tags._mytags[sin] then retain.tags._mytags[sin] = {names={},layouts={}} end
retain.tags._mytags[sin].names[tin] = ttb.name
retain.tags._mytags[sin].layouts[tin] = findLayout(ttb.layout)
end
end
-- save all screens
function retain.tags.save_all()
debug("save_all()")
for s in screen do
retain.tags.save(s)
end
end
-- save tags for a specific screen
function retain.tags.save(scr)
debug("save()")
if not scr or type(scr) ~= "screen" then return end
local si = tostring(scr.sid)
debug("screen id: " .. si)
-- collect tags and their layout name
local tbl = gatherTags(scr)
-- merge into loaded collection so we don't have to read the file again
-- this allows one to connect the screen again at a later time without
-- having to read the file again
if not retain.tags._loaded then retain.tags._loaded = {} end
retain.tags._loaded[si] = tbl
-- save to mytags
convertLoadedTags(si)
-- write serialized to file
debug("saving file")
local f = io.open(retain.tags.savefile, 'w')
f:write(json.encode(retain.tags._loaded))
f:close()
end
-- load saved tags
function retain.tags.load()
debug("load()")
local f = io.open(retain.tags.savefile, 'r')
-- no save file found
if not f then
debug("file not found")
-- XXX: This will always show on first load
naughty.notify({
preset = naughty.config.presets.critical,
text = "No save file found",
title = "retain",
})
-- load defaults
debug("loading defaults")
retain.tags._mytags = retain.tags.defaults
return
end
-- if _loaded is nil, load it
if not retain.tags._loaded then
debug("_loaded empty")
-- json to table, save
retain.tags._loaded = json.decode(f:read("*a"))
-- if failure
if not retain.tags._loaded or type(retain.tags._loaded) ~= "table" then
debug("failed to read file")
retain.tags._loaded = nil
naughty.notify({
preset = naughty.config.presets.critical,
text = "Error in loading json, loading defaults",
title = "retain",
})
-- load defaults
retain.tags._mytags = retain.tags.defaults
-- close the file before return
f:close()
return
end
end
f:close()
-- convert to numeric index
for sid,stb in pairs(retain.tags._loaded) do
debug(sid .. " " .. tostring(stb))
-- k = screen index
-- v = list of objects
local sin = tonumber(sid) -- screen index
retain.tags._mytags[sin] = {names={},layouts={}}
-- stb = {"tag index" = ttb, ...}
for tid,ttb in pairs(stb) do
-- ttb = {name = "tag name", layout = "layout name"}
debug(tid .. " " .. tostring(ttb))
local tin = tonumber(tid) -- tag index
retain.tags._mytags[sin].names[tin] = ttb.name
retain.tags._mytags[sin].layouts[tin] = findLayout(ttb.layout)
end
end
end
-- Reduce code duplication, get a table from tags table
local function getTable(scr, name)
debug("getTable()")
local s = getScreenIndex(scr)
debug(tostring(s))
if retain.tags._mytags[s] then
debug(#retain.tags._mytags[s])
if #retain.tags._mytags[s][name] > 0 then
return retain.tags._mytags[s][name]
end
end
return retain.tags.defaults[name]
end
-- get the names of tags from tags table
function retain.tags.getnames(scr)
return getTable(scr, "names")
end
-- get the layouts of tags from tags table
function retain.tags.getlayouts(scr)
return getTable(scr, "layouts")
end
function retain.connect_signals()
debug("connect_signals()")
-- always save on a screen removed
screen.connect_signal("removed", retain.tags.save)
-- save on awesome restart or exit
awesome.connect_signal("exit", retain.tags.save_all)
end
-- On disconnect of a screen, this should have our latest index
-- Retain will get this variable on screen removed signal
awful.screen.connect_for_each_screen(function(s)
s.sid = s.index
end)
-- reload on a screen add
--screen.connect_signal("added", retain.tags.update)
return retain