Merge pull request #2423 from Elv13/better_rules_doc

Better awful.rules doc
This commit is contained in:
Emmanuel Lepage Vallée 2018-10-16 08:44:58 -04:00 committed by GitHub
commit aa16d77d15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 720 additions and 314 deletions

View File

@ -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)")

View File

@ -354,13 +354,39 @@ 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
${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(
@ -370,6 +396,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,15 +406,20 @@ 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
${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}
)

View File

@ -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 {
"<a href='",
path_to_html(file),
"#",
element,
"'>",
element:match("[. ](.+)"),
"</a>"
}
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 = " <tr>"
for _, column in ipairs(columns) do
line = line.."<td>"..entry[column].."</td>"
end
table.insert(lines, line.."</tr>\n")
end
return [[<br \><br \><table class='widget_list' border=1>
<tr style='font-weight: bold;'>
<th align='center'>Name</th>
<th align='center'>Description</th>
</tr>]] .. table.concat(lines) .. "</table>\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.
<br /><br />
]]
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

191
docs/_parser.lua Normal file
View File

@ -0,0 +1,191 @@
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, element_name)
return table.concat {
"<a href='",
module.path_to_html(file),
element,
"'>",
element_name,
"</a>"
}
end
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 = {}
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) ~= "--" and 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, prefix)
prefix = prefix or ""
local lines = {}
for _, entry in ipairs(entries) do
local line = " <tr>"
for _, column in ipairs(columns) do
line = line.."<td>"..entry[column].."</td>"
end
table.insert(lines, prefix..line.."</tr>\n")
end
return [[--<table class='widget_list' border=1>
]]..prefix..[[<tr>
]]..prefix..[[ <th align='center'>Name</th>
]]..prefix..[[ <th align='center'>Description</th>
]]..prefix..[[</tr>
]] .. table.concat(lines) .. prefix .."</table>\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

View File

@ -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

View File

