Expand description
Macros for egui LayoutJob and TextFormat.
Documentation below assumes egui is installed and available, as well as the following imports:
use egui_layout_job_macro::{layout_job, text_format};
use egui::text::LayoutJob;
use egui::TextFormat;§Simple
Text is passed into layout_job as literals or expressions with no commas between them. Each literal/expression must have a .to_string() method.
layout_job!("LayoutJob consisting of one segment");
let num_segments = 3;
layout_job!("LayoutJob consisting of " num_segments " segments");§From pre-existing LayoutJob
Useful if your LayoutJob requires settings or already has segments in it. Syntax for defining fields for LayoutJob directly in the macro is planned.
use egui::text::TextWrapping;
let lj = layout_job!(use LayoutJob {
wrap: TextWrapping::wrap_at_width(10.0),
..LayoutJob::default()
}: "Pre-defined LayoutJob");§Formatting
Formatting syntax was inspired by LaTeX and Typst.
In layout_job, formatting functions have a @ prefix, optionally take arguments inside square brackets [] and are applied to segments inside parentheses ().
Each function’s arguments inside [] may have their own syntax. Formatting functions can be nested.
@format(...) <- functions with no arguments
@format[...](...) <- functions with argumentsArguments accept either literals, identifiers or expressions dpeending on the function command.
For float fields, integers and floats will be automatically cast to f32, and everything else is treated as an expression and will not be cast automatically to f32. (Note that negative integers currently do not work and will be fixed in a future release)
Some fields have identifiers as possible values (e.g. colours, backgrounds). Any unrecognised identifier is assumed to be an expression.
To force an argument to be an expression, wrap it in parentheses ().
// expand_bg accepts one float
@expand_bg[2.0](...) <- OK
@expand_bg[2](...) <- OK
@expand_bg[(2.0f32)](...) <- OK
@expand_bg[float_variable](...) <- OK if variable exists
@expand_bg["hello"](...) <- NOT OK
// col (1 argument) accepts one Color32
@col[red](...) <- OK
@col[egui::Color32::RED](...) <- OK
@col[(red)](...) <- OK, variable `red` will be used
@col[magic](...) <- OK if variable `magic` does not exist, NOT OK if notTo get a TextFormat of just the formatting (no segments or text to format), use text_format and list the functions without the @ prefix and separated by commas:
let tf = text_format!(red, u[2]);§Foreground & Background Colour
The full form is
layout_job!(@color[args...](...) @background[args...](...));For pre-defined colours in egui::Color32, just write the name of the colour in the args in snake case.
layout_job!(@color[light_green]("light green text") @background[light_green]("light green background"));Pre-defined colours have a shorter form. For background colours prepend bg_:
layout_job!(@light_green("light green text") @bg_light_green("light green background"));For custom colours, you can do so using the hex value (requires egui feature color-hex), RGB or RGBA:
layout_job!(@color["90ee90"]("this is ") @color[144, 238, 144]("all ") @color[144, 238, 144, 255]("light green"));color and background have shorthands:
layout_job!(@color[red]("these all ") @colour[red]("specify ") @col[red]("colour"));
layout_job!(@background[red]("and these ") @bg[red]("specify background"));§Font ID (Family/Size)
A FontID is made of a font size (float) and a font family (see below). However, you can specify only the size and the font family.
layout_job!(@font_id[20, mono]("Monospace with size 20"));
layout_job!(@size[20]("Size 20 only"));
layout_job!(@family[mono]("Monospace only"));For font families, the three options are mono, prop and custom family (any other expressions or literals)
layout_job!(@family[mono]("Monospace") @family[prop]("Proportional") @family["custom"]("Custom font family"));mono and prop have shorthands:
layout_job!(@mono("Monospace") @prop("Proportional"));§Italics
Most basic is just italics or i:
layout_job!(@italics("italics") @i("also italics"));It accepts one optional boolean argument to toggle italics (for e.g. italics off in the middle of italicised text)
layout_job!(@i[false]("not italics"));§Underline / Strikethrough
Most basic is just underline/strikethrough or u/s, defaulting to width 1.0 and same colour as the text:
layout_job!(@underline("underline") @u("also underline"));
layout_job!(@strikethrough("strikethrough") @s("also strikethrough"));Both accept optional arguments. The first is the width of the line (float):
layout_job!(@u[2]("thick underline") @s[2]("thick strikethrough"));The second argument onwards is the colour of the line. See “Foreground & Background Colour” for the syntax.
layout_job!(@u[2, red]("red underline") @s[2, 255, 0, 0]("red strikethrough"));§Extra Letter Spacing / Expand Background
Both accept one optional float argument.
layout_job!(@extra_letter_spacing[2]("extra letter spacing") @expand_bg[2]("expand background"));§Line Height
Similar to the above, but any non-literal expression passed to it must be an Option.
layout_job!(@line_height[2]("line height 2") @line_height[None]("default line height"));§Vertical Alignment
Possible options are min, centre/center, max, top, bottom and any custom literal/expression that is an egui::Align.
A super and sub function that combines this with size is planned for the future.
layout_job!(@valign[top]("superscript") @valign[bottom]("subscript"));
layout_job!(@top("these are ") @bottom("shorthands"));§Coords
I have no clue what this does, but I have implemented a syntax anyway. The special format for arguments is key=value,… where key is a bytestring that can be specified with or without byte quotes (b""), and value is a float.
layout_job!(@coords[wght=500,b"wdth"=75]("weight=500, width=75"));§Custom TextFormat
The syntax is @[text_format_expr](...). Useful for pre-defining TextFormat combinations and using them throughout your project.
let impt = text_format!(white, bg_red, u, i);
layout_job!(@[impt]("this is very important"));§Leading Space
The default leading space before each segment is 0.0. You can specify a custom leading space with the syntax ~number before any segment.
layout_job!("This leaves" ~10 "a lot of space");Note that this cannot be done before a formatting function.
layout_job!("This should not" ~10 @red("be done"));§Custom Segment
Fundamentally, appending a segment requires 1. a segment of text, 2. a leading space, 3. a TextFormat. You can pass all 3 directly as a tuple of (text, leading space, text format) with #expression:
let segment = ("custom segment", 1.0, TextFormat::default());
layout_job!("This is a " #segment);