From e1d3b7b2576481ca53bc7d650eeccabce1d121fa Mon Sep 17 00:00:00 2001 From: Emma Date: Fri, 6 Sep 2024 18:42:31 -0400 Subject: [PATCH] Clean up love2d parser and restructure code --- tools/get-docs/love2d.fnl | 123 ++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 51 deletions(-) diff --git a/tools/get-docs/love2d.fnl b/tools/get-docs/love2d.fnl index 7536057..781abbf 100644 --- a/tools/get-docs/love2d.fnl +++ b/tools/get-docs/love2d.fnl @@ -5,21 +5,18 @@ (local require-love-api (partial require (.. love-api-build-directory :/love_api))) -(local stringify-table fennel.view) - ; ; UTILS ; ----- -(fn merge [...] - (let [arg-count (select "#" ...) - args [...]] - (if (= arg-count 0) - {} - (faccumulate [result {} i 1 arg-count] - (collect [k v (pairs (. args i)) &into result] - (if (?. result k) - (values k (merge v (. result k))) - (values k v))))))) +(fn build-lsp-value [name ?args ?docstring ?fields] + "Takes ... and returns a table to be used with the LSP." + (let [lsp-value {:binding name} + ?metadata (or ?args ?docstring)] + (when ?metadata (set lsp-value.metadata {})) + (when ?args (set lsp-value.metadata.fnl/arglist ?args)) + (when ?docstring (set lsp-value.metadata.fnl/docstring ?docstring)) + (when ?fields (set lsp-value.fields ?fields)) + lsp-value)) (fn download-love-api-tooling! [] "Clones the LÖVE-API git repository that contains tooling to scrape and @@ -28,62 +25,86 @@ (git-clone love-api-build-directory "https://github.com/love2d-community/love-api"))) -(fn build-lsp-value [name ?args ?docstring] - "Takes ... and returns a table to be used with the LSP." - (let [lsp-value {:binding name :metadata {}}] - (when ?args (set lsp-value.metadata.fnl/arglist ?args)) - (when ?docstring (set lsp-value.metadata.fnl/docstring ?docstring)) - lsp-value)) +(fn merge [...] + (let [arg-count (select "#" ...) + args [...]] + (if (= arg-count 0) + {} + (faccumulate [result {} i 1 arg-count] + (collect [k v (pairs (. args i)) &into result] + (values k v)))))) ; ; PARSERS ; ------- -(fn fn-arguments->names [arguments] +(fn variant-arguments->names [arguments] "Given an array of arguments, return all names as an array." (icollect [_i {:description _ : name :type _} (ipairs arguments)] name)) -(fn fn-return->string [returns] - "Given an array of arguments, return a formatted description." +(fn variant-return->string [returns] + "Given an array of return values, return a formatted description." (accumulate [x "\n\nReturns -" _i {: description : name :type return-type} (ipairs returns)] (.. x "\n" " * " name " (`" return-type "`) - " description))) -(fn parse-fn-variant [variant] - "Given an array of fuction variants, return an object where the first variant - is made the formatted LSP option, with any remaining variants being formatted - as a single description." +(fn parse-first-function-variant [[variant]] + "Given an array of fuction variants, format and return the first variant + for the LSP." (collect [v-key v-value (pairs variant)] (case v-key - :returns (values :returns v-value) - :arguments (values :args (fn-arguments->names v-value))))) + :returns (values :returns (variant-return->string v-value)) + :arguments (values :args (variant-arguments->names v-value))))) -(fn parse-doc-module-tbl [docs-tbl] - "Takes a LÖVE-API documentation table and generates a list of each - key with values suitable for the Fennel LSP." - {:fields (collect [_i value (ipairs docs-tbl)] - (let [{: name : description} value - ?variants (?. value :variants) - first-variant (if ?variants - (parse-fn-variant (. ?variants 1)) - nil) - ?args (?. first-variant :args) - ?returns (?. first-variant :returns) - docstring (.. description - (if ?returns (fn-return->string ?returns) ""))] - (values name (build-lsp-value name ?args docstring))))}) +(fn love-functions->lsp [docs-tbl prefix] + "Given an array of documented functions for a LÖVE module, generate a table + for the Fennel LSP." + (collect [_i value (ipairs docs-tbl)] + (let [{: name : description} value + binding (.. prefix name) + ?variants (?. value :variants) + first-variant (if ?variants + (parse-first-function-variant ?variants) + nil) + ?args (?. first-variant :args) + ?returns (or (?. first-variant :returns) "") + docstring (.. description ?returns)] + (values name (build-lsp-value binding ?args docstring))))) -(fn love-api->root-lsp-tbl [love-api] - (let [love-doc-string (.. "LÖVE is a framework for making " - "2D games in the Lua programming language.") - love-docs (build-lsp-value :love nil love-doc-string) - love-functions (parse-doc-module-tbl love-api.functions) - love-callbacks (parse-doc-module-tbl love-api.callbacks)] - {:love (merge love-docs love-functions love-callbacks)})) +(fn module-list->fields [modules ?prefix] + "Given a list of LÖVE modules from the LÖVE-API Lua library, recursively + generate LSP data for Fennel." + (collect [_i module (ipairs modules)] + (let [{: name} module ; Other keys - :enum, :functions, :types + prefix (if ?prefix (.. ?prefix ".") "") + binding (.. prefix name) + ?docstring (?. module :description) + ?functions (?. module :functions) + ?modules (?. module :modules) + function-keys (if ?functions + (love-functions->lsp ?functions (.. binding ".")) + {}) + module-keys (if ?modules (module-list->fields ?modules binding) {}) + fields (merge function-keys module-keys)] + (values name (build-lsp-value binding nil ?docstring fields))))) + +(fn get-all-love-api-functions [love-api] + [(table.unpack love-api.functions) (table.unpack love-api.callbacks)]) + +(fn love-api->lsp [love-api] + "Given documentation for the entire LÖVE framework from the LÖVE-API Lua + library, generate the root LÖVE object suitable for the Fennel LSP." + (let [root-module {:description (.. "LÖVE is a framework for making 2D " + "games in the Lua programming language.") + :functions (get-all-love-api-functions love-api) + :modules love-api.modules + :name :love}] + (module-list->fields [root-module]))) (fn convert [] + "Convert LÖVE framework from Lua table to a configuration object + used by fennel-ls." (download-love-api-tooling!) - (let [love-api (require-love-api) - root-lsp-tbl (love-api->root-lsp-tbl love-api)] - (stringify-table root-lsp-tbl))) + (let [love-api (require-love-api)] + (fennel.view (love-api->lsp love-api)))) {: convert}