@ -0,0 +1,72 @@
--<table class='widget_list' border=1>
-- <tr>
-- <th align='center'>Name</th>
-- <th align='center'>Description</th>
-- </tr>
-- <tr><td><a href='../classes/client.html#client.placement'>placement</a></td><td>The client default placement on the screen</td></tr>
-- <tr><td><a href='../classes/client.html#client.honor_padding'>honor\_padding</a></td><td>When applying the placement, honor the screen padding</td></tr>
-- <tr><td><a href='../classes/client.html#client.honor_workarea'>honor\_workarea</a></td><td>When applying the placement, honor the screen work area</td></tr>
-- <tr><td><a href='../classes/client.html#client.tag'>tag</a></td><td>The client default tag</td></tr>
-- <tr><td><a href='../classes/client.html#client.tags'>tags</a></td><td>The client default tags</td></tr>
-- <tr><td><a href='../classes/client.html#client.new_tag'>new\_tag</a></td><td>Create a new tag for this client</td></tr>
-- <tr><td><a href='../classes/client.html#client.switch_to_tags'>switch\_to\_tags</a></td><td>Unselect the current tags and select this client tags</td></tr>
-- <tr><td><a href='../classes/client.html#client.focus'>focus</a></td><td>Define if the client should grab focus by default</td></tr>
-- <tr><td><a href='../classes/client.html#client.titlebars_enabled'>titlebars\_enabled</a></td><td>Should this client have a titlebar by default</td></tr>
-- <tr><td><a href='../classes/client.html#client.callback'>callback</a></td><td>A function to call when this client is ready</td></tr>
-- <tr><td><a href='../classes/client.html#client.marked'>marked</a></td><td>If a client is marked or not</td></tr>
-- <tr><td><a href='../classes/client.html#client.is_fixed'>is\_fixed</a></td><td>Return if a client has a fixed size or not</td></tr>
-- <tr><td><a href='../classes/client.html#client.immobilized'>immobilized</a></td><td>Is the client immobilized horizontally?</td></tr>
-- <tr><td><a href='../classes/client.html#client.immobilized'>immobilized</a></td><td>Is the client immobilized vertically?</td></tr>
-- <tr><td><a href='../classes/client.html#client.floating'>floating</a></td><td>The client floating state</td></tr>
-- <tr><td><a href='../classes/client.html#client.x'>x</a></td><td>The x coordinates</td></tr>
-- <tr><td><a href='../classes/client.html#client.y'>y</a></td><td>The y coordinates</td></tr>
-- <tr><td><a href='../classes/client.html#client.width'>width</a></td><td>The width of the client</td></tr>
-- <tr><td><a href='../classes/client.html#client.height'>height</a></td><td>The height of the client</td></tr>
-- <tr><td><a href='../classes/client.html#client.dockable'>dockable</a></td><td>If the client is dockable</td></tr>
-- <tr><td><a href='../classes/client.html#client.requests_no_titlebar'>requests\_no\_titlebar</a></td><td>If the client requests not to be decorated with a titlebar</td></tr>
-- <tr><td><a href='../classes/client.html#client.shape'>shape</a></td><td>Set the client shape</td></tr>
-- <tr><td><a href='../classes/client.html#client.window'>window</a></td><td>The X window id</td></tr>
-- <tr><td><a href='../classes/client.html#client.name'>name</a></td><td>The client title</td></tr>
-- <tr><td><a href='../classes/client.html#client.skip_taskbar'>skip\_taskbar</a></td><td>True if the client does not want to be in taskbar</td></tr>
-- <tr><td><a href='../classes/client.html#client.type'>type</a></td><td>The window type</td></tr>
-- <tr><td><a href='../classes/client.html#client.class'>class</a></td><td>The client class</td></tr>
-- <tr><td><a href='../classes/client.html#client.instance'>instance</a></td><td>The client instance</td></tr>
-- <tr><td><a href='../classes/client.html#client.pid'>pid</a></td><td>The client PID, if available</td></tr>
-- <tr><td><a href='../classes/client.html#client.role'>role</a></td><td>The window role, if available</td></tr>
-- <tr><td><a href='../classes/client.html#client.machine'>machine</a></td><td>The machine client is running on</td></tr>
-- <tr><td><a href='../classes/client.html#client.icon_name'>icon\_name</a></td><td>The client name when iconified</td></tr>
-- <tr><td><a href='../classes/client.html#client.icon'>icon</a></td><td>The client icon as a surface</td></tr>
-- <tr><td><a href='../classes/client.html#client.icon_sizes'>icon\_sizes</a></td><td>The available sizes of client icons</td></tr>
-- <tr><td><a href='../classes/client.html#client.screen'>screen</a></td><td>Client screen</td></tr>
-- <tr><td><a href='../classes/client.html#client.hidden'>hidden</a></td><td>Define if the client must be hidden, i</td></tr>
-- <tr><td><a href='../classes/client.html#client.minimized'>minimized</a></td><td>Define it the client must be iconify, i</td></tr>
-- <tr><td><a href='../classes/client.html#client.size_hints_honor'>size\_hints\_honor</a></td><td>Honor size hints, e</td></tr>
-- <tr><td><a href='../classes/client.html#client.border_width'>border\_width</a></td><td>The client border width</td></tr>
-- <tr><td><a href='../classes/client.html#client.border_color'>border\_color</a></td><td>The client border color</td></tr>
-- <tr><td><a href='../classes/client.html#client.urgent'>urgent</a></td><td>The client urgent state</td></tr>
-- <tr><td><a href='../classes/client.html#client.content'>content</a></td><td>A cairo surface for the client window content</td></tr>
-- <tr><td><a href='../classes/client.html#client.opacity'>opacity</a></td><td>The client opacity</td></tr>
-- <tr><td><a href='../classes/client.html#client.ontop'>ontop</a></td><td>The client is on top of every other windows</td></tr>
-- <tr><td><a href='../classes/client.html#client.above'>above</a></td><td>The client is above normal windows</td></tr>
-- <tr><td><a href='../classes/client.html#client.below'>below</a></td><td>The client is below normal windows</td></tr>
-- <tr><td><a href='../classes/client.html#client.fullscreen'>fullscreen</a></td><td>The client is fullscreen or not</td></tr>
-- <tr><td><a href='../classes/client.html#client.maximized'>maximized</a></td><td>The client is maximized (horizontally and vertically) or not</td></tr>
-- <tr><td><a href='../classes/client.html#client.maximized_horizontal'>maximized\_horizontal</a></td><td>The client is maximized horizontally or not</td></tr>
-- <tr><td><a href='../classes/client.html#client.maximized_vertical'>maximized\_vertical</a></td><td>The client is maximized vertically or not</td></tr>
-- <tr><td><a href='../classes/client.html#client.transient_for'>transient\_for</a></td><td>The client the window is transient for</td></tr>
-- <tr><td><a href='../classes/client.html#client.group_window'>group\_window</a></td><td>Window identification unique to a group of windows</td></tr>
-- <tr><td><a href='../classes/client.html#client.leader_window'>leader\_window</a></td><td>Identification unique to windows spawned by the same command</td></tr>
-- <tr><td><a href='../classes/client.html#client.size_hints'>size\_hints</a></td><td>A table with size hints of the client</td></tr>
-- <tr><td><a href='../classes/client.html#client.motif_wm_hints'>motif\_wm\_hints</a></td><td>The motif WM hints of the client</td></tr>
-- <tr><td><a href='../classes/client.html#client.sticky'>sticky</a></td><td>Set the client sticky, i</td></tr>
-- <tr><td><a href='../classes/client.html#client.modal'>modal</a></td><td>Indicate if the client is modal</td></tr>
-- <tr><td><a href='../classes/client.html#client.focusable'>focusable</a></td><td>True if the client can receive the input focus</td></tr>
-- <tr><td><a href='../classes/client.html#client.shape_bounding'>shape\_bounding</a></td><td>The client's bounding shape as set by awesome as a (native) cairo surface</td></tr>
-- <tr><td><a href='../classes/client.html#client.shape_clip'>shape\_clip</a></td><td>The client's clip shape as set by awesome as a (native) cairo surface</td></tr>
-- <tr><td><a href='../classes/client.html#client.shape_input'>shape\_input</a></td><td>The client's input shape as set by awesome as a (native) cairo surface</td></tr>
-- <tr><td><a href='../classes/client.html#client.client_shape_bounding'>client\_shape\_bounding</a></td><td>The client's bounding shape as set by the program as a (native) cairo surface</td></tr>
-- <tr><td><a href='../classes/client.html#client.client_shape_clip'>client\_shape\_clip</a></td><td>The client's clip shape as set by the program as a (native) cairo surface</td></tr>
-- <tr><td><a href='../classes/client.html#client.startup_id'>startup\_id</a></td><td>The FreeDesktop StartId</td></tr>
-- <tr><td><a href='../classes/client.html#client.valid'>valid</a></td><td>If the client that this object refers to is still managed by awesome</td></tr>
-- <tr><td><a href='../classes/client.html#client.first_tag'>first\_tag</a></td><td>The first tag of the client</td></tr>
-- </table>

