From bd37cc09c525d4db9400e224e4ca3cadcf0eed4c Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Fri, 22 Jun 2012 20:17:55 +0400 Subject: [PATCH] Update the Lua API document with info about scripts. --- LUA_API.rst | 183 ++++++++++++++++++++++++++++++----------- Lua API.html | 172 ++++++++++++++++++++++++++------------ library/lua/dfhack.lua | 2 + 3 files changed, 256 insertions(+), 101 deletions(-) diff --git a/LUA_API.rst b/LUA_API.rst index e8c413fe7..5fc653bb3 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -4,9 +4,26 @@ DFHack Lua API .. contents:: -==================== -DF structure wrapper -==================== +The current version of DFHack has extensive support for +the Lua scripting language, providing access to: + +1. Raw data structures used by the game. +2. Many C++ functions for high-level access to these + structures, and interaction with dfhack itself. +3. Some functions exported by C++ plugins. + +Lua code can be used both for writing scripts, which +are treated by DFHack command line prompt almost as +native C++ commands, and invoked by plugins written in c++. + +This document describes native API available to Lua in detail. +For the most part it does not describe utility functions +implemented by Lua files located in hack/lua/... + + +========================= +DF data structure wrapper +========================= DF structures described by the xml files in library/xml are exported to lua code as a tree of objects and functions under the ``df`` global, @@ -479,29 +496,6 @@ Input & Output If the interactive console is not accessible, returns *nil, error*. -Miscellaneous -------------- - -* ``dfhack.run_script(name[,args...])`` - - Run a lua script in hack/scripts/, as if it was started from dfhack command-line. - The ``name`` argument should be the name stem, as would be used on the command line. - Note that the script is re-read from the file every time it is called, and errors - are propagated to the caller. - -* ``dfhack.with_suspend(f[,args...])`` - - Calls ``f`` with arguments after grabbing the DF core suspend lock. - Suspending is necessary for accessing a consistent state of DF memory. - - Returned values and errors are propagated through after releasing - the lock. It is safe to nest suspends. - - Every thread is allowed only one suspend per DF frame, so it is best - to group operations together in one big critical section. A plugin - can choose to run all lua code inside a C++-side suspend lock. - - Exception handling ------------------ @@ -531,30 +525,6 @@ Exception handling Compares to coroutine.resume like dfhack.safecall vs pcall. -* ``dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])`` - - Invokes ``fn`` with ``args``, and after it returns or throws an - error calls ``cleanup_fn`` with ``cleanup_args``. Any return values from - ``fn`` are propagated, and errors are re-thrown. - - The ``num_cleanup_args`` integer specifies the number of ``cleanup_args``, - and the ``always`` boolean specifies if cleanup should be called in any case, - or only in case of an error. - -* ``dfhack.with_finalize(cleanup_fn,fn[,args...])`` - - Calls ``fn`` with arguments, then finalizes with ``cleanup_fn``. - Implemented using ``call_with_finalizer(0,true,...)``. - -* ``dfhack.with_onerror(cleanup_fn,fn[,args...])`` - - Calls ``fn`` with arguments, then finalizes with ``cleanup_fn`` on any thrown error. - Implemented using ``call_with_finalizer(0,false,...)``. - -* ``dfhack.with_temp_object(obj,fn[,args...])`` - - Calls ``fn(obj,args...)``, then finalizes with ``obj:delete()``. - * ``dfhack.exception`` Metatable of error objects used by dfhack. The objects have the @@ -580,6 +550,46 @@ Exception handling The default value of the ``verbose`` argument of ``err:tostring()``. +Locking and finalization +------------------------ + +* ``dfhack.with_suspend(f[,args...])`` + + Calls ``f`` with arguments after grabbing the DF core suspend lock. + Suspending is necessary for accessing a consistent state of DF memory. + + Returned values and errors are propagated through after releasing + the lock. It is safe to nest suspends. + + Every thread is allowed only one suspend per DF frame, so it is best + to group operations together in one big critical section. A plugin + can choose to run all lua code inside a C++-side suspend lock. + +* ``dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])`` + + Invokes ``fn`` with ``args``, and after it returns or throws an + error calls ``cleanup_fn`` with ``cleanup_args``. Any return values from + ``fn`` are propagated, and errors are re-thrown. + + The ``num_cleanup_args`` integer specifies the number of ``cleanup_args``, + and the ``always`` boolean specifies if cleanup should be called in any case, + or only in case of an error. + +* ``dfhack.with_finalize(cleanup_fn,fn[,args...])`` + + Calls ``fn`` with arguments, then finalizes with ``cleanup_fn``. + Implemented using ``call_with_finalizer(0,true,...)``. + +* ``dfhack.with_onerror(cleanup_fn,fn[,args...])`` + + Calls ``fn`` with arguments, then finalizes with ``cleanup_fn`` on any thrown error. + Implemented using ``call_with_finalizer(0,false,...)``. + +* ``dfhack.with_temp_object(obj,fn[,args...])`` + + Calls ``fn(obj,args...)``, then finalizes with ``obj:delete()``. + + Persistent configuration storage -------------------------------- @@ -1312,6 +1322,42 @@ Features: Invokes all listeners contained in the event in an arbitrary order using ``dfhack.safecall``. + +======= +Modules +======= + +DFHack sets up the lua interpreter so that the built-in ``require`` +function can be used to load shared lua code from hack/lua/. +The ``dfhack`` namespace reference itself may be obtained via +``require('dfhack')``, although it is initially created as a +global by C++ bootstrap code. + +The following functions are provided: + +* ``mkmodule(name)`` + + Creates an environment table for the module. Intended to be used as:: + + local _ENV = mkmodule('foo') + ... + return _ENV + + If called the second time, returns the same table; thus providing reload support. + +* ``reload(name)`` + + Reloads a previously ``require``-d module *"name"* from the file. + Intended as a help for module development. + +* ``dfhack.BASE_G`` + + This variable contains the root global environment table, which is + used as a base for all module and script environments. Its contents + should be kept limited to the standard Lua library and API described + in this document. + + ======= Plugins ======= @@ -1373,3 +1419,40 @@ sort Does not export any native functions as of now. Instead, it calls lua code to perform the actual ordering of list items. + + +======= +Scripts +======= + +Any files with the .lua extension placed into hack/scripts/* +are automatically used by the DFHack core as commands. The +matching command name consists of the name of the file sans +the extension. + +**NOTE:** Scripts placed in subdirectories still can be accessed, but +do not clutter the ``ls`` command list; thus it is preferred +for obscure developer-oriented scripts and scripts used by tools. +When calling such scripts, always use '/' as the separator for +directories, e.g. ``devel/lua-example``. + +Scripts are re-read from disk every time they are used +(this may be changed later to check the file change time); however +the global variable values persist in memory between calls. +Every script gets its own separate environment for global +variables. + +Arguments are passed in to the scripts via the **...** built-in +quasi-variable; when the script is called by the DFHack core, +they are all guaranteed to be non-nil strings. + +DFHack core invokes the scripts in the *core context* (see above); +however it is possible to call them from any lua code (including +from other scripts) in any context, via the same function the core uses: + +* ``dfhack.run_script(name[,args...])`` + + Run a lua script in hack/scripts/, as if it was started from dfhack command-line. + The ``name`` argument should be the name stem, as would be used on the command line. + +Note that this function lets errors propagate to the caller. diff --git a/Lua API.html b/Lua API.html index 47cf08ab6..04e899366 100644 --- a/Lua API.html +++ b/Lua API.html @@ -320,7 +320,7 @@ ul.auto-toc {

Contents

-
-

DF structure wrapper

+

The current version of DFHack has extensive support for +the Lua scripting language, providing access to:

+
    +
  1. Raw data structures used by the game.
  2. +
  3. Many C++ functions for high-level access to these +structures, and interaction with dfhack itself.
  4. +
  5. Some functions exported by C++ plugins.
  6. +
+

Lua code can be used both for writing scripts, which +are treated by DFHack command line prompt almost as +native C++ commands, and invoked by plugins written in c++.

+

This document describes native API available to Lua in detail. +For the most part it does not describe utility functions +implemented by Lua files located in hack/lua/...

+
+

DF data structure wrapper

DF structures described by the xml files in library/xml are exported to lua code as a tree of objects and functions under the df global, which broadly maps to the df namespace in C++.

@@ -764,28 +780,8 @@ string, global environment and command-line history file.

-
-

Miscellaneous

-
    -
  • dfhack.run_script(name[,args...])

    -

    Run a lua script in hack/scripts/, as if it was started from dfhack command-line. -The name argument should be the name stem, as would be used on the command line. -Note that the script is re-read from the file every time it is called, and errors -are propagated to the caller.

    -
  • -
  • dfhack.with_suspend(f[,args...])

    -

    Calls f with arguments after grabbing the DF core suspend lock. -Suspending is necessary for accessing a consistent state of DF memory.

    -

    Returned values and errors are propagated through after releasing -the lock. It is safe to nest suspends.

    -

    Every thread is allowed only one suspend per DF frame, so it is best -to group operations together in one big critical section. A plugin -can choose to run all lua code inside a C++-side suspend lock.

    -
  • -
-
-

Exception handling

+

Exception handling

  • dfhack.error(msg[,level[,verbose]])

    Throws a dfhack exception object with location and stack trace. @@ -808,25 +804,6 @@ returning. Intended as a convenience function.

  • dfhack.saferesume(coroutine[,args...])

    Compares to coroutine.resume like dfhack.safecall vs pcall.

  • -
  • dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])

    -

    Invokes fn with args, and after it returns or throws an -error calls cleanup_fn with cleanup_args. Any return values from -fn are propagated, and errors are re-thrown.

    -

    The num_cleanup_args integer specifies the number of cleanup_args, -and the always boolean specifies if cleanup should be called in any case, -or only in case of an error.

    -
  • -
  • dfhack.with_finalize(cleanup_fn,fn[,args...])

    -

    Calls fn with arguments, then finalizes with cleanup_fn. -Implemented using call_with_finalizer(0,true,...).

    -
  • -
  • dfhack.with_onerror(cleanup_fn,fn[,args...])

    -

    Calls fn with arguments, then finalizes with cleanup_fn on any thrown error. -Implemented using call_with_finalizer(0,false,...).

    -
  • -
  • dfhack.with_temp_object(obj,fn[,args...])

    -

    Calls fn(obj,args...), then finalizes with obj:delete().

    -
  • dfhack.exception

    Metatable of error objects used by dfhack. The objects have the following properties:

    @@ -859,6 +836,39 @@ following properties:

+
+

Locking and finalization

+
    +
  • dfhack.with_suspend(f[,args...])

    +

    Calls f with arguments after grabbing the DF core suspend lock. +Suspending is necessary for accessing a consistent state of DF memory.

    +

    Returned values and errors are propagated through after releasing +the lock. It is safe to nest suspends.

    +

    Every thread is allowed only one suspend per DF frame, so it is best +to group operations together in one big critical section. A plugin +can choose to run all lua code inside a C++-side suspend lock.

    +
  • +
  • dfhack.call_with_finalizer(num_cleanup_args,always,cleanup_fn[,cleanup_args...],fn[,args...])

    +

    Invokes fn with args, and after it returns or throws an +error calls cleanup_fn with cleanup_args. Any return values from +fn are propagated, and errors are re-thrown.

    +

    The num_cleanup_args integer specifies the number of cleanup_args, +and the always boolean specifies if cleanup should be called in any case, +or only in case of an error.

    +
  • +
  • dfhack.with_finalize(cleanup_fn,fn[,args...])

    +

    Calls fn with arguments, then finalizes with cleanup_fn. +Implemented using call_with_finalizer(0,true,...).

    +
  • +
  • dfhack.with_onerror(cleanup_fn,fn[,args...])

    +

    Calls fn with arguments, then finalizes with cleanup_fn on any thrown error. +Implemented using call_with_finalizer(0,false,...).

    +
  • +
  • dfhack.with_temp_object(obj,fn[,args...])

    +

    Calls fn(obj,args...), then finalizes with obj:delete().

    +
  • +
+

Persistent configuration storage

This api is intended for storing configuration options in the world itself. @@ -1470,15 +1480,45 @@ order using dfhack.safecall.

+
+

Modules

+

DFHack sets up the lua interpreter so that the built-in require +function can be used to load shared lua code from hack/lua/. +The dfhack namespace reference itself may be obtained via +require('dfhack'), although it is initially created as a +global by C++ bootstrap code.

+

The following functions are provided:

+ +
-

Plugins

+

Plugins

DFHack plugins may export native functions and events to lua contexts. They are automatically imported by mkmodule('plugins.<name>'); this means that a lua module file is still necessary for require to read.

The following plugins have lua support.

-

burrows

+

burrows

Implements extended burrow manipulations.

Events:

    @@ -1516,11 +1556,41 @@ set is the same as used by the command line.

    The lua module file also re-exports functions from dfhack.burrows.

-

sort

+

sort

Does not export any native functions as of now. Instead, it calls lua code to perform the actual ordering of list items.

+
+

Scripts

+

Any files with the .lua extension placed into hack/scripts/* +are automatically used by the DFHack core as commands. The +matching command name consists of the name of the file sans +the extension.

+

NOTE: Scripts placed in subdirectories still can be accessed, but +do not clutter the ls command list; thus it is preferred +for obscure developer-oriented scripts and scripts used by tools. +When calling such scripts, always use '/' as the separator for +directories, e.g. devel/lua-example.

+

Scripts are re-read from disk every time they are used +(this may be changed later to check the file change time); however +the global variable values persist in memory between calls. +Every script gets its own separate environment for global +variables.

+

Arguments are passed in to the scripts via the ... built-in +quasi-variable; when the script is called by the DFHack core, +they are all guaranteed to be non-nil strings.

+

DFHack core invokes the scripts in the core context (see above); +however it is possible to call them from any lua code (including +from other scripts) in any context, via the same function the core uses:

+ +

Note that this function lets errors propagate to the caller.

+
diff --git a/library/lua/dfhack.lua b/library/lua/dfhack.lua index d200a6c5c..d56d4df60 100644 --- a/library/lua/dfhack.lua +++ b/library/lua/dfhack.lua @@ -68,6 +68,8 @@ function dfhack.with_temp_object(obj,fn,...) return dfhack.call_with_finalizer(1,true,call_delete,obj,fn,obj,...) end +dfhack.exception.__index = dfhack.exception + -- Module loading function mkmodule(module,env)