Skip to content

Instantly share code, notes, and snippets.

@psychon
Last active August 29, 2015 14:26
Show Gist options
  • Save psychon/8447f229fd313b5f3e3e to your computer and use it in GitHub Desktop.
Save psychon/8447f229fd313b5f3e3e to your computer and use it in GitHub Desktop.
Add function for reading other processes output, line by line or in total when the process is done
diff --git a/awesomerc.lua b/awesomerc.lua
index d9c7d07..a24b35c 100755
--- a/awesomerc.lua
+++ b/awesomerc.lua
@@ -462,3 +462,46 @@ end)
client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
-- }}}
+
+local function spawn_with_lines_implementation(stream, line_callback, done_callback)
+ while true do
+ local line, length = stream:async_read_line()
+ if type(length) ~= "number" then
+ break -- error (and "line" is the error message)
+ end
+ if #line ~= length then
+ break -- end of file
+ end
+ line_callback(line)
+ end
+ stream:async_close()
+ if done_callback then
+ done_callback()
+ end
+end
+function spawn_with_lines(cmd, line_callback, done_callback)
+ local Gio = require("lgi").Gio
+ local pid, _, _, stdout, _ = awesome.spawn(cmd, false, false, true, false)
+ if type(pid) == "string" then
+ print("error: " .. pid)
+ return pid -- error
+ end
+ local stream = Gio.DataInputStream.new(Gio.UnixInputStream.new(stdout, true))
+ Gio.Async.start(spawn_with_lines_implementation)(stream, line_callback, done_callback)
+end
+local spawn_with_output = function(cmd, callback)
+ local result = ""
+ spawn_with_lines(cmd, function(line)
+ result = result .. tostring(line) .. "\n"
+ end, function()
+ callback(result)
+ end)
+end
+
+local cmd = { "bash", "-c", "for x in $(seq 1 3) ; do sleep 1 ; echo This is line number $x ; done" }
+spawn_with_lines(cmd, function(...)
+ print("Read a line:", ...)
+end)
+spawn_with_output(cmd, function(...)
+ print("Got output:", ...)
+end)
diff --git a/spawn.c b/spawn.c
index 8153ed3..2bba63e 100644
--- a/spawn.c
+++ b/spawn.c
@@ -340,8 +340,14 @@ parse_command(lua_State *L, int idx, GError **error)
*
* @tparam string|table cmd The command to launch.
* @tparam[opt=true] boolean use_sn Use startup-notification?
+ * @tparam[opt=false] boolean stdin Return a fd for stdin?
+ * @tparam[opt=false] boolean stdout Return a fd for stdout?
+ * @tparam[opt=false] boolean stderr Return a fd for stderr?
* @treturn[1] integer Process ID if everything is OK.
* @treturn[1] string Startup-notification ID, if `use_sn` is true.
+ * @treturn[1] integer stdin, if `stdin` is true.
+ * @treturn[1] integer stdout, if `stdout` is true.
+ * @treturn[1] integer stderr, if `stderr` is true.
* @treturn[2] string An error string if an error occured.
* @function spawn
*/
@@ -349,12 +355,26 @@ int
luaA_spawn(lua_State *L)
{
gchar **argv = NULL;
- bool use_sn = true;
+ bool use_sn = true, return_stdin = false, return_stdout = false, return_stderr = false;
+ int stdin_fd = -1, stdout_fd = -1, stderr_fd = -1;
+ int *stdin_ptr = NULL, *stdout_ptr = NULL, *stderr_ptr = NULL;
gboolean retval;
GPid pid;
if(lua_gettop(L) >= 2)
use_sn = luaA_checkboolean(L, 2);
+ if(lua_gettop(L) >= 3)
+ return_stdin = luaA_checkboolean(L, 3);
+ if(lua_gettop(L) >= 4)
+ return_stdout = luaA_checkboolean(L, 4);
+ if(lua_gettop(L) >= 5)
+ return_stderr = luaA_checkboolean(L, 5);
+ if(return_stdin)
+ stdin_ptr = &stdin_fd;
+ if(return_stdout)
+ stdout_ptr = &stdout_fd;
+ if(return_stderr)
+ stderr_ptr = &stderr_fd;
GError *error = NULL;
argv = parse_command(L, 1, &error);
@@ -383,8 +403,9 @@ luaA_spawn(lua_State *L)
sn_launcher_context_setup_child_process(context);
}
- retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
- spawn_callback, NULL, &pid, &error);
+ retval = g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
+ spawn_callback, NULL, &pid,
+ stdin_ptr, stdout_ptr, stderr_ptr, &error);
g_strfreev(argv);
if(!retval)
{
@@ -402,9 +423,24 @@ luaA_spawn(lua_State *L)
/* push sn on stack */
if (context)
- lua_pushstring(L,sn_launcher_context_get_startup_id(context));
+ lua_pushstring(L, sn_launcher_context_get_startup_id(context));
+ else
+ lua_pushnil(L);
+
+ if(return_stdin)
+ lua_pushinteger(L, stdin_fd);
+ else
+ lua_pushnil(L);
+ if(return_stdout)
+ lua_pushinteger(L, stdout_fd);
+ else
+ lua_pushnil(L);
+ if(return_stderr)
+ lua_pushinteger(L, stderr_fd);
+ else
+ lua_pushnil(L);
- return (context)?2:1;
+ return 5;
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment