Introducing
Numbers
Real numbers are a sequence of decimal digits containing a decimal point
RealValue
=
3.14;
3.14
Rational numbers
Ratios of integers can be created using the
over
operator.
OneThird
=
1
over
3;
FractionSum
=
OneThird
+
5
over
6;
1
1
6
Complex Numbers
Complex numbers are also supported, and real and imaginary parts are automatically aggregated
Complex1
=
3i
+
2i
+
5
+
3;
8
+
5
i
Strings
A
string
is an array of characters enclosed in quotation marks ("...") in source code.
SimpleString
=
"This is an array of characters"
;
This is an array of characters
String slices
All array operations work on strings, in the same way
SimpleString
=
"This is an array of characters"
;
StringSlice
=
SimpleString
[10
..
15];
StringNew
=
SimpleString
.
Insert(5
..
11,
"really "
);
This is an array of characters
array
This really is an array of characters
String Arguments
Strings can contain numbered sections that allow for substitutions supplied by arguments to the
string.
S1
Message
=
"There is an error in \"
{0}
\""
;
There is an error in "
{0}
"
String Argument Call
Message is not a string, but is instead a function taking 1 argument.
FileError
=
Message
(
"file.txt"
);
There is an error in "file.txt"
Unit Conversions
You can convert between compatible units using the
tounit
operator.
MetricDistance
=
Distance
tounit
centimeters
;
40.64Â centimeters
Compound unit conversions
The power of water flowing over Niagra falls
WaterFlow
=
1
mile
^
3
per
year
;
// from the book "Energy" by Richard Rhodes
FallsHeight
=
170
feet
;
g
=
9.8
meters
per
second
^
2;
Power
=
(
WaterFlow
*
WaterDensity
*
FallsHeight
*
g
)
tounit
megawatts
;
67Â megawatts
Array
An array is an ordered container of objects
[0, 1, 2, 3,
x
,
y
, A, B, C,
Ï€
2
,
i
]
Slices
An arbirtary slice of a array can be obtained by putting an array of ranges inside square brackets
[]
[0, 1, 3,
y
, A,
i
]
Ranges
A range is an ordered, inclusive pair of values using the
..
operator.
SmallRange
=
1
..
5;
1
..
5
Range arrays
An array can be created with a range using the
step
operator.
[1, 3, 5, 7, 9, 10]
Charts
The data used for a chart can come from an equation represented by a function
Quadratic
(
x
)
=
x
^
2
-
50;
ParabolaChart
=
VBox
{
Paragraph
{
TextEquation
:
true
;
Symbol
(
"y"
)
Tex
.
Equals
Quadratic
(
Symbol
(
"x"
));
};
HAlign
:
Center
;
Chart
(90%, 2") {
ChartType
:
ChartTypes
.
Line
;
Marker
:
Markers
.
Square
;
XAxis
:
ChartAxis
{
Start
:
-
15;
Stop
:
15};
ChartSeries
{
foreach
(
var
x
in
-
10
..
10)
new
DataPoint
(
x
,
Quadratic
(
x
)) {
Reference
:
x
};
};
};
};
y
 =Â
x
2
 −Â
