diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3b46df8722..4e4a9fbcaf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -240,10 +240,6 @@ jobs: if: matrix.coverage run: sudo -H luarocks install cluacov - - name: Install codecov.io uploader - if: matrix.coverage == 'codecov' - run: wget -O /tmp/codecov-bash https://codecov.io/bash - # Check out repository to ${{ github.workspace }} # Automatically picks the current branch/PR - uses: actions/checkout@v2 @@ -308,7 +304,7 @@ jobs: run: cd "${{ github.workspace }}/build" && make check-unit - name: Run examples tests - run: cd "${{ github.workspace }}/build" && make check-examples + run: cd "${{ github.workspace }}/build" && make check-examples -j24 - name: Run requires tests if: matrix.coverage @@ -317,13 +313,12 @@ jobs: - name: Run themes tests run: cd "${{ github.workspace }}/build" && make check-themes - - name: Upload Lua code coverage report + - name: Generate Lua coverage report if: matrix.coverage == 'codecov' run: | luacov - bash /tmp/codecov-bash -f build/luacov.report.out -X gcov -X coveragepy -F luacov - - name: Upload C code coverage report + - name: Generate C coverage report if: matrix.coverage == 'codecov' run: | # Report coverage for each .gcno file separately. @@ -342,9 +337,22 @@ jobs: # with Code Climate. find "gcov.$i" -maxdepth 1 -type f -name '#usr#*.gcov' -delete done - - # Upload to Codecov. - bash /tmp/codecov-bash -X gcov -X coveragepy -F gcov + + - name: Upload Lua code coverage report + if: matrix.coverage == 'codecov' + uses: codecov/codecov-action@v3 + with: + files: "${{ github.workspace }}/build/luacov.report.out" + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + - name: Upload C code coverage report + if: matrix.coverage == 'codecov' + uses: codecov/codecov-action@v3 + with: + files: "${{ github.workspace }}/build/*/*.gcov" + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} # `check-qa` is the only test that doesn't get a coverage report, so it has to run after all of that. - name: Run qa tests diff --git a/docs/common/cursor.ldoc b/docs/common/cursor.ldoc new file mode 100644 index 0000000000..8401b2e453 --- /dev/null +++ b/docs/common/cursor.ldoc @@ -0,0 +1,80 @@ +
+--
num\_glyphs
+--
arrow
+--
based\_arrow\_down
+--
based\_arrow\_up
+--
boat
+--
bogosity
+--
bottom\_left\_corner
+--
bottom\_right\_corner
+--
bottom\_side
+--
bottom\_tee
+--
box\_spiral
+--
center\_ptr
+--
circle
+--
clock
+--
coffee\_mug
+--
cross
+--
crosshair
+--
cross\_reverse
+--
cursor
+--
diamond\_cross
+--
dotbox
+--
dot
+--
double\_arrow
+--
draft\_large
+--
draft\_small
+--
draped\_box
+--
exchange
+--
fleur
+--
gobbler
+--
gumby
+--
hand
+--
hand
+--
heart
+--
icon
+--
iron\_cross
+--
leftbutton
+--
left\_ptr
+--
left\_side
+--
left\_tee
+--
ll\_angle
+--
lr\_angle
+--
man
+--
middlebutton
+--
mouse
+--
pencil
+--
pirate
+--
plus
+--
question\_arrow
+--
rightbutton
+--
right\_ptr
+--
right\_side
+--
right\_tee
+--
rtl\_logo
+--
sailboat
+--
sb\_down\_arrow
+--
sb\_h\_double\_arrow
+--
sb\_left\_arrow
+--
sb\_right\_arrow
+--
sb\_up\_arrow
+--
sb\_v\_double\_arrow
+--
shuttle
+--
sizing
+--
spider
+--
spraycan
+--
star
+--
target
+--
tcross
+--
top\_left\_arrow
+--
top\_left\_corner
+--
top\_right\_corner
+--
top\_side
+--
top\_tee
+--
trek
+--
ul\_angle
+--
umbrella
+--
ur\_angle
+--
watch
+--
xterm
+--
diff --git a/lib/awful/wallpaper.lua b/lib/awful/wallpaper.lua index 285bc8c013..2e7bdb837e 100644 --- a/lib/awful/wallpaper.lua +++ b/lib/awful/wallpaper.lua @@ -30,6 +30,11 @@ -- --@DOC_awful_wallpaper_mazimized3_EXAMPLE@ -- +-- To maintain the image's aspect ratio while filling the +-- screen, the image can be cropped using `gears.surface`: +-- +--@DOC_awful_wallpaper_mazimized4_EXAMPLE@ +-- -- Finally, it is also possible to use simpler "branding" in a corner using -- `awful.placement`: -- diff --git a/lib/awful/widget/keyboardlayout.lua b/lib/awful/widget/keyboardlayout.lua index 486259901b..8a41b64a23 100644 --- a/lib/awful/widget/keyboardlayout.lua +++ b/lib/awful/widget/keyboardlayout.lua @@ -265,8 +265,16 @@ end -- It shows current keyboard layout name in a textbox. -- -- @constructorfct awful.widget.keyboardlayout +-- @tparam[opt] table args The argument table containing any of the arguments below. +-- @tparam[opt] table args.country_codes Array of names of custom keyboard layouts. -- @treturn awful.widget.keyboardlayout A keyboard layout widget. -function keyboardlayout.new() +function keyboardlayout.new(args) + if args and args.country_codes then + for _, country_code in ipairs(args.country_codes) do + keyboardlayout.xkeyboard_country_code[country_code] = true + end + end + local widget = textbox() local self = widget_base.make_widget(widget, nil, {enable_properties=true}) diff --git a/lib/awful/widget/taglist.lua b/lib/awful/widget/taglist.lua index 8dd773057b..e5e41663f0 100644 --- a/lib/awful/widget/taglist.lua +++ b/lib/awful/widget/taglist.lua @@ -1,7 +1,7 @@ --------------------------------------------------------------------------- --- Taglist widget module for awful. -- --- Here is a more advanced example of how to extent the `taglist`. It provides: +-- Here is a more advanced example of how to extend the `taglist`. It provides: -- -- * mouse "hover" color -- * an extra index field @@ -431,7 +431,7 @@ end --- The current number of tags. -- --- Note that the `tasklist` is usually lazy-loaded. Reading this property +-- Note that the `taglist` is usually lazy-loaded. Reading this property -- may cause the widgets to be created. Depending on where the property is called -- from, it might, in theory, cause an infinite loop. -- diff --git a/lib/gears/table.lua b/lib/gears/table.lua index 9702c7bc24..2c6e6ad928 100644 --- a/lib/gears/table.lua +++ b/lib/gears/table.lua @@ -1,5 +1,5 @@ --------------------------------------------------------------------------- ---- Various functions to worj with tables. +--- Various functions to work with tables. -- -- Examples -- ======== diff --git a/lib/gears/timer.lua b/lib/gears/timer.lua index b8ab26fb86..28045292da 100644 --- a/lib/gears/timer.lua +++ b/lib/gears/timer.lua @@ -145,7 +145,7 @@ end -- @see start -- @see stop ---- The timer timeout value. +--- The timer timeout value in seconds. -- -- @property timeout -- @tparam[opt=0] number timeout @@ -182,8 +182,8 @@ local timer_instance_mt = { -- -- @tparam table args Arguments. -- @tparam number args.timeout Timeout in seconds (e.g. `1.5`). --- @tparam[opt=false] boolean args.autostart Automatically start the timer. --- @tparam[opt=false] boolean args.call_now Call the callback at timer creation. +-- @tparam[opt=false] boolean args.autostart Immediately start the timer countdown. +-- @tparam[opt=false] boolean args.call_now Immediately call the callback function. -- @tparam[opt] function args.callback Callback function to connect to the -- "timeout" signal. -- @tparam[opt=false] boolean args.single_shot Run only once then stop. @@ -205,12 +205,11 @@ function timer.new(args) end if args.callback then - if args.call_now then - args.callback() - end ret:connect_signal("timeout", args.callback) end - + if args.call_now then + ret:emit_signal("timeout") + end if args.single_shot then ret:connect_signal("timeout", function() ret:stop() end) end diff --git a/lib/naughty/layout/box.lua b/lib/naughty/layout/box.lua index dd7fe8f3fb..e12b0597ec 100644 --- a/lib/naughty/layout/box.lua +++ b/lib/naughty/layout/box.lua @@ -23,6 +23,7 @@ local abutton = require("awful.button") local ascreen = require("awful.screen") local gpcall = require("gears.protected_call") local dpi = require("beautiful").xresources.apply_dpi +local cst = require("naughty.constants") local default_widget = require("naughty.widget._default") @@ -378,18 +379,20 @@ local function new(args) end --TODO remove - local function hide() - local n = ret._private.notification[1] + local function hide(reason) + return function () + local n = ret._private.notification[1] - if n then - n:destroy() + if n then + n:destroy(reason) + end end end - --FIXME there's another pull request for this + -- On right click, close the notification without triggering the default action ret:buttons(gtable.join( - abutton({ }, 1, hide), - abutton({ }, 3, hide) + abutton({ }, 1, hide(cst.notification_closed_reason.dismissed_by_user)), + abutton({ }, 3, hide(cst.notification_closed_reason.silent)) )) gtable.crush(ret, box, false) diff --git a/lib/wibox/container/margin.lua b/lib/wibox/container/margin.lua index eb28eb5760..34072895cc 100644 --- a/lib/wibox/container/margin.lua +++ b/lib/wibox/container/margin.lua @@ -71,7 +71,7 @@ function margin:fit(context, width, height) return w + extra_w, h + extra_h end ---- The widget to be wrapped the the margins. +--- The widget to be wrapped by the margins. -- -- @property widget -- @tparam[opt=nil] widget|nil widget diff --git a/lib/wibox/widget/graph.lua b/lib/wibox/widget/graph.lua index 96fa3d2e5b..9982dbbd5d 100644 --- a/lib/wibox/widget/graph.lua +++ b/lib/wibox/widget/graph.lua @@ -1,9 +1,9 @@ --------------------------------------------------------------------------- --- Display multiple values as a stream of bars. -- --- The graph goes from left to right. To change this to right to left, use --- a `wibox.container.mirror` widget. This can also be used to have data --- shown from top to bottom. +-- The graph goes from left to right. To change the movement's direction, +-- use a `wibox.container.mirror` widget. This can also be used to have +-- data shown from top to bottom. -- -- To add text on top of the graph, use a `wibox.layout.stack` and a -- `wibox.container.align` widgets. diff --git a/lib/wibox/widget/separator.lua b/lib/wibox/widget/separator.lua index 3d13cb8816..32f44e5aea 100644 --- a/lib/wibox/widget/separator.lua +++ b/lib/wibox/widget/separator.lua @@ -1,7 +1,7 @@ --------------------------------------------------------------------------- -- A flexible separator widget. -- --- By default, this widget display a simple line, but can be extended by themes +-- By default, this widget displays a simple line, but can be extended by themes -- (or directly) to display much more complex visuals. -- -- This widget is mainly intended to be used alongside the `spacing_widget` diff --git a/lib/wibox/widget/slider.lua b/lib/wibox/widget/slider.lua index 690ee7fad6..dedc45415a 100644 --- a/lib/wibox/widget/slider.lua +++ b/lib/wibox/widget/slider.lua @@ -89,7 +89,11 @@ local slider = {mt={}} -- @propemits true false -- @propbeautiful ---- The handle grab cursor. +--- The cursor icon while grabbing the handle. +-- The available cursor names are: +-- +--@DOC_cursor_COMMON@ +-- -- @property handle_cursor -- @tparam[opt="fleur"] string|nil handle_cursor -- @propbeautiful @@ -228,7 +232,10 @@ local slider = {mt={}} -- @tparam[opt=gears.shape.rectangle] gears.shape shape -- @see gears.shape ---- The handle grab cursor. +--- The cursor icon while grabbing the handle. +-- The available cursor names are: +-- +--@DOC_cursor_COMMON@ -- -- @beautiful beautiful.slider_handle_cursor -- @tparam[opt="fleur"] string cursor @@ -565,7 +572,9 @@ end -- @tparam[opt] number args.handle_width The slider handle width. -- @tparam[opt] color args.handle_border_color The handle border_color. -- @tparam[opt] number args.handle_border_width The handle border width. --- @tparam[opt] string args.handle_cursor The handle grab cursor. +-- @tparam[opt] string args.handle_cursor +-- The cursor icon while grabbing the handle. +-- The available cursor names are listed under handle_cursor, in the "Object properties" section. -- @tparam[opt] gears.shape args.bar_shape The bar (background) shape. -- @tparam[opt] number args.bar_height The bar (background) height. -- @tparam[opt] color args.bar_color The bar (background) color. diff --git a/objects/client.c b/objects/client.c index 6946dbc638..17ad387abc 100644 --- a/objects/client.c +++ b/objects/client.c @@ -1375,7 +1375,7 @@ lua_class_t client_class; /** * The FreeDesktop StartId. * - * When a client is spawned (like using a terminal or `awful.spawn`, a startup + * When a client is spawned (like using a terminal or `awful.spawn`), a startup * notification identifier is created. When the client is created, this * identifier remain the same. This allow to match a spawn event to an actual * client. diff --git a/spawn.c b/spawn.c index d736d5834f..c0a21d4860 100644 --- a/spawn.c +++ b/spawn.c @@ -412,9 +412,21 @@ spawn_child_exited(pid_t pid, int status) * * @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? + * @tparam[opt="DEV_NULL"] boolean|string stdin Pass `true` to return a fd for + * stdin. Use `"DEV_NULL"` to redirect to /dev/null, or `"INHERIT"` to inherit + * the parent's stdin. Implementation note: Pre-2.74 glib doesn't support + * *explicit* `DEV_NULL`. When `DEV_NULL` is passed on glib <2.74, Awesome will + * use glib's default behaviour. + * @tparam[opt="INHERIT"] boolean|string stdout Pass `true` to return a fd for + * stdout. Use `"DEV_NULL"` to redirect to /dev/null, or `"INHERIT"` to + * inherit the parent's stdout. Implementation note: Pre-2.74 glib doesn't + * support *explicit* `INHERIT`. When `INHERIT` is passed on glib <2.74, + * Awesome will use glib's default behaviour. + * @tparam[opt="INHERIT"] boolean|string stderr Pass `true` to return a fd for + * stderr. Use `"DEV_NULL"` to redirect to /dev/null, or `"INHERIT"` to + * inherit the parent's stderr. Implementation note: Pre-2.74 glib doesn't + * support *explicit* `INHERIT`. When `INHERIT` is passed on glib <2.74, + * Awesome will use glib's default behaviour. * @tparam[opt=nil] function exit_callback Function to call on process exit. The * function arguments will be type of exit ("exit" or "signal") and the exit * code / the signal number causing process termination. @@ -441,12 +453,66 @@ luaA_spawn(lua_State *L) 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); + /* Valid values for return_std* are: + * true -> return a fd + * false -> keep glib's default behaviour + * "DEV_NULL" -> use direct output to /dev/null + * "INHERIT" -> use the same fd as the parent + */ + if(lua_gettop(L) >= 3) { + if (lua_isstring(L, 3)) { + const char *str = lua_tostring(L, 3); + if (a_strcmp(str, "DEV_NULL") == 0){ + // This is the default behaviour. Compiles to a no-op before 2.74. + #if GLIB_CHECK_VERSION(2, 74, 0) + flags |= G_SPAWN_STDIN_FROM_DEV_NULL; + # endif + } else if (a_strcmp(str, "INHERIT") == 0) + flags |= G_SPAWN_CHILD_INHERITS_STDIN; + else + luaA_typerror(L, 3, "DEV_NULL or INHERIT"); + } else if(lua_isboolean(L, 3)) { + return_stdin = lua_toboolean(L, 3); + } else { + luaA_typerror(L, 3, "boolean or string"); + } + } + if(lua_gettop(L) >= 4) { + if (lua_isstring(L, 4)) { + const char *str = lua_tostring(L, 4); + if (a_strcmp(str, "DEV_NULL") == 0) + flags |= G_SPAWN_STDOUT_TO_DEV_NULL; + else if (a_strcmp(str, "INHERIT") == 0) { + // This is the default behaviour. Compiles to a no-op before 2.74. + #if GLIB_CHECK_VERSION(2, 74, 0) + flags |= G_SPAWN_CHILD_INHERITS_STDOUT; + # endif + } else + luaA_typerror(L, 4, "DEV_NULL or INHERIT"); + } else if(lua_isboolean(L, 4)) { + return_stdout = lua_toboolean(L, 4); + } else { + luaA_typerror(L, 4, "boolean or string"); + } + } + if(lua_gettop(L) >= 5) { + if (lua_isstring(L, 5)) { + const char *str = lua_tostring(L, 5); + if (a_strcmp(str, "DEV_NULL") == 0) + flags |= G_SPAWN_STDERR_TO_DEV_NULL; + else if (a_strcmp(str, "INHERIT") == 0) { + // This is the default behaviour. Compiles to a no-op before 2.74. + #if GLIB_CHECK_VERSION(2, 74, 0) + flags |= G_SPAWN_CHILD_INHERITS_STDERR; + # endif + } else + luaA_typerror(L, 5, "DEV_NULL or INHERIT"); + } else if(lua_isboolean(L, 5)) { + return_stderr = lua_toboolean(L, 5); + } else { + luaA_typerror(L, 5, "boolean or string"); + } + } if (!lua_isnoneornil(L, 6)) { luaA_checkfunction(L, 6); diff --git a/tests/examples/awful/wallpaper/mazimized4.lua b/tests/examples/awful/wallpaper/mazimized4.lua new file mode 100644 index 0000000000..7dff60973a --- /dev/null +++ b/tests/examples/awful/wallpaper/mazimized4.lua @@ -0,0 +1,22 @@ +--DOC_NO_USAGE --DOC_GEN_IMAGE +local awful = { wallpaper = require("awful.wallpaper") } --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE +local beautiful = require("beautiful") --DOC_HIDE +local gears = require("gears") --DOC_HIDE + +screen[1]._resize {x = 0, y = 0, width = 320, height = 196} --DOC_HIDE +local s = screen[1] --DOC_HIDE + + awful.wallpaper { + screen = s, + widget = { + image = gears.surface.crop_surface { + surface = gears.surface.load_uncached(beautiful.wallpaper), + ratio = s.geometry.width/s.geometry.height, + }, + widget = wibox.widget.imagebox, + }, + } + +require("gears.timer").run_delayed_calls_now() --DOC_HIDE + diff --git a/tests/examples/awful/wallpaper/widget1.lua b/tests/examples/awful/wallpaper/widget1.lua index 26228e13a0..52b817ed17 100644 --- a/tests/examples/awful/wallpaper/widget1.lua +++ b/tests/examples/awful/wallpaper/widget1.lua @@ -31,7 +31,7 @@ local s = screen[1] --DOC_HIDE --DOC_NEWLINE - -- Clip-out some increasingly large sections of add the sun "bars" + -- Clip-out some increasingly large sections to add the sun "bars" for i=0, 6 do cr:rectangle(0, height*.28 + i*(height*.055 + i/2), width, height*.055) end diff --git a/tests/examples/screen/struts.lua b/tests/examples/screen/struts.lua index 42498661bb..92b5f52bbf 100644 --- a/tests/examples/screen/struts.lua +++ b/tests/examples/screen/struts.lua @@ -11,7 +11,7 @@ local awful = { --DOC_HIDE -- Wibars and docked clients are the main users of the struts. local wibar = awful.wibar { position = "top", - height = 24, -- this will set the wibar won :struts() to top=24 + height = 24, -- this will set the wibar own :struts() to top=24 } awful.tag.add("1", { --DOC_HIDE diff --git a/tests/examples/wibox/nwidget/rules/urgency.lua b/tests/examples/wibox/nwidget/rules/urgency.lua index 45aeb48eb4..727de4ae57 100644 --- a/tests/examples/wibox/nwidget/rules/urgency.lua +++ b/tests/examples/wibox/nwidget/rules/urgency.lua @@ -40,7 +40,7 @@ local notif = --DOC_HIDE --DOC_NEWLINE - -- Create a normal notification. + -- Create a critical notification. local notif2 = --DOC_HIDE naughty.notification { title = "A notification 2", diff --git a/tests/examples/wibox/nwidget/rules/widget_template.lua b/tests/examples/wibox/nwidget/rules/widget_template.lua index d2d00d1f53..67e19ff851 100644 --- a/tests/examples/wibox/nwidget/rules/widget_template.lua +++ b/tests/examples/wibox/nwidget/rules/widget_template.lua @@ -11,7 +11,7 @@ beautiful.notification_bg = beautiful.bg_normal --DOC_HIDE ruled.notification.connect_signal("request::rules", function() -- Add a red background for urgent notifications. ruled.notification.append_rule { - rule = { app_name = "mdp" }, + rule = { app_name = "mpd" }, properties = { widget_template = { { @@ -78,12 +78,12 @@ local notif2 = --DOC_HIDE naughty.notification { --DOC_HIDE title = "Daft Punk", --DOC_HIDE message = "Harder, Better, Faster, Stronger", --DOC_HIDE - icon = beautiful.awesome_icon, + icon = beautiful.awesome_icon, --DOC_HIDE icon_size = 128, --DOC_HIDE - app_name = "mdp", --DOC_HIDE + app_name = "mpd", --DOC_HIDE } --DOC_HIDE -assert(notif2.app_name == "mdp") --DOC_HIDE +assert(notif2.app_name == "mpd") --DOC_HIDE assert(box) --DOC_HIDE box.widget.forced_width = 250 --DOC_HIDE diff --git a/tests/examples/wibox/widget/defaults/slider.lua b/tests/examples/wibox/widget/defaults/slider.lua index 1450a871e5..b7b96387d5 100644 --- a/tests/examples/wibox/widget/defaults/slider.lua +++ b/tests/examples/wibox/widget/defaults/slider.lua @@ -27,7 +27,7 @@ widget:connect_signal("property::value", function(_, new_value) error(string.format("unexpected value %s", new_value)) end --DOC_HIDE_END - naughty.notify { title = "Slider changed", message = new_value } + naughty.notify { title = "Slider changed", message = tostring(new_value) } end) --DOC_HIDE_START diff --git a/tests/test-spawn.lua b/tests/test-spawn.lua index 71b901929c..dfc3cc5f8d 100644 --- a/tests/test-spawn.lua +++ b/tests/test-spawn.lua @@ -10,6 +10,7 @@ end local spawns_done = 0 local async_spawns_done = 0 +local io_spawns_done = 0 local exit_yay, exit_snd = nil, nil -- * Using spawn with array is already covered by the test client. @@ -161,6 +162,72 @@ local steps = { return true end end, + -- Test inheriting stdio + function(count) + if count == 1 then + do -- Test that DEV_NULL works and doesn't return a fd + local read_line = false + local pid, _, _, stdout, stderr = awesome.spawn({ 'readlink', '/proc/self/fd/2' }, + false, false, true, "DEV_NULL") + assert(type(pid) ~= "string", pid) + assert(stderr == nil) + spawn.read_lines(require("lgi").Gio.UnixInputStream.new(stdout, true), + function(line) + assert(not read_line) + read_line = true + assert(line == "/dev/null", line) + io_spawns_done = io_spawns_done + 1 + end, nil, true) + end + + do -- Test that INHERIT works and doesn't return a fd + -- Note: if this is /dev/null, this test is useless. + local test_stdin = require('lgi').GLib.file_read_link('/proc/self/fd/0') + + local read_line = false + local pid, _, stdin, stdout = awesome.spawn({ 'readlink', '/proc/self/fd/0' }, + false, "INHERIT", true, false) + assert(type(pid) ~= "string", pid) + assert(stdin == nil) + spawn.read_lines(require("lgi").Gio.UnixInputStream.new(stdout, true), + function(line) + assert(not read_line) + read_line = true + assert(line == test_stdin, line) + io_spawns_done = io_spawns_done + 1 + end, nil, true) + end + + do -- Test that false doesn't return a pointer (behavior is untested - GLib defaults) + local pid, _, stdin, stdout, stderr = awesome.spawn({"true"}, + false, false, false, false) + assert(type(pid) ~= "string", pid) + assert(stdin == nil) + assert(stdout == nil) + assert(stderr == nil) + end + + do -- Test that true returns a pipe + local read_line = false + local pid, _, stdin, stdout, stderr = awesome.spawn({ 'readlink', '/proc/self/fd/0' }, + false, true, true, true) + assert(type(pid) ~= "string", pid) + assert(stdin ~= nil) + assert(stdout ~= nil) + assert(stderr ~= nil) + spawn.read_lines(require("lgi").Gio.UnixInputStream.new(stdout, true), + function(line) + assert(not read_line) + read_line = true + assert(line:find("^pipe:%[[0-9]+%]$"), line) + io_spawns_done = io_spawns_done + 1 + end, nil, true) + end + end + if io_spawns_done == 3 then + return true + end + end, -- Test spawn_once function() if #client.get() ~= 1 then return end