WIP: awesomerc.tl
should work #85
|
@ -1,4 +1,6 @@
|
||||||
lua_modules/
|
lua_modules/
|
||||||
generated/
|
generated/*
|
||||||
|
!generated/awesomerc.tl
|
||||||
|
!generated/tlconfig.lua
|
||||||
build/
|
build/
|
||||||
luacov/
|
luacov/
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
},
|
},
|
||||||
"args": [
|
"args": [
|
||||||
"test",
|
"test",
|
||||||
"_spec" // Adapt to the spec to debug
|
"\"--pattern _spec --tags debug\""
|
||||||
],
|
],
|
||||||
"scriptFiles": ["${workspaceFolder}/**/*.tl"]
|
"scriptFiles": ["${workspaceFolder}/**/*.tl"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
"aireone",
|
"aireone",
|
||||||
"akorn",
|
"akorn",
|
||||||
"ansicolors",
|
"ansicolors",
|
||||||
|
"awesomerc",
|
||||||
"awesomewm",
|
"awesomewm",
|
||||||
"awesomewmdtl",
|
"awesomewmdtl",
|
||||||
"buildx",
|
"buildx",
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
"Luarocks",
|
"Luarocks",
|
||||||
"luasec",
|
"luasec",
|
||||||
"luasocket",
|
"luasocket",
|
||||||
|
"metamethods",
|
||||||
"mkdir",
|
"mkdir",
|
||||||
"modname",
|
"modname",
|
||||||
"reportfile",
|
"reportfile",
|
||||||
|
@ -45,6 +47,7 @@
|
||||||
"sublist",
|
"sublist",
|
||||||
"tablex",
|
"tablex",
|
||||||
"tbody",
|
"tbody",
|
||||||
|
"tlconfig",
|
||||||
"tmpl",
|
"tmpl",
|
||||||
"wibox",
|
"wibox",
|
||||||
"woodpeckerci",
|
"woodpeckerci",
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
variables:
|
||||||
|
- &cyan gitea.aireone.xyz/aire-one/awesomewm.d.tl/cyan:latest
|
||||||
|
|
||||||
|
pipeline:
|
||||||
|
build-and-run:
|
||||||
|
image: *cyan
|
||||||
|
commands:
|
||||||
|
- luarocks make awesomewmdtl-dev-1.rockspec
|
||||||
|
- awesomewmdtl
|
||||||
|
- just validate
|
||||||
|
|
||||||
|
branches: master
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- docker-build
|
|
@ -1,23 +0,0 @@
|
||||||
variables:
|
|
||||||
- &cyan gitea.aireone.xyz/aire-one/awesomewm.d.tl/cyan:latest
|
|
||||||
|
|
||||||
pipeline:
|
|
||||||
build:
|
|
||||||
image: *cyan
|
|
||||||
commands:
|
|
||||||
- just build
|
|
||||||
# run:
|
|
||||||
# image: akorn/luarocks:lua5.4-alpine
|
|
||||||
# commands:
|
|
||||||
# - apk add just
|
|
||||||
# - just run
|
|
||||||
# verify:
|
|
||||||
# image: alpine:3.16
|
|
||||||
# commands:
|
|
||||||
# - apk add tree
|
|
||||||
# - tree generated
|
|
||||||
|
|
||||||
branches: master
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- docker-build
|
|
|
@ -57,6 +57,7 @@ build = {
|
||||||
["awesomewmdtl.types.Dag"] = "build/awesomewmdtl/types/Dag.lua",
|
["awesomewmdtl.types.Dag"] = "build/awesomewmdtl/types/Dag.lua",
|
||||||
["awesomewmdtl.types.Node"] = "build/awesomewmdtl/types/Node.lua",
|
["awesomewmdtl.types.Node"] = "build/awesomewmdtl/types/Node.lua",
|
||||||
["awesomewmdtl.visitors.module_dependencies"] = "build/awesomewmdtl/visitors/module_dependencies.lua",
|
["awesomewmdtl.visitors.module_dependencies"] = "build/awesomewmdtl/visitors/module_dependencies.lua",
|
||||||
|
["awesomewmdtl.visitors.node_fixer"] = "build/awesomewmdtl/visitors/node_fixer.lua",
|
||||||
["awesomewmdtl.visitors.type_mapping"] = "build/awesomewmdtl/visitors/type_mapping.lua",
|
["awesomewmdtl.visitors.type_mapping"] = "build/awesomewmdtl/visitors/type_mapping.lua",
|
||||||
["awesomewmdtl.ast"] = "build/awesomewmdtl/ast.lua",
|
["awesomewmdtl.ast"] = "build/awesomewmdtl/ast.lua",
|
||||||
["awesomewmdtl.dag"] = "build/awesomewmdtl/dag.lua",
|
["awesomewmdtl.dag"] = "build/awesomewmdtl/dag.lua",
|
||||||
|
|
|
@ -0,0 +1,675 @@
|
||||||
|
-- awesome_mode: api-level=4:screen=on
|
||||||
|
-- If LuaRocks is installed, make sure that packages installed through it are
|
||||||
|
-- found (e.g. lgi). If LuaRocks is not installed, do nothing.
|
||||||
|
--- TODO : Write luarocks basic types definitions
|
||||||
|
-- pcall(require, "luarocks.loader")
|
||||||
|
|
||||||
|
-- @DOC_REQUIRE_SECTION@
|
||||||
|
-- Standard awesome library
|
||||||
|
local gears = require("gears")
|
||||||
|
local awful = require("awful")
|
||||||
|
require("awful.autofocus")
|
||||||
|
-- Widget and layout library
|
||||||
|
local wibox = require("wibox")
|
||||||
|
-- Theme handling library
|
||||||
|
local beautiful = require("beautiful")
|
||||||
|
-- Notification library
|
||||||
|
local naughty = require("naughty")
|
||||||
|
-- Declarative object management
|
||||||
|
local ruled = require("ruled")
|
||||||
|
local menubar = require("menubar")
|
||||||
|
local hotkeys_popup = require("awful.hotkeys_popup")
|
||||||
|
-- Enable hotkeys help widget for VIM and other apps
|
||||||
|
-- when client with a matching name is opened:
|
||||||
|
require("awful.hotkeys_popup.keys")
|
||||||
|
|
||||||
|
-- {{{ Error handling
|
||||||
|
-- Check if awesome encountered an error during startup and fell back to
|
||||||
|
-- another config (This code will only ever execute for the fallback config)
|
||||||
|
-- @DOC_ERROR_HANDLING@
|
||||||
|
naughty.connect_signal("request::display_error", function(message, startup)
|
||||||
|
naughty.notification {
|
||||||
|
urgency = "critical",
|
||||||
|
title = "Oops, an error happened"
|
||||||
|
.. (startup and " during startup!" or "!"),
|
||||||
|
message = message,
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Variable definitions
|
||||||
|
-- @DOC_LOAD_THEME@
|
||||||
|
-- Themes define colours, icons, font and wallpapers.
|
||||||
|
beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
|
||||||
|
|
||||||
|
-- @DOC_DEFAULT_APPLICATIONS@
|
||||||
|
-- This is used later as the default terminal and editor to run.
|
||||||
|
local terminal = "xterm"
|
||||||
|
local editor = os.getenv "EDITOR" or "nano"
|
||||||
|
local editor_cmd = terminal .. " -e " .. editor
|
||||||
|
|
||||||
|
-- Default modkey.
|
||||||
|
-- Usually, Mod4 is the key with a logo between Control and Alt.
|
||||||
|
-- If you do not like this or do not have such a key,
|
||||||
|
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
|
||||||
|
-- However, you can use another modifier like Mod1, but it may interact with others.
|
||||||
|
local modkey = "Mod4"
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Menu
|
||||||
|
-- @DOC_MENU@
|
||||||
|
-- Create a launcher widget and a main menu
|
||||||
|
local myawesomemenu = {
|
||||||
|
{
|
||||||
|
"hotkeys",
|
||||||
|
function()
|
||||||
|
hotkeys_popup.show_help(nil, awful.screen.focused())
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{ "manual", terminal .. " -e man awesome" },
|
||||||
|
{ "edit config", editor_cmd .. " " .. awesome.conffile },
|
||||||
|
{ "restart", awesome.restart },
|
||||||
|
{
|
||||||
|
"quit",
|
||||||
|
function()
|
||||||
|
awesome.quit()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local mymainmenu = awful.menu {
|
||||||
|
items = {
|
||||||
|
{ "awesome", myawesomemenu, beautiful.awesome_icon },
|
||||||
|
{ "open terminal", terminal },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local mylauncher = awful.widget.launcher {
|
||||||
|
image = beautiful.awesome_icon,
|
||||||
|
menu = mymainmenu,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Menubar configuration
|
||||||
|
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Tag layout
|
||||||
|
-- @DOC_LAYOUT@
|
||||||
|
-- Table of layouts to cover with awful.layout.inc, order matters.
|
||||||
|
tag.connect_signal("request::default_layouts", function()
|
||||||
|
awful.layout.append_default_layouts {
|
||||||
|
awful.layout.suit.floating,
|
||||||
|
awful.layout.suit.tile,
|
||||||
|
awful.layout.suit.tile.left,
|
||||||
|
awful.layout.suit.tile.bottom,
|
||||||
|
awful.layout.suit.tile.top,
|
||||||
|
awful.layout.suit.fair,
|
||||||
|
awful.layout.suit.fair.horizontal,
|
||||||
|
awful.layout.suit.spiral,
|
||||||
|
awful.layout.suit.spiral.dwindle,
|
||||||
|
awful.layout.suit.max,
|
||||||
|
awful.layout.suit.max.fullscreen,
|
||||||
|
awful.layout.suit.magnifier,
|
||||||
|
awful.layout.suit.corner.nw,
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Wallpaper
|
||||||
|
-- @DOC_WALLPAPER@
|
||||||
|
screen.connect_signal("request::wallpaper", function(s)
|
||||||
|
awful.wallpaper {
|
||||||
|
screen = s,
|
||||||
|
widget = {
|
||||||
|
{
|
||||||
|
image = beautiful.wallpaper,
|
||||||
|
upscale = true,
|
||||||
|
downscale = true,
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
},
|
||||||
|
valign = "center",
|
||||||
|
halign = "center",
|
||||||
|
tiled = false,
|
||||||
|
widget = wibox.container.tile,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Wibar
|
||||||
|
|
||||||
|
-- Keyboard map indicator and switcher
|
||||||
|
local mykeyboardlayout = awful.widget.keyboardlayout()
|
||||||
|
|
||||||
|
-- Create a textclock widget
|
||||||
|
local mytextclock = wibox.widget.textclock()
|
||||||
|
|
||||||
|
-- @DOC_FOR_EACH_SCREEN@
|
||||||
|
screen.connect_signal("request::desktop_decoration", function(s: screen)
|
||||||
|
-- Each screen has its own tag table.
|
||||||
|
awful.tag(
|
||||||
|
{ "1", "2", "3", "4", "5", "6", "7", "8", "9" },
|
||||||
|
s,
|
||||||
|
awful.layout.layouts[1]
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Create a promptbox for each screen
|
||||||
|
s.mypromptbox = awful.widget.prompt()
|
||||||
|
|
||||||
|
-- Create an imagebox widget which will contain an icon indicating which layout we're using.
|
||||||
|
-- We need one layoutbox per screen.
|
||||||
|
s.mylayoutbox = awful.widget.layoutbox {
|
||||||
|
screen = s,
|
||||||
|
buttons = {
|
||||||
|
awful.button({}, 1, function()
|
||||||
|
awful.layout.inc(1)
|
||||||
|
end),
|
||||||
|
awful.button({}, 3, function()
|
||||||
|
awful.layout.inc(-1)
|
||||||
|
end),
|
||||||
|
awful.button({}, 4, function()
|
||||||
|
awful.layout.inc(-1)
|
||||||
|
end),
|
||||||
|
awful.button({}, 5, function()
|
||||||
|
awful.layout.inc(1)
|
||||||
|
end),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Create a taglist widget
|
||||||
|
s.mytaglist = awful.widget.taglist {
|
||||||
|
screen = s,
|
||||||
|
filter = awful.widget.taglist.filter.all,
|
||||||
|
buttons = {
|
||||||
|
awful.button({}, 1, function(t: tag)
|
||||||
|
t:view_only()
|
||||||
|
end),
|
||||||
|
awful.button({ modkey }, 1, function(t: tag)
|
||||||
|
if client.focus then
|
||||||
|
client.focus:move_to_tag(t)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({}, 3, awful.tag.viewtoggle),
|
||||||
|
awful.button({ modkey }, 3, function(t: tag)
|
||||||
|
if client.focus then
|
||||||
|
client.focus:toggle_tag(t)
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
awful.button({}, 4, function(t: tag)
|
||||||
|
awful.tag.viewprev(t.screen)
|
||||||
|
end),
|
||||||
|
awful.button({}, 5, function(t: tag)
|
||||||
|
awful.tag.viewnext(t.screen)
|
||||||
|
end),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- @TASKLIST_BUTTON@
|
||||||
|
-- Create a tasklist widget
|
||||||
|
s.mytasklist = awful.widget.tasklist {
|
||||||
|
screen = s,
|
||||||
|
filter = awful.widget.tasklist.filter.currenttags,
|
||||||
|
buttons = {
|
||||||
|
awful.button({}, 1, function(c)
|
||||||
|
c:activate { context = "tasklist", action = "toggle_minimization" }
|
||||||
|
end),
|
||||||
|
awful.button({}, 3, function()
|
||||||
|
awful.menu.client_list { theme = { width = 250 } }
|
||||||
|
end),
|
||||||
|
awful.button({}, 4, function()
|
||||||
|
awful.client.focus.byidx(-1)
|
||||||
|
end),
|
||||||
|
awful.button({}, 5, function()
|
||||||
|
awful.client.focus.byidx(1)
|
||||||
|
end),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- @DOC_WIBAR@
|
||||||
|
-- Create the wibox
|
||||||
|
s.mywibox = awful.wibar {
|
||||||
|
position = "top",
|
||||||
|
screen = s,
|
||||||
|
-- @DOC_SETUP_WIDGETS@
|
||||||
|
widget = {
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
{ -- Left widgets
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
mylauncher,
|
||||||
|
s.mytaglist,
|
||||||
|
s.mypromptbox,
|
||||||
|
},
|
||||||
|
s.mytasklist, -- Middle widget
|
||||||
|
{ -- Right widgets
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
mykeyboardlayout,
|
||||||
|
wibox.widget.systray(),
|
||||||
|
mytextclock,
|
||||||
|
s.mylayoutbox,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Mouse bindings
|
||||||
|
-- @DOC_ROOT_BUTTONS@
|
||||||
|
awful.mouse.append_global_mousebindings {
|
||||||
|
awful.button({}, 3, function()
|
||||||
|
mymainmenu:toggle()
|
||||||
|
end),
|
||||||
|
awful.button({}, 4, awful.tag.viewprev),
|
||||||
|
awful.button({}, 5, awful.tag.viewnext),
|
||||||
|
}
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Key bindings
|
||||||
|
-- @DOC_GLOBAL_KEYBINDINGS@
|
||||||
|
|
||||||
|
-- General Awesome keys
|
||||||
|
awful.keyboard.append_global_keybindings {
|
||||||
|
awful.key(
|
||||||
|
{ modkey },
|
||||||
|
"s",
|
||||||
|
hotkeys_popup.show_help,
|
||||||
|
{ description = "show help", group = "awesome" }
|
||||||
|
),
|
||||||
|
awful.key({ modkey }, "w", function()
|
||||||
|
mymainmenu:show()
|
||||||
|
end, { description = "show main menu", group = "awesome" }),
|
||||||
|
awful.key(
|
||||||
|
{ modkey, "Control" },
|
||||||
|
"r",
|
||||||
|
awesome.restart,
|
||||||
|
{ description = "reload awesome", group = "awesome" }
|
||||||
|
),
|
||||||
|
awful.key(
|
||||||
|
{ modkey, "Shift" },
|
||||||
|
"q",
|
||||||
|
awesome.quit,
|
||||||
|
{ description = "quit awesome", group = "awesome" }
|
||||||
|
),
|
||||||
|
awful.key({ modkey }, "x", function()
|
||||||
|
awful.prompt.run {
|
||||||
|
prompt = "Run Lua code: ",
|
||||||
|
textbox = awful.screen.focused().mypromptbox.widget,
|
||||||
|
exe_callback = awful.util.eval,
|
||||||
|
history_path = awful.util.get_cache_dir() .. "/history_eval",
|
||||||
|
}
|
||||||
|
end, { description = "lua execute prompt", group = "awesome" }),
|
||||||
|
awful.key({ modkey }, "Return", function()
|
||||||
|
awful.spawn(terminal)
|
||||||
|
end, { description = "open a terminal", group = "launcher" }),
|
||||||
|
awful.key({ modkey }, "r", function()
|
||||||
|
awful.screen.focused().mypromptbox:run()
|
||||||
|
end, { description = "run prompt", group = "launcher" }),
|
||||||
|
awful.key({ modkey }, "p", function()
|
||||||
|
menubar.show()
|
||||||
|
end, { description = "show the menubar", group = "launcher" }),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Tags related keybindings
|
||||||
|
awful.keyboard.append_global_keybindings {
|
||||||
|
awful.key(
|
||||||
|
{ modkey },
|
||||||
|
"Left",
|
||||||
|
awful.tag.viewprev,
|
||||||
|
{ description = "view previous", group = "tag" }
|
||||||
|
),
|
||||||
|
awful.key(
|
||||||
|
{ modkey },
|
||||||
|
"Right",
|
||||||
|
awful.tag.viewnext,
|
||||||
|
{ description = "view next", group = "tag" }
|
||||||
|
),
|
||||||
|
awful.key(
|
||||||
|
{ modkey },
|
||||||
|
"Escape",
|
||||||
|
awful.tag.history.restore,
|
||||||
|
{ description = "go back", group = "tag" }
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Focus related keybindings
|
||||||
|
awful.keyboard.append_global_keybindings {
|
||||||
|
awful.key({ modkey }, "j", function()
|
||||||
|
awful.client.focus.byidx(1)
|
||||||
|
end, { description = "focus next by index", group = "client" }),
|
||||||
|
awful.key({ modkey }, "k", function()
|
||||||
|
awful.client.focus.byidx(-1)
|
||||||
|
end, { description = "focus previous by index", group = "client" }),
|
||||||
|
awful.key({ modkey }, "Tab", function()
|
||||||
|
awful.client.focus.history.previous()
|
||||||
|
if client.focus then
|
||||||
|
client.focus:raise()
|
||||||
|
end
|
||||||
|
end, { description = "go back", group = "client" }),
|
||||||
|
awful.key({ modkey, "Control" }, "j", function()
|
||||||
|
awful.screen.focus_relative(1)
|
||||||
|
end, { description = "focus the next screen", group = "screen" }),
|
||||||
|
awful.key({ modkey, "Control" }, "k", function()
|
||||||
|
awful.screen.focus_relative(-1)
|
||||||
|
end, { description = "focus the previous screen", group = "screen" }),
|
||||||
|
awful.key({ modkey, "Control" }, "n", function()
|
||||||
|
local c = awful.client.restore()
|
||||||
|
-- Focus restored client
|
||||||
|
if c then
|
||||||
|
c:activate { raise = true, context = "key.unminimize" }
|
||||||
|
end
|
||||||
|
end, { description = "restore minimized", group = "client" }),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Layout related keybindings
|
||||||
|
awful.keyboard.append_global_keybindings {
|
||||||
|
awful.key({ modkey, "Shift" }, "j", function()
|
||||||
|
awful.client.swap.byidx(1)
|
||||||
|
end, { description = "swap with next client by index", group = "client" }),
|
||||||
|
awful.key(
|
||||||
|
{ modkey, "Shift" },
|
||||||
|
"k",
|
||||||
|
function()
|
||||||
|
awful.client.swap.byidx(-1)
|
||||||
|
end,
|
||||||
|
{ description = "swap with previous client by index", group = "client" }
|
||||||
|
),
|
||||||
|
awful.key(
|
||||||
|
{ modkey },
|
||||||
|
"u",
|
||||||
|
awful.client.urgent.jumpto,
|
||||||
|
{ description = "jump to urgent client", group = "client" }
|
||||||
|
),
|
||||||
|
awful.key({ modkey }, "l", function()
|
||||||
|
awful.tag.incmwfact(0.05)
|
||||||
|
end, { description = "increase master width factor", group = "layout" }),
|
||||||
|
awful.key({ modkey }, "h", function()
|
||||||
|
awful.tag.incmwfact(-0.05)
|
||||||
|
end, { description = "decrease master width factor", group = "layout" }),
|
||||||
|
awful.key({ modkey, "Shift" }, "h", function()
|
||||||
|
awful.tag.incnmaster(1, nil, true)
|
||||||
|
end, {
|
||||||
|
description = "increase the number of master clients",
|
||||||
|
group = "layout",
|
||||||
|
}),
|
||||||
|
awful.key({ modkey, "Shift" }, "l", function()
|
||||||
|
awful.tag.incnmaster(-1, nil, true)
|
||||||
|
end, {
|
||||||
|
description = "decrease the number of master clients",
|
||||||
|
group = "layout",
|
||||||
|
}),
|
||||||
|
awful.key({ modkey, "Control" }, "h", function()
|
||||||
|
awful.tag.incncol(1, nil, true)
|
||||||
|
end, { description = "increase the number of columns", group = "layout" }),
|
||||||
|
awful.key({ modkey, "Control" }, "l", function()
|
||||||
|
awful.tag.incncol(-1, nil, true)
|
||||||
|
end, { description = "decrease the number of columns", group = "layout" }),
|
||||||
|
awful.key({ modkey }, "space", function()
|
||||||
|
awful.layout.inc(1)
|
||||||
|
end, { description = "select next", group = "layout" }),
|
||||||
|
awful.key({ modkey, "Shift" }, "space", function()
|
||||||
|
awful.layout.inc(-1)
|
||||||
|
end, { description = "select previous", group = "layout" }),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- @DOC_NUMBER_KEYBINDINGS@
|
||||||
|
|
||||||
|
awful.keyboard.append_global_keybindings {
|
||||||
|
awful.key {
|
||||||
|
modifiers = { modkey },
|
||||||
|
keygroup = "numrow",
|
||||||
|
description = "only view tag",
|
||||||
|
group = "tag",
|
||||||
|
on_press = function(index)
|
||||||
|
local screen = awful.screen.focused()
|
||||||
|
local tag = screen.tags[index]
|
||||||
|
if tag then
|
||||||
|
tag:view_only()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
awful.key {
|
||||||
|
modifiers = { modkey, "Control" },
|
||||||
|
keygroup = "numrow",
|
||||||
|
description = "toggle tag",
|
||||||
|
group = "tag",
|
||||||
|
on_press = function(index)
|
||||||
|
local screen = awful.screen.focused()
|
||||||
|
local tag = screen.tags[index]
|
||||||
|
if tag then
|
||||||
|
awful.tag.viewtoggle(tag)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
awful.key {
|
||||||
|
modifiers = { modkey, "Shift" },
|
||||||
|
keygroup = "numrow",
|
||||||
|
description = "move focused client to tag",
|
||||||
|
group = "tag",
|
||||||
|
on_press = function(index)
|
||||||
|
if client.focus then
|
||||||
|
local tag = client.focus.screen.tags[index]
|
||||||
|
if tag then
|
||||||
|
client.focus:move_to_tag(tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
awful.key {
|
||||||
|
modifiers = { modkey, "Control", "Shift" },
|
||||||
|
keygroup = "numrow",
|
||||||
|
description = "toggle focused client on tag",
|
||||||
|
group = "tag",
|
||||||
|
on_press = function(index)
|
||||||
|
if client.focus then
|
||||||
|
local tag = client.focus.screen.tags[index]
|
||||||
|
if tag then
|
||||||
|
client.focus:toggle_tag(tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
awful.key {
|
||||||
|
modifiers = { modkey },
|
||||||
|
keygroup = "numpad",
|
||||||
|
description = "select layout directly",
|
||||||
|
group = "layout",
|
||||||
|
on_press = function(index)
|
||||||
|
local t = awful.screen.focused().selected_tag
|
||||||
|
if t then
|
||||||
|
t.layout = t.layouts[index] or t.layout
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- @DOC_CLIENT_BUTTONS@
|
||||||
|
client.connect_signal("request::default_mousebindings", function()
|
||||||
|
awful.mouse.append_client_mousebindings {
|
||||||
|
awful.button({}, 1, function(c)
|
||||||
|
c:activate { context = "mouse_click" }
|
||||||
|
end),
|
||||||
|
awful.button({ modkey }, 1, function(c)
|
||||||
|
c:activate { context = "mouse_click", action = "mouse_move" }
|
||||||
|
end),
|
||||||
|
awful.button({ modkey }, 3, function(c)
|
||||||
|
c:activate { context = "mouse_click", action = "mouse_resize" }
|
||||||
|
end),
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- @DOC_CLIENT_KEYBINDINGS@
|
||||||
|
client.connect_signal("request::default_keybindings", function()
|
||||||
|
awful.keyboard.append_client_keybindings {
|
||||||
|
awful.key({ modkey }, "f", function(c: client)
|
||||||
|
c.fullscreen = not c.fullscreen
|
||||||
|
c:raise()
|
||||||
|
end, { description = "toggle fullscreen", group = "client" }),
|
||||||
|
awful.key({ modkey, "Shift" }, "c", function(c: client)
|
||||||
|
c:kill()
|
||||||
|
end, { description = "close", group = "client" }),
|
||||||
|
awful.key(
|
||||||
|
{ modkey, "Control" },
|
||||||
|
"space",
|
||||||
|
awful.client.floating.toggle,
|
||||||
|
{ description = "toggle floating", group = "client" }
|
||||||
|
),
|
||||||
|
awful.key({ modkey, "Control" }, "Return", function(c: client)
|
||||||
|
c:swap(awful.client.getmaster())
|
||||||
|
end, { description = "move to master", group = "client" }),
|
||||||
|
awful.key({ modkey }, "o", function(c: client)
|
||||||
|
c:move_to_screen()
|
||||||
|
end, { description = "move to screen", group = "client" }),
|
||||||
|
awful.key({ modkey }, "t", function(c: client)
|
||||||
|
c.ontop = not c.ontop
|
||||||
|
end, { description = "toggle keep on top", group = "client" }),
|
||||||
|
awful.key({ modkey }, "n", function(c: client)
|
||||||
|
-- The client currently has the input focus, so it cannot be
|
||||||
|
-- minimized, since minimized clients can't have the focus.
|
||||||
|
c.minimized = true
|
||||||
|
end, { description = "minimize", group = "client" }),
|
||||||
|
awful.key({ modkey }, "m", function(c: client)
|
||||||
|
c.maximized = not c.maximized
|
||||||
|
c:raise()
|
||||||
|
end, { description = "(un)maximize", group = "client" }),
|
||||||
|
awful.key({ modkey, "Control" }, "m", function(c: client)
|
||||||
|
c.maximized_vertical = not c.maximized_vertical
|
||||||
|
c:raise()
|
||||||
|
end, { description = "(un)maximize vertically", group = "client" }),
|
||||||
|
awful.key({ modkey, "Shift" }, "m", function(c: client)
|
||||||
|
c.maximized_horizontal = not c.maximized_horizontal
|
||||||
|
c:raise()
|
||||||
|
end, { description = "(un)maximize horizontally", group = "client" }),
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Rules
|
||||||
|
-- Rules to apply to new clients.
|
||||||
|
-- @DOC_RULES@
|
||||||
|
ruled.client.connect_signal("request::rules", function()
|
||||||
|
-- @DOC_GLOBAL_RULE@
|
||||||
|
-- All clients will match this rule.
|
||||||
|
ruled.client.append_rule {
|
||||||
|
id = "global",
|
||||||
|
rule = {},
|
||||||
|
properties = {
|
||||||
|
focus = awful.client.focus.filter,
|
||||||
|
raise = true,
|
||||||
|
screen = awful.screen.preferred,
|
||||||
|
placement = awful.placement.no_overlap + awful.placement.no_offscreen,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- @DOC_FLOATING_RULE@
|
||||||
|
-- Floating clients.
|
||||||
|
ruled.client.append_rule {
|
||||||
|
id = "floating",
|
||||||
|
rule_any = {
|
||||||
|
instance = { "copyq", "pinentry" },
|
||||||
|
class = {
|
||||||
|
"Arandr",
|
||||||
|
"Blueman-manager",
|
||||||
|
"Gpick",
|
||||||
|
"Kruler",
|
||||||
|
"Sxiv",
|
||||||
|
"Tor Browser",
|
||||||
|
"Wpa_gui",
|
||||||
|
"veromix",
|
||||||
|
"xtightvncviewer",
|
||||||
|
},
|
||||||
|
-- Note that the name property shown in xprop might be set slightly after creation of the client
|
||||||
|
-- and the name shown there might not match defined rules here.
|
||||||
|
name = {
|
||||||
|
"Event Tester", -- xev.
|
||||||
|
},
|
||||||
|
role = {
|
||||||
|
"AlarmWindow", -- Thunderbird's calendar.
|
||||||
|
"ConfigManager", -- Thunderbird's about:config.
|
||||||
|
"pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties = { floating = true },
|
||||||
|
}
|
||||||
|
|
||||||
|
-- @DOC_DIALOG_RULE@
|
||||||
|
-- Add titlebars to normal clients and dialogs
|
||||||
|
ruled.client.append_rule {
|
||||||
|
-- @DOC_CSD_TITLEBARS@
|
||||||
|
id = "titlebars",
|
||||||
|
rule_any = { type = { "normal", "dialog" } },
|
||||||
|
properties = { titlebars_enabled = true },
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Set Firefox to always map on the tag named "2" on screen 1.
|
||||||
|
-- ruled.client.append_rule {
|
||||||
|
-- rule = { class = "Firefox" },
|
||||||
|
-- properties = { screen = 1, tag = "2" }
|
||||||
|
-- }
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Titlebars
|
||||||
|
-- @DOC_TITLEBARS@
|
||||||
|
-- Add a titlebar if titlebars_enabled is set to true in the rules.
|
||||||
|
client.connect_signal("request::titlebars", function(c: client)
|
||||||
|
-- buttons for the titlebar
|
||||||
|
local buttons = {
|
||||||
|
awful.button({}, 1, function()
|
||||||
|
c:activate { context = "titlebar", action = "mouse_move" }
|
||||||
|
end),
|
||||||
|
awful.button({}, 3, function()
|
||||||
|
c:activate { context = "titlebar", action = "mouse_resize" }
|
||||||
|
end),
|
||||||
|
}
|
||||||
|
|
||||||
|
awful.titlebar(c).widget = {
|
||||||
|
{ -- Left
|
||||||
|
awful.titlebar.widget.iconwidget(c),
|
||||||
|
buttons = buttons,
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
},
|
||||||
|
{ -- Middle
|
||||||
|
{ -- Title
|
||||||
|
halign = "center",
|
||||||
|
widget = awful.titlebar.widget.titlewidget(c),
|
||||||
|
},
|
||||||
|
buttons = buttons,
|
||||||
|
layout = wibox.layout.flex.horizontal,
|
||||||
|
},
|
||||||
|
{ -- Right
|
||||||
|
awful.titlebar.widget.floatingbutton(c),
|
||||||
|
awful.titlebar.widget.maximizedbutton(c),
|
||||||
|
awful.titlebar.widget.stickybutton(c),
|
||||||
|
awful.titlebar.widget.ontopbutton(c),
|
||||||
|
awful.titlebar.widget.closebutton(c),
|
||||||
|
layout = wibox.layout.fixed.horizontal(),
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- {{{ Notifications
|
||||||
|
|
||||||
|
ruled.notification.connect_signal("request::rules", function()
|
||||||
|
-- All notifications will match this rule.
|
||||||
|
ruled.notification.append_rule {
|
||||||
|
rule = {},
|
||||||
|
properties = {
|
||||||
|
screen = awful.screen.preferred,
|
||||||
|
implicit_timeout = 5,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
naughty.connect_signal("request::display", function(n)
|
||||||
|
naughty.layout.box { notification = n }
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- }}}
|
||||||
|
|
||||||
|
-- Enable sloppy focus, so that focus follows mouse.
|
||||||
|
client.connect_signal("mouse::enter", function(c: client)
|
||||||
|
c:activate { context = "mouse_enter", raise = false }
|
||||||
|
end)
|
|
@ -0,0 +1,4 @@
|
||||||
|
return {
|
||||||
|
source_dir = ".",
|
||||||
|
global_env_def = "global_env_def",
|
||||||
|
}
|
6
justfile
6
justfile
|
@ -62,16 +62,14 @@ run:
|
||||||
validate:
|
validate:
|
||||||
cd generated && cyan \
|
cd generated && cyan \
|
||||||
check \
|
check \
|
||||||
--global-env-def "global_env" \
|
|
||||||
awesomerc.tl
|
awesomerc.tl
|
||||||
# `find . -type f -iname '*.d.tl' | xargs`
|
|
||||||
|
|
||||||
test PATTERN="_spec":
|
test PARAMETERS="--pattern=_spec":
|
||||||
luarocks \
|
luarocks \
|
||||||
--lua-version {{ lua_version }} \
|
--lua-version {{ lua_version }} \
|
||||||
test \
|
test \
|
||||||
{{ rockspec_file }} \
|
{{ rockspec_file }} \
|
||||||
-- --pattern={{ PATTERN }}
|
-- {{ PARAMETERS }}
|
||||||
|
|
||||||
local-test PATTERN="_spec":
|
local-test PATTERN="_spec":
|
||||||
luarocks \
|
luarocks \
|
||||||
|
|
|
@ -22,6 +22,7 @@ describe("Teal type definition Printer", function()
|
||||||
{
|
{
|
||||||
children = {},
|
children = {},
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
name = "Empty",
|
name = "Empty",
|
||||||
token = "module",
|
token = "module",
|
||||||
},
|
},
|
||||||
|
@ -53,6 +54,7 @@ describe("Teal type definition Printer", function()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
name = "Signal_Module",
|
name = "Signal_Module",
|
||||||
token = "module",
|
token = "module",
|
||||||
},
|
},
|
||||||
|
@ -79,6 +81,7 @@ describe("Teal type definition Printer", function()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
name = "Property_Module",
|
name = "Property_Module",
|
||||||
token = "module",
|
token = "module",
|
||||||
},
|
},
|
||||||
|
@ -108,12 +111,13 @@ describe("Teal type definition Printer", function()
|
||||||
token = "variable",
|
token = "variable",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
return_types = { "boolean" },
|
return_types = { { "boolean" }, { "nil", "number" } },
|
||||||
name = "kill",
|
name = "kill",
|
||||||
token = "function",
|
token = "function",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
name = "Function_Module",
|
name = "Function_Module",
|
||||||
token = "module",
|
token = "module",
|
||||||
},
|
},
|
||||||
|
@ -121,7 +125,7 @@ describe("Teal type definition Printer", function()
|
||||||
-- This file was auto-generated.
|
-- This file was auto-generated.
|
||||||
|
|
||||||
local record Function_Module
|
local record Function_Module
|
||||||
kill: function(pid: integer, sig: integer): boolean
|
kill: function(pid: integer, sig: integer): boolean, nil | number
|
||||||
end
|
end
|
||||||
|
|
||||||
return Function_Module
|
return Function_Module
|
||||||
|
@ -137,6 +141,7 @@ describe("Teal type definition Printer", function()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
name = "Nested_Module",
|
name = "Nested_Module",
|
||||||
token = "module",
|
token = "module",
|
||||||
},
|
},
|
||||||
|
@ -158,6 +163,7 @@ describe("Teal type definition Printer", function()
|
||||||
dep = "dep",
|
dep = "dep",
|
||||||
deeper = "path.dep.deeper",
|
deeper = "path.dep.deeper",
|
||||||
},
|
},
|
||||||
|
descendants = {},
|
||||||
name = "Module",
|
name = "Module",
|
||||||
token = "module",
|
token = "module",
|
||||||
},
|
},
|
||||||
|
@ -171,4 +177,104 @@ describe("Teal type definition Printer", function()
|
||||||
|
|
||||||
return Module
|
return Module
|
||||||
]]))
|
]]))
|
||||||
|
|
||||||
|
it("should print __call metamethod", gen(
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters = {
|
||||||
|
{
|
||||||
|
types = { "Timer" },
|
||||||
|
name = "self",
|
||||||
|
token = "variable",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
return_types = {},
|
||||||
|
name = "timer",
|
||||||
|
metamethod = "__call",
|
||||||
|
token = "metamethod",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "Timer",
|
||||||
|
module_path = "gears.timer",
|
||||||
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
},
|
||||||
|
[[
|
||||||
|
-- This file was auto-generated.
|
||||||
|
|
||||||
|
local record Timer
|
||||||
|
enum Signal
|
||||||
|
end
|
||||||
|
metamethod __call: function(self: Timer)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Timer
|
||||||
|
]]))
|
||||||
|
|
||||||
|
it("should print a module with descendants", gen(
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters = {},
|
||||||
|
return_types = {},
|
||||||
|
name = "draw_to_cairo_context",
|
||||||
|
token = "function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters = {},
|
||||||
|
return_types = {},
|
||||||
|
name = "imagebox",
|
||||||
|
metamethod = "__call",
|
||||||
|
token = "metamethod",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "Imagebox",
|
||||||
|
module_path = "wibox.widget.imagebox",
|
||||||
|
dependencies = {},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "Widget",
|
||||||
|
module_path = "wibox.widget",
|
||||||
|
dependencies = {},
|
||||||
|
descendants = {
|
||||||
|
Imagebox = "wibox.widget.imagebox",
|
||||||
|
},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
},
|
||||||
|
[[
|
||||||
|
-- This file was auto-generated.
|
||||||
|
local type Imagebox = require("wibox.widget.imagebox")
|
||||||
|
|
||||||
|
local record Widget
|
||||||
|
enum Signal
|
||||||
|
end
|
||||||
|
draw_to_cairo_context: function()
|
||||||
|
imagebox: Imagebox
|
||||||
|
end
|
||||||
|
|
||||||
|
return Widget
|
||||||
|
]]))
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -27,6 +27,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Empty",
|
name = "Empty",
|
||||||
module_path = "empty",
|
module_path = "empty",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -89,6 +91,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Property_signal",
|
name = "Property_signal",
|
||||||
module_path = "property_signal",
|
module_path = "property_signal",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -202,6 +206,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Property_enum",
|
name = "Property_enum",
|
||||||
module_path = "property_enum",
|
module_path = "property_enum",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -244,6 +250,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Property_string",
|
name = "Property_string",
|
||||||
module_path = "property_string",
|
module_path = "property_string",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -311,6 +319,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Tag",
|
name = "Tag",
|
||||||
module_path = "awful.tag",
|
module_path = "awful.tag",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -363,6 +373,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Signal",
|
name = "Signal",
|
||||||
module_path = "signal",
|
module_path = "signal",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -450,14 +462,16 @@ describe("Scrap documentation", function()
|
||||||
token = "variable",
|
token = "variable",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
return_types = { "boolean" },
|
return_types = { { "boolean" }},
|
||||||
name = "kill",
|
name = "kill",
|
||||||
token = "function",
|
token = "function",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
name = "Awesome",
|
name = "awesome",
|
||||||
module_path = "awesome",
|
module_path = "awesome",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -566,6 +580,7 @@ describe("Scrap documentation", function()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
name = "Focused_Args",
|
name = "Focused_Args",
|
||||||
|
global = false,
|
||||||
token = "record",
|
token = "record",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -576,7 +591,7 @@ describe("Scrap documentation", function()
|
||||||
token = "variable",
|
token = "variable",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
return_types = { "screen" },
|
return_types = { { "screen" }},
|
||||||
name = "focused",
|
name = "focused",
|
||||||
token = "function",
|
token = "function",
|
||||||
},
|
},
|
||||||
|
@ -584,6 +599,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Screen",
|
name = "Screen",
|
||||||
module_path = "awful.screen",
|
module_path = "awful.screen",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -667,7 +684,7 @@ describe("Scrap documentation", function()
|
||||||
token = "variable",
|
token = "variable",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
return_types = { "table" },
|
return_types = { { "table" }},
|
||||||
name = "crush",
|
name = "crush",
|
||||||
token = "function",
|
token = "function",
|
||||||
}
|
}
|
||||||
|
@ -675,6 +692,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Table",
|
name = "Table",
|
||||||
module_path = "gears.table",
|
module_path = "gears.table",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -759,7 +778,7 @@ describe("Scrap documentation", function()
|
||||||
token = "variable",
|
token = "variable",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
return_types = { "table" },
|
return_types = { { "table" } },
|
||||||
name = "tags",
|
name = "tags",
|
||||||
token = "function",
|
token = "function",
|
||||||
},
|
},
|
||||||
|
@ -767,6 +786,8 @@ describe("Scrap documentation", function()
|
||||||
name = "Client",
|
name = "Client",
|
||||||
module_path = "awful.client",
|
module_path = "awful.client",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -810,14 +831,145 @@ describe("Scrap documentation", function()
|
||||||
name = "Client",
|
name = "Client",
|
||||||
module_path = "awful.client",
|
module_path = "awful.client",
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
token = "module",
|
token = "module",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
parameters = {},
|
parameters = {},
|
||||||
return_types = { "integer" },
|
return_types = { { "integer" } },
|
||||||
name = "client.instances",
|
name = "client.instances",
|
||||||
token = "function",
|
token = "function",
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
it("should parse function return union types and multiple return values", test(
|
||||||
|
[[
|
||||||
|
<h2 class="section-header "><a name="Static_module_functions"></a>Static module functions</h2>
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a class="copy-link js-copy-link" name="load_image" href="#load_image">🔗</a>
|
||||||
|
<strong><span class="function_modname">awesome.</span>load_image <span class="function_args"> <b>(</b>name<b>)</b></span></strong>
|
||||||
|
<span class="proptype">
|
||||||
|
<span class="summary_type"> -> (gears.surface, nil <i>or</i> string)</span></span>
|
||||||
|
<span class="baseclass">
|
||||||
|
</span>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Load an image from a given path.
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<span class="types"><span class="type">gears.surface</span></span>
|
||||||
|
A cairo surface as light user datum.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="types"><span class="type">nil</span> or <a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4" target="_blank">string</a></span>
|
||||||
|
The error message, if any.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
]],
|
||||||
|
"awesome",
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters = {},
|
||||||
|
return_types = { { "gears.surface" }, { "nil", "string" } },
|
||||||
|
name = "load_image",
|
||||||
|
token = "function",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "awesome",
|
||||||
|
module_path = "awesome",
|
||||||
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
}))
|
||||||
|
|
||||||
|
it("should produce a __call metamethod for constructor", test(
|
||||||
|
[[
|
||||||
|
<h2 class="section-header "><a name="Constructors"></a>Constructors</h2>
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a class="copy-link js-copy-link" name="gears.timer" href="#gears.timer">🔗</a>
|
||||||
|
<strong>gears.timer <span class="function_named_args"><b>{</b>[args]<b>}</b></span></strong>
|
||||||
|
<span class="baseclass"></span>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
]],
|
||||||
|
"gears.timer",
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
parameters = {
|
||||||
|
{
|
||||||
|
types = { "Timer" },
|
||||||
|
name = "self",
|
||||||
|
token = "variable",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
return_types = {},
|
||||||
|
name = "timer",
|
||||||
|
metamethod = "__call",
|
||||||
|
token = "metamethod",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "Timer",
|
||||||
|
module_path = "gears.timer",
|
||||||
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
}))
|
||||||
|
|
||||||
|
it("should produce Variable for content in the Fields section", test(
|
||||||
|
[[
|
||||||
|
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a class="copy-link js-copy-link" name="primary" href="#primary">🔗</a>
|
||||||
|
<strong><span class="function_modname">screen.</span>primary</strong>
|
||||||
|
<span class="proptype"><span class="summary_type">screen</span></span>
|
||||||
|
<span class="baseclass"></span>
|
||||||
|
</dt>
|
||||||
|
<dd></dd>
|
||||||
|
</dl>
|
||||||
|
]],
|
||||||
|
"field_variable",
|
||||||
|
{
|
||||||
|
children = {
|
||||||
|
{
|
||||||
|
children = {},
|
||||||
|
name = "Signal",
|
||||||
|
token = "enum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "primary",
|
||||||
|
types = { "screen" },
|
||||||
|
token = "variable",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name = "Field_variable",
|
||||||
|
module_path = "field_variable",
|
||||||
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
global = false,
|
||||||
|
token = "module",
|
||||||
|
}))
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
|
||||||
local basic_nodes <total>: { Node.Token : function(name: string, ...: any): Node } = {
|
local basic_nodes <total>: { Node.Token : function(name: string, ...: any): Node } = {
|
||||||
module = function(name: string, module_path: string): Node
|
module = function(name: string, module_path: string, global: boolean): Node
|
||||||
return {
|
return {
|
||||||
token = "module",
|
token = "module",
|
||||||
|
global = global,
|
||||||
name = name,
|
name = name,
|
||||||
module_path = module_path,
|
module_path = module_path,
|
||||||
dependencies = {},
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
children = {},
|
children = {},
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
record = function(name: string): Node
|
record = function(name: string, global: boolean): Node
|
||||||
return {
|
return {
|
||||||
token = "record",
|
token = "record",
|
||||||
|
global = global,
|
||||||
name = name,
|
name = name,
|
||||||
children = {},
|
children = {},
|
||||||
}
|
}
|
||||||
|
@ -53,6 +56,14 @@ local basic_nodes <total>: { Node.Token : function(name: string, ...: any): Node
|
||||||
return_types = {},
|
return_types = {},
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
|
type = function(name: string, types: { string }, global: boolean): Node
|
||||||
|
return {
|
||||||
|
token = "type",
|
||||||
|
global = global,
|
||||||
|
name = name,
|
||||||
|
types = types,
|
||||||
|
}
|
||||||
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
local function create_node(token: Node.Token, name: string, ...: any): Node
|
local function create_node(token: Node.Token, name: string, ...: any): Node
|
||||||
|
@ -60,6 +71,47 @@ local function create_node(token: Node.Token, name: string, ...: any): Node
|
||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO : be less permissive and allow to merge only module ?
|
||||||
|
local function merge_nodes(node: Node, other: Node): Node
|
||||||
|
if node.token ~= other.token then
|
||||||
|
error("Cannot merge nodes of different types")
|
||||||
|
end
|
||||||
|
if node.name ~= other.name then
|
||||||
|
error("Cannot merge nodes of different names")
|
||||||
|
end
|
||||||
|
if node.module_path ~= other.module_path then
|
||||||
|
error("Cannot merge nodes of different module paths")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Basic fields should be overwritten by the new values
|
||||||
|
-- Teal wants us to use enums value to index a record, but it fails to understand my enum with
|
||||||
|
-- any other key from Node, so I'm forcing it to cooperate for now
|
||||||
|
local enum NodeField
|
||||||
|
"types"
|
||||||
|
end
|
||||||
|
for _, field in ipairs({"global", "types", "parameters", "return_types", "metamethod"}) do
|
||||||
|
local f = field as NodeField
|
||||||
|
node[f] = other[f]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Children should be merged
|
||||||
|
local children: { string : integer } = {}
|
||||||
|
for i, child in ipairs(node.children) do
|
||||||
|
children[child.name] = i
|
||||||
|
end
|
||||||
|
for _, child in ipairs(other.children) do
|
||||||
|
if children[child.name] ~= nil then
|
||||||
|
table.remove(node.children, children[child.name])
|
||||||
|
end
|
||||||
|
table.insert(node.children, child)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Dependencies should be merged
|
||||||
|
for name, path in pairs(other.dependencies) do
|
||||||
|
node.dependencies[name] = path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function iter_children(node: Node): function(): integer, Node
|
local function iter_children(node: Node): function(): integer, Node
|
||||||
if node.children == nil then
|
if node.children == nil then
|
||||||
return function(): integer, Node end
|
return function(): integer, Node end
|
||||||
|
@ -67,6 +119,7 @@ local function iter_children(node: Node): function(): integer, Node
|
||||||
return ipairs(node.children)
|
return ipairs(node.children)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO : deprecate in favor of the iterator definition ?
|
||||||
local function in_order_visitor(node: Node, visitor: function(Node))
|
local function in_order_visitor(node: Node, visitor: function(Node))
|
||||||
for _, child in iter_children(node) do
|
for _, child in iter_children(node) do
|
||||||
in_order_visitor(child, visitor)
|
in_order_visitor(child, visitor)
|
||||||
|
@ -74,8 +127,28 @@ local function in_order_visitor(node: Node, visitor: function(Node))
|
||||||
visitor(node)
|
visitor(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function iter_in_order(node: Node): function(): Node
|
||||||
|
local stack: { Node } = {}
|
||||||
|
|
||||||
|
local function traverse(n: Node)
|
||||||
|
for _, child in iter_children(n) do
|
||||||
|
traverse(child)
|
||||||
|
end
|
||||||
|
table.insert(stack, n)
|
||||||
|
end
|
||||||
|
traverse(node)
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
return function(): Node
|
||||||
|
i = i + 1
|
||||||
|
return stack[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
create_node = create_node,
|
create_node = create_node,
|
||||||
|
merge_nodes = merge_nodes,
|
||||||
iter_children = iter_children,
|
iter_children = iter_children,
|
||||||
in_order_visitor = in_order_visitor,
|
in_order_visitor = in_order_visitor,
|
||||||
|
iter_in_order = iter_in_order,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
local ast = require("awesomewmdtl.ast")
|
||||||
local type Dag = require("awesomewmdtl.types.Dag")
|
local type Dag = require("awesomewmdtl.types.Dag")
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
local utils <const> = require("awesomewmdtl.utils")
|
local utils <const> = require("awesomewmdtl.utils")
|
||||||
|
@ -10,16 +11,90 @@ local function new(): Dag
|
||||||
return dag
|
return dag
|
||||||
end
|
end
|
||||||
|
|
||||||
local function push_module(dag: Dag, module_path: string, root_node: Node)
|
local function push_module(dag: Dag, module_path: string, node: Node)
|
||||||
dag.modules[module_path] = root_node
|
local parent: Node = { children = dag.modules }
|
||||||
|
local current_path = ""
|
||||||
|
for breadcrumb in module_path:gmatch("([^%.]+)") do
|
||||||
|
current_path = current_path == "" and breadcrumb or current_path .. "." .. breadcrumb
|
||||||
|
|
||||||
|
if current_path == node.module_path then
|
||||||
|
local found = utils.find(parent.children, function(n: Node): boolean
|
||||||
|
return n.module_path == node.module_path
|
||||||
|
end)
|
||||||
|
if found then
|
||||||
|
ast.merge_nodes(found, node)
|
||||||
|
else
|
||||||
|
table.insert(parent.children, node)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local current: Node = nil
|
||||||
|
for _, n in ipairs(parent.children) do
|
||||||
|
if n.module_path == current_path then
|
||||||
|
current = n
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if current == nil then
|
||||||
|
current = {
|
||||||
|
children = {},
|
||||||
|
name = utils.capitalize(breadcrumb),
|
||||||
|
module_path = current_path,
|
||||||
|
dependencies = {},
|
||||||
|
descendants = {},
|
||||||
|
token = "module",
|
||||||
|
}
|
||||||
|
push_module(dag, current_path, current)
|
||||||
|
end
|
||||||
|
|
||||||
|
parent = current
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function push_global_nodes(dag: Dag, nodes: { Node })
|
local function push_global_nodes(dag: Dag, nodes: { Node })
|
||||||
utils.spread(dag.global_nodes, nodes)
|
utils.spread(dag.global_nodes, nodes)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function iter_modules(dag: Dag): function(): string, Node
|
local function iter_modules(dag: Dag): (function(): Node)
|
||||||
return pairs(dag.modules)
|
local stack: { Node } = {}
|
||||||
|
for _, root in ipairs(dag.modules) do
|
||||||
|
for node in ast.iter_in_order(root) do
|
||||||
|
if node.token == "module" then
|
||||||
|
table.insert(stack, node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
return function(): Node
|
||||||
|
i = i + 1
|
||||||
|
return stack[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function iter_global_nodes(dag: Dag): (function(): integer, Node)
|
||||||
|
return pairs(dag.global_nodes)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function find_module(dag: Dag, module_path: string): Node
|
||||||
|
local current_path = ""
|
||||||
|
local current: Node = { children = dag.modules }
|
||||||
|
for breadcrumb in module_path:gmatch("([^%.]+)") do
|
||||||
|
current_path = current_path == "" and breadcrumb or current_path .. "." .. breadcrumb
|
||||||
|
for _, child in ipairs(current.children) do
|
||||||
|
if child.module_path == module_path then
|
||||||
|
return child
|
||||||
|
end
|
||||||
|
if child.module_path == current_path then
|
||||||
|
current = child
|
||||||
|
goto continue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
break
|
||||||
|
::continue::
|
||||||
|
end
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -27,4 +102,6 @@ return {
|
||||||
push_module = push_module,
|
push_module = push_module,
|
||||||
push_global_nodes = push_global_nodes,
|
push_global_nodes = push_global_nodes,
|
||||||
iter_modules = iter_modules,
|
iter_modules = iter_modules,
|
||||||
|
iter_global_nodes = iter_global_nodes,
|
||||||
|
find_module = find_module,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,14 @@ local filesystem <const> = require("awesomewmdtl.filesystem")
|
||||||
local printer <const> = require("awesomewmdtl.printer")
|
local printer <const> = require("awesomewmdtl.printer")
|
||||||
local List <const> = require("pl.List")
|
local List <const> = require("pl.List")
|
||||||
local logger <const> = require("awesomewmdtl.logger")
|
local logger <const> = require("awesomewmdtl.logger")
|
||||||
local Map <const> = require("pl.Map")
|
|
||||||
local Module_Info <const> = require("awesomewmdtl.entity.Module_Info")
|
local Module_Info <const> = require("awesomewmdtl.entity.Module_Info")
|
||||||
local module_dependencies <const> = require("awesomewmdtl.visitors.module_dependencies")
|
local module_dependencies <const> = require("awesomewmdtl.visitors.module_dependencies")
|
||||||
|
local module_descendants <const> = require("awesomewmdtl.visitors.module_descendants")
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
local node_fixer <const> = require("awesomewmdtl.visitors.node_fixer")
|
||||||
local property <const> = require("awesomewmdtl.property")
|
local property <const> = require("awesomewmdtl.property")
|
||||||
|
local remove_duplicate_fields <const> = require("awesomewmdtl.visitors.remove_duplicate_fields")
|
||||||
local scraper <const> = require("awesomewmdtl.scraper")
|
local scraper <const> = require("awesomewmdtl.scraper")
|
||||||
local stringx <const> = require("pl.stringx")
|
|
||||||
local type_mapping <const> = require("awesomewmdtl.visitors.type_mapping")
|
local type_mapping <const> = require("awesomewmdtl.visitors.type_mapping")
|
||||||
local utils <const> = require("awesomewmdtl.utils")
|
local utils <const> = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
|
@ -45,53 +46,6 @@ local function module_lists(
|
||||||
return all_module_infos, module_infos, global_module_infos
|
return all_module_infos, module_infos, global_module_infos
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The module's children list produced can contain duplicates.
|
|
||||||
-- We ignore them for now because they are dismissed when building a Map for the printer.
|
|
||||||
local function modules_tree(modules: List<Module_Info.Module_Info>): Map<string, List<string>>
|
|
||||||
local tree: Map<string, List<string>> = Map()
|
|
||||||
for module in modules:iter() do
|
|
||||||
local parent = module.name:gmatch("(.*)%.(.*)$")()
|
|
||||||
if parent then
|
|
||||||
local ancestors = stringx.split(parent, ".")
|
|
||||||
for i = 1, #ancestors - 1 do
|
|
||||||
local ancestor = ancestors:slice(1, i):join(".")
|
|
||||||
if not tree:get(ancestor) then
|
|
||||||
tree:set(ancestor, List())
|
|
||||||
end
|
|
||||||
if not tree:get(ancestor):contains(parent) then
|
|
||||||
tree:get(ancestor):append(parent)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local parent_node = tree:get(parent)
|
|
||||||
if not parent_node then
|
|
||||||
tree:set(parent, List())
|
|
||||||
parent_node = tree:get(parent)
|
|
||||||
end
|
|
||||||
parent_node:append(module.name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return tree
|
|
||||||
end
|
|
||||||
|
|
||||||
--- TODO : rewrite this to use the DAG
|
|
||||||
local function do_module_init_definition(
|
|
||||||
module_infos: List<Module_Info.Module_Info>
|
|
||||||
)
|
|
||||||
local tree = modules_tree(module_infos)
|
|
||||||
for module, children in tree:iter() do
|
|
||||||
-- TODO : this map should be coupled with the all_module_infos list
|
|
||||||
local requires: Map<string, string> = Map()
|
|
||||||
for child in children:iter() do
|
|
||||||
local name = child:gmatch(".*%.(.*)$")()
|
|
||||||
requires:set(name, child)
|
|
||||||
end
|
|
||||||
filesystem.file_writer.write(
|
|
||||||
printer.module_init_definition.generate_teal(requires),
|
|
||||||
property.out_directory .. "/" .. stringx.split(module, "."):slice(1, -1):join("/") .. "/init.d.tl"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- TODO : rewrite the module_info thingy
|
--- TODO : rewrite the module_info thingy
|
||||||
local all_module_infos, module_infos, global_module_infos = module_lists(
|
local all_module_infos, module_infos, global_module_infos = module_lists(
|
||||||
property.base_url .. property.index_uri,
|
property.base_url .. property.index_uri,
|
||||||
|
@ -128,36 +82,102 @@ for module in module_infos:iter() do
|
||||||
dag.push_global_nodes(module_dag, other_nodes)
|
dag.push_global_nodes(module_dag, other_nodes)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Push global nodes to the global module
|
||||||
|
for _, mod in ipairs(property.capi_modules) do
|
||||||
|
local node: Node = nil
|
||||||
|
local index: integer
|
||||||
|
for i, n in ipairs(module_dag.modules) do
|
||||||
|
if n.module_path == mod then
|
||||||
|
node = n
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if node then
|
||||||
|
node.global = true
|
||||||
|
dag.push_global_nodes(module_dag, { node })
|
||||||
|
table.remove(module_dag.modules, index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Run the visitors
|
-- Run the visitors
|
||||||
for _,root in dag.iter_modules(module_dag) do
|
for _,root in dag.iter_global_nodes(module_dag) do
|
||||||
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
|
node_fixer.visit(node, root)
|
||||||
|
end)
|
||||||
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
|
type_mapping.visit(node, true)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
for root in dag.iter_modules(module_dag) do
|
||||||
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
|
remove_duplicate_fields.visit(node)
|
||||||
|
end)
|
||||||
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
|
node_fixer.visit(node, root)
|
||||||
|
end)
|
||||||
ast.in_order_visitor(root, function(node: Node)
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
type_mapping.visit(node)
|
type_mapping.visit(node)
|
||||||
end)
|
end)
|
||||||
ast.in_order_visitor(root, function(node: Node)
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
module_dependencies.visit(node, root, module_dag)
|
module_dependencies.visit(node, root, module_dag)
|
||||||
end)
|
end)
|
||||||
|
ast.in_order_visitor(root, function(node: Node)
|
||||||
|
module_descendants.visit(node)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Build the global module from dag.global_nodes
|
-- Build the global_env_def.d.tl module from module_dag.global_nodes
|
||||||
--- TODO : todo
|
local global_nodes_by_record_kind <const>: { string : { Node } } = {}
|
||||||
|
for _, node in dag.iter_global_nodes(module_dag) do
|
||||||
|
local record_kind = node.name:gmatch("[^%.]*")() -- get the most left part of the lua name path representation
|
||||||
|
if not global_nodes_by_record_kind[record_kind] then
|
||||||
|
global_nodes_by_record_kind[record_kind] = {}
|
||||||
|
end
|
||||||
|
table.insert(global_nodes_by_record_kind[record_kind], node)
|
||||||
|
end
|
||||||
|
local global_module_ast <const> = ast.create_node("module", "global_env_def", "global_env_def", true)
|
||||||
|
-- Declare global types
|
||||||
|
table.insert(global_module_ast.children, ast.create_node("type", "Gears_Shape_Function", { "(function(cr: any, width: integer, height: integer))" }, true))
|
||||||
|
table.insert(global_module_ast.children, ast.create_node("type", "Color", { "any" }, true))
|
||||||
|
table.insert(global_module_ast.children, ast.create_node("type", "Cairo_Surface", { "any" }, true))
|
||||||
|
table.insert(global_module_ast.children, ast.create_node("type", "Cairo_Context", { "any" }, true))
|
||||||
|
table.insert(global_module_ast.children, ast.create_node("type", "Image", { "any" }, true))
|
||||||
|
table.insert(global_module_ast.children, ast.create_node("type", "Awful_Placement_Function", { "function(d: any, args: table)" }, true))
|
||||||
|
for record_kind, nodes in pairs(global_nodes_by_record_kind) do
|
||||||
|
local record_kind_node = ast.create_node("record", record_kind, true)
|
||||||
|
for _, node in ipairs(nodes) do
|
||||||
|
node.name = node.name:gsub(record_kind .. "%.", "")
|
||||||
|
table.insert(record_kind_node.children, node)
|
||||||
|
end
|
||||||
|
table.insert(global_module_ast.children, record_kind_node)
|
||||||
|
end
|
||||||
|
|
||||||
--- TODO : this is fun, but we need to do something with it
|
--- TODO : this is fun, but we need to do something with it
|
||||||
-- Write the DAG to a file
|
-- Write the DAG to a file
|
||||||
-- local inspect = require("inspect")
|
-- local inspect = require("inspect")
|
||||||
-- filesystem.file_writer.write(
|
-- filesystem.file_writer.write(
|
||||||
-- inspect(module_dag, { newline = "\n", indent = " ", depth = 2 }),
|
-- inspect(module_dag, { newline = "\n", indent = " " }),
|
||||||
-- "generated_dag.lua"
|
-- "generated_dag.lua"
|
||||||
-- )
|
-- )
|
||||||
|
|
||||||
log:info("Preprocessing finished")
|
log:info("Preprocessing finished")
|
||||||
|
|
||||||
-- Write modules types definitions to files
|
-- Write modules types definitions to files
|
||||||
for module_path, root in dag.iter_modules(module_dag) do
|
for root in dag.iter_modules(module_dag) do
|
||||||
filesystem.file_writer.write(
|
filesystem.file_writer.write(
|
||||||
printer.teal_type_definition.printer(root),
|
printer.teal_type_definition.printer(root),
|
||||||
property.out_directory .. "/" .. module_path:gsub("%.", "/") .. ".d.tl"
|
property.out_directory .. "/" .. root.module_path:gsub("%.", "/") .. ".d.tl"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
do_module_init_definition(module_infos)
|
|
||||||
|
-- Write global types definition to file
|
||||||
|
filesystem.file_writer.write(
|
||||||
|
printer.teal_type_definition.printer(global_module_ast),
|
||||||
|
property.out_directory .. "/global_env_def.d.tl"
|
||||||
|
)
|
||||||
|
|
||||||
log:info("Module init files generated")
|
log:info("Module init files generated")
|
||||||
|
|
|
@ -6,11 +6,33 @@ local utils = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
local log = logger.log("scraper")
|
local log = logger.log("scraper")
|
||||||
|
|
||||||
local function render_types(types: { string }): string
|
local GEN_TEXT <const> = "-- This file was auto-generated.\n"
|
||||||
|
|
||||||
|
local function render_types(types: { string }, separator: string, with_colon_prefix: boolean): string
|
||||||
if not types or #types == 0 then
|
if not types or #types == 0 then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
return ": " .. table.concat(types, " | ")
|
return string.format(
|
||||||
|
"%s%s",
|
||||||
|
with_colon_prefix and ": " or "",
|
||||||
|
table.concat(types, separator))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function render_function_return_types(types: { { string } }): string
|
||||||
|
if not types or #types == 0 then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local positional_return_types = utils.map(types, function (t: { string }): string
|
||||||
|
return render_types(t, " | ")
|
||||||
|
end)
|
||||||
|
|
||||||
|
return ": " .. table.concat(positional_return_types, ", ")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function render_metamethod_type(metamethod: Node.Metamethod): string
|
||||||
|
-- Node.Metamethod enum matches the metamethods names, so we can simply print them as-is
|
||||||
|
return metamethod
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dedent(str: string): string
|
local function dedent(str: string): string
|
||||||
|
@ -37,30 +59,63 @@ local function render_require(dependencies: { string : string }): string
|
||||||
return generated
|
return generated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function render_descendant(descendants: { string : string }): string
|
||||||
|
local generated = ""
|
||||||
|
for descendant in utils.pairsByKeys(descendants) do
|
||||||
|
generated = generated .. string.format("%s: %s\n", utils.lowercase(descendant), descendant)
|
||||||
|
end
|
||||||
|
return generated
|
||||||
|
end
|
||||||
|
|
||||||
local record Node_Printer_Function
|
local record Node_Printer_Function
|
||||||
on_node: function(node: Node, indent_level: integer): string, integer
|
on_node: function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
before_node: nil | function(node: Node, indent_level: integer): string, integer
|
-- optional functions
|
||||||
after_node: nil | function(node: Node, indent_level: integer): string, integer
|
before_node: function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
|
after_node: function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
end
|
end
|
||||||
|
|
||||||
-- pre-declare functions to prevent forward reference errors
|
-- pre-declare functions to prevent forward reference errors
|
||||||
local print_teal: function(node: Node, indent_level: integer | nil): string
|
local print_teal: function(node: Node, indent_level: integer, parent_node: Node): string
|
||||||
local print_children: function(node: Node): string
|
local print_children: function(node: Node): string
|
||||||
|
|
||||||
local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
||||||
["module"] = {
|
["module"] = {
|
||||||
before_node = function(node: Node, indent_level: integer): string, integer
|
before_node = function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
|
if "module" == parent_token then
|
||||||
|
return "", indent_level
|
||||||
|
end
|
||||||
|
if node.global then
|
||||||
|
return "", indent_level
|
||||||
|
end
|
||||||
return render_code(
|
return render_code(
|
||||||
string.format(
|
string.format(
|
||||||
"-- This file was auto-generated.\n%s\nlocal record %s",
|
"%s%s\nlocal record %s",
|
||||||
render_require(node.dependencies), -- last require statement will have a newline
|
GEN_TEXT,
|
||||||
|
render_require(
|
||||||
|
utils.merge_map(
|
||||||
|
node.dependencies,
|
||||||
|
node.descendants)), -- last require statement will have a newline
|
||||||
node.name),
|
node.name),
|
||||||
indent_level), indent_level + 1
|
indent_level), indent_level + 1
|
||||||
end,
|
end,
|
||||||
on_node = function(node: Node, indent_level: integer): string, integer
|
on_node = function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
return render_code(print_children(node), indent_level), indent_level
|
if "module" == parent_token then
|
||||||
|
return "", indent_level
|
||||||
|
end
|
||||||
|
return render_code(
|
||||||
|
string.format(
|
||||||
|
"%s%s",
|
||||||
|
render_descendant(node.descendants),
|
||||||
|
print_children(node)
|
||||||
|
), indent_level), indent_level
|
||||||
end,
|
end,
|
||||||
after_node = function(node: Node, indent_level: integer): string, integer
|
after_node = function(node: Node, indent_level: integer, parent_token: Node.Token): string, integer
|
||||||
|
if "module" == parent_token then
|
||||||
|
return "", indent_level
|
||||||
|
end
|
||||||
|
if node.global then
|
||||||
|
return "", indent_level
|
||||||
|
end
|
||||||
return render_code("end", indent_level - 1) ..
|
return render_code("end", indent_level - 1) ..
|
||||||
"\n" ..
|
"\n" ..
|
||||||
render_code(
|
render_code(
|
||||||
|
@ -73,7 +128,8 @@ local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
||||||
before_node = function(node: Node, indent_level: integer): string, integer
|
before_node = function(node: Node, indent_level: integer): string, integer
|
||||||
return render_code(
|
return render_code(
|
||||||
string.format(
|
string.format(
|
||||||
"record %s",
|
"%srecord %s",
|
||||||
|
node.global and "\nglobal " or "",
|
||||||
node.name),
|
node.name),
|
||||||
indent_level), indent_level + 1
|
indent_level), indent_level + 1
|
||||||
end,
|
end,
|
||||||
|
@ -110,7 +166,7 @@ local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
||||||
string.format(
|
string.format(
|
||||||
"%s%s",
|
"%s%s",
|
||||||
node.name,
|
node.name,
|
||||||
render_types(node.types)),
|
render_types(node.types, " | ", true)),
|
||||||
indent_level), indent_level
|
indent_level), indent_level
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
@ -125,30 +181,56 @@ local node_printer <total>: { Node.Token : Node_Printer_Function } = {
|
||||||
"%s: function(%s)%s",
|
"%s: function(%s)%s",
|
||||||
node.name,
|
node.name,
|
||||||
table.concat(args, ", "),
|
table.concat(args, ", "),
|
||||||
render_types(node.return_types)),
|
render_function_return_types(node.return_types)
|
||||||
|
),
|
||||||
indent_level), indent_level
|
indent_level), indent_level
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
["metamethod"] = {
|
["metamethod"] = {
|
||||||
on_node = function(): string, integer
|
on_node = function(node: Node, indent_level: integer): string, integer
|
||||||
log:warn("Metamethods are not supported yet")
|
local args = {}
|
||||||
|
for _, parameter in ipairs(node.parameters) do
|
||||||
|
table.insert(args, print_teal(parameter):sub(1, -2)) -- need to remove the newline ending
|
||||||
|
end
|
||||||
|
return render_code(
|
||||||
|
string.format(
|
||||||
|
"metamethod %s: function(%s)%s",
|
||||||
|
render_metamethod_type(node.metamethod),
|
||||||
|
table.concat(args, ", "),
|
||||||
|
render_function_return_types(node.return_types)
|
||||||
|
),
|
||||||
|
indent_level), indent_level
|
||||||
end,
|
end,
|
||||||
}
|
},
|
||||||
|
["type"] = {
|
||||||
|
on_node = function(node: Node, indent_level: integer): string, integer
|
||||||
|
return render_code(
|
||||||
|
string.format(
|
||||||
|
"%stype %s = %s",
|
||||||
|
node.global and "\nglobal " or "",
|
||||||
|
node.name,
|
||||||
|
render_types(node.types, " | ")),
|
||||||
|
indent_level), indent_level
|
||||||
|
end,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function print_teal(node: Node, indent_level: integer | nil): string
|
function print_teal(node: Node,
|
||||||
|
-- optional parameters
|
||||||
|
indent_level: integer, parent_node: Node): string
|
||||||
indent_level = indent_level or 0
|
indent_level = indent_level or 0
|
||||||
|
local parent_node_token = parent_node and parent_node.token
|
||||||
local printer = node_printer[node.token]
|
local printer = node_printer[node.token]
|
||||||
local generated = ""
|
local generated = ""
|
||||||
local full_generated = ""
|
local full_generated = ""
|
||||||
if printer.before_node then
|
if printer.before_node then
|
||||||
generated, indent_level = (printer.before_node as function(Node, integer): string, integer)(node, indent_level)
|
generated, indent_level = printer.before_node(node, indent_level, parent_node_token)
|
||||||
full_generated = generated
|
full_generated = generated
|
||||||
end
|
end
|
||||||
generated, indent_level = printer.on_node(node, indent_level)
|
generated, indent_level = printer.on_node(node, indent_level, parent_node_token)
|
||||||
full_generated = full_generated .. generated
|
full_generated = full_generated .. generated
|
||||||
if printer.after_node then
|
if printer.after_node then
|
||||||
generated, indent_level = (printer.after_node as function(Node, integer): string, integer)(node, indent_level)
|
generated, indent_level = printer.after_node(node, indent_level, parent_node_token)
|
||||||
full_generated = full_generated .. generated
|
full_generated = full_generated .. generated
|
||||||
end
|
end
|
||||||
return full_generated
|
return full_generated
|
||||||
|
@ -157,7 +239,7 @@ end
|
||||||
function print_children(node: Node): string
|
function print_children(node: Node): string
|
||||||
local generated = ""
|
local generated = ""
|
||||||
for _, child in ast.iter_children(node) do
|
for _, child in ast.iter_children(node) do
|
||||||
generated = generated .. print_teal(child)
|
generated = generated .. print_teal(child, 0, node)
|
||||||
end
|
end
|
||||||
return generated
|
return generated
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,16 +18,13 @@ local record Property
|
||||||
end
|
end
|
||||||
|
|
||||||
local property: Property = {
|
local property: Property = {
|
||||||
-- base_url = "https://awesomewm.org/apidoc",
|
base_url = "https://awesomewm.org/apidoc",
|
||||||
-- base_url = "file:///usr/share/doc/awesome/doc",
|
-- base_url = "file:///usr/share/doc/awesome/doc",
|
||||||
base_url = "file:///home/aireone/documents/prog/awesome/build/doc",
|
|
||||||
index_uri = "/index.html",
|
index_uri = "/index.html",
|
||||||
out_directory = "generated",
|
out_directory = "generated",
|
||||||
capi_modules = {
|
capi_modules = {
|
||||||
"awesome",
|
"awesome",
|
||||||
"client and awful.client",
|
"drawable",
|
||||||
"screen and awful.screen",
|
|
||||||
"tag and awful.tag",
|
|
||||||
},
|
},
|
||||||
ignored_modules = {
|
ignored_modules = {
|
||||||
-- Sample files
|
-- Sample files
|
||||||
|
@ -35,33 +32,33 @@ local property: Property = {
|
||||||
"theme.lua",
|
"theme.lua",
|
||||||
|
|
||||||
-- Utility libraries
|
-- Utility libraries
|
||||||
"gears.debug",
|
-- "gears.debug",
|
||||||
"gears.filesystem",
|
-- "gears.filesystem",
|
||||||
"gears.geometry",
|
-- "gears.geometry",
|
||||||
"gears.math",
|
-- "gears.math",
|
||||||
"gears.object",
|
-- "gears.object",
|
||||||
"gears.protected_call",
|
-- "gears.protected_call",
|
||||||
"gears.sort",
|
-- "gears.sort",
|
||||||
"gears.string",
|
-- "gears.string",
|
||||||
"gears.table",
|
-- "gears.table",
|
||||||
"gears.wallpaper",
|
-- "gears.wallpaper",
|
||||||
|
|
||||||
-- Theme related libraries
|
-- Theme related libraries
|
||||||
"beautiful",
|
-- "beautiful",
|
||||||
"gears.color",
|
"gears.color",
|
||||||
"gears.shape",
|
-- "gears.shape",
|
||||||
|
|
||||||
-- Classes
|
-- Classes
|
||||||
"awful.widget.common",
|
-- "awful.widget.common",
|
||||||
"gears.cache",
|
-- "gears.cache",
|
||||||
"gears.matrix",
|
-- "gears.matrix",
|
||||||
"menubar.icon_theme",
|
-- "menubar.icon_theme",
|
||||||
"menubar.index_theme",
|
-- "menubar.index_theme",
|
||||||
"signals",
|
-- "signals",
|
||||||
"wibox.drawable",
|
-- "wibox.drawable",
|
||||||
"wibox.hierarchy",
|
-- "wibox.hierarchy",
|
||||||
"wibox.widget.base",
|
-- "wibox.widget.base",
|
||||||
"xproperties",
|
-- "xproperties",
|
||||||
|
|
||||||
-- Documentation
|
-- Documentation
|
||||||
"Authors",
|
"Authors",
|
||||||
|
|
|
@ -18,7 +18,11 @@ local function parse_parameter_types(parameter_type: string): { string }
|
||||||
end
|
end
|
||||||
|
|
||||||
local types = {}
|
local types = {}
|
||||||
for t in stringx.split(parameter_type, " or "):iter() do
|
for t in stringx.split(parameter_type)
|
||||||
|
:filter(
|
||||||
|
function(s: string): boolean
|
||||||
|
return s ~= "or" and s ~= ","
|
||||||
|
end):iter() do
|
||||||
table.insert(types, t)
|
table.insert(types, t)
|
||||||
end
|
end
|
||||||
return types
|
return types
|
||||||
|
@ -30,7 +34,7 @@ local function extract_item_name(item_name_node: scan.HTMLNode): string, string
|
||||||
end
|
end
|
||||||
local module_name_node <const> = scraper_utils.find(item_name_node:outer_html(), "span.function_modname")[1]
|
local module_name_node <const> = scraper_utils.find(item_name_node:outer_html(), "span.function_modname")[1]
|
||||||
local module_name = module_name_node and module_name_node:inner_text():gsub("[%.:]$", "")
|
local module_name = module_name_node and module_name_node:inner_text():gsub("[%.:]$", "")
|
||||||
local name <const> = item_name_node:inner_text():gsub("^.*[%.:](.+)%s*[%(%{].*[%)%}]", "%1")
|
local name <const> = item_name_node:inner_text():gsub("(.+)[%(%{].*$", "%1"):gsub("^.*[%.:](.+)", "%1")
|
||||||
return utils.sanitize_string(name), module_name and utils.sanitize_string(module_name) or nil
|
return utils.sanitize_string(name), module_name and utils.sanitize_string(module_name) or nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -50,6 +54,12 @@ local function extract_function_parameters(table_html: string, function_name: st
|
||||||
local name <const> = extract_node_text(name_node)
|
local name <const> = extract_node_text(name_node)
|
||||||
local types <const> = parse_parameter_types(extract_node_text(types_node))
|
local types <const> = parse_parameter_types(extract_node_text(types_node))
|
||||||
|
|
||||||
|
-- If the name contains a dot, then it's a nested field in a table
|
||||||
|
-- We don't support this yet, so we just ignore it
|
||||||
|
if name:match("%.") then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
-- Add a field to the current parameter type record
|
-- Add a field to the current parameter type record
|
||||||
if tr.attr ~= nil and tr.attr.class == "see_also_sublist" and is_populating_parameters_types then
|
if tr.attr ~= nil and tr.attr.class == "see_also_sublist" and is_populating_parameters_types then
|
||||||
local field = ast.create_node("variable", name)
|
local field = ast.create_node("variable", name)
|
||||||
|
@ -77,7 +87,7 @@ local function extract_function_parameters(table_html: string, function_name: st
|
||||||
"%s_%s",
|
"%s_%s",
|
||||||
utils.capitalize(function_name),
|
utils.capitalize(function_name),
|
||||||
utils.capitalize(name))
|
utils.capitalize(name))
|
||||||
table.insert(parameters_types, ast.create_node("record", record_name))
|
table.insert(parameters_types, ast.create_node("record", record_name, false))
|
||||||
is_populating_parameters_types = true
|
is_populating_parameters_types = true
|
||||||
field.types = { record_name }
|
field.types = { record_name }
|
||||||
end
|
end
|
||||||
|
@ -93,8 +103,21 @@ local function extract_function_parameters(table_html: string, function_name: st
|
||||||
return parameters, parameters_types
|
return parameters, parameters_types
|
||||||
end
|
end
|
||||||
|
|
||||||
local function extract_function_return_types(ol_html: string): { string }
|
local function extract_function_return_types(ol_html: string): { { string } }
|
||||||
return scraper_utils.scrape(ol_html, "span.types .type", extract_node_text)
|
local positional_return_types = scraper_utils.find(
|
||||||
|
ol_html,
|
||||||
|
"span.types")
|
||||||
|
|
||||||
|
local types: { { string } } = {}
|
||||||
|
for _,prt in ipairs(positional_return_types) do
|
||||||
|
local ts: { string } = {}
|
||||||
|
local union_types = scraper_utils.scrape(prt:outer_html(), ".type", extract_node_text)
|
||||||
|
for _,t in ipairs(union_types) do
|
||||||
|
table.insert(ts, t)
|
||||||
|
end
|
||||||
|
table.insert(types, ts)
|
||||||
|
end
|
||||||
|
return types
|
||||||
end
|
end
|
||||||
|
|
||||||
local function extract_property_constraints(property_constraint_node: scan.HTMLNode): { string }
|
local function extract_property_constraints(property_constraint_node: scan.HTMLNode): { string }
|
||||||
|
@ -151,11 +174,11 @@ local function extract_section_functions(dl: string, module_name: string | nil):
|
||||||
return functions, other_functions
|
return functions, other_functions
|
||||||
end
|
end
|
||||||
|
|
||||||
local function extract_section_variables(dl: string): { Node }, { string }
|
local function extract_section_variables(dl: string, with_constraint: boolean): { Node }, { string }
|
||||||
local query_selectors <const>: { string : string } = {
|
local query_selectors <const>: { string : string } = {
|
||||||
variable_name = "dt strong",
|
variable_name = "dt strong",
|
||||||
variable_summary_type = "dt span.summary_type",
|
variable_summary_type = "dt span.summary_type",
|
||||||
variable_property_constraint = "dd span.property_type",
|
variable_property_constraint = with_constraint and "dd span.property_type",
|
||||||
}
|
}
|
||||||
|
|
||||||
local variables <const>: { Node } = {}
|
local variables <const>: { Node } = {}
|
||||||
|
@ -171,11 +194,13 @@ local function extract_section_variables(dl: string): { Node }, { string }
|
||||||
if #node.types == 1 and node.types[1] == "string" then
|
if #node.types == 1 and node.types[1] == "string" then
|
||||||
log:debug("extract variable string with constraints, this is an enum", { name = node.name })
|
log:debug("extract variable string with constraints, this is an enum", { name = node.name })
|
||||||
local type_enum <const> = ast.create_node("enum", utils.capitalize(node.name))
|
local type_enum <const> = ast.create_node("enum", utils.capitalize(node.name))
|
||||||
for _, constraint in ipairs(extract_property_constraints(nodes[query_selectors.variable_property_constraint])) do
|
if with_constraint then
|
||||||
table.insert(
|
for _, constraint in ipairs(extract_property_constraints(nodes[query_selectors.variable_property_constraint])) do
|
||||||
type_enum.children,
|
table.insert(
|
||||||
ast.create_node("identifier", (constraint:gsub(""", "")))
|
type_enum.children,
|
||||||
)
|
ast.create_node("identifier", (constraint:gsub(""", "")))
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if #type_enum.children == 0 then
|
if #type_enum.children == 0 then
|
||||||
log:debug("Enum has no children, get back to variable", { name = node.name })
|
log:debug("Enum has no children, get back to variable", { name = node.name })
|
||||||
|
@ -198,9 +223,21 @@ local function extract_section_signal(dl: string): { string }
|
||||||
return scraper_utils.scrape(dl, selector, extract_node_text)
|
return scraper_utils.scrape(dl, selector, extract_node_text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function add_self_parameter(function_node: Node, record_name: string)
|
||||||
|
local self_parameter = ast.create_node("variable", "self")
|
||||||
|
self_parameter.types = { record_name }
|
||||||
|
table.insert(function_node.parameters, 1, self_parameter)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function transform_to_call_metamethod(function_node: Node)
|
||||||
|
function_node.token = "metamethod"
|
||||||
|
function_node.metamethod = "__call"
|
||||||
|
end
|
||||||
|
|
||||||
local enum Section
|
local enum Section
|
||||||
"Constructors"
|
"Constructors"
|
||||||
"Static module functions"
|
"Static module functions"
|
||||||
|
"Fields"
|
||||||
"Object properties"
|
"Object properties"
|
||||||
"Object methods"
|
"Object methods"
|
||||||
"Signals"
|
"Signals"
|
||||||
|
@ -211,11 +248,12 @@ end
|
||||||
-- - Nodes that should be added to the global scope
|
-- - Nodes that should be added to the global scope
|
||||||
-- - Strings that should be added to the record Signals
|
-- - Strings that should be added to the record Signals
|
||||||
local section_scrapers <total>: { Section : function(html: string, record_name: string, module_name: string): { Node }, { Node }, { string } } = {
|
local section_scrapers <total>: { Section : function(html: string, record_name: string, module_name: string): { Node }, { Node }, { string } } = {
|
||||||
["Constructors"] = function(html: string): { Node }, { Node }, { string }
|
["Constructors"] = function(html: string, record_name: string): { Node }, { Node }, { string }
|
||||||
local constructors <const> = extract_section_functions(html)
|
local constructors <const> = extract_section_functions(html)
|
||||||
for _, constructor in ipairs(constructors) do
|
for _, constructor in ipairs(constructors) do
|
||||||
if constructor.token == "function" then
|
if constructor.token == "function" and constructor.name == utils.lowercase(record_name) then
|
||||||
constructor.name = "new"
|
add_self_parameter(constructor, record_name)
|
||||||
|
transform_to_call_metamethod(constructor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return constructors, {}, {}
|
return constructors, {}, {}
|
||||||
|
@ -224,17 +262,19 @@ local section_scrapers <total>: { Section : function(html: string, record_name:
|
||||||
local static_functions, other_functions = extract_section_functions(html, module_name)
|
local static_functions, other_functions = extract_section_functions(html, module_name)
|
||||||
return static_functions, other_functions, {}
|
return static_functions, other_functions, {}
|
||||||
end,
|
end,
|
||||||
|
["Fields"] = function(html: string): { Node }, { Node }, { string }
|
||||||
|
local fields = extract_section_variables(html)
|
||||||
|
return fields, {}, {}
|
||||||
|
end,
|
||||||
["Object properties"] = function(html: string): { Node }, { Node }, { string }
|
["Object properties"] = function(html: string): { Node }, { Node }, { string }
|
||||||
local properties, signals = extract_section_variables(html)
|
local properties, signals = extract_section_variables(html, true)
|
||||||
return properties, {}, signals
|
return properties, {}, signals
|
||||||
end,
|
end,
|
||||||
["Object methods"] = function(html: string, record_name: string): { Node }, { Node }, { string }
|
["Object methods"] = function(html: string, record_name: string): { Node }, { Node }, { string }
|
||||||
local methods <const> = extract_section_functions(html)
|
local methods <const> = extract_section_functions(html)
|
||||||
for _, method in ipairs(methods) do
|
for _, method in ipairs(methods) do
|
||||||
if method.token == "function" then
|
if method.token == "function" then
|
||||||
local self_parameter = ast.create_node("variable", "self")
|
add_self_parameter(method, record_name)
|
||||||
self_parameter.types = { record_name }
|
|
||||||
table.insert(method.parameters, 1, self_parameter)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return methods, {}, {}
|
return methods, {}, {}
|
||||||
|
@ -257,12 +297,14 @@ function module.get_doc_from_page(html: string, module_path: string): Node, { No
|
||||||
"dl.function",
|
"dl.function",
|
||||||
})
|
})
|
||||||
|
|
||||||
if #html_nodes:get "h2.section-header" ~= #html_nodes:get "dl.function" then
|
if #html_nodes:get("h2.section-header") ~= #html_nodes:get("dl.function") then
|
||||||
error "The list aren't the same size!"
|
error "The list aren't the same size!"
|
||||||
end
|
end
|
||||||
|
|
||||||
local record_name <const> = utils.capitalize((module_path:gsub(".*%.", "")))
|
-- Awesome is a special case, we don't want to capitalize it.
|
||||||
local module_root <const> = ast.create_node("module", record_name, module_path)
|
-- I'm too lazy to make a special case for it because this project is in development for far too long and it's getting depressing
|
||||||
|
local record_name <const> = module_path == "awesome" and "awesome" or utils.capitalize((module_path:gsub(".*%.", "")))
|
||||||
|
local module_root <const> = ast.create_node("module", record_name, module_path, false)
|
||||||
local other_nodes <const>: { Node } = {}
|
local other_nodes <const>: { Node } = {}
|
||||||
|
|
||||||
local module_signals_node <const> = ast.create_node("enum", "Signal")
|
local module_signals_node <const> = ast.create_node("enum", "Signal")
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
|
||||||
local record Dag
|
local record Dag
|
||||||
modules: { string : Node } -- module_path (AKA "full name" `package.module.name`) -> root_node (token = "module")
|
modules: { Node } -- list of root modules
|
||||||
global_nodes: { Node }
|
global_nodes: { Node }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ local record Node
|
||||||
"variable"
|
"variable"
|
||||||
"function"
|
"function"
|
||||||
"metamethod"
|
"metamethod"
|
||||||
|
"type"
|
||||||
end
|
end
|
||||||
token: Token
|
token: Token
|
||||||
name: string
|
name: string
|
||||||
|
@ -14,16 +15,26 @@ local record Node
|
||||||
-- for "module", "record", "enum"
|
-- for "module", "record", "enum"
|
||||||
children: { Node }
|
children: { Node }
|
||||||
|
|
||||||
-- for "variable"
|
-- for "variable" and "type"
|
||||||
types: { string }
|
types: { string }
|
||||||
|
|
||||||
-- for "function" and "metamethod"
|
-- for "function" and "metamethod"
|
||||||
parameters: { Node }
|
parameters: { Node }
|
||||||
return_types: { string }
|
return_types: { { string } }
|
||||||
|
|
||||||
|
-- for "methamethod"
|
||||||
|
enum Metamethod
|
||||||
|
"__call"
|
||||||
|
end
|
||||||
|
metamethod: Metamethod
|
||||||
|
|
||||||
-- for "module"
|
-- for "module"
|
||||||
module_path: string
|
module_path: string
|
||||||
dependencies: { string : string } -- module_name -> module_path
|
dependencies: { string : string } -- module_name -> module_path
|
||||||
|
descendants: { string : string } -- modules in children that should be written in the final type definition. module_name -> module_path
|
||||||
|
|
||||||
|
-- for "module", "record", "type"
|
||||||
|
global: boolean
|
||||||
end
|
end
|
||||||
|
|
||||||
return Node
|
return Node
|
||||||
|
|
|
@ -13,6 +13,16 @@ function utils.has_item(t: table, item: any): any
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function utils.find<T>(list: { T }, predicate: function(value: T, position: integer): boolean): T, integer
|
||||||
|
for position, value in ipairs(list) do
|
||||||
|
if predicate(value, position) then
|
||||||
|
return value, position
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
function utils.filter<T>(list: { T }, predicate: function(value: T, position: integer): boolean): { T }
|
function utils.filter<T>(list: { T }, predicate: function(value: T, position: integer): boolean): { T }
|
||||||
local filtered: { T } = {}
|
local filtered: { T } = {}
|
||||||
|
|
||||||
|
@ -101,4 +111,27 @@ function utils.pairsByKeys<Key, Value>(list: { Key : Value }, comp: function(Key
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- We expect the user to type at the call site
|
||||||
|
function utils.pipe(...: function): function(...: any): any...
|
||||||
|
local funcs = { ... }
|
||||||
|
return function(...: any): any...
|
||||||
|
local res = ...
|
||||||
|
for _, f in ipairs(funcs) do
|
||||||
|
res = f(res)
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.merge_map<T, U>(t1: { T : U }, t2: { T : U }): { T : U }
|
||||||
|
local merged: { T : U } = {}
|
||||||
|
for k, v in pairs(t1) do
|
||||||
|
merged[k] = v
|
||||||
|
end
|
||||||
|
for k, v in pairs(t2) do
|
||||||
|
merged[k] = v
|
||||||
|
end
|
||||||
|
return merged
|
||||||
|
end
|
||||||
|
|
||||||
return utils
|
return utils
|
||||||
|
|
|
@ -1,9 +1,31 @@
|
||||||
local type Dag = require("awesomewmdtl.types.Dag")
|
local type Dag = require("awesomewmdtl.types.Dag")
|
||||||
|
local dag = require("awesomewmdtl.dag")
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
local utils <const> = require("awesomewmdtl.utils")
|
local utils <const> = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
local spread = utils.spread
|
local spread = utils.spread
|
||||||
|
|
||||||
|
-- Very hacky way to get the module path of a capi class
|
||||||
|
-- We shouldn't rely on partial record for Node
|
||||||
|
local capi_class <const>: { string : Node } = {
|
||||||
|
Client = {
|
||||||
|
name = "Client",
|
||||||
|
module_path = "awful.client",
|
||||||
|
},
|
||||||
|
Layout = {
|
||||||
|
name = "Layout",
|
||||||
|
module_path = "awful.layout",
|
||||||
|
},
|
||||||
|
Screen = {
|
||||||
|
name = "Screen",
|
||||||
|
module_path = "awful.screen",
|
||||||
|
},
|
||||||
|
Tag = {
|
||||||
|
name = "Tag",
|
||||||
|
module_path = "awful.tag",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
local function get_all_types_in_node(node: Node): { string }
|
local function get_all_types_in_node(node: Node): { string }
|
||||||
local parameters_types = {}
|
local parameters_types = {}
|
||||||
if node.parameters then
|
if node.parameters then
|
||||||
|
@ -11,11 +33,17 @@ local function get_all_types_in_node(node: Node): { string }
|
||||||
spread(parameters_types, v.types)
|
spread(parameters_types, v.types)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local return_types = {}
|
||||||
|
if node.return_types then
|
||||||
|
for _, rts in ipairs(node.return_types) do
|
||||||
|
spread(return_types, rts)
|
||||||
|
end
|
||||||
|
end
|
||||||
return spread(
|
return spread(
|
||||||
{},
|
{},
|
||||||
node.types or {},
|
node.types or {},
|
||||||
node.return_types or {},
|
return_types,
|
||||||
parameters_types or {})
|
parameters_types)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function replace_in_node_type(node: Node, old_type: string, new_type: string)
|
local function replace_in_node_type(node: Node, old_type: string, new_type: string)
|
||||||
|
@ -38,9 +66,11 @@ local function replace_in_node_type(node: Node, old_type: string, new_type: stri
|
||||||
end
|
end
|
||||||
|
|
||||||
if node.return_types then
|
if node.return_types then
|
||||||
for i, t in ipairs(node.return_types) do
|
for i, rt in ipairs(node.return_types) do
|
||||||
if t == old_type then
|
for j, t in ipairs(rt) do
|
||||||
node.return_types[i] = new_type
|
if t == old_type then
|
||||||
|
node.return_types[i][j] = new_type
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -56,10 +86,24 @@ function Module_Dependencies.visit(node: Node, mod: Node, d: Dag)
|
||||||
if type_name == mod.name then
|
if type_name == mod.name then
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
|
if utils.has_item({
|
||||||
|
"any",
|
||||||
|
"number",
|
||||||
|
"integer",
|
||||||
|
"string",
|
||||||
|
"boolean",
|
||||||
|
"function",
|
||||||
|
"nil",
|
||||||
|
"table",
|
||||||
|
}, type_name) then
|
||||||
|
goto continue
|
||||||
|
end
|
||||||
|
|
||||||
local dependency = d.modules[type_name] or d.modules[utils.lowercase(type_name)]
|
local dependency = dag.find_module(d, type_name) or capi_class[type_name]
|
||||||
if dependency then
|
if dependency then
|
||||||
mod.dependencies[dependency.name] = dependency.module_path
|
if dependency.name ~= mod.name then
|
||||||
|
mod.dependencies[dependency.name] = dependency.module_path
|
||||||
|
end
|
||||||
replace_in_node_type(node, dependency.module_path, dependency.name)
|
replace_in_node_type(node, dependency.module_path, dependency.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
local utils = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
|
local capitalize = utils.capitalize
|
||||||
|
|
||||||
|
local function get_descendants_module(node: Node): { string : string }
|
||||||
|
local descendants_by_name: { string : string } = {}
|
||||||
|
|
||||||
|
for _, descendant in ipairs(node.children) do
|
||||||
|
if descendant.token == "module" then
|
||||||
|
descendants_by_name[descendant.name] = descendant.module_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return descendants_by_name
|
||||||
|
end
|
||||||
|
|
||||||
|
local record Module_Descendants
|
||||||
|
visit: function(node: Node)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Module_Descendants.visit(node: Node)
|
||||||
|
if node.token ~= "module" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local descendants_by_name = get_descendants_module(node)
|
||||||
|
|
||||||
|
for _, descendant in ipairs(node.children) do
|
||||||
|
if descendant.token ~= "module" and descendants_by_name[capitalize(descendant.name)] then
|
||||||
|
descendants_by_name[capitalize(descendant.name)] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
node.descendants = descendants_by_name
|
||||||
|
end
|
||||||
|
|
||||||
|
return Module_Descendants
|
|
@ -0,0 +1,148 @@
|
||||||
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
|
||||||
|
-- Teal can't define nested Map types yet, so we have to define a type for the nested map.
|
||||||
|
local type New_Node_By_Name = { string : Node }
|
||||||
|
|
||||||
|
-- This is a map of module paths to a map of node names to a map of node keys to new values.
|
||||||
|
-- This is used to fix nodes where either
|
||||||
|
-- - Teal doesn't have a proper way to handle the types
|
||||||
|
-- - The Awesome API is too confusing to be translated to Teal
|
||||||
|
|
||||||
|
-- EVERYTHING IN HERE IS TEMPORARY AND SHOULD BE REMOVED!
|
||||||
|
-- EVERYTHING IN HERE IS TEMPORARY AND SHOULD BE REMOVED!
|
||||||
|
-- EVERYTHING IN HERE IS TEMPORARY AND SHOULD BE REMOVED!
|
||||||
|
|
||||||
|
local node_fixer <const>: { string : New_Node_By_Name } = {
|
||||||
|
["awful.titlebar"] = {
|
||||||
|
new = {
|
||||||
|
return_types = { { "Titlebar" } }, -- The Awesome APIDoc have to updated
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["awful.widget.prompt"] = {
|
||||||
|
set_shape = {
|
||||||
|
parameters = {
|
||||||
|
{ token = "variable", name = "self", types = { "Prompt" } },
|
||||||
|
{ token = "variable", name = "shape", types = { "Gears_Shape_Function" } }, -- cannot discriminate a union between multiple function types: Gears_Shape_Function | function(...: <any type>): <any type>...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["gears.filesystem"] = {
|
||||||
|
get_themes_dir = {
|
||||||
|
return_types = { { "string" } }, -- The Awesome APIDoc have to updated
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["gears.string"] = {
|
||||||
|
split = { -- psplit is documented as split in the APIDoc
|
||||||
|
parameters = {
|
||||||
|
{ token = "variable", name = "s", types = { "string" } },
|
||||||
|
{ token = "variable", name = "sep", types = { "string" } }, -- psplit optional parameter breaks the parser
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["gears.surface"] = {
|
||||||
|
apply_shape_bounding = {
|
||||||
|
parameters = {
|
||||||
|
{ token = "variable", name = "draw", types = { "any" } },
|
||||||
|
{ token = "variable", name = "shape", types = { "Gears_Shape_Function" } },
|
||||||
|
{ token = "variable", name = "...", types = { "any" } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["naughty.widget.background"] = {
|
||||||
|
set_shape = {
|
||||||
|
parameters = {
|
||||||
|
{ token = "variable", name = "self", types = { "Background" } },
|
||||||
|
{ token = "variable", name = "shape", types = { "Gears_Shape_Function" } }, -- cannot discriminate a union between multiple function types: Gears_Shape_Function | function
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["wibox.container.background"] = {
|
||||||
|
background = {
|
||||||
|
parameters = {
|
||||||
|
{ token = "variable", name = "self", types = { "Background" } },
|
||||||
|
{ token = "variable", name = "widget", types = { "Widget" } },
|
||||||
|
{ token = "variable", name = "bg", types = { "Color" } },
|
||||||
|
{ token = "variable", name = "shape", types = { "Gears_Shape_Function" } }, -- cannot discriminate a union between multiple function types: Gears_Shape_Function | function
|
||||||
|
},
|
||||||
|
},
|
||||||
|
set_shape = {
|
||||||
|
parameters = {
|
||||||
|
{ token = "variable", name = "self", types = { "Background" } },
|
||||||
|
{ token = "variable", name = "shape", types = { "Gears_Shape_Function" } }, -- cannot discriminate a union between multiple function types: Gears_Shape_Function | function(...: <any type>): <any type>
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["wibox.container.tile"] = {
|
||||||
|
Tile_Args = {
|
||||||
|
children = { -- widget is documented twice in the APIDoc
|
||||||
|
{
|
||||||
|
name = "widget",
|
||||||
|
token = "variable",
|
||||||
|
types = { "Widget" }
|
||||||
|
}, {
|
||||||
|
name = "halign",
|
||||||
|
token = "variable",
|
||||||
|
types = { "string" }
|
||||||
|
}, {
|
||||||
|
name = "valign",
|
||||||
|
token = "variable",
|
||||||
|
types = { "string" }
|
||||||
|
}, {
|
||||||
|
name = "horizontal_spacing",
|
||||||
|
token = "variable",
|
||||||
|
types = { "number" }
|
||||||
|
}, {
|
||||||
|
name = "vertical_spacing",
|
||||||
|
token = "variable",
|
||||||
|
types = { "number" }
|
||||||
|
}, {
|
||||||
|
name = "horizontal_crop",
|
||||||
|
token = "variable",
|
||||||
|
types = { "boolean" }
|
||||||
|
}, {
|
||||||
|
name = "vertical_crop",
|
||||||
|
token = "variable",
|
||||||
|
types = { "boolean" }
|
||||||
|
}, {
|
||||||
|
name = "tiled",
|
||||||
|
token = "variable",
|
||||||
|
types = { "boolean" }
|
||||||
|
}, {
|
||||||
|
name = "fill_vertical",
|
||||||
|
token = "variable",
|
||||||
|
types = { "boolean" }
|
||||||
|
}, {
|
||||||
|
name = "fill_horizontal",
|
||||||
|
token = "variable",
|
||||||
|
types = { "boolean" }
|
||||||
|
}, {
|
||||||
|
name = "content_fill_vertical",
|
||||||
|
token = "variable",
|
||||||
|
types = { "boolean" }
|
||||||
|
}, {
|
||||||
|
name = "content_fill_horizontal",
|
||||||
|
token = "variable",
|
||||||
|
types = { "boolean" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local record Node_Fixer
|
||||||
|
visit: function(node: Node, mod: Node)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Node_Fixer.visit(node: Node, mod: Node)
|
||||||
|
if not (node_fixer[mod.module_path] and node_fixer[mod.module_path][node.name]) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(node_fixer[mod.module_path][node.name] as { string : any }) do
|
||||||
|
-- Teal can't index `node` with our k,v
|
||||||
|
local n <const> = node as { string : any }
|
||||||
|
n[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Node_Fixer
|
|
@ -0,0 +1,31 @@
|
||||||
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
local utils <const> = require("awesomewmdtl.utils")
|
||||||
|
|
||||||
|
local has_item <const> = utils.has_item
|
||||||
|
|
||||||
|
-- This is quick hack to remove duplicate fields from a module
|
||||||
|
-- We can have duplicated fields in a module, because we currently
|
||||||
|
-- don't make difference between module record and instance record.
|
||||||
|
-- So static module fields and instance level fields are mixed together.
|
||||||
|
|
||||||
|
local record Remove_Duplicate_Fields
|
||||||
|
visit: function(node: Node)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Remove_Duplicate_Fields.visit(node: Node)
|
||||||
|
if node.token ~= "module" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local fields: { string } = {}
|
||||||
|
|
||||||
|
for i, n in ipairs(node.children) do
|
||||||
|
if has_item(fields, n.name) then
|
||||||
|
table.remove(node.children, i)
|
||||||
|
else
|
||||||
|
table.insert(fields, n.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Remove_Duplicate_Fields
|
|
@ -1,31 +1,60 @@
|
||||||
local type Node = require("awesomewmdtl.types.Node")
|
local type Node = require("awesomewmdtl.types.Node")
|
||||||
|
|
||||||
-- Special types I don't want to deal with for now
|
|
||||||
local gears_shape_function = "function(cr: any, width: integer, height: integer)"
|
|
||||||
|
|
||||||
local type_map <const>: { string : string } = {
|
local type_map <const>: { string : string } = {
|
||||||
awesome = "Awesome",
|
Awesome = "awesome",
|
||||||
bool = "boolean",
|
bool = "boolean",
|
||||||
|
["surface._native"] = "Cairo_Surface",
|
||||||
|
cairo_context = "Cairo_Context",
|
||||||
|
["cairo.surface"] = "Cairo_Surface",
|
||||||
|
color = "Color",
|
||||||
client = "Client",
|
client = "Client",
|
||||||
["gears.shape"] = gears_shape_function,
|
drawable = "Drawable",
|
||||||
["gears.surface"] = "Surface",
|
["gears.shape"] = "Gears_Shape_Function",
|
||||||
|
["gears.surface"] = "Cairo_Surface",
|
||||||
|
["Gio.InputStream"] = "any", -- We'll probably never have better support for this one, since it's a GI bindings
|
||||||
image = "Image",
|
image = "Image",
|
||||||
int = "integer",
|
int = "integer",
|
||||||
|
Integer = "integer",
|
||||||
|
keygrabber = "Keygrabber",
|
||||||
|
layout = "Layout",
|
||||||
|
["lgi.Pango.FontDescription"] = "any", -- We'll probably never have better support for this one, since it's a GI bindings
|
||||||
|
matrix = "Matrix",
|
||||||
|
["naughty.notification_closed_reason"] = "number", -- Teal doesn't support numeric enums
|
||||||
|
["Pango.FontDescription"] = "any", -- We'll probably never have better support for this one, since it's a GI bindings
|
||||||
|
placement = "Awful_Placement_Function",
|
||||||
|
raw_surface = "Cairo_Surface",
|
||||||
screen = "Screen",
|
screen = "Screen",
|
||||||
shape = gears_shape_function,
|
shape = "Gears_Shape_Function",
|
||||||
surface = "Surface",
|
surface = "Cairo_Surface",
|
||||||
tag = "Tag",
|
tag = "Tag",
|
||||||
|
template = "table",
|
||||||
|
["true"] = "boolean", -- Either Teal should support literal types or maybe Awesome should use booleans instead of true
|
||||||
|
["wibox.container"] = "table",
|
||||||
|
["wibox.drawable"] = "Drawable",
|
||||||
|
["wibox.layout"] = "table",
|
||||||
widget = "wibox.widget",
|
widget = "wibox.widget",
|
||||||
|
|
||||||
-- fixes we shouldn't have to do (We need to PR Awesome to fix the doc)
|
-- fixes we shouldn't have to do (We need to PR Awesome to fix the doc)
|
||||||
timer = "gears.timer",
|
font = "string", -- doesn't exist
|
||||||
|
func = "function", -- doesn't exist
|
||||||
|
["gears.color"] = "any", -- shouldn't be here
|
||||||
|
["gears.opacity"] = "number", -- error in the naughty.notification doc
|
||||||
|
["gears.margin"] = "number", -- error in the naughty.notification doc
|
||||||
|
gradient = "string", -- doesn't exist
|
||||||
|
["N/A"] = "any", -- we shouldn't have to do this, what `N/A` supposed to mean?
|
||||||
|
pattern = "string", -- doesn't exist
|
||||||
|
raw_curface = "Cairo_Surface", -- typo
|
||||||
|
shap = "Gears_Shape_Function", -- typo
|
||||||
|
tale = "table", -- typo
|
||||||
|
timer = "gears.timer", -- not resolvable
|
||||||
}
|
}
|
||||||
|
|
||||||
local function get_type(t: string): string
|
local global_type_map <const>: { string : string } = {
|
||||||
return type_map[t] or t
|
screen = "screen", -- global env cannot come from another module
|
||||||
end
|
}
|
||||||
|
|
||||||
local function check_node(node: Node)
|
|
||||||
|
local function check_node(node: Node, get_type: function(string): string)
|
||||||
if not node.types then
|
if not node.types then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -35,34 +64,42 @@ local function check_node(node: Node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function check_function_parameters(node: Node)
|
local function check_function_parameters(node: Node, get_type: function(string): string)
|
||||||
if not node.parameters then
|
if not node.parameters then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, parameter in ipairs(node.parameters) do
|
for _, parameter in ipairs(node.parameters) do
|
||||||
check_node(parameter)
|
check_node(parameter, get_type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function check_function_returns(node: Node)
|
local function check_function_returns(node: Node, get_type: function(string): string)
|
||||||
if not node.return_types then
|
if not node.return_types then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, ret in ipairs(node.return_types) do
|
for i, ret_ts in ipairs(node.return_types) do
|
||||||
node.return_types[i] = get_type(ret)
|
for j, t in ipairs(ret_ts) do
|
||||||
|
node.return_types[i][j] = get_type(t)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local record Type_Mapping
|
local record Type_Mapping
|
||||||
visit: function(node: Node)
|
visit: function(node: Node, is_global_module: boolean)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Type_Mapping.visit(node: Node)
|
function Type_Mapping.visit(node: Node, is_global_module: boolean)
|
||||||
check_node(node)
|
local get_type <const> = is_global_module and function(t: string): string
|
||||||
check_function_parameters(node)
|
return global_type_map[t] or type_map[t] or t
|
||||||
check_function_returns(node)
|
end or function(t: string): string
|
||||||
|
return type_map[t] or t
|
||||||
|
end
|
||||||
|
|
||||||
|
check_node(node, get_type)
|
||||||
|
check_function_parameters(node, get_type)
|
||||||
|
check_function_returns(node, get_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Type_Mapping
|
return Type_Mapping
|
||||||
|
|
Loading…
Reference in New Issue