-
Notifications
You must be signed in to change notification settings - Fork 28
/
asyncshell.lua
executable file
·71 lines (63 loc) · 2.58 KB
/
asyncshell.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
-- Asynchronous io.popen for Awesome WM.
-- How to use...
-- ...asynchronously:
-- asyncshell.request('wscript -Kiev', function(f) wwidget.text = f:read("*l") end)
-- ...synchronously
-- wwidget.text = asyncshell.demand('wscript -Kiev', 5):read("*l") or "Error"
local awful = require('awful')
asyncshell = {}
asyncshell.request_table = {}
asyncshell.id_counter = 0
asyncshell.folder = "/tmp/asyncshell"
asyncshell.file_template = asyncshell.folder .. '/req'
-- Create a directory for asynchell response files
os.execute("mkdir -p " .. asyncshell.folder)
-- Returns next tag - unique identifier of the request
local function next_id()
asyncshell.id_counter = (asyncshell.id_counter + 1) % 100000
return asyncshell.id_counter
end
-- Sends an asynchronous request for an output of the shell command.
-- @param command Command to be executed and taken output from
-- @param callback Function to be called when the command finishes
-- @return Request ID
function asyncshell.request(command, callback)
local id = next_id()
local tmpfname = asyncshell.file_template .. id
asyncshell.request_table[id] = {callback = callback}
local req =
string.format("bash -c '%s > %s; " ..
'echo "asyncshell.deliver(%s)" | ' ..
"awesome-client' 2> /dev/null",
string.gsub(command, "'", "'\\''"), tmpfname, id, tmpfname)
awful.util.spawn(req, false)
return id
end
-- Calls the remembered callback function on the output of the shell
-- command.
-- @param id Request ID
-- @param output The output file of the shell command to be delievered
function asyncshell.deliver(id)
if asyncshell.request_table[id] and
asyncshell.request_table[id].callback then
local output = io.open(asyncshell.file_template .. id, 'r')
asyncshell.request_table[id].callback(output)
end
end
-- Sends a synchronous request for an output of the command. Waits for
-- the output, but if the given timeout expires returns nil.
-- @param command Command to be executed and taken output from
-- @param timeout Maximum amount of time to wait for the result
-- @return File handler on success, nil otherwise
function asyncshell.demand(command, timeout)
local id = next_id()
local tmpfname = asyncshell.file_template .. id
local f = io.popen(string.format("(%s > %s; echo asyncshell_done) & " ..
"(sleep %s; echo asynchell_timeout)",
command, tmpfname, timeout))
local result = f:read("*line")
if result == "asyncshell_done" then
return io.open(tmpfname)
end
end
return asyncshell