diff --git a/.editorconfig b/.editorconfig index 185c3c8..bcfe9f9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,9 @@ insert_final_newline = true [*.lua] indent_size = 3 +[*.{tl,d.tl}] +indent_size = 3 + [justfile] indent_size = 2 diff --git a/.gitignore b/.gitignore index 8df544e..f6ca0ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ lua_modules generated +build diff --git a/.woodpecker/build.yml b/.woodpecker/build.yml new file mode 100644 index 0000000..7f586a5 --- /dev/null +++ b/.woodpecker/build.yml @@ -0,0 +1,25 @@ +depends_on: + - lint + +pipeline: + prepare: + image: akorn/luarocks:lua5.4-alpine + commands: + - apk add just gcc libc-dev musl-dev curl-dev + - just install + build: + image: akorn/luarocks:lua5.4-alpine + commands: + - apk add just gcc musl-dev + - luarocks install cyan + - 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 diff --git a/.woodpecker/lint.yml b/.woodpecker/lint.yml index 0ff55d8..4cf754e 100644 --- a/.woodpecker/lint.yml +++ b/.woodpecker/lint.yml @@ -1,23 +1,38 @@ variables: - - &when_path + - &when_path_lua - ".woodpecker/lint.yml" + - "justfile" - "**/*.lua" + - &when_path_teal + - ".woodpecker/lint.yml" + - "justfile" + - "**/*.tl" pipeline: - lint: + lint-lua: image: ghcr.io/lunarmodules/luacheck:v0.26.1 group: lint commands: - apk add just - just check-lua when: - path: *when_path + path: *when_path_lua - style: + style-lua: image: alpine:edge # Stylua is only available on edge repository for now group: lint commands: - apk add just stylua - just check-format when: - path: *when_path + path: *when_path_lua + + lint-teal: + image: akorn/luarocks:lua5.4-alpine + group: lint + commands: + - apk add just gcc libc-dev musl-dev + - luarocks install cyan + - just check-teal + when: + path: *when_path_teal diff --git a/justfile b/justfile index ce79ab5..2e65606 100644 --- a/justfile +++ b/justfile @@ -1,11 +1,13 @@ lua_version := "5.4" -lua_bin := "lua" + lua_version -lua := lua_bin + " -l set_paths" +lua := "lua" + " -l set_paths" + +tl := "tl run" + " -l set_paths" rocks_tree := "lua_modules" rockspec_file := "rockspecs/awesomewm.d.tl-dev-1.rockspec" -lua_targets := `find src/ -iname '*.lua' | xargs` + " " + `ls *.lua | xargs` +lua_targets := `find src/ -type f -iname '*.lua' | xargs` + " " + `ls *.lua | xargs` +teal_targets := `find src/ types/ -type f -iname '*.tl' | xargs` install: luarocks \ @@ -21,13 +23,27 @@ uninstall: check-lua *FLAGS: luacheck {{ lua_targets }} {{ FLAGS }} +check-teal: + cyan check {{ teal_targets }} + check-format: stylua --check {{ lua_targets }} -check: check-lua check-format +check: check-lua check-format check-teal + +build: + cyan build + +clean: + rm -rf build run: - {{ lua }} src/awesomewm.d.tl/init.lua + {{ tl }} src/awesomewm.d.tl/init.tl +# TODO : how to run a debugger on Teal code? debug: - {{ lua }} debug.lua src/awesomewm.d.tl/init.lua + {{ lua }} debug.lua build/awesomewm.d.tl/init.lua +debug-gen: + cyan gen --output set_paths.lua --gen-compat "off" set_paths.tl + sed -i 's/"src\/awesomewm.d.tl"/"build\/awesomewm.d.tl"/g' set_paths.lua + stylua set_paths.lua diff --git a/set_paths.lua b/set_paths.lua index 54c6239..0238a0c 100644 --- a/set_paths.lua +++ b/set_paths.lua @@ -1,4 +1,3 @@ --- set_paths.lua local version = _VERSION:match "%d+%.%d+" local function lua_module_paths(module_base_path) @@ -9,7 +8,8 @@ local function lua_module_paths(module_base_path) end package.path = lua_module_paths("lua_modules/share/lua/" .. version) - .. lua_module_paths "src/awesomewm.d.tl" + .. lua_module_paths "types" + .. lua_module_paths "build/awesomewm.d.tl" .. package.path package.cpath = "lua_modules/lib/lua/" .. version .. "/?.so;" .. package.cpath diff --git a/set_paths.tl b/set_paths.tl new file mode 100644 index 0000000..5473872 --- /dev/null +++ b/set_paths.tl @@ -0,0 +1,16 @@ +-- set_paths.lua +local version = _VERSION:match "%d+%.%d+" + +local function lua_module_paths(module_base_path: string): string + local paths = (module_base_path .. "/?.lua;") + .. (module_base_path .. "/?/init.lua;") + + return paths +end + +package.path = lua_module_paths("lua_modules/share/lua/" .. version) + .. lua_module_paths "types" + .. lua_module_paths "build/awesomewm.d.tl" + .. package.path + +package.cpath = "lua_modules/lib/lua/" .. version .. "/?.so;" .. package.cpath diff --git a/src/awesomewm.d.tl/crawler/init.lua b/src/awesomewm.d.tl/crawler/init.tl similarity index 86% rename from src/awesomewm.d.tl/crawler/init.lua rename to src/awesomewm.d.tl/crawler/init.tl index 1305b9c..c1d745c 100644 --- a/src/awesomewm.d.tl/crawler/init.lua +++ b/src/awesomewm.d.tl/crawler/init.tl @@ -6,7 +6,7 @@ local tablex = require "pl.tablex" local crawler = {} -local function http_request(url) +local function http_request(url: string): string local body, code_or_error = http.request(url) if not body then @@ -14,7 +14,7 @@ local function http_request(url) error { "Request failed", err = err, url = url } end - local code = code_or_error + local code = code_or_error as integer if code < 200 and code >= 300 then error { @@ -27,7 +27,7 @@ local function http_request(url) return body end -local function get_resource_by_protocol(url) +local function get_resource_by_protocol(url: string): boolean, string local protocol, resource = url:match "^(%a+)://(.*)$" if not not tablex.find({ "http", "https" }, protocol) then @@ -45,7 +45,7 @@ local function get_resource_by_protocol(url) end end -function crawler.fetch(url) +function crawler.fetch(url: string): string local success, result = get_resource_by_protocol(url) if not success then diff --git a/src/awesomewm.d.tl/entities/Function_Info.lua b/src/awesomewm.d.tl/entities/Function_Info.lua deleted file mode 100644 index 956ac11..0000000 --- a/src/awesomewm.d.tl/entities/Function_Info.lua +++ /dev/null @@ -1,23 +0,0 @@ -local class = require "pl.class" -local List = require "pl.List" - -local Function_Info = class.Module_Doc() - -function Function_Info:_init() - self.name = "" - self.parameters = List() - self.return_types = List() -end - -function Function_Info:append_return_type(return_type) - self.return_types:append(return_type) -end - -function Function_Info:append_parameter(name, type) - self.parameters:append { - name = name, - type = type, - } -end - -return Function_Info diff --git a/src/awesomewm.d.tl/entities/Function_Info.tl b/src/awesomewm.d.tl/entities/Function_Info.tl new file mode 100644 index 0000000..5f0b802 --- /dev/null +++ b/src/awesomewm.d.tl/entities/Function_Info.tl @@ -0,0 +1,38 @@ +local List = require "pl.List" + +local record Parameter + name: string + type: string +end + +local record Function_Info + metamethod __call: function(Function_Info): Function_Info + + Function_Info: Function_Info + + name: string + parameters: List + return_types: List + + append_parameter: function(self: Function_Info, name: string, type: string) + append_return_type: function(self: Function_Info, return_type: string) +end + +local __Function_Info: metatable = { + __call = function(_self: Function_Info): Function_Info + return {} + end, +} + +function Function_Info:append_parameter(name: string, type: string) + self.parameters:append { + name = name, + type = type, + } +end + +function Function_Info:append_return_type(return_type: string) + self.return_types:append(return_type) +end + +return setmetatable({} as Function_Info, __Function_Info) diff --git a/src/awesomewm.d.tl/entities/Module_Doc.lua b/src/awesomewm.d.tl/entities/Module_Doc.lua deleted file mode 100644 index 48ddc31..0000000 --- a/src/awesomewm.d.tl/entities/Module_Doc.lua +++ /dev/null @@ -1,12 +0,0 @@ -local class = require "pl.class" -local List = require "pl.List" - -local Module_Doc = class.Module_Doc() - -function Module_Doc:_init() - self.constructors = List() - self.methods = List() - self.static_functions = List() -end - -return Module_Doc diff --git a/src/awesomewm.d.tl/entities/Module_Doc.tl b/src/awesomewm.d.tl/entities/Module_Doc.tl new file mode 100644 index 0000000..28df225 --- /dev/null +++ b/src/awesomewm.d.tl/entities/Module_Doc.tl @@ -0,0 +1,21 @@ +local Function_Info = require "entities.Function_Info" +local List = require "pl.List" + +local record Module_Doc + metamethod __call: function(Module_Doc): Module_Doc + + Module_Doc: Module_Doc + + constructors: List + methods: List + static_functions: List +end + +local __Module_Doc: metatable = { + __call = function(_: Module_Doc): Module_Doc + return {} + end, +} + +return setmetatable({} as Module_Doc, __Module_Doc) + diff --git a/src/awesomewm.d.tl/entities/Module_Info.lua b/src/awesomewm.d.tl/entities/Module_Info.lua deleted file mode 100644 index df163d9..0000000 --- a/src/awesomewm.d.tl/entities/Module_Info.lua +++ /dev/null @@ -1,10 +0,0 @@ -local class = require "pl.class" - -local Module_Info = class.Module_Info() - -function Module_Info:_init(name, uri) - self.name = name - self.uri = uri -end - -return Module_Info diff --git a/src/awesomewm.d.tl/entities/Module_Info.tl b/src/awesomewm.d.tl/entities/Module_Info.tl new file mode 100644 index 0000000..8ab31b9 --- /dev/null +++ b/src/awesomewm.d.tl/entities/Module_Info.tl @@ -0,0 +1,19 @@ +local record Module_Info + metamethod __call: function(self: Module_Info, name: string, uri: string): Module_Info + + Module_Info: Module_Info + + name: string + uri: string +end + +local __Module_Info: metatable = { + __call = function(_self: Module_Info, name: string, uri: string): Module_Info + return { + name = name, + uri = uri, + } + end, +} + +return setmetatable({} as Module_Info, __Module_Info) diff --git a/src/awesomewm.d.tl/generator/init.lua b/src/awesomewm.d.tl/generator/init.tl similarity index 71% rename from src/awesomewm.d.tl/generator/init.lua rename to src/awesomewm.d.tl/generator/init.tl index 335bb79..d72d20d 100644 --- a/src/awesomewm.d.tl/generator/init.lua +++ b/src/awesomewm.d.tl/generator/init.tl @@ -5,7 +5,7 @@ local log = require "logger" local utils = require "utils" local snippets = require "generator.snippets" -local tmpl = (function(mod) +local tmpl = (function(mod: string): string local package_path = utils.do_or_fail(path.package_path, mod) local package_dir = path.dirname(package_path) return utils.do_or_fail(file.read, package_dir .. "/template.tl.tmpl", false) @@ -13,10 +13,22 @@ end)(...) local generator = {} -function generator.generate_teal(data) +local record Generate_Teal_Data_Record + section: string + items: { snippets.Anonymous_Function_Record } +end +function generator.generate_teal(data: { Generate_Teal_Data_Record }): string -- TODO : add the required modules to the generated code -- TODO : replace this with a proper way to get the module name (will also probably need the module path) - local module_data = { name = "module_name" } + local record Module_Data_Record + name: string + static_functions: { snippets.Anonymous_Function_Record } + constructors: { snippets.Anonymous_Function_Record } + methods: { string } + properties: { snippets.Anonymous_Function_Record } + signals: { snippets.Anonymous_Function_Record } + end + local module_data: Module_Data_Record = { name = "module_name" } for _, item in ipairs(data) do if item.section == "Static functions" then -- TODO @@ -49,19 +61,19 @@ function generator.generate_teal(data) return utils.do_or_fail(template.substitute, tmpl, env) end -function generator.write(file_content, file_path) +function generator.write(file_content:string, file_path: string) -- Make sure the directory we want to write the file to exists local directory = path.dirname(file_path) if not path.isdir(directory) then path.mkdir(directory) end - local success, error = file.write(file_path, file_content, false) + local success, error_message = file.write(file_path, file_content, false) if not success then log:error { "generator.write error", - error = error, + error = error_message, } return end diff --git a/src/awesomewm.d.tl/generator/snippets.lua b/src/awesomewm.d.tl/generator/snippets.tl similarity index 64% rename from src/awesomewm.d.tl/generator/snippets.lua rename to src/awesomewm.d.tl/generator/snippets.tl index 9d29310..78ad3dc 100644 --- a/src/awesomewm.d.tl/generator/snippets.lua +++ b/src/awesomewm.d.tl/generator/snippets.tl @@ -2,10 +2,10 @@ local utils = require "utils" local template = require "pl.template" -- Refactor scraper code to use pl.List objects -local function join(arr, delim) +local function join(arr: { string }, delim: string): string local ret = "" - for i, type in ipairs(arr) do - ret = ret .. type + for i, t in ipairs(arr) do + ret = ret .. t if i < #arr then ret = ret .. delim end @@ -13,13 +13,27 @@ local function join(arr, delim) return ret end -local snippets = {} +local record Anonymous_Function_Parameter_Record + name: string + type: { string } +end -function snippets.types_list(types) +local record Anonymous_Function_Record + name: string + parameters: { Anonymous_Function_Parameter_Record } + returns: { string } +end + +local snippets = { + Anonymous_Function_Parameter_Record = Anonymous_Function_Parameter_Record, + Anonymous_Function_Record = Anonymous_Function_Record, +} + +function snippets.types_list(types: { string }): string return join(types, ", ") end -function snippets.anonymous_function(item) +function snippets.anonymous_function(item: Anonymous_Function_Record): string local parameters_string = "" if item.parameters then for i, param in ipairs(item.parameters) do diff --git a/src/awesomewm.d.tl/init.lua b/src/awesomewm.d.tl/init.tl similarity index 100% rename from src/awesomewm.d.tl/init.lua rename to src/awesomewm.d.tl/init.tl diff --git a/src/awesomewm.d.tl/logger/init.lua b/src/awesomewm.d.tl/logger/init.lua deleted file mode 100644 index 76a4f92..0000000 --- a/src/awesomewm.d.tl/logger/init.lua +++ /dev/null @@ -1,18 +0,0 @@ -local ansicolors = require "ansicolors" -local console = require "logging.console" -local ll = require "logging" - -local log = console { - logLevel = ll.DEBUG, - destination = "stdout", - timestampPattern = "[%y-%m-%d %H:%M:%S]", - logPatterns = { - [ll.DEBUG] = ansicolors "%date%{cyan} %level %message %{reset}(%source)\n", - [ll.INFO] = ansicolors "%date %level %message\n", - [ll.WARN] = ansicolors "%date%{yellow} %level %message\n", - [ll.ERROR] = ansicolors "%date%{red bright} %level %message %{reset}(%source)\n", - [ll.FATAL] = ansicolors "%date%{magenta bright} %level %message %{reset}(%source)\n", - }, -} - -return log diff --git a/src/awesomewm.d.tl/logger/init.tl b/src/awesomewm.d.tl/logger/init.tl new file mode 100644 index 0000000..7470b33 --- /dev/null +++ b/src/awesomewm.d.tl/logger/init.tl @@ -0,0 +1,17 @@ +local ansicolors = require "ansicolors" +local logging_console = require "logging.console" + +local log = logging_console { + logLevel = "DEBUG", + destination = "stdout", + timestampPattern = "[%y-%m-%d %H:%M:%S]", + logPatterns = { + DEBUG = ansicolors "%date%{cyan} %level %message %{reset}(%source)\n", + INFO = ansicolors "%date %level %message\n", + WARN = ansicolors "%date%{yellow} %level %message\n", + ERROR = ansicolors "%date%{red bright} %level %message %{reset}(%source)\n", + FATAL = ansicolors "%date%{magenta bright} %level %message %{reset}(%source)\n", + }, +} + +return log diff --git a/src/awesomewm.d.tl/properties.lua b/src/awesomewm.d.tl/properties.lua deleted file mode 100644 index 0ca6f9a..0000000 --- a/src/awesomewm.d.tl/properties.lua +++ /dev/null @@ -1,66 +0,0 @@ -local properties = {} - --- properties.base_url = "https://awesomewm.org/apidoc" -properties.base_url = "file:///usr/share/doc/awesome/doc" - -properties.index_uri = "/index.html" - -properties.out_directory = "generated" - ---- Pages from the navigation menu to ignore. --- Sets to ignore documentations and sample file. I also added libraries with --- low quality API documentation, I'll probably work on them later, lets start --- with what works the best first. -properties.ignored_modules = { - -- Sample files - "rc.lua", - "theme.lua", - - -- Utility libraries - "gears.debug", - "gears.filesystem", - "gears.geometry", - "gears.math", - "gears.object", - "gears.protected_call", - "gears.sort", - "gears.string", - "gears.table", - "gears.wallpaper", - - -- Theme related libraries - "beautiful", - "gears.color", - "gears.shape", - - -- Classes - "awful.widget.common", - "gears.cache", - "gears.matrix", - "menubar.icon_theme", - "menubar.index_theme", - "signals", - "wibox.drawable", - "wibox.hierarchy", - "wibox.widget.base", - "xproperties", - - -- Documentation - "Authors", - "Readme", - "Contributing", - "The Widget system", - "Creating new widget", - "Default configuration file documentation", - "Change Awesome appearance", - "My first Awesome", - "The AwesomeWM client layout system", - "Startup options", - "Building and Testing", - "Using Cairo and LGI", - "Tips for upgrading your configuration", - "NEWS", - "FAQ", -} - -return properties diff --git a/src/awesomewm.d.tl/properties.tl b/src/awesomewm.d.tl/properties.tl new file mode 100644 index 0000000..5ce4a59 --- /dev/null +++ b/src/awesomewm.d.tl/properties.tl @@ -0,0 +1,72 @@ +local record Properties + base_url: string + index_uri: string + + out_directory: string + + --- Pages from the navigation menu to ignore. + -- Sets to ignore documentations and sample file. I also added libraries with + -- low quality API documentation, I'll probably work on them later, lets start + -- with what works the best first. + ignored_modules: { string } +end + +local properties: Properties = { + -- base_url = "https://awesomewm.org/apidoc", + base_url = "file:///usr/share/doc/awesome/doc", + index_uri = "/index.html", + out_directory = "generated", + ignored_modules = { + -- Sample files + "rc.lua", + "theme.lua", + + -- Utility libraries + "gears.debug", + "gears.filesystem", + "gears.geometry", + "gears.math", + "gears.object", + "gears.protected_call", + "gears.sort", + "gears.string", + "gears.table", + "gears.wallpaper", + + -- Theme related libraries + "beautiful", + "gears.color", + "gears.shape", + + -- Classes + "awful.widget.common", + "gears.cache", + "gears.matrix", + "menubar.icon_theme", + "menubar.index_theme", + "signals", + "wibox.drawable", + "wibox.hierarchy", + "wibox.widget.base", + "xproperties", + + -- Documentation + "Authors", + "Readme", + "Contributing", + "The Widget system", + "Creating new widget", + "Default configuration file documentation", + "Change Awesome appearance", + "My first Awesome", + "The AwesomeWM client layout system", + "Startup options", + "Building and Testing", + "Using Cairo and LGI", + "Tips for upgrading your configuration", + "NEWS", + "FAQ", + } +} + +return properties diff --git a/src/awesomewm.d.tl/scraper/init.lua b/src/awesomewm.d.tl/scraper/init.tl similarity index 100% rename from src/awesomewm.d.tl/scraper/init.lua rename to src/awesomewm.d.tl/scraper/init.tl diff --git a/src/awesomewm.d.tl/scraper/module_doc.lua b/src/awesomewm.d.tl/scraper/module_doc.tl similarity index 62% rename from src/awesomewm.d.tl/scraper/module_doc.lua rename to src/awesomewm.d.tl/scraper/module_doc.tl index be2efb6..528f737 100644 --- a/src/awesomewm.d.tl/scraper/module_doc.lua +++ b/src/awesomewm.d.tl/scraper/module_doc.tl @@ -1,13 +1,15 @@ local Function_Info = require "entities.Function_Info" +local List = require "pl.List" local Module_Doc = require "entities.Module_Doc" +local scan = require "web_sanitize.query.scan_html" local scraper_utils = require "scraper.utils" local utils = require "utils" -local function extract_function_name(function_name_node) - return function_name_node and (function_name_node.attr.name:gsub(".*:", "")) +local function extract_function_name(function_name_node: scan.HTMLNode): string + return function_name_node and ((function_name_node.attr.name as string):gsub(".*:", "")) end -local function extract_function_return_types(function_return_types_node) +local function extract_function_return_types(function_return_types_node: scan.HTMLNode): { string } if not function_return_types_node then return {} end @@ -15,12 +17,12 @@ local function extract_function_return_types(function_return_types_node) local selector = "span.types .type" local html = function_return_types_node:outer_html() - return scraper_utils.scrape(html, selector, function(node) + return scraper_utils.scrape(html, selector, function(node: scan.HTMLNode): string return utils.sanitize_string(node:inner_text()) end) end -local function extract_section_functions(dl) +local function extract_section_functions(dl: string): { Function_Info.Function_Info } local query_selectors = { function_name = "dt a", function_return_type = "dd ol", @@ -29,13 +31,15 @@ local function extract_section_functions(dl) return scraper_utils.scrape_tuples( dl, { query_selectors.function_name, query_selectors.function_return_type }, - function(nodes) + function(nodes: { string : scan.HTMLNode | nil }): Function_Info.Function_Info local function_info = Function_Info() function_info.name = extract_function_name(nodes[query_selectors.function_name]) - function_info.return_types = extract_function_return_types( - nodes[query_selectors.function_return_type] + function_info.return_types = List( + extract_function_return_types( + nodes[query_selectors.function_return_type] + ) ) return function_info @@ -45,7 +49,7 @@ end local module = {} -function module.get_doc_from_page(html) +function module.get_doc_from_page(html: string): Module_Doc.Module_Doc local nodes = scraper_utils.extract_nodes(html, { "h2.section-header", "dl.function", @@ -57,20 +61,21 @@ function module.get_doc_from_page(html) local module_doc = Module_Doc() - for i, h2 in ipairs(nodes:get "h2.section-header") do + for i = 1, #nodes:get("h2.section-header") do + local h2 = nodes:get("h2.section-header")[i] local section_name = utils.sanitize_string(h2:inner_text()) local dl_html = nodes:get("dl.function")[i]:outer_html() if section_name == "Constructors" then - module_doc.constructors = extract_section_functions(dl_html) + module_doc.constructors = List(extract_section_functions(dl_html)) elseif section_name == "Static module functions" then - module_doc.static_functions = extract_section_functions(dl_html) + module_doc.static_functions = List(extract_section_functions(dl_html)) elseif section_name == "Object properties" then - print "Not implemented: Deprecated object properties" + print "Not implemented: Object properties" elseif section_name == "Deprecated object properties" then print "Not implemented: Deprecated object properties" elseif section_name == "Object methods" then - module_doc.methods = extract_section_functions(dl_html) + module_doc.methods = List(extract_section_functions(dl_html)) elseif section_name == "Signals" then print "Not implemented: Signals" else diff --git a/src/awesomewm.d.tl/scraper/module_info_list.lua b/src/awesomewm.d.tl/scraper/module_info_list.tl similarity index 68% rename from src/awesomewm.d.tl/scraper/module_info_list.lua rename to src/awesomewm.d.tl/scraper/module_info_list.tl index f2a8b5f..21ecda9 100644 --- a/src/awesomewm.d.tl/scraper/module_info_list.lua +++ b/src/awesomewm.d.tl/scraper/module_info_list.tl @@ -1,4 +1,5 @@ local Module_Info = require "entities.Module_Info" +local scan = require "web_sanitize.query.scan_html" local scraper_utils = require "scraper.utils" local utils = require "utils" @@ -6,9 +7,9 @@ local module = {} local MODULE_A_TAG_QUERY_SELECTOR = "div#navigation ul li a" -local function extract_module_info(node) +local function extract_module_info(node: scan.HTMLNode): Module_Info.Module_Info local name = utils.sanitize_string(node:inner_text()) - local uri = node.attr.href + local uri = node.attr.href as string if not (name and uri) then error("Can't extract module info from node: " .. node:outer_html()) @@ -17,7 +18,7 @@ local function extract_module_info(node) return Module_Info(name, uri) end -function module.get_modules_from_index(html) +function module.get_modules_from_index(html: string): { Module_Info.Module_Info } return scraper_utils.scrape( html, MODULE_A_TAG_QUERY_SELECTOR, diff --git a/src/awesomewm.d.tl/scraper/utils.lua b/src/awesomewm.d.tl/scraper/utils.lua deleted file mode 100644 index 4668c0c..0000000 --- a/src/awesomewm.d.tl/scraper/utils.lua +++ /dev/null @@ -1,68 +0,0 @@ -local List = require "pl.List" -local log = require "logger" -local Map = require "pl.Map" -local scanner = require "web_sanitize.query.scan_html" -local tablex = require "pl.tablex" - -local scraper_utils = {} - -function scraper_utils.scrape(html, query_selector, extract_callback) - local ret = {} - - scanner.scan_html(html, function(stack) - if stack:is(query_selector) then - local node = stack:current() - local success, info = pcall(extract_callback, node) - - if not success then - log:error { message = info } - else - table.insert(ret, info) - end - end - end) - - return ret -end - -function scraper_utils.extract_nodes(html, query_selectors) - local siblings = Map() - - tablex.foreach(query_selectors, function(query_selector) - siblings:set(query_selector, List()) - end) - - scanner.scan_html(html, function(stack) - tablex.foreach(query_selectors, function(query_selector) - if stack:is(query_selector) then - siblings:get(query_selector):append(stack:current()) - end - end) - end) - - return siblings -end - -function scraper_utils.scrape_tuples(html, query_selectors, extract_callback) - local nodes = scraper_utils.extract_nodes(html, query_selectors) - - local ret = {} - - for i = 1, #nodes:get(query_selectors[1]) do - local node_list = {} - tablex.foreach(query_selectors, function(query_selector) - node_list[query_selector] = nodes:get(query_selector)[i] or nil - end) - local success, info = pcall(extract_callback, node_list) - - if not success then - log:error { message = info } - else - table.insert(ret, info) - end - end - - return ret -end - -return scraper_utils diff --git a/src/awesomewm.d.tl/scraper/utils.tl b/src/awesomewm.d.tl/scraper/utils.tl new file mode 100644 index 0000000..651ffd7 --- /dev/null +++ b/src/awesomewm.d.tl/scraper/utils.tl @@ -0,0 +1,73 @@ +local List = require "pl.List" +local log = require "logger" +local Map = require "pl.Map" +local scan = require "web_sanitize.query.scan_html" +local scanner = require "web_sanitize.query.scan_html" +local tablex = require "pl.tablex" + +local scraper_utils = {} + +function scraper_utils.scrape(html: string, query_selector: string, extract_callback: function(node: scan.HTMLNode): T): { T } + local ret: { T } = {} + + scanner.scan_html(html, function(stack: scan.NodeStack) + if stack:is(query_selector) then + local node = stack:current() + local success, info_or_error = pcall(extract_callback, node) + + if not success then + local error_message = info_or_error as string + log:error { message = error_message } + else + local info = info_or_error as T + table.insert(ret, info) + end + end + end) + + return ret +end + +function scraper_utils.extract_nodes(html: string, query_selectors: { string }): Map> + local siblings: Map> = Map() + + tablex.foreach(query_selectors, function(query_selector: string) + siblings:set(query_selector, List()) + end) + + scanner.scan_html(html, function(stack: scan.NodeStack) + tablex.foreach(query_selectors, function(query_selector: string) + if stack:is(query_selector) then + siblings:get(query_selector):append(stack:current()) + end + end) + end) + + return siblings +end + +function scraper_utils.scrape_tuples(html: string, query_selectors: { string }, extract_callback: function(tuple: { string : scan.HTMLNode | nil }): T): { T } + local nodes = scraper_utils.extract_nodes(html, query_selectors) + + local ret: { T } = {} + + for i = 1, #nodes:get(query_selectors[1]) do + local node_list: { string : scan.HTMLNode | nil } = {} + tablex.foreach(query_selectors, function(query_selector: string) + node_list[query_selector] = nodes:get(query_selector)[i] or nil + end) + local success, info_or_error = pcall(extract_callback, node_list) + + if not success then + local error_message = info_or_error as string + log:error { message = error_message } + else + local info = info_or_error as T + table.insert(ret, info) + end + end + + return ret +end + +return scraper_utils diff --git a/src/awesomewm.d.tl/utils.lua b/src/awesomewm.d.tl/utils.lua deleted file mode 100644 index ee4fb08..0000000 --- a/src/awesomewm.d.tl/utils.lua +++ /dev/null @@ -1,70 +0,0 @@ -local web_sanitize = require "web_sanitize" - -local utils = {} - -function utils.has_item(table, item) - for k, v in pairs(table) do - if v == item then - return k - end - end - - return nil -end - -function utils.filter(list, predicate) - local filtered = {} - - for position, value in ipairs(list) do - if predicate(value, position) then - table.insert(filtered, value) - end - end - - return filtered -end - -function utils.map(list, iteratee) - local mapped = {} - - for position, value in ipairs(list) do - table.insert(mapped, iteratee(value, position)) - end - - return mapped -end - -function utils.sanitize_string(string) - return utils.trim( - utils.replace(web_sanitize.extract_text(string), "^%s*(.-)%s*$", "%1") - ) -end - --- Extracted from teh Penlight Lua library. --- Sometime Lua string.gsub can't match unescaped strings. --- https://stackoverflow.com/a/72666170 -function utils.escape(string) - return (string:gsub("[%-%.%+%[%]%(%)%$%^%%%?%*]", "%%%1")) -end - -function utils.replace(string, old, new, n) - return (string:gsub(utils.escape(old), new:gsub("%%", "%%%%"), n)) -end - -function utils.trim(string) - return string:match "^%s*(.-)%s*$" -end - -function utils.do_or_fail(func, ...) - local log = require "logger" - local res, err = func(...) - - if not res then - log:error { "do_or_fail failed!", error = err } - error(err) - end - - return res -end - -return utils diff --git a/src/awesomewm.d.tl/utils.tl b/src/awesomewm.d.tl/utils.tl new file mode 100644 index 0000000..768af7f --- /dev/null +++ b/src/awesomewm.d.tl/utils.tl @@ -0,0 +1,71 @@ +local web_sanitize = require "web_sanitize" + +local utils = {} + +function utils.has_item(t: table, item: any): any + for k, v in pairs(t) do + if v == item then + return k + end + end + + return nil +end + +function utils.filter(list: { T }, predicate: function(value: T, position: integer): boolean): { T } + local filtered: { T } = {} + + for position, value in ipairs(list) do + if predicate(value, position) then + table.insert(filtered, value) + end + end + + return filtered +end + +function utils.map(list: { T }, iteratee: function(value: T, position: integer): U): { U } + local mapped: { U } = {} + + for position, value in ipairs(list) do + table.insert(mapped, iteratee(value, position)) + end + + return mapped +end + +-- Extracted from teh Penlight Lua library. +-- Sometime Lua string.gsub can't match unescaped strings. +-- https://stackoverflow.com/a/72666170 +function utils.escape(s: string): string + return (s:gsub("[%-%.%+%[%]%(%)%$%^%%%?%*]", "%%%1")) +end + +function utils.replace(s: string, old: string, new: string, n: number): string + return (s:gsub(utils.escape(old), new:gsub("%%", "%%%%"), n)) +end + +function utils.trim(s: string): string + return s:match "^%s*(.-)%s*$" +end + +function utils.sanitize_string(s: string): string + return utils.trim( + utils.replace(web_sanitize.extract_text(s), "^%s*(.-)%s*$", "%1") + ) +end + +-- At some point, we should probably write a wrapper to make penlight's function work with pcalls. +function utils.do_or_fail(func: function(...: any): (T | nil, string), ...: any): T + local log = require "logger" + local res, err = func(...) + + if not res then + log:error { "do_or_fail failed!", error = err } + error(err) + end + + return res +end + +return utils diff --git a/tlconfig.lua b/tlconfig.lua new file mode 100644 index 0000000..aafa9c4 --- /dev/null +++ b/tlconfig.lua @@ -0,0 +1,8 @@ +return { + build_dir = "build", + source_dir = "src", + include_dir = { + "src/awesomewm.d.tl", + "types", + }, +} diff --git a/types/ansicolors.d.tl b/types/ansicolors.d.tl new file mode 100644 index 0000000..1cc77c7 --- /dev/null +++ b/types/ansicolors.d.tl @@ -0,0 +1,6 @@ +local record ansicolors + noReset: function(str: string): string + metamethod __call: function(_: ansicolors, str: string): string +end + +return ansicolors diff --git a/types/inspect.d.tl b/types/inspect.d.tl new file mode 100644 index 0000000..e980df5 --- /dev/null +++ b/types/inspect.d.tl @@ -0,0 +1,12 @@ +local record inspect + record InspectOptions + depth: number + newline: string + indent: string + process: function(item: any, path: {any}): any + end + + metamethod __call: function(self: inspect, value: any, options: InspectOptions): string +end + +return inspect diff --git a/types/logging.d.tl b/types/logging.d.tl new file mode 100644 index 0000000..9fab25b --- /dev/null +++ b/types/logging.d.tl @@ -0,0 +1,97 @@ +local enum Level + "DEBUG" + "INFO" + "WARN" + "ERROR" + "FATAL" + "OFF" +end + +local type Append = function(params: T, ...: any): Log + +local record Log + append: Append + setLevel: function (self: Log, level: Level) + log: function(self: Log, level: Level, ...: any) + getPrint: function(self: Log, level: Level): function(...: any) + + debug: function(self: Log, ...: any) + info: function(self: Log, ...: any) + warn: function(self: Log, ...: any) + error: function(self: Log, ...: any) + fatal: function(self: Log, ...: any) + + DEBUG: Level + INFO: Level + WARN: Level + ERROR: Level + FATAL: Level + OFF: Level +end + +local record logging + Level: Level + Append: Append + Log: Log + + _COPYRIGHT: string + _DESCRIPTION: string + _VERSION: string + + DEBUG: Level + INFO: Level + WARN: Level + ERROR: Level + FATAL: Level + OFF: Level + + new: function(append: function(self: Log, level: Level, msg: string | function), startLevel: Level): Log + buildLogPatterns: function(patterns: table, default: string): table + defaultLogPatterns: function(patt: string | table): table + defaultTimestampPattern: function(patt: string): string + defaultLevel: function(level: Level): Level + defaultLogger: function(logger: Log): Log + + -- Deprecated + getDeprecatedParams: function(lst: table, ...: any) + + -- Appenders (dynamically added to logging when required) + record ConsoleParameters + enum ConsoleDestination + "stdout" + "stderr" + end + + destination: ConsoleDestination + logPattern: string + logPatterns: { Level : string } + timestampPattern: string + logLevel: Level + end + console: Append + + record FileParameters + filename: string + datePattern: string + logPattern: string + logPatterns: { Level : string } + timestampPattern: string + logLevel: Level + end + file: Append + + record RollingFileParameters + filename: string + maxFileSize: number + maxBackupIndex: number + logPattern: string + logPatterns: { Level : string } + timestampPattern: string + logLevel: Level + end + rolling_file: Append + + -- TODO : add more appenders +end + +return logging diff --git a/types/logging/console.d.tl b/types/logging/console.d.tl new file mode 100644 index 0000000..ad3818a --- /dev/null +++ b/types/logging/console.d.tl @@ -0,0 +1 @@ +return require "logging".console \ No newline at end of file diff --git a/types/logging/file.d.tl b/types/logging/file.d.tl new file mode 100644 index 0000000..27e89bf --- /dev/null +++ b/types/logging/file.d.tl @@ -0,0 +1 @@ +return require "logging".file \ No newline at end of file diff --git a/types/logging/rolling_file.d.tl b/types/logging/rolling_file.d.tl new file mode 100644 index 0000000..43e7891 --- /dev/null +++ b/types/logging/rolling_file.d.tl @@ -0,0 +1 @@ +return require("logging").rolling_file \ No newline at end of file diff --git a/types/ltn12.d.tl b/types/ltn12.d.tl new file mode 100644 index 0000000..d4ec368 --- /dev/null +++ b/types/ltn12.d.tl @@ -0,0 +1,45 @@ + +local record ltn12 + type Filter = function(string): string, string + type Sink = function(string, string): boolean, string + type Source = function(): string, string + + type FancySink = function(string, string): boolean, string | FancySink + type FancySource = function(): string, string | FancySource + + -- Docs just say returns a truthy value on success + -- Since this value should really only be + -- used to check for truthiness, any seems fine here + type Pump = function(Source, Sink): any, string + + record filter + chain: function(Filter, Filter, ...: Filter): Filter + + cycle: function(string, string, any): Filter + end + record pump + all: Pump + step: Pump + end + record sink + chain: function(Filter, Sink): Sink + error: function(string): Sink + file: function(FILE, string): Sink + null: function(): Sink + simplify: function(FancySink): Sink + table: function({string}): Sink, {string} + end + record source + cat: function(Source, ...: Source): Source + chain: function(Source, Filter): Source + empty: function(): Source + error: function(string): Source + file: function(FILE): Source + file: function(FILE, string): Source + simplify: function(FancySource): Source + string: function(string): Source + table: function({string}): Source, {string} + end +end + +return ltn12 diff --git a/types/mime.d.tl b/types/mime.d.tl new file mode 100644 index 0000000..027678c --- /dev/null +++ b/types/mime.d.tl @@ -0,0 +1,42 @@ +local ltn12 = require("ltn12") +local type Filter = ltn12.Filter + +local record mime + normalize: function(): Filter + normalize: function(string): Filter + + enum Encoding + "base64" + "quoted-printable" + end + enum Mode + "text" + "binary" + end + + decode: function(Encoding): Filter + encode: function(Encoding, Mode): Filter + + stuff: function(): Filter + + wrap: function(string, integer): Filter + wrap: function(Encoding): Filter + + b64: function(string, string): string, string + + dot: function(integer, string): string, integer + + eol: function(integer, string, string): string, integer + + qp: function(string, string, string): string, string + + qpwrp: function(integer, string, integer): string, integer + + unb64: function(string, string): string, string + + unqp: function(string, string): string, string + + wrp: function(integer, string, integer): string, integer +end + +return mime diff --git a/types/pl.d.tl b/types/pl.d.tl new file mode 100644 index 0000000..171e19a --- /dev/null +++ b/types/pl.d.tl @@ -0,0 +1,1077 @@ +local record pl + -- This is not divided into multiple files due to circular + -- dependency issues. For now, everything is declared here + -- and just reexported in the right file + + record List + -- {T} + + new: function({T}): pl.List + metamethod __call: function(any, {T}): pl.List + metamethod __concat: function(pl.List, pl.List): pl.List + metamethod __len: function(pl.List): number + metamethod __index: function(pl.List, number): T + + range: function(number, number, number): pl.List + split: function(string, string): pl.List + + len: function(pl.List): number + + append: function(pl.List, T): pl.List + clone: function(pl.List): pl.List + extend: function(pl.List, pl.List): pl.List + insert: function(pl.List, number, T): pl.List + pop: function(pl.List, number): T + put: function(pl.List, T): pl.List + remove: function(pl.List, number): pl.List + remove_value: function(pl.List, T): pl.List + + chop: function(pl.List, number, number): pl.List + slice_assign: function(pl.List, number, number, pl.List): pl.List + splice: function(pl.List, number, pl.List): pl.List + + reverse: function(pl.List): pl.List + sorted: function(pl.List, string | function(T, T): boolean): pl.List + sort: function(pl.List, string | function(T, T): boolean): pl.List + + clear: function(pl.List): pl.List + contains: function(pl.List, T): boolean + count: function(pl.List, T): number + index: function(pl.List, T, number): number + minmax: function(pl.List): number, number + slice: function(pl.List, number, number): pl.List + + concat: function(pl.List, string): string + join: function(pl.List, string): string + + foreach: function(pl.List, string | function(T, ...: any), ...: any) + foreachm: function(pl.List, string, ...: any) + filter: function(pl.List, (string | function(T, U): boolean), U): pl.List + + transform: function(pl.List, (string | function(T, ...: any): T), ...: any): pl.List + + map: function(pl.List, (string | function(T, ...: any): U), ...: any): pl.List + map2: function(pl.List, (string | function(T, U, ...: any): V), pl.List, ...: any): pl.List + mapm: function(pl.List, string, ...: any): pl.List + reduce: function(pl.List, (string | function(T, T): T)): T + + partition: function(List, (function(T, ...: any): K), ...: any): pl.Map > + + iter: function(pl.List): (function(): T) + iterate: function(string | table | function) -- FILE is also considered a table + end + + record Map + metamethod __call: function(any, {K: V}): Map + + -- These two are substitutes for maprecords ({K: V}) + metamethod __index: function(pl.Map, K): V + metamethod __newindex: function(pl.Map, K, V) + + keys: pl.List + values: pl.List + + iter: function(pl.Map): (function(): {K, V}) + items: function(pl.Map): (function(): {K, V}) + + get: function(pl.Map, K): V + set: function(pl.Map, K, V) + setdefault: function(pl.Map, K, V): V + + getvalues: function(pl.Map, {K}): pl.List + update: function(pl.Map, {K: V}) + + len: function(pl.Map): number + end + + record Date + metamethod __call: function(pl.Date, number, boolean): pl.Date + metamethod __call: function(pl.Date, {pl.Date.datefield: number}, boolean): pl.Date + metamethod __call: function(pl.Date, number, number, number, number, number, number) + + metamethod __lt: function(pl.Date, pl.Date): boolean + metamethod __add: function(pl.Date, pl.Date): pl.Date + metamethod __add: function(pl.Date, {pl.Date.datefield: number}): pl.Date + metamethod __sub: function(pl.Date, pl.Date): pl.Date + + enum datefield + 'year' + 'month' + 'day' + 'hour' + 'min' + 'sec' + end + + set: function(pl.Date, number) + tzone: function(pl.Date, number): number + toUTC: function(pl.Date): pl.Date + toLocal: function(pl.Date): pl.Date + + year: function(pl.Date): number + month: function(pl.Date): number + day: function(pl.Date): number + hour: function(pl.Date): number + min: function(pl.Date): number + sec: function(pl.Date): number + yday: function(pl.Date): number + + year: function(pl.Date, number) + month: function(pl.Date, number) + day: function(pl.Date, number) + hour: function(pl.Date, number) + min: function(pl.Date, number) + sec: function(pl.Date, number) + yday: function(pl.Date, number) + + is_weekend: function(pl.Date): boolean + weekday_name: function(pl.Date, boolean): string + month_name: function(pl.Date, boolean): string + + add: function(pl.Date, {pl.Date.datefield: number}) + diff: function(pl.Date, pl.Date): pl.Date + + last_day: function(pl.Date): number + + Interval: function(number): pl.Date + + record Format + metamethod __call: function(string): pl.Date.Format + parse: function(string): pl.Date + tostring: function(pl.Date): string + US_order: function(boolean) + end + end + + -- MultiMap inherits from Map, so this is just a weird case that can't + -- really be easily described in teal for now. Same for OrderedMap and Set. + + -- TODO MultiMap + -- TODO OrderedMap + -- TODO Set + + record app + script_name: function(): string + require_here: function(string): any + appfile: function(string): string + platform: function(): string + lua: function(): string, string + parse_args: function({string}, table, table) + end + + record array2d + record Array2D -- record just for generics + {{T}} + end + + new: function(number, number, T): Array2D + + size: function(pl.array2d.Array2D): number, number + column: function(pl.array2d.Array2D, number): List + flatten: function(pl.array2d.Array2D): List + reshape: function(pl.array2d.Array2D, number, boolean): pl.array2d.Array2D + + swap_rows: function(pl.array2d.Array2D, number, number) + swap_cols: function(pl.array2d.Array2D, number, number) + + reduce_rows: function(function(T, T): T, pl.array2d.Array2D): pl.List + reduce_cols: function(function(T, T): T, pl.array2d.Array2D): pl.List + reduce2: function(function(T, T): T, function(T, T): T, pl.array2d.Array2D): T + + map: function( + (string | function(T, ...: A): R), + pl.array2d.Array2D, ...: A + ): pl.array2d.Array2D + + map2: function( + (string | function({T1}, {T2}, ...: A): {R}), + number, number, + pl.array2d.Array2D, pl.array2d.Array2D, + ...: A + ): pl.array2d.Array2D + map2: function( + (string | function({T1}, {T2}, ...: A): R), + number, number, + pl.array2d.Array2D, {T2}, + ...: A + ): Array2D + map2: function( + (string | function({T1}, {T2}, ...: A): R), + number, number, + {T1}, pl.array2d.Array2D, + ...: A + ): pl.array2d.Array2D + map2: function( + (string | function({T1}, {T2}, ...: A): R), + number, number, + {T1}, {T2}, + ...: A + ): {R} + + product: function( + (string | function(T, U): R), + {T}, {U} + ): pl.array2d.Array2D + + extract_rows: function(pl.array2d.Array2D, {number}): pl.array2d.Array2D + extract_cols: function(pl.array2d.Array2D, {number}): pl.array2d.Array2D + + remove_row: function(pl.array2d.Array2D, number) + remove_col: function(pl.array2d.Array2D, number) + + parse_range: function(string): number, number, number, number + range: function(pl.array2d.Array2D, string): {T} + slice: function(pl.array2d.Array2D, number, number, number, number): {T} + set: function(pl.array2d.Array2D, T, number, number, number, number) + write: function(pl.array2d.Array2D, FILE, string, number, number, number, number) + + forall: function( + pl.array2d.Array2D, + (function({T}, number): any...), + (function(number): any...), + number, number, number, number + ) + move: function( + pl.array2d.Array2D, + number, number, + pl.array2d.Array2D, + number, number, number, number + ) + + iter: function( + pl.array2d.Array2D, boolean, + number, number, number, number + ): (function(): (T | {number, number, T})) + + columns: function(pl.array2d.Array2D): (function(): List) + end + + record class + metamethod __index: function(any, string): Class + metamethod __call: function(any, Class): Class + + record Class + class_of: function(Class, Instance): boolean + cast: function(Class, Instance) + end + + record Instance + -- FIXME this is not ideal, but I can't think of a better solution... + metamethod __index: function(Instance, any): any + + is_a: function(Instance, Class): boolean + end + end + + record compat + lua51: boolean + jit: boolean + jit52: boolean + is_windows: boolean + + dir_separator: string + + execute: function(string): boolean, number + + enum LoadMode + 'b' + 't' + 'bt' + end + load: function(any, string, LoadMode, {string: any}) + + getfenv: function(function): {string: any} + setfenv: function(function, {string: any}) + end + + record comprehension + type generator = (function(): {any}) + type parser = (function(string): generator) + new: function(): parser + end + + record config + enum ReadOpt + 'smart' + 'variabilize' + 'convert_numbers' + 'trim_space' + 'trim_quotes' + 'list_delim' + 'keysep' + end + + enum ReadError + 'not a file-like object' + 'file is nil' + end + + lines: function(FILE | string): function(): string, pl.config.ReadError + read: function(FILE | string, {pl.config.ReadOpt: any}): table, pl.config.ReadError + end + + record data + enum ReadOpt + 'delim' + 'fieldnames' + 'no_convert' + 'convert' + 'numfields' + 'last_field_collect' + 'thousands_dot' + 'csv' + end + + type rowiterator = function(): any... + + record Data + {{any}} + + fieldnames: pl.List + original_fieldnames: {string} + + column_by_name: function(pl.data.Data, string): pl.List + + select: function(pl.data.Data, string): pl.data.rowiterator + select_row: function(pl.data.Data, string): function(): {any} + + copy_select: function(pl.data.Data, string): Data + column_names: function(pl.data.Data): {string} + + write_row: function(pl.data.Data, FILE, {any}) + + write: function(pl.data.Data, FILE) + read: function(FILE | string, {pl.data.ReadOpt: any}): pl.data.Data, string + end + write: function(array2d.Array2D, FILE, {string}, string): boolean, string + + new: function({{any}}, {string}) + + query: function(pl.data.Data, (string | table), {table}, boolean): pl.data.rowiterator, string + filter: function(string, FILE | string, FILE | string, boolean) + end + + record dir + fnmatch: function(string, string): boolean + filter: function({string}, string): pl.List + + copyfile: function(string, string, boolean): boolean + movefile: function(string, string): boolean + makepath: function(string): boolean, string + rmtree: function(string): boolean, string + clonetree: function(string, string, (function(string, string): any)) + + getfiles: function(string, string): pl.List + getdirectories: function(string): pl.List + walk: function(string, boolean, boolean): (function(): string, pl.List, pl.List) + + dirtree: function(string): (function(): string, boolean) + getallfiles: function(string, string): pl.List + end + + record file + -- TODO copy declarations from other functions + -- this whole module is just renaming of other functions + read: function(string, boolean): string | nil, string + write: function(filename: string, str: string, is_bin: boolean): boolean | nil, string + end + + record func + record PHExp end + + _0: pl.func.PHExp + _1: pl.func.PHExp + _2: pl.func.PHExp + _3: pl.func.PHExp + _4: pl.func.PHExp + _5: pl.func.PHExp + + -- FIXME properly define return type of this... thing + import: function(string, {any: function}) + register: function(function, string): function + + tail: function({T}): {T} + + isPE: function(table): boolean + repr: function(pl.func.PHExp): string + instantiate: function(pl.func.PHExp): function + I: function(pl.func.PHExp): function + + -- FIXME this is horrible... + bind1: function((function(T): U), T): (function(): U) + bind1: function((function(T1, T2): U), T1): (function(T2): U) + bind1: function( + (function(T1, T2, T3): U), + T1 + ): (function(T2, T3): U) + bind1: function( + (function(T1, T2, T3, T4): U), + T1 + ): (function(T2, T3, T4): U) + bind1: function( + (function(T1, T2, T3, T4, T5): U), T1 + ): (function(T2, T3, T4, T5): U) + bind1: function( + (function(T1, T2, T3, T4, T5, T6): U), T1 + ): (function(T2, T3, T4, T5, T6): U) + + -- FIXME Will these screw up the above definitions? + bind1: function((function(...: T): U), T): (function(...: T): U) + + compose: function( + (function(T): U), + (function(U): V) + ): (function(T): V) + + -- FIXME same as above + compose: function( + (function(...: T): U...), + (function(...: U): V...) + ): (function(...: T): V...) + compose: function( + (function(...: any): any...), + (function(...: any): any...) + ): (function(...: any): any...) + + -- FIXME same as above + bind: function((function(T, ...: any): U), T): (function(...: any): U) + + bind: function((function(T1, T2, ...: any): U), T1, T2): (function(...: any): U) + bind: function((function(T1, T2, ...: any): U), pl.func.PHExp, T2): (function(T1, ...: any): U) + + -- This is literally exponential, I am NOT doing a 4 parameter version + bind: function((function(T1, T2, T3, ...: any): U), T1, T2, T3): (function(...: any): U) + bind: function((function(T1, T2, T3, ...: any): U), pl.func.PHExp, T2, T3): (function(T1, ...: any): U) + bind: function((function(T1, T2, T3, ...: any): U), T1, pl.func.PHExp, T3): (function(T2, ...: any): U) + bind: function((function(T1, T2, T3, ...: any): U), pl.func.PHExp, pl.func.PHExp, T3): (function(T1, T2, ...: any): U) + bind: function((function(T1, T2, T3, ...: any): U), T1, T2, pl.func.PHExp): (function(T3, ...: any): U) + bind: function((function(T1, T2, T3, ...: any): U), pl.func.PHExp, T2, pl.func.PHExp): (function(T1, T3, ...: any): U) + bind: function((function(T1, T2, T3, ...: any): U), T1, pl.func.PHExp, pl.func.PHExp): (function(T2, T3, ...: any): U) + end + + import_into: function(table): (table, table) + + record input + type linegetter = function(...: any): string + type source = string | table + + enum FieldsOpt + 'no_fail' + end + + alltokens: function(pl.input.linegetter, string, function(string): T): (function(): T) + create_getter: function(source): pl.input.linegetter + numbers: function(source): (function(): number) + words: function(source): (function(): string) + + -- {fields, nil} is a hacky substitute for a 1-tuple type + fields: function({number, nil}, string, source, {pl.input.FieldsOpt: any}): (function(): string) + fields: function( + {number, number}, + string, + source, + {pl.input.FieldsOpt: any} + ): (function(): string, string) + fields: function( + {number, number, number}, + string, + source, + {pl.input.FieldsOpt: any} + ): (function(): string, string, string) + fields: function( + {number, number, number, number}, + string, + source, + {pl.input.FieldsOpt: any} + ): (function(): string, string, string, string) + fields: function( + {number} | number, + string, + source, + {pl.input.FieldsOpt: any} + ): (function(): string...) + end + + record lapp + enum argtype + 'string' + 'number' + 'file' + 'file-in' + 'boolean' + end + + show_usage_error: boolean + + quit: function(string, boolean) + open: function(string, string): FILE + error: function(string, boolean) + assert: function(boolean, string) + add_type: function(string, (argtype | function(string): any), function(any)) + process_options_string: function(string, {string}): {string: any} + + metamethod __call: function(pl.lapp, string, {string}): {string: any} + end + + record lexer + type token = {string, string} + type tokenaction = function(string, {string: any}): (string, string) + type tokendesc = {string, pl.lexer.tokenaction} + type tokenstream = function(any): (string, string) + + scan: function( + string | FILE, + {tokendesc, tokenaction}, + {string: boolean}, + {string: any} + ): tokenstream + lua: function( + string | FILE, + {string: boolean}, + {string: any} + ) + cpp: function( + string | FILE, + {string: boolean}, + {string: any} + ) + + insert: function(pl.lexer.tokenstream, string, string) + insert: function(pl.lexer.tokenstream, {pl.lexer.token} | pl.lexer.tokenstream) + + getline: function(pl.lexer.tokenstream): string + getrest: function(pl.lexer.tokenstream): string + lineno: function(pl.lexer.tokenstream): number, number + get_keywords: function(): {string: boolean} + + get_separated_list: function( + pl.lexer.tokenstream, + string, + string + ): {{pl.lexer.token}}, pl.lexer.token + + skipws: function(pl.lexer.tokenstream): pl.lexer.token + expecting: function( + pl.lexer.tokenstream, + string, + boolean + ): pl.lexer.token + end + + record luabalanced + match_string: function(string, number): string, number + match_bracketed: function(string, number): string, number + match_expression: function(string, number): string, number + match_namelist: function(string, number): string, number + match_explist: function(string, number): string, number + + enum snippettype + 'e' + 'c' + 's' + end + match_gsub: function( + string, + (function(pl.luabalanced.snippettype, string): string) + ): string + end + + record operator + enum OpRepr + '+' + '-' + '*' + '/' + '%' + '^' + '..' + '()' + '[]' + '<' + '<=' + '>' + '>=' + '==' + '~=' + '#' + 'and' + 'or' + '{}' + '~' + '' + end + + optable: {pl.operator.OpRepr: function} + + -- TODO properly annotate types as in func + call: function(function, ...: any): any... + index: function(table, any): any + + eq: function(any, any): boolean + neq: function(any, any): boolean + lt: function(any, any): boolean + le: function(any, any): boolean + gt: function(any, any): boolean + ge: function(any, any): boolean + + len: function(string | table): number + + add: function(number, number): number + sub: function(number, number): number + mul: function(number, number): number + div: function(number, number): number + pow: function(number, number): number + mod: function(number, number): number + unm: function(number): number + concat: function(string, string): string + + add: function(any, any): any + sub: function(any, any): any + mul: function(any, any): any + div: function(any, any): any + pow: function(any, any): any + mod: function(any, any): any + unm: function(any): any + concat: function(any, any): any + + lnot: function(any): boolean + land: function(any, any): boolean + lor: function(any, any): boolean + + table: function(...: any): {any} + match: function(string, string): boolean + nop: function(...: any) + end + + record path + is_windows: boolean + sep: string + dirsep: string + + dir: function(string): function(): string + mkdir: function(string): boolean, string + rmdir: function(string): boolean, string + + currentdir: function(): string + chdir: function(string): boolean, string + + getsize: function(string): number + + isdir: function(string): boolean + isfile: function(string): boolean + isabs: function(string): boolean + exists: function(string): boolean + + getatime: function(string): number + getmtime: function(string): number + getctime: function(string): number + + splitpath: function(string): string, string + splitext: function(string): string, string + + abspath: function(string, string): string + dirname: function(string): string + basename: function(string): string + extension: function(string): string + + -- 2 mandatory parts + join: function(string, string, ...: string): string + + normcase: function(string): string + normpath: function(string): string + relpath: function(string, string): string + expanduser: function(string): string + + tmpname: function(): string + common_prefix: function(string, string): string + package_path: function(string): string, string + + -- TODO attrib (is there a way to + -- copy these and functions from lfs.d.tl?) + -- TODO linkattrib + end + + record permute + iter: function({any}): (function(): {any}) + table: function({any}): {{any}} + end + + record pretty + read: function(string): table, string + load: function(string, table, boolean): table, string + write: function(table, string, boolean): string, string + dump: function(table, string) + debug: function(...: any) + + enum PrettyNumberKind + 'N' + 'M' + 'T' + end + number: function(number, pl.pretty.PrettyNumberKind, number) + end + + record seq + matching: function(string): (function(string): number, number, any...) + list: function({T}): (function(): T) + + -- TODO check if this is an OK overload + keys: function(table): (function(): any) + keys: function({K: any}): (function(): K) + + range: function(number, number): (function(): number) + minmax: function({T} | function(): T): T, T + sum: function({T} | function(): T): T, number + sum: function({T} | function(): T, function(T): U): U, number + + copy: function({T} | function(): T): pl.List + copy2: function((function(T1, T2): R1, R2), T1, T2): {{R1, R2}} + copy_tuples: function(function(): any...): {{any}} + + random: function(number, number, number): (function(): number) + sort: function((function(): T), function(T, T): boolean): (function(): T) + zip: function((function(): T), (function(): U)): (function(): T, U) + printall: function({T} | function(): T, string, number, function(T): string) + + -- The official documentation is wrong, this only returns 1 value + count_map: function({T} | function(): T): pl.Map + + -- TODO + map: function((function(T): U), {T} | function(): T): (function(): U) + map: function((function(T1, T2): U), ({T1} | function(): T1), T2): (function(): U) + map: function((function(T1, T2): U), ({{T1, T2}} | function(): T1, T2)): (function(): U) + + filter: function(({T} | function(): T), (function(T): boolean)): (function(): T) + filter: function(({T} | function(): T), (function(T, U): boolean), U): (function(): T) + + reduce: function((function(R, T): R), ({T} | function(): T), R): R + take: function(({T} | function(): T), number): function(): T + take: function((function(): T, U), number): function(): T, U + + skip: function({T}, number): {T} + skip: function((function(): T), number): {T} + + enum: function(({T} | function(): T)): function(): number, T + enum: function((function(): T, U)): function(): number, T, U + + -- TODO Is this necessary? + mapmethod: function(({table} | function(): table), string): function(): any + mapmethod: function(({table} | function(T): table), string, T): function(): any + mapmethod: function(({table} | function(T, U): table), string, T, U): function(): any + + last: function(({T} | function(): T)): function(): T, T + + foreach: function(({T} | function(): T), (function(T))) + + lines: function(string | FILE, ...: any): function(): any... + end + + record sip + enum PatCompileOpt + 'at_start' + end + type matcher = function(string, table): boolean + + create_pattern: function(string, {pl.sip.PatCompileOpt: boolean}): string, {string}|string, {any} + compile: function(string, {pl.sip.PatCompileOpt: boolean}): matcher, {string}|string + match: function(string, string, table, {PatCompileOpt: boolean}): boolean + match_at_start: function(string, string, table): boolean + end + + record strict + module: function(table): table + module: function(table, table): table + module: function(string, table, table): table + + make_all_strict: function(table) + + closed_module: function(table, string) + end + + record stringio + record WriteBuffer + write: function(pl.stringio.WriteBuffer, {string | number}) + end + record ReadBuffer + read: function(...: string): any... + end + + create: function(): pl.stringio.WriteBuffer + open: function(string): pl.stringio.ReadBuffer + end + + record stringx + isalpha: function(string): boolean + isdigit: function(string): boolean + isalnum: function(string): boolean + isspace: function(string): boolean + islower: function(string): boolean + isupper: function(string): boolean + startswith: function(string): boolean + endswith: function(string): boolean + + join: function(string, {string} | function(): string): string + splitlines: function(string, boolean): pl.List + split: function(string, string, string): pl.List + expandtabs: function(string, number): string + + lfind: function(string, string, number, number): number + rfind: function(string, string, number, number): number + replace: function(string, string, string, number): string + count: function(string, string, boolean): number + + ljust: function(string, number, string): string + rjust: function(string, number, string): string + center: function(string, number, string): string + lstrip: function(string, string): string + rstrip: function(string, string): string + strip: function(string, string): string + + splitv: function(string, string): string, string... + partition: function(string, string): string, string, string + rpartition: function(string, string): string, string, string + at: function(string, number): string + + lines: function(string): function(): string + + title: function(string): string + shorten: function(string, number, boolean): string + quote_string: function(string): string + end + + record tablex + size: function(table): number + + index_by: function(table, {any}): pl.List + index_by: function({T: U}, {T}): pl.List + + -- TODO check if these are OK + transform: function((function(T): U), {any: T}) + transform: function((function(T, A): U), {any: T}, A) + transform: function((function(T): U), {T}) + transform: function((function(T, A): U), {T}, A) + transform: function((function(any, A)), table, A) + + range: function(number, number, number): {number} + reduce: function((function(R, T): R), {T}, R): R + index_map: function({T: U}): {U: T} + + makeset: function({T}): {T: boolean} + union: function({T: any}, {T: any}): {T: any} + intersection: function({T: any}, {T: any}): {T: any} + merge: function({T: any}, {T: any}, boolean): {T: any} + difference: function({T: any}, {T: any}, boolean): {T: any} + + count_map: function({T}, function(T, T): boolean): {T: number} + set: function({T}, T, number, number) + new: function(number, T): {T} + clear: function({T}, number) + + removevalues: function({T}, number, number) + readonly: function(table): table + + update: function(table, table): table + copy: function(table): table + deepcopy: function(table): table + icopy: function({T}, {T}, number, number, number) + + insertvalues: function({T}, {T}) + insertvalues: function({T}, number, {T}) + + compare: function({T}, {T}, function(T, T): boolean): boolean + deepcompare: function(table, table, boolean, number): boolean + compare_no_order: function({T}, {T}, function(T, T): boolean): boolean + + find: function({T}, T, number): number + rfind: function({T}, T, number): number + + type cmpf = function(T, U): boolean + find_if: function({T}, cmpf, U): number, R + + search: function(table, any, {table}): string + + map: function((function(T): R), {K: T}): {K: R} + map: function((function(T, A): R), {K: T}, A): {K: R} + + imap: function((function(T): R), {T}): {R} + imap: function((function(T, A): R), {T}, A): {R} + + map_named_method: function(string, {table}, ...: any): pl.List + + map2: function((function(T, U, A): R), {any: T}, {any: U}, A): {any: R} + imap2: function((function(T, U, A): R), {T}, {U}, A): {R} + mapn: function((function(...: T): R), ...: {T}): {R} + pairmap: function((function(K, V): R)): {R} + + filter: function({T}, (function(T): boolean)): pl.List + filter: function({T}, (function(T, A): boolean), A): pl.List + + foreach: function({ T }, function(T)) + foreach: function((function(V, K)), {K: V}) + foreach: function((function(V, K, A)), {K: V}, A) + foreachi: function((function(V, number)), {V}) + foreachi: function((function(V, number, A)), {V}, A) + + sort: function({K: V}, cmpf): function(): K, V + sortv: function({K: V}, cmpf): function(): K, V + + keys: function({any}): pl.List + keys: function({K: any}): pl.List + values: function({any: V}): pl.List + values: function({V}): pl.List + + sub: function({V}, number, number): pl.List + zip: function(...: {T}): {{T}} + zip: function({T1}, {T2}): {{T1, T2}} + zip: function({T1}, {T2}, {T3}): {{T1, T2, T3}} + end + + record template + record CompiledTemplate + render: function(pl.template.CompiledTemplate, table, table, boolean): string + end + + enum CompileOpt + 'chunk_name' + 'escape' + 'inline_escape' + 'inline_brackets' + 'newline' + 'debug' + end + + substitute: function(string, table): string, string, string + compile: function(string, {pl.template.CompileOpt: any}): pl.template.CompiledTemplate, string, string + end + + record test + error_handler: function(string, number, string, string, string) + complain: function(any, any, string, number) + assertmatch: function(string, string, number) + assertraise: function(function, string, number) + asserteq: function(any, any, number, number) + asserteq2: function(any, any, any, any, number, number) + tuple: function(...: any): {any} + + timer: function(string, number, function): number + timer: function(string, number, function(A), A): number + end + + record text + format_operator: function + + indent: function(string, number, string): string + dedent: function(string): string + wrap: function(string, number): pl.List + fill: function(string, number): string + + record Template + -- metamethod __call -- TODO + substitute: function(pl.text.Template, {string: any}): string + safe_substitute: function(pl.text.Template, {string: any}): string + indent_substitute: function(pl.text.Template, {string: any}): string + end + end + + record types + type: function(any): string + + is_type: function(any, any): boolean + is_callable: function(any): boolean + is_integer: function(number): boolean + is_empty: function(any, boolean) + is_indexable: function(any): boolean + is_iterable: function(any): boolean + is_writeable: function(any): boolean + + to_bool: function(any, {string}, boolean): boolean + end + + record url + quote: function(string, boolean): string + unquote: function(string): string + end + + record utils + record packedarray + {T} + n: number + end + pack: function(...: T): pl.utils.packedarray + unpack: function({T}, number, number) + printf: function(string, ...: any) + fprintf: function(FILE, string, ...: any) + import: function(string | table, table) + choose: function(boolean, T, T): T + + array_tostring: function({T}, table, function(T, number): string): string + is_type: function(any, string | metatable): boolean + + enum knownpattern + 'FLOAT' + 'INTEGER' + 'IDEN' + 'FILE' + end + patterns: {pl.utils.knownpattern: string} + + enum knownmt + 'List' + 'Map' + 'Set' + 'MultiMap' + end + record stdmt_entry + _name: string + end + + stdmt: {pl.utils.knownmt: pl.utils.stdmt_entry} + + function_arg: function(number, function | string, string): function + assert_arg: function( + number, + T, + string | metatable, + (function(any): boolean), + string, + number + ): T + assert_string: function(number, T): T + + enum errormode + 'default' + 'error' + 'quit' + end + on_error: function(pl.utils.errormode) + raise: function(string) + + readfile: function(string, boolean): string + writefile: function(string, string, boolean): boolean, string + readlines: function(string, boolean): {string} + + executeex: function(string, boolean): boolean, number, string, string + quote_arg: function(string | {string}): string + quit: function(string, ...: any) + quit: function(number, string, ...: any) + + escape: function(string): string + split: function(string, string, boolean, number): {string} + splitv: function(string, string): string... + + -- T must be callable, but this should be a good enough compromise + -- to guarantee function signature remains intact after memoization + memoize: function(T): T + + add_function_factory: function(metatable, (function(T): function)) + string_lambda: function(string): function(...: any): any... + bind1: function((string | function(T, U, ...: any): R), T): function(U, ...: any): R + bind2: function((string | function(T, U, ...: any): R), U): function(T, ...: any): R + end + + record xml + + end +end + +return pl diff --git a/types/pl/Date.d.tl b/types/pl/Date.d.tl new file mode 100644 index 0000000..3962683 --- /dev/null +++ b/types/pl/Date.d.tl @@ -0,0 +1 @@ +return require "pl".Date diff --git a/types/pl/List.d.tl b/types/pl/List.d.tl new file mode 100644 index 0000000..35b739c --- /dev/null +++ b/types/pl/List.d.tl @@ -0,0 +1 @@ +return require "pl".List diff --git a/types/pl/Map.d.tl b/types/pl/Map.d.tl new file mode 100644 index 0000000..47efa79 --- /dev/null +++ b/types/pl/Map.d.tl @@ -0,0 +1 @@ +return require "pl".Map diff --git a/types/pl/app.d.tl b/types/pl/app.d.tl new file mode 100644 index 0000000..08574b4 --- /dev/null +++ b/types/pl/app.d.tl @@ -0,0 +1 @@ +return require "pl".app diff --git a/types/pl/array2d.d.tl b/types/pl/array2d.d.tl new file mode 100644 index 0000000..9f27c78 --- /dev/null +++ b/types/pl/array2d.d.tl @@ -0,0 +1 @@ +return require "pl".array2d diff --git a/types/pl/class.d.tl b/types/pl/class.d.tl new file mode 100644 index 0000000..026c6c7 --- /dev/null +++ b/types/pl/class.d.tl @@ -0,0 +1 @@ +return require "pl".class diff --git a/types/pl/compat.d.tl b/types/pl/compat.d.tl new file mode 100644 index 0000000..a91df56 --- /dev/null +++ b/types/pl/compat.d.tl @@ -0,0 +1 @@ +return require "pl".compat diff --git a/types/pl/comprehension.d.tl b/types/pl/comprehension.d.tl new file mode 100644 index 0000000..435eca4 --- /dev/null +++ b/types/pl/comprehension.d.tl @@ -0,0 +1 @@ +return require "pl".comprehension diff --git a/types/pl/config.d.tl b/types/pl/config.d.tl new file mode 100644 index 0000000..fcec1b8 --- /dev/null +++ b/types/pl/config.d.tl @@ -0,0 +1 @@ +return require "pl".config diff --git a/types/pl/data.d.tl b/types/pl/data.d.tl new file mode 100644 index 0000000..c0a78f7 --- /dev/null +++ b/types/pl/data.d.tl @@ -0,0 +1 @@ +return require "pl".data diff --git a/types/pl/dir.d.tl b/types/pl/dir.d.tl new file mode 100644 index 0000000..341f8f6 --- /dev/null +++ b/types/pl/dir.d.tl @@ -0,0 +1 @@ +return require "pl".dir diff --git a/types/pl/file.d.tl b/types/pl/file.d.tl new file mode 100644 index 0000000..f901f88 --- /dev/null +++ b/types/pl/file.d.tl @@ -0,0 +1 @@ +return require "pl".file diff --git a/types/pl/func.d.tl b/types/pl/func.d.tl new file mode 100644 index 0000000..84c9796 --- /dev/null +++ b/types/pl/func.d.tl @@ -0,0 +1 @@ +return require "pl".func diff --git a/types/pl/input.d.tl b/types/pl/input.d.tl new file mode 100644 index 0000000..46016c0 --- /dev/null +++ b/types/pl/input.d.tl @@ -0,0 +1 @@ +return require "pl".input diff --git a/types/pl/lapp.d.tl b/types/pl/lapp.d.tl new file mode 100644 index 0000000..591ff3c --- /dev/null +++ b/types/pl/lapp.d.tl @@ -0,0 +1 @@ +return require "pl".lapp diff --git a/types/pl/lexer.d.tl b/types/pl/lexer.d.tl new file mode 100644 index 0000000..5de3a13 --- /dev/null +++ b/types/pl/lexer.d.tl @@ -0,0 +1 @@ +return require "pl".lexer diff --git a/types/pl/luabalanced.d.tl b/types/pl/luabalanced.d.tl new file mode 100644 index 0000000..3b2654d --- /dev/null +++ b/types/pl/luabalanced.d.tl @@ -0,0 +1 @@ +return require "pl".luabalanced diff --git a/types/pl/operator.d.tl b/types/pl/operator.d.tl new file mode 100644 index 0000000..d252e3b --- /dev/null +++ b/types/pl/operator.d.tl @@ -0,0 +1 @@ +return require "pl".operator diff --git a/types/pl/path.d.tl b/types/pl/path.d.tl new file mode 100644 index 0000000..7000dc5 --- /dev/null +++ b/types/pl/path.d.tl @@ -0,0 +1 @@ +return require "pl".path diff --git a/types/pl/permute.d.tl b/types/pl/permute.d.tl new file mode 100644 index 0000000..28b4be1 --- /dev/null +++ b/types/pl/permute.d.tl @@ -0,0 +1 @@ +return require "pl".permute diff --git a/types/pl/pretty.d.tl b/types/pl/pretty.d.tl new file mode 100644 index 0000000..d0106bf --- /dev/null +++ b/types/pl/pretty.d.tl @@ -0,0 +1 @@ +return require "pl".pretty diff --git a/types/pl/seq.d.tl b/types/pl/seq.d.tl new file mode 100644 index 0000000..a026476 --- /dev/null +++ b/types/pl/seq.d.tl @@ -0,0 +1 @@ +return require "pl".seq diff --git a/types/pl/sip.d.tl b/types/pl/sip.d.tl new file mode 100644 index 0000000..f7591ee --- /dev/null +++ b/types/pl/sip.d.tl @@ -0,0 +1 @@ +return require "pl".sip diff --git a/types/pl/strict.d.tl b/types/pl/strict.d.tl new file mode 100644 index 0000000..1285e3e --- /dev/null +++ b/types/pl/strict.d.tl @@ -0,0 +1 @@ +return require "pl".strict diff --git a/types/pl/stringio.d.tl b/types/pl/stringio.d.tl new file mode 100644 index 0000000..5f35816 --- /dev/null +++ b/types/pl/stringio.d.tl @@ -0,0 +1 @@ +return require "pl".stringio diff --git a/types/pl/stringx.d.tl b/types/pl/stringx.d.tl new file mode 100644 index 0000000..415cf1f --- /dev/null +++ b/types/pl/stringx.d.tl @@ -0,0 +1 @@ +return require "pl".stringx diff --git a/types/pl/tablex.d.tl b/types/pl/tablex.d.tl new file mode 100644 index 0000000..4569a8d --- /dev/null +++ b/types/pl/tablex.d.tl @@ -0,0 +1 @@ +return require("pl").tablex diff --git a/types/pl/template.d.tl b/types/pl/template.d.tl new file mode 100644 index 0000000..0bba715 --- /dev/null +++ b/types/pl/template.d.tl @@ -0,0 +1 @@ +return require "pl".template diff --git a/types/pl/test.d.tl b/types/pl/test.d.tl new file mode 100644 index 0000000..3dafe9c --- /dev/null +++ b/types/pl/test.d.tl @@ -0,0 +1 @@ +return require "pl".test diff --git a/types/pl/text.d.tl b/types/pl/text.d.tl new file mode 100644 index 0000000..5c38b3f --- /dev/null +++ b/types/pl/text.d.tl @@ -0,0 +1 @@ +return require "pl".text diff --git a/types/pl/types.d.tl b/types/pl/types.d.tl new file mode 100644 index 0000000..b92c16c --- /dev/null +++ b/types/pl/types.d.tl @@ -0,0 +1 @@ +return require "pl".types diff --git a/types/pl/url.d.tl b/types/pl/url.d.tl new file mode 100644 index 0000000..9ac180e --- /dev/null +++ b/types/pl/url.d.tl @@ -0,0 +1 @@ +return require "pl".url diff --git a/types/pl/utils.d.tl b/types/pl/utils.d.tl new file mode 100644 index 0000000..5d41fe0 --- /dev/null +++ b/types/pl/utils.d.tl @@ -0,0 +1 @@ +return require "pl".utils diff --git a/types/pl/xml.d.tl b/types/pl/xml.d.tl new file mode 100644 index 0000000..2883aea --- /dev/null +++ b/types/pl/xml.d.tl @@ -0,0 +1 @@ +return require "pl".xml diff --git a/types/socket.d.tl b/types/socket.d.tl new file mode 100644 index 0000000..c7fc6b1 --- /dev/null +++ b/types/socket.d.tl @@ -0,0 +1,158 @@ +local ltn12 = require("ltn12") +local Sink = ltn12.Sink +local Source = ltn12.Source + +local record socket + record TCP + -- master methods + bind: function(TCP, string, integer) + connect: function(TCP, string, integer): integer, string + listen: function(TCP, integer): integer, string + + -- client methods + getpeername: function(TCP): string, integer + + enum TCPReceivePattern + "*l" + "*a" + end + enum TCPReceiveError + "closed" + "timeout" + end + receive: function(TCP, TCPReceivePattern|integer, string): string, TCPReceiveError + + send: function(TCP, string, integer, integer): integer, string, integer + + enum TCPShutdownMode + "both" + "send" + "receive" + end + shutdown: function(TCP, TCPShutdownMode): integer + + -- server methods + accept: function(TCP): TCP, string + + -- client and server methods + enum TCPOption + "keepalive" + "reuseaddr" + "tcp-nodelay" + end + enum TCPLinger + "linger" + end + record TCPLingerOption + on: boolean + timeout: integer + end + setoption: function(TCP, TCPOption): integer + setoption: function(TCP, TCPLinger, TCPLingerOption): integer + + -- master, client, and server methods + close: function(TCP) + + getsockname: function(TCP): string, integer + + getstats: function(TCP): integer, integer, integer + + setstats: function(TCP, integer, integer, integer): integer + + enum TCPTimeoutMode + "b" + "t" + end + settimeout: function(TCP, integer, TCPTimeoutMode) + end + record UDP + close: function(UDP) + + getpeername: function(UDP): string, integer + + getsockname: function(UDP): string, integer + + enum UDPTimeout + "timeout" + end + receive: function(UDP, integer): string, UDPTimeout + + receivefrom: function(UDP, integer): string, string, integer, UDPTimeout + + send: function(UDP, string): integer, string + + sendto: function(UDP, string, string, integer): integer, string + + setpeername: function(UDP, string, integer): integer, string + + setsockname: function(UDP, string, integer): integer, string + + enum UDPOptions + "dontroute" + "broadcast" + end + setoption: function(UDP, UDPOptions, boolean): integer, string + + settimeout: function(UDP, integer) + end + tcp: function(): TCP, string + + udp: function(): UDP, string + + record dns + record DNSResolved + name: string + alias: {string} + ip: {string} + end + toip: function(): string + tohostname: function(string): string, DNSResolved|string + gethostname: function(string): string, DNSResolved|string + end + + bind: function(string, integer, integer): TCP + + connect: function(string, integer, string, integer): TCP + + _DEBUG: boolean + + newtry: function(function): function + + protect: function(function): function + + -- tagged records/Table Union types would be nice here, + -- as this should be {TCP|UDP} + -- but I imagine this should be fine for most uses + select: function({UDP}, {UDP}, integer): {UDP}, {UDP}, string + select: function({TCP}, {TCP}, integer): {TCP}, {TCP}, string + + enum SinkMode + "http-chunked" + "close-when-done" + "keep-open" + end + + sink: function(SinkMode, UDP): Sink + sink: function(SinkMode, TCP): Sink + + skip: function(integer, ...: any): any... + + sleep: function(integer) + + enum SourceMode + "http-chunked" + "by-length" + "until-closed" + end + + source: function(SourceMode, TCP, integer): Source + source: function(SourceMode, UDP, integer): Source + + gettime: function(): integer + + try: function(...: any): any... + + _VERSION: string +end + +return socket diff --git a/types/socket/ftp.d.tl b/types/socket/ftp.d.tl new file mode 100644 index 0000000..f996b07 --- /dev/null +++ b/types/socket/ftp.d.tl @@ -0,0 +1,39 @@ +local ltn12 = require("ltn12") +local type Pump = ltn12.Pump +local type Sink = ltn12.Sink + +local record ftp + get: function(string): string, string + record FTPGetInfo + host: string + sink: Sink + argument: string + path: string + user: string + password: string + command: string + port: integer + type: string + step: Pump + create: function() + end + get: function(FTPGetInfo): integer, string + + record FTPPutInfo + host: string + source: Sink -- yes, this is a sink + argument: string + path: string + user: string + password: string + command: string + port: integer + type: string + step: Pump + create: function() + end + put: function(string, string): integer, string + put: function(FTPPutInfo): integer, string +end + +return ftp diff --git a/types/socket/http.d.tl b/types/socket/http.d.tl new file mode 100644 index 0000000..27ba24d --- /dev/null +++ b/types/socket/http.d.tl @@ -0,0 +1,28 @@ +local ltn12 = require("ltn12") +local type Pump = ltn12.Pump +local type Sink = ltn12.Sink +local type Source = ltn12.Source + +local record http + request: function(string): string, integer|string, string, string + request: function(string, string): string, integer|string, string, string + record HTTPRequest + url: string + sink: Sink + method: string + headers: {string:string} + source: Source + step: Pump + proxy: string + redirect: boolean + create: function + end + request: function(HTTPRequest): string, integer|string, string, string + + PORT: integer + PROXY: string + TIMEOUT: integer + USERAGENT: string +end + +return http diff --git a/types/socket/smtp.d.tl b/types/socket/smtp.d.tl new file mode 100644 index 0000000..542d406 --- /dev/null +++ b/types/socket/smtp.d.tl @@ -0,0 +1,32 @@ +local ltn12 = require("ltn12") +local type Pump = ltn12.Pump +local type Source = ltn12.Source + +local record smtp + record Message + headers: {string:string} + body: Source | string | MultipartMessage + end + record MultipartMessage + {Message} + preamble: string + epilogue: string + end + message: function(Message): Source + + record SMTPSendFormat + from: string + rcpt: string | {string} + source: Source + user: string + password: string + server: string + port: integer + domain: string + step: Pump + create: function + end + send: function(SMTPSendFormat): integer, string +end + +return smtp diff --git a/types/socket/url.d.tl b/types/socket/url.d.tl new file mode 100644 index 0000000..ee947a2 --- /dev/null +++ b/types/socket/url.d.tl @@ -0,0 +1,25 @@ +local record url + record ParsedUrl + url: string + scheme: string + authority: string + path: string + params: string + query: string + fragment: string + userinfo: string + host: string + port: string + user: string + password: string + end + + absolute: function(string, string): string + build: function(ParsedUrl): string + build_path: function({string}, any): string + escape: function(string): string + parse: function(string, table): ParsedUrl + parse_path: function(string): {string} + unescape: function(string): string +end +return url diff --git a/types/web_sanitize.d.tl b/types/web_sanitize.d.tl new file mode 100644 index 0000000..f94455f --- /dev/null +++ b/types/web_sanitize.d.tl @@ -0,0 +1,16 @@ +local record Web_Sanitize + sanitize_html: function(unsafe_html: string): string + extract_text: function(unsafe_html: string): string + sanitize_style: function(unsafe_style_attributes: string): string + + record whitelist + clone: function(): whitelist + tags: table + add_attributes: table + self_closing: table + end + + Sanitizer: function(parameters: table): function(unsafe_html: string): string +end + +return Web_Sanitize diff --git a/types/web_sanitize/query/scan_html.d.tl b/types/web_sanitize/query/scan_html.d.tl new file mode 100644 index 0000000..05f0ae2 --- /dev/null +++ b/types/web_sanitize/query/scan_html.d.tl @@ -0,0 +1,23 @@ +local record Scanner + record HTMLNode + tag: string + type: string | nil + num: number + self_closing: boolean | nil + attr: table + outer_html: function(self: HTMLNode): string + inner_html: function(self: HTMLNode): string + inner_text: function(self: HTMLNode): string + -- TODO : add replacement methods + end + + record NodeStack + -- stack[n] - get the nth item in the stack (as an HTMLNode) + current: function(self: NodeStack): HTMLNode + is: function(self: NodeStack, query: string): boolean + end + + scan_html: function(html_text: string, callback: function(stack: NodeStack), opts: table) +end + +return Scanner