Skip to content

Commit fef0acc

Browse files
authored
Refactor/deprecate ipc msgs (#63)
* Config: deprecate ipc message handling (#53) * Readme: Change ipc message example to `hs` cli * Config: fix typo in return value of config:validate() method, guard against toggling non-boolean setting, simplify conditional logic, cleanup formatting, fix typo in return variable name
1 parent 29cfa7a commit fef0acc

File tree

2 files changed

+44
-110
lines changed

2 files changed

+44
-110
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ Did the terminal window expand to cover the area previously occupied by Safari?
170170
If the icons are a bit too heavy for you, you can toggle minimalist mode by turning the icons off:
171171

172172
```sh
173-
echo ":toggle_appearance.show_icons:" | hs -m stackline-config
173+
hs -c 'stackline.config:toggle("appearance.showIcons")'
174174
```
175175

176176

stackline/configmanager.lua

Lines changed: 43 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
-- https://github.com/erento/lua-schema-validation
22
local log = hs.logger.new('sline.conf')
33
log.setLogLevel('info')
4-
log.i("Loading module")
4+
log.i('Loading module')
55

66
local M = {}
77

@@ -15,8 +15,8 @@ local is_color = v.is_table { -- {{{
1515
blue = o(v.is_number()),
1616
alpha = o(v.is_number()),
1717
} -- }}}
18-
local function unknownTypeValidator(v) -- {{{
19-
log.i("Not validating: ", schemaType)
18+
local function unknownTypeValidator(val) -- {{{
19+
log.i('Not validating: ', val)
2020
return true
2121
end -- }}}
2222

@@ -51,7 +51,7 @@ M.types = { -- {{{
5151
},
5252
} -- }}}
5353

54-
local defaultOnChangeEvt = { -- {{{
54+
local defaultOnChangeEvt = { -- {{{
5555
__index = function() stackline.queryWindowState:start() end
5656
} -- }}}
5757

@@ -67,7 +67,7 @@ M.events = setmetatable({ -- {{{
6767
dynamicLuminosity = nil,
6868
},
6969
advanced = {
70-
maxRefreshRate = function() print('Needs implemented') end,
70+
maxRefreshRate = function() print('Needs implemented') end,
7171
},
7272
}, defaultOnChangeEvt) -- }}}
7373

@@ -108,39 +108,30 @@ M.schema = { -- {{{
108108

109109
function M:getPathSchema(path) -- {{{
110110
local _type = u.getfield(path, self.schema) -- lookup type in schema
111-
if not _type then
112-
return false
113-
end
111+
if not _type then return false end
114112
local validator = self.types[_type].validator()
113+
115114
return _type, validator
116115
end -- }}}
117116

118117
function M.generateValidator(schemaType) -- {{{
119-
if type(schemaType) == 'table' then
118+
if type(schemaType)=='table' then -- recursively build validator
120119
local children = u.map(schemaType, M.generateValidator)
121120
log.d('validator children:\n', hs.inspect(children))
122121
return v.is_table(children)
123-
else
124-
log.i('schemaType:', schemaType)
125-
return
126-
M.types[schemaType] and M.types[schemaType].validator() -- returns a fn to be called with value to validate
127-
or unknownTypeValidator -- unknown types are assumed-valid
128122
end
123+
124+
-- otherwise, return validation fn forgiven type
125+
log.i('schemaType:', schemaType)
126+
return M.types[schemaType] -- if schemaType is a known config type..
127+
and M.types[schemaType].validator() -- then return validation fn
128+
or unknownTypeValidator -- otherwise, unknown types are assumed valid
129129
end -- }}}
130130

131131
-- Config manager
132132
function M:init(conf) -- {{{
133133
log.i('Initializing configmanager…')
134134
self:validate(conf)
135-
ipcConfigPort = hs.ipc.localPort('stackline-config',
136-
function(_, msgID, msg)
137-
if msgID == 900 then
138-
return "version:2.0a" -- if this is not returned, *ipc msgs will NOT work*
139-
elseif msgID == 500 then
140-
self:handleMsg(msg)
141-
end
142-
end)
143-
144135
self.__index = self
145136
return self
146137
end -- }}}
@@ -155,18 +146,17 @@ function M:validate(conf) -- {{{
155146
self.conf = conf
156147
self.autosuggestions = u.keys(u.flatten(self.conf))
157148
else
158-
local invalidKeys = table.concat(u.keys(u.flatten(err)), ", ")
149+
local invalidKeys = table.concat(u.keys(u.flatten(err)), ', ')
150+
log.e('Invalid stackline config:\n', hs.inspect(err))
159151
hs.notify.new(nil, {
160152
title = 'Invalid stackline config!',
161-
subTitle = 'invalid keys:' .. invalidKeys,
153+
subTitle = 'invalid keys:' .. invalidKeys,
162154
informativeText = 'Please refer to the default conf file.',
163155
withdrawAfter = 10
164156
}):send()
165-
166-
log.e('Invalid stackline config:\n', hs.inspect(err))
167157
end
168158

169-
return valid, err
159+
return isValid, err
170160
end -- }}}
171161

172162
function M:autosuggest(path) -- {{{
@@ -178,7 +168,9 @@ function M:autosuggest(path) -- {{{
178168
local function asc(a, b)
179169
return a[1] < b[1]
180170
end
171+
181172
table.sort(scores, asc)
173+
182174
log.d(hs.inspect(scores))
183175

184176
local result1, result2 = scores[1][2], scores[2][2] -- return the best 2 matches
@@ -189,15 +181,14 @@ function M:autosuggest(path) -- {{{
189181
informativeText = string.format('"%s" is not a default stackline config path', path),
190182
withdrawAfter = 10
191183
}):send()
192-
193184
end -- }}}
194185

195186
function M:getOrSet(path, val) -- {{{
196-
if path == nil or val == nil then
197-
return self:get(path)
198-
else
187+
if path and val then
199188
return self:set(path, val)
200189
end
190+
191+
return self:get(path)
201192
end -- }}}
202193

203194
function M:get(path) -- {{{
@@ -221,93 +212,36 @@ function M:set(path, val) -- {{{
221212

222213
if _type == nil then
223214
self:autosuggest(path)
224-
else
225-
local typedVal = self.types[_type].coerce(val)
226-
local isValid, err = validator(typedVal) -- validate val is appropriate type
227-
log.d('\nval:', typedVal)
228-
log.d('val type:', type(typedVal))
229-
if isValid then
230-
log.d('Setting', path, 'to', typedVal)
231-
u.setfield(path, typedVal, self.conf)
232-
233-
local onChange = u.getfield(path, self.events, true)
234-
if type(onChange) == 'function' then onChange() end
235-
else
236-
log.e(hs.inspect(err))
237-
end
238-
return self, val
215+
return self
239216
end
240217

241-
end -- }}}
218+
local typedVal = self.types[_type].coerce(val)
219+
local isValid, err = validator(typedVal) -- validate val is appropriate type
242220

243-
function M:toggle(key) -- {{{
244-
local toggledVal = not self:get(key)
245-
log.d('Toggling', key, 'from ', self:get(key), 'to ', toggledVal)
246-
self:set(key, toggledVal)
247-
return self
248-
end -- }}}
249-
250-
-- TODO: Add m:Increment(delta)
251-
-- TODO: Add m:Decrement(delta)
221+
log.d('\nval:', typedVal, '\nval type:', type(typedVal))
252222

253-
function M:parseMsg(msg) -- {{{
254-
local _, path, val = table.unpack(msg:split(':'))
255-
path = path:gsub("_(.)", string.upper) -- convert snake_case to camelCase
256-
log.d('path parsed from ipc port', path)
257-
258-
if type(val) == 'string' then
259-
val = val:gsub("%W", "") -- remove all whitespace
223+
if not isValid then
224+
log.e(hs.inspect(err))
225+
return self
260226
end
261227

262-
-- TODO: resolve 'chicken & egg' problem: need type to fully parse, need to fully parse to get type w/o error
263-
-- local _type, validator = self:getPathSchema(path)
264-
265-
local parsedMsg = {
266-
path = path,
267-
val = val,
268-
_type = _type,
269-
validator = validator,
270-
isGet = (path ~= nil) and (val == nil),
271-
isSet = (path ~= nil) and (val ~= nil),
272-
isToggle = path:match("toggle") ~= nil, -- TODO: add and _type == 'boolean' when todo above is complete
273-
}
274-
275-
log.d('Parsed msg:\n', hs.inspect(parsedMsg))
228+
log.d('Setting', path, 'to', typedVal)
276229

277-
return parsedMsg
278-
end -- }}}
230+
u.setfield(path, typedVal, self.conf)
279231

280-
function M:handleMsg(msg) -- {{{
281-
log.d('msg', msg)
282-
local m = self:parseMsg(msg)
283-
log.d(m)
284-
285-
if m.isToggle then
286-
log.d('isToggle')
287-
local key = m.path
288-
:gsub('toggle', '') -- strip leading 'toggle'
289-
:gsub("^%L", string.lower) -- lowercase 1st character
290-
self:toggle(key)
291-
return self:get(key)
292-
293-
elseif m.isSet then
294-
log.d('isSet')
295-
local _, setVal = self:set(m.path, m.val)
296-
return setVal
297-
298-
elseif m.isGet then
299-
log.d('isGet')
300-
local val = self:get(m.path)
301-
return val
232+
local onChange = u.getfield(path, self.events, true)
233+
if type(onChange) == 'function' then onChange() end
234+
return self, val
302235

303-
else
304-
log.e('Unparsable IPC message. Try:')
305-
log.i( ' `echo ":toggle_appearance.show_icons:" | hs -m stackline-config"`')
306-
log.i( ' `echo ":get_appearance.show_icons:" | hs -m stackline-config"`')
307-
end
308-
309-
return "ok"
310236
end -- }}}
311237

238+
function M:toggle(key) -- {{{
239+
local val = self:get(key)
240+
if type(val)~='boolean' then log.w(key, 'cannot be toggled because it is not boolean') end
241+
local toggledVal = not val
242+
log.d('Toggling', key, 'from ', val, 'to ', toggledVal)
243+
self:set(key, toggledVal)
244+
return self
245+
end -- }}}
312246

313247
return M

0 commit comments

Comments
 (0)