Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
api:non-standard-lua-libs [2016/06/19 08:24]
payonel [Input and Output Facilities]
api:non-standard-lua-libs [2016/06/20 20:38]
payonel [Input and Output Facilities]
Line 18: Line 18:
 Coroutine Manipulation Coroutine Manipulation
 ---------------------- ----------------------
-The [original functions](http://​www.lua.org/​manual/​5.2/​manual.html#​6.2) from the `coroutine` library are available with no observable differences.+The [original functions](http://​www.lua.org/​manual/​5.3/​manual.html#​6.2) from the `coroutine` library are available with no observable differences.
  
 Note that the `coroutine.resume` and `coroutine.yield` implementations exposed to user code are wrappers that take care of aborting code that does not yield after a certain time (see config), and to allow differentiating system yields from user yields (system yields "​bubble",​ for example this is used for the shutdown command and component API calls). This should not be noticeable from user code, however. If it is, it should be considered a bug. Note that the `coroutine.resume` and `coroutine.yield` implementations exposed to user code are wrappers that take care of aborting code that does not yield after a certain time (see config), and to allow differentiating system yields from user yields (system yields "​bubble",​ for example this is used for the shutdown command and component API calls). This should not be noticeable from user code, however. If it is, it should be considered a bug.
Line 24: Line 24:
 Modules Modules
 ------- -------
-The package module got a reimplementation for OpenComputers. It should operate the same as [the original](http://​www.lua.org/​manual/​5.2/​manual.html#​6.3),​ but is lacking the following functions:+The package module got a reimplementation for OpenComputers. It should operate the same as [the original](http://​www.lua.org/​manual/​5.3/​manual.html#​6.3),​ but is lacking the following functions:
  
 - `package.config` is missing and not used. - `package.config` is missing and not used.
Line 30: Line 30:
 - `package.loadlib` is not implemented - `package.loadlib` is not implemented
  
-The latter two are missing because it is impossible to load C code in OpenComputers +The latter two are missing because it is impossible to load C code in OpenComputers. 
-.+ 
 +`require` is a method available in the global scope, i.e. no module loading is required to have access to it, you can use it on the first line of your scripts (which is commonly the case). Its interworkings depend on the `package` library so a description of it is appropriate here. 
 + 
 +  * ''​require(library:​ string) table''​ 
 + 
 +  Returns `library` defined by name. First, if the library has been loaded previously, the `package` library will have cached it and `require` will return the cached version of the library. For unloading a precached library, see `package.loaded`. If the library is not cached, the `package.path` is searched until a match is found. 
 + 
 +  * ''​package.path''​ 
 +**It is recommended that users do not change the default package.path. Rather they should place their custom libraries in /​usr/​lib/​** 
 + 
 +  Defines a list of library search paths that `require` iterates to find libraries. It is a semi-colon delimited list of paths, using '?'​ as a placeholder for a library name passed to `require`. An example would make this much easier to explain 
 + 
 +  Default package.path 
 + 
 +  `/​lib/?​.lua;/​usr/​lib/?​.lua;/​home/​lib/?​.lua;​./?​.lua;/​lib/?/​init.lua;/​usr/​lib/?/​init.lua;/​home/​lib/?/​init.lua;​./?/​init.lua` 
 + 
 +  if the user tries to load "​foobar"​ 
 + 
 +  `local foobar = require(*foobar"​)` 
 + 
 +  Following is the order of files `require` looks for to resolve require("​foobar"​). To make it interesting,​ we are assuming the current working directory is /tmp/ 
 + 
 +    - /​lib/​foobar.lua 
 +    - /​usr/​lib/​foobar.lua 
 +    - /​home/​lib/​foobar.lua 
 +    - /​tmp/​foobar.lua 
 +    - /​lib/​foobar/​init.lua 
 +    - /​usr/​lib/​foobar/​init.lua 
 +    - /​home/​lib/​foobar/​init.lua 
 +    - /​tmp/​foobar/​init.lua 
 + 
 +  * ''​package.loaded''​ 
 +**It is nonstandard to modify `package.loaded`** 
 + 
 +  Contains the source of cached libraries in a table, keyed by the library name (as given to `require`), and whose value is the cached library itself. Setting a value to `nil` in this table essentially removes the library from the cache. Some libraries are assumed to remain loaded for the proper execution of the operating system. 
 + 
 +  * ''​delayloaded-start'',​ ''​delayloaded-end''​ 
 + 
 +  This is an advanced library loading feature built for memory optimizations in OpenOS. We don't expect users to ever need to use this feature, nor should there be a need to understand it. But it is here because it deserves some documentation. 
 + 
 +  This specially formatted comment, called a delayload annotation, guides the `package` loader to only partially store a library in memory along with sufficient metadata about which functions have not been loaded. The returned library table uses metatable redirection to lazy-load these not-yet-loaded methods, giving the user the experience that all methods are available form the start. This unusual optimization was done to reduce memory costs on boot of OpenOS. To include a method for delay loading 3 things are required: proper delayload annotation syntax, proper environment boxing, and marking `package.delayed[libname]` to true for the library before loading (i.e. before `require`). 
 + 
 +    - delayload annotation syntax 
 + 
 +  This exact text, `--[[@delayloaded-start@]]`,​ must come after `function` and before the function name. The method must be at least one generation below the library table, e.g. `lib.methodName` or `lib.a.b.methodName`,​ but not just `methodName`. 
 + 
 +  `end` must be on a new line, with no text before it, followed by this exact text `--[[@delayloaded-end@]]` followed by a newline. 
 + 
 +    - delayloaded method environments 
 + 
 +  Delay loaded methods may expect closure around local identifiers. In order to pass the local environment (and because the oc sandbox does not give sufficient debug hooks), you must return a second table from the library lua file that holds locals needed. For example, if your delay loaded method is using a local function `foobar`, you'll return a env table at the end of your library file, as a second return, of at least `{foobar=foobar}` 
 + 
 +    - ''​package.delayed''​ 
 + 
 +  `package.delayed` is a table whose keys are the library names and values of `true` to indicate to the package loader to attempt to delay load the methods. Note that failed delay load parsing falls back to a normal load of the library. 
 + 
 +```lua 
 +function --[[@delayloaded-start@]] lib.name(...) 
 +   ​body(1,​2,​3) 
 +end --[[@delayloaded-end@]] 
 + 
 +return lib, {body=body} 
 +``` 
 + 
 +```lua 
 +package.delayed["​foobar"​] = true 
 +local foobar = require("​foobar"​) 
 +``` 
 + 
 String Manipulation String Manipulation
 ------------------- -------------------
Line 66: Line 135:
   - **binary mode**   - **binary mode**
  
-  Streams given by `io.open(path,​ "​rb"​)` or `filesystem.open(path)` are in binary mode. `filesystem.open(path,​ "​rb"​)` also works, but streams returned by `filesystem.open` are **always** in binary mode. `stream:​read(1)` in binary mode reads a single byte. Reading a numerical value via `buffered_stream:​read("​*n"​)` ​considers ​the `string.char()` of each byte (buffered streams are returned from `io.open`, and support interpreting numerical values from a stream)+  Streams given by `io.open(path,​ "​rb"​)` or `filesystem.open(path)` are in binary mode. `filesystem.open(path,​ "​rb"​)` also works, but streams returned by `filesystem.open` are **always** in binary mode. `stream:​read(1)` in binary mode reads a single byte. Reading a numerical value via `buffered_stream:​read("​*n"​)` ​reads the data as single-byte characters. ​(buffered streams are returned from `io.open`, and support interpreting numerical values from a stream)
  
   - **text mode**   - **text mode**
  
-  Only streams given by `io.open` that specifically do not use "​b"​ in the mode are in text mode. Examples are `io.open(path)` and `io.open(path,​ "​r"​)`. No type of handle given by `filesystem.open` is a stream in text mode. `stream:​read(1)` in text mode reads a single unicode-aware char. This could be a single byte, or even 3 bytes - depending on the text. Reading a numerical value via `buffered_stream:​read("​*n"​)` ​considers ​the `unicode.char()` of the series of bytes (buffered streams are returned from `io.open`, and support interpreting numerical values from a stream)+  Only streams given by `io.open` that specifically do not use "​b"​ in the mode are in text mode. Examples are `io.open(path)` and `io.open(path,​ "​r"​)`. No type of handle given by `filesystem.open` is a stream in text mode. `stream:​read(1)` in text mode reads a single unicode-aware char. This could be a single byte, or even 3 bytes - depending on the text. Reading a numerical value via `buffered_stream:​read("​*n"​)` ​reads the data as unicode ​chars. (buffered streams are returned from `io.open`, and support interpreting numerical values from a stream)
  
   * `io.open(path,​ "​r"​)` is equivalent to `io.open(path)`,​ which opens a file in text read-only mode.   * `io.open(path,​ "​r"​)` is equivalent to `io.open(path)`,​ which opens a file in text read-only mode.
-  * `io.open(path,​ "​rb"​)` ​is equivalent to `io.open(path)`,​ which opens a file in binary read-only mode.+  * `io.open(path,​ "​rb"​)` opens a file in binary read-only mode.
   * `io.open(path,​ "​w"​)` truncates all contents from a file and opens it in write-mode. The binary vs text mode of the stream does not affect writes. Thus, "​w"​ is functionally equivalent to "​wb"​.   * `io.open(path,​ "​w"​)` truncates all contents from a file and opens it in write-mode. The binary vs text mode of the stream does not affect writes. Thus, "​w"​ is functionally equivalent to "​wb"​.
   * `io.open(path,​ "​a"​)` opens a file in write-mode putting the file handle position at the end of the file, meaning the next write will append to the end of the file.   * `io.open(path,​ "​a"​)` opens a file in write-mode putting the file handle position at the end of the file, meaning the next write will append to the end of the file.