X-Macro Tables
Completion, checks and highlighting for C command tables written as X-macros:
#define MACHINE_COMMANDS(ROUTINE, QUERY, COMPOSITE, PARAMETER) \
ROUTINE(HEAT, PARAMETER(float, temperature_c)) \
ROUTINE(POUR, PARAMETER(uint32_t, volume_ml)) \
QUERY(GET_STATUS, COMMAND_NO_PARAMETERS, .allow_while_busy = true) \
\
COMPOSITE(BREW, \
PARAMETER(float, water_temperature_c) PARAMETER(uint32_t, cup_ml), \
STEP(HEAT, MAP_PARAM(temperature_c, water_temperature_c)), \
STEP(POUR, MAP_PARAM(volume_ml, cup_ml)))
A table is a #define whose parameters are row kinds (ROUTINE, QUERY, COMPOSITE) and PARAMETER. A composite lists its steps after its parameters; each STEP names a command and gives its arguments with MAP_PARAM(step_parameter, composite_parameter) or SET_PARAM(step_parameter, "text").
- Completion: row kinds, parameter types and flags inside a table; inside a
STEP, the commands, the step's parameters not yet given, and for MAP_PARAM the composite's parameters of the same type.
- Checks: duplicate names, a
Raw parameter that is not last, a query without .allow_while_busy, a composite without steps, and a step that names an unknown or composite command, misses or repeats a parameter, names a parameter its command lacks, or maps a parameter of another type.
- Highlighting: fades the trailing
\ of every table line and the step boilerplate.
- Continuation: inside a table's
#define, Enter continues the line with \. Starting a row right below a table's last line gives that line its \ too, since clang-format strips it from a last line while the line below is still empty.
It reads the tables by running clang over the headers with the flags in the nearest .clangd, so it needs clang (xmacroTables.clangPath, default /usr/bin/clang).