Agent Skill
2/7/2026

format-strings

Only read if you're struggling with debugging weird string formatting

A
all
0GitHub Stars
1Views
npx skills add All-Out-Games/infection-2

SKILL.md

Nameformat-strings
DescriptionOnly read if you're struggling with debugging weird string formatting

name: format-strings description: "Only read if you're struggling with debugging weird string formatting"

String Formatting

CSL uses format_string() for string interpolation. The first argument is a format string, and arguments are passed in an array.

Basic Usage

Use % as a placeholder for arguments:

name := "John";
str := format_string("hello: %", {name}); // "hello: John"

x := 10;
y := 20;
str := format_string("position: %, %", {x, y}); // "position: 10, 20"

Literal Percent Signs

Use %% to output a literal %:

format_string("health: 100%%"); // "health: 100%"

Arguments Next to Literal Percent

// THIS IS WRONG
hp := 67;
format_string("health: %%%", {hp}); // "health: %67"

The first two %% will insert a literal '%', and then the third % will perform an argument insertion. When you need an argument immediately followed by a literal %, use %0 for the argument. %0 is an alias for % but serves to disambiguate.

hp := 67;
format_string("health: %0%%", {hp}); // "health: 67%"

Here %0 gets replaced by the next argument, and then the %% inserts a literal '%'.

%0 is functionally equivalent to % in that it inserts the next argument, but just disambiguates when you need it as above where we want a literal percent after an argument insertion.

format_string("%0, %, %0, %,", 1, 2, 3, 4); // "1, 2, 3, 4"

Formatting Integers with Leading Zeroes

Use Format_Int to pad integers with leading zeroes:

score := 42;
format_string("Score: %", {format_int(score, leading_zeroes=5)}); // "Score: 00042"

timer_minutes := 3;
timer_seconds := 7;
format_string("%:%", {format_int(timer_minutes, leading_zeroes=2), format_int(timer_seconds, leading_zeroes=2)}); // "03:07"

The Format_Int struct has two fields:

  • v: s64 - the integer value to format
  • leading_zeroes: s64 - minimum width, padded with zeros

Formatting Floats with Decimal Precision

Use Format_Float to control decimal places and optional leading zeroes:

value := 3.14159;
format_string("pi: %", {format_float(value, decimals=2)}); // "pi: 3.14"

// Zero decimals for whole numbers
percent := 0.875;
format_string("%0%%", {format_float(percent * 100, decimals=0)}); // "88%"

// With leading zeroes (total width includes decimal point and decimal places)
time := 5.3;
format_string("%", {format_float(time, leading_zeroes=2, decimals=1)}); // "05.3"

The Format_Float struct has three fields:

  • v: f32 - the float value to format
  • leading_zeroes: s64 - minimum digits before decimal point (0 to disable)
  • decimals: s64 - number of decimal places to display

Indexed Arguments

Use %1, %2, %3, etc. as one-based indices into the parameters array to reference arguments out of order or multiple times:

format_string("%3, %2, %1", {"a", "b", "c"}); // "c, b, a"

name := "Alice";
format_string("% said hello. % is friendly.", {name, name}); // works but repetitive
format_string("%1 said hello. %1 is friendly.", {name});     // cleaner with indices

Error Handling

Too Many Arguments

If you pass more arguments than placeholders, extra arguments are appended with a warning:

format_string("%", {123, 456}); // "123 %{ADDITIONAL ARG(S): (456)}"

Too Few Arguments

If you don't pass enough arguments, unused % placeholders remain as literal % characters:

format_string("foo: %"); // "foo: %"

This behavior is intentional—it allows passing pre-formatted strings that happen to contain %:

health := "100%";
print(health); // "100%" (not an error)
Skills Info
Original Name:format-stringsAuthor:all