diff --git a/Makefile b/Makefile index 280ea69..514be03 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ LUA ?= lua FENNEL=$(if $(wildcard fennel),$(LUA) fennel,fennel) EXE=fennel-ls -SRC:=$(shell find src -name "*.fnl") +SRC:=$(shell find src -name "*.fnl" | grep -v "/generated/") +TOOLS:=$(shell find tools -name "*.fnl") DESTDIR ?= PREFIX ?= /usr/local @@ -41,12 +42,18 @@ install: $(EXE) build/fennel-ls.1 docs: src/fennel-ls/docs/generated/lua51.fnl \ src/fennel-ls/docs/generated/lua52.fnl \ src/fennel-ls/docs/generated/lua53.fnl \ - src/fennel-ls/docs/generated/lua54.fnl + src/fennel-ls/docs/generated/lua54.fnl \ + src/fennel-ls/docs/generated/compiler-env.fnl -src/fennel-ls/docs/generated/%.fnl: +src/fennel-ls/docs/generated/lua%.fnl: $(TOOLS) mkdir -p build/ mkdir -p src/fennel-ls/docs/generated/ - $(FENNEL) $(FENNELFLAGS) tools/generate-lua-docs.fnl ${*} > $@ + $(FENNEL) $(FENNELFLAGS) tools/generate-lua-docs.fnl lua${*} > $@ + +src/fennel-ls/docs/generated/compiler-env.fnl: $(TOOLS) + mkdir -p build/ + mkdir -p src/fennel-ls/docs/generated/ + $(FENNEL) $(FENNELFLAGS) tools/generate-compiler-env-docs.fnl ${*} > $@ docs/lints.md: src/fennel-ls/lint.fnl $(FENNEL) $(FENNELFLAGS) tools/extract-lint-docs.fnl > $@ diff --git a/src/fennel-ls/docs/generated/compiler-env.fnl b/src/fennel-ls/docs/generated/compiler-env.fnl new file mode 100644 index 0000000..04f65fc --- /dev/null +++ b/src/fennel-ls/docs/generated/compiler-env.fnl @@ -0,0 +1,116 @@ +{:assert-compile {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["condition" + "msg" + "ast" + "?fallback-ast"] + :fnl/docstring "Assert a condition and raise a compile error with line numbers. +The ast arg should be unmodified so that its first element is the form called."}} + :ast-source {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["ast"] + :fnl/docstring "Get a table for the given ast which includes file/line info, if possible."}} + :comment {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["contents" "?source"]}} + :comment? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["x"]}} + :fennel-module-name {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist []}} + :gensym {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["base"]}} + :get-scope {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist []}} + :in-scope? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["symbol"]}} + :list {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist [...] + :fnl/docstring "Create a new list. Lists are a compile-time construct in Fennel; they are +represented as tables with a special marker metatable. They only come from +the parser, and they represent code which comes from reading a paren form; +they are specifically not cons cells."}} + :list? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["x"] + :fnl/docstring "Checks if an object is a list. Returns the object if is."}} + :macro-loaded {:fields {}} + :macroexpand {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["form"]}} + :multi-sym? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["str"] + :fnl/docstring "Returns a table containing the symbol's segments if passed a multi-sym. +A multi-sym refers to a table field reference like tbl.x or access.channel:deny. +Returns nil if passed something other than a multi-sym."}} + :pack {} + :sequence {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist [...] + :fnl/docstring "Create a new sequence. Sequences are tables that come from the parser when +it encounters a form with square brackets. They are treated as regular tables +except when certain macros need to look for binding forms, etc specifically."}} + :sequence? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["x"] + :fnl/docstring "Checks if an object is a sequence (created with a [] literal)"}} + :sym {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["str" "?source"] + :fnl/docstring "Create a new symbol. Symbols are a compile-time construct in Fennel and are +not exposed outside the compiler. Second optional argument is a table describing +where the symbol came from; should be a table with filename, line, bytestart, +and byteend fields."}} + :sym? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["x" "?name"] + :fnl/docstring "Checks if an object is a symbol. Returns the object if it is. +When given a second string argument, will check that the sym's name matches it."}} + :table? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["x"] + :fnl/docstring "Checks if an object any kind of table, EXCEPT list/symbol/varg/comment."}} + :unpack {} + :varg? {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["x"] + :fnl/docstring "Checks if an object is the varg symbol. Returns the object if is."}} + :version {:definition "1.5.3"} + :view {:metadata {:fls/fntype "fn" + :fls/itemKind "Function" + :fnl/arglist ["x" "?options"] + :fnl/docstring "Return a string representation of x. + +Can take an options table with the following keys: + +* :one-line? (default: false) keep the output string as a one-liner +* :depth (number, default: 128) limit how many levels to go (default: 128) +* :detect-cycles? (default: true) don't try to traverse a looping table +* :metamethod? (default: true) use the __fennelview metamethod if found +* :empty-as-sequence? (default: false) render empty tables as [] +* :line-length (number, default: 80) length of the line at which + multi-line output for tables is forced +* :escape-newlines? (default: false) emit strings with \\n instead of newline +* :prefer-colon? (default: false) emit strings in colon notation when possible +* :utf8? (default: true) whether to use the utf8 module to compute string lengths +* :max-sparse-gap: maximum gap to fill in with nils in sparse sequential tables +* :preprocess (function) if present, called on x (and recursively on each value + in x), and the result is used for pretty printing; takes the same arguments as + `fennel.view` +* :infinity, :negative-infinity - how to serialize infinity and negative infinity +* :nan, :negative-nan - how to serialize NaN and negative NaN values + +All options can be set to `{:once some-value}` to force their value to be +`some-value` but only for the current level. After that, the option is reset +to its default value. Alternatively, `{:once value :after other-value}` can +be used, with the difference that after the first use, the options will be set to +`other-value` instead of the default value. + +You can set a `__fennelview` metamethod on a table to override its serialization +behavior; see the API reference for details."}}} diff --git a/tools/generate-compiler-env-docs.fnl b/tools/generate-compiler-env-docs.fnl new file mode 100644 index 0000000..cbbac30 --- /dev/null +++ b/tools/generate-compiler-env-docs.fnl @@ -0,0 +1,40 @@ +(local fennel (require :fennel)) + +(local files (require :fennel-ls.files)) +(local analyzer (require :fennel-ls.analyzer)) +(local navigate (require :fennel-ls.navigate)) +(local docs (require :fennel-ls.docs)) + +(local {: create-client} (require :test.utils)) + +(local get-deps (require :tools.get-deps)) + +;; ensure fennel source is present +(get-deps.get-fennel) + +;; use fennel-ls to observe fennel/specials.fnl (make-compiler-env) +(local {: server : uri} + (create-client {:main.fnl "(local {: make-compiler-env} (require :fennel.specials)) + (make-compiler-env)" + :flsproject.fnl "{:fennel-path \"build/fennel/src/?.fnl\"}"})) + +(set server.root-uri "file://.") + +(local file (files.get-by-uri server uri)) +(local result (analyzer.search server file (. file.ast (length file.ast)) {} {})) + +;; convert results into a doc file + +(tset (getmetatable (fennel.sym "x")) :__fennelview #(fennel.view (. $ 1))) +(fn into-doc [result] + (if (= (type result.definition) :string) + {:definition result.definition} + {:metadata (navigate.getmetadata server result) + :fields (if (navigate.has-fields server result) + (collect [key field (navigate.iter-fields server result)] + key (into-doc field)))})) + +(print (fennel.view (collect [key field (navigate.iter-fields server result)] + (if (and (not (docs.get-global server nil key)) + (not (key:find "^_"))) + (values key (into-doc field)))))) diff --git a/tools/get-deps.fnl b/tools/get-deps.fnl index b5675fc..c2bd7c1 100644 --- a/tools/get-deps.fnl +++ b/tools/get-deps.fnl @@ -15,34 +15,50 @@ (local dkjson-sha1sum "19b27918b411b52b1c2b0061dd479672cb746687 build/dkjson.lua") -;; get fennel -(sh :mkdir :-p "build/") -(when (not (io.open "build/fennel/fennel")) - (git-clone "build/fennel" - "https://git.sr.ht/~technomancy/fennel" - fennel-version) - (sh :make :-C "build/fennel")) +(fn get-fennel [] + (sh :mkdir :-p "build/") + (when (not (io.open "build/fennel/fennel")) + (git-clone "build/fennel" + "https://git.sr.ht/~technomancy/fennel" + fennel-version) + (sh :make :-C "build/fennel"))) -;; get faith -(when (not (io.open "build/faith/faith.fnl")) - (git-clone "build/faith" "https://git.sr.ht/~technomancy/faith" faith-version)) +(fn get-faith [] + (when (not (io.open "build/faith/faith.fnl")) + (git-clone "build/faith" "https://git.sr.ht/~technomancy/faith" faith-version))) -;; get penlight.stringio -(when (not (io.open "build/penlight/lua/pl/stringio.lua")) - (git-clone "build/penlight" "https://github.com/lunarmodules/Penlight" penlight-version)) +;; we clone all of penlight, but only stringio.lua will be installed +(fn get-penlight-stringio [] + (when (not (io.open "build/penlight/lua/pl/stringio.lua")) + (git-clone "build/penlight" "https://github.com/lunarmodules/Penlight" penlight-version))) ;; get dkjson -(when (not (io.open "build/dkjson.lua")) - (sh :curl (.. "http://dkolf.de/dkjson-lua/dkjson-" dkjson-version ".lua") [:>] "build/dkjson.lua") - (assert (sh :echo dkjson-md5sum [:|] :md5sum "--check" "--status")) - (assert (sh :echo dkjson-sha1sum [:|] :sha1sum "--check" "--status"))) +(fn get-dkjson [] + (when (not (io.open "build/dkjson.lua")) + (sh :curl (.. "http://dkolf.de/dkjson-lua/dkjson-" dkjson-version ".lua") [:>] "build/dkjson.lua") + (assert (sh :echo dkjson-md5sum [:|] :md5sum "--check" "--status")) + (assert (sh :echo dkjson-sha1sum [:|] :sha1sum "--check" "--status")))) -;; copy to the "deps" folder -(sh :mkdir :-p "deps/") -(sh :cp "build/fennel/fennel" ".") -(sh :cp "build/fennel/fennel.lua" "deps/") -(sh :cp "build/faith/faith.fnl" "deps/") -(sh :mkdir :-p "deps/pl") -(sh :cp "build/penlight/lua/pl/stringio.lua" "deps/pl/") -(sh :cp "build/penlight/LICENSE.md" "deps/pl/") -(sh :cp "build/dkjson.lua" "deps/") +(fn install [] + ;; installing just means copying to the "deps" folder + (sh :mkdir :-p "deps/") + (sh :cp "build/fennel/fennel" ".") + (sh :cp "build/fennel/fennel.lua" "deps/") + (sh :cp "build/faith/faith.fnl" "deps/") + (sh :mkdir :-p "deps/pl") + (sh :cp "build/penlight/lua/pl/stringio.lua" "deps/pl/") + (sh :cp "build/penlight/LICENSE.md" "deps/pl/") + (sh :cp "build/dkjson.lua" "deps/")) + +(when (not ...) + (get-fennel) + (get-faith) + (get-penlight-stringio) + (get-dkjson) + (install)) + +{: get-fennel + : get-faith + : get-penlight-stringio + : get-dkjson + : install}