View File

@ -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

View File

@ -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;
@ -136,6 +149,7 @@ pre {
padding: 15px;
overflow: auto;
font-family: monospace;
max-width: 720px;
}
#content ul pre.example {
@ -191,6 +205,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;

View File

@ -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

View File

@ -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.
--

View File

@ -8,17 +8,98 @@
-- 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:
-- 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:
--
-- * placement
-- * honor_padding
-- * honor_workarea
-- * tag
-- * new_tag
-- * switch_to_tags (also called switchtotag)
-- * focus
-- * titlebars_enabled
-- * callback
-- { 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
-- ===
--
-- 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 &lt;julien@danjou.info&gt;
-- @copyright 2009 Julien Danjou
@ -44,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.
@ -536,11 +534,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

View File

@ -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,44 +48,56 @@
-- *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**:
-- **Understanding blocking versus asynchronous execution**:
--
-- 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 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.
--
-- 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:
-- 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.
--
-- DESKTOP_STARTUP_ID="something_TIME$(date '+%s')" my_command
-- If we do (but *really*, don't do that):
--
-- 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.
-- -- **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")
--
-- Awesome can automatically set the `DESKTOP_STARTUP_ID` variable. This is used
-- by `awful.spawn` to specify additional rules for the startup. For example:
-- The label will display `foo`. But If we do:
--
-- awful.spawn("urxvt -e maxima -name CALCULATOR", {
-- floating = true,
-- tag = mouse.screen.selected_tag,
-- placement = awful.placement.bottom_right,
-- })
-- -- 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")
--
-- This can also be used from the command line:
-- 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".
--
-- 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 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**:
--
@ -148,6 +163,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 &lt;julien@danjou.info&gt;
-- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
-- @copyright 2008 Julien Danjou

View File

@ -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.