├── manage
├── resources
├── print-namespace.tex
├── test.zip
├── images
│ ├── cast.png
│ ├── node.id.png
│ ├── tex.sp.png
│ ├── node.write.png
│ ├── LPeg_alias-01.png
│ ├── LPeg_alias-02.png
│ ├── Screenshot_CTAN.png
│ ├── tex.sp_overload.png
│ ├── Screenshot_LuaCATS.png
│ ├── node.id_definition.png
│ ├── node.id_wrong-type.png
│ ├── PreLinebreakFilterCallback.png
│ ├── Screenshot_VSCode-extension.png
│ ├── PdfColorstockWhatsitNode.data.png
│ └── Screenshot_Lua-Addon-Manager.png
├── screencasts
│ └── node.new.gif
├── update-lls-addons.sh
├── webpages
│ ├── md5.html.lua
│ ├── md5.html
│ ├── zip.html.lua
│ ├── zip.html
│ ├── socket.html.lua
│ ├── mime.html.lua
│ ├── mime.html
│ └── socket.html
└── namespaces
│ └── luametatex_luaonly.md
├── .gitignore
├── stylua.toml
├── search.sh
├── docs
├── Lua-language-servers.md
└── Lua-language-servers.tex
├── .vscode
├── settings.json
└── snippets.code-snippets
├── Makefile
├── .gitmodules
├── LICENSE
├── utils.lua
└── README.md
/manage:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | ./manager/.venv/bin/manager --base-path="$(pwd)" "$@"
4 |
--------------------------------------------------------------------------------
/resources/print-namespace.tex:
--------------------------------------------------------------------------------
1 |
2 | \directlua{require('resources/print-namespace.lua')()}
3 | \bye
4 |
--------------------------------------------------------------------------------
/resources/test.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/test.zip
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist/*
2 | tmp_cleaned.lua
3 | tmp.tex
4 | tmp.lua
5 | tmp.txt
6 | test.gz
7 | tmp.log
8 | tmp.pdf
9 |
--------------------------------------------------------------------------------
/resources/images/cast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/cast.png
--------------------------------------------------------------------------------
/resources/images/node.id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/node.id.png
--------------------------------------------------------------------------------
/resources/images/tex.sp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/tex.sp.png
--------------------------------------------------------------------------------
/resources/images/node.write.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/node.write.png
--------------------------------------------------------------------------------
/resources/images/LPeg_alias-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/LPeg_alias-01.png
--------------------------------------------------------------------------------
/resources/images/LPeg_alias-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/LPeg_alias-02.png
--------------------------------------------------------------------------------
/resources/images/Screenshot_CTAN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/Screenshot_CTAN.png
--------------------------------------------------------------------------------
/resources/images/tex.sp_overload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/tex.sp_overload.png
--------------------------------------------------------------------------------
/resources/screencasts/node.new.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/screencasts/node.new.gif
--------------------------------------------------------------------------------
/resources/images/Screenshot_LuaCATS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/Screenshot_LuaCATS.png
--------------------------------------------------------------------------------
/resources/images/node.id_definition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/node.id_definition.png
--------------------------------------------------------------------------------
/resources/images/node.id_wrong-type.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/node.id_wrong-type.png
--------------------------------------------------------------------------------
/resources/images/PreLinebreakFilterCallback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/PreLinebreakFilterCallback.png
--------------------------------------------------------------------------------
/resources/images/Screenshot_VSCode-extension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/Screenshot_VSCode-extension.png
--------------------------------------------------------------------------------
/resources/images/PdfColorstockWhatsitNode.data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/PdfColorstockWhatsitNode.data.png
--------------------------------------------------------------------------------
/resources/images/Screenshot_Lua-Addon-Manager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Josef-Friedrich/LuaTeX_Lua-API/HEAD/resources/images/Screenshot_Lua-Addon-Manager.png
--------------------------------------------------------------------------------
/stylua.toml:
--------------------------------------------------------------------------------
1 | syntax = "Lua53"
2 | column_width = 120
3 | line_endings = "Unix"
4 | indent_type = "Spaces"
5 | indent_width = 2
6 | quote_style = "AutoPreferDouble"
7 | call_parentheses = "Always"
8 | collapse_simple_statement = "Never"
9 | space_after_function_names = "Never"
10 |
11 | [sort_requires]
12 | enabled = true
13 |
--------------------------------------------------------------------------------
/search.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | # --context=num
4 | # Print num lines of leading and trailing output context.
5 | grep \
6 | --context=3 \
7 | --group-separator=----------------------------------------- \
8 | --recursive \
9 | --line-number \
10 | --colour \
11 | "$*" \
12 | /usr/local/src/luatex \
13 | "$HOME/repos/tex/mailing_lists" \
14 | /usr/local/texlive \
15 | .
16 |
--------------------------------------------------------------------------------
/resources/update-lls-addons.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | LUA_HOME="${HOME}/repos/lua"
4 | ROOT="${LUA_HOME}/lls_addons"
5 |
6 | rm -rf "${ROOT}"
7 |
8 | git clone --recurse-submodules git@github.com:TeXLuaCATS/LLS-Addons.git "${ROOT}"
9 |
10 | cd "${ROOT}"
11 |
12 | # https://stackoverflow.com/a/7244456
13 | git remote add upstream git@github.com:LuaLS/LLS-Addons.git
14 | git fetch upstream
15 | git checkout main
16 | git rebase upstream/main
17 | git push -u origin main
18 |
19 | UPDATE_BRANCH="update_$(date +%F)"
20 |
21 | git push -d origin update_2025-08-03
22 |
23 | git branch "$UPDATE_BRANCH"
24 | git checkout "$UPDATE_BRANCH"
25 |
26 | ADDONS="\
27 | lmathx
28 | lpeg
29 | luasocket
30 | luazip
31 | lzlib
32 | md5
33 | slnunicode
34 | tex-lualatex
35 | tex-lualibs
36 | tex-luametatex
37 | tex-luatex\
38 | "
39 |
40 | _update() {
41 | local ADDON_ROOT="${ROOT}/addons/$1/module"
42 | echo "
43 | ${ADDON_ROOT}"
44 | cd "${ADDON_ROOT}"
45 | git checkout main
46 | git pull
47 | stylua "${ADDON_ROOT}/library"
48 | }
49 |
50 | for ADDON in $ADDONS; do
51 | _update $ADDON
52 | done
53 |
54 | cd "${ROOT}"
55 |
56 | git add -Av
57 | git commit -m "Update TeX related submodules to the latest version"
58 |
59 | git push -u origin "$UPDATE_BRANCH"
60 |
--------------------------------------------------------------------------------
/docs/Lua-language-servers.md:
--------------------------------------------------------------------------------
1 | ### Overview of the existing Lua language server
2 |
3 | #### lua-language-server
4 |
5 | The most popular language server, simply named
6 | [lua-language-server](https://github.com/LuaLS/lua-language-server), was
7 | created by a Chinese with the nickname
8 | [*sumneko*](https://github.com/sumneko). In addition to the nickname,
9 | *sumnekos* Github profile also shows 最萌小汐 in Chinese characters,
10 | which means “The cutest Xiaoxi”[^google-translate] or “Xiao Shi, the
11 | most adorable child in the world”[^deepl]. The [first
12 | commit](https://github.com/LuaLS/lua-language-server/commit/3546129c29fbfd7211099a3fbee03a763915ab58)
13 | in the Git repository was made on 7 September 2018. The
14 | *lua-language-server* is written in Lua. In August 2025, the repository
15 | on Gibhub has around 3,800 stars.
16 |
17 | [^google-translate]: https://translate.google.de/?sl=zh-CN&tl=en&text=%E6%9C%80%E8%90%8C%E5%B0%8F%E6%B1%90%20&op=translate
18 | [^deepl]: https://www.deepl.com/en/translator#zh/en-gb/%E6%9C%80%E8%90%8C%E5%B0%8F%E6%B1%90
19 |
20 | ### EmmyLua Analyzer Rust
21 |
22 | A promising language server that is not written in Lua but in Rust is
23 | the [EmmyLua Analyzer
24 | Rust](https://github.com/EmmyLuaLs/emmylua-analyzer-rust). This server
25 | was written by [CppCXY](https://github.com/CppCXY), the developer with
26 | the most commits after sumneko. The new server is advertised in
27 | [several](https://github.com/LuaLS/lua-language-server/issues/2910)
28 | [issues](https://github.com/LuaLS/lua-language-server/issues/3017) in
29 | the sumnekos *lua-language-server* Github repository.
30 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.formatting.provider": "black",
3 | // https://github.com/sumneko/lua-language-server/wiki/Libraries
4 | "Lua.workspace.library": [
5 | "./TeXLuaCATS/LuaTeX/library",
6 | "${addons}/busted/module/library",
7 | "${3rd}/luassert/library"
8 | ],
9 | "[lua]": {
10 | "editor.defaultFormatter": "JohnnyMorganz.stylua",
11 | "editor.rulers": [80]
12 | },
13 | "Lua.diagnostics.disable": [
14 | "duplicate-set-field",
15 | "param-type-mismatch"
16 | ],
17 | "files.exclude": {
18 | "**/_minted*/": true,
19 | "**/*.aux": true,
20 | "**/*.fdb_latexmk": true,
21 | "**/*.fls": true,
22 | "**/*.glo": true,
23 | "**/*.gls": true,
24 | "**/*.hd": true,
25 | "**/*.idx": true,
26 | "**/*.ilg": true,
27 | "**/*.ind": true,
28 | "**/*.log": true,
29 | "**/*.out": true,
30 | "**/*.synctex.gz": true,
31 | "**/*.synctex": true,
32 | "**/*.synctex*": true,
33 | "**/*.tar.gz": false,
34 | "**/*.toc": true
35 | },
36 | // "latex-workshop.latex.recipes": [
37 | // {
38 | // "name": "luatex",
39 | // "tools": ["luatex"]
40 | // }
41 | // ],
42 | // "latex-workshop.latex.tools": [
43 | // {
44 | // "name": "luatex",
45 | // "command": "luatex",
46 | // "args": [
47 | // "--synctex=1",
48 | // "--interaction=nonstopmode",
49 | // "--file-line-error",
50 | // "%DOC%"
51 | // ],
52 | // "env": {}
53 | // }
54 | // ],
55 | "Lua.workspace.checkThirdParty": false,
56 | "Lua.format.defaultConfig": {
57 | "indent_style": "space",
58 | "indent_size": "2"
59 | },
60 | "Lua.format.enable": true
61 | }
62 |
--------------------------------------------------------------------------------
/docs/Lua-language-servers.tex:
--------------------------------------------------------------------------------
1 | \documentclass{ltxdoc}
2 | \usepackage{standalone}
3 |
4 | \begin{document}
5 | \subsubsection{Overview of the existing Lua language server}
6 |
7 | \paragraph{lua-language-server}
8 |
9 | The most popular language server, simply named
10 | \href{https://github.com/LuaLS/lua-language-server}{lua-language-server
11 | }, was created by a Chinese with the nickname
12 | \href{https://github.com/sumneko}{\emph{sumneko}}. In addition to the
13 | nickname, \emph{sumnekos} Github profile also shows 最萌小汐 in Chinese
14 | characters, which means “The cutest
15 | Xiaoxi”\href{https://translate.google.de/?sl=zh-CN&tl=en&text=\%E6\%9C\%80
16 | \%E8\%90\%8C\%E5\%B0\%8F\%E6\%B1\%90\%20&op=translate}{google-translate} or
17 | “Xiao Shi, the most adorable child in the
18 | world”\href{https://www.deepl.com/en/translator#zh/en-gb/\%E6\%9C\%80\%E8\%9
19 | 0\%8C\%E5\%B0\%8F\%E6\%B1\%90}{deepl}. The
20 | \href{https://github.com/LuaLS/lua-language-server/commit/3546129c29fbf
21 | d7211099a3fbee03a763915ab58}{firstcommit} in the Git repository was
22 | made on 7 September 2018. The \emph{lua-language-server} is written in
23 | Lua. In August 2025, the repository on Gibhub has around 3,800 stars.
24 |
25 | \subsubsection{EmmyLua Analyzer Rust}
26 |
27 | A promising language server that is not written in Lua but in Rust is
28 | the \href{https://github.com/EmmyLuaLs/emmylua-analyzer-rust}{EmmyLua
29 | AnalyzerRust}. This server was written by
30 | \href{https://github.com/CppCXY}{CppCXY}, the developer with the most
31 | commits after sumneko. The new server is advertised in
32 | \href{https://github.com/LuaLS/lua-language-server/issues/2910}{several
33 | }
34 | \href{https://github.com/LuaLS/lua-language-server/issues/3017}{issues}
35 | in the sumnekos \emph{lua-language-server} Github repository.
36 |
37 | \end{document}
38 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | jobname = luatex-type-definitions
2 | texmf = $(HOME)/texmf
3 | texmftex = $(texmf)/tex/luatex
4 | installdir = $(texmftex)/$(jobname)
5 |
6 | .PHONY: all
7 | all: format
8 |
9 | .PHONY: format
10 | format:
11 | ./manage format
12 |
13 | .PHONY: convert
14 | convert:
15 | ./manage convert
16 |
17 | .PHONY: debug
18 | debug:
19 | luatex --luaonly debug.lua
20 |
21 | .PHONY: print_namespace
22 | print_namespace:
23 | luatex resources/print-namespace.tex
24 |
25 | .PHONY: dist
26 | dist:
27 | ./manage dist
28 |
29 | .PHONY: update_lls_addons
30 | update_lls_addons:
31 | resources/update-lls-addons.sh
32 |
33 | .PHONY: submodules
34 | submodules:
35 | ./manage submodules
36 |
37 | .PHONY: submodules_init
38 | submodules_init:
39 | git submodule update --init --recursive --remote
40 | cd manager; make install
41 |
42 | .PHONY: test
43 | test:
44 | ./manage test
45 |
46 | .PHONY: doc
47 | doc:
48 | lualatex --shell-escape $(jobname)-doc.tex
49 | makeindex -s gglo.ist -o $(jobname)-doc.gls $(jobname)-doc.glo
50 | makeindex -s gind.ist -o $(jobname)-doc.ind $(jobname)-doc.idx
51 | lualatex --shell-escape $(jobname)-doc.tex
52 | mkdir -p $(texmf)/doc
53 | cp $(jobname)-doc.pdf $(texmf)/doc/$(jobname).pdf
54 |
55 | .PHONY: ctan
56 | ctan: doc dist_rsync
57 | rm -rf $(jobname)
58 | rm -rf $(jobname).tar.gz
59 | mkdir $(jobname)
60 | ./manage merge luatex
61 | $(HOME)/.cargo/bin/stylua $(jobname)
62 | cp -f README.md $(jobname)
63 | cp -f $(jobname)-doc.tex $(jobname)
64 | cp -f $(jobname)-doc.pdf $(jobname)
65 | tar cvfz $(jobname).tar.gz $(jobname)
66 | # rm -rf $(jobname)
67 |
68 | .PHONY: clean
69 | clean:
70 | git clean -dfX
71 |
72 | .PHONY: download_manuals
73 | download_manuals:
74 | ./manage manuals
75 |
76 | .PHONY: update_manual
77 | update_manual:
78 | wget -O /usr/local/texlive/texmf-dist/doc/luatex/base/luatex.pdf https://gitlab.lisn.upsaclay.fr/texlive/luatex/-/raw/master/manual/luatex.pdf
79 | wget -O /usr/local/texlive/texmf-dist/doc/context/documents/general/manuals/luametatex.pdf https://raw.githubusercontent.com/contextgarden/context/main/doc/context/documents/general/manuals/luametatex.pdf
80 |
81 | LUATEX = ./manage example --print-docstring --subproject luatex
82 |
83 | .PHONY: namespace_luametatex
84 | namespace_luametatex:
85 | $(LUATEX) luametatex/namespace.lua
86 | .PHONY: namespace_luametatex_luaonly
87 | namespace_luametatex_luaonly:
88 | luametatex --luaonly examples/luatex/namespace.lua
89 |
90 | .PHONY: namespace_luatex
91 | namespace_luatex:
92 | $(LUATEX) namespace.lua
93 |
94 | .PHONY: namespace_luatex_luaonly
95 | namespace_luatex_luaonly:
96 | luatex --luaonly examples/luatex/namespace_luaonly.lua
97 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "resources/LuaCATS/upstream/lmathx"]
2 | path = LuaCATS/upstream/lmathx
3 | url = git@github.com:LuaCATS/lmathx.git
4 | [submodule "resources/LuaCATS/upstream/lpeg"]
5 | path = LuaCATS/upstream/lpeg
6 | url = git@github.com:LuaCATS/lpeg.git
7 | [submodule "resources/LuaCATS/upstream/luaharfbuzz"]
8 | path = LuaCATS/upstream/luaharfbuzz
9 | url = git@github.com:LuaCATS/luaharfbuzz.git
10 | [submodule "resources/LuaCATS/upstream/luasocket"]
11 | path = LuaCATS/upstream/luasocket
12 | url = git@github.com:LuaCATS/luasocket.git
13 | [submodule "resources/LuaCATS/upstream/luazip"]
14 | path = LuaCATS/upstream/luazip
15 | url = git@github.com:LuaCATS/luazip.git
16 | [submodule "resources/LuaCATS/upstream/lzlib"]
17 | path = LuaCATS/upstream/lzlib
18 | url = git@github.com:LuaCATS/lzlib.git
19 | [submodule "resources/LuaCATS/upstream/md5"]
20 | path = LuaCATS/upstream/md5
21 | url = git@github.com:LuaCATS/md5.git
22 | [submodule "resources/LuaCATS/upstream/slnunicode"]
23 | path = LuaCATS/upstream/slnunicode
24 | url = git@github.com:LuaCATS/slnunicode.git
25 | [submodule "resources/LuaCATS/downstream/tex-lualatex"]
26 | path = LuaCATS/downstream/tex-lualatex
27 | url = git@github.com:LuaCATS/tex-lualatex.git
28 | [submodule "resources/LuaCATS/downstream/tex-luatex"]
29 | path = LuaCATS/downstream/tex-luatex
30 | url = git@github.com:LuaCATS/tex-luatex.git
31 | [submodule "resources/LuaCATS/downstream/tex-lualibs"]
32 | path = LuaCATS/downstream/tex-lualibs
33 | url = git@github.com:LuaCATS/tex-lualibs.git
34 | [submodule "resources/LuaCATS/downstream/tex-luametatex"]
35 | path = LuaCATS/downstream/tex-luametatex
36 | url = git@github.com:LuaCATS/tex-luametatex.git
37 | [submodule "resources/vscode_extension"]
38 | path = vscode_extension
39 | url = git@github.com:TeXLuaCATS/vscode_extension.git
40 | [submodule "doc-generators/rust"]
41 | path = doc-generators/rust
42 | url = git@github.com:TeXLuaCATS/emmylua-analyzer-rust.git
43 | [submodule "subrepos/Lua-TeX/LuaTeX"]
44 | path = TeXLuaCATS/LuaTeX
45 | url = git@github.com:TeXLuaCATS/LuaTeX.git
46 | [submodule "subrepos/TeXLuaCATS/Lualibs"]
47 | path = TeXLuaCATS/Lualibs
48 | url = git@github.com:TeXLuaCATS/Lualibs.git
49 | [submodule "TeXLuaCATS/LuaLaTeX"]
50 | path = TeXLuaCATS/LuaLaTeX
51 | url = git@github.com:TeXLuaCATS/LuaLaTeX.git
52 | [submodule "TeXLuaCATS/LuaOTFload"]
53 | path = TeXLuaCATS/LuaOTFload
54 | url = git@github.com:TeXLuaCATS/LuaOTFload.git
55 | [submodule "TeXLuaCATS/LuaMetaTeX"]
56 | path = TeXLuaCATS/LuaMetaTeX
57 | url = git@github.com:TeXLuaCATS/LuaMetaTeX.git
58 | [submodule "manager"]
59 | path = manager
60 | url = git@github.com:TeXLuaCATS/manager.git
61 | [submodule "doc-generator"]
62 | path = doc-generator
63 | url = git@github.com:TeXLuaCATS/doc-generator.git
64 |
--------------------------------------------------------------------------------
/resources/webpages/md5.html.lua:
--------------------------------------------------------------------------------
1 | ---
2 | ---Cryptographic Library for Lua 5.0
3 | ---
4 | ---
5 | ---This library offers basic cryptographic facilities for Lua 5.0:
6 | ---a hash (digest) function, an a pair crypt/decrypt.
7 | ---(download)
8 | ---
9 | ---
10 | ---Lua API
11 | ---
12 | ---All functions are registered inside a table `md5`.
13 | ---
14 | ---
15 | ---
16 | ---* `md5.sum (message)`
17 | ---
18 | ---Computes the MD5 message-digest of the string `message`.
19 | ---This function takes as input a message of arbitrary length and content
20 | ---and returns as output a 128-bit "fingerprint" (or "message digest")
21 | ---of the input.
22 | ---The output is formated as a binary string with 16 characters.
23 | ---It is conjectured that it is computationally infeasible to produce
24 | ---two messages having the same message digest, or to produce any
25 | ---message having a given pre-specified target message digest.
26 | ---(see
27 | ---RFC 1321)
28 | ---
29 | ---
30 | ---* `md5.sumhexa (message)`
31 | ---
32 | ---Similar to `md5.sum`,
33 | ---but returns its value as a string of 32 hexadecimal digits.
34 | ---
35 | ---* `md5.crypt (message, key [,seed])`
36 | ---
37 | ---Encrypts a string, using MD5 in CFB (Cipher-feedback mode).
38 | ---`message` is an arbitrary binary string to be encrypted.
39 | ---`key` is an arbitrary binary string to be used as a key.
40 | ---`seed` is an arbitrary binary string to be used as a seed;
41 | ---Returns the cyphertext (as a binary string).
42 | ---
43 | ---
44 | ---If no seed is provided,
45 | ---the function uses the result of `os.time()` as a seed.
46 | ---It is recommended that you use different seeds for each message;
47 | ---the seed itself is not private, and should contain no private data,
48 | ---because it goes plain in the beginning of the encrypted message.
49 | ---
50 | ---
51 | ---The length of the cyphertext is the length of the message plus the
52 | ---length of the seed plus one.
53 | ---
54 | ---
55 | ---* `md5.decrypt (message, key)`
56 | ---
57 | ---Decrypts a string.
58 | ---The input `message` must be the result of a previous call
59 | ---to `crypt`.
60 | ---For any `msg`, `key`,
61 | ---and `seed`, we have that
62 | ---```
63 | --- md5.decrypt(md5.crypt(msg, key, seed), key) == msg
64 | ---```
65 | ---
66 | ---
67 | ---* `md5.exor (s1, s2)`
68 | ---
69 | ---Does a bit-a-bit exclusive or of strings `s1` and `s2`.
70 | ---Both strings must have the same length,
71 | ---which will be also the length of the resulting string.
72 | ---
73 | ---
74 | ---
75 | ---
76 | ---
77 | ---C API
78 | ---
79 | ---The following functions are declared in `md5.h`
80 | ---
81 | ---
82 | ---* `int luaopen_md5 (lua_State *L);`
83 | ---
84 | ---Opens the library:
85 | ---Registers the above Lua functions in the given state.
86 | ---
87 | ---
88 | ---* `void md5 (const char *message, long len, char *output);`
89 | ---
90 | ---Computes the MD5 message-digest of `message`.
91 | ---`len` is the length of `message`.
92 | ---`output` is a buffer that receives the result;
93 | ---it must have at least 16 bytes (128 bits).
94 | ---
95 | ---
96 | ---
97 | ---
98 | ---INSTALL
99 | ---
100 | ---The following instructions assume that your Lua installation has a dynamic
101 | ---linking facility (function `loadlib`):
102 | ---
103 | ---
104 | ---
105 | ---* Build a shared library (`.so`, `.dll`, etc.)
106 | ---with files `md5.c` and `md5lib.c`.
107 | ---(There is a `makefile` for Linux and similar systems.)
108 | ---
109 | ---* Put the shared library somewhere,
110 | ---and edit file `md5.lua` to point to it.
111 | ---
112 | ---* Put the file `md5.lua` in a directory of your
113 | ---`LUA_PATH`.
114 | ---
115 | ---
116 | ---
117 | ---
118 | ---$Id: md5.html,v 1.4 2003/04/28 16:40:42 roberto Exp $
119 | ---
120 | ---
121 | ---
122 | ---
123 | ---
--------------------------------------------------------------------------------
/resources/webpages/md5.html:
--------------------------------------------------------------------------------
1 |
2 |
Cryptographic Library for Lua 5.0
3 |
4 |
5 | This library offers basic cryptographic facilities for Lua 5.0:
6 | a hash (digest) function, an a pair crypt/decrypt.
7 | (download)
8 |
9 |
10 |
Lua API
11 |
12 | All functions are registered inside a table md5.
13 |
14 |
15 |
16 |
md5.sum (message)
17 |
18 | Computes the MD5 message-digest of the string message.
19 | This function takes as input a message of arbitrary length and content
20 | and returns as output a 128-bit "fingerprint" (or "message digest")
21 | of the input.
22 | The output is formated as a binary string with 16 characters.
23 | It is conjectured that it is computationally infeasible to produce
24 | two messages having the same message digest, or to produce any
25 | message having a given pre-specified target message digest.
26 | (see
27 | RFC 1321)
28 |
29 |
30 |
md5.sumhexa (message)
31 |
32 | Similar to md5.sum,
33 | but returns its value as a string of 32 hexadecimal digits.
34 |
35 |
md5.crypt (message, key [,seed])
36 |
37 | Encrypts a string, using MD5 in CFB (Cipher-feedback mode).
38 | message is an arbitrary binary string to be encrypted.
39 | key is an arbitrary binary string to be used as a key.
40 | seed is an arbitrary binary string to be used as a seed;
41 | Returns the cyphertext (as a binary string).
42 |
43 |
44 | If no seed is provided,
45 | the function uses the result of os.time() as a seed.
46 | It is recommended that you use different seeds for each message;
47 | the seed itself is not private, and should contain no private data,
48 | because it goes plain in the beginning of the encrypted message.
49 |
50 |
51 | The length of the cyphertext is the length of the message plus the
52 | length of the seed plus one.
53 |
54 |
55 |
md5.decrypt (message, key)
56 |
57 | Decrypts a string.
58 | The input message must be the result of a previous call
59 | to crypt.
60 | For any msg, key,
61 | and seed, we have that
62 |
69 | Does a bit-a-bit exclusive or of strings s1 and s2.
70 | Both strings must have the same length,
71 | which will be also the length of the resulting string.
72 |
73 |
74 |
75 |
76 |
77 |
C API
78 |
79 | The following functions are declared in md5.h
80 |
81 |
82 |
int luaopen_md5 (lua_State *L);
83 |
84 | Opens the library:
85 | Registers the above Lua functions in the given state.
86 |
90 | Computes the MD5 message-digest of message.
91 | len is the length of message.
92 | output is a buffer that receives the result;
93 | it must have at least 16 bytes (128 bits).
94 |
95 |
96 |
97 |
98 |
INSTALL
99 |
100 | The following instructions assume that your Lua installation has a dynamic
101 | linking facility (function loadlib):
102 |
103 |
104 |
105 |
Build a shared library (.so, .dll, etc.)
106 | with files md5.c and md5lib.c.
107 | (There is a makefile for Linux and similar systems.)
108 |
109 |
Put the shared library somewhere,
110 | and edit file md5.lua to point to it.
111 |
112 |
Put the file md5.lua in a directory of your
113 | LUA_PATH.
114 |
115 |
116 |
117 |
118 | $Id: md5.html,v 1.4 2003/04/28 16:40:42 roberto Exp $
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/.vscode/snippets.code-snippets:
--------------------------------------------------------------------------------
1 | {
2 | "examples": {
3 | "prefix": [
4 | "example"
5 | ],
6 | "body": [
7 | "\n---",
8 | "---__Example:__",
9 | "---",
10 | "---```${1:lua}",
11 | "---$0",
12 | "---```",
13 | "---"
14 | ],
15 | "description": "An code example."
16 | },
17 | "for-example": {
18 | "prefix": [
19 | "fexample",
20 | "forexample"
21 | ],
22 | "body": [
23 | ", for example `$0`."
24 | ],
25 | "description": "Inline code example"
26 | },
27 | "references": {
28 | "prefix": [
29 | "reference"
30 | ],
31 | "body": [
32 | "",
33 | "---",
34 | "---__Reference:__",
35 | "---",
36 | "---* [$2]($1)",
37 | "---$0"
38 | ],
39 | "description": "Reference heading"
40 | },
41 | "referenceLuaTeXManual": {
42 | "prefix": [
43 | "manual"
44 | ],
45 | "body": [
46 | "",
47 | "---* `LuaTeX` manual: ${1:chapter} “${2:title}” page ${3:page}",
48 | "---$0"
49 | ],
50 | "description": "* `LuaTeX` manual: "
51 | },
52 | "referenceSourceLuaTeXManual": {
53 | "prefix": [
54 | "source"
55 | ],
56 | "body": [
57 | "",
58 | "---* Source file of the `LuaTeX` manual: [$2]($1)",
59 | "---$0"
60 | ],
61 | "description": "* Source file of the `LuaTeX` manual"
62 | },
63 | "link": {
64 | "prefix": [
65 | "link"
66 | ],
67 | "body": [
68 | "",
69 | "---* [$2]($1)",
70 | "---$0"
71 | ],
72 | "description": "* item and markdown link"
73 | },
74 | "referenceC": {
75 | "prefix": [
76 | "c",
77 | "ccode"
78 | ],
79 | "body": [
80 | "",
81 | "---",
82 | "---* Corresponding C source code: [$2]($1)",
83 | "---$0"
84 | ],
85 | "description": "* Corresponding C source code: "
86 | },
87 | "referenceLua": {
88 | "prefix": [
89 | "l",
90 | "lcode"
91 | ],
92 | "body": [
93 | "",
94 | "---",
95 | "---* Corresponding Lua source code: [$2]($1)",
96 | "---$0"
97 | ],
98 | "description": "* Corresponding Lua source code: "
99 | },
100 | "referenceCLines": {
101 | "prefix": [
102 | "l",
103 | "ccode"
104 | ],
105 | "body": [
106 | "",
107 | "---",
108 | "---* Corresponding C source code: [luafflib.c#L$1-L$2](https://gitlab.lisn.upsaclay.fr/texlive/luatex/-/blob/f52b099f3e01d53dc03b315e1909245c3d5418d3/source/texk/web2c/luatexdir/luafontloader/src/luafflib.c#L$1-L$2)",
109 | "---$0"
110 | ],
111 | "description": "* Corresponding C source code: only line numbers"
112 | },
113 | "referenceCpp": {
114 | "prefix": [
115 | "p",
116 | "cpp"
117 | ],
118 | "body": [
119 | "",
120 | "---",
121 | "---* cppreference.com: [$2]($1)",
122 | "---$0"
123 | ],
124 | "description": "* cppreference.com"
125 | },
126 | "referenceHarfBuzz": {
127 | "prefix": [
128 | "h",
129 | "harf"
130 | ],
131 | "body": [
132 | "",
133 | "---",
134 | "---* HarfBuzz online documentation: [$2]($1)",
135 | "---$0"
136 | ],
137 | "description": "* HarfBuzz online documentation: "
138 | },
139 | "referenceWikibooks": {
140 | "prefix": [
141 | "wikibook"
142 | ],
143 | "body": [
144 | "",
145 | "---* [Wikibook/TeX](https://en.wikibooks.org/wiki/TeX/$1)",
146 | "---$0"
147 | ],
148 | "description": "Link to Wikibooks / TeX"
149 | },
150 | "referenceTeXbyTopic": {
151 | "prefix": [
152 | "texbytopic"
153 | ],
154 | "body": [
155 | "",
156 | "---* [TeX by Topic, page $1](http://mirrors.ctan.org/info/texbytopic/TeXbyTopic.pdf)",
157 | "---$0"
158 | ],
159 | "description": "Link to CTAN version of TeX by Topic"
160 | },
161 | "return": {
162 | "prefix": [
163 | "return"
164 | ],
165 | "body": [
166 | "",
167 | "---",
168 | "---@return $0"
169 | ],
170 | "description": "@return"
171 | },
172 | "param": {
173 | "prefix": [
174 | "param"
175 | ],
176 | "body": [
177 | "",
178 | "---",
179 | "---@param $0"
180 | ],
181 | "description": "@param"
182 | },
183 | "see": {
184 | "prefix": [
185 | "see"
186 | ],
187 | "body": [
188 | "",
189 | "---",
190 | "---@see $0"
191 | ],
192 | "description": "@see"
193 | },
194 | "alias": {
195 | "prefix": [
196 | "alias"
197 | ],
198 | "body": [
199 | "",
200 | "---",
201 | "---@alias $1 $2 $0"
202 | ],
203 | "description": "@alias"
204 | },
205 | "type": {
206 | "prefix": [
207 | "type"
208 | ],
209 | "body": [
210 | "",
211 | "---",
212 | "---@type $1"
213 | ],
214 | "description": "@alias"
215 | },
216 | "class": {
217 | "prefix": [
218 | "class"
219 | ],
220 | "body": [
221 | "",
222 | "---",
223 | "---@class $1 $0"
224 | ],
225 | "description": "@class"
226 | },
227 | "as": {
228 | "prefix": [
229 | "a",
230 | "as"
231 | ],
232 | "body": [
233 | " --[[@as ]] $1 $0"
234 | ],
235 | "description": "@as"
236 | },
237 | "direct": {
238 | "prefix": [
239 | "direct"
240 | ],
241 | "body": [
242 | "node.direct.$0 = node.$0"
243 | ],
244 | "description": "node.direct.xxx = node.xxx"
245 | },
246 | "linebreak": {
247 | "prefix": [
248 | "-"
249 | ],
250 | "body": [
251 | "",
252 | "---",
253 | "---"
254 | ],
255 | "description": "---"
256 | },
257 | "inspect": {
258 | "prefix": [
259 | "i",
260 | "inspect"
261 | ],
262 | "body": [
263 | "",
264 | "local inspect = require('inspect')",
265 | "print(inspect())",
266 | "local function printi(data) print(inspect(data)) end"
267 | ],
268 | "description": "---"
269 | },
270 | "man": {
271 | "prefix": [
272 | "m",
273 | "man"
274 | ],
275 | "body": [
276 | "",
277 | "---* [man3/$1](https://man7.org/linux/man-pages/man3/$1.3.html)"
278 | ],
279 | "description": "man"
280 | },
281 | "`code`": {
282 | "body": [
283 | "`${TM_SELECTED_TEXT:text}`"
284 | ],
285 | "prefix": "code"
286 | }
287 | }
288 |
--------------------------------------------------------------------------------
/resources/webpages/zip.html.lua:
--------------------------------------------------------------------------------
1 | ---
3 | ---
4 | ---
5 | --- LuaZip: Reading files inside zip files
6 | ---
7 | ---
8 | ---
9 | ---
10 | ---
11 | ---
12 | ---
13 | ---
14 | ---
15 | ---
16 | ---
17 | --- LuaZip
18 | --- Reading files inside zip files
19 | ---
20 | ---
21 | ---
22 | ---
23 | ---
24 | ---LuaZip
25 | ---
26 | --- * Home
27 | ---
28 | --- * Overview
29 | --- * Status
30 | --- * Download
31 | --- * History
32 | --- * Credits
33 | --- * Contact
34 | ---
35 | ---
36 | --- * Manual
37 | ---
38 | --- * Introduction
39 | --- * Building
40 | --- * Installation
41 | --- * Reference
42 | ---
43 | ---
44 | --- * Examples
45 | --- * Project
46 | ---
47 | --- * Bug Tracker
48 | --- * CVS
49 | ---
50 | ---
51 | --- * License
52 | ---
53 | ---
54 | ---
55 | ---
56 | ---
57 | ---
58 | ---Introduction
59 | ---
60 | ---LuaZip is a lightweight Luaextension library
61 | ---that can be used to read files stored inside zip files. It uses
62 | ---zziplibto do all the hard work.
63 | ---
64 | ---The API exposed to Lua is very simple and very similiar to the usual file handling
65 | ---functions provided by the
66 | ---I/O Lua standard library.
67 | ---In fact, the API is so similar that parts of this manual are extracted from the Lua manual,
68 | ---copyrighted by Tecgraf, PUC-Rio.
69 | ---
70 | ---Building
71 | ---
72 | ---
73 | ---LuaZip could be built to Lua 5.0 or to Lua 5.1.
74 | ---In both cases, the language library and headers files for the target version
75 | ---must be installed properly.
76 | ---
77 | ---
78 | ---
79 | ---LuaZip offers a Makefile and a separate configuration file,
80 | ---`config`, which should be edited to suit your installation
81 | ---before runnig `make`.
82 | ---The file has some definitions like paths to the external libraries,
83 | ---compiler options and the like.
84 | ---One important definition is the version of Lua language,
85 | ---which is not obtained from the installed software.
86 | ---
87 | ---
88 | ---LuaZip compilation depends on
89 | ---zziplib 0.13.49and
90 | ---zlib 1.2.3.
91 | ---
92 | ---
93 | ---Installation
94 | ---
95 | ---The LuaZip compiled binary should be copied to a directory in your
96 | ---C path.
97 | ---Lua 5.0 users should also install Compat-5.1.
98 | ---
99 | ---
100 | ---Reference
101 | ---
102 | ---
103 | --- zip.open (filename)
104 | --- This function opens a zip file and returns a new zip file handle. In case of
105 | --- error it returns nil and an error message. Unlike `io.open`, there is no
106 | --- `mode` parameter, as the only supported mode is "read".
107 | ---
108 | --- zip.openfile (filename [, extensions]])
109 | --- This function opens a file and returns a file handle. In case of
110 | --- error it returns nil and an error message. Unlike `io.open`, there is no
111 | --- `mode` parameter, as the only supported mode is "read".
112 | --- This function implements a virtual file system based on optionally compressed files.
113 | --- Instead of simply looking for a file at a given path, this function goes recursively up
114 | --- through all path separators ("/") looking for zip files there. If it finds a zip file,
115 | --- this function use the remaining path to open the requested file.
116 | --- The optional parameter extensionsallows the use of file extensions other than .zip
117 | --- during the lookup. It can be a string corresponding to the extension or an indexed table
118 | --- with the lookup extensions sequence.
119 | ---
120 | --- zfile:close ()
121 | --- This function closes a zfile opened by `zip.open`
122 | ---
123 | --- zfile:files ()
124 | --- Returns an iterator function that returns a new table containing the
125 | --- following information each time it is called:
126 | ---
127 | --- * `filename`: the full path of a file
128 | --- * `compressed_size`: the compressed size of the file in bytes
129 | --- * `uncompressed_size`: the uncompressed size of the file in bytes
130 | ---
131 | ---
132 | ---
133 | --- zfile:open (filename)
134 | --- This function opens a file that is stored inside the zip file opened by `zip.open`.
135 | --- The filename may contain the full path of the file contained inside the zip. The
136 | --- directory separator must be '/'.
137 | --- Unlike `f:open`, there is no `mode` parameter, as the only
138 | --- supported mode is "read".
139 | ---
140 | --- file:read (format1, ...)
141 | --- Reads a `file` according to the given formats, which specify what to read.
142 | --- For each format, the function returns a string with the characters read, or nil if it cannot read
143 | --- data with the specified format. When called without formats, it uses a default format that reads
144 | --- the entire next line (see below).
145 | --- The available formats are:
146 | ---
147 | --- * `"*a"`: reads the whole file, starting at the current position. On end of file, it
148 | --- returns the empty string.
149 | --- * `"*l"`: reads the next line (skipping the end of line), returns nil on end of file.
150 | --- This is the default format.
151 | --- * `number`: reads a string with up to that number of characters, returning nil
152 | --- on end of file.
153 | ---
154 | ---
155 | --- Unlike the standard I/O read, the format `"*n"` is not supported.
156 | ---
157 | --- file:seek ([whence] [, offset])
158 | --- Sets and gets the file position, measured from the beginning of the file, to the position given
159 | --- by `offset` plus a base specified by the string `whence`, as follows:
160 | ---
161 | --- * `set`: base is position 0 (beginning of the file);
162 | --- * `cur`: base is current position;
163 | --- * `end`: base is end of file;
164 | ---
165 | --- In case of success, function `seek` returns the final file position, measured in bytes
166 | --- from the beginning of the file. If this function fails, it returns nil, plus an error string.
167 | --- The default value for `whence` is `"cur"`, and for `offset` is 0.
168 | --- Therefore, the call `file:seek()` returns the current file position, without changing
169 | --- it; the call `file:seek("set")` sets the position to the beginning of the file (and returns 0);
170 | --- and the call `file:seek("end")` sets the position to the end of the file, and returns its
171 | --- size.
172 | ---
173 | --- file:close ()
174 | --- This function closes a file opened by `zfile:open`.
175 | ---
176 | --- file:lines ()
177 | --- Returns an iterator function that returns a new line from the file each time it is called.
178 | --- Therefore, the construction
179 | --- ```for line in file:lines() do ... end```
180 | --- will iterate over all lines of the file.
181 | ---
182 | ---
183 | ---
184 | ---
185 | ---
186 | ---
187 | ---
188 | ---
189 | --- $Id: manual.html,v 1.12 2007-06-18 18:47:05 carregal Exp $
190 | ---
191 | ---
192 | ---
193 | ---
194 | ---
195 | ---
196 | ---
--------------------------------------------------------------------------------
/resources/webpages/zip.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | LuaZip: Reading files inside zip files
6 |
7 |
8 |
9 |
10 |
11 |
LuaZip is a lightweight Lua extension library
61 | that can be used to read files stored inside zip files. It uses
62 | zziplib to do all the hard work.
63 |
64 |
The API exposed to Lua is very simple and very similiar to the usual file handling
65 | functions provided by the
66 | I/O Lua standard library.
67 | In fact, the API is so similar that parts of this manual are extracted from the Lua manual,
68 | copyrighted by Tecgraf, PUC-Rio.
69 |
70 |
Building
71 |
72 |
73 | LuaZip could be built to Lua 5.0 or to Lua 5.1.
74 | In both cases, the language library and headers files for the target version
75 | must be installed properly.
76 |
77 |
78 |
79 | LuaZip offers a Makefile and a separate configuration file,
80 | config, which should be edited to suit your installation
81 | before runnig make.
82 | The file has some definitions like paths to the external libraries,
83 | compiler options and the like.
84 | One important definition is the version of Lua language,
85 | which is not obtained from the installed software.
86 |
The LuaZip compiled binary should be copied to a directory in your
96 | C path.
97 | Lua 5.0 users should also install Compat-5.1.
98 |
99 |
100 |
Reference
101 |
102 |
103 |
zip.open (filename)
104 |
This function opens a zip file and returns a new zip file handle. In case of
105 | error it returns nil and an error message. Unlike io.open, there is no
106 | mode parameter, as the only supported mode is "read".
107 |
108 |
zip.openfile (filename [, extensions]])
109 |
This function opens a file and returns a file handle. In case of
110 | error it returns nil and an error message. Unlike io.open, there is no
111 | mode parameter, as the only supported mode is "read".
112 | This function implements a virtual file system based on optionally compressed files.
113 | Instead of simply looking for a file at a given path, this function goes recursively up
114 | through all path separators ("/") looking for zip files there. If it finds a zip file,
115 | this function use the remaining path to open the requested file.
116 | The optional parameter extensions allows the use of file extensions other than .zip
117 | during the lookup. It can be a string corresponding to the extension or an indexed table
118 | with the lookup extensions sequence.
119 |
120 |
zfile:close ()
121 |
This function closes a zfile opened by zip.open
122 |
123 |
zfile:files ()
124 |
Returns an iterator function that returns a new table containing the
125 | following information each time it is called:
126 |
127 |
filename: the full path of a file
128 |
compressed_size: the compressed size of the file in bytes
129 |
uncompressed_size: the uncompressed size of the file in bytes
130 |
131 |
132 |
133 |
zfile:open (filename)
134 |
This function opens a file that is stored inside the zip file opened by zip.open.
135 | The filename may contain the full path of the file contained inside the zip. The
136 | directory separator must be '/'.
137 | Unlike f:open, there is no mode parameter, as the only
138 | supported mode is "read".
139 |
140 |
file:read (format1, ...)
141 |
Reads a file according to the given formats, which specify what to read.
142 | For each format, the function returns a string with the characters read, or nil if it cannot read
143 | data with the specified format. When called without formats, it uses a default format that reads
144 | the entire next line (see below).
145 | The available formats are:
146 |
147 |
"*a": reads the whole file, starting at the current position. On end of file, it
148 | returns the empty string.
149 |
"*l": reads the next line (skipping the end of line), returns nil on end of file.
150 | This is the default format.
151 |
number: reads a string with up to that number of characters, returning nil
152 | on end of file.
153 |
154 |
155 | Unlike the standard I/O read, the format "*n" is not supported.
156 |
157 |
file:seek ([whence] [, offset])
158 |
Sets and gets the file position, measured from the beginning of the file, to the position given
159 | by offset plus a base specified by the string whence, as follows:
160 |
161 |
set: base is position 0 (beginning of the file);
162 |
cur: base is current position;
163 |
end: base is end of file;
164 |
165 | In case of success, function seek returns the final file position, measured in bytes
166 | from the beginning of the file. If this function fails, it returns nil, plus an error string.
167 | The default value for whence is "cur", and for offset is 0.
168 | Therefore, the call file:seek() returns the current file position, without changing
169 | it; the call file:seek("set") sets the position to the beginning of the file (and returns 0);
170 | and the call file:seek("end") sets the position to the end of the file, and returns its
171 | size.
172 |
173 |
file:close ()
174 |
This function closes a file opened by zfile:open.
175 |
176 |
file:lines ()
177 |
Returns an iterator function that returns a new line from the file each time it is called.
178 | Therefore, the construction
179 |
42 | The mime namespace offers filters that apply and remove common
43 | content transfer encodings, such as Base64 and Quoted-Printable.
44 | It also provides functions to break text into lines and change
45 | the end-of-line convention.
46 | MIME is described mainly in
47 | RFC 2045,
48 | 2046,
49 | 2047,
50 | 2048, and
51 | 2049.
52 |
96 | Returns a filter that encodes data according to a given transfer content
97 | encoding.
98 |
99 |
100 |
101 | In the Quoted-Printable case, the user can specify whether the data is
102 | textual or binary, by passing the mode strings "text" or
103 | "binary". Mode defaults to "text".
104 |
105 |
106 |
107 | Although both transfer content encodings specify a limit for the line
108 | length, the encoding filters do not break text into lines (for
109 | added flexibility).
110 | Below is a filter that converts binary data to the Base64 transfer content
111 | encoding and breaks it into lines of the correct size.
112 |
141 | Converts most common end-of-line markers to a specific given marker.
142 |
143 |
144 |
145 | Marker is the new marker. It defaults to CRLF, the canonic
146 | end-of-line marker defined by the MIME standard.
147 |
148 |
149 |
150 | The function returns a filter that performs the conversion.
151 |
152 |
153 |
154 | Note: There is no perfect solution to this problem. Different end-of-line
155 | markers are an evil that will probably plague developers forever.
156 | This function, however, will work perfectly for text created with any of
157 | the most common end-of-line markers, i.e. the Mac OS (CR), the Unix (LF),
158 | or the DOS (CRLF) conventions. Even if the data has mixed end-of-line
159 | markers, the function will still work well, although it doesn't
160 | guarantee that the number of empty lines will be correct.
161 |
162 |
163 |
164 |
165 |
166 | mime.stuff()
167 |
168 |
169 |
170 | Creates and returns a filter that performs stuffing of SMTP messages.
171 |
172 |
173 |
174 | Note: The smtp.send function
175 | uses this filter automatically. You don't need to chain it with your
176 | source, or apply it to your message body.
177 |
188 | Returns a filter that breaks data into lines.
189 |
190 |
191 |
192 | The "text" line-wrap filter simply breaks text into lines by
193 | inserting CRLF end-of-line markers at appropriate positions.
194 | Length defaults 76.
195 | The "base64" line-wrap filter works just like the default
196 | "text" line-wrap filter with default length.
197 | The function can also wrap "quoted-printable" lines, taking care
198 | not to break lines in the middle of an escaped character. In that case, the
199 | line length is fixed at 76.
200 |
201 |
202 |
203 | For example, to create an encoding filter for the Quoted-Printable transfer content encoding of text data, do the following:
204 |
215 | Note: To break into lines with a different end-of-line convention, apply
216 | a normalization filter after the line break filter.
217 |
218 |
219 |
220 |
221 |
Low-level filters
222 |
223 |
224 |
225 |
226 | A, B = mime.b64(C [, D])
227 |
228 |
229 |
230 | Low-level filter to perform Base64 encoding.
231 |
232 |
233 |
234 | A is the encoded version of the largest prefix of
235 | C..D
236 | that can be encoded unambiguously. B has the remaining bytes of
237 | C..D, before encoding.
238 | If D is nil, A is padded with
239 | the encoding of the remaining bytes of C.
240 |
241 |
242 |
243 | Note: The simplest use of this function is to encode a string into it's
244 | Base64 transfer content encoding. Notice the extra parenthesis around the
245 | call to mime.b64, to discard the second return value.
246 |
259 | Low-level filter to perform SMTP stuffing and enable transmission of
260 | messages containing the sequence "CRLF.CRLF".
261 |
262 |
263 |
264 | A is the stuffed version of B. 'n' gives the
265 | number of characters from the sequence CRLF seen in the end of B.
266 | 'm' should tell the same, but for the previous chunk.
267 |
268 |
269 |
Note: The message body is defined to begin with
270 | an implicit CRLF. Therefore, to stuff a message correctly, the
271 | first m should have the value 2.
272 |
273 |
274 |
275 | print((string.gsub(mime.dot(2, ".\r\nStuffing the message.\r\n.\r\n."), "\r\n", "\\n")))
276 | --> ..\nStuffing the message.\n..\n..
277 |
278 |
279 |
280 | Note: The smtp.send function
281 | uses this filter automatically. You don't need to
282 | apply it again.
283 |
284 |
285 |
286 |
287 |
288 | A, B = mime.eol(C [, D, marker])
289 |
290 |
291 |
292 | Low-level filter to perform end-of-line marker translation.
293 | For each chunk, the function needs to know if the last character of the
294 | previous chunk could be part of an end-of-line marker or not. This is the
295 | context the function receives besides the chunk. An updated version of
296 | the context is returned after each new chunk.
297 |
298 |
299 |
300 | A is the translated version of D. C is the
301 | ASCII value of the last character of the previous chunk, if it was a
302 | candidate for line break, or 0 otherwise.
303 | B is the same as C, but for the current
304 | chunk. Marker gives the new end-of-line marker and defaults to CRLF.
305 |
306 |
307 |
308 | -- translates the end-of-line marker to UNIX
309 | unix = mime.eol(0, dos, "\n")
310 |
311 |
312 |
313 |
314 |
315 | A, B = mime.qp(C [, D, marker])
316 |
317 |
318 |
319 | Low-level filter to perform Quoted-Printable encoding.
320 |
321 |
322 |
323 | A is the encoded version of the largest prefix of
324 | C..D
325 | that can be encoded unambiguously. B has the remaining bytes of
326 | C..D, before encoding.
327 | If D is nil, A is padded with
328 | the encoding of the remaining bytes of C.
329 | Throughout encoding, occurrences of CRLF are replaced by the
330 | marker, which itself defaults to CRLF.
331 |
332 |
333 |
334 | Note: The simplest use of this function is to encode a string into it's
335 | Quoted-Printable transfer content encoding.
336 | Notice the extra parenthesis around the call to mime.qp, to discard the second return value.
337 |
351 | Low-level filter to break Quoted-Printable text into lines.
352 |
353 |
354 |
355 | A is a copy of B, broken into lines of at most
356 | length bytes (defaults to 76).
357 | 'n' should tell how many bytes are left for the first
358 | line of B and 'm' returns the number of bytes
359 | left in the last line of A.
360 |
361 |
362 |
363 | Note: Besides breaking text into lines, this function makes sure the line
364 | breaks don't fall in the middle of an escaped character combination. Also,
365 | this function only breaks lines that are bigger than length bytes.
366 |
367 |
368 |
369 |
370 |
371 | A, B = mime.unb64(C [, D])
372 |
373 |
374 |
375 | Low-level filter to perform Base64 decoding.
376 |
377 |
378 |
379 | A is the decoded version of the largest prefix of
380 | C..D
381 | that can be decoded unambiguously. B has the remaining bytes of
382 | C..D, before decoding.
383 | If D is nil, A is the empty string
384 | and B returns whatever couldn't be decoded.
385 |
386 |
387 |
388 | Note: The simplest use of this function is to decode a string from it's
389 | Base64 transfer content encoding.
390 | Notice the extra parenthesis around the call to mime.unqp, to discard the second return value.
391 |
405 | Low-level filter to remove the Quoted-Printable transfer content encoding
406 | from data.
407 |
408 |
409 |
410 | A is the decoded version of the largest prefix of
411 | C..D
412 | that can be decoded unambiguously. B has the remaining bytes of
413 | C..D, before decoding.
414 | If D is nil, A is augmented with
415 | the encoding of the remaining bytes of C.
416 |
417 |
418 |
419 | Note: The simplest use of this function is to decode a string from it's
420 | Quoted-Printable transfer content encoding.
421 | Notice the extra parenthesis around the call to mime.unqp, to discard the second return value.
422 |
436 | Low-level filter to break text into lines with CRLF marker.
437 | Text is assumed to be in the normalize form.
438 |
439 |
440 |
441 | A is a copy of B, broken into lines of at most
442 | length bytes (defaults to 76).
443 | 'n' should tell how many bytes are left for the first
444 | line of B and 'm' returns the number of bytes
445 | left in the last line of A.
446 |
447 |
448 |
449 | Note: This function only breaks lines that are bigger than
450 | length bytes. The resulting line length does not include the CRLF
451 | marker.
452 |
42 | The socket namespace contains the core functionality of LuaSocket.
43 |
44 |
45 |
46 | To obtain the socket namespace, run:
47 |
48 |
49 |
50 | -- loads the socket module
51 | local socket = require("socket")
52 |
53 |
54 |
55 |
56 |
57 | socket.headers.canonic
58 |
59 |
The socket.headers.canonic table
60 | is used by the HTTP and SMTP modules to translate from
61 | lowercase field names back into their canonic
62 | capitalization. When a lowercase field name exists as a key
63 | in this table, the associated value is substituted in
64 | whenever the field name is sent out.
65 |
66 |
67 |
68 | You can obtain the headers namespace if case run-time
69 | modifications are required by running:
70 |
71 |
72 |
73 | -- loads the headers module
74 | local headers = require("headers")
75 |
76 |
77 |
78 |
79 |
80 |
81 | socket.bind(address, port [, backlog])
82 |
83 |
84 |
85 | This function is a shortcut that creates and returns a TCP server object
86 | bound to a local address and port, ready to
87 | accept client connections. Optionally,
88 | user can also specify the backlog argument to the
89 | listen method (defaults to 32).
90 |
91 |
92 |
93 | Note: The server object returned will have the option "reuseaddr"
94 | set to true.
95 |
104 | This function is a shortcut that creates and returns a TCP client object
105 | connected to a remote address at a given port. Optionally,
106 | the user can also specify the local address and port to bind
107 | (locaddr and locport), or restrict the socket family
108 | to "inet" or "inet6".
109 | Without specifying family to connect, whether a tcp or tcp6
110 | connection is created depends on your system configuration. Two variations
111 | of connect are defined as simple helper functions that restrict the
112 | family, socket.connect4 and socket.connect6.
113 |
114 |
115 |
116 |
117 |
118 | socket._DEBUG
119 |
120 |
121 |
122 | This constant is set to true if the library was compiled
123 | with debug support.
124 |
125 |
126 |
127 |
128 |
129 | socket._DATAGRAMSIZE
130 |
131 |
132 |
133 | Default datagram size used by calls to
134 | receive and
135 | receivefrom.
136 | (Unless changed in compile time, the value is 8192.)
137 |
138 |
139 |
140 |
141 |
142 | socket.gettime()
143 |
144 |
145 |
146 | Returns the UNIX time in seconds. You should subtract the values returned by this function
147 | to get meaningful values.
148 |
149 |
150 |
151 | t = socket.gettime()
152 | -- do stuff
153 | print(socket.gettime() - t .. " seconds elapsed")
154 |
155 |
156 |
157 |
158 |
159 | socket.newtry(finalizer)
160 |
161 |
162 |
163 | Creates and returns a clean
164 | try
165 | function that allows for cleanup before the exception
166 | is raised.
167 |
168 |
169 |
170 | Finalizer is a function that will be called before
171 | try throws the exception.
172 |
173 |
174 |
175 | The function returns your customized try function.
176 |
177 |
178 |
179 | Note: This idea saved a lot of work with the
180 | implementation of protocols in LuaSocket:
181 |
182 |
183 |
184 | foo = socket.protect(function()
185 | -- connect somewhere
186 | local c = socket.try(socket.connect("somewhere", 42))
187 | -- create a try function that closes 'c' on error
188 | local try = socket.newtry(function() c:close() end)
189 | -- do everything reassured c will be closed
190 | try(c:send("hello there?\r\n"))
191 | local answer = try(c:receive())
192 | ...
193 | try(c:send("good bye\r\n"))
194 | c:close()
195 | end)
196 |
197 |
198 |
199 |
200 |
201 |
202 | socket.protect(func)
203 |
204 |
205 |
206 | Converts a function that throws exceptions into a safe function. This
207 | function only catches exceptions thrown by the try
208 | and newtry functions. It does not catch normal
209 | Lua errors.
210 |
211 |
212 |
213 | Func is a function that calls
214 | try (or assert, or error)
215 | to throw exceptions.
216 |
217 |
218 |
219 | Returns an equivalent function that instead of throwing exceptions in case of
220 | a failed try call, returns nil
221 | followed by an error message.
222 |
223 |
224 |
225 |
226 |
227 | socket.select(recvt, sendt [, timeout])
228 |
229 |
230 |
231 | Waits for a number of sockets to change status.
232 |
233 |
234 |
235 | Recvt is an array with the sockets to test for characters
236 | available for reading. Sockets in the sendt array are watched to
237 | see if it is OK to immediately write on them. Timeout is the
238 | maximum amount of time (in seconds) to wait for a change in status. A
239 | nil, negative or omitted timeout value allows the
240 | function to block indefinitely. Recvt and sendt can also
241 | be empty tables or nil. Non-socket values (or values with
242 | non-numeric indices) in the arrays will be silently ignored.
243 |
244 |
245 |
The function returns a list with the sockets ready for
246 | reading, a list with the sockets ready for writing and an error message.
247 | The error message is "timeout" if a timeout
248 | condition was met, "select failed" if the call
249 | to select failed, and
250 | nil otherwise. The returned tables are
251 | doubly keyed both by integers and also by the sockets
252 | themselves, to simplify the test if a specific socket has
253 | changed status.
254 |
255 |
256 |
257 | Note:select can monitor a limited number
258 | of sockets, as defined by the constant
259 | socket._SETSIZE. This
260 | number may be as high as 1024 or as low as 64 by default,
261 | depending on the system. It is usually possible to change this
262 | at compile time. Invoking select with a larger
263 | number of sockets will raise an error.
264 |
265 |
266 |
267 | Important note: a known bug in WinSock causes select to fail
268 | on non-blocking TCP sockets. The function may return a socket as
269 | writable even though the socket is not ready for sending.
270 |
271 |
272 |
273 | Another important note: calling select with a server socket in the receive parameter before a call to accept does not guarantee
274 | accept will return immediately.
275 | Use the settimeout
276 | method or accept might block forever.
277 |
278 |
279 |
280 | Yet another note: If you close a socket and pass
281 | it to select, it will be ignored.
282 |
283 |
284 |
285 | Using select with non-socket objects: Any object that implements getfd and dirty can be used with select, allowing objects from other libraries to be used within a socket.select driven loop.
286 |
287 |
288 |
289 |
290 |
291 | socket._SETSIZE
292 |
293 |
294 |
295 | The maximum number of sockets that the select function can handle.
297 |
298 |
299 |
300 |
301 |
302 |
303 | socket.sink(mode, socket)
304 |
305 |
306 |
307 | Creates an
308 | LTN12
309 | sink from a stream socket object.
310 |
311 |
312 |
313 | Mode defines the behavior of the sink. The following
314 | options are available:
315 |
316 |
317 |
"http-chunked": sends data through socket after applying the
318 | chunked transfer coding, closing the socket when done;
319 |
"close-when-done": sends all received data through the
320 | socket, closing the socket when done;
321 |
"keep-open": sends all received data through the
322 | socket, leaving it open when done.
323 |
324 |
325 | Socket is the stream socket object used to send the data.
326 |
327 |
328 |
329 | The function returns a sink with the appropriate behavior.
330 |
382 | Creates an
383 | LTN12
384 | source from a stream socket object.
385 |
386 |
387 |
388 | Mode defines the behavior of the source. The following
389 | options are available:
390 |
391 |
392 |
"http-chunked": receives data from socket and removes the
393 | chunked transfer coding before returning the data;
394 |
"by-length": receives a fixed number of bytes from the
395 | socket. This mode requires the extra argument length;
396 |
"until-closed": receives data from a socket until the other
397 | side closes the connection.
398 |
399 |
400 | Socket is the stream socket object used to receive the data.
401 |
402 |
403 |
404 | The function returns a source with the appropriate behavior.
405 |
406 |
407 |
408 |
409 |
410 | socket._SOCKETINVALID
411 |
412 |
413 |
414 | The OS value for an invalid socket. This can be used with
415 | tcp:getfd and tcp:setfd methods.
416 |
417 |
418 |
419 |
420 |
421 | socket.try(ret1 [, ret2 ... retN])
422 |
423 |
424 |
425 | Throws an exception in case ret1 is falsy, using
426 | ret2 as the error message. The exception is supposed to be caught
427 | by a protected function only.
428 |
429 |
430 |
431 | Ret1 to retN can be arbitrary
432 | arguments, but are usually the return values of a function call
433 | nested with try.
434 |
435 |
436 |
437 | The function returns ret1 to retN if
438 | ret1 is not nil or false.
439 | Otherwise, it calls error passing ret2 wrapped
440 | in a table with metatable used by protect to
441 | distinguish exceptions from runtime errors.
442 |
443 |
444 |
445 | -- connects or throws an exception with the appropriate error message
446 | c = socket.try(socket.connect("localhost", 80))
447 |
448 |
449 |
450 |
451 |
452 | socket._VERSION
453 |
454 |
455 |
456 | This constant has a string describing the current LuaSocket version.
457 |
458 |
459 |
460 |
461 |
479 |
480 |
481 |
482 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C)
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | , 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/utils.lua:
--------------------------------------------------------------------------------
1 | ---This file is intended as a library for the various example files.
2 | local inspect = (function()
3 | --- https://raw.githubusercontent.com/kikito/inspect.lua/refs/heads/master/inspect.lua
4 | local _tl_compat
5 | if (tonumber((_VERSION or ""):match("[%d.]*$")) or 0) < 5.3 then
6 | local p, m = pcall(require, "compat53.module")
7 | if p then
8 | _tl_compat = m
9 | end
10 | end
11 | local math = _tl_compat and _tl_compat.math or math
12 | local string = _tl_compat and _tl_compat.string or string
13 | local table = _tl_compat and _tl_compat.table or table
14 | local inspect = { Options = {} }
15 |
16 | inspect._VERSION = "inspect.lua 3.1.0"
17 | inspect._URL = "http://github.com/kikito/inspect.lua"
18 | inspect._DESCRIPTION = "human-readable representations of tables"
19 | inspect._LICENSE = [[
20 | MIT LICENSE
21 |
22 | Copyright (c) 2022 Enrique García Cota
23 |
24 | Permission is hereby granted, free of charge, to any person obtaining a
25 | copy of this software and associated documentation files (the
26 | "Software"), to deal in the Software without restriction, including
27 | without limitation the rights to use, copy, modify, merge, publish,
28 | distribute, sublicense, and/or sell copies of the Software, and to
29 | permit persons to whom the Software is furnished to do so, subject to
30 | the following conditions:
31 |
32 | The above copyright notice and this permission notice shall be included
33 | in all copies or substantial portions of the Software.
34 |
35 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
36 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
38 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
39 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
40 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
41 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 | ]]
43 | inspect.KEY = setmetatable({}, {
44 | __tostring = function()
45 | return "inspect.KEY"
46 | end,
47 | })
48 | inspect.METATABLE = setmetatable({}, {
49 | __tostring = function()
50 | return "inspect.METATABLE"
51 | end,
52 | })
53 |
54 | local tostring = tostring
55 | local rep = string.rep
56 | local match = string.match
57 | local char = string.char
58 | local gsub = string.gsub
59 | local fmt = string.format
60 |
61 | local _rawget
62 | if rawget then
63 | _rawget = rawget
64 | else
65 | _rawget = function(t, k)
66 | return t[k]
67 | end
68 | end
69 |
70 | local function rawpairs(t)
71 | return next, t, nil
72 | end
73 |
74 | local function smartQuote(str)
75 | if match(str, '"') and not match(str, "'") then
76 | return "'" .. str .. "'"
77 | end
78 | return '"' .. gsub(str, '"', '\\"') .. '"'
79 | end
80 |
81 | local shortControlCharEscapes = {
82 | ["\a"] = "\\a",
83 | ["\b"] = "\\b",
84 | ["\f"] = "\\f",
85 | ["\n"] = "\\n",
86 | ["\r"] = "\\r",
87 | ["\t"] = "\\t",
88 | ["\v"] = "\\v",
89 | ["\127"] = "\\127",
90 | }
91 | local longControlCharEscapes = { ["\127"] = "\127" }
92 | for i = 0, 31 do
93 | local ch = char(i)
94 | if not shortControlCharEscapes[ch] then
95 | shortControlCharEscapes[ch] = "\\" .. i
96 | longControlCharEscapes[ch] = fmt("\\%03d", i)
97 | end
98 | end
99 |
100 | local function escape(str)
101 | return (gsub(gsub(gsub(str, "\\", "\\\\"), "(%c)%f[0-9]", longControlCharEscapes), "%c", shortControlCharEscapes))
102 | end
103 |
104 | local luaKeywords = {
105 | ["and"] = true,
106 | ["break"] = true,
107 | ["do"] = true,
108 | ["else"] = true,
109 | ["elseif"] = true,
110 | ["end"] = true,
111 | ["false"] = true,
112 | ["for"] = true,
113 | ["function"] = true,
114 | ["goto"] = true,
115 | ["if"] = true,
116 | ["in"] = true,
117 | ["local"] = true,
118 | ["nil"] = true,
119 | ["not"] = true,
120 | ["or"] = true,
121 | ["repeat"] = true,
122 | ["return"] = true,
123 | ["then"] = true,
124 | ["true"] = true,
125 | ["until"] = true,
126 | ["while"] = true,
127 | }
128 |
129 | local function isIdentifier(str)
130 | return type(str) == "string" and not not str:match("^[_%a][_%a%d]*$") and not luaKeywords[str]
131 | end
132 |
133 | local flr = math.floor
134 | local function isSequenceKey(k, sequenceLength)
135 | return type(k) == "number" and flr(k) == k and 1 <= k and k <= sequenceLength
136 | end
137 |
138 | local defaultTypeOrders = {
139 | ["number"] = 1,
140 | ["boolean"] = 2,
141 | ["string"] = 3,
142 | ["table"] = 4,
143 | ["function"] = 5,
144 | ["userdata"] = 6,
145 | ["thread"] = 7,
146 | }
147 |
148 | local function sortKeys(a, b)
149 | local ta, tb = type(a), type(b)
150 |
151 | if ta == tb and (ta == "string" or ta == "number") then
152 | return a < b
153 | end
154 |
155 | local dta = defaultTypeOrders[ta] or 100
156 | local dtb = defaultTypeOrders[tb] or 100
157 |
158 | return dta == dtb and ta < tb or dta < dtb
159 | end
160 |
161 | local function getKeys(t)
162 | local seqLen = 1
163 | while _rawget(t, seqLen) ~= nil do
164 | seqLen = seqLen + 1
165 | end
166 | seqLen = seqLen - 1
167 |
168 | local keys, keysLen = {}, 0
169 | for k in rawpairs(t) do
170 | if not isSequenceKey(k, seqLen) then
171 | keysLen = keysLen + 1
172 | keys[keysLen] = k
173 | end
174 | end
175 | table.sort(keys, sortKeys)
176 | return keys, keysLen, seqLen
177 | end
178 |
179 | local function countCycles(x, cycles)
180 | if type(x) == "table" then
181 | if cycles[x] then
182 | cycles[x] = cycles[x] + 1
183 | else
184 | cycles[x] = 1
185 | for k, v in rawpairs(x) do
186 | countCycles(k, cycles)
187 | countCycles(v, cycles)
188 | end
189 | countCycles(getmetatable(x), cycles)
190 | end
191 | end
192 | end
193 |
194 | local function makePath(path, a, b)
195 | local newPath = {}
196 | local len = #path
197 | for i = 1, len do
198 | newPath[i] = path[i]
199 | end
200 |
201 | newPath[len + 1] = a
202 | newPath[len + 2] = b
203 |
204 | return newPath
205 | end
206 |
207 | local function processRecursive(process, item, path, visited)
208 | if item == nil then
209 | return nil
210 | end
211 | if visited[item] then
212 | return visited[item]
213 | end
214 |
215 | local processed = process(item, path)
216 | if type(processed) == "table" then
217 | local processedCopy = {}
218 | visited[item] = processedCopy
219 | local processedKey
220 |
221 | for k, v in rawpairs(processed) do
222 | processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
223 | if processedKey ~= nil then
224 | processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
225 | end
226 | end
227 |
228 | local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
229 | if type(mt) ~= "table" then
230 | mt = nil
231 | end
232 | setmetatable(processedCopy, mt)
233 | processed = processedCopy
234 | end
235 | return processed
236 | end
237 |
238 | local function puts(buf, str)
239 | buf.n = buf.n + 1
240 | buf[buf.n] = str
241 | end
242 |
243 | local Inspector = {}
244 |
245 | local Inspector_mt = { __index = Inspector }
246 |
247 | local function tabify(inspector)
248 | puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level))
249 | end
250 |
251 | function Inspector:getId(v)
252 | local id = self.ids[v]
253 | local ids = self.ids
254 | if not id then
255 | local tv = type(v)
256 | id = (ids[tv] or 0) + 1
257 | ids[v], ids[tv] = id, id
258 | end
259 | return tostring(id)
260 | end
261 |
262 | function Inspector:putValue(v)
263 | local buf = self.buf
264 | local tv = type(v)
265 | if tv == "string" then
266 | puts(buf, smartQuote(escape(v)))
267 | elseif tv == "number" or tv == "boolean" or tv == "nil" or tv == "cdata" or tv == "ctype" then
268 | puts(buf, tostring(v))
269 | elseif tv == "table" and not self.ids[v] then
270 | local t = v
271 |
272 | if t == inspect.KEY or t == inspect.METATABLE then
273 | puts(buf, tostring(t))
274 | elseif self.level >= self.depth then
275 | puts(buf, "{...}")
276 | else
277 | if self.cycles[t] > 1 then
278 | puts(buf, fmt("<%d>", self:getId(t)))
279 | end
280 |
281 | local keys, keysLen, seqLen = getKeys(t)
282 |
283 | puts(buf, "{")
284 | self.level = self.level + 1
285 |
286 | for i = 1, seqLen + keysLen do
287 | if i > 1 then
288 | puts(buf, ",")
289 | end
290 | if i <= seqLen then
291 | puts(buf, " ")
292 | self:putValue(t[i])
293 | else
294 | local k = keys[i - seqLen]
295 | tabify(self)
296 | if isIdentifier(k) then
297 | puts(buf, k)
298 | else
299 | puts(buf, "[")
300 | self:putValue(k)
301 | puts(buf, "]")
302 | end
303 | puts(buf, " = ")
304 | self:putValue(t[k])
305 | end
306 | end
307 |
308 | local mt = getmetatable(t)
309 | if type(mt) == "table" then
310 | if seqLen + keysLen > 0 then
311 | puts(buf, ",")
312 | end
313 | tabify(self)
314 | puts(buf, " = ")
315 | self:putValue(mt)
316 | end
317 |
318 | self.level = self.level - 1
319 |
320 | if keysLen > 0 or type(mt) == "table" then
321 | tabify(self)
322 | elseif seqLen > 0 then
323 | puts(buf, " ")
324 | end
325 |
326 | puts(buf, "}")
327 | end
328 | else
329 | puts(buf, fmt("<%s %d>", tv, self:getId(v)))
330 | end
331 | end
332 |
333 | function inspect.inspect(root, options)
334 | options = options or {}
335 |
336 | local depth = options.depth or math.huge
337 | local newline = options.newline or "\n"
338 | local indent = options.indent or " "
339 | local process = options.process
340 |
341 | if process then
342 | root = processRecursive(process, root, {}, {})
343 | end
344 |
345 | local cycles = {}
346 | countCycles(root, cycles)
347 |
348 | local inspector = setmetatable({
349 | buf = { n = 0 },
350 | ids = {},
351 | cycles = cycles,
352 | depth = depth,
353 | level = 0,
354 | newline = newline,
355 | indent = indent,
356 | }, Inspector_mt)
357 |
358 | inspector:putValue(root)
359 |
360 | return table.concat(inspector.buf)
361 | end
362 |
363 | setmetatable(inspect, {
364 | __call = function(_, root, options)
365 | return inspect.inspect(root, options)
366 | end,
367 | })
368 |
369 | return inspect
370 | end)()
371 |
372 | ---
373 | ---__ANSI color codes:__
374 | ---
375 | ---* `0`: Reset
376 | ---* `30`: Black
377 | ---* `31`: Red
378 | ---* `32`: Green
379 | ---* `33`: Yellow
380 | ---* `34`: Blue
381 | ---* `35`: Purple
382 | ---* `36`: Cyan
383 | ---* `37`: White
384 | ---@param color_code integer
385 | local function format_ansi_color_code(color_code)
386 | return string.char(27) .. "[" .. tostring(color_code) .. "m"
387 | end
388 |
389 | ---
390 | ---__ANSI color codes:__
391 | ---
392 | ---* `0`: Reset
393 | ---* `30`: Black
394 | ---* `31`: Red
395 | ---* `32`: Green
396 | ---* `33`: Yellow
397 | ---* `34`: Blue
398 | ---* `35`: Purple
399 | ---* `36`: Cyan
400 | ---* `37`: White
401 | ---
402 | ---@param color_code integer
403 | ---@param text unknown
404 | ---@param skip_colorize? boolean
405 | ---
406 | ---@return string
407 | local function colorize(color_code, text, skip_colorize)
408 | if skip_colorize then
409 | return text
410 | end
411 | return format_ansi_color_code(color_code) .. tostring(text) .. format_ansi_color_code(0)
412 | end
413 |
414 | ---Print the inspected version of the value
415 | local function pinspect(value)
416 | print(inspect(value))
417 | end
418 |
419 | ---
420 | ---@param names string[]
421 | local function convert_string_array_to_alias_union(names)
422 | for index, name in ipairs(names) do
423 | print("---|`" .. name .. "`")
424 | end
425 | end
426 |
427 | ---
428 | ---Returns the file extension from a given file path.
429 | ---
430 | ---@param path string: The file path to extract the extension from.
431 | ---
432 | ---@return string|nil: The file extension (including the dot), or nil if no extension is found.
433 | local function get_file_extension(path)
434 | return path:match("^.+(%..+)$")
435 | end
436 |
437 | ---
438 | ---https://stackoverflow.com/a/49405922
439 | ---
440 | ---@param path string The path of a directory
441 | ---
442 | ---@return fun(...): string, LuaFileSystem.Attributes
443 | local function list_files_recursively(path)
444 | assert(path and path ~= "", "Please pass directory parameter")
445 | if string.sub(path, -1) == "/" then
446 | path = string.sub(path, 1, -2)
447 | end
448 |
449 | ---
450 | ---@param dir string
451 | local function yieldtree(dir)
452 | for entry in lfs.dir(dir) do
453 | if entry ~= "." and entry ~= ".." then
454 | local new_entry = dir .. "/" .. entry
455 | local attr = lfs.attributes(new_entry)
456 | coroutine.yield(new_entry, attr)
457 | if attr.mode == "directory" then
458 | yieldtree(new_entry)
459 | end
460 | end
461 | end
462 | end
463 |
464 | return coroutine.wrap(function()
465 | yieldtree(path)
466 | end)
467 | end
468 |
469 | local namespace = (function()
470 | ---https://stackoverflow.com/a/29246308
471 | ---
472 | ---@param fun function
473 | ---@return string
474 | local function get_function_args(fun)
475 | local args = {}
476 | local hook = debug.gethook()
477 |
478 | local arg_hook = function(...)
479 | local info = debug.getinfo(3)
480 | if "pcall" ~= info.name then
481 | return
482 | end
483 |
484 | for i = 1, math.huge do
485 | local name, value = debug.getlocal(2, i)
486 | if "(*temporary)" == name then
487 | debug.sethook(hook)
488 | error("")
489 | return
490 | end
491 | table.insert(args, name)
492 | end
493 | end
494 |
495 | debug.sethook(arg_hook, "c")
496 | pcall(fun)
497 |
498 | return table.concat(args, ", ")
499 | end
500 |
501 | ---
502 | ---@param s string
503 | ---@param ... any
504 | local function printf(s, ...)
505 | print(string.format(s, ...))
506 | end
507 |
508 | ---
509 | ---@param t table
510 | ---@return table
511 | local function sort_keys(t)
512 | local keys = {}
513 | for k in pairs(t) do
514 | table.insert(keys, k)
515 | end
516 | table.sort(keys)
517 | return keys
518 | end
519 |
520 | ---
521 | ---@param lib_name string
522 | ---@param lib table
523 | ---@param as_lua? boolean # Print as Lua code, not as Markdown
524 | local function print_lib_members(lib_name, lib, as_lua)
525 | if as_lua == nil then
526 | as_lua = false
527 | end
528 | local member_names = sort_keys(lib)
529 | for _, member in ipairs(member_names) do
530 | local member_type = type(lib[member])
531 | if not as_lua then
532 | if member_type == "table" and member ~= "__index" and member ~= "_M" then
533 | printf("- *`%s.%s` (%s)*", lib_name, member, member_type)
534 | print_lib_members(lib_name .. "." .. member, lib[member], as_lua)
535 | elseif member_type == "function" then
536 | printf("- __`%s.%s` (%s)__", lib_name, member, member_type)
537 | else
538 | printf("- `%s.%s` (%s)", lib_name, member, member_type)
539 | end
540 | else
541 | if member_type == "function" then
542 | local args = get_function_args(lib[member])
543 | printf("function %s.%s(%s) end", lib_name, member, args)
544 | end
545 | end
546 | end
547 | end
548 |
549 | local lua_std = {
550 | _G = true,
551 | arg = true,
552 | boolean = true,
553 | coroutine = true,
554 | debug = true,
555 | io = true,
556 | math = true,
557 | number = true,
558 | os = true,
559 | package = true,
560 | string = true,
561 | table = true,
562 | utf8 = true,
563 | }
564 |
565 | local function print_global_namespace()
566 | local env = _ENV
567 | local lib_names = sort_keys(env)
568 | for _, lib_name in ipairs(lib_names) do
569 | if not lua_std[lib_name] then
570 | local lib = env[lib_name]
571 | if type(lib) == "table" then
572 | printf("\n### %s\n", lib_name)
573 | print_lib_members(lib_name, env[lib_name])
574 | end
575 | end
576 | end
577 | end
578 |
579 | return print_global_namespace
580 | end)()
581 |
582 | ---@class NodeTypeInfo
583 | ---@field id NodeTypeName
584 | ---@field subtype? WhatsitTypeName
585 | ---@field subtypes? table
586 | ---@field fields? table
587 |
588 | ---
589 | ---@param id NodeTypeName
590 | ---@param subtype? WhatsitTypeName
591 | ---@return NodeTypeInfo
592 | local function get_node_info(id, subtype)
593 | ---
594 | ---Some luatex lua functions return an array table with a 0 index for the first element.
595 | ---
596 | ---inspect prints out:
597 | ---
598 | ---```lua
599 | ---{ "line", "box",
600 | --- [0] = "unknown"
601 | ---}
602 | ---```
603 | ---
604 | ---@param tbl? table
605 | local function reindex_array(tbl)
606 | if not tbl then
607 | return
608 | end
609 | local new = {}
610 | for i = -3, 100 do
611 | if tbl[i] then
612 | table.insert(new, tbl[i] .. " (" .. i .. ")")
613 | end
614 | end
615 | return new
616 | end
617 |
618 | local function render_numberic(number)
619 | return " (" .. tostring(number) .. ")"
620 | end
621 |
622 | ---@type NodeTypeInfo
623 | local info = {
624 | id = id .. render_numberic(node.id(id)),
625 | }
626 | if subtype ~= nil then
627 | info.subtype = subtype .. render_numberic(node.subtype(subtype))
628 | info.fields = reindex_array(node.fields(node.id(id), node.subtype(subtype)))
629 | else
630 | info.subtypes = reindex_array(node.subtypes(id))
631 | info.fields = reindex_array(node.fields(node.id(id)))
632 | end
633 | return info
634 | end
635 |
636 | local assertions = (function()
637 | ---
638 | ---@param actual unknown
639 | ---@param expected unknown
640 | ---@param compare fun(actual: unknown, expected: unknown): boolean
641 | local function report_diff(compare, actual, expected)
642 | if not compare(actual, expected) then
643 | print("actual:", inspect(actual))
644 | print("expected:", inspect(expected))
645 | assert(false)
646 | else
647 | print(colorize(31, inspect(actual)))
648 | end
649 | end
650 |
651 | ---@param actual unknown
652 | ---@param expected unknown
653 | ---
654 | ---@return boolean
655 | local function compare_equality(actual, expected)
656 | return actual == expected
657 | end
658 |
659 | ---@param actual unknown
660 | ---
661 | ---@return boolean
662 | local function compare_truthy(actual)
663 | if actual then
664 | return true
665 | end
666 | return false
667 | end
668 |
669 | ---@param a number
670 | ---@param b number
671 | ---@param epsilon number
672 | ---
673 | ---@return boolean
674 | local function compare_numbers(a, b, epsilon)
675 | epsilon = epsilon or 1e-6
676 | return a == b or math.abs(a - b) < epsilon
677 | end
678 |
679 | ---
680 | ---Deeply compare two objects.
681 | ---
682 | ---Source: [gist.github.com/sapphyrus/fd9aeb871e3ce966cc4b0b969f62f539](https://gist.github.com/sapphyrus/fd9aeb871e3ce966cc4b0b969f62f539?permalink_comment_id=4563041#gistcomment-4563041)
683 | ---
684 | ---@param o1 unknown # An object of any type.
685 | ---@param o2 unknown # An object of any type.
686 | ---@param ignore_mt? boolean # Ignore the metatable.
687 | ---
688 | ---@return boolean # `true`, if the two specified objects are deeply equal.
689 | local function compare_tables(o1, o2, ignore_mt)
690 | -- same object
691 | if o1 == o2 then
692 | return true
693 | end
694 |
695 | local o1Type = type(o1)
696 | local o2Type = type(o2)
697 | --- different type
698 | if o1Type ~= o2Type then
699 | return false
700 | end
701 | --- same type but not table, already compared above
702 | if o1Type ~= "table" then
703 | return false
704 | end
705 |
706 | -- use metatable method
707 | if not ignore_mt then
708 | local mt1 = getmetatable(o1)
709 | if mt1 and mt1.__eq then
710 | -- compare using built in method
711 | return o1 == o2
712 | end
713 | end
714 |
715 | -- iterate over o1
716 | for key1, value1 in pairs(o1) do
717 | local value2 = o2[key1]
718 | if value2 == nil or compare_tables(value1, value2, ignore_mt) == false then
719 | return false
720 | end
721 | end
722 |
723 | --- check keys in o2 but missing from o1
724 | for key2, _ in pairs(o2) do
725 | if o1[key2] == nil then
726 | return false
727 | end
728 | end
729 | return true
730 | end
731 |
732 | return {
733 | ---@param actual unknown
734 | ---@param expected unknown
735 | equals = function(actual, expected)
736 | report_diff(compare_equality, actual, expected)
737 | end,
738 |
739 | ---@param actual unknown
740 | is_nil = function(actual)
741 | report_diff(compare_equality, actual, nil)
742 | end,
743 |
744 | ---@param actual unknown
745 | is_true = function(actual)
746 | report_diff(compare_equality, actual, true)
747 | end,
748 |
749 | ---@param actual unknown
750 | is_truthy = function(actual)
751 | report_diff(compare_truthy, actual, true)
752 | end,
753 |
754 | ---@param actual unknown
755 | is_false = function(actual)
756 | report_diff(compare_equality, actual, false)
757 | end,
758 |
759 | ---@param actual unknown
760 | ---@param expected "nil"|"number"|"string"|"boolean"|"table"|"function"|"thread"|"userdata"
761 | is_type = function(actual, expected)
762 | report_diff(compare_equality, type(actual), expected)
763 | end,
764 |
765 | ---@param actual unknown
766 | ---@param expected unknown
767 | numbers = function(actual, expected)
768 | report_diff(compare_numbers, actual, expected)
769 | end,
770 |
771 | ---@param actual unknown
772 | ---@param expected unknown
773 | same = function(actual, expected)
774 | report_diff(compare_tables, actual, expected)
775 | end,
776 |
777 | ---@param id NodeTypeName
778 | ---@param subtype? WhatsitTypeName
779 | ---@param expected unknown
780 | node_type = function(id, subtype, expected)
781 | local info = get_node_info(id, subtype)
782 | report_diff(compare_tables, info, expected)
783 | end,
784 | }
785 | end)()
786 |
787 | return {
788 | pinspect = pinspect,
789 | assert = assertions,
790 | print_global_namespace = namespace,
791 | convert_string_array_to_alias_union = convert_string_array_to_alias_union,
792 | list_files_recursively = list_files_recursively,
793 | get_file_extension = get_file_extension,
794 | }
795 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LuaTeX Lua API
2 |
3 | Type definitions for the Lua API of `LuaTeX` and related projects.
4 |
5 | 
6 |
7 | [LuaTeX](https://www.luatex.org) has a very large [Lua](https://www.lua.org)
8 | API. This project tries to make this API accessible in the text editor
9 | of your choice. This is made possible by the
10 | [lua-language-server](https://github.com/LuaLS/lua-language-server) - a
11 | server that implements the [Language Server Protocol
12 | (LSP)](https://en.wikipedia.org/wiki/Language_Server_Protocol) for the
13 | `Lua` language. Features such as code completion, syntax highlighting
14 | and marking of warnings and errors, should therefore not only be
15 | possible in [Visual Studio Code](https://code.visualstudio.com), but in
16 | a [large number of
17 | editors](https://langserver.org/#implementations-client) that support
18 | the `LSP`.
19 |
20 | ## Subprojects
21 |
22 | * [lualatex](https://github.com/TeXLuaCATS/LuaLaTeX)
23 | * [lualibs](https://github.com/TeXLuaCATS/Lualibs)
24 | * [luametatex](https://github.com/TeXLuaCATS/LuaMetaTeX)
25 | * [luaotfload](https://github.com/TeXLuaCATS/LuaOTFload)
26 | * [luatex](https://github.com/TeXLuaCATS/LuaTeX)
27 |
28 | ## Distribution ...
29 |
30 | ## via CTAN
31 |
32 | 
33 |
34 | The type definitions are published on
35 | [CTAN](https://www.ctan.org/pkg/luatex-type-definitions) as a single
36 | file to avoid cluttering the CTAN directory with many individual Lua
37 | files. Since this one file is just under 1.5 MB in size, a configuration
38 | must be made so that the language server can load the file. The
39 | following configuration example sets the preload file size to a maximum
40 | of 5000 kB.
41 |
42 | ```json
43 | {
44 | "Lua.workspace.preloadFileSize": 5000,
45 | }
46 | ```
47 |
48 | There are several ways to include type definitions in a project.
49 | The easiest way is to copy the file into the project folder.
50 | Or you can use the configuration `Lua.workspace.library`:
51 |
52 | ```json
53 | {
54 | "Lua.workspace.library": ["/path/to/luatex-type-definitions.lua"]
55 | }
56 | ```
57 |
58 | ### via Visual Studio Code Extension
59 |
60 | [](https://marketplace.visualstudio.com/items?itemName=JosefFriedrich.luatex)
61 |
62 | [Visual Studio Code LuaTeX Extension](https://github.com/TeXLuaCATS/vscode_extension)
63 |
64 | ### via LuaCATS git respositories
65 |
66 | 
67 |
68 | [LuaCATS](https://github.com/LuaCATS) is a [Github](https://github.com)
69 | organisation and stands for *“Lua Comment And Type System”*. This
70 | organization provides a place for community projects to live. These
71 | projects are [addons](https://luals.github.io/wiki/addons/) for popular
72 | libraries/frameworks.
73 | The repositories in this organization are used by
74 | [LLS-Addons](https://github.com/LuaLS/LLS-Addons), a repository that is used by the [addon
75 | manager](https://luals.github.io/wiki/addons/#addon-manager) of the [VS
76 | Code
77 | extension](https://marketplace.visualstudio.com/items?itemName=sumneko.lua)
78 | for the [Lua Language Server](https://github.com/LuaLS/lua-language-server).
79 |
80 | #### All related LuaCATS repositories
81 |
82 | This repositories in LuaCATS are related to this project:
83 |
84 | * [lmathx](https://github.com/LuaCATS/lmathx)
85 | * [lpeg](https://github.com/LuaCATS/lpeg)
86 | * [luafilesystem](https://github.com/LuaCATS/luafilesystem)
87 | * [luaharfbuzz](https://github.com/LuaCATS/luaharfbuzz)
88 | * [luasocket](https://github.com/LuaCATS/luasocket)
89 | * [luazip](https://github.com/LuaCATS/luazip)
90 | * [lzlib](https://github.com/LuaCATS/lzlib)
91 | * [md5](https://github.com/LuaCATS/md5)
92 | * [slnunicode](https://github.com/LuaCATS/slnunicode)
93 | * [tex-lualatex](https://github.com/LuaCATS/tex-lualatex)
94 | * [tex-lualibs](https://github.com/LuaCATS/tex-lualibs)
95 | * [tex-luametatex](https://github.com/LuaCATS/tex-luametatex)
96 | * [tex-luatex](https://github.com/LuaCATS/tex-luatex)
97 |
98 | #### Upstream LuaCATS repositories
99 |
100 | The following repositories are *upstream* projects. This means: The type
101 | definitions are developed in a LuaCATS repository and *pulled* in by
102 | this project.
103 |
104 | * [LuaCATS: lmathx](https://github.com/LuaCATS/lmathx)
105 | → [library/luametatex/lmathx.lua](https://github.com/TeXLuaCATS/LuaMetaTeX/blob/main/library/xmath.lua)
106 | * [LuaCATS: lpeg](https://github.com/LuaCATS/lpeg)
107 | → [TeXLuaCATS/LuaTeX/lpeg.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/lpeg.lua)
108 | * [LuaCATS: luaharfbuzz](https://github.com/LuaCATS/luaharfbuzz)
109 | → [TeXLuaCATS/LuaTeX/luaharfbuzz.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/luaharfbuzz.lua)
110 | * [LuaCATS: luasocket](https://github.com/LuaCATS/luasocket)
111 | → [TeXLuaCATS/LuaTeX/socket.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/socket.lua)
112 | → [TeXLuaCATS/LuaTeX/mime.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/mime.lua)
113 | * [LuaCATS: luazip](https://github.com/LuaCATS/luazip)
114 | → [TeXLuaCATS/LuaTeX/zip.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/zip.lua)
115 | * [LuaCATS: lzlib](https://github.com/LuaCATS/lzlib)
116 | → [TeXLuaCATS/LuaTeX/zlib.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/zlib.lua)
117 | * [LuaCATS: md5](https://github.com/LuaCATS/md5)
118 | → [TeXLuaCATS/LuaTeX/md5.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/md5.lua)
119 | * [LuaCATS: slnunicode](https://github.com/LuaCATS/slnunicode)
120 | → [TeXLuaCATS/LuaTeX/unicode.lua](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/unicode.lua)
121 |
122 | #### Downstream LuaCATS repositories
123 |
124 | The following repositories are *downstream* projects. This means: The
125 | type definitions are developed in this project. They are then *pushed*
126 | into a LuaCATS repository.
127 |
128 | * [LuaCATS: tex-lualatex](https://github.com/LuaCATS/tex-lualatex)
129 | ← [TeXLuaCATS/LuaLaTeX](https://github.com/TeXLuaCATS/LuaLaTeX)
130 | * [LuaCATS: tex-luatex](https://github.com/LuaCATS/tex-luatex)
131 | ← [TeXLuaCATS/LuaTeX](https://github.com/TeXLuaCATS/LuaTeX)
132 | * [LuaCATS: tex-lualibs](https://github.com/LuaCATS/tex-lualibs)
133 | ← [TeXLuaCATS/Lualibs](https://github.com/TeXLuaCATS/Lualibs)
134 | * [LuaCATS: tex-luametatex](https://github.com/LuaCATS/tex-luametatex)
135 | ← [TeXLuaCATS/LuaMetaTeX](https://github.com/TeXLuaCATS/LuaMetaTeX)
136 |
137 | ## Directory structure of the repository
138 |
139 | In the subfolder `library` are files named after the global libraries
140 | they document. For example, the `library/tex.lua` file contains the
141 | documentation for the `tex` library. These *Lua* files don’t contain
142 | real *Lua* code. They consist only of function bodies and empty
143 | tables. The main focus is in the docstrings.
144 |
145 | The API documentation is written in a [well documented annotation
146 | format](https://luals.github.io/wiki/annotations/).
147 | This format is based on the [EmmyLua](https://emmylua.github.io)
148 | format. Unfortunately, the *Lua* community has not yet been able to
149 | agree on a standarized annotation format. Many *Lua* project are
150 | documented in the [LDoc](https://github.com/lunarmodules/LDoc) format.
151 | However, the differences between these formats are marginal.
152 |
153 | ### Directory `library`
154 |
155 | The actual definitions are located in the directory `library`. This
156 | directory is divided into further subdirectories. In the folder `luatex`
157 | you will find the definitions that the engine *LuaTeX* provides. The
158 | folder `lualibs` documents the extension library of the same name. If
159 | you use `lualatex`, you may be interested in the folder of the same
160 | name.
161 |
162 | ### Directory `resources`
163 |
164 | The folder `resources` contains *TeX* manuals and *HTML* online
165 | documentation converted into *Lua* docstrings.
166 |
167 | ### Directory `examples`
168 |
169 | The `example` folder contains *TeX* and *Lua* files for demonstrating
170 | and testing the documented Lua API.
171 |
172 | ## Current version
173 |
174 | 2025/07/24 v0.2.0
175 |
176 | ## License
177 |
178 | Copyright (C) 2022-2025 by Josef Friedrich
179 | ------------------------------------------------------------------------
180 |
181 | This program is free software: you can redistribute it and/or modify it
182 | under the terms of the GNU General Public License as published by the
183 | Free Software Foundation, either version 2 of the License, or (at your
184 | option) any later version.
185 |
186 | This program is distributed in the hope that it will be useful, but
187 | WITHOUT ANY WARRANTY; without even the implied warranty of
188 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
189 | Public License for more details.
190 |
191 | You should have received a copy of the GNU General Public License along
192 | with this program. If not, see .
193 |
194 | ### About the license selection
195 |
196 | The same license was used for the type definitions as for LuaTeX (GPLv2).
197 | The MIT license is used for the external upstream projects.
198 |
199 | ### GPLv2 copyright notice for every file
200 |
201 | Only two hyphens are used here, rather than three, so that the copyright notice
202 | does not end up in the rendered documentation.
203 |
204 | ```lua
205 | -- -----------------------------------------------------------------------------
206 | -- Copyright (C) 2022-2025 by Josef Friedrich
207 | -- -----------------------------------------------------------------------------
208 | --
209 | -- This program is free software: you can redistribute it and/or modify it
210 | -- under the terms of the GNU General Public License as published by the
211 | -- Free Software Foundation, either version 2 of the License, or (at your
212 | -- option) any later version.
213 | --
214 | -- This program is distributed in the hope that it will be useful, but
215 | -- WITHOUT ANY WARRANTY; without even the implied warranty of
216 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
217 | -- Public License for more details.
218 | --
219 | -- You should have received a copy of the GNU General Public License along
220 | -- with this program. If not, see .
221 | --
222 | -- -----------------------------------------------------------------------------
223 |
224 | ```
225 |
226 | ### MIT copyright notice for every file
227 |
228 | ```lua
229 | -- -----------------------------------------------------------------------------
230 | -- Copyright (c) 2023-2025 by Josef Friedrich
231 | -- -----------------------------------------------------------------------------
232 | --
233 | -- MIT License
234 | --
235 | -- Permission is hereby granted, free of charge, to any person obtaining a copy
236 | -- of this software and associated documentation files (the "Software"), to deal
237 | -- in the Software without restriction, including without limitation the rights
238 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
239 | -- copies of the Software, and to permit persons to whom the Software is
240 | -- furnished to do so, subject to the following conditions:
241 | --
242 | -- The above copyright notice and this permission notice shall be included in
243 | -- all copies or substantial portions of the Software.
244 | --
245 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
246 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
247 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
248 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
249 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
250 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
251 | -- SOFTWARE.
252 | --
253 | -- -----------------------------------------------------------------------------
254 |
255 | ```
256 |
257 | ## Installation / Setup for Visual Studio Code
258 |
259 | Install [Visual Studio Code](https://code.visualstudio.com/) and the
260 | [lua-language-server](https://marketplace.visualstudio.com/items?itemName=sumneko.lua).
261 |
262 |
263 | ```
264 | git clone https://github.com/TeXLuaCATS/LuaTeX.git
265 | ```
266 |
267 | `.vscode/settings.json`:
268 |
269 | ```json
270 | {
271 | "Lua.workspace.library": [
272 | "/library"
273 | ]
274 | }
275 | ```
276 |
277 | ## How to contribute
278 |
279 | The preferred method of contributing to the project is via Github pull
280 | requests. You can also email patches to josef@friedrich.rocks.
281 | It is ok if you only document the data types of the input parameters.
282 |
283 | Use imperative mood for the first line: https://peps.python.org/pep-0257/
284 |
285 | `Please contribute!` messages
286 |
287 | Default message:
288 |
289 | ```lua
290 | ---😱 [Types](https://github.com/TeXLuaCATS/LuaTeX/blob/main/library/pdf.lua) incomplete or incorrect? 🙏 [Please contribute!](https://github.com/TeXLuaCATS/LuaTeX/pulls)
291 | ```
292 |
293 | No documentation at all:
294 |
295 | ```lua
296 | ---
297 | ---Warning! Undocumented code!