parse lua reference manual more accurately

the files and io are now properly treated like two different things
This commit is contained in:
XeroOl 2025-04-23 21:40:01 -05:00
parent 8a1aa53505
commit 163ea1fd80
6 changed files with 534 additions and 22 deletions

View File

@ -1546,8 +1546,121 @@ In this case, `xpcall` also returns all results from the call,
after this first result.
In case of any error,
`xpcall` returns **false** plus the result from `err`."}}})
(local file-fields {:close {:binding "file:close"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Closes `file`.
Note that files are automatically closed when
their handles are garbage collected,
but that takes an unpredictable amount of time to happen."}}
:flush {:binding "file:flush"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Saves any written data to `file`."}}
:lines {:binding "file:lines"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Returns an iterator function that,
each time it is called,
returns a new line from the file.
Therefore, the construction
```lua
for line in file:lines() do *body* end
```
will iterate over all lines of the file.
(Unlike `io.lines`, this function does not close the file
when the loop ends.)"}}
:read {:binding "file:read"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Reads the file `file`,
according to the given formats, which specify what to read.
For each format,
the function returns a string (or a number) with the characters read,
or **nil** if it cannot read data with the specified format.
When called without formats,
it uses a default format that reads the entire next line
(see below).
The available formats are
* **\"*n\":**
reads a number;
this is the only format that returns a number instead of a string.
* **\"*a\":**
reads the whole file, starting at the current position.
On end of file, it returns the empty string.
* **\"*l\":**
reads the next line (skipping the end of line),
returning **nil** on end of file.
This is the default format.
* ***number*:**
reads a string with up to this number of characters,
returning **nil** on end of file.
If number is zero,
it reads nothing and returns an empty string,
or **nil** on end of file."}}
:seek {:binding "file:seek"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "[whence]" "?offset"]
:fnl/docstring "Sets and gets the file position,
measured from the beginning of the file,
to the position given by `?offset` plus a base
specified by the string `whence`, as follows:
* **\"set\":** base is position 0 (beginning of the file);
* **\"cur\":** base is current position;
* **\"end\":** base is end of file;
In case of success, function `seek` returns the final file position,
measured in bytes from the beginning of the file.
If this function fails, it returns **nil**,
plus a string describing the error.
The default value for `whence` is `\"cur\"`,
and for `?offset` is 0.
Therefore, the call `file:seek()` returns the current
file position, without changing it;
the call `file:seek(\"set\")` sets the position to the
beginning of the file (and returns 0);
and the call `file:seek(\"end\")` sets the position to the
end of the file, and returns its size."}}
:setvbuf {:binding "file:setvbuf"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "mode" "?size"]
:fnl/docstring "Sets the buffering mode for an output file.
There are three available modes:
* **\"no\":**
no buffering; the result of any output operation appears immediately.
* **\"full\":**
full buffering; output operation is performed only
when the buffer is full (or when you explicitly `flush` the file
(see `io.flush`)).
* **\"line\":**
line buffering; output is buffered until a newline is output
or there is any input from some special files
(such as a terminal device).
For the last two cases, `?size`
specifies the size of the buffer, in bytes.
The default is an appropriate size."}}
:write {:binding "file:write"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Writes the value of each of its arguments to
the `file`.
The arguments must be strings or numbers.
To write other values,
use `tostring` or `string.format` before `write`."}}})
(set docs._G.fields docs)
(set docs.io.fields.stdin.fields docs.io.fields)
(set docs.io.fields.stdout.fields docs.io.fields)
(set docs.io.fields.stderr.fields docs.io.fields)
(set docs.io.fields.stdin.fields file-fields)
(set docs.io.fields.stdout.fields file-fields)
(set docs.io.fields.stderr.fields file-fields)
docs

View File

@ -1813,8 +1813,135 @@ and `\"userdata\"`."}}
:fnl/arglist ["f" "msgh" "?arg1" "..."]
:fnl/docstring "This function is similar to `pcall`,
except that it sets a new message handler `msgh`."}}})
(local file-fields {:close {:binding "file:close"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Closes `file`.
Note that files are automatically closed when
their handles are garbage collected,
but that takes an unpredictable amount of time to happen.
When closing a file handle created with `io.popen`,
`file:close` returns the same values
returned by `os.execute`."}}
:flush {:binding "file:flush"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Saves any written data to `file`."}}
:lines {:binding "file:lines"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Returns an iterator function that,
each time it is called,
reads the file according to the given formats.
When no format is given,
uses \"*l\" as a default.
As an example, the construction
```lua
for c in file:lines(1) do *body* end
```
will iterate over all characters of the file,
starting at the current position.
Unlike `io.lines`, this function does not close the file
when the loop ends.
In case of errors this function raises the error,
instead of returning an error code."}}
:read {:binding "file:read"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Reads the file `file`,
according to the given formats, which specify what to read.
For each format,
the function returns a string (or a number) with the characters read,
or **nil** if it cannot read data with the specified format.
When called without formats,
it uses a default format that reads the next line
(see below).
The available formats are
* **`\"*n\"`: **
reads a number;
this is the only format that returns a number instead of a string.
* **`\"*a\"`: **
reads the whole file, starting at the current position.
On end of file, it returns the empty string.
* **`\"*l\"`: **
reads the next line skipping the end of line,
returning **nil** on end of file.
This is the default format.
* **`\"*L\"`: **
reads the next line keeping the end of line (if present),
returning **nil** on end of file.
* ***number*: **
reads a string with up to this number of bytes,
returning **nil** on end of file.
If number is zero,
it reads nothing and returns an empty string,
or **nil** on end of file."}}
:seek {:binding "file:seek"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "?whence" "?offset"]
:fnl/docstring "Sets and gets the file position,
measured from the beginning of the file,
to the position given by `?offset` plus a base
specified by the string `?whence`, as follows:
* **`\"set\"`: ** base is position 0 (beginning of the file);
* **`\"cur\"`: ** base is current position;
* **`\"end\"`: ** base is end of file;
In case of success, `seek` returns the final file position,
measured in bytes from the beginning of the file.
If `seek` fails, it returns **nil**,
plus a string describing the error.
The default value for `?whence` is `\"cur\"`,
and for `?offset` is 0.
Therefore, the call `file:seek()` returns the current
file position, without changing it;
the call `file:seek(\"set\")` sets the position to the
beginning of the file (and returns 0);
and the call `file:seek(\"end\")` sets the position to the
end of the file, and returns its size."}}
:setvbuf {:binding "file:setvbuf"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "mode" "?size"]
:fnl/docstring "Sets the buffering mode for an output file.
There are three available modes:
* **`\"no\"`: **
no buffering; the result of any output operation appears immediately.
* **`\"full\"`: **
full buffering; output operation is performed only
when the buffer is full or when
you explicitly `flush` the file (see `io.flush`).
* **`\"line\"`: **
line buffering; output is buffered until a newline is output
or there is any input from some special files
(such as a terminal device).
For the last two cases, `?size`
specifies the size of the buffer, in bytes.
The default is an appropriate size."}}
:write {:binding "file:write"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Writes the value of each of its arguments to `file`.
The arguments must be strings or numbers.
In case of success, this function returns `file`.
Otherwise it returns **nil** plus a string describing the error."}}})
(set docs._G.fields docs)
(set docs.io.fields.stdin.fields docs.io.fields)
(set docs.io.fields.stdout.fields docs.io.fields)
(set docs.io.fields.stderr.fields docs.io.fields)
(set docs.io.fields.stdin.fields file-fields)
(set docs.io.fields.stdout.fields file-fields)
(set docs.io.fields.stderr.fields file-fields)
docs

View File

@ -1841,8 +1841,145 @@ negative indices count from the end of the string."}}
:fnl/arglist ["f" "msgh" "?arg1" "..."]
:fnl/docstring "This function is similar to `pcall`,
except that it sets a new message handler `msgh`."}}})
(local file-fields {:close {:binding "file:close"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Closes `file`.
Note that files are automatically closed when
their handles are garbage collected,
but that takes an unpredictable amount of time to happen.
When closing a file handle created with `io.popen`,
`file:close` returns the same values
returned by `os.execute`."}}
:flush {:binding "file:flush"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Saves any written data to `file`."}}
:lines {:binding "file:lines"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Returns an iterator function that,
each time it is called,
reads the file according to the given formats.
When no format is given,
uses `\"l\"` as a default.
As an example, the construction
```lua
for c in file:lines(1) do *body* end
```
will iterate over all characters of the file,
starting at the current position.
Unlike `io.lines`, this function does not close the file
when the loop ends.
In case of errors this function raises the error,
instead of returning an error code."}}
:read {:binding "file:read"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Reads the file `file`,
according to the given formats, which specify what to read.
For each format,
the function returns a string or a number with the characters read,
or **nil** if it cannot read data with the specified format.
(In this latter case,
the function does not read subsequent formats.)
When called without formats,
it uses a default format that reads the next line
(see below).
The available formats are
* **`\"n\"`: **
reads a numeral and returns it as a float or an integer,
following the lexical conventions of Lua.
(The numeral may have leading spaces and a sign.)
This format always reads the longest input sequence that
is a valid prefix for a numeral;
if that prefix does not form a valid numeral
(e.g., an empty string, `\"0x\"`, or `\"3.4e-\"`),
it is discarded and the function returns **nil**.
* **`\"a\"`: **
reads the whole file, starting at the current position.
On end of file, it returns the empty string.
* **`\"l\"`: **
reads the next line skipping the end of line,
returning **nil** on end of file.
This is the default format.
* **`\"L\"`: **
reads the next line keeping the end-of-line character (if present),
returning **nil** on end of file.
* ***number*: **
reads a string with up to this number of bytes,
returning **nil** on end of file.
If `number` is zero,
it reads nothing and returns an empty string,
or **nil** on end of file.
The formats `\"l\"` and `\"L\"` should be used only for text files."}}
:seek {:binding "file:seek"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "?whence" "?offset"]
:fnl/docstring "Sets and gets the file position,
measured from the beginning of the file,
to the position given by `?offset` plus a base
specified by the string `?whence`, as follows:
* **`\"set\"`: ** base is position 0 (beginning of the file);
* **`\"cur\"`: ** base is current position;
* **`\"end\"`: ** base is end of file;
In case of success, `seek` returns the final file position,
measured in bytes from the beginning of the file.
If `seek` fails, it returns **nil**,
plus a string describing the error.
The default value for `?whence` is `\"cur\"`,
and for `?offset` is 0.
Therefore, the call `file:seek()` returns the current
file position, without changing it;
the call `file:seek(\"set\")` sets the position to the
beginning of the file (and returns 0);
and the call `file:seek(\"end\")` sets the position to the
end of the file, and returns its size."}}
:setvbuf {:binding "file:setvbuf"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "mode" "?size"]
:fnl/docstring "Sets the buffering mode for an output file.
There are three available modes:
* **`\"no\"`: **
no buffering; the result of any output operation appears immediately.
* **`\"full\"`: **
full buffering; output operation is performed only
when the buffer is full or when
you explicitly `flush` the file (see `io.flush`).
* **`\"line\"`: **
line buffering; output is buffered until a newline is output
or there is any input from some special files
(such as a terminal device).
For the last two cases, `?size`
specifies the size of the buffer, in bytes.
The default is an appropriate size."}}
:write {:binding "file:write"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Writes the value of each of its arguments to `file`.
The arguments must be strings or numbers.
In case of success, this function returns `file`.
Otherwise it returns **nil** plus a string describing the error."}}})
(set docs._G.fields docs)
(set docs.io.fields.stdin.fields docs.io.fields)
(set docs.io.fields.stdout.fields docs.io.fields)
(set docs.io.fields.stderr.fields docs.io.fields)
(set docs.io.fields.stdin.fields file-fields)
(set docs.io.fields.stdout.fields file-fields)
(set docs.io.fields.stderr.fields file-fields)
docs

View File

@ -2024,8 +2024,138 @@ it ignores unknown control messages."}}
:fnl/arglist ["f" "msgh" "?arg1" "..."]
:fnl/docstring "This function is similar to `pcall`,
except that it sets a new message handler `msgh`."}}})
(local file-fields {:close {:binding "file:close"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Closes `file`.
Note that files are automatically closed when
their handles are garbage collected,
but that takes an unpredictable amount of time to happen.
When closing a file handle created with `io.popen`,
`file:close` returns the same values
returned by `os.execute`."}}
:flush {:binding "file:flush"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self"]
:fnl/docstring "Saves any written data to `file`."}}
:lines {:binding "file:lines"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Returns an iterator function that,
each time it is called,
reads the file according to the given formats.
When no format is given,
uses `\"l\"` as a default.
As an example, the construction
```lua
for c in file:lines(1) do *body* end
```
will iterate over all characters of the file,
starting at the current position.
Unlike `io.lines`, this function does not close the file
when the loop ends."}}
:read {:binding "file:read"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Reads the file `file`,
according to the given formats, which specify what to read.
For each format,
the function returns a string or a number with the characters read,
or **fail** if it cannot read data with the specified format.
(In this latter case,
the function does not read subsequent formats.)
When called without arguments,
it uses a default format that reads the next line
(see below).
The available formats are
* **`\"n\"`: **
reads a numeral and returns it as a float or an integer,
following the lexical conventions of Lua.
(The numeral may have leading whitespaces and a sign.)
This format always reads the longest input sequence that
is a valid prefix for a numeral;
if that prefix does not form a valid numeral
(e.g., an empty string, `\"0x\"`, or `\"3.4e-\"`)
or it is too long (more than 200 characters),
it is discarded and the format returns **fail**.
* **`\"a\"`: **
reads the whole file, starting at the current position.
On end of file, it returns the empty string;
this format never fails.
* **`\"l\"`: **
reads the next line skipping the end of line,
returning **fail** on end of file.
This is the default format.
* **`\"L\"`: **
reads the next line keeping the end-of-line character (if present),
returning **fail** on end of file.
* ***number*: **
reads a string with up to this number of bytes,
returning **fail** on end of file.
If `number` is zero,
it reads nothing and returns an empty string,
or **fail** on end of file.
The formats `\"l\"` and `\"L\"` should be used only for text files."}}
:seek {:binding "file:seek"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "?whence" "?offset"]
:fnl/docstring "Sets and gets the file position,
measured from the beginning of the file,
to the position given by `?offset` plus a base
specified by the string `?whence`, as follows:
* **`\"set\"`: ** base is position 0 (beginning of the file);
* **`\"cur\"`: ** base is current position;
* **`\"end\"`: ** base is end of file;
In case of success, `seek` returns the final file position,
measured in bytes from the beginning of the file.
If `seek` fails, it returns **fail**,
plus a string describing the error.
The default value for `?whence` is `\"cur\"`,
and for `?offset` is 0.
Therefore, the call `file:seek()` returns the current
file position, without changing it;
the call `file:seek(\"set\")` sets the position to the
beginning of the file (and returns 0);
and the call `file:seek(\"end\")` sets the position to the
end of the file, and returns its size."}}
:setvbuf {:binding "file:setvbuf"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "mode" "?size"]
:fnl/docstring "Sets the buffering mode for a file.
There are three available modes:
* **`\"no\"`: ** no buffering.
* **`\"full\"`: ** full buffering.
* **`\"line\"`: ** line buffering.
For the last two cases,
`?size` is a hint for the size of the buffer, in bytes.
The default is an appropriate size.
The specific behavior of each mode is non portable;
check the underlying ISO C function `setvbuf` in your platform for
more details."}}
:write {:binding "file:write"
:metadata {:fls/itemKind "Function"
:fnl/arglist ["self" "..."]
:fnl/docstring "Writes the value of each of its arguments to `file`.
The arguments must be strings or numbers.
In case of success, this function returns `file`."}}})
(set docs._G.fields docs)
(set docs.io.fields.stdin.fields docs.io.fields)
(set docs.io.fields.stdout.fields docs.io.fields)
(set docs.io.fields.stderr.fields docs.io.fields)
(set docs.io.fields.stdin.fields file-fields)
(set docs.io.fields.stdout.fields file-fields)
(set docs.io.fields.stderr.fields file-fields)
docs

View File

@ -192,24 +192,29 @@
(let [version (input:match "Lua .- Reference Manual")
(modules module-items last-update) (parse-html input)
docs (collect [_ module (ipairs modules)]
(parse-h2-section module))]
(parse-h2-section module))
file-fields {}]
(each [_ section (ipairs module-items)]
(let [(mod k v) (parse-h3-section section)]
(if (not mod)
(tset docs k v)
(not= mod "file")
(= mod "file")
(do
(table.insert v.metadata.fnl/arglist 1 "self")
(tset file-fields k v))
(let [module-doc (. docs mod)]
(assert module-doc (.. mod " not found"))
(tset (. module-doc :fields) k v)))))
{: docs : last-update : version}))
{: docs : file-fields : last-update : version}))
(fn render [{: docs : last-update : version}]
(fn render [{: docs : file-fields : last-update : version}]
(.. ";; Lua " version " last updated " last-update "\n"
(fennel.view (fennel.list (fennel.sym :local) (fennel.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"
(fennel.view (fennel.list (fennel.sym :local) (fennel.sym :docs) docs)) "\n"
(fennel.view (fennel.list (fennel.sym :local) (fennel.sym :file-fields) file-fields)) "\n"
"(set docs._G.fields docs)\n"
"(set docs.io.fields.stdin.fields file-fields)\n"
"(set docs.io.fields.stdout.fields file-fields)\n"
"(set docs.io.fields.stderr.fields file-fields)\n"
"docs"))
(fn derive-docs-for [version]

View File

@ -14,7 +14,7 @@
(string.gsub arg "'" "\\'")
"'")))
" ")]
(print (.. "running command: " command))
(io.stderr:write "running command: " command "\n")
(assert (os.execute command))))
(fn clone [location url ?tag]