diff --git a/spawn.lua b/spawn.lua new file mode 100644 index 0000000..d252684 --- /dev/null +++ b/spawn.lua @@ -0,0 +1,76 @@ +-- spawn.lua - wrapper around Awesome awful.spawn with fallback +-- Copyright (C) 2019 Nguyễn Gia Phong +-- +-- This file is part of Vicious. +-- +-- Vicious is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as +-- published by the Free Software Foundation, either version 2 of the +-- License, or (at your option) any later version. +-- +-- Vicious is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with Vicious. If not, see . + +local status, spawn = pcall(require, "awful.spawn") +if status then return spawn end + +local io = { popen = io.popen } + +-- In case the Awesome library is not available, +-- fall back to this synchronous, handicapped API. +local spawn = {} + +--- Spawn a program and capture its output line by line. +-- @tparam string|table cmd The command. +-- @tab callbacks Table containing callbacks that should be invoked on +-- various conditions. +-- @tparam[opt] function callbacks.stdout Function that is called with each +-- line of output on stdout, e.g. `stdout(line)`. +-- @tparam[opt] function callbacks.stderr Function that is supposed to be called +-- with each line of output on stderr, but due to limitation of io.popen, +-- stderr will be discarded (sorry!). +-- @tparam[opt] function callbacks.output_done Function to call when no more +-- output is produced. +-- @tparam[opt] function callbacks.exit Function to call when the spawned +-- process exits. This function gets the exit reason and code as its +-- arguments. +-- The reason can be "exit" or "signal". +-- For "exit", the second argument is the exit code. +-- For "signal", the second argument is the signal causing process +-- termination. +-- @treturn boolean|nil true if cmd terminated successfully, or nil otherwise +function spawn.with_line_callback(cmd, callbacks) + local stdout_callback, stdout = callbacks.stdout, io.popen(cmd) + for line in stdout:lines() do stdout_callback(line) end + if callbacks.output_done then callbacks.output_done() end + + local success, reason, code = stdout:close() -- this requires Lua 5.2 + if callbacks.exit then callbacks.exit(reason, code) end + return success +end + +--- Spawn a program and capture its output. +-- @tparam string|table cmd The command. +-- @tab callback Function with the following arguments +-- @tparam string callback.stdout Output on stdout. +-- @tparam string callback.stderr Output on stderr, +-- which will be an empty due to limitation of io.popen. +-- @tparam string callback.exitreason Exit reason ("exit" or "signal"). +-- @tparam integer callback.exitcode Exit code (exit code or signal number, +-- depending on "exitreason"). +-- @treturn boolean|nil true if cmd terminated successfully, or nil otherwise +function spawn.easy_async(cmd, callback) + local out_stream = io.popen(cmd) + local stdout = out_stream:read("*all") + local success, reason, code = out_stream:close() -- requiring Lua 5.2 + callback(stdout, "", reason, code) + return success +end + +return spawn +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80