From 90b17bdc094adcfb873fb214a00cebbbc262074f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sat, 6 Oct 2018 19:40:36 -0400 Subject: [PATCH 1/9] awful.rules: Add proper documentation to the extra client properties. Until now there wasn't much documentation available about how to use these properties. With the new work on `awful.spawn` that rely more and more on `awful.rules` integration, it is worth fixing. This commit add a new documentation section and a future commit will aggregate them to generate an index. --- docs/config.ld | 8 +++- lib/awful/client.lua | 87 ++++++++++++++++++++++++++++++++++++++++++++ lib/awful/rules.lua | 5 --- objects/client.c | 23 +++++++++++- 4 files changed, 116 insertions(+), 7 deletions(-) diff --git a/docs/config.ld b/docs/config.ld index a640e4f7c..0d783ace1 100644 --- a/docs/config.ld +++ b/docs/config.ld @@ -72,6 +72,8 @@ new_type("callback", "Callback functions prototype", false, "Parameters") new_type("rulesources", "Rule sources", false, "param") -- Filter functions for the taglist/tasklist/layoutlist new_type("filterfunction", "List filters", false) +-- Extra client properties available only in awful.rules/spawn constructs +new_type("clientruleproperty", "Extra properties available in awful.rules and awful.spawn", false, "Type") -- More fitting section names kind_names={topic='Documentation', module='Libraries', script='Sample files'} @@ -135,10 +137,14 @@ file = { } } +local no_prefix = { + property = true, signal = true, clientruleproperty = true +} + custom_display_name_handler = function(item, default_handler) -- Remove the "namespace" from the signals and properties - if item.type == "property" or item.type == "signal" then + if no_prefix[item.type] then local name = item.name:match("%.([^.]+)$") return name ~= "" and name or item.name end diff --git a/lib/awful/client.lua b/lib/awful/client.lua index ffa20e04d..f75270cfa 100644 --- a/lib/awful/client.lua +++ b/lib/awful/client.lua @@ -59,6 +59,93 @@ client.property = {} client.shape = require("awful.client.shape") client.focus = require("awful.client.focus") +--- The client default placement on the screen. +-- +-- The default config uses: +-- +-- awful.placement.no_overlap+awful.placement.no_offscreen +-- +-- @clientruleproperty placement +-- @see awful.placement + +--- When applying the placement, honor the screen padding. +-- @clientruleproperty honor_padding +-- @param[opt=true] boolean +-- @see awful.placement + +--- When applying the placement, honor the screen work area. +-- +-- The workarea is the part of the screen that excludes the bars and docks. +-- +-- @clientruleproperty honor_workarea +-- @param[opt=true] boolean +-- @see awful.placement + +--- The client default tag. +-- @clientruleproperty tag +-- @param tag +-- @see tag +-- @see new_tag +-- @see tags +-- @see switch_to_tags + +--- The client default tags. +-- +-- Avoid using the tag and tags properties at the same time, it will cause +-- issues. +-- +-- @clientruleproperty tags +-- @param[opt={tag}] table +-- @see tag +-- @see new_tag +-- @see tags +-- @see switch_to_tags + +--- Create a new tag for this client. +-- +-- If the value is `true`, the new tag will be named after the client `class`. +-- If it is a string, it will be the tag name. +-- +-- If a table is used, all of its properties will be passed to the tag +-- constructor: +-- +-- new_tag = { +-- name = "My new tag!", -- The tag name. +-- layout = awful.layout.suit.max, -- Set the tag layout. +-- volatile = true, -- Remove the tag when the client is closed. +-- } +-- +-- @tparam[opt=false] table|string|boolean new_tag +-- @clientruleproperty new_tag +-- @see tag +-- @see tags +-- @see switch_to_tags + +--- Unselect the current tags and select this client tags. +-- Note that this property was called `switchtotag` in previous Awesome versions. +-- @clientruleproperty switch_to_tags +-- @param[opt=false] boolean +-- @see tag.selected + +--- Define if the client should grab focus by default. +-- +-- The `request::activate` context for this call is `rules`. +-- +-- @clientruleproperty focus +-- @param[opt=false] boolean + +--- Should this client have a titlebar by default. +-- @clientruleproperty titlebars_enabled +-- @param[opt=false] boolean +-- @see awful.titlebar + +--- A function to call when this client is ready. +-- +-- It can be useful to set extra properties or perform actions. +-- +-- @clientruleproperty callback +-- @see awful.spawn + --- Jump to the given client. -- Takes care of focussing the screen, the right tag, etc. -- diff --git a/lib/awful/rules.lua b/lib/awful/rules.lua index 31ca6d044..f16741879 100644 --- a/lib/awful/rules.lua +++ b/lib/awful/rules.lua @@ -536,11 +536,6 @@ function rules.extra_properties.geometry(c, _, props) c:geometry(new_geo) --TODO use request::geometry end ---- Create a new tag based on a rule. --- @tparam client c The client --- @tparam boolean|function|string value The value. --- @tparam table props The properties. --- @treturn tag The new tag function rules.high_priority_properties.new_tag(c, value, props) local ty = type(value) local t = nil diff --git a/objects/client.c b/objects/client.c index ce3e748dd..2144c3c5e 100644 --- a/objects/client.c +++ b/objects/client.c @@ -108,7 +108,28 @@ /** Client class. * - * @table object + * This table allow to add more dynamic properties to the clients. For example, + * doing: + * + * function awful.client.object.set_my_cool_property(c, value) + * -- Some logic code + * c._my_secret_my_cool_property = value + * c:emit_signal("property::my_cool_property) + * end + * + * function awful.client.object.get_my_cool_property() + * return c._my_secret_my_cool_property + * end + * + * Will add a new "my_cool_property" dyanmic property to all client. These + * methods will be called when an user does `c.my_cool_property = "something"` + * or set them in `awdul.rules`. + * + * Note that doing this isn't required to set random properties to the client, + * it is only useful when setting or getting these properties require code to + * executed. + * + * @table awful.object */ /** When a client gains focus. From 6ac8f30d62413758c1b0e9bc6813d2987650563c Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 12 Oct 2018 14:01:11 -0400 Subject: [PATCH 2/9] build: Add more dependencies to the ldoc target Right now it was possible to modify `rc.lua` without the doc being aware of it. --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9285124c6..789ff98ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,7 +289,12 @@ if(GENERATE_DOC) file(COPY ${SOURCE_DIR}/docs/ldoc.css DESTINATION ${BUILD_DIR}/docs) add_custom_target(ldoc ALL - DEPENDS ${BUILD_DIR}/doc/index.html ${BUILD_DIR}/docs/ldoc.css) + DEPENDS + ${BUILD_DIR}/doc/index.html + ${BUILD_DIR}/docs/ldoc.css + generate_awesomerc + ) + if (STRICT_TESTS) set(ldoc_args --fatalwarnings .) set(ldoc_desc_suffix " (fatal warnings)") From 62c95d5fe6b14e9b26900e13c20b1f21748a034c Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sat, 6 Oct 2018 23:29:37 -0400 Subject: [PATCH 3/9] build: Move the meta file parser to an helper module The commit also re-work the build target so if the file are deleted, then they are created again. Using `file(COPY ...)` and `file(MAKE_DIRECTORY ...)` as done previously caused some file to be out of date or not being regenerated at all. This commit also fixes some broken target that depended on `file(` and `configure_file` CMake command not being part of any target. Fix #2342 --- awesomeConfig.cmake | 13 ++- docs/_parser.lua | 196 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 docs/_parser.lua diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake index ea1d6057e..c22698beb 100644 --- a/awesomeConfig.cmake +++ b/awesomeConfig.cmake @@ -354,13 +354,20 @@ add_custom_target(lgi-check-run ALL # {{{ Generate some aggregated documentation from lua script -file(MAKE_DIRECTORY ${BUILD_DIR}/script_files/) +add_custom_target(setup_directories DEPENDS lgi-check-run) + +add_custom_command(TARGET setup_directories + COMMAND ${CMAKE_COMMAND} -E make_directory ${BUILD_DIR}/script_files/ + COMMAND ${CMAKE_COMMAND} -E make_directory ${BUILD_DIR}/docs/common/ + COMMAND ${CMAKE_COMMAND} -E make_directory ${BUILD_DIR}/doc/images/ + COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_DIR}/docs/_parser.lua ${BUILD_DIR}/docs/ +) add_custom_command( OUTPUT ${BUILD_DIR}/docs/06-appearance.md COMMAND lua ${SOURCE_DIR}/docs/06-appearance.md.lua ${BUILD_DIR}/docs/06-appearance.md - DEPENDS lgi-check-run + DEPENDS lgi-check-run ${SOURCE_DIR}/docs/06-appearance.md.lua ) add_custom_command( @@ -370,6 +377,7 @@ add_custom_command( ${BUILD_DIR}/docs/05-awesomerc.md ${SOURCE_DIR}/awesomerc.lua ${BUILD_DIR}/awesomerc.lua ${BUILD_DIR}/script_files/rc.lua + DEPENDS ${SOURCE_DIR}/awesomerc.lua ${SOURCE_DIR}/docs/05-awesomerc.md.lua ) add_custom_command( @@ -379,6 +387,7 @@ add_custom_command( # Create a target for the auto-generated awesomerc.lua and other files add_custom_target(generate_awesomerc DEPENDS + setup_directories ${BUILD_DIR}/awesomerc.lua ${BUILD_DIR}/script_files/theme.lua ${BUILD_DIR}/script_files/rc.lua diff --git a/docs/_parser.lua b/docs/_parser.lua new file mode 100644 index 000000000..85abfc854 --- /dev/null +++ b/docs/_parser.lua @@ -0,0 +1,196 @@ +local gio = require("lgi").Gio +local gobject = require("lgi").GObject +local glib = require("lgi").GLib + +local name_attr = gio.FILE_ATTRIBUTE_STANDARD_NAME +local type_attr = gio.FILE_ATTRIBUTE_STANDARD_TYPE + +local module = {} + +-- Like pairs(), but iterate over keys in a sorted manner. Does not support +-- modifying the table while iterating. +local function sorted_pairs(t) + -- Collect all keys + local keys = {} + for k in pairs(t) do + table.insert(keys, k) + end + + table.sort(keys) + + -- return iterator function + local i = 0 + return function() + i = i + 1 + if keys[i] then + return keys[i], t[keys[i]] + end + end +end + +-- Recursive file scanner +local function get_all_files(path, ext, ret) + ret = ret or {} + local enumerator = gio.File.new_for_path(path):enumerate_children( + table.concat({name_attr, type_attr}, ",") , 0, nil, nil + ) + + for file in function() return enumerator:next_file() end do + local file_name = file:get_attribute_as_string(name_attr) + local file_type = file:get_file_type() + local match_ext = file_name:match("[.]"..ext.."$" or "") + local fpath = enumerator:get_child(file):get_path() + local is_test = fpath:match("/tests/") + if file_type == "REGULAR" and match_ext and not is_test then + table.insert(ret, fpath) + elseif file_type == "DIRECTORY" then + get_all_files(enumerator:get_child(file):get_path(), ext, ret) + end + end + + return ret +end + +local function path_to_module(path) + if path:match("[.]c$") then + return path:gmatch("/([^./]+)[.]c$")() + end + + for _, module in ipairs { + "awful", "wibox", "gears", "naughty", "menubar", "beautiful" + } do + local match = path:match("/"..module.."/([^.]+).lua") + if match then + return module.."."..match:gsub("/",".") + end + end + + error("Cannot figure out module for " .. tostring(path)) +end + +function module.path_to_html(path) + local mod = path_to_module(path):gsub(".init", "") + local f = assert(io.open(path)) + while true do + local line = f:read() + if not line then break end + if line:match("@classmod") then + f:close() + return "../classes/".. mod ..".html#" + end + if line:match("@module") or line:match("@submodule") then + f:close() + return "../libraries/".. mod ..".html#" + end + end + f:close() + + error("Cannot figure out if module or class: " .. tostring(path)) +end + +local function get_link(file, element) + return table.concat { + "", + element:match("[. ](.+)"), + "" + } +end + +local function parse_files(property_name, matcher) + local exp1 = "--[ ]*@".. property_name .." ([^ \n]*)" + local exp2 = matcher or "--[ ]*".. property_name ..".(.+)" + + local ret = {} + + local paths = get_all_files("./lib/", "lua") + assert(paths) + + for _, f in ipairs(get_all_files("./", "c")) do + table.insert(paths, f) + end + + table.sort(paths) + + -- Find all @beautiful doc entries + for _,file in ipairs(paths) do + local f = io.open(file) + + local buffer = "" + + for line in f:lines() do + + local var = line:gmatch(exp1)() + + -- There is no backward/forward pattern in lua + if #line <= 1 then + buffer = "" + elseif #buffer and not var then + buffer = buffer.."\n"..line + elseif line:sub(1,3) == "---" or line:sub(1,3) == "/**" then + buffer = line + end + + + if var then + -- Get the @param, @see and @usage + local params = "" + for line in f:lines() do + if line:sub(1,2) ~= "--" then + break + else + params = params.."\n"..line + end + end + + local name = var:gmatch(exp2)() + if not name then + print("WARNING:", var, + "seems to be misformatted. Use `beautiful.namespace_name`" + ) + else + table.insert(ret, { + file = file, + name = name:gsub("_", "\\_"), + link = get_link(file, var, var:match(exp3):gsub("_", "\\_")), + desc = buffer:gmatch("[-*/ \n]+([^\n.]*)")() or "", + mod = path_to_module(file), + }) + end + + buffer = "" + end + end + end + + return ret +end + +local function create_table(entries, columns) + local lines = {} + + for _, entry in ipairs(entries) do + local line = " " + + for _, column in ipairs(columns) do + line = line..""..entry[column].."" + end + + table.insert(lines, line.."\n") + end + + return [[

