mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
143 lines
5 KiB
Python
143 lines
5 KiB
Python
|
"""
|
||
|
This script generates docs/plugin-meta.lua. It accepts no arguments
|
||
|
|
||
|
It assumes comments look like:
|
||
|
/**
|
||
|
* Thing
|
||
|
*
|
||
|
* @lua@param thing boolean
|
||
|
* @lua@returns boolean
|
||
|
* @exposed name
|
||
|
*/
|
||
|
- Do not have any useful info on '/**' and '*/' lines.
|
||
|
- Class members are not allowed to have non-@command lines and commands different from @lua@field
|
||
|
|
||
|
Valid commands are:
|
||
|
1. @exposeenum [dotted.name.in_lua.last_part]
|
||
|
Define a table with keys of the enum. Values behind those keys aren't
|
||
|
written on purpose.
|
||
|
This generates three lines:
|
||
|
- An type alias of [last_part] to integer,
|
||
|
- A type description that describes available values of the enum,
|
||
|
- A global table definition for the num
|
||
|
2. @lua[@command]
|
||
|
Writes [@command] to the file as a comment, usually this is @class, @param, @return, ...
|
||
|
@lua@class and @lua@field have special treatment when it comes to generation of spacing new lines
|
||
|
3. @exposed [c2.name]
|
||
|
Generates a function definition line from the last `@lua@param`s.
|
||
|
|
||
|
Non-command lines of comments are written with a space after '---'
|
||
|
"""
|
||
|
from pathlib import Path
|
||
|
|
||
|
BOILERPLATE = """
|
||
|
---@meta Chatterino2
|
||
|
|
||
|
-- This file is automatically generated from src/controllers/plugins/LuaAPI.hpp by the scripts/make_luals_meta.py script
|
||
|
-- This file is intended to be used with LuaLS (https://luals.github.io/).
|
||
|
-- Add the folder this file is in to "Lua.workspace.library".
|
||
|
|
||
|
c2 = {}
|
||
|
"""
|
||
|
|
||
|
repo_root = Path(__file__).parent.parent
|
||
|
lua_api_file = repo_root / "src" / "controllers" / "plugins" / "LuaAPI.hpp"
|
||
|
lua_meta = repo_root / "docs" / "plugin-meta.lua"
|
||
|
|
||
|
print("Reading from", lua_api_file.relative_to(repo_root))
|
||
|
print("Writing to", lua_meta.relative_to(repo_root))
|
||
|
with lua_api_file.open("r") as f:
|
||
|
lines = f.read().splitlines()
|
||
|
|
||
|
# Are we in a doc comment?
|
||
|
comment: bool = False
|
||
|
|
||
|
# Last `@lua@param`s seen - for @exposed generation
|
||
|
last_params_names: list[str] = []
|
||
|
# Are we in a `@lua@class` definition? - makes newlines around @lua@class and @lua@field prettier
|
||
|
is_class = False
|
||
|
|
||
|
# The name of the next enum in lua world
|
||
|
expose_next_enum_as: str | None = None
|
||
|
# Name of the current enum in c++ world, used to generate internal typenames for
|
||
|
current_enum_name: str | None = None
|
||
|
|
||
|
with lua_meta.open("w") as out:
|
||
|
out.write(BOILERPLATE[1:]) # skip the newline after triple quote
|
||
|
|
||
|
for line in lines:
|
||
|
line = line.strip()
|
||
|
if line.startswith("enum class "):
|
||
|
line = line.removeprefix("enum class ")
|
||
|
temp = line.split(" ", 2)
|
||
|
current_enum_name = temp[0]
|
||
|
if not expose_next_enum_as:
|
||
|
print(
|
||
|
f"Skipping enum {current_enum_name}, there wasn't a @exposeenum command"
|
||
|
)
|
||
|
current_enum_name = None
|
||
|
continue
|
||
|
current_enum_name = expose_next_enum_as.split(".", 1)[-1]
|
||
|
out.write("---@alias " + current_enum_name + " integer\n")
|
||
|
out.write("---@type { ")
|
||
|
# temp[1] is '{'
|
||
|
if len(temp) == 2: # no values on this line
|
||
|
continue
|
||
|
line = temp[2]
|
||
|
|
||
|
if current_enum_name is not None:
|
||
|
for i, tok in enumerate(line.split(" ")):
|
||
|
if tok == "};":
|
||
|
break
|
||
|
entry = tok.removesuffix(",")
|
||
|
if i != 0:
|
||
|
out.write(", ")
|
||
|
out.write(entry + ": " + current_enum_name)
|
||
|
out.write(" }\n" f"{expose_next_enum_as} = {{}}\n")
|
||
|
print(f"Wrote enum {expose_next_enum_as} => {current_enum_name}")
|
||
|
current_enum_name = None
|
||
|
expose_next_enum_as = None
|
||
|
continue
|
||
|
|
||
|
if line.startswith("/**"):
|
||
|
comment = True
|
||
|
continue
|
||
|
elif "*/" in line:
|
||
|
comment = False
|
||
|
if not is_class:
|
||
|
out.write("\n")
|
||
|
continue
|
||
|
if not comment:
|
||
|
continue
|
||
|
line = line.replace("*", "", 1).lstrip()
|
||
|
if line == "":
|
||
|
out.write("---\n")
|
||
|
elif line.startswith("@exposeenum "):
|
||
|
expose_next_enum_as = line.split(" ", 1)[1]
|
||
|
elif line.startswith("@exposed "):
|
||
|
exp = line.replace("@exposed ", "", 1)
|
||
|
params = ", ".join(last_params_names)
|
||
|
out.write(f"function {exp}({params}) end\n")
|
||
|
print(f"Wrote function {exp}(...)")
|
||
|
last_params_names = []
|
||
|
elif line.startswith("@lua"):
|
||
|
command = line.replace("@lua", "", 1)
|
||
|
if command.startswith("@param"):
|
||
|
last_params_names.append(command.split(" ", 2)[1])
|
||
|
elif command.startswith("@class"):
|
||
|
print(f"Writing {command}")
|
||
|
if is_class:
|
||
|
out.write("\n")
|
||
|
is_class = True
|
||
|
elif not command.startswith("@field"):
|
||
|
is_class = False
|
||
|
|
||
|
out.write("---" + command + "\n")
|
||
|
else:
|
||
|
if is_class:
|
||
|
is_class = False
|
||
|
out.write("\n")
|
||
|
|
||
|
# note the space difference from the branch above
|
||
|
out.write("--- " + line + "\n")
|