50
-15
-13
-11
-9
-7
-5
-3
-1
0
2
4
6
8
10
12
14
-50
-30
-10
10
30
50
Tables
A table can be created from a fixed set of values using the
Table
formatter.
RainfallTable
=
Table
(
new
Edge
(1, 0,
Colors
.
LightGray
),
PadLR
(3), [0.8", 1", 1"]) {
TextDigits
:
1;
TextHeight
:
9pt;
NytrilStyle
.
HeaderRow
{
Cell
(
null
, 3) {
ParAlignment
:
Center
;
"Rainfall"
};
};
Row
{
Background
:
Colors
.
DarkGray
;
TextColor
:
Colors
.
White
;
"Month"
;
"Value"
;
"Error"
};
RainRow
(
each
Rainfall
)
};
Rainfall
Month
Value
Error
January
12.0Â inches
-1.0 +1.0
February
13.2Â inches
-1.0 +1.0
March
14.6Â inches
-1.0 +1.2
April
18.5Â inches
-1.0 +1.0
May
12.6Â inches
-0.6 +0.4
June
7.2Â inches
-1.0 +1.0
July
4.0Â inches
-1.0 +1.0
August
4.7Â inches
-0.4 +1.2
September
5.0Â inches
-1.0 +1.0
October
6.0Â inches
-1.0 +1.0
November
12.6Â inches
-1.0 +1.0
December
15.1Â inches
-1.0 +1.0
Trees
A tree is a structure comprising nested nodes, each one having its own branch length.
MyTree
=
new
Node
(
"Root"
, 0.5) {
new
Node
(
"A"
, 1) {
new
Node
(
"A1"
, 0.3);
new
Node
(
"A2"
, 0.4);
};
new
Node
(
"B"
, 2);
new
Node
(
"C"
, 1);
};
ShowTree
=
TreeBox
(3",
null
) {
Default
:
new
Node
(
null
) {
Curvature
:
50%;
Bevel
:
50%;
Marker
:
Markers
.
Circle
(
Colors
.
Red
);
};
Root
:
MyTree
;
};
Root
A
A1
A2
B
C
Revisions
Revisions are used to alter the typesetting of any Span or Paragraph.
FormatPar
=
Span
{
TextFamily
:
TextFamilies
.
TimesNewRoman
;
"The following text is: "
;
}
;
ShowRevision
=
Block
{
FormatPar
{
Span
{
TextHeight
:
120%;
"Large"
}};
FormatPar
{
Span
{
Bold
;
"Bold"
}};
FormatPar
{
Span
{
Italic
;
"Italic"
}};
FormatPar
{
Span
{
TextHeight
:
120%;
Bold
;
Italic
;
"Large, Bold, Italic"
}};
};
The following text is:
Large
The following text is:
Bold
The following text is:
Italic
The following text is:
Large, Bold, Italic
Text Color
If you want to change color of the text in a Span, use the
TextColor
property.
ShowTextColor
=
Paragraph
{
"The following item is "
;
Span
{
TextColor
:
Colors
.
Red
;
"important"
;
};
" to note. "
;
};
The following item is
important
to note.
Text Background
The background color of text can be set with the
TextBackground
property.
ShowTextBackground
=
Paragraph
{
"The following item is "
;
Span
{
TextBackground
:
Colors
.
Yellow
;
"marked"
;
};
" with a highlighter. "
;
};
The following item is
marked
with a highlighter.
Italic Text
Make the font italic by setting the
TextItalic
property to true.
ShowItalic
=
Paragraph
{
"Make "
;
Span
{
TextItalic
:
true
;
"sure"
;
};
" to read the instructions. "
;
};
Make
sure
to read the instructions.
Italic shortcut
Apply the special Italic revision directly to a string for a more concise expression.
ShowItalic2
=
Paragraph
{
"Make "
;
Italic
"sure"
;
" to read the instructions. "
;
};
Make
sure
to read the instructions.
Bold Text
Make the font bold by setting the
TextWeight
property to Bold.
ShowBold
=
Paragraph
{
"Use "
;
Span
{
TextWeight
:
Bold
;
"extreme"
;
};
" caution. "
;
};
Use
extreme
caution.
Bold shortcut
Apply the special Bold revision directly to a string for a more concise expression.
ShowBold2
=
Paragraph
{
"Use "
;
Bold
"extreme"
;
" caution. "
;
};
Use
extreme
caution.
Font Face
Use the
TextFace
property to change the font face to one of the built-in styles.
ShowFace
=
Block
{
"Normal Text"
;
Span
{
TextFace
:
TextFaces
.
Mono
;
"Monospaced Text"
;
};
};
Normal Text
Monospaced Text
Font Family
Use the
TextFamily
property to change the font family to a specific installed family.
ShowFamily
=
Paragraph
{
TextFamily
:
TextFamilies
.
LibertinusSerif
;
"Classic font for journal articles"
;
};
Classic font for journal articles
Underlining Text
Use the
TextUnderline
property to underline text in a variety of styles.
ShowUnderline
=
Paragraph
{
Separator
:
Space
*
3;
foreach
(
var
u
in
TextUnderlines
) {
Span
{
TextUnderline
:
u
;
u
.
Name
;
};
}
};
None
Single
Words
Dotted
Dashed
DotDash
DotDotDash
Thick
Double
Wave
WavyDouble
Striking-out Text
Use the
TextStrike
property to strike-out sections of text.
StrikeText
=
Paragraph
{
Separator
:
Space
*
3;
foreach
(
var
s
in
TextStrikes
) {
Span
{
TextStrike
:
s
;
s
.
Name
;
};
}
};
None
Single
Double
Text Casing
You can control the mixture of uppercase and lowercase letters with the
TextCase
property.
ShowTextCase
=
Table
(
null
,
PadLR
(3), [
Column
.
Fit
(50%)]) {
foreach
(
var
tc
in
TextCases
) {
Row
{
tc
.
Name
;
Span
{
TextCase
:
tc
;
"hello Hello HELLO!"
;
};
};
}
};
None
hello Hello HELLO!
AllUpper
HELLO HELLO HELLO!
AllLower
hello hello hello!
WordUpper
Hello Hello Hello!
FirstUpper
Hello Hello HELLO!
FirstLower
hello Hello HELLO!
SmallCaps
hello Hello HELLO!
Letter Spacing
Change how much space is allocated between letters with the
TextLetterSpace
property.
ShowTextLetterSpace
=
Block
{
foreach
(
var
space
in
1
..
5) {
Paragraph
(
null
, [5%]) {
space
;
Tab
;
Span
{
TextLetterSpace
:
space
;
"The quick brown fox"
;
};
Span
{
TextColor
:
Colors
.
Green
;
" jumped over the lazy dog."
};
};
}
};
1
The quick brown fox
jumped over the lazy dog.
2
The quick brown fox
jumped over the lazy dog.
3
The quick brown fox
jumped over the lazy dog.
4
The quick brown fox
jumped over the lazy dog.
5
The quick brown fox
jumped over the lazy dog.
Letter Stretching
Text can be compressed or stretched with the
TextStretch
property.
ShowLetterScale
=
Block
{
foreach
(
var
stretch
in
[50%, 75%, 100%, 150%, 200%]) {
Paragraph
(
null
, [8%]) {
stretch
;
Tab
;
Span
{
TextStretch
:
stretch
;
"Stretch"
;
};
Span
{
TextColor
:
Colors
.
Green
;
" -> goal."
};
}
}
};
50%
Stretch
-> goal.
75%
Stretch
-> goal.
100%
Stretch
-> goal.
150%
Stretch
-> goal.
200%
Stretch
-> goal.
Separators
Insert content between elements with the
Separator
property.
ShowSeparator
=
Paragraph
{
Separator
:
", "
;
1
..
5
step
1;
};
1, 2, 3, 4, 5
Last Separator
Change the final separator in the revision with the
LastSeparator
property.
ShowLastSeparator
=
Paragraph
{
Separator
:
", "
;
LastSeparator
:
" and "
;
1
..
5
step
1;
};
1, 2, 3, 4 and 5
Pair Separator
To handle lists that have exactly two items, use the
PairSeparator
property.
OxfordList
=
Span
{
Separator
:
", "
;
LastSeparator
:
", and "
;
// Oxford comma
PairSeparator
:
" and "
;
};
ShowLists
=
Block
{
OxfordList
{1};
OxfordList
{1; 2};
OxfordList
{1; 2; 3};
};
1
1 and 2
1, 2, and 3
int Literals
To show an integer, simply include the literal number as one of the elements inside a span.
IntegerLiteral
=
Span
{
42
;
};
42
Functions and Variables with int Values
Functions that return integers or variables containing integers, like the function X shown here, will
be formatted the same way.
X
(
i
)
=
i
*
i
+
3;
IntegerVariable
=
Span
{
"The output of X(5) is "
;
X
(5);
};
The output of X(5) is 28
Hexadecimal Format
To format an integer in hexadecimal, change the
TextRadix
to 16.
IntegerHexadecimal
=
Span
{
TextRadix
:
16
;
129579;
};
1fa2b
Uppercase Hex Format
To have the hex digits shown in upper-case, change the
TextCase
property to AllUpper.
IntegerHexadecimalUpper
=
Span
{
TextRadix
:
16;
TextCase
:
AllUpper
;
671277;
};
A3E2D
Binary Format
To format a number in binary, use 2 as the
TextRadix
.
IntegerBinary
=
Span
{
TextRadix
:
2
;
127;
};
1111111
Number Zero-Padding
Use the
TextNumPadding
property to set the minimum width of a number. This is handy for text
sorting and creating tables with aligned numbers.
IntegerHexadecimal4
=
Block
{
TextRadix
:
16;
TextNumPadding
:
4
;
4;
27;
12245;
};
0004
001b
2fd5
Group Separators
To format an integer with a group separator, set the
TextGroup
property to true.
IntegerGroup
=
Span
{
TextGroup
:
true
;
1234567.89;
};
1,234,567.89
Culture Settings
Use the
TextCulture
property to ensure the formatting is correct for the intended readership.
IntegerGroupCulture
=
Span
{
TextCulture
:
CultureInfo
.
FindCulture
(
"de-DE"
);
TextGroup
:
true
;
8912345.67;
};
8.912.345,67
double Literals
As with integers, to a format a number of type
double
, include it as an element in the revision.
DoubleFormatting
=
Span
{
4325.1245
;
};
4325.1245
Function Return Values
Formatting a return value from a function works the same way.
DoubleReturn
=
Span
{
Math
.
Sqrt
(1
+
1)
;
};
1.4142135623730951
Decimal Digits
Use the
TextDigits
property to fix the number of fractional digits in the number.
DoubleDigits
=
Span
{
TextDigits
:
3
;
Math
.
PI
;
};
3.142
Percentage Format
Set the
TextPercent
property to true to show numbers as percentages.
Percentage
=
Block
{
TextPercent
:
true
;
0.04;
1.5;
};
4%
150%
Significant Figures
Set
TextSignificant
to true, to make TextDigits refer to 'significant' figures, rather than decimal
digits.
SignificantDigits
=
Block
{
TextSignificant
:
true
;
TextDigits
:
3
;
// 3 significant figures
4325.1245;
5.4193;
0.0006427;
1.215e10;
1.2e-10;
};
4330
5.42
0.000643
12200000000
0.000000000120
Scientific Notation
Format the number in scientific notation by setting
TextScientific
to true.
ScientificNotation
=
Span
{
TextScientific
:
true
;
TextDigits
:
2;
175_000;
};
1.75x10
5
Significant Figures in Scientific Notation
Notice that the
TextSignificant
property controls the total number of significant figures with
scientific notation.
ScientificNotationSig
=
Span
{
TextScientific
:
true
;
TextSignificant
:
true
;
TextDigits
:
2
;
8_175_400;
};
8.2x10
6
Decimal Tab Stops
You can use a custom tab stop in a paragraph to align numbers on decimal point.
readonly
AlignedPar
=
Paragraph
(
null
, [
new
(5%,
Decimal
)]);
AlignedPars
=
Block
{
AlignedPar
{
Tab
; 1.2 };
AlignedPar
{
Tab
; 123.99};
AlignedPar
{
Tab
; 0.5544};
};
1.2
123.99
0.5544
Fractional Expressions
Use the
TextDenominator
property to convert a number to a fraction, with a maximum
denominator, in lowest terms.
Denominator
=
Block
{
TextDenominator
:
16
;
0.125;
0.5;
12.75;
1.04125;
};
1
8
1
2
12
3
4
1
1
16
Symbols
Use the
Symbol
function to create objects that behave like algebraic symbols. The second
argument is the tip that pops up when the mouse is hovered over the symbol.
x
=
Symbol
(
"x"
,
"The independent variable 'x'"
);
y
=
Symbol
(
"y"
,
"The independent variable 'y'"
);
RaisePower
(
a
,
b
)
=
Span
{
a
;
" raised to the power of "
;
b
;
" is "
;
a
^
b
;
};
Powers
=
Block
{
RaisePower
(2, 5);
// Perform calculation with numbers
RaisePower
(
x
,
y
);
// Create formula
};
2 raised to the power of 5 is 32
x
raised to the power of
y
is
x
y
The independent variable 'y'
Fractions
Create several different types of common fractions with the
Fraction
formatter.
FormatFraction
=
Fraction
{
x
;
y
+
1;
};
x
y
 +Â
1
Slanted Fractions
Format the fraction with a diagonal slash by setting the diagonal argument to true.
SlantedFraction
=
Fraction
(
true
) {
x
;
y
^
2;
};
x
y
2
Compact Fractions
Create a more compact fraction layout by setting the compact argument to true.
ThreeQuarters
=
Fraction
(
false
,
true
) {3; 4};
CompactFraction
=
Span
{
"Add "
;
ThreeQuarters
;
" of a cup of flour. "
;
};
Add
3
4
of a cup of flour.
Compact Fraction Shortcut
For numeric fractions, get a more concise expression by using a rational number.
OneHalf
=
1
over
2;
CompactShortcut
=
Span
{
"Add "
;
OneHalf
;
" teaspoon of sugar and stir. "
;
};
Add
1
2
teaspoon of sugar and stir.
TextDiagonal Property
Change the default rational number display to a diagonal bar by settting the
TextDiagonal
property to true.
CompactSlanted
=
Span
{
TextDiagonal
:
true
;
"Mix in "
;
4
over
3;
" tablespoons of warm water if the dough is too firm. "
;
};
Mix in
1
1
3
tablespoons of warm water if the dough is too firm.
Subscripts
Add a subscript to a symbol by using the
sub
operator.
X1
=
x
sub
1;
x
1
Superscripts
Use the
sup
operator in the same way to make superscripts.
E
=
Symbol
(
"E"
,
"Energy"
);
m
=
Symbol
(
"m"
,
"Mass"
);
c
=
Symbol
(
"c"
,
"The speed of light"
);
MassEnergy
=
Span
{
E
;
Tex
.
Equals
;
m
;
c
sup
2};
E
 =Â
m
c
2
The speed of light
Radicals
Square-root symbols can be created with the
Radical
formatter.
Solution
=
Paragraph
{
"The solution is: "
;
Tex
.
pm
;
Radical
{
x
;
Tex
.
Plus
;
2;
};
};
The solution is:
 ±Â
x
 +Â
2
Radical degree
Change the degree of the radical by setting the
Degree
property
V
=
Symbol
(
"V"
,
"Volume"
);
Cube
=
Paragraph
{
"The edge of a cube of volume "
;
V
;
" is given by "
;
Radical
{
V
;
Degree
:
3
;
};
};
The edge of a cube of volume
V
is given by
V
3
Nary formatter
The
Nary
is the most complex formatter covering a wide variety of math expressions.
NaryComponents
=
Nary
{
Operator
:
"Operator"
;
PreUpper
:
"pre-upper"
;
PreLower
:
"pre-lower"
;
Upper
:
"upper"
;
Lower
:
"lower"
;
"[Body Elements]"
;
};
[Body Elements]
Operator
pre-upper
pre-lower
upper
lower
Nary Operator property
Set the
Operator
property to one of the built-in symbols appropriate for your expression.
s
=
Symbol
(
"s"
,
"Zeta argument (complex number)"
);
n
=
Symbol
(
"n"
,
"Integer"
);
ZetaSum
=
Nary
{
Operator
:
Tex
.
sum
;
TextStacked
:
true
;
Fraction
{1;
n
^
s
};
};
1
n
s
Nary Upper Property
Use the
Upper
and
Lower
properties to set the superscript and subscript of the Operator.
InverseSquareIntegral
=
Paragraph
{
TextEquation
:
true
;
Symbol
(
"f"
);
"("
;
x
;
")"
;
Tex
.
Equals
;
Nary
{
Operator
:
Tex
.
Integral1
;
Upper
:
Tex
.
infty
;
Lower
:
x
Tex
.
Equals
1
;
};
Fraction
{
1;
x
^
2;
};
Tex
.
nbsp
;
Tex
.
derivative
;
x
;
};
f
(
x
)
 =Â
∞
x
 =Â
1
1
x
2
Â
d
x
TextStacked property
Place the superscripts and subscripts above and below the Operator by setting the
TextStacked
property to true.
StackedNary
=
InverseSquareIntegral
{
TextStacked
:
true
;
};
f
(
x
)
 =Â
∞
x
 =Â
1
1
x
2
Â
d
x
Nary PreUpper and PreLower
Use
PreUpper
and
PreLower
to specify the operator prefixes.
Isotope
(
weight
,
element
,
name
)
=
Nary
{
PreUpper
:
weight
;
PreLower
:
element
;
Operator
:
HBox
{
Margin
:
PadL
(0.1%);
TextHeight
:
150%;
name
};
};
Thorium232
=
Isotope
(232, 90,
"Th"
);
Th
232
90
Nary Elements
The child elements of an Nary formatter are shown to the right of the Operator.
p
=
Symbol
(
"p"
,
"Prime number"
);
ZetaProduct
=
Nary
{
TextStacked
:
true
;
Operator
:
Tex
.
prod
;
Fraction
{
p
^
s
;
p
^
s
-
1;
};
};
p
s
p
s
 −Â
1
TextEquation property
If you set the
TextEquation
property to true, the math font is used for all of the symbols, and the
expression will stay together across line breaks.
LineEquation
=
Paragraph
{
TextEquation
:
true
;
TextStacked
:
true
;
};
ZetaEquivalence
=
LineEquation
{
Tex
.
zeta
;
"("
;
s
;
")"
;
Tex
.
Equals
;
ZetaSum
;
Tex
.
Equals
;
ZetaProduct
;
};
ζ
(
s
)
 =Â
1
n
s
 =Â
p
s
p
s
 −Â
1
Polynomial Equations
Here is an example of a loop inside a revision, to generate a combination of polynomial terms.
Polynomial
(
int
degree
)
=
LineEquation
{
for
(
var
i
=
degree
;
i
>=
0;
--
i
)
{
Symbol
(
'a'
+
(
degree
-
i
));
if
(
i
>
0) {
x
^
i
;
Tex
.
Plus
;
}
}
};
FifthDegree
=
Polynomial
(5);
a
x
5
 +Â
b
x
4
 +Â
c
x
3
 +Â
d
x
2
 +Â
e
x
 +Â
f
Bracket Property
Use the
Bracket
property to wrap an expression in scaled brackets.
Term
(
index
)
=
Fraction
{
x
^
index
;
index
;
Tex
.
factorial
};
Series
=
HBox
{
Bracket
:
Brackets
.
Round
;
Separator
:
Tex
.
Plus
;
LastSeparator
:
Tex
.
Plus
Tex
.
cdots
Tex
.
Plus
;
1;
Term
(
each
[1, 2, 3,
n
]);
// A term for each item in the array
};
EulerNumber
=
LineEquation
{
Symbolic
.
E
^
x
;
Tex
.
Equals
;
Nary
{
Operator
:
Tex
.
lim
;
Lower
:
n
Tex
.
rightarrow
Tex
.
infty
;
};
Series
;
};
e
x
 =Â
lim
n
 → ∞
1
 +Â
x
1
!
 +Â
x
2
2
!
 +Â
x
3
3
!
 +Â
⋯
 +Â
x
n
n
!
Bracket Styles
Choose from a wide variety of arrow and bracket styles.
VerticalBrackets
=
HBox
{
Separation
:
20;
VBox
{
Bracket
:
Brackets
.
RightArrow
.
Over
;
"Over"
};
VBox
{
Bracket
:
Brackets
.
RightArrow
.
Under
;
"Under"
};
VBox
{
Bracket
:
Brackets
.
Bar
.
Top
;
"bar above"
};
VBox
{
Bracket
:
Brackets
.
FlatCurly
.
Bottom
;
"flat curly below"
};
VBox
{
Bracket
:
Brackets
.
Round
.
Top
;
"round above"
};
};
Over
Under
bar above
flat curly below
round above
Large expressions in Brackets
Enclose large expressions in horizontal or vertical brackets.
BracketEnclosure
=
HBox
{
Bracket
:
Brackets
.
FlatRound
.
TopBottom
;
Separation
:
24pt;
VAlign
:
Center
;
HBox
{
Bracket
:
Brackets
.
Round
;
"parenthesis"
};
HBox
{
Bracket
:
Brackets
.
Square
;
"square brackets"
};
VBox
{
Bracket
:
Brackets
.
FlatCurly
.
Left
;
"Topic
{0}
"
(
each
1
..
3);
};
};
(
parenthesis
)
[
square brackets
]
Topic 1
Topic 2
Topic 3
All Bracket Types
Here is a complete list of the bracket types.
TestAllBrackets
=
Paragraph
{
Separator
:
Space
*
4;
foreach
(
var
b
in
attribute
Brackets
) {
HBox
{
Bracket
:
new
BracketGroup
(
b
.
Value,
null
,
b
.
Value,
null
);
VBox
{
Bracket
:
new
BracketGroup
(
null
,
b
.
Value,
null
,
b
.
Value);
NytrilStyle
.
PropName
(
b
);
};
};
}
};
None
Angle
Bar
Curly
FlatCurly
CurvedAngle
Round
FlatRound
Square
Tortoise
DoubleAngle
DoubleBar
DoubleRound
DoubleSquare
DoubleTortoise
RightArrow
LeftArrow
RightHarp
LeftHarp
Directional Bracket Placement
Use the directional member of a bracket to place arrows in specific locations.
Decay
(
type
)
=
VBox
(
null
,
null
,
PadLR
(6pt)) {
Bracket
:
Brackets
.
RightArrow
.
Under
;
Margin
:
PadLR
(4pt);
VAlignment
:
Top
;
HAlign
:
Center
;
Span
{
Space
*
2;
type
;
Space
*
2};
};
ThoriumDecay
=
HBox
{
VAlign
:
Center
;
Thorium232
;
Decay
(
Tex
.
alpha
);
Isotope
(228, 88,
"Ra"
);
Decay
(
Tex
.
beta
sup
Tex
.
Minus
);
Isotope
(228, 89,
"Ac"
);
};
Th
232
90
α
Ra
228
88
β
−
Ac
228
89
Matrices
Matrices are created with the
MatrixBox
formatter. They contain a list of rows and cells
automatically sized to fit the contents.
PlainMatrix
=
MatrixBox
{
VAlign
:
Center
;
HAlign
:
Center
;
ColumnGap
:
6pt;
Row
{1;
Fraction
{
Tex
.
pi
; 2}; 3};
Row
{4; 1;
Symbolic
.
Sqrt
(
x
+
2)};
Row
{
y
+
5; 8; 1}
};
WithBraces
=
HBox
{
Separation
:
16pt;
PlainMatrix
;
PlainMatrix
{
Bracket
:
Brackets
.
FlatRound
};
PlainMatrix
{
Bracket
:
Brackets
.
Square
};
};
1
Ï€
2
3
4
1
x
 +Â
2
y
 +Â
5
8
1
1
Ï€
2
3
4
1
x
 +Â
2
y
 +Â
5
8
1
1
Ï€
2
3
4
1
x
 +Â
2
y
 +Â
5
8
1
Blocks
Let's review some basics. A
Block
contains Paragraph or Table elements. If those elements are not
already Paragraphs, they will be automatically placed inside a Paragraph. A Block can have
formatting properties, which will serve as the default properties of the child elements.
SimpleBlock
=
Block
{
// Explicit paragraph
Paragraph
{
"Paragraph One"
;
};
// Non-paragraph elements turned into a paragraphs
"Paragraph Two"
;
Span
{
Bold
;
Math
.
Sqrt
(2)
+
1};
};
Paragraph One
Paragraph Two
2.414213562373095
Nested Blocks
A Block can be included inside another Block, but this does not create a nested structure. Instead,
the parent Block will simply include the child Block's formatted content.
NestedBlock
=
Block
{
TextColor
:
Colors
.
Red
;
Block
{
"Line 1"
;
};
"Line 2"
;
Block
{
TextColor
:
Colors
.
Blue
;
"Line 3"
;
};
};
Line 1
Line 2
Line 3
Default block format
Overridden format
Paragraphs
A
Paragraph
is a formatter that puts its child elements end-to-end into horizontal lines. The text
will wrap at the edge of the available space, and may continue onto the next page of the
document.
Success
=
Paragraph
{
"I've missed more than 9000 shots in my career. "
;
"I've lost almost 300 games. "
;
"26 times I've been trusted "
;
"to take the game winning shot and missed. "
;
"I've failed over and over and over again in my life. "
;
"And that is why I succeed. "
;
"–Michael Jordan"
;
};
I've missed more than 9000 shots in my career. I've lost almost 300 games. 26 times I've
been trusted to take the game winning shot and missed. I've failed over and over and
over again in my life. And that is why I succeed. –Michael Jordan
Indenting
Use the
LeftIndent
,
RightIndent
, and
FirstIndent
properties to control the margins of the
paragraph. Notice that you may revise an existing paragraph with new properties, without
changing the original.
Greatness
=
Paragraph
{
"Be not afraid of greatness. "
;
"Some are born great, "
;
"some achieve greatness, "
;
"and others have greatness thrust upon them. "
;
};
Quote
=
Block
{
Greatness
{
RightIndent
:
10pt;
LeftIndent
:
16pt;
FirstIndent
:
-
8pt
;
// Relative to LeftIndent
TextHeight
:
120%;
};
Italic
"― William Shakespeare, Twelfth Night"
;
};
Be not afraid of greatness. Some are born great, some
achieve greatness, and others have greatness thrust upon
them.
― William Shakespeare, Twelfth Night
Alignment
Alignment of the text can be controlled with the
ParAlignment
property.
SmallBlock
=
Block
{
Paragraph
{
ParAlignment
:
Left
;
"Left"
};
Paragraph
{
ParAlignment
:
Center
;
"Center"
};
Paragraph
{
ParAlignment
:
Right
;
"Right"
};
};
Left
Center
Right
Justify Alignment
The Justify alignment stretches the spaces in the line so that it fits evenly on the right.
JustifiedBlock
=
Paragraph
{
ParAlignment
:
Justify
;
"As the light changed from red to green to yellow and back to red again, "
;
"I sat there thinking about life. "
;
"Was it nothing more than a bunch of honking and yelling? "
;
"Sometimes it seemed that way. "
;
Tex
.
EmDash
;
" Jack Handey"
;
};
As the light changed from red to green to yellow and back to
red again, I sat there thinking about life. Was it nothing more
than a bunch of honking and yelling? Sometimes it seemed
that way. — Jack Handey
Tab stops
The tabstops argument is an array of TabStop objects that determine how the tab character is
interpreted inside a paragraph.
TabStop
[]
TabList
=
[
5%,
// Left align (default)
new
(20%,
TabTypes
.
Bar
),
// Place vertical bar (no stop)
new
(30%,
TabTypes
.
Center
),
// Center text around tab
new
(60%,
TabTypes
.
Decimal
),
// Line up decimal point at tab
new
(95%,
TabTypes
.
Right
,
TabLeaders
.
Dot
),
// Right align at tab
];
TabStopExample
=
Block
{
Paragraph
(
null
,
TabList
) {
Tab
;
"Left"
;
Tab
;
"Center"
;
Tab
;
"3.1415"
;
Tab
;
"Right"
;
};
Paragraph
(
null
,
TabList
) {
Tab
;
"Left Align"
;
Tab
;
"Center Align"
;
Tab
;
"527.10"
;
Tab
;
"Right Align"
;
};
};
Left
Center
3.1415
.....................................................
Right
Left Align
Center Align
527.10
.................................................
Right Align
Frames
A
Frame
is a rectangular box that can contain Paragraphs and Tables, but it acts like a large
character when placed inside a Paragraph.
FrameExample
=
Paragraph
{
"Quote "
;
// Acts like a big single character
Frame
(30%,
null
,
new
Edge
(1, 4pt)) {
"Luck is what happens when preparation meets opportunity."
;
"—Seneca "
;
};
" of the day. "
;
};
Quote
Luck is what happens when
preparation meets opportunity.
—Seneca
of the day.
Large 'character' in the text
Inline lists
A
ListSpan
formatter can be used to create a numbered list inside a paragraph with a variety of
numbering styles. Notice that the "Topics" array variable is automatically expanded inside the
revision to become a part of the numbered list.
Topics
=
[
"Point one"
,
"Point two"
,
"Point three"
];
NumberedSpan
=
Paragraph
{
"Main discussion points: "
;
ListSpan
(
@
Enumerators
.
NumberParens
) {
Separator
:
"; "
;
End
:
DotSpace
;
Topics
;
};
};
Main discussion points:
(1)
 Point one;
(2)
 Point two;
(3)
 Point three.
Background Color
Paragraphs have an optional background color which can be set with the
ParBackground
property.
HeaderPar
=
Paragraph
{
ParBackground
:
Colors
.
Blue
;
TextColor
:
Colors
.
White
;
ParAlignment
:
Center
;
Bold
;
"Header"
;
};
Header
Space Before
Add extra space before the start of a paragraph using the
SpaceBefore
property.
ParSpaceBefore
=
Block
{
Bold
"Header"
;
Paragraph
{
"First line"
;
SpaceBefore
:
200%
;
};
};
Header
First line
Space before the paragraph
Space After
Add extra space after the end of a paragraph using the
SpaceAfter
property.
ParSpaceAfter
=
Block
{
Paragraph
{
SpaceAfter
:
200%
;
TextHeight
:
120%;
Bold
;
"Title"
;
};
"Body text"
;
};
Title
Body text
Space after the paragraph
Borders
Set the border argument for a Paragraph to display a border on any combination of sides.
BorderPar
(
Border
border
)
=
Paragraph
(
border
) {
ParAlignment
:
Center
;
ParBackground
:
95%;
};
BorderExamples
=
Block
{
Separator
:
Paragraph
;
BorderPar
(4pt) {
"all sides"
};
BorderPar
(
BorderTB
(4pt)) {
"top - bottom"
};
BorderPar
(
BorderLR
(4pt)) {
"left - right"
};
};
all sides
top - bottom
left - right
Border color and padding
Paragraph borders can also have different colors and padding
ColorBorder
=
Paragraph
(
new
Edge
(3pt, 5pt,
Colors
.
Red
)) {
ParAlignment
:
Center
;
ParBackground
:
#FCFCF4#
;
LeftIndent
:
16pt;
RightIndent
:
15pt;
Bold
;
"Very Important Notice"
;
};
Very Important Notice
Line Height
Change the default line height using the
LineHeight
property.
LegalText
=
Block
{
LineHeight
:
200%
;
TextFace
:
Mono
;
Paragraph
{
Bold
;
TextCase
:
AllUpper
;
Underline
;
"Memorandum of Points"
;
};
"Statement of Relevant Facts"
;
};
MEMORANDUM OF POINTS
Statement of Relevant Facts
Double-spaced lines
Create Named Styles
Use global variables to create styles with familiar names. You can even use a named style to serve
as the root template for another style, as show below.
Normal
=
Paragraph
{
TextFamily
:
TextFamilies
.
CMUSerif
};
Heading1
=
Normal
{
ParAlignment
:
Center
;
TextFace
:
Serif
;
TextHeight
:
140%;
Bold
};
Heading2
=
Normal
{
TextHeight
:
110%;
Underline
};
Body
=
Normal
{
FirstIndent
:
8pt;
TextFamily
:
ParAlignment
:
Justify
};
Chapter1
=
Block
{
Heading1
{
"Chapter 1"
};
Heading2
{
"Introduction"
};
Body
{
"Consider the curious case of Dr. Jeckle. "
};
};
Chapter 1
Introduction
Consider the curious case of Dr. Jeckle.
Style Sheets
Once you have a set of styles, you can use them consistently throughout your content. Now, all of
your style information is in one place, separated from your content.
Emphasis
=
Span
{
Italic
;
TextColor
:
Colors
.
Red
};
Chapter2
=
Block
{
Heading1
{
"Chapter 2"
};
Heading2
{
"Introduction"
};
Body
{
"I would like to "
;
Emphasis
{
"emphasize"
};
" the following points. "
};
};
Chapter 2
Introduction
I would like to
emphasize
the following points.
Combine Content
You can also build manageable blocks of content in the same way, for reuse in different
documents, limited only by your imagination. A global style change, across all content and all
documents is now almost instant.
Book
=
Block
{
Chapter1
;
Chapter2
;
};
Chapter 1
Introduction
Consider the curious case of Dr. Jeckle.
Chapter 2
Introduction
I would like to
emphasize
the following points.
Bitmap Images
Bitmap pictures are represented with an
Image
object which accepts a path to a local file. Placing
the
res
operator in front of the file name to causes the compiler to search for the path at compile
time. This causes a missing file to be a compile error, rather than a runtime error.
readonly
Image
Zombie
=
new
(
res
"Zombie.png
");
ZombieText
=
Paragraph
{
"Zombies eat brains! "
;
FitBox
(
Zombie
, 20%, 20%);
};
Zombies eat brains!
Scalable Drawings
Scalable drawings like SVG files are represented with a
Drawing
object. Whether an
Image
or
Drawing
, it is a good practice to load images into a variable with the
readonly
attribute to ensure
that the file is loaded only once.
readonly
Drawing
NytrilBug
=
new
(
res
"Figure.svg
");
ScaleFigure
=
Paragraph
{
FitBox
(
NytrilBug
, 10%);
};
Change Baseline
Use the
Baseline
property to set the baseline of the image for alignment with other text.
ChangeBaseline
=
Block
{
Paragraph
{
"No baseline adjustment: "
;
FitBox
(
NytrilBug
, 5%);
};
Paragraph
{
"Baseline at 70%: "
;
FitBox
(
NytrilBug
, 5%) {
Baseline
:
70%
};
};
};
No baseline adjustment:
Baseline at 70%:
Fit to Width
You can fit an image to a given size using the
FitBox
formatter. Here we set the width parameter
to fit an image to a given width, while scaling the height proportionately.
PictureWidth
=
FitBox
(
Zombie
,
4%
);
Fit to Height
Set the height parameter to fit an image to a given height, while scaling the width
proportionately.
PictureHeight
=
FitBox
(
Zombie
,
null
,
10%
);
Fit to Rectangle
Fit an image inside both a given width and height, while maintaining proportion.
PictureBoth
=
FitBox
(
Zombie
,
10%, 20%
);
Force Dimensions
Force an image to a given size without preserving the image aspect ratio by setting the skew
parameter to true.
PictureSkew
=
FitBox
(
Zombie
, 20%, 10%,
null
,
true
);
Out of proportion
Opacity
Use the
Opacity
property to change how opaque the contents of a formatter appear.
PictureOpacity
(
opacity
)
=
VBox
{
Opacity
:
opacity
;
HAlign
:
Center
;
TextDigits
:
0;
opacity
;
FitBox
(
Zombie
, 5%);
};
ShowPictureOpacity
=
Paragraph
{
Separator
:
Space
*
5;
PictureOpacity
(
each
(10%
..
100%
step
10%))
};
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
Scaling Mode
Use the
ScalingMode
property to change how the pixels of the bitmap scale and resolve.
ImageMode
(
ScalingModes
mode
)
=
VBox
{
Margin
:
PadR
(10pt);
HAlign
:
Center
;
mode
;
FitBox
(
Zombie
, 7%) {
ScalingMode
:
mode
};
};
ShowPictureMode
=
Paragraph
{
ImageMode
(
each
ScalingModes
);
};
None
Pixelated
MediumQuality
HighQuality
Framed Drawings
Clip an image inside a border by setting the
BorderClip
property to true.
readonly
Image
Sally
=
new
(
res
"../Examples/Family Tree/SallyJones.jpg
");
FrameFigure
(
Image
image
,
w
)
=
Canvas
(
null
,
w
*
1.6,
new
Edge
(
w
*
10%, 0,
#DCBC93#
)) {
Background
:
95%;
BorderRadius
:
w
*
50%;
BorderClip
:
true
;
FitBox
(
image
,
null
,
w
*
1.4);
};
SallyFrame
=
FrameFigure
(
Sally
,
Math
.
Max
(
ExtentWidth
,
ExtentHeight
)
*
10%);
Rotated Drawings
Rotate and skew an image by setting the
Transform
property.
readonly
Image
Michael
=
new
(
res
"../Examples/Family Tree/MichaelJones.jpg
");
RotateFrame
(
Image
image
,
w
,
angle
)
=
FrameFigure
(
image
,
w
) {
Transform
:
Transform
.
Rotate
(
angle
)
Transform
.
Skew
(
angle
,
angle
);
TransformFit
:
true
;
};
Locket
=
HBox
{
VAlign
:
Top
;
var
w
=
Math
.
Max
(
ExtentWidth
,
ExtentHeight
)
*
5%;
RotateFrame
(
Sally
,
w
,
-
8
degrees
);
Canvas
(
w
*
5%,
w
*
50%) {
Margin
:
PadT
(
w
*
60%);
Background
:
#C9AC87#
};
RotateFrame
(
Michael
,
w
, 8
degrees
);
};
Icons
The
Icons
namespace has a library of common material icons.
MenuItem
=
Paragraph
{
TextHeight
:
200%;
Span
{
Icons
.
folder
;
TextColor
:
Colors
.
Gold
};
Space
;
"Open the folder"
;
};

Open the folder
Icon Drawing
Here we place the icon in a box with a hoverable tip, by applying the
Canvas
formatter with a
TipAction
property.
YouTube
(
height
,
URL
url
)
=
Canvas
(
height
*
1.4,
height
) {
TipAction
:
url
;
HAlign
:
Center
;
VAlign
:
Center
;
BorderRadius
:
height
*
20%;
Background
:
#FF0033#
;
TextColor
:
Colors
.
White
;
TextHeight
:
height
*
0.85;
TextOffset
:
4%;
Baseline
:
83%;
Icons
.
play_arrow
;
};
IconFigure
=
Paragraph
{
YouTube
(
ExtentWidth
*
3%,
new
(
"www.youtube.com/@Nytril"
));
Space
;
"Follow us on YouTube"
;
};

Follow us on YouTube
https://www.youtube.com/@Nytril
Web links
You can create a hyperlink to a web address simply by placing the
URL
inside a Span.
readonly
URL
WebAddress
=
new
(
"www.nytril.com"
);
LinkText
=
Span
{
WebAddress
;
};
www.nytril.com
Underlined on mouse-over
Change the text
If you want different text for the link, put the text in a Span and use the
Action
property to specify
the link.
Message
=
Span
{
Action
:
WebAddress
;
TextColor
:
Colors
.
Blue
;
"Visit us on the web"
;
};
Visit us on the web
Hidden URL
Popup tips
Use the
Tip
property to specify a formatted popup when the mouse hovers over the text in the
Span.
TheAnswer
=
Span
{
TextColor
:
Colors
.
DarkGreen
;
"The answer is "
;
Bold
42;
};
PopupMessage
=
Span
{
"The answer"
;
Tip
:
new
Tip
(
TheAnswer
);
};
The answer
The answer is
42
Tip + Action
Use the
TipAction
property to specify a both a tip and an action at the same time.
ActionTip
=
Span
{
"Here's a tip: "
;
Span
{
"Visit us on the web"
;
Underline
;
TipAction
:
WebAddress
;
}
};
Here's a tip:
Visit us on the web
www.nytril.com
Document Anchors
To create links within a single document, you must first give the target Paragraphs a reference
name using the
Anchor
function. The anchor name of each Paragraph must be unique in the
document.
HelpAnchor
=
"HelpCenter"
;
AnchoredPar
=
Paragraph
{
"Paragraph with the \"
{0}
\" anchor. "
(
HelpAnchor
);
DocFields
.
Anchor
(
HelpAnchor
)
;
};
Paragraph with the "HelpCenter" anchor.
Anchor Links
Once the anchor name is assigned to a paragraph, you can create an action that links to that
paragaph, no matter where it is placed in the document.
HelpLink
=
Span
{
Action
:
new
Action
(
Actions
.
ToAnchor
,
HelpAnchor
);
"Find out more in the help section. "
;
};
Find out more in the help section.
QR Codes
To label products or printed documents, QR codes can be added with the
QRBox
formatter. Notice
that there is always a white border around the QR code which is required by the QR readers.
QRCode
=
VBox
{
HAlign
:
Center
;
"Follow us online"
;
QRBox
(
WebAddress
,
QRSize
);
};
Follow us online
https://www.nytril.com
"Quiet zone"
QR Codes with Links
Change the level of error correction in the QR code by setting the error parameter to a number
from 0 to 3.
QRLink
=
VBox
{
HAlign
:
Center
;
"Community Edition"
;
QRBox
(
WebAddress
,
QRSize
,
3
) {
TipAction
:
WebAddress
;
};
};
Community Edition
https://www.nytril.com
More complex pattern
includes more error correction
Links to Files
Create an action to browse to a local file with the
ToFile
action type. This will bring up File
Explorer on Windows (or Finder on the Mac) and point it to the specified path.
FileLink
=
Span
{
"Open in File System"
;
Tip
:
"Browse the File"
;
Action
:
new
Action
(
Actions
.
ToFile
,
res
"Hyperlinks.nytril
");
};
Open in File System
Browse the File
Custom Actions
Create a complex custom action by inheriting the
Action
class and overriding the Execute function.
class
CustomAction
:
Action
{
var
Text
;
Constructor
(
text
) {
super
.
Constructor
(
Actions
.
Execute
);
Text
=
text
;
}
override
EventResponse
Execute
{
System
.
TextToClipboard
(
Text
);
return
EventResponses
.
MessageTip
(
"Text copied to the clipboard"
);
}
}
CustomLink
=
Span
{
Icons
.
copy
;
Space
;
"Copy Text"
;
TipAction
:
new
CustomAction
(
"Custom Text"
);
};

Copy Text
Text copied to the clipboard
HBoxes
Enclose content in a horizontally aligned box using the
HBox
formatter.
Outline
=
new
Edge
(
Gap
*
0.5, 0,
OutColor
);
DigitBox
(
i
)
=
HBox
(
null
,
null
,
new
Edge
(0,
Gap
)) {
Background
:
Colors
.
Green
;
TextColor
:
Colors
.
White
;
HAlign
:
Center
;
Space
;
i
;
Space
;
};
HBoxSet
=
HBox
(
null
,
null
,
Outline
) {
VAlign
:
Center
;
DigitBox
(
each
'A'
..
'C'
);
};
A
B
C
VBoxes
Enclose content in a vertically aligned box using the
VBox
formatter.
VBoxSet
=
VBox
(
null
,
null
,
Outline
) {
HAlign
:
Center
;
DigitBox
(
each
1
..
3);
};
1
2
3
Separation
Space between each element can be added with the
Separation
property.
BoxesWithSeparation
=
Paragraph
{
HBoxSet
{
Separation
:
Gap
;
};
Space
;
VBoxSet
{
Separation
:
Gap
;
};
};
A
B
C
1
2
3
Separators
New separator elements can be automatically added between each existing element of the box by
using the
Separator
property. Notice that the same separator revision is used to modify two
different box formatters.
PlusEquals
=
{
Separator
:
" + "
;
LastSeparator
:
" = "
;
};
BoxesWithSeparators
=
Paragraph
{
VBoxSet
PlusEquals
;
Space
;
HBoxSet
PlusEquals
;
};
1
+
2
=
3
A
+
B
=
C
Justification
Change the justification of items inside the box using the
Justify
property.
JustifiedBox
=
HBox
(50%,
null
,
Outline
) {
Justify
:
Justifiers
.
SpaceBetween
;
1
..
5
step
1;
};
1
2
3
4
5
Justification Examples
Use a loop to create a chart of all the
Justify
options.
JustifiedBoxes
=
VBox
{
Separation
:
1%;
foreach
(
var
j
in
Justifiers
)
{
HBox
{
HBox
(20%) {
HAlign
:
Right
;
Margin
:
PadR
(2%);
j
};
HBox
(50%,
null
,
Outline
) {
Justify
:
j
;
1
..
5
step
1;
};
}
}
};
None
1
2
3
4
5
Start
1
2
3
4
5
End
1
2
3
4
5
Center
1
2
3
4
5
SpaceBetween
1
2
3
4
5
SpaceAround
1
2
3
4
5
SpaceEvenly
1
2
3
4
5
Margins
Use the
Margin
property to put distance between the box and adjacent content.
MarginPadding
=
HBox
(
null
,
null
,
new
Edge
(0.5%, 0,
OutColor
)) {
HBox
{
Margin
:
Gap
;
Background
:
90%;
" Inner box with outside margin "
;
};
};
Inner box with outside margin
Margin Examples
Here are some examples of different combinations of
Margin
settings.
MarginBox
(
name
,
l
,
t
,
r
,
b
)
=
HBox
(
null
,
null
,
new
Edge
(0.5%, 0,
OutColor
)) {
HBox
{
Margin
:
new
Thickness
(
l
,
t
,
r
,
b
);
Background
:
90%;
Space
;
name
;
Space
;
};
};
BoxesWithMargins
=
Paragraph
{
Separator
:
Space
*
4;
MarginBox
(
"LTRB"
,
Gap
,
Gap
,
Gap
,
Gap
);
MarginBox
(
"T"
, 0,
Gap
, 0, 0);
MarginBox
(
"B"
, 0, 0, 0,
Gap
);
MarginBox
(
"L"
,
Gap
, 0, 0, 0);
MarginBox
(
"R"
, 0, 0,
Gap
, 0);
MarginBox
(
"LR"
,
Gap
, 0,
Gap
, 0);
MarginBox
(
"TB"
, 0,
Gap
, 0,
Gap
);
};
LTRB
T
B
L
R
LR
TB
Padding
Set the border padding using the Padding parameter of the
Edge
constructor. This puts distance
between the border and its contents.
EdgePadding
=
HBox
(
null
,
null
,
new
Edge
(0.5%,
Gap
,
OutColor
)) {
"Padding between content and edge"
;
};
Padding between content and edge
Padding Examples
Here are some examples of
Border
padding applied in different combinations.
PaddingBox
(
n
,
l
,
t
,
r
,
b
)
=
HBox
(
null
,
null
,
new
(
new
(1,
l
),
new
(1,
t
),
new
(1,
r
),
new
(1,
b
)
)) {
HBox
{
Background
:
90%;
Span
{
Space
;
n
;
Space
};
};
};
BoxesWithPadding
=
Paragraph
{
Separator
:
Space
*
4;
PaddingBox
(
"LTRB"
,
Gap
,
Gap
,
Gap
,
Gap
);
PaddingBox
(
"T"
, 0,
Gap
, 0, 0);
PaddingBox
(
"B"
, 0, 0, 0,
Gap
);
PaddingBox
(
"L"
,
Gap
, 0, 0, 0);
PaddingBox
(
"R"
, 0, 0,
Gap
, 0);
PaddingBox
(
"LR"
,
Gap
, 0,
Gap
, 0);
PaddingBox
(
"TB"
, 0,
Gap
, 0,
Gap
);
};
LTRB
T
B
L
R
LR
TB
Border Radius
Rounded corners can be specified using the
BorderRadius
property.
RoundedBorders
=
HBox
(
null
,
null
,
new
Edge
(1%, 3%,
Colors
.
Blue
)) {
BorderRadius
:
Gap
*
2;
TextHeight
:
200%;
HAlign
:
Center
;
"Rounded Corners"
;
};
Rounded Corners
Border Radius Examples
Here are some examples of rounded corners with different values for each corner.
Chicklet
(
text
)
=
HBox
(
null
,
null
,
new
Edge
(0.5%, 0,
Colors
.
Blue
)) {
TextHeight
:
200%;
HAlign
:
Center
;
Background
:
Colors
.
AliceBlue
;
Space
;
text
;
Space
;
};
AllChicklets
=
Paragraph
{
Separator
:
Space
*
3;
Chicklet
(
"Rounded"
) {
BorderRadius
:
Gap
};
Chicklet
(
"Flat"
) {
BorderRadius
:
new
Size
(2
Gap,
Gap
)};
Chicklet
(
"TL-BR"
) {
BorderRadius
:
new
BorderRadius
(
Gap
, 0,
Gap
, 0)
};
Chicklet
(
"Top"
) {
BorderRadius
:
new
BorderRadius
(
Gap
,
Gap
, 0, 0)};
Chicklet
(
"Right"
) {
BorderRadius
:
new
BorderRadius
(0,
new
Size
(
Gap
, 2
Gap
),
new
Size
(
Gap
, 2
Gap
), 0)};
};
Rounded
Flat
TL-BR
Top
Right
Background
The
Background
property sets the fill pattern for the box.
Back
=
new
RadialGradient
(20%, 30%, 20%, 30%, 20%, 40%,
[
new
(0,
Colors
.
White
),
new
(100%,
Colors
.
LightGreen
)]
);
BoxWithBackground
=
HBox
(
null
,
null
,
new
Edge
(0.5%, 1%)) {
Background
:
Back
;
BorderRadius
:
Gap
;
TextHeight
:
150%;
" Start "
;
};
Start
Shadows
Use the
Shadow
property to add a raised look to a box.
ShadowBox
=
BoxWithBackground
{
Shadow
:
new
Edge
(0.4%, 0,
Colors
.
DarkGray
);
};
Start
Shapes
A
Shape
formatter holds a group of open or closed paths. Here the path is a simple line segment.
LineSize
=
LessonExample
.
FontHeight
*
0.5;
readonly
Stroke
Stroke1
=
new
(
LineSize
);
LineSeg
=
Canvas
(
ExtentWidth
*
50%,
ExtentWidth
*
10%) {
Margin
:
LineSize
;
Shape
(
null
,
Stroke1
) {
OpenPath
(0, 0) {
LineTo
(33%, 100%);
};
};
};
Open Paths
Make an open line path using the
OpenPath
formatterThe arguments are the starting point of the
shape.
ZigZag
(
Stroke
stroke
)
=
Canvas
(
ExtentWidth
*
50%,
ExtentWidth
*
10%) {
Margin
:
LineSize
;
Shape
(
null
,
stroke
) {
OpenPath
(0, 0) {
LineTo
(33%, 100%);
LineTo
(66%, 0);
LineTo
(100%, 100%);
}
};
};
BlackZigZag
=
ZigZag
(
Stroke1
);
Color options
Change the color of the line with the 2nd parameter of the
Stroke
constructor.
Stroke
LS1
=
new
(
LineSize
,
Colors
.
Red
);
Line1
=
ZigZag
(
LS1
);
Line Styles
Change the style of the line using LineStyles, the 3rd parameter of the
Stroke
constructor.
Stroke
LS2
=
new
(
LineSize
,
Colors
.
Red
,
Dotted
);
Line2
=
ZigZag
(
LS2
);
Line Style Gallery
Use a loop to enumerate the different
LineStyles
options.
DrawLineStyle
(
LineStyles
linestyle
)
=
Canvas
(40%,
LessonExample
.
FontHeight
) {
Shape
(
null
,
new
(
LineSize
,
Colors
.
Black
,
linestyle
,
Flat
)) {
OpenPath
(0, 50%) {
LineTo
(100%, 50%)};
};
};
LineStyleList
=
TwoColumTable
{
foreach
(
var
style
in
LineStyles
)
Row
{
style
.
Name
;
DrawLineStyle
(
style
)};
};
Solid
Dashed
Dotted
DashDot
DashDotDot
Line Caps
Change the LineCap style using the 4th parameter of the
Stroke
constructor.
Stroke
LS3
=
new
(
LineSize
,
Colors
.
Red
,
Dotted
,
Round
);
Line3
=
ZigZag
(
LS3
);
Line Cap Gallery
Iterate over the different
LineCaps
options.
DrawLineCap
(
LineCaps
cap
)
=
Canvas
(10%,
LessonExample
.
FontHeight
*
2) {
Shape
(
null
,
new
(
LineSize
*
2,
Colors
.
Black
,
LineStyles
.
Solid
,
cap
)) {
OpenPath
(0, 50%) {
LineTo
(100%, 50%);}
};
Shape
(
null
,
new
(
LineSize
*
0.25,
Colors
.
Red
,
LineStyles
.
Solid
,
cap
)) {
OpenPath
(0, 50%) {
LineTo
(100%, 50%);}
};
};
LineCapTable
=
TwoColumTable
{
foreach
(
var
cap
in
LineCaps
)
Row
{
cap
.
Name
;
DrawLineCap
(
cap
)};
};
Flat
Square
Round
Line Joins
Change the LineJoin style using the 5th parameter of the
Stroke
constructor.
Stroke
LS4
=
new
(
LineSize
*
2,
Colors
.
Blue
,
Solid
,
Flat
,
Round
);
Line4
=
ZigZag
(
LS4
);
Line Join Gallery
Loop over the different
LineJoins
options.
DrawLineJoin
(
LineJoins
linejoin
)
=
Canvas
(7%,
LessonExample
.
FontHeight
*
2) {
VAlign
:
Center
;
Shape
(
null
,
new
(
LineSize
,
Colors
.
Black
,
Solid
,
Flat
,
linejoin
)) {
OpenPath
(0) {
LineTo
(50%, 70%);
LineTo
(100%, 0)};
};
};
LineJoinTable
=
TwoColumTable
{
foreach
(
var
linejoin
in
LineJoins
)
Row
{
linejoin
.
Name
;
DrawLineJoin
(
linejoin
)};
};
Miter
Round
Bevel
Miter limit
Use the miterlimit parameter to limit the ratio of the extent of a miter join to the stroke size
(default: 4.0).
DrawMiterJoin
(
miter
)
=
Canvas
(6%,
LessonExample
.
FontHeight
*
1.5) {
VAlign
:
Center
;
Shape
(
null
,
new
(
LineSize
*
0.25,
Colors
.
Black
,
Solid
,
Flat
,
Miter
,
miter
)) {
OpenPath
(0, 30%) {
LineTo
(100%, 50%);
LineTo
(0, 70%)};
};
};
MiterTable
=
TwoColumTable
{
Row
{
Bold
;
"Miter Limit"
;
"Effect"
};
foreach
(
var
m
in
[50, 1])
Row
{
TextDigits
:
0;
m
;
DrawMiterJoin
(
m
)};
};
Miter Limit
Effect
50
1
Closed paths
Use the
ClosedPath
formatter to create a closed, fillable path. A final line segment to the origin of
the path is automatically added to the end of the path.
ShowClosedPath
=
Canvas
(
LessonExample
.
FontHeight
*
10,
LessonExample
.
FontHeight
*
10) {
Shape
(
Colors
.
Green
) {
ClosedPath
(10%, 10%) {
LineTo
(90%, 90%);
LineTo
(10%, 90%);
// Line to origin is added automatically
};
};
};
Cutouts
Adding a second closed path in the same shape will 'cut a hole' in the first shape.
CutoutFigure
=
Canvas
(
LessonExample
.
FontHeight
*
10,
LessonExample
.
FontHeight
*
10) {
Shape
(
Colors
.
Green
) {
ClosedPath
(10%, 10%) {
LineTo
(90%, 90%);
LineTo
(10%, 90%);
};
EllipsePath
(
new
(
new
(15%, 40%),
new
(20%)));
// Cutout
};
};
Repeated segments
Use a loop to make a shape with a repeated set of line segments.
Saw
=
Canvas
(90%,
LessonExample
.
FontHeight
*
3) {
Shape
(
Colors
.
Silver
) {
ClosedPath
(0) {
foreach
(
var
x
in
0%
..
100%
step
10%)
{
LineTo
(
x
, 100%);
LineTo
(
x
, 50%);
}
LineTo
(100%, 0);
};
};
};
PolygonPath
Make a regular n-sided polygon using the
PolygonPath
function.
NGon
(
radius
,
n
)
=
VBox
(
radius
*
2
+
6) {
HAlign
:
Center
;
Span
{
TextColor
:
Colors
.
Red
;
n
};
Shape
(
Colors
.
Yellow
, 3) {
PolygonPath
(
new
(0,
radius
*
2),
n
,
-
90
degrees
);
};
};
NGons
=
HBox
{
VAlign
:
Top
;
var
sep
=
LessonExample
.
FontHeight
*
0.5;
Separation
:
sep
;
NGon
(
ExtentWidth
/
16
-
sep
,
each
3
..
10);
};
3
4
5
6
7
8
9
10
QuadTo formatter
Make a quadratic curve with two endpoints and a control point using the
QuadTo
function.
CheckMark
=
Canvas
(
LessonExample
.
FontHeight
*
7,
LessonExample
.
FontHeight
*
5) {
Shape
(
Colors
.
LightGreen
,
Colors
.
DarkGreen
) {
ClosedPath
(1%, 50%) {
QuadTo
(
new
(9%, 44%),
new
(20%, 43%));
QuadTo
(
new
(31%, 52%),
new
(36%, 69%));
QuadTo
(
new
(60%, 28%),
new
(99%, 5%));
QuadTo
(
new
(55%, 39%),
new
(36%, 96%));
QuadTo
(
new
(34.5%, 100%),
new
(33%, 96%));
QuadTo
(
new
(21%, 60%),
new
(1%, 50%));
};
};
};
Quadratic Examples
Here are some examples of how the position of the control point affects the shape of a quadratic
curve.
ShowQuads
=
Canvas
{
Margin
:
LineSize
;
ShowQExample
(
each
QuadExamples
);
};
Cubic curves
Make a cubic curve with two endpoints and two control points, using the
CurveTo
function.
BowTie
=
Canvas
(
LessonExample
.
FontHeight
*
5,
LessonExample
.
FontHeight
*
5) {
Shape
(
null
,
LS1
) {
OpenPath
(33%, 10%) {
CurveTo
(
new
(100%, 100%),
new
(0, 100%),
new
(65%, 10%));
};
};
};
Cubic Examples
The following examples show how the control points bend the curve.
ShowCubics
=
Canvas
{
Margin
:
LineSize
;
ShowCurve
(
each
CubicExamples
);
};
Glyph paths
Placing a string inside a shape will cause the paths of the character glyphs to be added to the
shape. This allows you to build fanciful titles and designs with text.
GlyphBox
(
text
,
angle
=
0)
=
Canvas
(
null
,
null
,
new
Edge
(0,
LineSize
*
2)) {
Background
:
AgedWood
;
BorderRadius
:
LineSize
;
Transform
:
Transform
.
Rotate
(
angle
);
TransformFit
:
true
;
Shape
(
null
,
new
(
LineSize
*
0.25,
Colors
.
Black
,
Dotted
,
Round
)) {
text
;
};
};
AGlyph
=
HBox
{
VAlign
:
Top
;
TextHeight
:
LessonExample
.
FontHeight
*
5;
GlyphBox
(
"Shooting"
);
GlyphBox
(
"Range"
, 20
degrees
);
};
Symbols
Symbols are special values that can represent constants or variables
x
=
Symbol
(
"x"
);
x
Algebra
Basic algebra is performed automatically when symbols are multipled or added.
AddX
=
2
x
+
5
x
+
3;
7
x
 +Â
3
Operand Affinity
The operator between common types can be ommited in simple expressions
ThreeX
=
3
x
;
g
=
9.8
meters
per
second
^
2;
Palindrome
=
"was it "
"a car "
"or a cat I saw"
;
3
x
9.8Â
meters
second
2
was it a car or a cat I saw
Statistics
The
standard deviation
of an array is defined as:
σ
 =Â
(
x
i
 −Â
x
)
2
n
i
 =Â
1
n
It can be computed using the
StandardDeviation
function.
StdDevData
=
Math
.
StandardDeviation
(
NumberSet
);
1.6647488966474462
Vectors
Vector objects represent a 1 dimensional array of values of a fixed size.
x
=
Symbol
(
"x"
);
y
=
Symbol
(
"y"
);
z
=
Symbol
(
"z"
);
a
=
Symbol
(
"a"
);
b
=
Symbol
(
"b"
);
c
=
Symbol
(
"c"
);
d
=
Symbol
(
"d"
);
N1
=
Vector
.
Convert
([4.0, 2.0]);
N2
=
Vector
.
Convert
([1.0, 9.0]);
V1
=
Vector
.
Convert
([
a
,
b
]);
V2
=
Vector
.
Convert
([
c
,
d
]);
[4, 2]
[1, 9]
[
a
,
b
]
[
c
,
d
]
Vector math
The cross product of two 3-vectors is calculated using the
Cross
function.
VCross
=
Vector
.
Convert
([
a
,
b
,
c
])
.
Cross
([
x
,
y
,
z
]);
NCross
=
Vector
.
Convert
([1.0, 2.0, 3.0])
.
Cross
([4.0, 5.0, 6.0]);
[
b
z
 −Â
c
y
,
c
x
 −Â
a
z
,
a
y
 −Â
b
x
]
[-3, 6, -3]
Matrices
Matrix objects represent a 2 dimensional array of numbers or symbols of a fixed size.
x
=
Symbol
(
"x"
);
y
=
Symbol
(
"y"
);
z
=
Symbol
(
"z"
);
a
=
Symbol
(
"a"
);
b
=
Symbol
(
"b"
);
c
=
Symbol
(
"c"
);
d
=
Symbol
(
"d"
);
e
=
Symbol
(
"e"
);
f
=
Symbol
(
"f"
);
g
=
Symbol
(
"g"
);
h
=
Symbol
(
"h"
);
N1
=
Matrix
.
Convert
([[1.0, 4.0], [3.0, 1.0]]);
N2
=
Matrix
.
Convert
([[7.0, 5.0], [8.0, 9.0]]);
V1
=
Matrix
.
Convert
([[
a
,
b
], [
c
,
d
]]);
V2
=
Matrix
.
Convert
([[
e
,
f
], [
g
,
h
]]);
1
4
3
1
7
5
8
9
a
b
c
d
e
f
g
h
Matrix math
Matrices of the same size can be added together using the
+
operator.
VAdd
=
V1
+
V2
;
NAdd
=
N1
+
N2
;
a
 +Â
e
b
 +Â
f
c
 +Â
g
d
 +Â
h
8
9
11
10
External processes
An executable file can be run using
Process
readonly
Console
=
Paragraph
{
TextFace
:
Mono
;
TextHeight
:
12pt;
TextColor
:
Colors
.
White
;
ParBackground
:
Colors
.
Black
;
Process
process
;
if
(
System
.
OperatingSystem
==
OperatingSystems
.
Mac
)
process
=
new
Process
(
"/bin/ls"
);
else
process
=
new
Process
(
Folders
.
System
FileName
(
"netstat.exe"
),
"-e"
);
var
result
=
process
.
Run
;
if
(
result
.
ExitCode
==
0)
result
.
StandardOutput
;
else
result
.
ErrorMessage
;
};
Interface Statistics
Received Sent
Bytes 2959409358 398000592
Unicast packets 1022486 804722
Non-unicast packets 34430 10040
Discards 0 0
Errors 0 0
Unknown protocols 0