diff --git a/README.md b/README.md index 44d5d14..92c516b 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,8 @@ This project also contains files from other projects: * [LICENSE](test/pl/LICENSE.md) * src/fennel-ls/json/* is modified, but is originally from [json.lua](https://github.com/rxi/json.lua) [MIT license] * [LICENSE](src/fennel-ls/json/LICENSE) -* src/fennel-ls/docs/* contains information from the [lua](https://lua.org) reference [MIT license] +* src/fennel-ls/docs/* is generated. It contains information from: + * the [lua](https://lua.org) reference [MIT license] + * [TIC80's webpage](https://tic80.com/learn) [MIT license] * test/faith/faith.lua is from [faith](https://git.sr.ht/~technomancy/faith) [MIT license] * fennel and src/fennel.lua are compiled from [fennel](https://git.sr.ht/~technomancy/fennel) [MIT license] diff --git a/src/fennel-ls/docs/lua51.fnl b/src/fennel-ls/docs/lua51.fnl index 254e307..3ea1e88 100644 --- a/src/fennel-ls/docs/lua51.fnl +++ b/src/fennel-ls/docs/lua51.fnl @@ -1,4 +1,4 @@ -;; auto-generated by `make docs` from fennel-ls. Contents come from 5.1 +;; auto-generated by `make docs` from fennel-ls. Contents come from https://www.lua.org/manual/5.1/manual.html ;; Lua Lua 5.1 Reference Manual last updated Thu Aug 29 20:43:58 UTC 2019 (local docs {:_G {:binding "_G" :metadata {:fnl/docstring "A global variable (not a function) that diff --git a/src/fennel-ls/docs/lua52.fnl b/src/fennel-ls/docs/lua52.fnl index 10b64aa..592be29 100644 --- a/src/fennel-ls/docs/lua52.fnl +++ b/src/fennel-ls/docs/lua52.fnl @@ -1,4 +1,4 @@ -;; auto-generated by `make docs` from fennel-ls. Contents come from 5.2 +;; auto-generated by `make docs` from fennel-ls. Contents come from https://www.lua.org/manual/5.2/manual.html ;; Lua Lua 5.2 Reference Manual last updated Thu Aug 29 20:10:02 UTC 2019 (local docs {:_G {:binding "_G" :metadata {:fnl/docstring "A global variable (not a function) that diff --git a/src/fennel-ls/docs/lua53.fnl b/src/fennel-ls/docs/lua53.fnl index db841d1..d116c77 100644 --- a/src/fennel-ls/docs/lua53.fnl +++ b/src/fennel-ls/docs/lua53.fnl @@ -1,4 +1,4 @@ -;; auto-generated by `make docs` from fennel-ls. Contents come from 5.3 +;; auto-generated by `make docs` from fennel-ls. Contents come from https://www.lua.org/manual/5.3/manual.html ;; Lua Lua 5.3 Reference Manual last updated Tue Jul 14 10:32:39 UTC 2020 (local docs {:_G {:binding "_G" :metadata {:fnl/docstring "A global variable (not a function) that diff --git a/src/fennel-ls/docs/lua54.fnl b/src/fennel-ls/docs/lua54.fnl index 01b01b8..0769d47 100644 --- a/src/fennel-ls/docs/lua54.fnl +++ b/src/fennel-ls/docs/lua54.fnl @@ -1,4 +1,4 @@ -;; auto-generated by `make docs` from fennel-ls. Contents come from 5.4 +;; auto-generated by `make docs` from fennel-ls. Contents come from https://www.lua.org/manual/5.4/manual.html ;; Lua Lua 5.4 Reference Manual last updated Tue May 2 20:09:38 UTC 2023 (local docs {:_G {:binding "_G" :metadata {:fnl/docstring "A global variable (not a function) that diff --git a/src/fennel-ls/docs/tic80.fnl b/src/fennel-ls/docs/tic80.fnl new file mode 100644 index 0000000..d9c8aa3 --- /dev/null +++ b/src/fennel-ls/docs/tic80.fnl @@ -0,0 +1,318 @@ +;; auto-generated by `make docs` from fennel-ls. Contents come from https://tic80.com/learn +{:BDR {:metadata {:fnl/arglist ["row"] + :fnl/docstring "Allows you to execute code between the drawing of each fullscreen scanline, for example, to manipulate the palette. +"}} + :BOOT {:metadata {:fnl/docstring "Startup function. +"}} + :MENU {:metadata {:fnl/arglist ["index"] + :fnl/docstring "Game Menu handler. +"}} + :SCN {:metadata {:fnl/arglist ["row"] + :fnl/docstring "Allows you to execute code between the drawing of each scanline, for example, to manipulate the palette. +"}} + :TIC {:metadata {:fnl/arglist {} + :fnl/docstring "Main function. It's called at 60fps (60 times every second). +"}} + :btn {:metadata {:fnl/arglist ["id"] + :fnl/docstring "This function allows you to read the status of one of the buttons attached to TIC. +The function returns true if the key with the supplied id is currently in the pressed state. +It remains true for as long as the key is held down. +If you want to test if a key was just pressed, use `btnp()` instead. +"}} + :btnp {:metadata {:fnl/arglist ["id" "?hold" "?period"] + :fnl/docstring "This function allows you to read the status of one of TIC's buttons. +It returns true only if the key has been pressed since the last frame. +You can also use the optional hold and period parameters which allow you to check if a button is being held down. +After the time specified by hold has elapsed, btnp will return true each time period is passed if the key is still down. +For example, to re-examine the state of button `0` after 2 seconds and continue to check its state every 1/10th of a second, you would use btnp(0, 120, 6). +Since time is expressed in ticks and TIC runs at 60 frames per second, we use the value of 120 to wait 2 seconds and 6 ticks (ie 60/10) as the interval for re-checking. +"}} + :circ {:metadata {:fnl/arglist ["x" "y" "radius" "color"] + :fnl/docstring "This function draws a filled circle of the desired radius and color with its center at x, y. +It uses the Bresenham algorithm. +"}} + :circb {:metadata {:fnl/arglist ["x" "y" "radius" "color"] + :fnl/docstring "Draws the circumference of a circle with its center at x, y using the radius and color requested. +It uses the Bresenham algorithm. +"}} + :clip {:metadata {:fnl/arglist ["x" "y" "width" "height"] + :fnl/docstring "This function limits drawing to a clipping region or `viewport` defined by x,y,w,h. +Things drawn outside of this area will not be visible. +Calling clip() with no parameters will reset the drawing area to the entire screen. +"}} + :cls {:metadata {:fnl/arglist ["?color"] + :fnl/docstring "Clear the screen. +When called this function clear all the screen using the color passed as argument. +If no parameter is passed first color (0) is used. +"}} + :elli {:metadata {:fnl/arglist ["x" "y" "a" "b" "color"] + :fnl/docstring "This function draws a filled ellipse of the desired a, b radiuses and color with its center at x, y. +It uses the Bresenham algorithm. +"}} + :ellib {:metadata {:fnl/arglist ["x" "y" "a" "b" "color"] + :fnl/docstring "This function draws an ellipse border with the desired radiuses a b and color with its center at x, y. +It uses the Bresenham algorithm. +"}} + :exit {:metadata {:fnl/arglist {} + :fnl/docstring "Interrupts program execution and returns to the console when the TIC function ends. +"}} + :fget {:metadata {:fnl/arglist ["sprite_id" "flag"] + :fnl/docstring "Returns true if the specified flag of the sprite is set. See `fset()` for more details. +"}} + :font {:metadata {:fnl/arglist ["text" + "x" + "y" + "chromakey" + "char_width" + "char_height" + "?fixed" + "?scale" + "?alt"] + :fnl/docstring "Print string with font defined in foreground sprites. +To simply print to the screen, check out `print()`. +To print to the console, check out `trace()`. +"}} + :fset {:metadata {:fnl/arglist ["sprite_id" "flag" "bool"] + :fnl/docstring "Each sprite has eight flags which can be used to store information or signal different conditions. +For example, flag 0 might be used to indicate that the sprite is invisible, flag 6 might indicate that the flag should be draw scaled etc. +See algo `fget()`. +"}} + :key {:metadata {:fnl/arglist ["?code"] + :fnl/docstring "The function returns true if the key denoted by keycode is pressed. +"}} + :keyp {:metadata {:fnl/arglist ["?code" "?hold" "?period"] + :fnl/docstring "This function returns true if the given key is pressed but wasn't pressed in the previous frame. +Refer to `btnp()` for an explanation of the optional hold and period parameters. +"}} + :line {:metadata {:fnl/arglist ["x0" "y0" "x1" "y1" "color"] + :fnl/docstring "Draws a straight line from point (x0,y0) to point (x1,y1) in the specified color. +"}} + :map {:metadata {:fnl/arglist ["?x" + "?y" + "?w" + "?h" + "?sx" + "?sy" + "?colorkey" + "?scale" + "?remap"] + :fnl/docstring "The map consists of cells of 8x8 pixels, each of which can be filled with a sprite using the map editor. +The map can be up to 240 cells wide by 136 deep. +This function will draw the desired area of the map to a specified screen position. +For example, map(5,5,12,10,0,0) will draw a 12x10 section of the map, starting from map coordinates (5,5) to screen position (0,0). +The map function's last parameter is a powerful callback function for changing how map cells (sprites) are drawn when map is called. +It can be used to rotate, flip and replace sprites while the game is running. +Unlike mset, which saves changes to the map, this special function can be used to create animated tiles or replace them completely. +Some examples include changing sprites to open doorways, hiding sprites used to spawn objects in your game and even to emit the objects themselves. +The tilemap is laid out sequentially in RAM - writing 1 to 0x08000 will cause tile(sprite) #1 to appear at top left when map() is called. +To set the tile immediately below this we need to write to 0x08000 + 240, ie 0x080F0. +"}} + :memcpy {:metadata {:fnl/arglist ["dest" "source" "size"] + :fnl/docstring "This function allows you to copy a continuous block of TIC's 96K RAM from one address to another. +Addresses are specified are in hexadecimal format, values are decimal. +"}} + :memset {:metadata {:fnl/arglist ["dest" "value" "size"] + :fnl/docstring "This function allows you to set a continuous block of any part of TIC's RAM to the same value. +The address is specified in hexadecimal format, the value in decimal. +"}} + :mget {:metadata {:fnl/arglist ["x" "y"] + :fnl/docstring "Gets the sprite id at the given x and y map coordinate. +"}} + :mouse {:metadata {:fnl/arglist {} + :fnl/docstring "This function returns the mouse coordinates and a boolean value for the state of each mouse button,with true indicating that a button is pressed. +"}} + :mset {:metadata {:fnl/arglist ["x" "y" "tile_id"] + :fnl/docstring "This function will change the tile at the specified map coordinates. +By default, changes made are only kept while the current game is running. +To make permanent changes to the map, see `sync()`. +Related: `map()` `mget()` `sync()`. +"}} + :music {:metadata {:fnl/arglist ["?track" + "?frame" + "?row" + "?loop" + "?sustain" + "?tempo" + "?speed"] + :fnl/docstring "This function starts playing a track created in the Music Editor. +Call without arguments to stop the music. +"}} + :peek {:metadata {:fnl/arglist ["addr" "?bits"] + :fnl/docstring "This function allows to read the memory from TIC. +It's useful to access resources created with the integrated tools like sprite, maps, sounds, cartridges data? +Never dream to sound a sprite? +Address are in hexadecimal format but values are decimal. +To write to a memory address, use `poke()`. +`bits` allowed to be 1,2,4,8. +"}} + :peek1 {:metadata {:fnl/arglist ["addr"] + :fnl/docstring "This function enables you to read single bit values from TIC's RAM. +The address is often specified in hexadecimal format. +"}} + :peek2 {:metadata {:fnl/arglist ["addr"] + :fnl/docstring "This function enables you to read two bits values from TIC's RAM. +The address is often specified in hexadecimal format. +"}} + :peek4 {:metadata {:fnl/arglist ["addr"] + :fnl/docstring "This function enables you to read values from TIC's RAM. +The address is often specified in hexadecimal format. +See 'poke4()' for detailed information on how nibble addressing compares with byte addressing. +"}} + :pix {:metadata {:fnl/arglist ["x" "y" "color"] + :fnl/docstring "This function can read or write pixel color values. +When called with a color parameter, the pixel at the specified coordinates is set to that color. +Calling the function without a color parameter returns the color of the pixel at the specified position. +"}} + :pmem {:metadata {:fnl/arglist ["index" "value"] + :fnl/docstring "This function allows you to save and retrieve data in one of the 256 individual 32-bit slots available in the cartridge's persistent memory. +This is useful for saving high-scores, level advancement or achievements. +The data is stored as unsigned 32-bit integers (from 0 to 4294967295). + +Tips: +- pmem depends on the cartridge hash (md5), so don't change your lua script if you want to keep the data. +- Use `saveid:` with a personalized string in the header metadata to override the default MD5 calculation. +This allows the user to update a cart without losing their saved data. +"}} + :poke {:metadata {:fnl/arglist ["addr" "value" "?bits"] + :fnl/docstring "This function allows you to write a single byte to any address in TIC's RAM. +The address should be specified in hexadecimal format, the value in decimal. +`bits` allowed to be 1,2,4,8. +"}} + :poke1 {:metadata {:fnl/arglist ["addr" "value"] + :fnl/docstring "This function allows you to write single bit values directly to RAM. +The address is often specified in hexadecimal format. +"}} + :poke2 {:metadata {:fnl/arglist ["addr" "value"] + :fnl/docstring "This function allows you to write two bits values directly to RAM. +The address is often specified in hexadecimal format. +"}} + :poke4 {:metadata {:fnl/arglist ["addr" "value"] + :fnl/docstring "This function allows you to write directly to RAM. +The address is often specified in hexadecimal format. +For both peek4 and poke4 RAM is addressed in 4 bit segments (nibbles). +Therefore, to access the the RAM at byte address 0x4000 +you would need to access both the 0x8000 and 0x8001 nibble addresses. +"}} + :print {:metadata {:fnl/arglist ["text" + "?x" + "?y" + "?color" + "?fixed" + "?scale" + "?smallfont"] + :fnl/docstring "This will simply print text to the screen using the font defined in config. +When set to true, the fixed width option ensures that each character will be printed in a `box` of the same size, so the character `i` will occupy the same width as the character `w` for example. +When fixed width is false, there will be a single space between each character. + +Tips: +- To use a custom rastered font, check out `font()`. +- To print to the console, check out `trace()`. +"}} + :rect {:metadata {:fnl/arglist ["x" "y" "w" "h" "color"] + :fnl/docstring "This function draws a filled rectangle of the desired size and color at the specified position. +If you only need to draw the the border or outline of a rectangle (ie not filled) see `rectb()`. +"}} + :rectb {:metadata {:fnl/arglist ["x" "y" "w" "h" "color"] + :fnl/docstring "This function draws a one pixel thick rectangle border at the position requested. +If you need to fill the rectangle with a color, see `rect()` instead. +"}} + :reset {:metadata {:fnl/arglist {} + :fnl/docstring "Resets the cartridge. To return to the console, see the `exit()`. +"}} + :sfx {:metadata {:fnl/arglist ["id" + "?note" + "?duration" + "?channel" + "?volume" + "?speed"] + :fnl/docstring "This function will play the sound with `id` created in the sfx editor. +Calling the function with id set to -1 will stop playing the channel. +The note can be supplied as an integer between 0 and 95 (representing 8 octaves of 12 notes each) or as a string giving the note name and octave. +For example, a note value of `14` will play the note `D` in the second octave. +The same note could be specified by the string `D-2`. +Note names consist of two characters, the note itself (in upper case) followed by `-` to represent the natural note or `#` to represent a sharp. +There is no option to indicate flat values. +The available note names are therefore: C-, C#, D-, D#, E-, F-, F#, G-, G#, A-, A#, B-. +The `octave` is specified using a single digit in the range 0 to 8. +The `duration` specifies how many ticks to play the sound for since TIC-80 runs at 60 frames per second, a value of 30 represents half a second. +A value of -1 will play the sound continuously. +The `channel` parameter indicates which of the four channels to use. Allowed values are 0 to 3. +The `volume` can be between 0 and 15. +The `speed` in the range -4 to 3 can be specified and means how many `ticks+1` to play each step, so speed==0 means 1 tick per step. +"}} + :spr {:metadata {:fnl/arglist ["id" + "x" + "y" + "?colorkey" + "?scale" + "?flip" + "?rotate" + "?w" + "?h"] + :fnl/docstring "Draws the sprite number index at the x and y coordinate. +You can specify a colorkey in the palette which will be used as the transparent color or use a value of -1 for an opaque sprite. +The sprite can be scaled up by a desired factor. For example, a scale factor of 2 means an 8x8 pixel sprite is drawn to a 16x16 area of the screen. +You can flip the sprite where: +- 0 = No Flip +- 1 = Flip horizontally +- 2 = Flip vertically +- 3 = Flip both vertically and horizontally +When you rotate the sprite, it's rotated clockwise in 90 steps: +- 0 = No rotation +- 1 = 90 rotation +- 2 = 180 rotation +- 3 = 270 rotation +You can draw a composite sprite (consisting of a rectangular region of sprites from the sprite sheet) by specifying the `w` and `h` parameters (which default to 1). +"}} + :sync {:metadata {:fnl/arglist ["?mask" "?bank" "?tocart"] + :fnl/docstring "The pro version of TIC-80 contains 8 memory banks. +To switch between these banks, sync can be used to either load contents from a memory bank to runtime, or save contents from the active runtime to a bank. +The function can only be called once per frame.If you have manipulated the runtime memory (e.g. by using mset), you can reset the active state by calling sync(0,0,false). +This resets the whole runtime memory to the contents of bank 0.Note that sync is not used to load code from banks; this is done automatically. +"}} + :time {:metadata {:fnl/arglist {} + :fnl/docstring "This function returns the number of milliseconds elapsed since the cartridge began execution. +Useful for keeping track of time, animating items and triggering events. +"}} + :trace {:metadata {:fnl/arglist ["message" "?color"] + :fnl/docstring "This is a service function, useful for debugging your code. +It prints the message parameter to the console in the (optional) color specified. + +Tips: +- The Lua concatenator for strings is .. (two points). +- Use console cls command to clear the output from trace. +"}} + :tri {:metadata {:fnl/arglist ["x1" "y1" "x2" "y2" "x3" "y3" "color"] + :fnl/docstring "This function draws a triangle filled with color, using the supplied vertices. +"}} + :trib {:metadata {:fnl/arglist ["x1" "y1" "x2" "y2" "x3" "y3" "color"] + :fnl/docstring "This function draws a triangle border with color, using the supplied vertices. +"}} + :tstamp {:metadata {:fnl/arglist {} + :fnl/docstring "This function returns the number of seconds elapsed since January 1st, 1970. +Useful for creating persistent games which evolve over time between plays. +"}} + :ttri {:metadata {:fnl/arglist ["x1" + "y1" + "x2" + "y2" + "x3" + "y3" + "u1" + "v1" + "u2" + "v2" + "u3" + "v3" + "?texsrc" + "?chromakey" + "?z1" + "?z2" + "?z3"] + :fnl/docstring "It renders a triangle filled with texture from image ram, map ram or vbank. +Use in 3D graphics. +In particular, if the vertices in the triangle have different 3D depth, you may see some distortion. +These can be thought of as the window inside image ram (sprite sheet), map ram or another vbank. +Note that the sprite sheet or map in this case is treated as a single large image, with U and V addressing its pixels directly, rather than by sprite ID. +So for example the top left corner of sprite #2 would be located at u=16, v=0. +"}}} diff --git a/tools/gen-docs.fnl b/tools/gen-docs.fnl index feb2ac9..e9ca992 100644 --- a/tools/gen-docs.fnl +++ b/tools/gen-docs.fnl @@ -22,30 +22,31 @@ (fn mkdir-p [dirname] (sh "mkdir" "-p" dirname)) -(fn open-file-cached [filename url] - (var file (io.open filename :r)) - (when (not file) - ;; I think the repos also have the html file (or the ability to generate it, depending on lua version) - ;; but for simplicity I'm just grabbing the html straight from the website - (sh "curl" url [">"] filename) - (set file (io.open filename :r))) - file) +(fn curl-cached [url] + (let [filename (.. "build/" (url:gsub "[/:]" "_")) + file (io.open filename :r)] + (if file + file + (do + (sh "curl" url [">"] filename) + (io.open filename :r))))) +(fn derive-docs-from-url [url out-filename convert] + (let [result + (convert + (with-open [file (curl-cached url)] + (file:read "*a")))] + (with-open [file (io.open (.. "src/fennel-ls/docs/" out-filename) :w)] + (file:write ";; auto-generated by `make docs` from fennel-ls. Contents come from " url "\n" + result "\n")))) (fn main [] - (mkdir-p "build") - (let [lua-manual-parser (require :tools.gen-docs.lua-manual)] - (each [_ version (ipairs [:5.1 :5.2 :5.3 :5.4])] - (let [html-filename (.. "build/lua" version ".html") - url (.. "https://www.lua.org/manual/" version "/manual.html") - infile (open-file-cached html-filename url) - contents (infile:read "*a") - _ (infile:close) - docfile (lua-manual-parser.html-to-docfile contents version) - outfilename (.. "src/fennel-ls/docs/lua" (version:gsub "%." "") ".fnl")] - (print (.. "tools/gen-docs: writing " outfilename)) - (doto (io.open outfilename "w") - (: :write docfile) - (: :close)))))) + (let [{:convert lua-manual} (require :tools.gen-docs.lua-manual) + {:convert tic-manual} (require :tools.gen-docs.tic80)] + (derive-docs-from-url "https://www.lua.org/manual/5.1/manual.html" "lua51.fnl" lua-manual) + (derive-docs-from-url "https://www.lua.org/manual/5.2/manual.html" "lua52.fnl" lua-manual) + (derive-docs-from-url "https://www.lua.org/manual/5.3/manual.html" "lua53.fnl" lua-manual) + (derive-docs-from-url "https://www.lua.org/manual/5.4/manual.html" "lua54.fnl" lua-manual) + (derive-docs-from-url "https://tic80.com/learn" "tic80.fnl" tic-manual))) (main) diff --git a/tools/gen-docs/lua-manual.fnl b/tools/gen-docs/lua-manual.fnl index 6261748..d5874b7 100644 --- a/tools/gen-docs/lua-manual.fnl +++ b/tools/gen-docs/lua-manual.fnl @@ -185,19 +185,18 @@ (tset (. module-doc :fields) k v))))) {: docs : last-update : version})) -(fn render [{: docs : last-update : version} url] +(fn render [{: docs : last-update : version}] (let [{: view : sym : list} (require :fennel)] (.. - ";; auto-generated by `make docs` from fennel-ls. Contents come from " url "\n" ";; Lua " version " last updated " last-update "\n" (view (list (sym :local) (sym :docs) docs)) "\n" "(set docs._G.fields docs)\n" "(set docs.io.fields.stdin.fields docs.io.fields)\n" "(set docs.io.fields.stdout.fields docs.io.fields)\n" "(set docs.io.fields.stderr.fields docs.io.fields)\n" - "docs\n"))) + "docs"))) -(fn html-to-docfile [input url] - (render (parse input) url)) +(fn convert [input] + (render (parse input))) -{: html-to-docfile} +{: convert} diff --git a/tools/gen-docs/tic80.fnl b/tools/gen-docs/tic80.fnl new file mode 100644 index 0000000..bc132d3 --- /dev/null +++ b/tools/gen-docs/tic80.fnl @@ -0,0 +1,33 @@ +(local fennel (require :fennel)) + +(fn remove-html-escape-codes [x] + (-> x + (: :gsub " " " ") + (: :gsub "–" "–") + (: :gsub "—" "—") + (: :gsub ">" ">") + (: :gsub "<" "<") + (: :gsub "&" "<") + (: :gsub "π" "π"))) + +(fn markdown->arglist [markdown] + (case (markdown:match "%(([^%)]*)%)") + signature + (icollect [arg (signature:gmatch "%S+")] + (case (arg:match "(.*)=") + argname (.. "?" argname) + _ arg)))) + +(fn markdown->data [html] + (let [api-markdown (html:match "## API functions.-### (.*)## Button IDs") + api-markdown (remove-html-escape-codes api-markdown)] + (collect [(name args docs) (api-markdown:gmatch + "([_%w]+)%s+`([^`]+)`%s(.-)\n### ")] + (let [arglist (markdown->arglist args)] + (values name {:metadata {:fnl/arglist arglist + :fnl/docstring docs}}))))) + +(fn convert [contents] + (fennel.view (markdown->data contents))) + +{: convert}