Introducing
NumbersReal numbers are a sequence of decimal digits containing a decimal pointRealValue = 3.14;3.14
Rational numbersRatios of integers can be created using the over operator.OneThird = 1 over 3;FractionSum = OneThird + 5 over 6;116
Complex NumbersComplex numbers are also supported, and real and imaginary parts are automatically aggregatedComplex1 = 3i + 2i + 5 + 3;8+5i
StringsA 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 slicesAll array operations work on strings, in the same waySimpleString = "This is an array of characters";StringSlice = SimpleString[10..15];StringNew = SimpleString.Insert(5..11, "really ");This is an array of characters arrayThis really is an array of characters
String ArgumentsStrings 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 CallMessage is not a string, but is instead a function taking 1 argument. FileError = Message("file.txt");There is an error in "file.txt"
Unit ConversionsYou can convert between compatible units using the tounit operator.MetricDistance = Distance tounit centimeters;40.64 centimeters
Compound unit conversionsThe power of water flowing over Niagra fallsWaterFlow = 1 mile^3 per year; // from the book "Energy" by Richard RhodesFallsHeight = 170 feet;g = 9.8 meters per second^2;Power = (WaterFlow * WaterDensity * FallsHeight * g) tounit megawatts;67 megawatts
ArrayAn array is an ordered container of objects[0, 1, 2, 3, x, y, A, B, C, π2, i]
SlicesAn arbirtary slice of a array can be obtained by putting an array of ranges inside square brackets [][0, 1, 3, y, A, i]
RangesA range is an ordered, inclusive pair of values using the .. operator. SmallRange = 1..5;1..5
Range arraysAn array can be created with a range using the step operator.[1, 3, 5, 7, 9, 10]
ChartsThe data used for a chart can come from an equation represented by a functionQuadratic(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 = x2 − 50-15-13-11-9-7-5-3-102468101214-50-30-10103050
TablesA 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)};RainfallMonthValueErrorJanuary12.0 inches-1.0 +1.0February13.2 inches-1.0 +1.0March14.6 inches-1.0 +1.2April18.5 inches-1.0 +1.0May12.6 inches-0.6 +0.4June7.2 inches-1.0 +1.0July4.0 inches-1.0 +1.0August4.7 inches-0.4 +1.2September5.0 inches-1.0 +1.0October6.0 inches-1.0 +1.0November12.6 inches-1.0 +1.0December15.1 inches-1.0 +1.0
TreesA 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;};RootAA1A2BC
RevisionsRevisions 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: LargeThe following text is: BoldThe following text is: ItalicThe following text is: Large, Bold, Italic
Text ColorIf 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 BackgroundThe 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 TextMake 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 shortcutApply 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 TextMake the font bold by setting the TextWeight property to Bold.ShowBold = Paragraph { "Use "; Span { TextWeight: Bold; "extreme"; }; " caution. ";};Use extreme caution.
Bold shortcutApply the special Bold revision directly to a string for a more concise expression.ShowBold2 = Paragraph { "Use "; Bold "extreme"; " caution. ";};Use extreme caution.
Font FaceUse 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 TextMonospaced Text
Font FamilyUse 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 TextUse 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 TextUse 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 CasingYou 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!"; }; }; }};Nonehello Hello HELLO!AllUpperHELLO HELLO HELLO!AllLowerhello hello hello!WordUpperHello Hello Hello!FirstUpperHello Hello HELLO!FirstLowerhello Hello HELLO!SmallCapshello Hello HELLO!
Letter SpacingChange 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." }; }; }};1The quick brown fox jumped over the lazy dog.2The quick brown fox jumped over the lazy dog.3The quick brown fox jumped over the lazy dog.4The quick brown fox jumped over the lazy dog.5The quick brown fox jumped over the lazy dog.
Letter StretchingText 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.
SeparatorsInsert content between elements with the Separator property.ShowSeparator = Paragraph { Separator: ", "; 1..5 step 1;};1, 2, 3, 4, 5
Last SeparatorChange 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 SeparatorTo 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};};11 and 21, 2, and 3
int LiteralsTo 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 ValuesFunctions 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 FormatTo format an integer in hexadecimal, change the TextRadix to 16. IntegerHexadecimal = Span { TextRadix: 16; 129579;};1fa2b
Uppercase Hex FormatTo have the hex digits shown in upper-case, change the TextCase property to AllUpper. IntegerHexadecimalUpper = Span { TextRadix: 16; TextCase: AllUpper; 671277;};A3E2D
Binary FormatTo format a number in binary, use 2 as the TextRadix. IntegerBinary = Span { TextRadix: 2; 127;};1111111
Number Zero-PaddingUse 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;};0004001b2fd5
Group SeparatorsTo format an integer with a group separator, set the TextGroup property to true. IntegerGroup = Span { TextGroup: true; 1234567.89;};1,234,567.89
Culture SettingsUse 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 LiteralsAs 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 ValuesFormatting a return value from a function works the same way. DoubleReturn = Span { Math.Sqrt(1 + 1);};1.4142135623730951
Decimal DigitsUse the TextDigits property to fix the number of fractional digits in the number. DoubleDigits = Span { TextDigits: 3; Math.PI;};3.142
Percentage FormatSet the TextPercent property to true to show numbers as percentages. Percentage = Block { TextPercent: true; 0.04; 1.5;};4%150%
Significant FiguresSet 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;};43305.420.000643122000000000.000000000120
Scientific NotationFormat the number in scientific notation by setting TextScientific to true. ScientificNotation = Span { TextScientific: true; TextDigits: 2; 175_000;};1.75x105
Significant Figures in Scientific NotationNotice 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.2x106
Decimal Tab StopsYou 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.2123.990.5544
Fractional ExpressionsUse 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;};181212341116
SymbolsUse 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 32x raised to the power of y is xyThe independent variable 'y'
FractionsCreate several different types of common fractions with the Fraction formatter.FormatFraction = Fraction { x; y+1;};xy + 1
Slanted FractionsFormat the fraction with a diagonal slash by setting the diagonal argument to true. SlantedFraction = Fraction(true) { x; y ^ 2;};xy2
Compact FractionsCreate 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 34 of a cup of flour.
Compact Fraction ShortcutFor 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 12 teaspoon of sugar and stir.
TextDiagonal PropertyChange 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 113 tablespoons of warm water if the dough is too firm.
SubscriptsAdd a subscript to a symbol by using the sub operator. X1 = x sub 1;x1
SuperscriptsUse 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 = mc2The speed of light
RadicalsSquare-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 degreeChange the degree of the radical by setting the Degree propertyV = 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 V3
Nary formatterThe 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]Operatorpre-upperpre-lowerupperlower
Nary Operator propertySet 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};};1ns
Nary Upper PropertyUse 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 = 11x2 dx
TextStacked propertyPlace the superscripts and subscripts above and below the Operator by setting the TextStacked property to true. StackedNary = InverseSquareIntegral { TextStacked: true;};f(x) = ∞x = 11x2 dx
Nary PreUpper and PreLowerUse 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");Th23290
Nary ElementsThe 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; };};psps − 1
TextEquation propertyIf 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) = 1ns = psps − 1
Polynomial EquationsHere 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);ax5 + bx4 + cx3 + dx2 + ex + f
Bracket PropertyUse 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;};ex = limn → ∞1 + x1! + x22! + x33! + ⋯ + xnn!
Bracket StylesChoose 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"};};OverUnderbar aboveflat curly belowround above
Large expressions in BracketsEnclose 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 1Topic 2Topic 3
All Bracket TypesHere 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 PlacementUse 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");};Th23290 α Ra22888 β− Ac22889
MatricesMatrices 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π2341x + 2y + 5811π2341x + 2y + 5811π2341x + 2y + 581
BlocksLet'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 OneParagraph Two2.414213562373095
Nested BlocksA 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 1Line 2Line 3Default block formatOverridden format
ParagraphsA 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
IndentingUse 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
AlignmentAlignment of the text can be controlled with the ParAlignment property. SmallBlock = Block { Paragraph {ParAlignment: Left; "Left"}; Paragraph {ParAlignment: Center; "Center"}; Paragraph {ParAlignment: Right; "Right"};};LeftCenterRight
Justify AlignmentThe 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 stopsThe 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"; };};LeftCenter3.1415.....................................................RightLeft AlignCenter Align527.10.................................................Right Align
FramesA 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 listsA 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 ColorParagraphs 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 BeforeAdd extra space before the start of a paragraph using the SpaceBefore property. ParSpaceBefore = Block { Bold "Header"; Paragraph { "First line"; SpaceBefore: 200%; };};HeaderFirst lineSpace before the paragraph
Space AfterAdd extra space after the end of a paragraph using the SpaceAfter property. ParSpaceAfter = Block { Paragraph { SpaceAfter: 200%; TextHeight: 120%; Bold; "Title"; }; "Body text";};TitleBody textSpace after the paragraph
BordersSet 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 sidestop - bottomleft - right
Border color and paddingParagraph borders can also have different colors and paddingColorBorder = Paragraph(new Edge(3pt, 5pt, Colors.Red)) { ParAlignment: Center; ParBackground: #FCFCF4#; LeftIndent: 16pt; RightIndent: 15pt; Bold; "Very Important Notice";};Very Important Notice
Line HeightChange 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 POINTSStatement of Relevant FactsDouble-spaced lines
Create Named StylesUse 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 1IntroductionConsider the curious case of Dr. Jeckle.
Style SheetsOnce 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 2IntroductionI would like to emphasize the following points.
Combine ContentYou 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 1IntroductionConsider the curious case of Dr. Jeckle. Chapter 2IntroductionI would like to emphasize the following points.
Bitmap ImagesBitmap 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 DrawingsScalable 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 BaselineUse 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 WidthYou 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 HeightSet the height parameter to fit an image to a given height, while scaling the width proportionately. PictureHeight = FitBox(Zombie, null, 10%);
Fit to RectangleFit an image inside both a given width and height, while maintaining proportion. PictureBoth = FitBox(Zombie, 10%, 20%);
Force DimensionsForce 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
OpacityUse 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 ModeUse 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);};NonePixelatedMediumQualityHighQuality
Framed DrawingsClip 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 DrawingsRotate 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);};
IconsThe 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 DrawingHere 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 YouTubehttps://www.youtube.com/@Nytril
Web linksYou 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.comUnderlined on mouse-over
Change the textIf 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 webHidden URL
Popup tipsUse 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 answerThe answer is 42
Tip + ActionUse 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 webwww.nytril.com
Document AnchorsTo 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 LinksOnce 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 CodesTo 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 onlinehttps://www.nytril.com"Quiet zone"
QR Codes with LinksChange 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 Editionhttps://www.nytril.comMore complex patternincludes more error correction
Links to FilesCreate 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 SystemBrowse the File
Custom ActionsCreate 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 TextText copied to the clipboard
HBoxesEnclose 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
VBoxesEnclose content in a vertically aligned box using the VBox formatter. VBoxSet = VBox(null, null, Outline) { HAlign: Center; DigitBox(each 1..3);}; 1 2 3
SeparationSpace 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
SeparatorsNew 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
JustificationChange the justification of items inside the box using the Justify property. JustifiedBox = HBox(50%, null, Outline) { Justify: Justifiers.SpaceBetween; 1..5 step 1;};12345
Justification ExamplesUse 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; }; } }};None12345Start12345End12345Center12345SpaceBetween12345SpaceAround12345SpaceEvenly12345
MarginsUse 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 ExamplesHere 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
PaddingSet 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 ExamplesHere 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 RadiusRounded 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 ExamplesHere 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
BackgroundThe 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
ShadowsUse the Shadow property to add a raised look to a box.ShadowBox = BoxWithBackground { Shadow: new Edge(0.4%, 0, Colors.DarkGray);}; Start
ShapesA 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 PathsMake 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 optionsChange the color of the line with the 2nd parameter of the Stroke constructor. Stroke LS1 = new(LineSize, Colors.Red);Line1 = ZigZag(LS1);
Line StylesChange 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 GalleryUse 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)};};SolidDashedDottedDashDotDashDotDot
Line CapsChange the LineCap style using the 4th parameter of the Stroke constructor. Stroke LS3 = new(LineSize, Colors.Red, Dotted, Round);Line3 = ZigZag(LS3);
Line Cap GalleryIterate 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)};};FlatSquareRound
Line JoinsChange 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 GalleryLoop 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)};};MiterRoundBevel
Miter limitUse 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 LimitEffect501
Closed pathsUse 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 }; };};
CutoutsAdding 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 segmentsUse 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); }; };};
PolygonPathMake 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);};345678910
QuadTo formatterMake 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 ExamplesHere 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 curvesMake 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 ExamplesThe following examples show how the control points bend the curve.ShowCubics = Canvas { Margin: LineSize; ShowCurve(each CubicExamples);};
Glyph pathsPlacing 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);};
SymbolsSymbols are special values that can represent constants or variablesx = Symbol("x");x
AlgebraBasic algebra is performed automatically when symbols are multipled or added. AddX = 2 x + 5 x + 3;7x + 3
Operand AffinityThe operator between common types can be ommited in simple expressionsThreeX = 3 x;g = 9.8 meters per second^2;Palindrome = "was it " "a car " "or a cat I saw";3x9.8 meterssecond2was it a car or a cat I saw
StatisticsThe standard deviation of an array is defined as:σ = (xi − x)2ni = 1nIt can be computed using the StandardDeviation function. StdDevData = Math.StandardDeviation(NumberSet);1.6647488966474462
VectorsVector 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 mathThe 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]);[bz − cy, cx − az, ay − bx][-3, 6, -3]
MatricesMatrix 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]]);14317589abcdefgh
Matrix mathMatrices of the same size can be added together using the + operator.VAdd = V1 + V2;NAdd = N1 + N2;a + eb + fc + gd + h891110
External processesAn executable file can be run using Processreadonly 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 SentBytes 2959409358 398000592Unicast packets 1022486 804722Non-unicast packets 34430 10040Discards 0 0Errors 0 0Unknown protocols 0