The ubiquitous undocumented verbatim string WML preprocessor directive

Some time ago, I rewrote most of the PreprocessorRef article in the Wesnoth.org wiki to make syntax and examples clearer, but it seems I missed something.

[lua]
code = <<
wesnoth.dofile '~add-ons/After_the_Storm/lua/common.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/npc.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/gui/bug.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/gui/character_action_dialog.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/gui/item_choice_dialog.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/gui/show_image.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/gui/transient_message.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/gui/top_message.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/wlp.lua'
wesnoth.dofile '~add-ons/After_the_Storm/lua/After_the_Storm.lua'
>>
[/lua]

The << and >> ASCII angular quotes are actually part of the general WML preprocessor syntax, not the [lua] tag in particular. They were introduced for version 1.7.0 in r34037 and r34038 as quotes denoting a verbatim (i.e. not preprocessed) string. The committer’s intention was obviously to allow for more convenient inlining of Lua code in WML document, but that is not the only possible use for this feature.

I had worked this whole time under the impression that the [lua] tag was somehow magical and special to the WML preprocessor, when in reality, it is not. The only thing that is special about it is that most people use the << foobar >> syntax in order to avoid clashes with tokens that the WML preprocessor recognizes as directives, such as curly braces {} (the file/macro substitution directive), but that is merely a convention, not a requirement — unless you do have such conflicting tokens within your string literal, of course.

Incidentally, I only figured this out when deploying a special AI engine for certain AtS E3 scenarios a few days ago:

#define AI_BOSS_TARGETING_ENGINE _TARGETS_LIST
[engine]
name="lua"
code= <<
local ai = ...
return wesnoth.require("~add-ons/After_the_Storm/ai/eng/priority_target_engine.lua").init(ai)
>>
[/engine]
[modify_ai]
side=2
action=add
path="stage[main_loop].candidate_action[]"
[candidate_action]
engine=lua
name=change_attacks_aspect
id=change_attacks_aspect
max_score=999999
evaluation="return (...):change_attacks_aspect("+{_TARGETS_LIST}+")"
execution="(...):change_attacks_aspect()"
[/candidate_action]
[/modify_ai]
#enddef

In this snippet, the _TARGET_LIST argument needs to be substituted with a valid Lua table. However, for that one would have to use curly braces like this:

{AI_BOSS_TARGETING_ENGINE {"Hero 1","Hero 2"}}

That will not work, of course, since the preprocessor will see that as an attempt to include a file or macro named "Hero 1","Hero 2". The correct syntax is:

{AI_BOSS_TARGETING_ENGINE <<{"Hero 1","Hero 2"}>>

Now I just need to get around to documenting this thing some day, and figure out how it interacts with translatable strings and textdomains.