+ + + + ]] .. table.concat(lines) .. "
NameDescription
\n" +end + +module.create_table = create_table +module.parse_files = parse_files +module.sorted_pairs = sorted_pairs +module.get_all_files = get_all_files + +return module From b49f7e22dd2b34d2118b1f0e20271eb863352598 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 7 Oct 2018 01:29:41 -0400 Subject: [PATCH 4/9] doc: Add an index of valid properties to awful.spawn and awful.rules. --- awesomeConfig.cmake | 25 ++++- docs/06-appearance.md.lua | 173 ++--------------------------------- docs/_parser.lua | 37 ++++---- docs/build_rules_index.lua | 30 ++++++ docs/common/rules_index.ldoc | 72 +++++++++++++++ docs/load_ldoc.cmake | 26 +++--- lib/awful/rules.lua | 18 ++-- 7 files changed, 170 insertions(+), 211 deletions(-) create mode 100644 docs/build_rules_index.lua create mode 100644 docs/common/rules_index.ldoc diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake index c22698beb..1d4a4e5e0 100644 --- a/awesomeConfig.cmake +++ b/awesomeConfig.cmake @@ -367,7 +367,26 @@ add_custom_command( OUTPUT ${BUILD_DIR}/docs/06-appearance.md COMMAND lua ${SOURCE_DIR}/docs/06-appearance.md.lua ${BUILD_DIR}/docs/06-appearance.md - DEPENDS lgi-check-run ${SOURCE_DIR}/docs/06-appearance.md.lua + DEPENDS + lgi-check-run + ${SOURCE_DIR}/docs/06-appearance.md.lua + ${SOURCE_DIR}/docs/_parser.lua +) + +add_custom_command( + OUTPUT ${BUILD_DIR}/docs/common/rules_index.ldoc + COMMAND lua ${SOURCE_DIR}/docs/build_rules_index.lua + ${BUILD_DIR}/docs/common/rules_index.ldoc + + # Cheap trick until the ldoc `configure_file` is ported to be a build + # step rather than part of cmake. + COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/docs/common/rules_index.ldoc + ${SOURCE_DIR}/docs/common/rules_index.ldoc + + DEPENDS + lgi-check-run + ${SOURCE_DIR}/docs/build_rules_index.lua + ${SOURCE_DIR}/docs/_parser.lua ) add_custom_command( @@ -394,9 +413,13 @@ add_custom_target(generate_awesomerc DEPENDS ${SOURCE_DIR}/awesomerc.lua ${BUILD_DIR}/docs/06-appearance.md ${SOURCE_DIR}/docs/05-awesomerc.md.lua + ${SOURCE_DIR}/docs/build_rules_index.lua + ${BUILD_DIR}/docs/common/rules_index.ldoc ${SOURCE_DIR}/docs/sample_theme.lua ${SOURCE_DIR}/docs/sample_files.lua ${SOURCE_DIR}/awesomerc.lua + ${awesome_c_configure_files} + ${awesome_lua_configure_files} ) diff --git a/docs/06-appearance.md.lua b/docs/06-appearance.md.lua index 48fe4325e..cfb583b90 100644 --- a/docs/06-appearance.md.lua +++ b/docs/06-appearance.md.lua @@ -1,174 +1,14 @@ #! /usr/bin/lua local args = {...} +local parser = require("docs._parser") local gio = require("lgi").Gio local gobject = require("lgi").GObject local glib = require("lgi").GLib -local name_attr = gio.FILE_ATTRIBUTE_STANDARD_NAME -local type_attr = gio.FILE_ATTRIBUTE_STANDARD_TYPE +local paths = parser.get_all_files("./lib/", "lua", parser.get_all_files("./", "c")) --- Like pairs(), but iterate over keys in a sorted manner. Does not support --- modifying the table while iterating. -local function sorted_pairs(t) - -- Collect all keys - local keys = {} - for k in pairs(t) do - table.insert(keys, k) - end - - table.sort(keys) - - -- return iterator function - local i = 0 - return function() - i = i + 1 - if keys[i] then - return keys[i], t[keys[i]] - end - end -end - --- Recursive file scanner -local function get_all_files(path, ext, ret) - ret = ret or {} - local enumerator = gio.File.new_for_path(path):enumerate_children( - table.concat({name_attr, type_attr}, ",") , 0, nil, nil - ) - - for file in function() return enumerator:next_file() end do - local file_name = file:get_attribute_as_string(name_attr) - local file_type = file:get_file_type() - if file_type == "REGULAR" and file_name:match(ext or "") then - table.insert(ret, enumerator:get_child(file):get_path()) - elseif file_type == "DIRECTORY" then - get_all_files(enumerator:get_child(file):get_path(), ext, ret) - end - end - - return ret -end - -local function path_to_module(path) - for _, module in ipairs { - "awful", "wibox", "gears", "naughty", "menubar", "beautiful" - } do - local match = path:match("/"..module.."/([^.]+).lua") - if match then - return module.."."..match:gsub("/",".") - end - end - - error("Cannot figure out module for " .. tostring(path)) -end - -local function path_to_html(path) - local mod = path_to_module(path):gsub(".init", "") - local f = assert(io.open(path)) - while true do - local line = f:read() - if not line then break end - if line:match("@classmod") then - f:close() - return "../classes/".. mod ..".html" - end - if line:match("@module") or line:match("@submodule") then - f:close() - return "../libraries/".. mod ..".html" - end - end - f:close() - - error("Cannot figure out if module or class: " .. tostring(path)) -end - -local function get_link(file, element) - return table.concat { - "", - element:match("[. ](.+)"), - "" - } -end - -local all_files = get_all_files("./lib/", "lua") -table.sort(all_files) - -local beautiful_vars = {} - --- Find all @beautiful doc entries -for _,file in ipairs(all_files) do - local f = io.open(file) - - local buffer = "" - - for line in f:lines() do - - local var = line:gmatch("--[ ]*@beautiful ([^ \n]*)")() - - -- There is no backward/forward pattern in lua - if #line <= 1 then - buffer = "" - elseif #buffer and not var then - buffer = buffer.."\n"..line - elseif line:sub(1,3) == "---" then - buffer = line - end - - - if var then - -- Get the @param, @see and @usage - local params = "" - for line in f:lines() do - if line:sub(1,2) ~= "--" then - break - else - params = params.."\n"..line - end - end - - local name = var:gmatch("[ ]*beautiful.(.+)")() - if not name then - print("WARNING:", var, - "seems to be misformatted. Use `beautiful.namespace_name`" - ) - else - table.insert(beautiful_vars, { - file = file, - name = name, - link = get_link(file, var), - desc = buffer:gmatch("[- ]+([^\n.]*)")() or "", - mod = path_to_module(file), - }) - end - - buffer = "" - end - end -end - -local function create_table(entries, columns) - local lines = {} - - for _, entry in ipairs(entries) do - local line = " " - - for _, column in ipairs(columns) do - line = line..""..entry[column].."" - end - - table.insert(lines, line.."\n") - end - - return [[

