If long pieces of action code are needed, such as don't easily fit into a dialog's input box, then another note can be used to store the code, which might be described as a 'code note' (though this is not a formal Tinderbox term). A new note is created and its text is used to just hold the code. This offers:
- More overall editing space for code
- Line (paragraph) breaks are ignored when code is run so each statement can be on a different line
- Setting host text note to use a monospace font (useful for string concatenation so spaces show up clearly)
- They can be re-used by numerous notes.
An important consideration with these 'code repository' notes is that generally it is not required to export such notes or have them appear in the content part of a document (e.g. in agents). If using a top-level split of content and utility notes, these code repository notes should definitely go into the utility.
Formatting tip: if using code notes, first add the built-in prototype "Code" to the TBX and then assign the prototype to your code note(s). If using several such notes, make a codes container and set the "code" prototype via its $OnAdd. The code note sets a monospace font, removes paragraph (line break) spacing, turns of auto-lists, etc. All this makes setting and testing code much easier.
The easiest way to use this code is to use a Rule or other action code to call the stored code. If stored code is in a note "code sample 1":
$Rule=$Text(code sample 1);
will call it. Note that if entering a rule via the a note's Rule input box on the create/rename dialog you must include the whole expression, typing this in the box
$Text(code sample 1); WRONG!
won't work. It is just less intuitive to do this when the output of the $Rule is the $Rule itself rather than other attributes.
Usage Tip: avoid the temptation to make the code note affect itself, e.g. set its own $Rule by copying pasting code from the note's $text into a $Rule displayed as a key attribute. Use the code note simply to store/edit the code, then use its $rule to set an attribute in a different note.
The limitation of the above is the result is to overwrite the note's own $Rule, or other action attribute, with the code from the referenced note's $Text. However, if the latter is updated, the changed code is not reflected as the note needing the code is no longer referencing it, as the $Rule now has a literal copy of the old code. The fix is to reverse the reference, so the note with the code sets the attribute of note needing to use it. If note "Complex Test" needs to use the code in $Text of "code sample 1", then in "code sample 1" this $Rule is added:
$Rule("Complex Test") = $Text
The "Complex Test" note's $Rule, if one, makes no reference to "code sample 1". Now, if the code-holding note's $Text is edited, on the next update cycle the $Rule of "Complex Test" is updated. Another variant on this is to use the same technique to set a complex conditional $Rule or $DisplayExpression for a prototype note. Editing the 'source' code will update the prototype and the new code will be inherited by all notes using that prototype.
The target of this process doesn't just have to be a rule. Other examples:
$OnAdd(some note)=$Text(code sample 2);
$AgentQuery(some agent)=$Text(code sample 3);
The eval() action can be used to further extend the complexity of what may be done. For example, assume a code note of the above type has written, into another note's $TempString, a literal string value of:
See how the attribute value, though a string, includes enclosing quotes. This means that it is possible to delay the evaluation of $MyDate. Now, in the note using the code, a single eval() call on $TempString,
eval($TempString), returns the same string in different form. Now the literal string value of the current note's $MyDate is inserted into it (this example is on a system using day/month date order) and stripped of enclosing quotes:
collect_if(all,$MyDate== '23/7/2011 10:02',$Name)
The latter is important as the value of eval($TempString) is now a string of valid action code. To actually get the result of the collect_if(), it is still necessary to evaluate that code. Thus by nesting a second eval() call, the output of the first call is evaluated afresh. Using
Note A;Note C;Note_X
which is the output of the collect_if(). As a side note, observe how in the initial string it was necessary to added enclosing single quotes around where the code reference to $MyDate occurred, ensuring the literal value, when inserted, was a properly quoted string literal. Single quotes were used as the overall initial string already used double quotes.