awful.spawn: Use LGI's Async facilities

Normally, writing asynchronous code with Gio results in an awful mess of
spaghetti code, because every operation needs a callback that is called when
this operation is done. To improve upon this, LGI provides some magic with
coroutines that hide the asyncronous nature of things and you end up with
"normal looking" code.

Use this Gio.Async facility in awful.spawn to make the code easier to follow.

Signed-off-by: Uli Schlachter <uli.schlachter@informatik.uni-oldenburg.de>
This commit is contained in:
Uli Schlachter 2016-09-12 14:55:03 +02:00 committed by Uli Schlachter
parent aab37dc629
commit 28fec60bf9
1 changed files with 28 additions and 33 deletions

View File

@ -161,7 +161,6 @@ local capi =
}
local lgi = require("lgi")
local Gio = lgi.Gio
local GLib = lgi.GLib
local util = require("awful.util")
local protected_call = require("gears.protected_call")
@ -370,6 +369,33 @@ function spawn.easy_async(cmd, callback)
})
end
local function read_stream(stream, line_callback, done_callback, close)
while true do
local line, length = stream:async_read_line()
if type(length) ~= "number" then
-- Error
print("Error in awful.spawn.read_lines:", tostring(length))
break
elseif end_of_file(line, length) then
-- End of file
break
else
-- Read a line
-- This needs tostring() for older lgi versions which returned
-- "GLib.Bytes" instead of Lua strings (I guess)
protected_call(line_callback, tostring(line))
end
end
if close then
stream:async_close()
end
if done_callback then
protected_call(done_callback)
end
end
--- Read lines from a Gio input stream
-- @tparam Gio.InputStream input_stream The input stream to read from.
-- @tparam function line_callback Function that is called with each line
@ -379,38 +405,7 @@ end
-- @tparam[opt=false] boolean close Should the stream be closed after end-of-file?
function spawn.read_lines(input_stream, line_callback, done_callback, close)
local stream = Gio.DataInputStream.new(input_stream)
local function done()
if close then
stream:close()
end
if done_callback then
protected_call(done_callback)
end
end
local start_read, finish_read
start_read = function()
stream:read_line_async(GLib.PRIORITY_DEFAULT, nil, finish_read)
end
finish_read = function(obj, res)
local line, length = obj:read_line_finish(res)
if type(length) ~= "number" then
-- Error
print("Error in awful.spawn.read_lines:", tostring(length))
done()
elseif end_of_file(line, length) then
-- End of file
done()
else
-- Read a line
-- This needs tostring() for older lgi versions which returned
-- "GLib.Bytes" instead of Lua strings (I guess)
protected_call(line_callback, tostring(line))
-- Read the next line
start_read()
end
end
start_read()
Gio.Async.start(read_stream)(stream, line_callback, done_callback, close)
end
capi.awesome.connect_signal("spawn::canceled" , spawn.on_snid_cancel )