Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package awesome-vicious for openSUSE:Factory
checked in at 2022-10-12 18:25:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/awesome-vicious (Old)
and /work/SRC/openSUSE:Factory/.awesome-vicious.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "awesome-vicious"
Wed Oct 12 18:25:27 2022 rev:9 rq:1010014 version:2.5.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/awesome-vicious/awesome-vicious.changes
2021-06-01 10:38:16.340895850 +0200
+++
/work/SRC/openSUSE:Factory/.awesome-vicious.new.2275/awesome-vicious.changes
2022-10-12 18:27:14.786027314 +0200
@@ -1,0 +2,11 @@
+Mon Oct 10 18:28:18 UTC 2022 - Ferdinand Thiessen <[email protected]>
+
+- Update to version 2.5.1
+ * Fixed escaping of % in helpers.format, which affects mpd widget ${Progress}
+ * Fixed possible deadlock of when update widgets
+ * [contrib.openweather] New API compatibility, which requires an API key
+ * [gmail] Authentication documentation
+ * [mpd] Added support for sending arbitrary commands
+ * [contrib.openweather] Added various new return values
+
+-------------------------------------------------------------------
Old:
----
vicious-2.5.0.tar.gz
New:
----
vicious-2.5.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ awesome-vicious.spec ++++++
--- /var/tmp/diff_new_pack.FS65gi/_old 2022-10-12 18:27:15.230028292 +0200
+++ /var/tmp/diff_new_pack.FS65gi/_new 2022-10-12 18:27:15.234028300 +0200
@@ -1,7 +1,7 @@
#
# spec file for package awesome-vicious
#
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
%define packname vicious
Name: awesome-vicious
-Version: 2.5.0
+Version: 2.5.1
Release: 0
Summary: Vicious plugins for awesome
License: GPL-2.0-or-later
++++++ vicious-2.5.0.tar.gz -> vicious-2.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/.build.yml new/vicious-2.5.1/.build.yml
--- old/vicious-2.5.0/.build.yml 1970-01-01 01:00:00.000000000 +0100
+++ new/vicious-2.5.1/.build.yml 2022-05-04 03:43:26.000000000 +0200
@@ -0,0 +1,9 @@
+image: alpine/edge
+packages:
+ - luacheck
+sources:
+ - https://github.com/vicious-widgets/vicious
+tasks:
+ - check: |
+ cd vicious
+ luacheck --config=tools/luacheckrc .
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/CHANGELOG.rst
new/vicious-2.5.1/CHANGELOG.rst
--- old/vicious-2.5.0/CHANGELOG.rst 2020-09-27 16:31:00.000000000 +0200
+++ new/vicious-2.5.1/CHANGELOG.rst 2022-05-04 03:43:26.000000000 +0200
@@ -1,6 +1,21 @@
Changelog
=========
+Changes in 2.5.1
+----------------
+
+Fixed:
+
+- Escaping of % in ``helpers.format``, which affects mpd widget ``${Progress}``
+- Possible deadlock of when ``update`` widgets
+- [contrib.openweather] New API compatibility, which requires an API key
+- [gmail] Authentication documentation
+
+Added:
+
+- [mpd] Support for sending arbitrary commands
+- [contrib.openweather] Various new return values
+
Changes in 2.5.0
----------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/CONTRIBUTING.rst
new/vicious-2.5.1/CONTRIBUTING.rst
--- old/vicious-2.5.0/CONTRIBUTING.rst 2020-09-27 16:31:00.000000000 +0200
+++ new/vicious-2.5.1/CONTRIBUTING.rst 2022-05-04 03:43:26.000000000 +0200
@@ -44,7 +44,7 @@
#. `Fork this repository`_
#. Check out the source code with::
- git clone https://github.com/YOUR_GITHUB_USERNAME/vicious.git
+ git clone [email protected]:YOUR_GITHUB_USERNAME/vicious
cd vicious
#. Start working on your patch. If you want to add a new widget type,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/contrib/openweather_all.lua
new/vicious-2.5.1/contrib/openweather_all.lua
--- old/vicious-2.5.0/contrib/openweather_all.lua 2020-09-27
16:31:00.000000000 +0200
+++ new/vicious-2.5.1/contrib/openweather_all.lua 2022-05-04
03:43:26.000000000 +0200
@@ -1,6 +1,7 @@
-- contrib/openweather_all.lua
-- Copyright (C) 2013 NormalRa <normalrawr gmail com>
-- Copyright (C) 2017 J??rg Thalheim <[email protected]>
+-- Copyright (C) 2020 Marcel Arpogaus <marcel.arpogaus gmail com>
--
-- This file is part of Vicious.
--
@@ -16,69 +17,66 @@
--
-- You should have received a copy of the GNU General Public License
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
-
-- {{{ Grab environment
local tonumber = tonumber
-local io = { popen = io.popen }
-local setmetatable = setmetatable
-local string = { match = string.match }
-local math = {
- ceil = math.ceil,
- floor = math.floor
-}
+local string = {match = string.match}
+local math = {ceil = math.ceil, floor = math.floor}
+local helpers = require "vicious.helpers"
+local spawn = require "vicious.spawn"
-- }}}
-
-- Openweather: provides weather information for a requested station
-- vicious.widgets.openweather
local openweather_all = {}
-
-- Initialize function tables
-local _wdirs = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" }
+local _wdirs = {"N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"}
local _wdata = {
- ["{city}"] = "N/A",
- ["{wind deg}"] = "N/A",
- ["{wind aim}"] = "N/A",
- ["{wind mps}"] = "N/A",
- ["{wind kmh}"] = "N/A",
- ["{sky}"] = "N/A",
- ["{weather}"] = "N/A",
- ["{temp c}"] = "N/A",
- ["{humid}"] = "N/A",
- ["{press}"] = "N/A"
+ ["{city}"] = "N/A",
+ ["{wind deg}"] = "N/A",
+ ["{wind aim}"] = "N/A",
+ ["{wind mps}"] = "N/A",
+ ["{wind kmh}"] = "N/A",
+ ["{sky}"] = "N/A",
+ ["{weather}"] = "N/A",
+ ["{temp c}"] = "N/A",
+ ["{temp min c}"] = "N/A",
+ ["{temp max c}"] = "N/A",
+ ["{sunrise}"] = -1,
+ ["{sunset}"] = -1,
+ ["{humid}"] = "N/A",
+ ["{press}"] = "N/A"
}
-- {{{ Openweather widget type
-local function worker(format, warg)
- if not warg then return end
-
- -- Get weather forceast using the city ID code, from:
- -- * OpenWeatherMap.org
- local openweather =
"http://api.openweathermap.org/data/2.5/weather?id="..warg.."&mode=json&units=metric"
- local f = io.popen("curl --connect-timeout 1 -fsm 3 '"..openweather.."'")
- local ws = f:read("*all")
- f:close()
-
+local function parse(stdout, stderr, exitreason, exitcode)
-- Check if there was a timeout or a problem with the station
- if ws == nil then return _wdata end
+ if stdout == nil or exitcode ~= 0 then return _wdata end
- _wdata["{city}"] = -- City name
- string.match(ws, '"name":"([%a%s%-]+)"') or _wdata["{city}"]
+ _wdata["{city}"] = -- City name
+ string.match(stdout, '"name":"([%a%s%-]+)"') or _wdata["{city}"]
_wdata["{wind deg}"] = -- Wind degrees
- string.match(ws, '"deg":([%d]+)') or _wdata["{wind deg}"]
- _wdata["{wind mps}"] = -- Wind speed in meters per second
- string.match(ws, '"speed":([%d%.]+)') or _wdata["{wind mps}"]
- _wdata["{sky}"] = -- Sky conditions
- string.match(ws, '"main":"([%a]+)"') or _wdata["{sky}"]
- _wdata["{weather}"] = -- Weather description
- string.match(ws, '"description":"([%a%s]+)"') or _wdata["{weather}"]
- _wdata["{temp c}"] = -- Temperature in celsius
- string.match(ws, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"]
- _wdata["{humid}"] = -- Relative humidity in percent
- string.match(ws, '"humidity":([%d]+)') or _wdata["{humid}"]
- _wdata["{press}"] = -- Pressure in hPa
- string.match(ws, '"pressure":([%d%.]+)') or _wdata["{press}"]
+ string.match(stdout, '"deg":([%d]+)') or _wdata["{wind deg}"]
+ _wdata["{wind mps}"] = -- Wind speed in meters per second
+ string.match(stdout, '"speed":([%d%.]+)') or _wdata["{wind mps}"]
+ _wdata["{sky}"] = -- Sky conditions
+ string.match(stdout, '"main":"([%a]+)"') or _wdata["{sky}"]
+ _wdata["{weather}"] = -- Weather description
+ string.match(stdout, '"description":"([%a%s]+)"') or _wdata["{weather}"]
+ _wdata["{temp c}"] = -- Temperature in celsius
+ string.match(stdout, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"]
+ _wdata["{temp min c}"] = -- Minimal Temperature in celsius
+ string.match(stdout, '"temp_min":([%-]?[%d%.]+)') or _wdata["{temp min c}"]
+ _wdata["{temp max c}"] = -- Maximal Temperature in celsius
+ string.match(stdout, '"temp_max":([%-]?[%d%.]+)') or _wdata["{temp max c}"]
+ _wdata["{humid}"] = -- Relative humidity in percent
+ string.match(stdout, '"humidity":([%d]+)') or _wdata["{humid}"]
+ _wdata["{sunrise}"] = -- Sunrise
+ tonumber(string.match(stdout, '"sunrise":([%d]+)')) or _wdata["{sunrise}"]
+ _wdata["{sunset}"] = -- Sunset
+ tonumber(string.match(stdout, '"sunset":([%d]+)')) or _wdata["{sunset}"]
+ _wdata["{press}"] = -- Pressure in hPa
+ string.match(stdout, '"pressure":([%d%.]+)') or _wdata["{press}"]
-- Wind speed in km/h
if _wdata["{wind mps}"] ~= "N/A" then
@@ -92,17 +90,32 @@
_wdata["{wind deg}"] = tonumber(_wdata["{wind deg}"])
-- Lua tables start at [1]
- if (_wdata["{wind deg}"] / 45)%1 == 0 then
+ if (_wdata["{wind deg}"] / 45) % 1 == 0 then
_wdata["{wind aim}"] = _wdirs[_wdata["{wind deg}"] / 45 + 1]
else
- _wdata["{wind aim}"] =
- _wdirs[math.ceil(_wdata["{wind deg}"] / 45) + 1]..
- _wdirs[math.floor(_wdata["{wind deg}"] / 45) + 1]
+ _wdata["{wind aim}"] = _wdirs[math.ceil(_wdata["{wind deg}"] / 45)
+
+ 1] ..
+ _wdirs[math.floor(
+ _wdata["{wind deg}"] / 45) + 1]
end
end
return _wdata
end
+
+function openweather_all.async(format, warg, callback)
+ if not warg then return callback {} end
+ if type(warg) ~= "table" then return callback {} end
+
+ -- Get weather forceast using the city ID code, from:
+ -- * OpenWeatherMap.org
+ local openweather = "http://api.openweathermap.org/data/2.5/weather?id=" ..
+ warg.city_id .. "&appid=" .. warg.app_id ..
+ "&mode=json&units=metric"
+
+ spawn.easy_async("curl --connect-timeout 1 -fsm 3 '" .. openweather .. "'",
+ function(...) callback(parse(...)) end)
+end
-- }}}
-return setmetatable(openweather_all, { __call = function(_, ...) return
worker(...) end })
+return helpers.setasyncall(openweather_all)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/docs/requirements.txt
new/vicious-2.5.1/docs/requirements.txt
--- old/vicious-2.5.0/docs/requirements.txt 2020-09-27 16:31:00.000000000
+0200
+++ new/vicious-2.5.1/docs/requirements.txt 2022-05-04 03:43:26.000000000
+0200
@@ -1,3 +1,3 @@
Sphinx >= 3
-sphinx_rtd_theme
+sphinx_rtd_theme >= 1
sphinxcontrib-luadomain
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/docs/source/contrib.rst
new/vicious-2.5.1/docs/source/contrib.rst
--- old/vicious-2.5.0/docs/source/contrib.rst 2020-09-27 16:31:00.000000000
+0200
+++ new/vicious-2.5.1/docs/source/contrib.rst 2022-05-04 03:43:26.000000000
+0200
@@ -133,12 +133,15 @@
vicious.contrib.openweather
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Provides weather information for a requested city
+Provides weather information for a requested city from OpenWeatherMap (OWM)
-* Argument: OpenWeatherMap city ID, e.g. ``"1275339"``
-* Returns a table with string keys: ``${city}``, ``${wind deg}``,
- ``${wind aim}``, ``${wind kmh}``, ``${wind mps}``, ``${sky}``,
- ``${weather}``, ``${temp c}``, ``${humid}`` and ``${press}``
+* Argument: a table containing the fields ``city_id`` with the OWM city ID,
e.g.
+ ``"2643743"`` and ``app_id`` with the the OWM app ID, e.g
+ ``"4c57f0c88d9844630327623633ce269cf826ab99"``
+* Returns a table with string keys: ``${city}``, ``${humid}``, ``${press}``,
+ ``${sky}``, ``${sunrise}``, ``${sunset}``, ``${temp c}``, ``${temp max c}``,
+ ``${temp min c}``, ``${weather}``, ``${wind aim}``, ``${wind deg}``,
+ ``${wind kmh}`` and ``${wind mps}``,
vicious.contrib.nvinf
^^^^^^^^^^^^^^^^^^^^^
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/docs/source/widgets.rst
new/vicious-2.5.1/docs/source/widgets.rst
--- old/vicious-2.5.0/docs/source/widgets.rst 2020-09-27 16:31:00.000000000
+0200
+++ new/vicious-2.5.1/docs/source/widgets.rst 2022-05-04 03:43:26.000000000
+0200
@@ -150,8 +150,9 @@
Supported platform: platform independent, requiring ``curl``.
This widget expects login information in your ``~/.netrc`` file, e.g.
-``machine mail.google.com login user password pass`` and you have to disable
-`two step verification`_. `Allow access for less secure apps`_ afterwards.
+``machine mail.google.com login user password pass``. Use your `app
+password`_ if you can, or disable `two step verification`_
+and `allow access for less secure apps`_.
.. caution::
@@ -289,6 +290,11 @@
``${random}``, ``${repeat}``, ``${state}``, ``${Artist}``, ``${Title}``,
``${Album}``, ``${Genre}`` and optionally ``${Name}`` and ``${file}``.
+In addition, some common mpd commands are available as functions:
+``playpause``, ``play``, ``pause``, ``stop``, ``next``, ``previous``.
+Arguments are of the same form as above, and no value is returned,
+e.g. ``vicious.widgets.mpd.playpause()``.
+
vicious.widgets.net
-------------------
@@ -351,6 +357,7 @@
Supported platforms: platform independent.
Returns an array containing:
+
* ``$1``: Operating system in use
* ``$2``: Release version
* ``$3``: Username
@@ -501,7 +508,8 @@
and ``${sign}`` (signal level, in dBm)
.. _strftime(3): https://linux.die.net/man/3/strftime
+.. _app password: https://support.google.com/accounts/answer/185833?hl=en
.. _two step verification: https://support.google.com/accounts/answer/1064203
-.. _Allow access for less secure apps:
+.. _allow access for less secure apps:
https://www.google.com/settings/security/lesssecureapps
.. _amixer(1): https://linux.die.net/man/1/amixer
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/helpers.lua
new/vicious-2.5.1/helpers.lua
--- old/vicious-2.5.0/helpers.lua 2020-09-27 16:31:00.000000000 +0200
+++ new/vicious-2.5.1/helpers.lua 2022-05-04 03:43:26.000000000 +0200
@@ -4,16 +4,13 @@
-- Copyright (C) 2009 Lucas de Vries <[email protected]>
-- Copyright (C) 2009 R??my C. <[email protected]>
-- Copyright (C) 2009-2012 Adrian C. (anrxc) <[email protected]>
--- Copyright (C) 2011 Joerg T. (Mic92) <[email protected]>
+-- Copyright (C) 2011-2018 J??rg Thalheim <[email protected]>
-- Copyright (C) 2012 Arvydas Sidorenko <[email protected]>
--- Copyright (C) 2012 J??rg Thalheim <[email protected]>
--- Copyright (C) 2014-2015 J??rg Thalheim <[email protected]>
--- Copyright (C) 2017 Joerg Thalheim <[email protected]>
-- Copyright (C) 2017,2019 mutlusun <[email protected]>
--- Copyright (C) 2017-2018 J??rg Thalheim <[email protected]>
-- Copyright (C) 2018-2019 Nguy???n Gia Phong <[email protected]>
-- Copyright (C) 2019 Alexander Koch <[email protected]>
-- Copyright (C) 2019 Enric Morales <[email protected]>
+-- Copyright (C) 2022 Constantin Piber <[email protected]>
--
-- This file is part of Vicious.
--
@@ -37,6 +34,7 @@
local require = require
local tonumber = tonumber
local tostring = tostring
+local type = type
local io = { open = io.open, popen = io.popen }
local setmetatable = setmetatable
local getmetatable = getmetatable
@@ -168,11 +166,12 @@
-- {{{ Format a string with args
function helpers.format(format, args)
for var, val in pairs(args) do
- format = format:gsub("$" .. (tonumber(var) and var or
- var:gsub("[-+?*]", function(i) return "%"..i end)),
- val)
+ if tonumber(var) == nil then
+ var = var:gsub("[-+?*]", function(i) return "%"..i end)
+ end
+ if type(val) == "string" then val = val:gsub("%%", "%%%%") end
+ format = format:gsub("$" .. var, val)
end
-
return format
end
-- }}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/init.lua new/vicious-2.5.1/init.lua
--- old/vicious-2.5.0/init.lua 2020-09-27 16:31:00.000000000 +0200
+++ new/vicious-2.5.1/init.lua 2022-05-04 03:43:26.000000000 +0200
@@ -11,6 +11,7 @@
-- Copyright (C) 2017 mutlusun <[email protected]>
-- Copyright (C) 2018 Beniamin Kalinowski <[email protected]>
-- Copyright (C) 2018,2020 Nguy???n Gia Phong <[email protected]>
+-- Copyright (C) 2022 Constantin Piber <[email protected]>
--
-- This file is part of Vicious.
--
@@ -38,6 +39,14 @@
remove = table.remove
}
local helpers = require("vicious.helpers")
+local dstatus, debug = pcall(require, "gears.debug")
+local stderr = io.stderr
+local warn
+if dstatus then
+ warn = debug.print_warning
+else
+ warn = function (msg) stderr:write("Warning (vicious): ", msg, "\n") end
+end
-- Vicious: widgets for the awesome window manager
local vicious = {}
@@ -132,7 +141,8 @@
reg.warg,
function(data)
update_cache(data, update_time, c)
- update_value(data)
+ local status, res = pcall(update_value, data)
+ if not status then warn(res) end
reg.lock=false
end)
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/vicious-2.5.0/widgets/mpd_all.lua
new/vicious-2.5.1/widgets/mpd_all.lua
--- old/vicious-2.5.0/widgets/mpd_all.lua 2020-09-27 16:31:00.000000000
+0200
+++ new/vicious-2.5.1/widgets/mpd_all.lua 2022-05-04 03:43:26.000000000
+0200
@@ -5,6 +5,7 @@
-- Copyright (C) 2018-2019 Nguy???n Gia Phong <[email protected]>
-- Copyright (C) 2019 Juan Carlos Menonita
<[email protected]>
-- Copyright (C) 2019 Lorenzo Gaggini <[email protected]>
+-- Copyright (C) 2022 Constantin Piber <[email protected]>
--
-- This file is part of Vicious.
--
@@ -75,6 +76,40 @@
end
-- }}}
+-- {{{ Build shell command from mpd command string
+local function build_cmd(warg, q)
+ -- Construct MPD client options, fallback to defaults when necessary
+ local query = ("printf 'password %s\n%sclose\n'"):format(
+ warg and (warg.password or warg[1]) or '""',
+ q)
+ local connect = ("curl --connect-timeout 1 -fsm 3 telnet://%s:%s"):format(
+ warg and (warg.host or warg[2]) or "127.0.0.1",
+ warg and (warg.port or warg[3]) or "6600")
+ return query .. "|" .. connect
+end
+-- }}}
+
+-- {{{ Common MPD commands
+function mpd_all.playpause(warg)
+ spawn.with_shell(build_cmd(warg, "pause\n"))
+end
+function mpd_all.play(warg)
+ spawn.with_shell(build_cmd(warg, "pause 0\n"))
+end
+function mpd_all.pause(warg)
+ spawn.with_shell(build_cmd(warg, "pause 1\n"))
+end
+function mpd_all.stop(warg)
+ spawn.with_shell(build_cmd(warg, "stop\n"))
+end
+function mpd_all.next(warg)
+ spawn.with_shell(build_cmd(warg, "next\n"))
+end
+function mpd_all.previous(warg)
+ spawn.with_shell(build_cmd(warg, "previous\n"))
+end
+-- }}}
+
-- {{{ MPD widget type
function mpd_all.async(format, warg, callback)
-- Fallback values
@@ -83,8 +118,8 @@
["{bitrate}"] = 0,
["{elapsed}"] = 0,
["{duration}"] = 0,
- ["{repeat}"] = false,
- ["{random}"] = false,
+ ["{repeat}"] = 0,
+ ["{random}"] = 0,
["{state}"] = "N/A",
["{Artist}"] = "N/A",
["{Title}"] = "N/A",
@@ -94,15 +129,10 @@
--["{file}"] = "N/A",
}
- -- Construct MPD client options, fallback to defaults when necessary
- local query = ("printf 'password
%s\nstatus\ncurrentsong\nclose\n'"):format(
- warg and (warg.password or warg[1]) or '""')
- local connect = ("curl --connect-timeout 1 -fsm 3 telnet://%s:%s"):format(
- warg and (warg.host or warg[2]) or "127.0.0.1",
- warg and (warg.port or warg[3]) or "6600")
+ local cmd = build_cmd(warg, "status\ncurrentsong\n")
-- Get data from MPD server
- spawn.with_line_callback_with_shell(query .. "|" .. connect, {
+ spawn.with_line_callback_with_shell(cmd, {
stdout = function (line)
for k, v in line:gmatch"([%w]+):[%s](.*)$" do
local key = "{" .. k .. "}"