Maintenance tools
The Wesnoth source code distribution includes a couple of tools intended to help authors maintain campaigns, faction & unit packs, and other WML resources. These are:
- wmlscope
- a cross-reference lister, useful for finding unresolved macro and resource-file references.
- wmllint
- a utility for sanity-checking WML syntax and porting your old WML to the current version of WML.
- wmlindent
- a utility for reindenting WML to a uniform style.
You will need a Python interpreter on your system to use these tools. Linux, *BSD, and Mac OS/X should already have Python installed; for Windows it's a free download from http://www.python.org. You will also need to know how to run command-line tools on your system.
All three tools will require you to supply a directory list. This is a set of directories containing the WML files you want to work on.
Note to Windows Users: This means you have to run it from the Command Line. The command line may be reached by hitting Start, then Run, then "cmd" or "command" depending on your version of Windows.
Example uses:
python wmllint --oldversion=1.3.4 path\to\files python wmlindent path\to\files
Another example:
"C:\Program Files\Python2.4\python.exe" data\tools\wmllint --dryrun data\core data\{multiplayer,themes} data\campaigns
(You have to specify the full directory path to the executable if you don't have your environment variables set up correctly). The first thing you type is the path to your python executable, followed by a space. The second thing you type is the path to the desired script to run, followed by a space. The third thing you type is the path to the folder (or file) to be processed.
wmlscope
The main use for wmlscope is to find WML macro references without definitions and references to resource files (sounds and images) that don't exist. These are difficult to spot from in-game because they usually result in silence or a missing image rather than actual broken game logic. They may happen because of typos in your WML, or because the name of a macro or the location of a resource file changed between versions of the game.
wmlscope also checks macro invocations for consistency. It will complain if a macro is called with the wrong number of arguments. In most cases it can deduce information about the type of the literal expected to be passed to a given macro argument by looking at the name of the formal.
Type | Meanining | Formals requiring this type | Literals of this type |
---|---|---|---|
macro | A macro invocation | {.*} | |
numeric | a numeric literal | SIDE, X, Y, RED, GREEN, BLUE, TURN, RADIUS, *NUMBER, *AMOUNT, *COST, *_X, *_Y | \-?[0-9]+ |
position | a coordinate, coordinate range, or set of coordinate ranges | POSITION | ([0-9]+\-[0-9]+,?|[0-9]+,?)+ |
span | a coordinate, coordinate range, or set of coordinate ranges | *_SPAN | "melee" or "ranged" |
range | an attack range | RANGE | "melee" or "ranged" |
alignment | an alignment keyword | ALIGN | "lawful" or "neutral" or "chaotic" |
image | an image name | IMAGE | string ending in .png or .jpg |
terrain | a terrain code | TERRAIN | [A-Z][a-z]+\^[A-Z][a-z\\|/]+\Z |
sound | a music or sound resource | MUSIC, SOUND | \.wav|\.ogg |
affix | a prefix, suffix, or infix for a variable name | AFFIX | an ID or nothing |
image | an image name | IMAGE | string ending in .png or .jpg |
filter | filter expression | FILTER | any non-quoted string containing "=" |
WML | a WML fragment | *_WML | any non-quoted string containing "=", or the empty string |
name | a name or ID | NAME, VAR, IMAGESTEM, ID | [A-Z][a-z]+\^[A-Z][a-z\\|/]+\Z |
string | a nonempty string not matching any of the preceding types | TYPE, TEXT, *_TEXT | Anything surrounded by doublequotes, 'or anything with embedded spaces that doesn't match one of the preceding types |
optional string | a string value (may be empty) | DESCRIPTION, USER_DESCRIPTION | Anything surrounded by doublequotes, 'or anything with embedded spaces that doesn't match one of the preceding types |
value | anything | *VALUE | anything |
Any numeric or position is accepted by a span argument. Any image or name is accepted for a string argument. Any actual argument that is a macro is accepted for any formal. Otherwise, if the formal has an identifiable type, wmlscope will complain if the actual literal does not match it.
The argument type check only works in macro calls that fit on a single line.
wmlscope has many options for changing the reports it generates; the more advanced ones are intended for Wesnoth developers. Invocations for the most commonly useful reports it generates are included in data/tools/Makefile of the source distribution. Here are some of those reports:
- make unresolved
- Report on unresolved macro calls and resource references; also report macro argument-type mismatches. (This is what you are most likely to want to do).
- make all
- Report all macro and resource file references, not just unresolved ones.
- make collisions
- Report on duplicate resource files.
For more advanced users, or those who want to understand what the canned Makefile invocations are doing, here is a summary of wmlscope's options. Some of the more advanced options will require you to understand Python regular expressions.
- -h, --help
- Emit a help message and quit
- -c, --crossreference
- Report resolved macro references (implies -w 1)
- -C, --collisions
- Report duplicate resource files
- -d, --deflist
- Make definition list. (This one is for campaign server maintainers.)
- -e regexp, --exclude regexp
- Ignore files matching the specified regular expression.
- -f dir, --from dir
- Report only on macros defined under dir
- -l, --listfiles
- List files that will be processed
- -r ddd, --refcount=ddd
- Report only on macros with references in exactly ddd files.
- -u, --unresolved
- Report unresolved macro references
- -w, --warnlevel
- Set to 1 to warn of duplicate macro definitions
- --force-used reg
- Ignore reference count 0 on names matching regexp
- --extracthelp
- Extract help from macro definition comments.
wmllint
wmllint is a tool for migrating your WML to the current version. It handles two problems:
- Resource files and macro names may change between versions of the game. wmllint knows about these changes and will tweak your WML to fit where it can.
- Between 1.2.x and 1.3.1 the terrain-coding system used in map files underwent a major change. It changed again in a minor way between 1.3.1 and 1.3.2. wmllint will translate your maps for you, unless you use custom terrains in which case you will have to do it by hand.
wmllint also performs various sanity-checking operations, reporting:
- unbalanced tags
- strings that need a translation mark and do not have them
- strings that have a translation mark and should not
- translatable strings containing macro references
- filter references by description= (id= in 1.5) not matched by an actual unit
- abilities or traits without matching special notes, or vice-versa
- consistency between recruit= and recruitment_pattern= instances
- double space after punctuation in translatable strings.
- unknown races or movement types in units
wmllint takes a directory-path argument specifying the WML directories to work on. It will modify any cfg and map files under those directories that need to be changed. Here is a summary of its options:
- -h, --help
- Emit a help message and quit.
- -d, --dryrun
- List changes but don't perform them.
- -v, --verbose
- Set verbosity; more details below.
- -c, --clean
- Clean up -bak files.
- -D, --diff
- Show diffs between unconverted and unconverted files.
- -r, --revert
- Revert the conversion from the -bak files.
- -n, --nolift
- Suppress lifting, do sanity checks only
The verbosity option works like this:
- -v
- lists changes.
- -v -v
- warns of maps already converted.
- -v -v -v
- names each file before it's processed.
- -v -v -v -v
- shows verbose parse details (developers only).
The recommended procedure is this:
- Run it with --dryrun first to see what it will do.
- If the messages look good, run without --dryrun; the old content will be left in backup files with a -bak extension.
- Eyeball the changes with the --diff option.
- Use wmlscope, with a directory path including the Wesnoth mainline WML, to check that you have no unresolved references.
- Test the conversion.
- Use either --clean to remove the -bak files or --revert to undo the conversion.
Wmllint now in 1.6 has the additional feature that it tries to locate a spell checker on your system and spell-checks storyline and message strings. It will work automatically with either aspell, myspell, or ispell provided you have the enchant.py Python library installed.
wmlindent
Call with no arguments to filter WML on standard input to reindented WML on standard output. If arguments are specified, they are taken to be files to be re-indented in place; interrupting will be safe, as each reindenting will be done to a copy that is atomically renamed when it's done. This code never modifies anything but blank lines and leading and trailing whitespace on non-blank lines.
The indent unit is four spaces. Absence of an option to change this is deliberate; the purpose of this tool is to prevent style wars, not encourage them.
If you don't apply this tool to your own WML, the mainline-campaign maintainers will do it when and if your code is accepted into the tree.
Note: This tool does not include a parser. It will produce bad results on WML that is syntactically unbalanced. Unbalanced double quotes that aren't part of a multiline literal will also confuse it. You will receive warnings oiif there's an indent open at end of file or if a closer occurs with indent already zero; these two conditions strongly suggest unbalanced WML.