diff --git a/doc/html/tutorials/module.html b/doc/html/tutorials/module.html index 097ce753d..89463216a 100644 --- a/doc/html/tutorials/module.html +++ b/doc/html/tutorials/module.html @@ -234,10 +234,9 @@
A few notes on this example. BADARGS is a macro that checks the input provided to the Tcl command. The first argument BADARGS accepts is the minimum number of parameters the Tcl command must accept (including the command itself). The second argument is the maximum number of parameters that BADARGS will accept. The third argument is the help text that will be displayed if these boundaries are exceeded. For example, BADARGS(2, 4, “ name ?date? ?place?”) requires at least one argument to be passed, and a maximum of three arguments. Eggdrop code style is to enclose optional arguments between qusetion marks in the help text.
Similar to adding a partyline command, you also have to create a function table for a new Tcl command:
static tcl_cmds mytcl[] = {
{"echome", tcl_echome},
@@ -302,7 +301,7 @@ Defining bind arguments
Calling the Bind¶
-To call the bind, Eggdrop coding style it to name that function “check_tcl_bindname”. So here, whenever we reach a point in code that should trigger the bind, we’ll call check_tcl_woobie() and pass the arguments we defined- in this case, two arguments that woobie_2char was created to handle. Here is some sample code:
+To call the bind, Eggdrop coding style is to name that function “check_tcl_bindname”. So here, whenever we reach a point in code that should trigger the bind, we’ll call check_tcl_woobie() and pass the arguments we defined- in this case, two arguments that woobie_2char was created to handle. Here is some sample code:
check_tcl_woobie(chan, nick);
@@ -321,7 +320,80 @@ Calling the Bind
+Bind Configuration Settings¶
+The last argument to check_tcl_bind sets additional configurations for the bind, these are the defined values:
+
+
+Value
+Description
+
+MATCH_PARTIAL
+Check the triggering value against the beginning of the bind mask, ie DIR triggers a mask for DIRECTORY (case insensitive)
+
+MATCH_EXACT
+Check the triggering value exactly against the bind mask value (case insensitive)
+
+MATCH_CASE
+Check the triggering value exactly against the bind mask value (case sensitive)
+
+MATCH_MASK
+Check if the bind mask is contained within the triggering value, as a wildcarded value
+
+MATCH_MODE
+Check if the triggering value is contained within the bind mask, as a wildcarded value
+
+MATCH_CRON
+Check the triggering value against a bind mask formatted as a cron entry, ie “30 7 6 7 * “ triggers a mask for “30 7 * * * “
+
+BIND_USE_ATTR
+Check the flags of the user match the flags required to trigger the bind
+
+BIND_STACKABLE
+Allow multiple binds to call the same Tcl proc
+
+BIND_WANTRET
+With stacked binds, if the called Tcl proc called returns a ‘1’, halt processing any further binds triggered by the action
+
+BIND_STACKRET
+Used with BIND_WANTRET; allow stacked binds to continue despite receiving a ‘1’
+
+BIND_ALTER_ARGS
+Replaces arguments (which ones?) with the result returned from the called Tcl proc
+
+
+
+The value returned by the bind is often matched against a desired value to return a ‘1’ (often used with BIND_WANTRET and BIND_STACKRET) to the calling function.
+
+
+Bind Return Values¶
+
+
+Value
+Description
+
+BIND_NOMATCH
+The bind was not triggered due to not meeting the criteria set for the bind
+
+BIND_AMBIGUOUS
+The bind was ambiguous, similar to this explanation
+
+BIND_MATCHED
+The bind criteria was met, but the Tcl proc it tried to call could not be found
+
+BIND_EXECUTED
+The bind criteria was met and the Tcl proc was called
+
+BIND_EXEC_LOG
+The bind criteria was met, the Tcl proc was called, and Eggdrop logged the bind being called
+
+BIND_QUIT
+The bind was triggered in conjunction with the target leaving the partyline or filesys area (?)
+
+
+
+
diff --git a/doc/sphinx_source/modules/internals.rst b/doc/sphinx_source/modules/internals.rst
index 5e026a391..2d7d7c16a 100644
--- a/doc/sphinx_source/modules/internals.rst
+++ b/doc/sphinx_source/modules/internals.rst
@@ -9,10 +9,19 @@ It already exists and is suitable to illustrate the details of bind handling in
Note: All code snippets are altered for brevity and simplicity, see original source code for the full and current versions.
-Bind Table Creation
--------------------
+General Workflow To Create a New Bind
+-------------------------------------
+
+To create a new type of bind, there are generally three steps. First, you must add the new bind type to the `Bind Table`_. Once you have registered the bind type with the bind table, you must create a `C Function`_ that will be called to perform the functionality you wish to occur when the bind is triggered. Finally, once the C code supporting the new bind has been finished, the new `Tcl Binding`_ is ready to be used in a Tcl script.
+
+.. _Bind Table:
-The bind table is added by calling, either at module initialization or startup::
+Adding a New Bind Type to the Bind Table
+----------------------------------------
+
+The bind is added to the bind table is by calling, either at module initialization or startup
+
+.. code-block:: C
/* Global symbol, available to other C files with
* extern p_tcl_bind_list H_dcc;
@@ -31,40 +40,28 @@ What the :code:`C handler` does is explained later, because a lot happens before
:code:`H_dcc` can be exported from core and imported into modules as any other variable or function. That should be explained in a separate document.
+.. _HT_STACKABLE:
+
Stackable Binds: HT_STACKABLE
------------------------------
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:code:`HT_STACKABLE` means that multiple binds can exist for the same mask.
-::
+:code:`HT_STACKABLE` means that multiple binds can exist for the same mask. An example of what happens when NOT using this flag shown in the code block below.
+
+.. code-block:: Tcl
bind dcc - test proc1; # not stackable
bind dcc - test proc2; # overwrites the first one, only proc2 will be called
-It does not automatically call multiple binds that match, see later in the `Triggering any Bind`_ section for details.
-
-Tcl Binding
------------
-
-After the bind table is created with :code:`add_bind_table`, Tcl procs can already be registered to this bind by calling::
-
- bind dcc -|- test myproc
- proc myproc {args} {
- putlog "myproc was called, argument list: '[join $args ',']'"
- return 0
- }
+To enable this feature, you must set the second argument to ``add_bind_table()`` with ``HT_STACKABLE``. Using ``HT_STACKABLE`` does not automatically call all the binds that match, see the bind flags listed in `Triggering any Bind`_ section for details on the partner flags ``BIND_STACKABLE`` and ``BIND_WANTRET`` used in ``check_tcl_bind()``.
-Of course it is not clear so far:
+.. _C Function:
-* If flags :code:`-|-` matter for this bind at all and what they are checked against
-* If channel flags have a meaning or global/bot only
-* What :code:`test` is matched against to see if the bind should trigger
-* Which arguments :code:`myproc` receives, the example just accepts all arguments
+Adding Bind Functionality
+-------------------------
-Triggering the Bind
--------------------
+A C function must created that will be called when the bind is triggered. Importantly, the function is designed to accept specific arguments passed by Tcl.
-To trigger the bind and call it with the desired arguments, a function is created.
-::
+.. code-block:: C
int check_tcl_dcc(const char *cmd, int idx, const char *args) {
struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
@@ -92,10 +89,34 @@ This shows which arguments the callbacks in Tcl get:
The call to :code:`check_tcl_dcc` can be found in the DCC parsing in `src/dcc.c`.
+Using the Bind in Tcl
+---------------------
+
+After the bind table is created with :code:`add_bind_table`, Tcl procs can already be registered to this bind by calling
+
+.. code-block:: Tcl
+
+ bind dcc -|- test myproc
+ proc myproc {args} {
+ putlog "myproc was called, argument list: '[join $args ',']'"
+ return 0
+ }
+
+Of course it is not clear so far:
+
+* If flags :code:`-|-` matter for this bind at all and what they are checked against
+* If channel flags have a meaning or global/bot only
+* What :code:`test` is matched against to see if the bind should trigger
+* Which arguments :code:`myproc` receives, the example just accepts all arguments
+
+.. _triggering_any_bind:
+
Triggering any Bind
-------------------
-`check_tcl_bind` is used by all binds and does the following::
+`check_tcl_bind` is used by all binds and does the following
+
+.. code-block:: C
/* Generic function to call one/all matching binds
* @param[in] tcl_bind_list_t *tl Bind table (e.g. H_dcc)
@@ -125,15 +146,54 @@ Triggering any Bind
return x;
}
-The supplied flags to :code:`check_tcl_bind` in `check_tcl_dcc` are what defines how matching is performed.
-
-In the case of a DCC bind we had:
-
-* Matchtype :code:`MATCH_PARTIAL`: Prefix-Matching if the command can be uniquely identified (e.g. dcc .help calls .help)
-* Additional flag :code:`BIND_USE_ATTR`: Flags are checked
-* Additional flag :code:`BIND_HAS_BUILTINS`: Something with flag matching, unsure
-
-For details on the available match types (wildcard matching, exact matching, etc.) see :code:`src/tclegg.h`. Additional flags are also described there as well as the return codes of :code:`check_tcl_bind` (e.g. :code:`BIND_NOMATCH`).
+Bind Flags
+^^^^^^^^^^
+
+The last argument to :code:`check_tcl_bind` in `check_tcl_dcc` sets additional configurations for the bind. These are the allowed defined values:
+
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| **Value** | **Description** |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| MATCH_PARTIAL | Check the triggering value against the beginning of the bind mask, ie DIR triggers a mask for DIRECTORY (case insensitive) |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| MATCH_EXACT | Check the triggering value exactly against the bind mask value (case insensitive) |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| MATCH_CASE | Check the triggering value exactly against the bind mask value (case sensitive) |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| MATCH_MASK | Check if the bind mask is matched against the triggering value as a wildcarded value |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| MATCH_MODE | Check if the triggering value matches the bind mask as a wildcarded value |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| MATCH_CRON | Check the triggering value against a bind mask formatted as a cron entry, ie "30 7 6 7 5 " triggers a mask for "30 7 * * * " |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| BIND_USE_ATTR | Check the flags of the user match the flags required to trigger the bind |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| BIND_STACKABLE | Allow one mask to be re-used to call multiple Tcl proc. Must be used with HT_STACKABLE_ |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| BIND_WANTRET | With stacked binds, if the called Tcl proc called returns a '1', halt processing any further binds triggered by the action |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+| BIND_STACKRET | Used with BIND_WANTRET; allow stacked binds to continue despite receiving a '1' |
++-------------------+-------------------------------------------------------------------------------------------------------------------------------+
+
+Bind Return Values
+^^^^^^^^^^^^^^^^^^
+The value returned by the bind is often matched against a desired value to return a '1' (often used with BIND_WANTRET and BIND_STACKRET) to the calling function.
+
++----------------+--------------------------------------------------------------------------------------------------------------+
+| **Value** | **Description** |
++----------------+--------------------------------------------------------------------------------------------------------------+
+| BIND_NOMATCH | The bind was not triggered due to not meeting the criteria set for the bind |
++----------------+--------------------------------------------------------------------------------------------------------------+
+| BIND_AMBIGUOUS | The triggering action matched multiple non-stackable binds |
++----------------+--------------------------------------------------------------------------------------------------------------+
+| BIND_MATCHED | The bind criteria was met, but the Tcl proc it tried to call could not be found |
++----------------+--------------------------------------------------------------------------------------------------------------+
+| BIND_EXECUTED | The bind criteria was met and the Tcl proc was called |
++----------------+--------------------------------------------------------------------------------------------------------------+
+| BIND_EXEC_LOG | The bind criteria was met, the Tcl proc was called, and Eggdrop logged the bind being called |
++----------------+--------------------------------------------------------------------------------------------------------------+
+| BIND_QUIT | The bind was triggered in conjunction with the target leaving the partyline or filesys area (?) |
++----------------+--------------------------------------------------------------------------------------------------------------+
Note: For a bind type to be stackable it needs to be registered with :code:`HT_STACKABLE` AND :code:`check_tcl_bind` must be called with :code:`BIND_STACKABLE`.
@@ -141,7 +201,8 @@ C Binding
---------
To create a C function that is called by the bind, Eggdrop provides the :code:`add_builtins` function.
-::
+
+.. code-block:: C
/* Add a list of C function callbacks to a bind
* @param[in] tcl_bind_list_t * the bind type (e.g. H_dcc)
@@ -178,7 +239,9 @@ Now we can actually look at the C function handler for dcc as an example and wha
C Handler
---------
-The example handler for DCC looks as follows::
+The example handler for DCC looks as follows
+
+.. code-block:: C
/* Typical Tcl_Command arguments, just like e.g. tcl_putdcc is a Tcl/C command for [putdcc] */
static int builtin_dcc (ClientData cd, Tcl_Interp *irp, int argc, char *argv[]) {
@@ -209,13 +272,15 @@ The example handler for DCC looks as follows::
This is finally the part where we see the arguments a C function gets for a DCC bind as opposed to a Tcl proc.
-code:`F(dcc[idx].user, idx, argv[3])`:
+:code:`F(dcc[idx].user, idx, argv[3])`:
* User information as struct userrec *
* IDX as int
* The 3rd string argument from the Tcl call to \*dcc:cmd_boot, which was :code:`$_dcc3` which was :code:`args` to :code:`check_tcl_dcc` which was everything after the dcc command
-So this is how we register C callbacks for binds with the correct arguments::
+So this is how we register C callbacks for binds with the correct arguments
+
+.. code-block:: C
/* We know the return value is ignored because the return value of F
* in builtin_dcc is ignored, so it can be void, but for other binds
diff --git a/doc/sphinx_source/tutorials/module.rst b/doc/sphinx_source/tutorials/module.rst
index 532b70d16..42c30b76d 100644
--- a/doc/sphinx_source/tutorials/module.rst
+++ b/doc/sphinx_source/tutorials/module.rst
@@ -138,7 +138,7 @@ Eggdrop uses the Tcl C API library to interact with the Tcl interpreter. Learnin
}
}
- A few notes on this example. BADARGS is a macro that checks the input provided to the Tcl command. The first argument BADARGS accepts is the minimum number of parameters the Tcl command must accept (including the command itself). The second argument is the maximum number of parameters that BADARGS will accept. The third argument is the help text that will be displayed if these boundaries are exceeded. For example, BADARGS(2, 4, " name ?date? ?place?") requires at least one argument to be passed, and a maximum of three arguments. Eggdrop code style is to enclose optional arguments between qusetion marks in the help text.
+A few notes on this example. BADARGS is a macro that checks the input provided to the Tcl command. The first argument BADARGS accepts is the minimum number of parameters the Tcl command must accept (including the command itself). The second argument is the maximum number of parameters that BADARGS will accept. The third argument is the help text that will be displayed if these boundaries are exceeded. For example, BADARGS(2, 4, " name ?date? ?place?") requires at least one argument to be passed, and a maximum of three arguments. Eggdrop code style is to enclose optional arguments between qusetion marks in the help text.
Similar to adding a partyline command, you also have to create a function table for a new Tcl command::
@@ -208,7 +208,7 @@ Like before, BADARGS still checks that the number of arguments passed is correct
Calling the Bind
^^^^^^^^^^^^^^^^
-To call the bind, Eggdrop coding style it to name that function "check_tcl_bindname". So here, whenever we reach a point in code that should trigger the bind, we'll call check_tcl_woobie() and pass the arguments we defined- in this case, two arguments that woobie_2char was created to handle. Here is some sample code::
+To call the bind, Eggdrop coding style is to name that function "check_tcl_bindname". So here, whenever we reach a point in code that should trigger the bind, we'll call check_tcl_woobie() and pass the arguments we defined- in this case, two arguments that woobie_2char was created to handle. Here is some sample code::
check_tcl_woobie(chan, nick);
@@ -227,7 +227,7 @@ To call the bind, Eggdrop coding style it to name that function "check_tcl_bindn
return (x == BIND_EXEC_LOG);
}
-Now that we have encountered a condition that triggers the bind, we need to check it against the binds the user has loaded in scripts and see if it matches those conditions. This is done with check_tcl_bind(), called with the bind type, the userhost of the user, the flag record of the user if it exists, the bind arguments, and bind options.
+Now that we have encountered a condition that triggers the bind type (in code by calling ``check_tcl_woobie()`` ), we need to check it against the binds the user has loaded in scripts and see if it matches those conditions. This is done with ``check_tcl_bind()``, called with the bind type, the userhost of the user, the flag record of the user if it exists, the bind arguments, and bind options. We can configure how we want to check the triggering action against the bind, and we can further use the return value from ``check_tcl_bind()`` to take additional action by Eggdrop. You can read more about the specific calues used in ``check_tcl_bind`` in :ref:`triggering_any_bind`
Exporting the Bind
------------------