- - - - ]] .. table.concat(lines) .. "
NameDescription
\n" -end +local beautiful_vars = parser.parse_files(paths, "beautiful") local override_cats = { ["border" ] = true, @@ -200,7 +40,7 @@ local function create_sample(entries) " local theme = {}" } - for name, cat in sorted_pairs(categorize(entries)) do + for name, cat in parser.sorted_pairs(categorize(entries)) do table.insert(ret, "\n -- "..name) for _, v in ipairs(cat) do table.insert(ret, " -- theme."..v.name.." = nil") @@ -217,6 +57,7 @@ local function create_sample(entries) return table.concat(ret, '\n') end + -- Create the file local filename = args[1] @@ -229,8 +70,9 @@ f:write[[ Beautiful is where Awesome theme variables are stored. +

]] -f:write(create_table(beautiful_vars, {"link", "desc"})) +f:write(parser.create_table(beautiful_vars, {"link", "desc"})) f:write("\n\n## Sample theme file\n\n") @@ -241,6 +83,5 @@ f:close() --TODO add some linting to direct undeclared beautiful variables --TODO re-generate all official themes --TODO generate a complete sample theme ---TODO also parse C files. -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/docs/_parser.lua b/docs/_parser.lua index 85abfc854..a75d8daf5 100644 --- a/docs/_parser.lua +++ b/docs/_parser.lua @@ -88,30 +88,24 @@ function module.path_to_html(path) error("Cannot figure out if module or class: " .. tostring(path)) end -local function get_link(file, element) +local function get_link(file, element, element_name) return table.concat { "", - element:match("[. ](.+)"), + element_name, "" } end -local function parse_files(property_name, matcher) - local exp1 = "--[ ]*@".. property_name .." ([^ \n]*)" - local exp2 = matcher or "--[ ]*".. property_name ..".(.+)" +local function parse_files(paths, property_name, matcher, name_matcher) + local exp1 = "[-*]*[ ]*@".. property_name .." ([^ \n]*)" + local exp2 = matcher or "[-*]*[ ]*".. property_name ..".(.+)" + local exp3 = name_matcher or "[. ](.+)" local ret = {} - local paths = get_all_files("./lib/", "lua") - assert(paths) - - for _, f in ipairs(get_all_files("./", "c")) do - table.insert(paths, f) - end - table.sort(paths) -- Find all @beautiful doc entries @@ -133,12 +127,11 @@ local function parse_files(property_name, matcher) buffer = line end - if var then -- Get the @param, @see and @usage local params = "" for line in f:lines() do - if line:sub(1,2) ~= "--" then + if line:sub(1,2) ~= "--" and line:sub(1,2) ~= " *" then break else params = params.."\n"..line @@ -168,7 +161,8 @@ local function parse_files(property_name, matcher) return ret end -local function create_table(entries, columns) +local function create_table(entries, columns, prefix) + prefix = prefix or "" local lines = {} for _, entry in ipairs(entries) do @@ -178,14 +172,15 @@ local function create_table(entries, columns) line = line..""..entry[column].."" end - table.insert(lines, line.."\n") + table.insert(lines, prefix..line.."\n") end - return [[

- - - - ]] .. table.concat(lines) .. "
NameDescription
\n" + return [[-- +]]..prefix..[[ +]]..prefix..[[ +]]..prefix..[[ +]]..prefix..[[ +]] .. table.concat(lines) .. prefix .."
NameDescription
\n" end module.create_table = create_table diff --git a/docs/build_rules_index.lua b/docs/build_rules_index.lua new file mode 100644 index 000000000..1e9341c4e --- /dev/null +++ b/docs/build_rules_index.lua @@ -0,0 +1,30 @@ +#! /usr/bin/lua +local args = {...} +local parser = require("docs._parser") + +local files = {"./objects/client.c", "./lib/awful/client.lua"} +local matcher, matcher2 = "(.*)", ".*" + +-- The client function comes from 5 different files, but all of those are +-- merged into one documentation page (aka, awful.client doesn't have content +-- anymore). This override the path so the parser doesn't have to be aware of it +function parser.path_to_html() + return "../classes/client.html#client." +end + +local clientruleproperty = parser.parse_files(files, "clientruleproperty", matcher, matcher2) + +for _, prop in ipairs(parser.parse_files(files, "property", matcher, matcher2)) do + table.insert(clientruleproperty, prop) +end + +-- Create the file +local filename = args[1] + +local f = io.open(filename, "w") + +f:write(parser.create_table(clientruleproperty, {"link", "desc"}, "-- ")) + +f:close() + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/docs/common/rules_index.ldoc b/docs/common/rules_index.ldoc new file mode 100644 index 000000000..b4fc76c44 --- /dev/null +++ b/docs/common/rules_index.ldoc @@ -0,0 +1,72 @@ +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +--
NameDescription
placementThe client default placement on the screen
honor\_paddingWhen applying the placement, honor the screen padding
honor\_workareaWhen applying the placement, honor the screen work area
tagThe client default tag
tagsThe client default tags
new\_tagCreate a new tag for this client
switch\_to\_tagsUnselect the current tags and select this client tags
focusDefine if the client should grab focus by default
titlebars\_enabledShould this client have a titlebar by default
callbackA function to call when this client is ready
markedIf a client is marked or not
is\_fixedReturn if a client has a fixed size or not
immobilizedIs the client immobilized horizontally?
immobilizedIs the client immobilized vertically?
floatingThe client floating state
xThe x coordinates
yThe y coordinates
widthThe width of the client
heightThe height of the client
dockableIf the client is dockable
requests\_no\_titlebarIf the client requests not to be decorated with a titlebar
shapeSet the client shape
windowThe X window id
nameThe client title
skip\_taskbarTrue if the client does not want to be in taskbar
typeThe window type
classThe client class
instanceThe client instance
pidThe client PID, if available
roleThe window role, if available
machineThe machine client is running on
icon\_nameThe client name when iconified
iconThe client icon as a surface
icon\_sizesThe available sizes of client icons
screenClient screen
hiddenDefine if the client must be hidden, i
minimizedDefine it the client must be iconify, i
size\_hints\_honorHonor size hints, e
border\_widthThe client border width
border\_colorThe client border color
urgentThe client urgent state
contentA cairo surface for the client window content
opacityThe client opacity
ontopThe client is on top of every other windows
aboveThe client is above normal windows
belowThe client is below normal windows
fullscreenThe client is fullscreen or not
maximizedThe client is maximized (horizontally and vertically) or not
maximized\_horizontalThe client is maximized horizontally or not
maximized\_verticalThe client is maximized vertically or not
transient\_forThe client the window is transient for
group\_windowWindow identification unique to a group of windows
leader\_windowIdentification unique to windows spawned by the same command
size\_hintsA table with size hints of the client
motif\_wm\_hintsThe motif WM hints of the client
stickySet the client sticky, i
modalIndicate if the client is modal
focusableTrue if the client can receive the input focus
shape\_boundingThe client's bounding shape as set by awesome as a (native) cairo surface
shape\_clipThe client's clip shape as set by awesome as a (native) cairo surface
shape\_inputThe client's input shape as set by awesome as a (native) cairo surface
client\_shape\_boundingThe client's bounding shape as set by the program as a (native) cairo surface
client\_shape\_clipThe client's clip shape as set by the program as a (native) cairo surface
startup\_idThe FreeDesktop StartId
validIf the client that this object refers to is still managed by awesome
first\_tagThe first tag of the client
diff --git a/docs/load_ldoc.cmake b/docs/load_ldoc.cmake index a783e7db4..161d49e02 100644 --- a/docs/load_ldoc.cmake +++ b/docs/load_ldoc.cmake @@ -1,23 +1,23 @@ # To avoid copy pasting, some documentation is stored in reusable files set(SHAPE_FILE "${SOURCE_DIR}/docs/common/${SHAPE_NAME}.lua") -set(path "${SOURCE_DIR}/docs/common/") +foreach(path ${BUILD_DIR}/docs/common/;${SOURCE_DIR}/docs/common/) + # Get the documentation file list + file(GLOB doc_files RELATIVE "${path}" "${path}/*.ldoc") -# Get the documentation file list -file(GLOB doc_files RELATIVE "${path}" "${path}/*.ldoc") + foreach(doc_file_name ${doc_files}) + # Read the file + file(READ "${path}/${doc_file_name}" doc_file_content) -foreach(doc_file_name ${doc_files}) - # Read the file - file(READ "${path}/${doc_file_name}" doc_file_content) + # Remove the file extension + string(REGEX REPLACE "\\.ldoc" "" DOC_FILE_NAME ${doc_file_name}) - # Remove the file extension - string(REGEX REPLACE "\\.ldoc" "" DOC_FILE_NAME ${doc_file_name}) + # There is a trailing \n, remove it or it cannot be included in existing blocks + string(REGEX REPLACE "\n$" "" doc_file_content "${doc_file_content}") - # There is a trailing \n, remove it or it cannot be included in existing blocks - string(REGEX REPLACE "\n$" "" doc_file_content "${doc_file_content}") - - # Create a new variable usable from lua files - set(DOC_${DOC_FILE_NAME}_COMMON "${doc_file_content}") + # Create a new variable usable from lua files + set(DOC_${DOC_FILE_NAME}_COMMON "${doc_file_content}") + endforeach() endforeach() # vim: filetype=cmake:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80:foldmethod=marker diff --git a/lib/awful/rules.lua b/lib/awful/rules.lua index f16741879..6b5684201 100644 --- a/lib/awful/rules.lua +++ b/lib/awful/rules.lua @@ -8,17 +8,15 @@ -- to add random properties that will be later accessible as `c.property_name` -- (where `c` is a valid client object) -- --- In addition to the existing properties, the following are supported: +-- Applicable client properties +-- === -- --- * placement --- * honor_padding --- * honor_workarea --- * tag --- * new_tag --- * switch_to_tags (also called switchtotag) --- * focus --- * titlebars_enabled --- * callback +-- The table below holds the list of default client properties along with +-- some extra properties that are specific to the rules. Note that any property +-- can be set in the rules and interpreted by user provided code. This table +-- only represent those offered by default. +-- +--@DOC_rules_index_COMMON@ -- -- @author Julien Danjou <julien@danjou.info> -- @copyright 2009 Julien Danjou From b4e0363ac387b125e000172241ffe0a415b7618b Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 7 Oct 2018 01:37:35 -0400 Subject: [PATCH 5/9] doc: Move the awful.rules to the header. It's easier to find. --- lib/awful/rules.lua | 168 ++++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/lib/awful/rules.lua b/lib/awful/rules.lua index 6b5684201..1d26abb4c 100644 --- a/lib/awful/rules.lua +++ b/lib/awful/rules.lua @@ -8,6 +8,89 @@ -- to add random properties that will be later accessible as `c.property_name` -- (where `c` is a valid client object) -- +-- Syntax +-- === +-- You should fill this table with your rule and properties to apply. +-- For example, if you want to set xterm maximized at startup, you can add: +-- +-- { rule = { class = "xterm" }, +-- properties = { maximized_vertical = true, maximized_horizontal = true } } +-- +-- If you want to set mplayer floating at startup, you can add: +-- +-- { rule = { name = "MPlayer" }, +-- properties = { floating = true } } +-- +-- If you want to put Firefox on a specific tag at startup, you can add: +-- +-- { rule = { instance = "firefox" }, +-- properties = { tag = mytagobject } } +-- +-- Alternatively, you can specify the tag by name: +-- +-- { rule = { instance = "firefox" }, +-- properties = { tag = "3" } } +-- +-- If you want to put Thunderbird on a specific screen at startup, use: +-- +-- { rule = { instance = "Thunderbird" }, +-- properties = { screen = 1 } } +-- +-- Assuming that your X11 server supports the RandR extension, you can also specify +-- the screen by name: +-- +-- { rule = { instance = "Thunderbird" }, +-- properties = { screen = "VGA1" } } +-- +-- If you want to put Emacs on a specific tag at startup, and immediately switch +-- to that tag you can add: +-- +-- { rule = { class = "Emacs" }, +-- properties = { tag = mytagobject, switchtotag = true } } +-- +-- If you want to apply a custom callback to execute when a rule matched, +-- for example to pause playing music from mpd when you start dosbox, you +-- can add: +-- +-- { rule = { class = "dosbox" }, +-- callback = function(c) +-- awful.spawn('mpc pause') +-- end } +-- +-- Note that all "rule" entries need to match. If any of the entry does not +-- match, the rule won't be applied. +-- +-- If a client matches multiple rules, they are applied in the order they are +-- put in this global rules table. If the value of a rule is a string, then the +-- match function is used to determine if the client matches the rule. +-- +-- If the value of a property is a function, that function gets called and +-- function's return value is used for the property. +-- +-- To match multiple clients to a rule one need to use slightly different +-- syntax: +-- +-- { rule_any = { class = { "MPlayer", "Nitrogen" }, instance = { "xterm" } }, +-- properties = { floating = true } } +-- +-- To match multiple clients with an exception one can couple `rules.except` or +-- `rules.except_any` with the rules: +-- +-- { rule = { class = "Firefox" }, +-- except = { instance = "Navigator" }, +-- properties = {floating = true}, +-- }, +-- +-- { rule_any = { class = { "Pidgin", "Xchat" } }, +-- except_any = { role = { "conversation" } }, +-- properties = { tag = "1" } +-- } +-- +-- { rule = {}, +-- except_any = { class = { "Firefox", "Vim" } }, +-- properties = { floating = true } +-- } +-- -- Applicable client properties -- === -- @@ -42,90 +125,7 @@ local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility local rules = {} ---[[-- -This is the global rules table. - -You should fill this table with your rule and properties to apply. -For example, if you want to set xterm maximized at startup, you can add: - - { rule = { class = "xterm" }, - properties = { maximized_vertical = true, maximized_horizontal = true } } - -If you want to set mplayer floating at startup, you can add: - - { rule = { name = "MPlayer" }, - properties = { floating = true } } - -If you want to put Firefox on a specific tag at startup, you can add: - - { rule = { instance = "firefox" }, - properties = { tag = mytagobject } } - -Alternatively, you can specify the tag by name: - - { rule = { instance = "firefox" }, - properties = { tag = "3" } } - -If you want to put Thunderbird on a specific screen at startup, use: - - { rule = { instance = "Thunderbird" }, - properties = { screen = 1 } } - -Assuming that your X11 server supports the RandR extension, you can also specify -the screen by name: - - { rule = { instance = "Thunderbird" }, - properties = { screen = "VGA1" } } - -If you want to put Emacs on a specific tag at startup, and immediately switch -to that tag you can add: - - { rule = { class = "Emacs" }, - properties = { tag = mytagobject, switch_to_tags = true } } - -If you want to apply a custom callback to execute when a rule matched, -for example to pause playing music from mpd when you start dosbox, you -can add: - - { rule = { class = "dosbox" }, - callback = function(c) - awful.spawn('mpc pause') - end } - -Note that all "rule" entries need to match. If any of the entry does not -match, the rule won't be applied. - -If a client matches multiple rules, they are applied in the order they are -put in this global rules table. If the value of a rule is a string, then the -match function is used to determine if the client matches the rule. - -If the value of a property is a function, that function gets called and -function's return value is used for the property. - -To match multiple clients to a rule one need to use slightly different -syntax: - - { rule_any = { class = { "MPlayer", "Nitrogen" }, instance = { "xterm" } }, - properties = { floating = true } } - -To match multiple clients with an exception one can couple `rules.except` or -`rules.except_any` with the rules: - - { rule = { class = "Firefox" }, - except = { instance = "Navigator" }, - properties = {floating = true}, - }, - - { rule_any = { class = { "Pidgin", "Xchat" } }, - except_any = { role = { "conversation" } }, - properties = { tag = "1" } - } - - { rule = {}, - except_any = { class = { "Firefox", "Vim" } }, - properties = { floating = true } - } -]]-- +--- This is the global rules table. rules.rules = {} --- Check if a client matches a rule. From 845b9a930ce8b8eb9c2108589e5c25cb52b67758 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 12 Oct 2018 14:10:02 -0400 Subject: [PATCH 6/9] doc: Refactor awful.spawn doc to have a property list. --- lib/awful/spawn.lua | 89 +++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 39 deletions(-) diff --git a/lib/awful/spawn.lua b/lib/awful/spawn.lua index 402dad5cc..7cef92f9f 100644 --- a/lib/awful/spawn.lua +++ b/lib/awful/spawn.lua @@ -8,6 +8,9 @@ -- program after it has been launched. This requires currently that the -- applicaton supports them. -- +-- Frequently asked questions +-- === +-- -- **Rules of thumb when a shell is needed**: -- -- * A shell is required when the commands contain `&&`, `;`, `||`, `&` or @@ -45,45 +48,6 @@ -- *instance*, a *role*, and a *type*. See `client.class`, `client.instance`, -- `client.role` and `client.type` for more information about these properties. -- --- **The startup notification protocol**: --- --- The startup notification protocol is an optional specification implemented --- by X11 applications to bridge the chain of knowledge between the moment a --- program is launched to the moment its window (client) is shown. It can be --- found [on the FreeDesktop.org website](https://www.freedesktop.org/wiki/Specifications/startup-notification-spec/). --- --- Awesome has support for the various events that are part of the protocol, but --- the most useful is the identifier, usually identified by its `SNID` acronym in --- the documentation. It isn't usually necessary to even know it exists, as it --- is all done automatically. However, if more control is required, the --- identifier can be specified by an environment variable called --- `DESKTOP_STARTUP_ID`. For example, let us consider execution of the following --- command: --- --- DESKTOP_STARTUP_ID="something_TIME$(date '+%s')" my_command --- --- This should (if the program correctly implements the protocol) result in --- `c.startup_id` to at least match `something`. --- This identifier can then be used in `awful.rules` to configure the client. --- --- Awesome can automatically set the `DESKTOP_STARTUP_ID` variable. This is used --- by `awful.spawn` to specify additional rules for the startup. For example: --- --- awful.spawn("urxvt -e maxima -name CALCULATOR", { --- floating = true, --- tag = mouse.screen.selected_tag, --- placement = awful.placement.bottom_right, --- }) --- --- This can also be used from the command line: --- --- awesome-client 'awful=require("awful"); --- awful.spawn("urxvt -e maxima -name CALCULATOR", { --- floating = true, --- tag = mouse.screen.selected_tag, --- placement = awful.placement.bottom_right, --- })' --- -- **Getting a command's output**: -- -- First, do **not** use `io.popen` **ever**. It is synchronous. Synchronous @@ -148,6 +112,53 @@ -- [Desktop Entry](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html) -- specification. -- +-- Spawning applications with specific properties +-- === +-- +-- **The startup notification protocol**: +-- +-- The startup notification protocol is an optional specification implemented +-- by X11 applications to bridge the chain of knowledge between the moment a +-- program is launched to the moment its window (client) is shown. It can be +-- found [on the FreeDesktop.org website](https://www.freedesktop.org/wiki/Specifications/startup-notification-spec/). +-- +-- Awesome has support for the various events that are part of the protocol, but +-- the most useful is the identifier, usually identified by its `SNID` acronym in +-- the documentation. It isn't usually necessary to even know it exists, as it +-- is all done automatically. However, if more control is required, the +-- identifier can be specified by an environment variable called +-- `DESKTOP_STARTUP_ID`. For example, let us consider execution of the following +-- command: +-- +-- DESKTOP_STARTUP_ID="something_TIME$(date '+%s')" my_command +-- +-- This should (if the program correctly implements the protocol) result in +-- `c.startup_id` to at least match `something`. +-- This identifier can then be used in `awful.rules` to configure the client. +-- +-- Awesome can automatically set the `DESKTOP_STARTUP_ID` variable. This is used +-- by `awful.spawn` to specify additional rules for the startup. For example: +-- +-- awful.spawn("urxvt -e maxima -name CALCULATOR", { +-- floating = true, +-- tag = mouse.screen.selected_tag, +-- placement = awful.placement.bottom_right, +-- }) +-- +-- This can also be used from the command line: +-- +-- awesome-client 'awful=require("awful"); +-- awful.spawn("urxvt -e maxima -name CALCULATOR", { +-- floating = true, +-- tag = mouse.screen.selected_tag, +-- placement = awful.placement.bottom_right, +-- })' +-- +-- This table contains the client properties that are valid when used the +-- `sn_rules` or `prop` function argument. They are the same as in `awful.rules`. +-- +--@DOC_rules_index_COMMON@ +-- -- @author Julien Danjou <julien@danjou.info> -- @author Emmanuel Lepage Vallee <elv1313@gmail.com> -- @copyright 2008 Julien Danjou From cd6979618ff1b1380c40400c5952cfd84ee56ac2 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 10 Oct 2018 00:18:45 -0400 Subject: [PATCH 7/9] doc: Update the CSS to support our custom table class Other change: * Use GitHub style border * Add support for HTML tags --- docs/_parser.lua | 2 +- docs/common/rules_index.ldoc | 2 +- docs/ldoc.css | 67 +++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/docs/_parser.lua b/docs/_parser.lua index a75d8daf5..323f86770 100644 --- a/docs/_parser.lua +++ b/docs/_parser.lua @@ -176,7 +176,7 @@ local function create_table(entries, columns, prefix) end return [[-- -]]..prefix..[[ +]]..prefix..[[ ]]..prefix..[[ ]]..prefix..[[ ]]..prefix..[[ diff --git a/docs/common/rules_index.ldoc b/docs/common/rules_index.ldoc index b4fc76c44..ac75c08ca 100644 --- a/docs/common/rules_index.ldoc +++ b/docs/common/rules_index.ldoc @@ -1,5 +1,5 @@ --
NameDescription
--- +-- -- -- -- diff --git a/docs/ldoc.css b/docs/ldoc.css index 6cea44f1e..db6cb177f 100644 --- a/docs/ldoc.css +++ b/docs/ldoc.css @@ -22,7 +22,7 @@ hr { margin: 15px 0; } -code, tt { +tt { font-family: monospace; } span.parameter { @@ -47,6 +47,19 @@ p.name { font-family: monospace; } +kbd, p code, ol code { + background-color: #eaedf587; + padding-left: 3px; + padding-right: 3px; + border-radius: 3px; + border-style: solid; + border-width: 1px; + border-color: #b7bac1; + font-family: monospace; + margin-left: 5px; + margin-right: 5px; +} + #navigation { float: left; background-color: white; @@ -191,6 +204,58 @@ table th, table td { padding: 2px; } +.widget_list td { + padding-top: 10px; + padding-bottom: 10px; +} + +.widget_list tr td:first-child { + padding-left: 5px; +} + +.widget_list tr td:last-child { + padding-right: 10px; +} + +.widget_list { + border-collapse: unset; + overflow: hidden; + border-style: solid; + border-width: 0.5px; + border-top-left-radius: 7px; + border-top-right-radius: 7px; +} + +.widget_list th { + background-color: #2c3e67; + font-weight: bold; + color: white; + padding-top: 10px; + padding-bottom: 10px; +} + +.widget_list th:first-child { + border-top-left-radius: 7px; + border-bottom-width: 1px; + padding-left: 20px; + padding-right: 20px; +} + +.widget_list th:last-child { + border-top-right-radius: 7px; + border-width: 0px; + border-bottom-width: 1px; + padding-left: 20px; + padding-right: 20px; +} + +.widget_list td { + border-style: solid; + border-width: 0px; + border-right-width: 1px;; + border-bottom-width: 1px; +} + #about { padding: 15px; padding-left: 16em; From 43a82f34f08d02eb84860fef46b7b2afc72b626a Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 10 Oct 2018 00:50:22 -0400 Subject: [PATCH 8/9] doc: Add more examples about the spawn.easy_async Ref #1373 Ref https://stackoverflow.com/questions/52634985/awesome-wm-os-execute-vs-afwul-spawn --- lib/awful/spawn.lua | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/lib/awful/spawn.lua b/lib/awful/spawn.lua index 7cef92f9f..6eaff0c07 100644 --- a/lib/awful/spawn.lua +++ b/lib/awful/spawn.lua @@ -48,6 +48,57 @@ -- *instance*, a *role*, and a *type*. See `client.class`, `client.instance`, -- `client.role` and `client.type` for more information about these properties. -- +-- **Understanding blocking versus asynchronous execution**: +-- +-- Awesome is single threaded, it means only one thing is executed at any time. +-- But Awesome isn't doomed to be slow. It may not have multiple threads, but +-- it has something called coroutine and also has callbacks. This means things +-- that take time to execute can still do so in the background (using C threads +-- or external process + sockets). When they are done, they can notify the +-- Awesome thread. This works perfectly and avoid blocking Awesome. +-- +-- If you want to update the text of a `wibox.widget.textbox` with the output +-- of a shell command, you should use the `awful.spawn.easy_async_with_shell` +-- command. It is strongly recommanded not to use `io.popen` is explained in the +-- "Getting a command's output" section. Asynchronous execution is at first a +-- bit tricky to understand if you never used that before. The example below +-- should demonstrate how it works. +-- +-- If we do (but *really*, don't do that): +-- +-- -- **NEVER, EVER, DO THIS**: your computer will freeze +-- os.execute("sleep 1; echo foo > /tmp/foo.txt") +-- mylabel.text = io.popen("cat /tmp/foo.txt"):read("*all") +-- +-- The label will display `foo`. But If we do: +-- +-- -- Don't do this, it wont work. +-- -- Assumes /tmp/foo.txt does not exist +-- awful.spawn.with_shell("sleep 1; echo foo > /tmp/foo.txt") +-- mylabel.text = io.popen("cat /tmp/foo.txt"):read("*all") +-- +-- Then the label will be **empty**. `awful.spawn` and `awful.spawn.with_shell` +-- will **not** block and thus the `io.popen` will be executed before +-- `sleep 1` finishes. This is why we have async functions to execute shell +-- commands. There are many variants with difference characteristics and +-- complexity. `awful.spawn.easy_async` is the most common as it is good enough +-- for the general "I want to execute a command and do something with the +-- output when it finishes". +-- +-- -- This is the correct way +-- local command = "sleep 1; echo foo > /tmp/foo.txt" +-- +-- awful.spawn.easy_async_with_shell(command, function() +-- awful.spawn.easy_async_with_shell("cat /tmp/foo.txt", function(out) +-- mylabel.text = out +-- end) +-- end) +-- +-- In this variant, Awesome will not block. Again, like other spawn, you +-- cannot add code outside of the callback function to use the result of the +-- command. The code will be executed before the command is finished so the +-- result wont yet be available. +-- -- **Getting a command's output**: -- -- First, do **not** use `io.popen` **ever**. It is synchronous. Synchronous From bb357dd33e75bcb97002665aabfa93b824fae62d Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 10 Oct 2018 00:53:14 -0400 Subject: [PATCH 9/9] doc: Restore the example width limit to fit in 1024x768. The old stylesheet did this and it forced the examples to be smaller. This commit restore this limit. --- docs/ldoc.css | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ldoc.css b/docs/ldoc.css index db6cb177f..a761088f6 100644 --- a/docs/ldoc.css +++ b/docs/ldoc.css @@ -149,6 +149,7 @@ pre { padding: 15px; overflow: auto; font-family: monospace; + max-width: 720px; } #content ul pre.example {
NameDescription