diff --git a/README.md b/README.md index 2ce652f..3d06ba6 100644 --- a/README.md +++ b/README.md @@ -40,13 +40,25 @@ A Minetest mod library to make modifying formspecs easier. The AST is similar (and generated from) [the formspec element list], however all attributes are lowercase. -[the formspec element list]: https://github.com/minetest/minetest/blob/dee2210/doc/lua_api.txt#L1959 +[the formspec element list]: https://minetest.gitlab.io/minetest/formspec/#elements ### Recent backwards incompatibilities +While I try to reduce backwards incompatibilities, sometimes they are necessary +to either fix bugs in formspec_ast or for implementing new formspec features. + +#### February 2021 + + - The `close_on_enter` value for `field_close_on_enter` is now a boolean + instead of a string. + - The `frame_count`, `frame_duration` and `frame_start` values in + `animated_image` are now numbers. + +#### September 2020 + - The `style[]` element has a `selectors` field instead of `name`. Using - `name` when unparsing formspecs still works, however parsed formspecs - always use `selectors`. + `name` when unparsing formspecs still works, however parsed formspecs + always use `selectors`. ### Special cases diff --git a/elements.lua b/elements.lua index 24ba3e7..c65ae39 100644 --- a/elements.lua +++ b/elements.lua @@ -3,4 +3,4 @@ -- by make_elements.py. -- -return {["formspec_version"] = {{{"version", "number"}}}, ["size"] = {{{{"w", "number"}, {"h", "number"}}}, {{{"w", "number"}, {"h", "number"}, {"fixed_size", "boolean"}}}}, ["position"] = {{{{"x", "number"}, {"y", "number"}}}}, ["anchor"] = {{{{"x", "number"}, {"y", "number"}}}}, ["no_prepend"] = {{}}, ["real_coordinates"] = {{{"bool", "boolean"}}}, ["container"] = {{{{"x", "number"}, {"y", "number"}}}}, ["container_end"] = {{}}, ["scroll_container"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"scrollbar_name", "string"}, {"orientation", "string"}, {"scroll_factor", "number"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"scrollbar_name", "string"}, {"orientation", "string"}}}, ["scroll_container_end"] = {{}}, ["list"] = {{{"inventory_location", "string"}, {"list_name", "string"}, {{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"", "null"}}, {{"inventory_location", "string"}, {"list_name", "string"}, {{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"starting_item_index", "number"}}}, ["listring"] = {{{"inventory_location", "string"}, {"list_name", "string"}}, {}}, ["listcolors"] = {{{"slot_bg_normal", "string"}, {"slot_bg_hover", "string"}, {"slot_border", "string"}, {"tooltip_bgcolor", "string"}, {"tooltip_fontcolor", "string"}}, {{"slot_bg_normal", "string"}, {"slot_bg_hover", "string"}, {"slot_border", "string"}}, {{"slot_bg_normal", "string"}, {"slot_bg_hover", "string"}}}, ["tooltip"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"tooltip_text", "string"}, {"bgcolor", "string"}, {"fontcolor", "string"}}, {{"gui_element_name", "string"}, {"tooltip_text", "string"}, {"bgcolor", "string"}, {"fontcolor", "string"}}}, ["image"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}}}, ["animated_image"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"texture_name", "string"}, {"frame_count", "string"}, {"frame_duration", "string"}, {"frame_start", "string"}}}, ["item_image"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"item_name", "string"}}}, ["bgcolor"] = {{{"bgcolor", "string"}, {"fullscreen", "boolean"}, {"fbgcolor", "string"}}, {{"bgcolor", "string"}, {"fullscreen", "boolean"}}, {{"bgcolor", "string"}}}, ["background"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}}}, ["background9"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}, {{"middle_x", "number"}, {"middle_y", "number"}, {"middle_x2", "number"}, {"middle_y2", "number"}}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}, {{"middle_x", "number"}, {"middle_y", "number"}}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}, {{"middle_x", "number"}}}}, ["pwdfield"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}}}, ["field"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}, {"default", "string"}}, {{"name", "string"}, {"label", "string"}, {"default", "string"}}}, ["field_close_on_enter"] = {{{"name", "string"}, {"close_on_enter", "string"}}}, ["textarea"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}, {"default", "string"}}}, ["label"] = {{{{"x", "number"}, {"y", "number"}}, {"label", "string"}}}, ["hypertext"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"text", "string"}}}, ["vertlabel"] = {{{{"x", "number"}, {"y", "number"}}, {"label", "string"}}}, ["button"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}}}, ["image_button"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"name", "string"}, {"label", "string"}, {"noclip", "boolean"}, {"drawborder", "boolean"}, {"pressed_texture_name", "string"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"name", "string"}, {"label", "string"}}}, ["item_image_button"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"item_name", "string"}, {"name", "string"}, {"label", "string"}}}, ["button_exit"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}}}, ["image_button_exit"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"name", "string"}, {"label", "string"}}}, ["textlist"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"listelem", "string"}, "..."}}, {"selected_idx", "number"}, {"transparent", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"listelem", "string"}, "..."}}}}, ["tabheader"] = {{{{"x", "number"}, {"y", "number"}}, {"h", "number"}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}, {"draw_border", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}, {"draw_border", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}, {"draw_border", "boolean"}}}, ["box"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"color", "string"}}}, ["dropdown"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}, {"index_event", "string"}}, {{{"x", "number"}, {"y", "number"}}, {"w", "number"}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}, {"index_event", "string"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}}, {{{"x", "number"}, {"y", "number"}}, {"w", "number"}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}}}, ["checkbox"] = {{{{"x", "number"}, {"y", "number"}}, {"name", "string"}, {"label", "string"}, {"selected", "boolean"}}}, ["scrollbar"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"orientation", "string"}, {"name", "string"}, {"value", "string"}}}, ["scrollbaroptions"] = {{{{"opt", "table"}, "..."}}}, ["table"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"cells", "string"}, "..."}}, {"selected_idx", "number"}}}, ["tableoptions"] = {{{{"opt", "table"}, "..."}}}, ["tablecolumns"] = {{{{{"type", "string"}, {{"opt", "table"}, "..."}}, "..."}}}, ["style"] = {{{{{"selectors", "string"}, "..."}}, {{"prop", "table"}, "..."}}, {{{"name", "string"}}, {{"prop", "table"}, "..."}}}, ["style_type"] = {{{{{"selectors", "string"}, "..."}}, {{"prop", "table"}, "..."}}, {{{"name", "string"}}, {{"prop", "table"}, "..."}}}, ["set_focus"] = {{{"name", "string"}, {"force", "boolean"}}}} \ No newline at end of file +return {["formspec_version"] = {{{"version", "number"}}}, ["size"] = {{{{"w", "number"}, {"h", "number"}}}, {{{"w", "number"}, {"h", "number"}, {"fixed_size", "boolean"}}}}, ["position"] = {{{{"x", "number"}, {"y", "number"}}}}, ["anchor"] = {{{{"x", "number"}, {"y", "number"}}}}, ["no_prepend"] = {{}}, ["real_coordinates"] = {{{"bool", "boolean"}}}, ["container"] = {{{{"x", "number"}, {"y", "number"}}}}, ["container_end"] = {{}}, ["scroll_container"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"scrollbar_name", "string"}, {"orientation", "string"}, {"scroll_factor", "number"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"scrollbar_name", "string"}, {"orientation", "string"}}}, ["scroll_container_end"] = {{}}, ["list"] = {{{"inventory_location", "string"}, {"list_name", "string"}, {{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"", "null"}}, {{"inventory_location", "string"}, {"list_name", "string"}, {{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"starting_item_index", "number"}}}, ["listring"] = {{{"inventory_location", "string"}, {"list_name", "string"}}, {}}, ["listcolors"] = {{{"slot_bg_normal", "string"}, {"slot_bg_hover", "string"}, {"slot_border", "string"}, {"tooltip_bgcolor", "string"}, {"tooltip_fontcolor", "string"}}, {{"slot_bg_normal", "string"}, {"slot_bg_hover", "string"}, {"slot_border", "string"}}, {{"slot_bg_normal", "string"}, {"slot_bg_hover", "string"}}}, ["tooltip"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"tooltip_text", "string"}, {"bgcolor", "string"}, {"fontcolor", "string"}}, {{"gui_element_name", "string"}, {"tooltip_text", "string"}, {"bgcolor", "string"}, {"fontcolor", "string"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"tooltip_text", "string"}, {"bgcolor", "string"}}, {{"gui_element_name", "string"}, {"tooltip_text", "string"}, {"bgcolor", "string"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"tooltip_text", "string"}}, {{"gui_element_name", "string"}, {"tooltip_text", "string"}}}, ["image"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}}}, ["animated_image"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"texture_name", "string"}, {"frame_count", "number"}, {"frame_duration", "number"}, {"frame_start", "number"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"texture_name", "string"}, {"frame_count", "number"}, {"frame_duration", "number"}}}, ["item_image"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"item_name", "string"}}}, ["bgcolor"] = {{{"bgcolor", "string"}, {"fullscreen", "boolean"}, {"fbgcolor", "string"}}, {{"bgcolor", "string"}, {"fullscreen", "boolean"}}, {{"bgcolor", "string"}}}, ["background"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}}}, ["background9"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}, {{"middle_x", "number"}, {"middle_y", "number"}, {"middle_x2", "number"}, {"middle_y2", "number"}}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}, {{"middle_x", "number"}, {"middle_y", "number"}}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"auto_clip", "boolean"}, {{"middle_x", "number"}}}}, ["pwdfield"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}}}, ["field"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}, {"default", "string"}}, {{"name", "string"}, {"label", "string"}, {"default", "string"}}}, ["field_close_on_enter"] = {{{"name", "string"}, {"close_on_enter", "boolean"}}}, ["textarea"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}, {"default", "string"}}}, ["label"] = {{{{"x", "number"}, {"y", "number"}}, {"label", "string"}}}, ["hypertext"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"text", "string"}}}, ["vertlabel"] = {{{{"x", "number"}, {"y", "number"}}, {"label", "string"}}}, ["button"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}}}, ["image_button"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"name", "string"}, {"label", "string"}, {"noclip", "boolean"}, {"drawborder", "boolean"}, {"pressed_texture_name", "string"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"name", "string"}, {"label", "string"}}}, ["item_image_button"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"item_name", "string"}, {"name", "string"}, {"label", "string"}}}, ["button_exit"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {"label", "string"}}}, ["image_button_exit"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"texture_name", "string"}, {"name", "string"}, {"label", "string"}}}, ["textlist"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"listelem", "string"}, "..."}}, {"selected_idx", "number"}, {"transparent", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"listelem", "string"}, "..."}}, {"selected_idx", "number"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"listelem", "string"}, "..."}}}}, ["tabheader"] = {{{{"x", "number"}, {"y", "number"}}, {"h", "number"}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}, {"draw_border", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}, {"draw_border", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}, {"draw_border", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {"h", "number"}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}, {"transparent", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {"h", "number"}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}}, {{{"x", "number"}, {"y", "number"}}, {"name", "string"}, {{{"caption", "string"}, "..."}}, {"current_tab", "string"}}}, ["box"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"color", "string"}}}, ["dropdown"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}, {"index_event", "string"}}, {{{"x", "number"}, {"y", "number"}}, {"w", "number"}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}, {"index_event", "string"}}, {{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}}, {{{"x", "number"}, {"y", "number"}}, {"w", "number"}, {"name", "string"}, {{{"item", "string"}, "..."}}, {"selected_idx", "number"}}}, ["checkbox"] = {{{{"x", "number"}, {"y", "number"}}, {"name", "string"}, {"label", "string"}, {"selected", "boolean"}}, {{{"x", "number"}, {"y", "number"}}, {"name", "string"}, {"label", "string"}}}, ["scrollbar"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"orientation", "string"}, {"name", "string"}, {"value", "string"}}}, ["scrollbaroptions"] = {{{{"opt", "table"}, "..."}}}, ["table"] = {{{{"x", "number"}, {"y", "number"}}, {{"w", "number"}, {"h", "number"}}, {"name", "string"}, {{{"cells", "string"}, "..."}}, {"selected_idx", "number"}}}, ["tableoptions"] = {{{{"opt", "table"}, "..."}}}, ["tablecolumns"] = {{{{{"type", "string"}, {{"opt", "table"}, "..."}}, "..."}}}, ["style"] = {{{{{"selectors", "string"}, "..."}}, {{"prop", "table"}, "..."}}, {{{"name", "string"}}, {{"prop", "table"}, "..."}}}, ["style_type"] = {{{{{"selectors", "string"}, "..."}}, {{"prop", "table"}, "..."}}, {{{"name", "string"}}, {{"prop", "table"}, "..."}}}, ["set_focus"] = {{{"name", "string"}, {"force", "boolean"}}, {{"name", "string"}}}} \ No newline at end of file diff --git a/elements.yaml b/elements.yaml new file mode 100644 index 0000000..4a373e4 --- /dev/null +++ b/elements.yaml @@ -0,0 +1,465 @@ +# +# This file is automatically generated by make_elements.py and isn't actually +# used by formspec_ast, however it is useful for comparing changes across +# lua_api versions. +# + +anchor: +- - - [x, number] + - [y, number] +animated_image: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [texture_name, string] + - [frame_count, number] + - [frame_duration, number] + - [frame_start, number] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [texture_name, string] + - [frame_count, number] + - [frame_duration, number] +background: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] + - [auto_clip, boolean] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] +background9: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] + - [auto_clip, boolean] + - - [middle_x, number] + - [middle_y, number] + - [middle_x2, number] + - [middle_y2, number] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] + - [auto_clip, boolean] + - - [middle_x, number] + - [middle_y, number] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] + - [auto_clip, boolean] + - - [middle_x, number] +bgcolor: +- - [bgcolor, string] + - [fullscreen, boolean] + - [fbgcolor, string] +- - [bgcolor, string] + - [fullscreen, boolean] +- - [bgcolor, string] +box: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [color, string] +button: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [label, string] +button_exit: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [label, string] +checkbox: +- - - [x, number] + - [y, number] + - [name, string] + - [label, string] + - [selected, boolean] +- - - [x, number] + - [y, number] + - [name, string] + - [label, string] +container: +- - - [x, number] + - [y, number] +container_end: +- [] +dropdown: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [item, string] + - '...' + - [selected_idx, number] + - [index_event, string] +- - - [x, number] + - [y, number] + - [w, number] + - [name, string] + - - - [item, string] + - '...' + - [selected_idx, number] + - [index_event, string] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [item, string] + - '...' + - [selected_idx, number] +- - - [x, number] + - [y, number] + - [w, number] + - [name, string] + - - - [item, string] + - '...' + - [selected_idx, number] +field: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [label, string] + - [default, string] +- - [name, string] + - [label, string] + - [default, string] +field_close_on_enter: +- - [name, string] + - [close_on_enter, boolean] +formspec_version: +- - [version, number] +hypertext: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [text, string] +image: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] +image_button: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] + - [name, string] + - [label, string] + - [noclip, boolean] + - [drawborder, boolean] + - [pressed_texture_name, string] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] + - [name, string] + - [label, string] +image_button_exit: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [texture_name, string] + - [name, string] + - [label, string] +item_image: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [item_name, string] +item_image_button: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [item_name, string] + - [name, string] + - [label, string] +label: +- - - [x, number] + - [y, number] + - [label, string] +list: +- - [inventory_location, string] + - [list_name, string] + - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - ['', 'null'] +- - [inventory_location, string] + - [list_name, string] + - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [starting_item_index, number] +listcolors: +- - [slot_bg_normal, string] + - [slot_bg_hover, string] + - [slot_border, string] + - [tooltip_bgcolor, string] + - [tooltip_fontcolor, string] +- - [slot_bg_normal, string] + - [slot_bg_hover, string] + - [slot_border, string] +- - [slot_bg_normal, string] + - [slot_bg_hover, string] +listring: +- - [inventory_location, string] + - [list_name, string] +- [] +no_prepend: +- [] +position: +- - - [x, number] + - [y, number] +pwdfield: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [label, string] +real_coordinates: +- - [bool, boolean] +scroll_container: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [scrollbar_name, string] + - [orientation, string] + - [scroll_factor, number] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [scrollbar_name, string] + - [orientation, string] +scroll_container_end: +- [] +scrollbar: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [orientation, string] + - [name, string] + - [value, string] +scrollbaroptions: +- - - [opt, table] + - '...' +set_focus: +- - [name, string] + - [force, boolean] +- - [name, string] +size: +- - - [w, number] + - [h, number] +- - - [w, number] + - [h, number] + - [fixed_size, boolean] +style: +- - - - [selectors, string] + - '...' + - - [prop, table] + - '...' +- - - [name, string] + - - [prop, table] + - '...' +style_type: +- - - - [selectors, string] + - '...' + - - [prop, table] + - '...' +- - - [name, string] + - - [prop, table] + - '...' +tabheader: +- - - [x, number] + - [y, number] + - [h, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] + - [transparent, boolean] + - [draw_border, boolean] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] + - [transparent, boolean] + - [draw_border, boolean] +- - - [x, number] + - [y, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] + - [transparent, boolean] + - [draw_border, boolean] +- - - [x, number] + - [y, number] + - [h, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] + - [transparent, boolean] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] + - [transparent, boolean] +- - - [x, number] + - [y, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] + - [transparent, boolean] +- - - [x, number] + - [y, number] + - [h, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] +- - - [x, number] + - [y, number] + - [name, string] + - - - [caption, string] + - '...' + - [current_tab, string] +table: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [cells, string] + - '...' + - [selected_idx, number] +tablecolumns: +- - - - [type, string] + - - [opt, table] + - '...' + - '...' +tableoptions: +- - - [opt, table] + - '...' +textarea: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - [label, string] + - [default, string] +textlist: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [listelem, string] + - '...' + - [selected_idx, number] + - [transparent, boolean] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [listelem, string] + - '...' + - [selected_idx, number] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [name, string] + - - - [listelem, string] + - '...' +tooltip: +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [tooltip_text, string] + - [bgcolor, string] + - [fontcolor, string] +- - [gui_element_name, string] + - [tooltip_text, string] + - [bgcolor, string] + - [fontcolor, string] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [tooltip_text, string] + - [bgcolor, string] +- - [gui_element_name, string] + - [tooltip_text, string] + - [bgcolor, string] +- - - [x, number] + - [y, number] + - - [w, number] + - [h, number] + - [tooltip_text, string] +- - [gui_element_name, string] + - [tooltip_text, string] +vertlabel: +- - - [x, number] + - [y, number] + - [label, string] diff --git a/make_elements.py b/make_elements.py index 1daca9b..5e9629f 100755 --- a/make_elements.py +++ b/make_elements.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 # # A primitive script to parse lua_api.txt for formspec elements. +# This script needs Python 3.8+ and ruamel.yaml to work. # -import copy, lua_dump, os, urllib.request +import copy, json, lua_dump, os, re, ruamel.yaml, urllib.request def _make_known(**kwargs): known = {} @@ -14,9 +15,11 @@ def _make_known(**kwargs): _known = _make_known( number=('x', 'y', 'w', 'h', 'selected_idx', 'version', - 'starting_item_index', 'scroll_factor'), + 'starting_item_index', 'scroll_factor', 'frame_count', + 'frame_duration', 'frame_start'), boolean=('auto_clip', 'fixed_size', 'transparent', 'draw_border', 'bool', - 'fullscreen', 'noclip', 'drawborder', 'selected', 'force'), + 'fullscreen', 'noclip', 'drawborder', 'selected', 'force', + 'close_on_enter'), table=('param', 'opt', 'prop'), null=('',), ) @@ -31,12 +34,16 @@ _aliases = { 'cell': 'cells', } +def _fix_param_name(param): + param = param.lower().strip().strip('<>').replace(' ', '_') + param = _aliases.get(param, param) + assert param != '...' + return param + def _fix_param(param): if isinstance(param, str): if ',' not in param: - param = param.lower().strip().strip('<>').replace(' ', '_') - param = _aliases.get(param, param) - assert param != '...' + param = _fix_param_name(param) return (param, _known.get(param, 'string')) param = param.split(',') @@ -111,12 +118,6 @@ def _style_hook(params): params[0] = [(('selectors', 'string'), '...')] yield params -# Fix scroll_container -@hook('scroll_container') -def _scroll_container_hook(params): - yield params - yield params[:4] - # Fix dropdown @hook('dropdown') def _scroll_container_hook(params): @@ -127,14 +128,29 @@ def _scroll_container_hook(params): yield params[:5] yield params +# Fix textlist +@hook('textlist') +def _textlist_hook(params): + if len(params) > 5: + yield params[:5] + yield params + +_param_re = re.compile(r'^\* `([^`]+)`(?: and `([^`]+)`)?:? ') def _raw_parse(data): + # Get everything from the elements heading to the end of the next heading data = data.split('\nElements\n--------\n', 1)[-1].split('\n----', 1)[0] - for line in data.split('\n'): - if not line.startswith('### `') or not line.endswith('`'): + + # Remove the next heading + data = data.rsplit('\n', 1)[0] + + # Get element data + for elem_data in data.split('\n### '): + lines = elem_data.split('\n') + raw_elem = lines.pop(0) + if not raw_elem.startswith('`') or not raw_elem.endswith('`'): continue - elem = line[5:-2] - name, params = elem.split('[', 1) + name, params = raw_elem[1:-2].split('[', 1) if params: params = _fix_param(params.split(';')) else: @@ -143,9 +159,37 @@ def _raw_parse(data): if name in _hooks: for p in reversed(tuple(map(copy.deepcopy, _hooks[name](params)))): yield name, p - else: + continue + + # Optional parameters + optional_params = set() + for line in lines: + match = _param_re.match(line) + if not match or 'optional' not in line.lower(): + continue + + optional_params.add(_fix_param_name(match.group(1))) + if p2 := match.group(2): + optional_params.add(_fix_param_name(p2)) + + # if optional_params: + # print('Optional', name, optional_params) + + # Convert the optional parameters into a format formspec_ast can + # understand without major changes + while True: yield name, params + if not params: + break + last_param = params[-1] + if (not isinstance(last_param, tuple) or + not isinstance(last_param[0], str) or + last_param[0] not in optional_params): + break + # print('Optional', name, last_param) + params = params[:-1] + def parse(data): """ Returns a dict: @@ -167,7 +211,8 @@ def parse(data): return res -URL = 'https://github.com/minetest/minetest/raw/master/doc/lua_api.txt' +# TODO: Fix model[] parsing then switch this back to the master branch +URL = 'https://github.com/minetest/minetest/raw/050964b/doc/lua_api.txt' def fetch_and_parse(*, url=URL): with urllib.request.urlopen(url) as f: raw = f.read() @@ -181,13 +226,33 @@ _comment = """ """ +_yaml_comment = """ +# +# This file is automatically generated by make_elements.py and isn't actually +# used by formspec_ast, however it is useful for comparing changes across +# lua_api versions. +# + +""" + def main(): dirname = os.path.dirname(__file__) filename = os.path.join(dirname, 'elements.lua') + data = fetch_and_parse() + + # Horrible code to create elements.yaml + filename2 = os.path.join(dirname, 'elements.yaml') + print('Writing to ' + filename2 + '...') + with open(filename2, 'w') as f: + f.write(_yaml_comment.lstrip()) + # Yuck - Unparsing then re-parsing the data as JSON is the easiest way + # I can think of to convert tuples to lists. + ruamel.yaml.dump(json.loads(json.dumps(data)), f) + print('Writing to ' + filename + '...') with open(filename, 'w') as f: f.write(_comment.lstrip()) - f.write(lua_dump.serialize(fetch_and_parse())) + f.write(lua_dump.serialize(data)) # elems = fetch_and_parse() # for elem in sorted(elems): # for def_ in elems[elem]: diff --git a/tests.lua b/tests.lua index 21c9303..0782687 100644 --- a/tests.lua +++ b/tests.lua @@ -80,6 +80,8 @@ local fs = [[ image[0,1;1,1;air.png] set_focus[name;true] dropdown[0,0;1;test;abc,def,ghi,jkl;2] + field_close_on_enter[my-field;false] + bgcolor[blue] ]] fs = ('\n' .. fs):gsub('\n[ \n]*', '') @@ -161,7 +163,16 @@ test_parse_unparse(fs, { name = "test", item = {"abc", "def", "ghi", "jkl"}, selected_idx = 2, - } + }, + { + type = "field_close_on_enter", + name = "my-field", + close_on_enter = false, + }, + { + type = "bgcolor", + bgcolor = "blue", + }, })