In code input boxes, using opt+Return will insert a line break into the code whereas Return executes the change.
The 'code note' concept
If long pieces of action code are needed, such as do not 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
- They can be re-used by numerous notes.
Use the 'code' prototype: 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.
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.
Using a code note
The best way to deploy code in the code note is to use its rule (or edict if preferred) to set the rule/OnAdd/etc of another note. Therefore a self-focussed action, i.e. rule or edict, in the note will set an action in another note, for example:
$Rule("Some note")=$Text;
Assuming the $Name "some note" is unique, this will set that's note's $Rule's code to be the current note's $Text. If the $Name is not unique, consider using the $Path:
$Rule("/Stuff/examples/Some note")=$Text;
This approach allows use of the $RuleEnabled (or $EdictEnabled) to act as a cut-off and stop propagation of code if the code in the note's $Text is being worked on, e.g. to extend or correct existing code. Once the edit is complete, re-enable and the new code will be passed to the relevant note(s). Although, it is more instinctive to use a rule in this role, unless the code will change often, an edict is a more sensible choice as it runs less often (edict execution). If using these 'enable' attributes, consider adding either/both as additional Displayed Attributes to the Code prototype.
If the reference is to more than one note, a list of offsets is possible:
$Rule("Some note;Another note")=$Text;
But, if more than two or three matches are desired, a better approach is to use a prototype name as the match. Then, all notes using the prototype are updated.
Storing stamps: if a stamp's code is long, it may be more convenient to write the code in a code note and then make the actual stamp an action() task that executes the $Text of the code note. Thus if a code note 'Test-stamp' held the action code $Colour="red";
, then a stamp with the code:
action($Text("Test-stamp"));
when run would result in the stamped note(s) turning red. The example is trivial but shows the technique. Note the offset reference in the stamp to the code note is case sensitive and should use a unique $Name (or else cite the full $Path to the code note). Local attribute references, i.e. $Color or $ChildCount, are bound to the note being stamped: it is not possible to reference values in the code note using a designator.
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 Displayed 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 context of this process does not just have to be a rule. Other examples:
$OnAdd(some note)=$Text(code sample 2);
$AgentQuery(some agent)=$Text(code sample 3);
Using eval()
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:
"collect_if(all,$MyDate== '"+$MyDate+"',$Name)"
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 eval(eval($TempString))
gives:
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.