El lenguaje de
programación
Versión 1.8.0.0
Contenido
Introducción
The Nytril Language
........................................................................................................................
5
Basic Syntax
.....................................................................................................................................
6
Crear un nuevo proyecto
................................................................................................................
7
Revision = {Properties + Elements}
.................................................................................................
8
Functions
.......................................................................................................................................
12
The 'each' operator
.......................................................................................................................
16
Namespaces
..................................................................................................................................
17
Numbers
........................................................................................................................................
18
Strings
...........................................................................................................................................
20
Percentages
...................................................................................................................................
21
Dates
.............................................................................................................................................
22
Units
..............................................................................................................................................
23
Currency
........................................................................................................................................
24
Arrays
............................................................................................................................................
25
Ranges
...........................................................................................................................................
27
Classes and Objects
.......................................................................................................................
28
Formateo
Transforms
....................................................................................................................................
31
Charts
............................................................................................................................................
34
Tables
............................................................................................................................................
40
Trees
..............................................................................................................................................
42
Creating a Document
....................................................................................................................
45
Formatting Properties
...................................................................................................................
46
Number Formatting
......................................................................................................................
50
Math Formatting
...........................................................................................................................
53
Paragraph Formatting
...................................................................................................................
59
Image Formatting
..........................................................................................................................
65
Hyperlinks and Tips
.......................................................................................................................
69
Box Formatting
..............................................................................................................................
71
Drawings
.......................................................................................................................................
76
Colors and Fills
..............................................................................................................................
84
MatemƔticas
User defined symbols
....................................................................................................................
89
Algebra
..........................................................................................................................................
89
Statistics
........................................................................................................................................
91
Vectors
..........................................................................................................................................
94
Matrices
........................................................................................................................................
96
Automatic Equation Typesetting
...................................................................................................
97
Local Resources
Processes
.......................................................................................................................................
99
File System
....................................................................................................................................
99
GenƩtica
Bases
...........................................................................................................................................
103
Proteins
.......................................................................................................................................
106
Mutations
....................................................................................................................................
107
PƔgina 5 de
108
Introducción
The Nytril Language
Nytril is a high-level, general purpose programming language. The standard output of a Nytril program is
one or more typeset documents that can be published. This Tutorial document is written entirely in Nytril.
Nytril has a 'C' style, with insignificant white space, strings in double-quotes, expressions separated by a
semi-colon (;), and scope enclosed by curly braces {}. It uses all but one of the standard C operators and flow
statements ('mod' is used for integer modulus instead of %). It supports both dynamic and static typing or a
mix of the two. Namespaces can be created and used to organize symbols. It is an object oriented language
with classes, single-inheritance, virtual functions and templates. Memory is managed, with automatic
garbage collection.
Nytril contains built-in support for creating complex typeset documents, including alignments, tables,
charts, drawings, and complex math layout, in the spirit of
LaT
E
X
. Nytril is not a markup language like HTML
or Markdown, but the grammar has a unique property called 'affinity' that allows the fluid mixing of
calculations and text with a minimum of operators and escapes. Because it is a conventional programming
language, Nytril allows for arbitrarily complex calculations to be performed with the usual mix of classes and
methods, and then inserted inline with the text with minimal punctuation.
Design Philosophy
A guiding principle of Nytril development is the DRY principle in programming (i.e. Don't Repeat Yourself).
To make a large number of similar documents, without repeating information, the data and text must be
separated from the style and the organization of the documents themselves. In this pattern, the documents
are only a temporary representation of the text and data, and they can be discarded and rebuilt from source
automatically, in the same way that an executable program can be rebuilt from source. When this source
changes, the entire corpus of documents is rebuilt from scratch, which guarantees that every document is
always up to date.
By combining the best aspects of programming, markup and data storage languages, Nytril allows technical
document authors, engineers and scientists to build documents that contain embedded data and
calculations quickly and easily. This can be as simple as a quick "what-if" calculation that fits on a sheet of
paper or it can be much more advanced, like technical one-sheets for every item in an inventory of products,
from a set of product facts and narrative.
Nytril source files are UTF-8 text files compatible with Git, and several authors can collaborate on different
parts of the corpus of documents, in the same way that they would collaborate on different parts of a large
software project. Raw information can be stored in Nytril source files in a structured way, minimizing the
need for data to be stored in different formats like JSON and XML. All changes to data and style are tracked
by source control in the same way.
Portability
Nytril is portable across operating systems and CPU architectures. Currently Nytril runs on computers
running Windows 10-11, MacOS 13 and later (x64 and M-series), and Linux (amd64 and arm64). The
compiler, runtime library, layout, and fonts are identical on all platforms. Typesetting may differ
imperceptably on different platforms due to the use of different underlying graphics frameworks.
The compiler
Nytril is a compiled language and the code for an entire nytril program is compiled before any of the
statements are executed. The program is compiled at project load and in the background as the programmer
types. The compiled program resides in memory and is discarded and rebuilt in the background each time
the program is opened or changed. The compile time for a program is usually less than one second.
Introducción
PƔgina 6 de
108
Nytril has a 2-pass compiler. Pass 1 gathers any included files and libraries and then builds namespaces and
class definitions. Pass 2 compiles global and class functions. Two passes allow the programmer to reference
classes and variables before they are declared in code, as in modern C++ variants like C# and Typescript.
Classes and member functions are defined together in one scope, in a single source file.
There are no 'Project Files' in Nytril. Instead, a project's functionality is determined entirely by its main
source file. The compiler simply follows the chain of included files starting with the main file, with redundant
include files being ignored. All symbols are visible to every included file, unless they are marked private.
There is not a single entry point for a Nytril program (i.e. no
main()
function). Once compiled, various
parts of the program can run when called. This is usually in the form of producing typeset output. For
instance, an object can override methods to show itself in a document or a popup tip.
Each program should include a Main.Documents collection that lists one or more document objects. These
are the documents that are available for the program to view on-screen or publish.
A program may also include a Main.Configurations collection. This is a list of variations of the whole
program that the programmer wishes to build for publication. Only one of these is active at a time, and the
programmer may selectively define a namespace for certain configuration properties.
readonly
namespace
Lang
if
(Language
==
Languages
.
English) {
Hello
=
"Hello"
;
}
readonly
namespace
Lang
if
(Language
==
Languages
.
Spanish) {
Hello
=
"Hola"
;
}
readonly
Greeting
=
Lang
.
Hello;
Nytril supports compiling and publishing alternate configurations for different languages, measurment
units and paper sizes. This provides a way to create a set of documents for every reader, without repeating
text or data.
Configurations
You can conditionally build your program with the the Configuration feature. Use Configurations to create
several versions of the same documents that have different global properties such as style, paper size,
measurement units. language and culture. This works directly with the publishing feature, to present each
viewer with a document that is customized for their preferences.
Publishing
Once you have created a set of documents, you can publish all documents, in all configurations in a variety
of output formats in one step. The community edition supports limited publishing to a local drive. The
professional edition supports publishing locally and online in one step. When viewed online, the viewer is
presented with a unique 'sliding-pane' interface that allows them to move easily between documents, make
bookmarks, and share content with others. The presentation feature allows the user to present a document
as an online slideshow.
Basic Syntax
Nytril syntax is broadly similar to 'C' style languages like C#, Java and TypeScript. Literal strings are
delimited by double quotation marks and have a standard syntax for escape characters.
HelloWorld
=
Span
{
"Hello World"
;
"Line\nFeed"
;
"\tTab"
;
" Quotes \"\" are escaped"
;
};
El lenguaje de programación Nytril
Ā®
PƔgina 7 de
108
Hello WorldLine
Feed
Tab Quotes "" are escaped
Outside of quoted text, white space, including newlines and indentation, has no effect on the code.
This tutorial and the included examples use a modified K&R bracing style, but this is a matter of
personal taste.
Spacing
=
Span
{
"White space"
;
/* and comments */
" between "
;
"expressions has no effect. "
;
// Neither do single-line comments
};
White space between expressions has no effect.
Nytril is a two-pass compiler. The first pass gathers up namespace, class and function definitions.
The second pass compiles the bodies of functions. This means that you can reference a function or
variable in a namspace or class before it is defined. This makes it simple to move and reorganize
code.
Variable2
=
Variable1
;
Variable1
=
"A string"
;
A string
To create complex formatted text in an easy way, Nytril introduces the affinity operator. In most
programming languages, two operands must be seperated by a binary operator or else there is a
syntax error. In Nytril, if the compiler encounters two operands without a binary operator between
them, it inserts an invisible binary 'affinity' operator and continues without error. At runtime, the
type of the two operands is assessed and if an affinity exists between the two types, the operation
is executed. If there is no affinity between the types, there is a runtime error. The affinity action
should be intuitive, but you can use an explicit binary operator if you find that it makes the code
clearer.
Affinity
=
Block
{
Paragraph
{
"Line"
;
Bold
};
// + affinity between format objects and revisions
"1"
2;
// + affinity between strings and other objects
"123"
"abc"
;
// + affinity
3
meters
;
// There is a * affinity between numbers and units
};
Line
12
123abc
3Ā meters
Crear un nuevo proyecto
Like all compiled languages, Nytril reads source code stored in plain-text files stored on your computer.
The source code is Unicode, and files are saved in the UTF8 format (unix style \n line endings, without a
byte-order-mark). This makes them interchangeable between Windows, Mac and Linux systems. Nytril works
well with Git and other source-control systems and some Git repository operations are built-in to the IDE
and can be accessed through the
Git
menu.
Nytril has a native source editor with syntax highlighting and multi-level undo/redo, but source files can be
Introducción
PƔgina 8 de
108
edited with any plain-text editor. Each time the Nytril IDE is brought into focus, the opened source files are
checked and reloaded if they have changed.
Nytril does not produce an executable file (like an .exe or .app file). Instead, the code is compiled into
memory in the background any time the code changes. When you exit Nytril there are no residual or
temporary files. When you open Nytril, the last project will load, compile and run automatically.
The typical output of a Nytril program is one or more typeset documents. Most simple programs contain
just one document, but it is easy to create projects that can generate dozens of different documents. To
keep things simple, we will focus on creating a program with a single document.
To make a new program, you must first create a new project and set the path of the 'main' source file.
ā¢
Select the menu
File..New..Project
ā¢
Double-click on a project template.
ā¢
Specify a name for your project.
ā¢
Select OK.
You should see the following on the screen:
Start from scratch
Your project settings are saved automatically and this new project will now be listed under the
Project
menu. You can make changes to the code, and select
Build..Refresh documents
to update the document.
When you switch projects using the
Project
menu, the previous settings and tabs will be restored, and the
project will rebuilt and refreshed automatically.
A key feature of Nytril is that text and figures in the Document can be traced back to source code easily.
Hold down the control-key and click on the text in any document, including this one. The IDE will take you to
the immediate antecedant of that text in the code. That is, the expression that gave rise to that content.
Usually this means a literal string in quotes, but sometimes it can mean a number, date or even an operator
like a '+' sign.
Hold down the control and shift key together, and hover over any part of the document. You will see the
typesetting layout lines that Nytril uses to align text and figures.
A Nytril project is defined entirely by its main source file. As this file is compiled, every other source file will
be added to the project by any
include
statements in the main file, and in turn, by any of the included source
files. There are no separate project files in Nytril, as there are in other development environments. Instead,
all repository and project settings are stored in a single
settings.ini
file on your system. This file contains the
repository and project settings for you on your system, and is not shared in source control.
Revision = {Properties + Elements}
Revisions are the backbone of coding in Nytril. A revision is a collecion of properties and elements inside
curly braces {} that are separated by semi-colons (;}.
A property is the combination of a field name, a colon (:) and a compatible value.
BigText
=
TextHeight
:
16pt;
// A single property
El lenguaje de programación Nytril
Ā®
PƔgina 9 de
108
An element is any other expression, including variables and values returned from function calls,
separated by a ';'. The properties and elements of a revision are computed at runtime, so a revision
"executes" just like a scope in a function.
RevisionWithElements
=
{1; 1
+
2;
Math
.
Sqrt
(4
+
1)};
RevisedBlock
=
Block
RevisionWithElements
;
// Format and Revision joined by affinity
1
3
2,23606797749979
You 'apply' a revision to a formatting object to give it content and properties.
Elements
are placed
in a revision in the order that they are encountered in code.
Properties
, on the other hand, can
appear anywhere inside a revision and have the same effect. In other words, placing the property
before or after any element (or another property) makes no difference. In the code below, the
TextColor property is placed after the 'Text' element, but it still affects the entire revision.
Revision
=
{
"Text"
;
// Element
TextColor
:
Colors
.
Red
;
// Property
4
*
(1
+
2);
// Element
};
Text
12
A revision acts on the format object to its left, without modifying it. In the code below, a Span is
revised by an inline revision - the lines of code between curly braces {}. It is critical to understand
that although this example revision comprises several lines of code, it is a single revision object.
This revision object is then applied to the Span to add content.
FirstSum
=
Span
{
// Inline revision defined over the next 10 lines of code
var
x
;
// Variable declaration (not added)
x
=
9;
// Variable assignment (not added)
++
x
;
// Increment variable (not added)
x
+=
2;
// Increment/assignment (not added)
// White space (not added)
null
;
// null (not added)
x
+
5;
// Expression (added)
" is the sum of 5 + "
;
// Constant (added)
x
;
// Variable (added)
}
// End of revision
;
// End of expression
17 is the sum of 5 + 12
Each single expression (separated by ';') inside the curly braces '{}' is evaluated, and then added to the
revision. But there are two important exceptions. The following types of expressions (determined at
runtime) are NOT added to a revision:
ā¢
The value
null
, whether literal or as a return value from a function.
ā¢
A variable declaration / assignment expression.
The latter comes in handy when you need to create 'helper' variables inside a revision to do calculations or
make the code easier to understand.
Revisions can be added together to create a new revision that combines the elements and
properties of both (in left-right order). It is important to remember that adding revisions has no
effect on the revisions being added. In the code below the previous revised span gets some text
Introducción
PƔgina 10 de
108
added at the end.
NextSum
=
FirstSum
{
// Add old revision to new revision in {}
", and then some. "
;
// New element
};
17 is the sum of 5 + 12, and then some.
A revision can contain properties as well as elements. Here the previous span is revised to change
its formatting properties.
FormattedSpan
=
NextSum
{
BigText
;
// References to property variables work the same as inline properties
TextColor
:
Colors
.
Red
;
};
17 is the sum of 5 + 12, and then some.
A revision can also revise existing properties. Again, this has no effect on the original, but instead
creates a new revision that substitutes the properties of the right-hand revision for those of the
left.
ChangedSpan
=
FormattedSpan
{
TextColor
:
Colors
.
Blue
;
// Change the TextColor property that was added above
TextWeight
:
TextWeights
.
Bold
;
// Add a new property
};
17 is the sum of 5 + 12, and then some.
A revision can contain conditional statements that optionally add elements or properties.
ScoreText
(
score
)
=
Span
{
"A score of
{0}
will recieve the grade "
(
score
);
if
(
score
>=
90) {
TextColor
:
Colors
.
Green
;
"A"
;
}
else
if
(
score
>=
80) {
TextColor
:
Colors
.
Blue
;
"B"
;
}
else
if
(
score
>=
70) {
TextColor
:
Colors
.
Yellow
;
"C"
;
}
else
if
(
score
>=
60) {
TextColor
:
Colors
.
Orange
;
"D"
;
}
else
{
TextColor
:
Colors
.
Red
;
"F"
;
}
"."
;
};
TheScores
=
Block
{
// Call the function above
ScoreText
(95);
ScoreText
(83);
ScoreText
(55);
El lenguaje de programación Nytril
Ā®
PƔgina 11 de
108
};
A score of 95 will recieve the grade A.
A score of 83 will recieve the grade B.
A score of 55 will recieve the grade F.
A revision can contain a
for
,
foreach
,
do
or
while
loop. In this situation, the expressions inside the
loop acts the same way as expressions inside a revision, except they are repeated each time the
loop repeats. This allows revisions to contain a programmable number of elements.
ShowSet
(
count
)
=
Span
{
"The set has
{0}
members ["
(
count
);
// Repeat 'count' times
for
(
var
i
=
1;
i
<=
count
;
++
i
) {
if
(
i
>
1)
", "
;
// Add this element
i
;
// Add this element
}
"]."
;
};
TheSets
=
Block
{
ShowSet
(2);
ShowSet
(5);
ShowSet
(10);
};
The set has 2 members [1, 2].
The set has 5 members [1, 2, 3, 4, 5].
The set has 10 members [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
Certain properties can add implicit elements to a revision. The properties
Begin
,
End
,
Separator
,
PairSeparator
, and
LastSeparator
act after the revision gets all of its explicit elements. This allows
you to create formatting styles that insert elements in certain places.
CommaList
=
Span
{
Begin
:
"["
;
// Add this element at the beginning
End
:
"]."
;
// Add this element at the end
Separator
:
", "
;
// Add this element between each element
PairSeparator
:
" and "
;
// Use as a separator only if there are 2 items
LastSeparator
:
", and "
;
// Use this as the last separator
};
ShowArray
(
count
)
=
CommaList
{
for
(
var
i
=
1;
i
<=
count
;
++
i
)
i
;
// Add this element
};
AllArrays
=
Block
{
ShowArray
(1);
ShowArray
(2);
ShowArray
(4);
};
[1].
[1 and 2].
[1, 2, 3, and 4].
Important:
If an array is an element of a revision then all of the elements of the array are added, as
Introducción
PƔgina 12 de
108
if they were placed directly in the revision. This may seem counter-intuitive at first, but this
convention makes it easy to add iterated content.
ArrayElements
=
Span
{
"Elements are "
;
Span
{
Separator
:
CommaSpace
;
[1, 2, 3];
// Add 3 elements instead of 1 array
4
..
10
step
1;
// This expression is the same as [4, 5, 6, 7, 8, 9, 10]
};
};
Elements are 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
You can use the rules of revisions to construct layers of related formatting styles. By stacking and
combining revisions, heirarchical style dictionaries can be created easily in a manner that is similar
to CSS or to the way word processors allow styles to inherit from each other and override
properties.
BaseStyle
=
Paragraph
{
TextFamily
:
TextFamilies
.
Calibri
;
TextHeight
:
11pt;
};
BodyStyle
=
BaseStyle
{
FirstIndent
:
16pt;
};
HeaderStyle
=
BaseStyle
{
TextFamily
:
TextFamilies
.
TimesNewRoman
;
TextHeight
:
120%;
Bold
;
Underline
;
SpaceAfter
:
8pt;
};
Document
=
Block
{
HeaderStyle
{
"Introduction"
;
};
BodyStyle
{
"The rain in Spain lies mainly on the plane."
;
};
};
Introduction
The rain in Spain lies mainly on the plane.
Functions
There are some important syntactic differences between Nytril and other C-style languages regarding
function definitions, consistent with the goal of having a minimum of operators to increase readability.
ā¢
Nytril allows, but does not require, an empty set of parenthesis () after functions that take no
parameters, either on declaration or at the call site.
ā¢
Nytril has an optional inline function declaration syntax that uses an equal (=) sign and a single
expression, in lieu of a full {} scope with a return statment.
ā¢
A function that returns a value does not need to have a declared return type.
El lenguaje de programación Nytril
Ā®
PƔgina 13 de
108
If the return type declaration is missing, the return type is assumed to be 'any'.
A void return type means that the function returns no value.
ā¢
Nytril requires an '@' operator whenever a function reference is used as a closure.
ā¢
Nytril allows global functions that do not belong to a class and have no 'this' pointer, although they
can be defined inside of a namespace.
Functions can be declared in the global scope or inside a namespace.
F1
(
x
)
=
x
+
1;
// F1 defined globally
N1
.
F2
(
x
)
=
x
+
2;
// F2 defined inside the namespace N1
namespace
N2
{
F3
(
x
)
=
x
+
3;
// F3 defined inside the namespace N2
}
If a global function is marked as readonly, then the function is run the first time it is called
anywhere in the program, and the return value is cached. If the function is called again anywhere,
the cached value from the first run is returned immediately. This is useful when loading large
constant values such as images or the results of database queries or REST calls, where the intention
is usually to retrieve information once and then use the same copy for many calculations.
ComplexSlowQuery
{
// Slow process...
return
0;
}
readonly
Data
=
ComplexSlowQuery
;
// Run only once
readonly
Cost
=
Data
.
Quantity
*
Data
.
Price;
// Use like a variable
Functions can be declared without a specific (i.e. 'any') return type. This allows the flexible use of an
abstract expression to return different types of results.
SquareNumber
(
x
) {
return
x
*
x
;
}
ShowSquares
=
Block
{
SquareNumber
(4);
SquareNumber
(
Symbol
(
"x"
));
};
16
x
2
Note that each separate expression is terminated by a semicolon (;). If the statement is followed by
a closing brace '}' then the ';' is optional. Branch statements (such as
if
,
else
and
foreach
), class
definitions and regular function blocks are not terminated by a semicolon.
ExampleFunction
{
var
s
=
"Statements are terminated by a semicolon"
;
return
s
+
";"
;
}
Statements are terminated by a semicolon;
Functions can also be declared with a return type. This allows the compiler to more easily check for
common errors. Furthermore, if the returned value is an object, a return type on the function will
increase performance and compile-time error checking. This is because the calling expression
knows the class of the return value, it can do a compile-time checking/binding of any members
Introducción
PƔgina 14 de
108
referenced on that object.
int
TypedFunction
{
return
7;
// Must match return type of function
}
7
A function can be declared using a direct "=" syntax. The code for the function can be on more than
one source line, but must be a single expression terminated by a ';'. This type of function does not
run faster, but the more compact representation might be easier to understand.
Power
=
3;
Cube
(
x
)
=
x
^
Power
;
OneThousand
=
Cube
(10);
1000
Unlike other C-Style languages, a function without parameters does not require an empty set of
parens '()' either on declaration or when it is used. This can cause some confusion to programmers
used to the other convention. It is important to remember that although a function taking no
parameters 'looks' like a simple variable access, it is a function call that is executed each time it is
referenced (unless it is marked
const
or it is a global function marked as
readonly
).
RandomNumber
=
Math
.
Random
(1
..
100);
// Takes no parameters and returns a ramdom number
ShowRandom
=
Paragraph
{
Separator
:
CommaSpace
;
for
(
int
i
=
0;
i
<
10;
++
i
)
RandomNumber
;
// Called 10 times in a row, generating a new value each time
};
69, 39, 71, 58, 94, 76, 49, 96, 44, 4
If a global or static function without parameters is declared using the keyword
readonly
, the return
value is cached when it is evaluated for the first time in the program's execution. After that, the
same value is returned without re-evaluation. If the function is called more than once, this will
result in speed improvements. Use this option with care, as it can lead to confusion, but there are
many scenarios where readonly functions are the right choice. For instance, when loading an image
from a file or loading data from a database, you may wish to read the data once, and refer to it
many times throughout your code. This feature allows you to accomplish that goal without creating
another variable to hold the cached value.
readonly
Measurement
=
8.65
*
Math
.
Sin
(
Math
.
Random
(0
..
90)
degrees
);
// Run once
ShowMeasurements
=
Paragraph
{
Separator
:
CommaSpace
;
for
(
int
i
=
0;
i
<
3;
++
i
)
Measurement
;
// Function body executed only once, after which the same value is returned
};
0,7538971747672432, 0,7538971747672432, 0,7538971747672432
Values that are known at compile time can be declared using the keyword
const
. These values are
substituted directly into the code during compilation. This speeds up runtime performance and
prevents accidental modification of the symbol's value.
El lenguaje de programación Nytril
Ā®
PƔgina 15 de
108
const
g
=
9.8m
per
second
^
2;
// Calculated at compile time
ShowGravity
=
Paragraph
{
TextAbbreviate
:
true
;
g
;
};
9,8Ā
m
s
2
Global variables can be declared using the keyword
var
. These variables can be changed throughout
the execution of the program.
var
Number
=
1;
ShowNumbers
=
Block
{
"Number = "
+
Number
++
;
"Number = "
+
Number
;
};
Number = 1
Number = 2
Variables can be declared with a type, which can help the compiler catch common errors and
possibly improve performance.
var
double
TypedNumber
=
2.7;
ShowTypedNumber
=
Paragraph
{
"Number = "
;
TypedNumber
;
};
Number = 2,7
A feature called 'affinity' allows for more natural and compact expression of common pairs of
values. Values placed side-by-side without an operator in-between them are combined using an
implied binary affinity operator. Each pair of values will be joined based on their actual types at
runtime. As shown below, the first line shows a normal expression using the '+' operator. Here, as
you would expect, the '4' and '1000' are added together. On the next line, the '4' and 'inches' are
placed together without an operator between them. At runtime, the compiler determines that an
integer and a unit should be multiplied together.
ShowAffinity
=
Block
{
Paragraph
{
"Numbers summed: "
;
4
+
1000;
// Using the '+' operator
};
Paragraph
{
"Numbers multiplied: "
;
4
inches
;
// Using an implied 'affinity' operator
};
};
Numbers summed: 1004
Numbers multiplied: 4Ā inches
Other examples are show below.
AffinityExample
=
Block
{
Introducción
PƔgina 16 de
108
"String-"
"String"
;
// Append
"Example "
2;
// Append
3
meters
;
// Multiply
CiteOptions
.
AddSuffix
CiteOptions
.
ShowDate
;
// Binary or
};
String-String
Example 2
3Ā meters
ShowDate AddSuffix
The 'each' operator
The
each
operator is used to call a function with a parameter, once for every item in an array. The
resulting expression is an array of function return values.
Square
(
x
)
=
x
*
x
;
SquareNumbers
=
Paragraph
{
Separator
:
CommaSpace
;
Square
(
each
[1, 2, 3, 4]);
};
1, 4, 9, 16
If a function has more than 1 parameter, the
each
operator can be used on more than 1 argument.
This raises the dimension of the output array.
Power
(
x
,
power
)
=
x
^
power
;
PowerNumbers
=
Block
{
var
result
=
Power
(
each
[2, 3, 4],
each
[1, 2, 3]);
// Returns 2-d array
foreach
(
var
r
in
result
) {
Paragraph
{
Separator
:
CommaSpace
;
r
;
}
}
};
2, 4, 8
3, 9, 27
4, 16, 64
Most unary and binary operators can also be used in conjunction with the
each
operator to provide
a very compact expression. The code below shows the number 2 being raised to the power of an
array of numbers using the
^
power operator.
PowerVector
=
Vector
.
Convert
(2
^
(
each
1
..
8));
[2, 4, 8, 16, 32, 64, 128, 256]
If you use an
each
expression on both sides of a binary operator, you get a 2-dimensional array
result. The code below shows an array of numbers being raised to the power of another array of
numbers using the
^
power operator and the results are converted to a matrix.
PowerMatrix
=
Matrix
.
Convert
((
each
[2, 3, 4])
^
(
each
[2, 3, 4]));
El lenguaje de programación Nytril
Ā®
PƔgina 17 de
108
4
8
16
9
27
81
16
64
256
Namespaces
A namespace is a collection of global variables, functions and classes. A namespace can be declared
using the keyword
namespace
. If the namespace does not already exist, it will be created. The
variables declared within the space will be added in the order encountered.
namespace
Products
{
Apple
=
"Gala"
;
Lemon
=
"Meyer"
;
}
ShowProducts
=
Block
{
Products
.
Apple
;
Products
.
Lemon
;
};
Gala
Meyer
Namespaces can also be declared with an indentifier followed by a dot and then the identifier to
add to that namespace. As in the case of the of the explicity declared namespace, a namespace will
be created if it does not already exist.
Handbags
.
LouisVuitton
=
"Louis Vuitton"
;
// Added to the existing 'Handbags' namespace above
namespace
Handbags
{
Gucci
=
"Gucci"
;
Prada
=
"Prada"
;
}
ShowAllHandbags
=
Block
{
Table
(0.5,
null
, [1", 1"]) {
Row
{
Background
:
80%;
"Variable"
;
"Value"
;
};
foreach
(
var
a
in
attribute
Handbags
)
Row
{
a
.
Name;
a
.
Value;
}
}
};
Variable
Value
LouisVuitton
Louis Vuitton
Gucci
Gucci
Prada
Prada
Namespaces can be used to accumulate data into a common container. The container can then be
used to make charts, tables or do other calculations.
namespace
Revenue
{
Year1
=
20_000_000;
Year2
=
670_000_000;
Introducción
PƔgina 18 de
108
Year3
=
1220_000_000;
}
ShowRevenue
=
Chart
(3", 2") {
var
revenue
=
attribute
(
Revenue
)
.
Children
;
ChartType
:
ChartTypes
.
Column
;
XLabel
:
Bold
"Year"
;
XAxis
:
ChartAxis
{
(
each
revenue
)
.
Name
;
};
ValueLabel
:
Bold
"Revenue\n(Millions)"
;
ValueAxis
:
ChartAxis
;
ChartSeries
{
foreach
(
var
r
in
revenue
)
new
DataPoint
(
each0
,
r
.
Value
*
0.000001);
};
};
Year
Revenue
(Millions)
Year1
Year2
Year3
0
200
400
600
800
1000
1200
1400
Numbers
An integer is a simple sequence of decimal digits without a decimal point
IntegerValue
=
42;
42
An unsigned integer is an integer that cannot have a negative value
UnsignedValue
=
33U;
33
Here is a list of the numeric types that can be specified with a special suffix
NumberTypeList
=
Block
{
typeof
(2);
typeof
(2L);
typeof
(2U);
typeof
(2UL);
typeof
(2.0F);
typeof
(2.0D);
typeof
(2.0M);
};
int
long
El lenguaje de programación Nytril
Ā®
PƔgina 19 de
108
uint
ulong
float
double
decimal
Hexadecimal values can be specified by preceeding the number with 0x
HexValue
=
0x15;
21
Binary values can be specified by preceeding the number with 0b
BinaryValue
=
0b1101;
13
Real numbers are a sequence of decimal digits containing a decimal point
RealValue
=
3.14;
3,14
Ratios of integers can be created using the
over
operator.
OneThird
=
1
over
3;
FractionSum
=
OneThird
+
5
over
6;
1
1
6
Operations that mix real and fractional or integer values will be converted to real numbers
DerivedValue
=
RealValue
*
FractionSum
;
3,6633333333333336
Real numbers can be formatted to the desired number of decimal places
FormattedValue
=
{
TextDigits
:
3}
DerivedValue
;
3,663
Digit groups for large numbers can be seperated using an underscore
_
SegmentedValue
=
2_164_843;
2164843
Imaginary numbers can be expressed in a variety of forms
Imaginary1
=
Symbolic
.
Sqrt
(
-
1)
+
1i
+
Math
.
I
+
(
-
1)
^
(1
over
2);
4
i
Imaginary numbers can be added
Introducción
PƔgina 20 de
108
Imaginary2
=
3i;;
ISum
=
Imaginary1
+
Imaginary2
;
7
i
Complex numbers are also supported, and real and imaginary parts are automatically aggregated
Complex1
=
3i
+
2i
+
5
+
3;
8
+
5
i
Complex multiplication and powers are supported
Complex2
=
Complex1
*
(2i
+
4);
22
+
36
i
Get the real part of a complex number with the
RealPart
function.
Real2
=
Math
.
RealPart
(
Complex2
);
22
Get the imaginary part of a complex number with the
ImaginaryPart
function.
Imaginary3
=
Math
.
ImaginaryPart
(
Complex2
);
36
Get the modulus of a complex number with the
Abs
function.
ComplexModulus
=
Math
.
Abs
(
Complex2
);
445
2
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
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
Strings can be concatenated by simply placing them together or by using using the
+
operator.
JoinString
=
SimpleString
", and some more"
+
", and some more still"
;
El lenguaje de programación Nytril
Ā®
PƔgina 21 de
108
This is an array of characters, and some more, and some more still
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}
"
Message is not a string, but is instead a function taking 1 argument.
FileError
=
Message
(
"file.txt"
);
There is an error in "file.txt"
The sections can be out of order in the string, but they will still correspond to the order of the
arguments
S2
Warning
=
"Please wait
{1}
seconds for
{0}
"
;
WaitWarning
=
Warning
(
"the report to generate"
, 5);
Please wait 5 seconds for the report to generate
The arguments to a string format can be any type, including equations or pictures
S2
RootFormat
=
"The inverse square root of
{0}
is
{1}
"
;
RootFunction
(
x
)
=
RootFormat
(
x
, 1
/
Symbolic
.
Sqrt
(
x
));
RootArray
=
Span
{
Separator
:
", "
;
RootFunction
(
each
[2,
Symbol
(
"x"
),
"two"
])};
The inverse square root of 2 is
1
2
, The inverse square root of
x
is
1
x
, The inverse square root of two is
1
two
Percentages
Percentages are specified using the
%
operator.
BaseRate
=
10%;
10%
Percentages can be added together like normal numbers
BonusRate
=
4%;
TotalRate
=
BaseRate
+
BonusRate
;
14,000000000000002%
Percent values can be multiplied to yield a plain numeric value
Sales
=
$
1000;
Payment
=
TotalRate
*
Sales
;
$
140,00
Some properties behave differently when a percent value is used.
Introducción
PƔgina 22 de
108
BigText
=
Span
{
TextHeight
:
200%;
// Percentage of existing TextHeight
TextColor
:
50%;
// Gray scale
"Big Text"
;
};
Big Text
Dates
A
DateTime
is specified using #YYYY-M-D:H:M:S# in source code.
const
DayOfBirth
=
#2016-1-31#
;
// YYYY-MM-DD
2016-01-31
A constant date can be specified directly in source code. A date value carries with it an indicator of
the precision of its specification
const
TimeOfBirth
=
#2016-01-31 03:10:37.513#
;
2016-01-31 03:10:37,513
Dates can be formatted with the field
TextFormat
FormatDate
=
Paragraph
{
DateTime
.
Now
;
TextFormat
:
"dddd, MMMM dd, yyyy"
;
};
miƩrcoles, octubre 28, 2026
Dates can be operated on with time units
TwinBirth
=
TimeOfBirth
+
1
minute
+
41
seconds
;
2016-01-31 03:12:18,513
A time span is specified with
TimeSpan
TimeInHospital
=
new
TimeSpan
(2, 4);
2d04:00:00,
Time spans can be added to dates
FirstDayHome
=
TwinBirth
+
TimeInHospital
;
2016-02-02 07:12:18,513
Subtracting two dates gives a TimeSpanClass
TimeDifference
=
#2016-1-31 6:10:37.5#
-
#2012-1-31#
;
1461d
El lenguaje de programación Nytril
Ā®
PƔgina 23 de
108
TimeSpanClass members can be used to extract real numeric values for various units of time
Difference
=
Block
{
"
{0}
Years"
(
TimeDifference
.
Years);
"
{0}
Days"
(
TimeDifference
.
Days);
"
{0}
Hours"
(
TimeDifference
.
Hours);
"
{0}
Minutes"
(
TimeDifference
.
Minutes);
"
{0}
Seconds"
(
TimeDifference
.
Seconds);
};
4,000704663852765 Years
1461,2573784722222 Days
35070,177083333336 Hours
2104210,625 Minutes
126252637,5 Seconds
Units
Measurment units are handled natively
Distance
=
16";
16Ā inches
You can convert between compatible units using the
tounit
operator.
MetricDistance
=
Distance
tounit
centimeters
;
40,64Ā centimeters
Common units can be combined with a literal number using a special suffix.
ViewCommonUnits
=
Block
{
foreach
(
var
u
in
CommonUnits
) {
Paragraph
(
null
, [0.9"]) {
SourceSelection
(
u
);
"\t = "
;
u
;
}
}
};
4"
= 4Ā inches
4.25"
= 4,25Ā inches
6'
= 6Ā feet
6'2
= 74Ā inches
6'3"
= 75Ā inches
6'3.5
= 75,5Ā inches
6'3.25"
= 75,25Ā inches
5g
= 5Ā grams
5kg
= 5Ā kilograms
5cg
= 5Ā centigrams
5mg
= 5Ā milligrams
5l
= 5Ā liters
5ml
= 5Ā milliliters
6.25m
= 6,25Ā meters
5km
= 5Ā kilometers
5mm
= 5Ā millimeters
Introducción
PƔgina 24 de
108
5cm
= 5Ā centimeters
5ft
= 5Ā feet
5in
= 5Ā inches
5mi
= 5Ā miles
5pt
= 5Ā pts
5px
= 5Ā pixels
Values with different, but compatible, units can be added together
LongerDistance
=
3"
+
25.4cm
+
1';
25Ā inches
Units can be multiplied together to form units of higher dimension
Area
=
Distance
*
2
yards
;
Volume
=
Area
*
14.0"
tounit
centimeters
^
3;
264.291Ā centimeters
3
Common conversions of higher dimension units are handled in the same way
LiquidMeasure
=
Volume
tounit
gallons
;
69,8181818182Ā gallons
Multiplications factor out the correct units
WaterDensity
=
1
kilogram
per
liter
;
LiquidWeight
=
WaterDensity
*
Volume
tounit
pounds
;
583Ā pounds
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
Currency
Monetary quantities are supported natively
PocketChange
=
47
Ā¢
;
TotalChange
=
PocketChange
+
3
Cents
+
$
0.05;
55Ā¢
Compatible currency values can be added together
WalletCash
=
$
12;
TotalMoney
=
(
WalletCash
+
TotalChange
)
tounit
Dollars
;
$
12,55
El lenguaje de programación Nytril
Ā®
PƔgina 25 de
108
Simple accruals can be calculated with a user-defined function
Compound
(
amount
,
rate
,
times
) {
while
(
times
>
0) {
amount
+=
amount
*
rate
;
--
times
;
}
return
amount
;
}
Payments
=
Block
{
TextGroup
:
true
;
Compound
(
$
200_000, 4.1%, 5);
};
$
244.502,69
Arrays
An array is an ordered container of objects
[0, 1, 2, 3,
x
,
y
, A, B, C,
Ļ
2
,
i
]
Get the value of a child in the array using a zero-based index inside square brackets
[]
ArraySub
=
Numbers
[1];
1
A slice of the start of the array is obtained by putting a right range inside square brackets
[]
[0, 1, 2, 3]
A negative subscript represents the index obtained by subtracting the subscript from the length of
the array
[0, 1, 2, 3,
x
,
y
, A, B, C]
A slice of the middle of the array is obtained by putting a full range inside square brackets
[]
[2, 3,
x
,
y
]
A slice of the end of the array is obtained by putting a left range inside square brackets
[]
[3,
x
,
y
, A, B, C,
Ļ
2
,
i
]
An arbirtary slice of a array can be obtained by putting an array of ranges inside square brackets
[]
[0, 1, 3,
y
, A,
i
]
Return a new array missing elements from the target array with the
Remove
function.
Introducción
PƔgina 26 de
108
[0,
x
,
y
, A, B, C,
Ļ
2
,
i
]
Delete elements from an index to the end of the array by omitting the second argument
[0, 1, 3,
x
,
y
, A, B, C,
Ļ
2
,
i
]
Negative numbers in the range represent the number of items from the end of the array
[0, 1, 2, 3,
x
,
y
, A, B]
Find items in a array that match a value with the
FindIndex
function.
[0]
Find the indexes of items in an array that match criteria by specifying a boolean function that takes
1 argument
[1
..
2, 5]
Create an array of items that match a predicate with the
FindSlice
function.
[10, 7, 8]
Arrays can be sorted in ascending or descending order with the
ToSortedArray
function.
[2, 4, 5, 7, 8, 10]
Change the sort direction by setting the descending parameter to true
[10, 8, 7, 5, 4, 2]
Use a comparison function to sort complex structures
readonly
ValueClass
[]
Structures
=
[
new
(3),
new
(5),
new
(2),
new
(0),
new
(1),
];
int
CompareStructure
(
ValueClass
a
,
ValueClass
b
)
=
a
.
Value
.
Compare
(
b
.
Value
);
readonly
SortedStructures
=
Structures
.
ToSortedArray
(
false
,
@
CompareStructure
);
ShowStructureArray
=
Paragraph
{
Separator
:
", "
;
SortedStructures
;
};
0, 1, 2, 3, 5
El lenguaje de programación Nytril
Ā®
PƔgina 27 de
108
An array can contain data of all types, including variables and formulas
[2,
1
3
,
Ļ
,
x
2
Ā +Ā
y
2
a
]
An array can include other arrays
[A simple sentence, 0, 1, 2, 3,
x
,
y
, A, B, C,
Ļ
2
,
i
, 2,
1
3
,
Ļ
,
x
2
Ā +Ā
y
2
a
]
The contents of two arrays can be joined together to make a larger array using the
+
operator.
[0, 1, 2, 3,
x
,
y
, A, B, C,
Ļ
2
,
i
, 2,
1
3
,
Ļ
,
x
2
Ā +Ā
y
2
a
]
You can create another array which contains the result of the operation performed on each item in
the array using the
each
operator.
[3,
1
1
3
,
Ļ
Ā +Ā
1
,
x
2
Ā +Ā
y
2
a
Ā +Ā
1
]
This works for all operators and can be daisy-chained to apply to more than one operation
[
4
a
2
,
1
9
a
2
,
(
Ļ
a
)
2
,
x
2
Ā +Ā
y
2
]
Function arguments can also be expanded using the
each
operator.
[
8
,
1
27
,
Ļ
3
,
x
2
Ā +Ā
y
2
a
3
]
Ranges
A range is an ordered, inclusive pair of values using the
..
operator.
SmallRange
=
1
..
5;
1
..
5
A range can also use variables for the min or max values
Min
=
1;
Max
=
5;
MinMax
=
Min
..
Max
;
1
..
5
An array can be created with a range using the
step
operator.
[1, 3, 5, 7, 9, 10]
Introducción
PƔgina 28 de
108
Make the array enumerate backwards by using a negative step
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Non-numeric arrays can be created from a range, as long as the range limits can be compared
[
x
,
x
Ā +Ā
1
,
x
Ā +Ā
2
,
x
Ā +Ā
3
,
x
Ā +Ā
4
,
x
Ā +Ā
5
]
Exclude the low end of the range using the
>..
operator.
[2, 3, 4, 5]
Exclude the high end of the range using the
..<
operator.
[1, 2, 3, 4]
A slice of an array can be created using a range
[A, B, C]
A low open range can be used to specify the beginning of an array
[A, B, C, D]
A high open range can be used to specify the end of an array
[D, E, F, G]
Negative numbers denote the distance from the end of the array
[E, F, G]
A slice can include an arbitrary array of indices and ranges
[A, B, C, E, F, G]
Classes and Objects
Class definitions can be used for a more formal approach to design. A class may have 1 special
function called "Constructor" which initializes the members.
class
LocationClass
{
var
X
,
Y
;
Constructor
(
x
,
y
) {
X
=
x
;
Y
=
y
;
}
override
GetLayoutSpan
=
Span
{
X
;
CommaSpace
;
Y
;
};
El lenguaje de programación Nytril
Ā®
PƔgina 29 de
108
}
ShowObjects
=
Block
{
var
p1
=
new
LocationClass
(1, 2);
// Constructor called here
var
p2
=
new
LocationClass
(1, 2);
// ..
p1
;
// LocationClass.GetLayoutSpan called here
p2
;
// ..
};
1, 2
1, 2
A class may inherit one other class and add members and methods.
class
CircleClass
:
LocationClass
{
var
Radius
;
Constructor
(
x
,
y
,
r
) {
super
.
Constructor
(
x
,
y
);
Radius
=
r
;
}
override
GetLayoutSpan
=
Span
{
"("
;
super
.
GetLayoutSpan
;
")["
;
Radius
;
"]"
;
};
}
SomeObjects
=
[
new
LocationClass
(1, 2),
new
CircleClass
(4, 5, 8)];
ShowObjectArray
=
Block
{
SomeObjects
;
};
1, 2
(4, 5)[8]
You can add custom left and right affinity between objects of different types to make the creation
of compound data types more intuitive.
class
BaseClass
{
var
Name
;
Constructor
(
name
) {
Name
=
name
;
}
static
operator
Affinity
(
BaseClass
b
,
int
number
) {
return
new
CompoundClass
(
b
,
number
);
}
static
operator
Affinity
(
int
number
,
BaseClass
b
) {
return
new
GroupClass
(
new
CompoundClass
(
b
),
number
);
}
override
GetLayoutSpan
=
Name
;
}
class
CompoundClass
{
var
BaseClass
Base
;
var
int
Number
;
Constructor
(
BaseClass
b
,
int
n
=
0) {
Base
=
b
;
Number
=
n
;
Introducción
PƔgina 30 de
108
}
static
operator
Affinity
(
int
number
,
CompoundClass
c
) {
return
new
GroupClass
(
c
,
number
);
}
override
GetLayoutSpan
=
Number
>
0
?
Base
sub
Number
:
Base
;
}
class
GroupClass
{
var
CompoundClass
Compound
;
var
int
Number
;
Constructor
(
CompoundClass
c
,
int
n
=
0) {
Compound
=
c
;
Number
=
n
;
}
override
GetLayoutSpan
{
if
(
Number
>
0) {
return
Nary
{
PreUpper
:
Number
;
Operator
:
Span
{
"("
;
Compound
;
")"
};
};
}
return
Compound
;
}
}
CompoundTypes
=
Block
{
var
b
=
new
BaseClass
(
"B"
);
// Make a base
var
c
=
b
2;
// Make a compound from the base
var
g
=
3
c
;
// Make a group from the compound
Table
(
null
,
null
, [1", 1"]) {
Row
{
"Base"
;
b
};
Row
{
"Compound"
;
c
};
Row
{
"Group"
;
g
};
};
};
Base
B
Compound
B
2
Group
(B
2
)
3
PƔgina 31 de
108
Formateo
Transforms
An affine 2D transform is represented by a sparse 3x3 matrix (3 of the elements are zero)
m11
m12
0
m21
m22
0
x
y
0
The matrix is commonly represented more compactly as:
[m11 m12 m21 m22 x y]
The following shows mirror transforms about the origin
Mirror - X
[-1, 0, 0, 1, 0, 0,]
Mirror - Y
[1, 0, 0, -1, 0, 0,]
You can use other functions for common transforms like translation, rotation, scaling and skewing.
RotateCanvas
=
Canvas
(1", 0.5",
new
Edge
(0.5pt)) {
Canvas
{
TextHeight
:
14pt;
Transform
:
Transform
.
Rotate
(20
degrees
)
Transform
.
Translate
(30, 10);
"Rotate"
}
};
Rotate
All angles are specified in radians. Convert from degrees to radians using the
degrees
operator..
Angle
=
90
degrees
;
1,5707963267948966
Below is a list of common transforms and their effects.
Formateo
PƔgina 32 de
108
public
static
Transform
Translate
(
x
,
y
=
null
)
=> [1 0 0 1 x y]
Translate(10, 10)
[1, 0, 0, 1, 10, 10,]
Translate(-10, 10)
[1, 0, 0, 1, -10, 10,]
Translate(10, -20)
[1, 0, 0, 1, 10, -20,]
Translate(-10, -20)
[1, 0, 0, 1, -10, -20,]
public
static
Transform
Scale
(
x
,
y
=
null
)
=> [x 0 0 y 0 0]
Scale(0,5, 0,75)
[0,5 0, 0, 0,8 0, 0,]
Scale(0,75, 0,5)
[0,8 0, 0, 0,5 0, 0,]
Scale(0,5, 1,5)
[0,5 0, 0, 1,5 0, 0,]
Scale(1,5, 0,5)
[1,5 0, 0, 0,5 0, 0,]
public
static
Transform
Rotate
(
double
angle
)
=> [cos(angle) size(angle) -
sin(angle) cos(angle) 0 0]
Rotate(30 degrees)
[0,9 0,5 -0,5 0,9 0, 0,]
Rotate(-30 degrees)
[0,9 -0,5 0,5 0,9 0, 0,]
public
static
Transform
Skew
(
x
,
y
=
null
)
=> [1 tan(x) tan(y) 1 0 0]
Skew(20, 10)
[1, 0,4 0,2 1, 0, 0,]
Skew(-20, -10)
[1, -0,4 -0,2 1, 0, 0,]
Transforms can be combined by listing them together, but the order is significant. Applying the
El lenguaje de programación Nytril
Ā®
PƔgina 33 de
108
same list of transforms in a different order will yield different results.
Start
Translate
Rotate
Scale
Scale
Rotate
Translate
Set the
TransformFit
field to
true
to add an additional translation that brings a figure back to the
origin of its container. This is handy for chart legends, and picture rotations. It has the same effect
as rotating the object about its center, rather than its upper left corner.
RotateFit
(
name
,
fit
)
=
Canvas
(1", 0.75",
new
Edge
(0.5pt, 0, 80%)) {
Margin
:
PadR
(20pt);
Canvas
{
TextHeight
:
14pt;
Transform
:
Transform
.
Rotate
(75
degrees
);
TransformFit
:
fit
;
name
;
}
};
ShowFitComparison
=
Paragraph
{
HBox
{
RotateFit
(
"Normal"
,
false
);
RotateFit
(
"Fit"
,
true
);
}
};
Normal
Fit
Use the
Transform
field to apply a transform to any element.
BackwardsCanvas
=
Canvas
{
TextHeight
:
20pt;
Transform
:
new
Transform
(
-
1, 0, 0, 1, 0, 0);
TransformFit
:
true
;
"Backwards"
};
Backwards
Formateo
PƔgina 34 de
108
Use a different transform to flip the canvas vertically.
UpsideDownCanvas
=
Canvas
{
TextHeight
:
20pt;
Transform
:
new
Transform
(1, 0, 0,
-
1, 0, 0);
TransformFit
:
true
;
"Upside Down"
};
Upside Down
Use the
ClipPath
to set the clipping path of the canvas or frame
ClippedText
=
Canvas
{
var
r
=
new
Rect
(
new
(15pt),
new
(210pt, 35pt));
Canvas
{
TextHeight
:
50pt;
"Clipped Text"
;
ClipPath
:
r
;
};
Shape
(
null
) {
RectanglePath
(
r
)
};
};
Clipped Text
Clipping paths can be set to be figures of arbitrary complexity
TextArt
=
Canvas
{
TextFigure
(
new
(1));
Frame
(2.2") {
ClipPath
:
TextFigure
(
null
);
Paragraph
{
ParBackground
:
Colors
.
Blue
..
Colors
.
Orange
;
TextHeight
:
16;
TextColor
:
Colors
.
White
;
"Clip "
*
42;
};
}
};
Clip Clip Clip Clip Clip Clip Clip
Clip Clip Clip Clip Clip Clip Clip
Clip Clip Clip Clip Clip Clip Clip
Clip Clip Clip Clip Clip Clip Clip
Clip Clip Clip Clip Clip Clip Clip
Clip Clip Clip Clip Clip Clip Clip
Charts
A chart can be created from a series of data points with the
Chart
formatter.
El lenguaje de programación Nytril
Ā®
PƔgina 35 de
108
DataPoint
RainPoint
(
RainClass
rain
)
=
new
RainPointClass
(
each0
,
rain
) {
Marker
:
Markers
.
Circle
(
Colors
.
Blue
);
};
RainPoints
=
RainPoint
(
each
Rainfall
);
RainAxis
=
ChartAxis
{(
each
CalendarMonth
.
MonthsOfTheYear
)
.
ShortName
};
FillColor
=
new
LinearGradient
(0, 0, 0, 1, [
new
(0.0,
Colors
.
LightGray
),
new
(0.9,
Colors
.
SkyBlue
),
new
(1,
Colors
.
DarkGreen
)]);
RainChart
=
VBox
{
HAlign
:
Center
;
CloudTitle
;
Chart
(89%, 30%) {
Smoothing
:
0.75;
ChartType
:
ChartTypes
.
Area
;
XLabel
:
"Month"
{
TextHeight
:
14pt};
XAxis
:
RainAxis
;
ValueLabel
:
HBox
{
attribute
(
RainUnit
)
.
UnitPlural
;
TextHeight
:
14pt;
Transform
:
Transform
.
Rotate
(90
degrees
);
TransformFit
:
true
;
};
ValueAxis
:
ChartAxis
{
MinorTics
:
true
};
ChartSeries
(
FillColor
,
new
(1,
Colors
.
DarkGreen
)) {
RainPoints
;
};
};
};
Yearly Rainfall
Month
inches
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
0
2
4
6
8
10
12
14
16
18
20
A pie chart can be created by changing the
ChartType
property.
PieChart
=
Chart
(5", 2.5") {
TextDigits
:
2;
ChartType
:
ChartTypes
.
Pie
;
XAxis
:
RainAxis
;
Legend
:
ChartLegend
{
Direction
:
Directions
.
Vertical
;
Placement
:
Placements
.
Right
};
Formateo
PƔgina 36 de
108
ChartSeries
{
WedgeGap
:
2;
RainPoints
;
};
};
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
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
Use the
X
property of the datapoint to set a specific x coordinate for a scatter plot
RandomNumber
=
Math
.
Random
(0.0
..
10.0);
RandomSeries
(
name
)
=
ChartSeries
{
El lenguaje de programación Nytril
Ā®
PƔgina 37 de
108
Label
:
name
;
foreach
(
var
r
in
0
..
50)
new
DataPoint
(
RandomNumber
,
RandomNumber
);
};
ScatterChart
=
VBox
{
Paragraph
{
"Random Points"
;
};
HAlign
:
Center
;
Chart
(89%, 30%,
new
Edge
(0, 5)) {
ChartType
:
ChartTypes
.
Scatter
;
Legend
:
ChartLegend
(0.5pt) {
Direction
:
Directions
.
Vertical
;
Placement
:
Placements
.
Right
;
};
RandomSeries
(
"One"
);
RandomSeries
(
"Two"
);
};
};
Random Points
One
Two
0
1
2
3
4
5
6
7
8
9
10
0
1
2
3
4
5
6
7
8
9
10
More than one series can be specified in the same chart by adding more than one
ChartSeries
element to the Chart formatter.
AngleRange
=
0
..
Symbolic
.
PI2
;
AllAngles
=
AngleRange
step
Symbolic
.
PI
/
12;
FuncSeries
(
Attribute
func
,
marker
)
=
ChartSeries
{
Label
:
func
.
Prototype
;
Marker
:
marker
;
foreach
(
var
a
in
AllAngles
)
new
DataPoint
(
a
,
func
.
Value
(
a
));
};
TrigChart
=
VBox
{
HAlign
:
Center
;
"Trig Functions"
;
Chart
(89%, 30%) {
ChartType
:
ChartTypes
.
Line
;
Legend
:
ChartLegend
{
Placement
:
Placements
.
Right
;
Direction
:
Directions
.
Vertical
;
Formateo
PƔgina 38 de
108
};
XAxis
:
ChartAxis
{
VAlign
:
Center
;
LabelEach
:
2;
AllAngles
;
};
FuncSeries
(
attribute
Symbolic
.
Sin
,
Markers
.
Circle
);
FuncSeries
(
attribute
Symbolic
.
Cos
,
Markers
.
Square
);
}
};
Trig Functions
Cos
(
x
)
Sin
(
x
)
0
1
6
Ļ
1
3
Ļ
1
2
Ļ
2
3
Ļ
5
6
Ļ
Ļ
1
1
6
Ļ
1
1
3
Ļ
1
1
2
Ļ
1
2
3
Ļ
1
5
6
Ļ
2
Ļ
-1,0
-0,8
-0,6
-0,4
-0,2
-0,0
0,2
0,4
0,6
0,8
1,0
Use a stacked chart to compare data from different series
ActivationChart
(
type
,
rotation
,
legend
=
false
)
=
VBox
{
HAlign
:
Center
;
Paragraph
{
SpaceAfter
:
8pt;
type
;
};
BaseChart
(
type
,
rotation
,
legend
);
};
ActivationCharts
(
left
,
right
)
=
Paragraph
{
SpaceAfter
:
8pt;
ActivationChart
(
left
, 45
degrees
);
Space
*
5;
ActivationChart
(
right
,
null
)
};
ActivationGallery
=
Block
{
ActivationCharts
(
ChartTypes
.
Line
,
ChartTypes
.
Area
);
ActivationCharts
(
ChartTypes
.
Column
,
ChartTypes
.
Bar
);
ActivationCharts
(
ChartTypes
.
StackedColumn
,
ChartTypes
.
StackedBar
);
ActivationCharts
(
ChartTypes
.
StackedColumn100
,
ChartTypes
.
StackedBar100
);
ActivationChart
(
ChartTypes
.
Doughnut
,
null
,
true
)
};
El lenguaje de programación Nytril
Ā®
PƔgina 39 de
108
Line
pcDNA4
TW
p65
Both
dWR
d194
0
100
200
300
400
Area
pcDNA4
TW
p65
Both
dWR
d194
0
100
200
300
400
Column
pcDNA4
TW
p65
Both
dWR
d194
0
100
200
300
400
Bar
0
100
200
300
400
pcDNA4
TW
p65
Both
dWR
d194
StackedColumn
pcDNA4
TW
p65
Both
dWR
d194
0
100
200
300
400
500
600
StackedBar
0
100
200
300
400
500
600
pcDNA4
TW
p65
Both
dWR
d194
Formateo
PƔgina 40 de
108
StackedColumn100
pcDNA4
TW
p65
Both
dWR
d194
0
10
20
30
40
50
60
70
80
90
100
StackedBar100
0
10
20
30
40
50
60
70
80
90
100
pcDNA4
TW
p65
Both
dWR
d194
Doughnut
% IL7
% IL8
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
El lenguaje de programación Nytril
Ā®
PƔgina 41 de
108
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
Table cells can contain any type of formatter, including other tables.
Attribute
[]
TrigFunctions
=
[
attribute
Symbolic
.
Sin
,
attribute
Symbolic
.
Cos
,
attribute
Symbolic
.
Tan
];
TrigRow
(
angle
)
=
Row
{
HAlign
:
Center
;
VAlign
:
Center
;
angle
;
foreach
(
var
f
in
TrigFunctions
) {
f
.
Value
(
angle
);
}
};
Angles
=
0
..
Symbolic
.
PI
/
2
step
Symbolic
.
PI
/
12;
TrigTable
=
Table
(
new
Edge
(1, 0,
Colors
.
LightGray
),
PadAll
(1), [1", 1.5"]) {
TextHeight
:
10pt;
Row
{
TextHeight
:
14pt;
Background
:
95%;
Cell
(
null
, 4) {
ParAlignment
:
Center
;
"Trig Functions"
;
}
};
Row
{
VAlign
:
Center
;
HAlign
:
Center
;
Background
:
70%;
TextColor
:
Colors
.
White
;
TextHeight
:
12pt;
"Angle"
;
foreach
(
var
f
in
TrigFunctions
) {
Span
{
f
.
Prototype
;
Tip
:
f
};
}
};
TrigRow
(
each
Angles
)
};
Trig Functions
Angle
Sin
(
x
)
Cos
(
x
)
Tan
(
x
)
0
0
1
0
1
12
Ļ
0,25881904510252074
0,9659258262890683
0,2679491924311227
1
6
Ļ
1
2
3
2
1
3
1
4
Ļ
1
2
1
2
1
1
3
Ļ
3
2
1
2
3
5
12
Ļ
0,9659258262890683
0,258819045102521
3,7320508075688736
1
2
Ļ
1
0
ā
Formateo
PƔgina 42 de
108
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
Some or all of a tree's contents may be calculated.
Circle
(
r
,
fill
)
=
Shape
(
fill
) {
EllipsePath
(
new
(
new
(0),
new
(
r
)))
};
NumberNode
(
i
)
=
new
Node
(
Radical
{
i
},
Sqrt
(
i
)) {
Marker
:
Circle
(
i
*
5,
new
Color
((
i
*
15)
%
, 0, 0));
Stroke
:
new
Stroke
(
i
,
new
Color
(0, 0, (
i
*
15)
%
),
LineStyles
.
Solid
,
LineCaps
.
Round
);
};
CalcTree
=
new
Node
{
Bevel
:
80%;
NodeGap
:
10pt;
new
Node
(
"A"
);
new
Node
(
"B"
) {
NumberNode
(
each
1
..
6);
};
new
Node
(
"C"
);
};
ShowTree2
=
TreeBox
(3", 2") {
Root
:
CalcTree
;
};
A
B
1
2
3
4
5
6
C
El lenguaje de programación Nytril
Ā®
PƔgina 43 de
108
A tree's contents may be generated recursively.
Attribute
[]
TreeMarkers
=
[
attribute
Markers
.
Circle
,
attribute
Markers
.
Square
,
attribute
Markers
.
TriangleUp
,
attribute
Markers
.
Diamond
];
TreeColors
=
[
Colors
.
Red
,
Colors
.
Green
,
Colors
.
Purple
,
Colors
.
Blue
];
MaxDepth
=
TreeMarkers
.
Length
-
1;
RecurseNode
(
depth
,
number
)
=
new
Node
(
"
{0}{1}
"
(
'A'
+
depth
,
number
), 1
/
(
depth
+
1)) {
Stroke
:
new
Stroke
(
MaxDepth
-
depth
+
1,
depth
*
25%);
NodeGap
:
6pt;
if
(
depth
>
0) {
Bevel
:
depth
*
0.25;
Curvature
:
depth
*
0.25;
}
else
Bevel
:
100%;
Marker
:
TreeMarkers
[
depth
]
.
Value
(
TreeColors
[
depth
]);
if
(
depth
<
MaxDepth
)
RecurseNode
(
depth
+
1,
each
0
..
(
depth
+
1));
};
ShowTree3
=
TreeBox
(
null
, 1.5") {
Placement
:
Placements
.
Bottom
;
TextHeight
:
10pt;
Root
:
RecurseNode
(0, 0);
};
A0
B0
C0
D0
D1
D2
D3
C1
D0
D1
D2
D3
C2
D0
D1
D2
D3
B1
C0
D0
D1
D2
D3
C1
D0
D1
D2
D3
C2
D0
D1
D2
D3
The structure of a math expression may be shown with the
GetExpressionTree
function.
readonly
Equation
=
((
x
-
y
*
2)
/
sigma
)
^
2
+
5;
ShowEquation
=
HBox
(
null
,
null
,
new
Edge
(0.5, 8pt)) {
Separation
:
16pt;
VAlign
:
Center
;
Paragraph
{
HBox
{
VAlign
:
Center
;
"Equation = "
;
Equation
;
};
};
TreeBox
(3",
null
) {
Default
:
new
Node
(
null
) {
Curvature
:
20%;
Bevel
:
20%;
NodeGap
:
10pt;
};
Root
:
Equation
.
GetExpressionTree
;
};
};
Formateo
PƔgina 44 de
108
Equation =
ā
x
Ļ
2
Ā +Ā
5
Add
Power
Divide
Multiply
-1
x
Ļ
2
5
Tree structures can be read directly from a data file.
ShowTrees
=
Block
{
ShowTreeName
(
each
TreeFile
.
Trees
);
};
El lenguaje de programación Nytril
Ā®
PƔgina 45 de
108
tree9
F
A
B
E
C
D
Tree structures can be formatted in a variety of ways using
Bevel
and
Curvature
settings
FormattedTrees
=
Block
{
ShowNexusTree
(
TreeFile
.
FindTree
(
"tree4"
));
ShowNexusTree
(
TreeFile
.
FindTree
(
"tree5"
));
};
tree4
Curvature
Bevel
0%
50%
100%
0
F
A
B
E
C
D
F
A
B
E
C
D
F
A
B
E
C
D
50%
F
A
B
E
C
D
F
A
B
E
C
D
F
A
B
E
C
D
100%
F
A
B
E
C
D
F
A
B
E
C
D
F
A
B
E
C
D
tree5
Curvature
Bevel
0%
50%
100%
0
50%
100%
Creating a Document
A document is made by creating a new class that inherits
DocumentEntry
. Overload the function
GetDocument
and add new content.
class
HelloDocClass
:
DocumentEntry
{
Constructor
{
super
.
Constructor
(
#ab6ec337-2885-4777-b223-855509822fa5#
,
"Hello"
);
}
override
GetDocument
=
Document
{
"Hello World"
;
};
}
Formateo
PƔgina 46 de
108
Formatting Properties
Use a wide variety of formatting properties to program the look of the
content in your document. Together with the revision mechanism, you can
create named styles and combine them with your data to create beautiful,
accurate documents.
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
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.
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.
Make the font italic by setting the
TextItalic
property to true.
ShowItalic
=
Paragraph
{
"Make "
;
Span
{
TextItalic
:
true
;
El lenguaje de programación Nytril
Ā®
PƔgina 47 de
108
"sure"
;
};
" to read the instructions. "
;
};
Make
sure
to read the instructions.
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.
Make the font bold by setting the
TextWeight
property to Bold.
ShowBold
=
Paragraph
{
"Use "
;
Span
{
TextWeight
:
Bold
;
"extreme"
;
};
" caution. "
;
};
Use
extreme
caution.
Apply the special Bold revision directly to a string for a more concise expression.
ShowBold2
=
Paragraph
{
"Use "
;
Bold
"extreme"
;
" caution. "
;
};
Use
extreme
caution.
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
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
Use the
TextUnderline
property to underline text in a variety of styles.
Formateo
PƔgina 48 de
108
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
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
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!
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."
};
};
}
El lenguaje de programación Nytril
Ā®
PƔgina 49 de
108
};
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.
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.
Insert content between elements with the
Separator
property.
ShowSeparator
=
Paragraph
{
Separator
:
", "
;
1
..
5
step
1;
};
1, 2, 3, 4, 5
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
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};
Formateo
PƔgina 50 de
108
};
1
1 and 2
1, 2, and 3
Number Formatting
Use a large selection of different number formatting properties to add data
to your documents.
To show an integer, simply include the literal number as one of the elements inside a span.
IntegerLiteral
=
Span
{
42
;
};
42
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
To format an integer in hexadecimal, change the
TextRadix
to 16.
IntegerHexadecimal
=
Span
{
TextRadix
:
16
;
129579;
};
1fa2b
To have the hex digits shown in upper-case, change the
TextCase
property to AllUpper.
IntegerHexadecimalUpper
=
Span
{
TextRadix
:
16;
TextCase
:
AllUpper
;
671277;
};
A3E2D
To format a number in binary, use 2 as the
TextRadix
.
IntegerBinary
=
Span
{
TextRadix
:
2
;
127;
};
1111111
El lenguaje de programación Nytril
Ā®
PƔgina 51 de
108
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
To format an integer with a group separator, set the
TextGroup
property to true.
IntegerGroup
=
Span
{
TextGroup
:
true
;
1234567.89;
};
1.234.567,89
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
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
Formatting a return value from a function works the same way.
DoubleReturn
=
Span
{
Math
.
Sqrt
(1
+
1)
;
};
1,4142135623730951
Use the
TextDigits
property to fix the number of fractional digits in the number.
DoubleDigits
=
Span
{
TextDigits
:
3
;
Math
.
PI
;
};
3,142
Formateo
PƔgina 52 de
108
Set the
TextPercent
property to true to show numbers as percentages.
Percentage
=
Block
{
TextPercent
:
true
;
0.04;
1.5;
};
4%
150%
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
Format the number in scientific notation by setting
TextScientific
to true.
ScientificNotation
=
Span
{
TextScientific
:
true
;
TextDigits
:
2;
175_000;
};
1,75x10
5
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
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};
El lenguaje de programación Nytril
Ā®
PƔgina 53 de
108
AlignedPar
{
Tab
; 0.5544};
};
1,2
123,99
0,5544
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
Math Formatting
Create professionally typeset math equations using a small number of
formatting primitives.
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'
Create several different types of common fractions with the
Fraction
formatter.
FormatFraction
=
Fraction
{
x
;
y
+
1;
};
x
y
Ā +Ā
1
Formateo
PƔgina 54 de
108
Format the fraction with a diagonal slash by setting the diagonal argument to true.
SlantedFraction
=
Fraction
(
true
) {
x
;
y
^
2;
};
x
y
2
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.
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.
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.
Add a subscript to a symbol by using the
sub
operator.
X1
=
x
sub
1;
x
1
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
El lenguaje de programación Nytril
Ā®
PƔgina 55 de
108
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
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
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
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
Use the
Upper
and
Lower
properties to set the superscript and subscript of the Operator.
InverseSquareIntegral
=
Paragraph
{
Formateo
PƔgina 56 de
108
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
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
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
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
If you set the
TextEquation
property to true, the math font is used for all of the symbols, and the
El lenguaje de programación Nytril
Ā®
PƔgina 57 de
108
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
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
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
!
Choose from a wide variety of arrow and bracket styles.
VerticalBrackets
=
HBox
{
Separation
:
20;
Formateo
PƔgina 58 de
108
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
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
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
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
;
El lenguaje de programación Nytril
Ā®
PƔgina 59 de
108
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 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
Paragraph Formatting
Paragraphs wrap content inside the body of a document or frame. They are
the fundamental container for free flowing text in your documents. A
paragraph inherits the properties of a Span formatter, and adds borders, tabs
and indenting.
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};
Formateo
PƔgina 60 de
108
};
Paragraph One
Paragraph Two
2,414213562373095
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
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
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%;
};
El lenguaje de programación Nytril
Ā®
PƔgina 61 de
108
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 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
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
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
Formateo
PƔgina 62 de
108
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
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.
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
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
El lenguaje de programación Nytril
Ā®
PƔgina 63 de
108
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
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
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
Change the default line height using the
LineHeight
property.
LegalText
=
Block
{
LineHeight
:
200%
;
TextFace
:
Mono
;
Paragraph
{
Bold
;
TextCase
:
AllUpper
;
Underline
;
Formateo
PƔgina 64 de
108
"Memorandum of Points"
;
};
"Statement of Relevant Facts"
;
};
MEMORANDUM OF POINTS
Statement of Relevant Facts
Double-spaced lines
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.
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.
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
El lenguaje de programación Nytril
Ā®
PƔgina 65 de
108
I would like to
emphasize
the following points.
Image Formatting
Images loaded from external files are an important part of most documents.
To use an image find the path relative to your source code. Then, load the
image into a variable. Next, you can scale and format the image, and place
it into a Paragraph.
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 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%);
};
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%);
};
Formateo
PƔgina 66 de
108
Paragraph
{
"Baseline at 70%: "
;
FitBox
(
NytrilBug
, 5%) {
Baseline
:
70%
};
};
};
No baseline adjustment:
Baseline at 70%:
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%
);
Set the height parameter to fit an image to a given height, while scaling the width proportionately.
PictureHeight
=
FitBox
(
Zombie
,
null
,
10%
);
Fit an image inside both a given width and height, while maintaining proportion.
PictureBoth
=
FitBox
(
Zombie
,
10%, 20%
);
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
);
El lenguaje de programación Nytril
Ā®
PƔgina 67 de
108
Out of proportion
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%
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
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);
};
Formateo
PƔgina 68 de
108
SallyFrame
=
FrameFigure
(
Sally
,
Math
.
Max
(
ExtentWidth
,
ExtentHeight
)
*
10%);
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
);
};
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
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
;
};
El lenguaje de programación Nytril
Ā®
PƔgina 69 de
108
IconFigure
=
Paragraph
{
YouTube
(
ExtentWidth
*
3%,
new
(
"www.youtube.com/@Nytril"
));
Space
;
"Follow us on YouTube"
;
};
ī·
Follow us on YouTube
https://www.youtube.com/@Nytril
Hyperlinks and Tips
Use hyperlinks to create content that is connected to other Nytril documents
or content on the Web. Connect user input to different types of custom
actions to create dynamiclly generated content.
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
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
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
Use the
TipAction
property to specify a both a tip and an action at the same time.
ActionTip
=
Span
{
Formateo
PƔgina 70 de
108
"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
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.
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.
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"
Change the level of error correction in the QR code by setting the error parameter to a number
from 0 to 3.
QRLink
=
VBox
{
El lenguaje de programación Nytril
Ā®
PƔgina 71 de
108
HAlign
:
Center
;
"Community Edition"
;
QRBox
(
WebAddress
,
QRSize
,
3
) {
TipAction
:
WebAddress
;
};
};
Community Edition
https://www.nytril.com
More complex pattern
includes more error correction
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
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
.
content_copy
;
Space
;
"Copy Text"
;
TipAction
:
new
CustomAction
(
"Custom Text"
);
};
ī
Copy Text
Text copied to the clipboard
Box Formatting
Boxes are rectangular containers with optional borders and padding. They
align their content either horizontally or vertically, and can justify that
Formateo
PƔgina 72 de
108
content in flexible ways.
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
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
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
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.
El lenguaje de programación Nytril
Ā®
PƔgina 73 de
108
PlusEquals
=
{
Separator
:
" + "
;
LastSeparator
:
" = "
;
};
BoxesWithSeparators
=
Paragraph
{
VBoxSet
PlusEquals
;
Space
;
HBoxSet
PlusEquals
;
};
1
+
2
=
3
A
+
B
=
C
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
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
Use the
Margin
property to put distance between the box and adjacent content.
Formateo
PƔgina 74 de
108
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
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
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
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);
El lenguaje de programación Nytril
Ā®
PƔgina 75 de
108
PaddingBox
(
"LR"
,
Gap
, 0,
Gap
, 0);
PaddingBox
(
"TB"
, 0,
Gap
, 0,
Gap
);
};
LTRB
T
B
L
R
LR
TB
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
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
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
Formateo
PƔgina 76 de
108
Use the
Shadow
property to add a raised look to a box.
ShadowBox
=
BoxWithBackground
{
Shadow
:
new
Edge
(0.4%, 0,
Colors
.
DarkGray
);
};
Start
Drawings
Create drawings using canvases and shapes. You can combine lines and
curves with fill patterns using a variety of colors and styles.
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%);
};
};
};
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
);
Change the color of the line with the 2nd parameter of the
Stroke
constructor.
El lenguaje de programación Nytril
Ā®
PƔgina 77 de
108
Stroke
LS1
=
new
(
LineSize
,
Colors
.
Red
);
Line1
=
ZigZag
(
LS1
);
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
);
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
Change the LineCap style using the 4th parameter of the
Stroke
constructor.
Stroke
LS3
=
new
(
LineSize
,
Colors
.
Red
,
Dotted
,
Round
);
Line3
=
ZigZag
(
LS3
);
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%);}
Formateo
PƔgina 78 de
108
};
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
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
);
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
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%)};
};
El lenguaje de programación Nytril
Ā®
PƔgina 79 de
108
};
MiterTable
=
TwoColumTable
{
Row
{
Bold
;
"Miter Limit"
;
"Effect"
};
foreach
(
var
m
in
[50, 1])
Row
{
TextDigits
:
0;
m
;
DrawMiterJoin
(
m
)};
};
Miter Limit
Effect
50
1
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
};
};
};
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
};
};
Formateo
PƔgina 80 de
108
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);
};
};
};
Make a regular n-sided polygon with 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
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%));
};
};
};
El lenguaje de programación Nytril
Ā®
PƔgina 81 de
108
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
);
};
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%));
};
};
};
The following examples show how the control points bend the curve.
ShowCubics
=
Canvas
{
Margin
:
LineSize
;
ShowCurve
(
each
CubicExamples
);
};
Formateo
PƔgina 82 de
108
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
);
};
Elliptic arcs flow between two end points, around an invisible ellipse rotated at the specified angle. The
following examples show how the angle effects the curve.
El lenguaje de programación Nytril
Ā®
PƔgina 83 de
108
large
false
clockwise
false
-30 degrees
0 degrees
30 degrees
clockwise
true
-30 degrees
0 degrees
30 degrees
large
true
clockwise
false
-30 degrees
0 degrees
30 degrees
clockwise
true
-30 degrees
0 degrees
30 degrees
If you want to create a circular arc (such as for a pie wedge), set the radius(width, height) to the same
number. There are four different paths that are determined by the two boolean parameters large and
clockwise. Imagine two circles drawn along the major axis. If large is set to true, then the larger of the two
possible arcs will be selected.
large
false
clockwise
false
clockwise
true
large
true
clockwise
false
clockwise
true
Use the 'fillrule' parameter to change the way of determining which points are inside the shape.
Formateo
PƔgina 84 de
108
The following values determine the 'insideness' of a point in the shape. This determines which
areas will be filled.
EvenOdd
: Default
Imagine drawing a ray from a point in the shape to infinity in any direction, and then examining the
places where a segment of the shape crosses the ray. If this number is even, the point is outside.
Ā āĀ
Ā āĀ
NonZero
Imagine drawing a ray from any point in the shape to infinity in any direction and counting the
number of path segments from the given shape that the ray crosses. Starting with a count of zero,
add one each time a path segment crosses the ray from left to right and subtract one each time a
path segment crosses the ray from right to left. After counting the crossings, if the result is zero
then the point is outside.
Ā āĀ
Ā āĀ
Colors and Fills
Nytril gives you full control over colors and fill patterns with lines, shapes
and text. Use a color palette and different fill gradients to make colorful and
informative documents.
The
Colors
namespace contains a variety of commonly used solid colors for lines and text.
Headline
=
Paragraph
{
TextHeight
:
200%;
TextFamily
:
TextFamilies
.
TimesNewRoman
;
TextColor
:
Colors
.
Green
;
Icons
.
rocket
;
Bold
;
" Aliens Finally Land!"
;
};

Aliens Finally Land!
Use a loop to build a palette with each color in the
Colors
namespace .
ShowColors
=
Paragraph
{
foreach
(
var
c
in
Colors
)
{
Canvas
(
BoxSize
,
BoxSize
) {
Background
:
c
;
Tip
:
c
;
};
El lenguaje de programación Nytril
Ā®
PƔgina 85 de
108
}
};
For applications where contrasting colors are needed, get the bar colors used in charts with the
ChartColor
function.
ChartColors
=
HBox
{
Separation
:
8;
for
(
int
i
=
1;
i
<
20;
++
i
) {
HBox
(
BoxSize
,
BoxSize
) {
Background
:
Color
.
ChartColor
(
i
);
}
}
};
The
Color
constructor initializes a color with a specific RGBA value.
ShowColor
(
Color
color
)
=
Span
{
Canvas
(
BoxSize
,
BoxSize
) {
Background
:
color
;
Baseline
:
80%;
};
Space
;
Span
{
Separator
:
CommaSpace
;
TextRadix
:
16;
TextNumPadding
:
2;
color
.
R
;
color
.
G
;
color
.
B
;
color
.
A
;
};
};
ColorConstructor
=
ShowColor
(
new
Color
(0x3F, 0x80, 0xFF, 0xFF)
);
3f, 80, ff, ff
The same color can be specified directly in source code using the #rrggbbaa# color notation.
ColorSource
=
Span
{
ShowColor
(
#3F80FFFF#
);
};
3f, 80, ff, ff
Colors can also be constructed from hue-saturation-lightness-alpha values with the
FromHSLA
function.
ShowHSLA
=
HBox
{
var
color
=
Color
.
FromHSLA
(170, 0.25, 0.5);
Separation
:
3;
VAlign
:
Center
;
Canvas
(
BoxSize
,
BoxSize
) {
Background
:
color
;
};
Formateo
PƔgina 86 de
108
Paragraph
{
TextDigits
:
2;
Separator
:
Space
*
3;
color
.
H
;
color
.
S
;
color
.
L
;
color
.
A
;
};
};
170,00 0,25 0,50 255,00
Set the alpha value of a color to less than 1 to mix overlayed colors.
AlphaBlend
=
Canvas
{
Span
{
"Text"
;
TextHeight
:
W
*
2;
TextColor
:
#00004560#
};
Canvas
(
W
,
W
) {
X
:
W
;
Y
:
W
;
Background
:
#00640080#
;
};
Canvas
(
W
,
W
) {
X
:
W
*
0.5;
Y
:
W
*
0.5;
Background
:
#64000060#
;
};
};
Text
Blended colors
Use a
LinearGradient
to create a fill pattern that shifts smoothly from one color to the next.
ShowShapes
(
name
,
fill
)
=
HBox
{
VAlign
:
Center
;
Separation
:
sh
;
Margin
:
PadB
(
sh
*
0.5);
HBox
(
sh
*
6) {
TextHeight
:
sh
;
name
};
Shape
(
fill
) {
EllipsePath
(
new
(
new
(0),
new
(
hm
,
hm
)))};
Canvas
(
hm
,
hm
) {
Background
:
fill
};
Shape
(
fill
) {
OpenPath
(0) {
LineTo
(
hm
,
hm
);
LineTo
(
hm
*
2,
hm
*
0.5);
LineTo
(
hm
*
3,
hm
);
LineTo
(
hm
*
4, 0)};
};
};
readonly
ColorStop
[]
ColorStops
=
[
new
(10%,
Colors
.
Orange
),
new
(25%,
Colors
.
Blue
),
new
(50%,
Colors
.
Red
),
new
(80%,
Colors
.
Green
)
];
FillLinearGradient
=
Block
{
ShowShapes
(
"Linear"
,
new
LinearGradient
(0, 0, 0, 1,
ColorStops
));
};
Linear
Use the points in the constructor to define the direction of the gradient.
FillLinearGradients
=
Block
{
ShowShapes
(
"Vertical"
,
new
LinearGradient
(
0, 0, 0, 1
,
ColorStops
));
ShowShapes
(
"Horizontal"
,
new
LinearGradient
(0, 0, 1, 0,
ColorStops
));
ShowShapes
(
"Diagonal"
,
new
LinearGradient
(0, 0, 1, 1,
ColorStops
));
El lenguaje de programación Nytril
Ā®
PƔgina 87 de
108
};
Vertical
Horizontal
Diagonal
Use
RadialGradient
to create a fill pattern that radiates from a central point.
FillRadialGradient
=
Block
{
ShowShapes
(
"Radial"
,
new
RadialGradient
(0, 0, 0, 0, 1, 1,
ColorStops
));
};
Radial
Use the points in the constructor to define the center, focus and radius of the gradient.
FillRadialGradients
=
Block
{
ShowShapes
(
"Top Left"
,
new
RadialGradient
(
0, 0, 0, 0, 1, 1
,
ColorStops
));
ShowShapes
(
"Top Right"
,
new
RadialGradient
(1, 0, 1, 0, 1, 1,
ColorStops
));
ShowShapes
(
"Centered"
,
new
RadialGradient
(0.5, 0.5, 0.5, 0.5, 1, 1,
ColorStops
));
ShowShapes
(
"Bottom Left"
,
new
RadialGradient
(0, 1, 0, 1, 1, 1,
ColorStops
));
ShowShapes
(
"Bottom Right"
,
new
RadialGradient
(1, 1, 1, 1, 1, 1,
ColorStops
));
};
Top Left
Top Right
Centered
Bottom Left
Bottom Right
An even color spectrum can be formed from an array of colors with the
FromColorArray
function.
readonly
Heat
=
LinearGradient
.
FromColorArray
([
Colors
.
Blue
,
Colors
.
Cyan
,
Colors
.
Yellow
,
Colors
.
Red
]);
ShowHeatmap
=
HBox
(
BoxSize
*
20,
BoxSize
) {
Background
:
Heat
;
};
Formateo
PƔgina 88 de
108
An interpolated color can be computed using a color gradient with the
InterpolateColor
function.
Interpolation
=
HBox
{
for
(
double
i
=
0;
i
<=
1.0;
i
+=
0.04) {
HBox
(
BoxSize
,
BoxSize
,
BorderR
(
new
(1, 0, 89%))) {
Background
:
Heat
.
InterpolateColor
(
i
);
}
}
};
A 2-dimensional color image can be created from the values in a matrix with the
GetImage
function.
Color
HeatColor
(
int
_
,
int
_1
,
double
value
)
=
Heat
.
InterpolateColor(
value
);
GetMapImage
=
Span
{
int
size
=
150;
var
m
=
new
Matrix
<
double
>
(
size
,
size
, 0);
for
(
int
i
=
0;
i
<
size
;
++
i
) {
for
(
int
j
=
0;
j
<
size
;
++
j
)
m
[
i
,
j
]
=
0.5
+
0.5
/
size
*
i
*
Math
.
Sin
(
j
*
2.0
*
Math
.
PI2
/
size
);
}
var
image
=
m
.
GetImage
(
@
HeatColor
,
"Sinusoidal Heat Map"
);
FitBox
(
image
,
BoxSize
*
10);
};
Sinusoidal Heat Map
PƔgina 89 de
108
MatemƔticas
User defined symbols
Symbols are special values that can represent constants or variables
x
=
Symbol
(
"x"
);
x
The typeset representation of a symbol can differ from its variable name
sigma
=
Symbol
(
"Ļ"
);
Ļ
You can create symbols with subscripts and superscripts
SigmaNaught
=
sigma
sub
0;
XSquared
=
x
sup
2;
SymbolSum
=
XSquared
+
SigmaNaught
;
x
2
Ā +Ā
Ļ
0
Algebra
Addition is carried out using the
+
operator.
Number
=
1
+
3;
Sum
=
Number
+
x
;
4
Ā +Ā
x
Subtraction is carried out using the
-
operator.
Difference
=
5
-
7;
-2
Multiplication is carried out using the
*
operator.
Product
=
5
*
3;
15
Floating point division is carried out using the
/
operator., the result is a floating point number.
RealDivision
=
3
/
5;
0,6
Rational division is carried out using the
over
operator.
Ratio
=
3
over
5;
MatemƔticas
PƔgina 90 de
108
3
5
Integer division (even division without a remainder) is carried out using the
div
operator.
IntResult
=
8
div
5;
1
The remainder after integer division can be found using the
mod
operator.
Remainder
=
8
mod
5;
3
A value can be raised to a power using the
^
operator.
Power
=
4
^
2;
16
Symbols obey the rules of algebra when combined with other symbols and numbers.
Polynomial
=
a
x
^
2
+
b
x
+
c
;
a
x
2
Ā +Ā
b
x
Ā +Ā
c
Basic algebra is performed automatically when symbols are multipled or added.
AddX
=
2
x
+
5
x
+
3;
7
x
Ā +Ā
3
Combined terms can be expanded with the
GetExpandedTerms
function.
CompareAll
=
[
CompareEquations
(14),
CompareEquations
((3
x
+
y
)
*
x
*
y
),
CompareEquations
(2
*
(6
+
y
)
*
y
),
CompareEquations
((3
x
+
1)
*
1
*
x
),
];
14
=> 14
(
3
x
Ā +Ā
y
)
x
y
=>
3
x
2
y
Ā +Ā
y
2
x
2
(
6
Ā +Ā
y
)
y
=>
12
y
Ā +Ā
2
y
2
(
3
x
Ā +Ā
1
)
x
=>
3
x
2
Ā +Ā
x
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
Get the minimum of two values with the
Min
function.
El lenguaje de programación Nytril
Ā®
PƔgina 91 de
108
CheckMin1
=
Math
.
Min
(
-
5, 2);
CheckMin2
=
Math
.
Min
(
Symbolic
.
PI
, 4);
-5
Ļ
Get the maximum of two values with the
Max
function.
CheckMax1
=
Math
.
Max
(
-
5,
-
2);
CheckMax2
=
Math
.
Max
(
Math
.
E
, 2);
-2
2,718281828459045
Get the absolute value of a number with the
Abs
function.
CheckAbs1
=
Math
.
Abs
(5);
CheckAbs2
=
Math
.
Abs
(
-
10);
CheckAbs3
=
Math
.
Abs
(
-
x
);
5
10
ā
x
Get the logarithm of a number with the
Log
function.
CheckLog1
=
{
TextDigits
:
5}
Math
.
Log
(5.345);
CheckLog2
=
Math
.
Log
(
Math
.
E
);
CheckLog3
=
Math
.
Log
(
Math
.
E
*
2);
CheckLog4
=
Math
.
Log
(1000, 10);
CheckLog5
=
Math
.
Log
(16, 2);
1,67616
1
1,6931471805599452
2,9999999999999996
4
Get the factorial of a number with the
Factorial
function.
FactArray
=
Span
{
Separator
:
", "
;
Math
.
Factorial
(
each
1
..
6)};
1, 2, 6, 24, 120, 720
Statistics
Statistics functions operate on arrays of double values. For example suppose we define the
following arrays:
NumberSet
=
[3.6, 4.0, 4.5, 5.5, 6.4, 8.5];
[
3,6
,
4
,
4,5
,
5,5
,
6,4
,
8,5
]
The
sum
of an array is defined as:
S
Ā =Ā
x
i
n
i
Ā =Ā
1
where
n
is the length of the array and
x
i
is the
i
th
element.
It can be computed with the
Sum
function.
SumData
=
Math
.
Sum
(
NumberSet
);
32,5
The
product
of an array is defined as:
MatemƔticas
PƔgina 92 de
108
P
Ā =Ā
x
i
n
i
Ā =Ā
1
where
n
is the length of the array and
x
i
is the
i
th
element.
It can be computed with the
Product
function.
ProductData
=
Math
.
Product
(
NumberSet
);
19388,16
The
arithmetic mean
of an array is defined as:
x
Ā =Ā
x
i
n
i
Ā =Ā
1
n
where
n
is the length of the array and
x
i
is the
i
th
element.
It can be computed with the
Mean
function.
MeanData
=
Math
.
Mean
(
NumberSet
);
5,416666666666667
The
harmonic mean
of an array is defined as:
H
Ā =Ā
n
1
x
i
n
i
Ā =Ā
1
where
n
is the length of the array and
x
i
is the
i
th
element.
It can be computed with the
HarmonicMean
function.
HarmonicMeanData
=
Math
.
HarmonicMean
(
NumberSet
);
4,976299376299376
The
geometric mean
of an array is defined as:
H
Ā =Ā
x
i
n
i
Ā =Ā
1
n
where
n
is the length of the array and
x
i
is the
i
th
element.
It can be computed with the
GeometricMean
function.
GeometricMeanData
=
Math
.
GeometricMean
(
NumberSet
);
5,183098144673662
The
median
of an array can be computed with the
Median
function.
[5]
The
mode
of an array can be computed with the
Mode
function.
DoubleData
=
Math
.
Mode
([1.0, 2.0, 3.0, 2.0, 4.0]);
2
The
variance
of an array is defined as:
Ļ
2
Ā =Ā
(
x
i
Ā āĀ
x
)
2
n
i
Ā =Ā
1
n
where
x
is the mean.
El lenguaje de programación Nytril
Ā®
PƔgina 93 de
108
It can be computed with the
Variance
function.
VarianceData
=
Math
.
Variance
(
NumberSet
);
2,771388888888889
The
standard deviation
of an array is defined as:
Ļ
Ā =Ā
(
x
i
Ā āĀ
x
)
2
n
i
Ā =Ā
1
n
It can be computed with the
StandardDeviation
function.
StdDevData
=
Math
.
StandardDeviation
(
NumberSet
);
1,6647488966474462
The
standard scores
(Z-scores) for every element in an array can be calculated
Z
Ā =Ā
x
Ā āĀ
x
Ļ
It can be computed with the
StandardScores
function.
[-1,0912556664402422, -0,850979189425877, -0,5506335931579205, 0,05005759937799258,
0,5906796726603146, 1,8521311769857318]
The
Quantiles
of an array can be computed with the
Quantiles
function.
[3,6, 4, 4,5, 5,5, 6,4, 8,5]
The
Chi Squared Statistic
of two datasets is defined as:
Ļ
2
Ā =Ā
(
O
i
Ā āĀ
E
i
)
2
E
i
n
i
Ā =Ā
1
Where O
i
is the
i
th
observed value and E
i
is the
i
th
expected value.
It can be computed with the
ChiSquare
function.
ObservedValues
=
[1.0, 3.0, 5.0, 4.0, 7.0];
ExpectedValues
=
[1.0, 4.0, 3.0, 4.0, 8.0];
ChiSquaredData
=
Math
.
ChiSquare
(
ObservedValues
,
ExpectedValues
);
1,7083333333333333
You can perform a simple regression analysis on two datasets using the
LinearRegression
class.
Temperature
=
[88.6, 71.6, 93.3, 84.3, 80.6, 75.2, 69.7, 82, 69.4, 83.3,79.6,82.6,80.6];
ChirpsPerSec
=
[20, 16, 19.8, 18.4, 17.1, 15.5, 14.7, 17.1, 15.4, 16.2, 15, 17.2, 16];
//Data from "The Song of Insects" by Dr. G.W. Pierce, Harvard College Pre
Math
.
LinearRegression
Regression
=
new
Math
.
LinearRegression
(
Temperature
,
ChirpsPerSec
);
The LinearRegression also has a method to predict the value at different points:
ValueAt95
=
Regression
.
GetYValue
(95.0);
19,86279259953732
The
Correlation Coefficient
of two datasets is defined as:
MatemƔticas
PƔgina 94 de
108
r
Ā =Ā
(
x
i
Ā āĀ
x
)
(
y
i
Ā āĀ
y
)
n
i
Ā =Ā
1
(
x
i
Ā āĀ
x
)
2
n
i
Ā =Ā
1
(
y
i
Ā āĀ
y
)
2
n
i
Ā =Ā
1
It can be computed with the
Correlation
function.
Correlation
=
Regression
.
Correlation
;
0,8506559172499765
Here is an example of how to add regression lines to a chart
CricketChart
=
VBox
{
Paragraph
{
TextHeight
:
16pt;
"Cricket Chirps vs. Temperature"
;
};
HAlign
:
Center
;
Chart
(
ExtentWidth
*
0.75, 3") {
ChartType
:
ChartTypes
.
Scatter
;
XAxis
:
ChartAxis
;
ValueLabel
:
"Cricket\nChirps"
;
XLabel
:
"Temperature (F)"
;
ChartSeries
{
new
LinearTrend
;
Label
:
"Temperature"
;
foreach
(
var
x
in
Temperature
)
new
DataPoint
(
x
,
ChirpsPerSec
[
each0
]);
};
}
};
Cricket Chirps vs. Temperature
Temperature (F)
Cricket
Chirps
68
70
72
74
76
78
80
82
84
86
88
90
92
94
0
2
4
6
8
10
12
14
16
18
20
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"
);
El lenguaje de programación Nytril
Ā®
PƔgina 95 de
108
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
]
Vectors can be initialize with uniform contents
Vector
I10
=
new
Vector
(5,
a
);
[
a
,
a
,
a
,
a
,
a
]
Vectors of the same size can be added together using the
+
operator.
VAdd
=
V1
+
V2
;
NAdd
=
N1
+
N2
;
[
a
Ā +Ā
c
,
b
Ā +Ā
d
]
[5, 11]
Vectors of the same size can be subtracted using the
-
operator.
VSub
=
V1
-
V2
;
NSub
=
N1
-
N2
;
[
a
Ā āĀ
c
,
b
Ā āĀ
d
]
[3, -7]
The dot product of two vectors is calculated with the
Dot
function.
VDot
=
V1
.
Dot(
V2
);
NDot
=
N1
.
Dot(
N2
);
a
c
Ā +Ā
b
d
22
The cross product of two 3-vectors is calculated with 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]
The norm of a vector is calculated with the
Norm
function.
VNorm
=
V1
.
Norm;
NNorm
=
N1
.
Norm;
a
2
Ā +Ā
b
2
4,47213595499958
The normalize form of a vector is calculated with the
Normalize
function.
VNormalize
=
V1
.
Normalize;
NNormalize
=
N1
.
Normalize;
[
a
a
2
Ā +Ā
b
2
,
b
a
2
Ā +Ā
b
2
]
[0,8944271909999159, 0,4472135954999579]
MatemƔticas
PƔgina 96 de
108
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
Matrices can be initialized with uniform contents and an optional diagonal element for square
matrices
I52
=
new
Matrix
(4, 4, 0.0, 1.0);
1
0
0
0
0
1
0
0
0
0
1
0
0
0
0
1
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
Matrices of the same size can be subtracted using the
-
operator.
VSub
=
V1
-
V2
;
NSub
=
N1
-
N2
;
a
Ā āĀ
e
b
Ā āĀ
f
c
Ā āĀ
g
d
Ā āĀ
h
-6
-1
-5
-8
The determinant of a matrix is calculated with the
Determinant
function.
El lenguaje de programación Nytril
Ā®
PƔgina 97 de
108
VDet
=
V1
.
Determinant;
NDet
=
N1
.
Determinant;
a
d
Ā āĀ
b
c
-11
The inverse of a matrix is calculated with the
Inverse
function.
VInv
=
V1
.
Inverse;
NInv
=
N1
.
Inverse;
d
a
d
Ā āĀ
b
c
ā
b
a
d
Ā āĀ
b
c
ā
c
a
d
Ā āĀ
b
c
a
a
d
Ā āĀ
b
c
-0,09090909090909091
0,36363636363636365
0,2727272727272727
-0,09090909090909091
The transposition of a matrix is calculated with the
Transpose
function.
VTran
=
V1
.
Transpose;
NTran
=
N1
.
Transpose;
a
c
b
d
1
3
4
1
The normalize form of a matrix is calculated with the
Normalize
function.
VNormalize
=
V1
.
Normalize;
NNormalize
=
N1
.
Normalize;
a
a
d
Ā āĀ
b
c
b
a
d
Ā āĀ
b
c
c
a
d
Ā āĀ
b
c
d
a
d
Ā āĀ
b
c
-0,09090909090909091
-0,36363636363636365
-0,2727272727272727
-0,09090909090909091
The cofactor matrix of a given square matrix is calculated with the
CofactorMatrix
function.
VCofactor
=
V1
.
CofactorMatrix;
NCofactor
=
N1
.
CofactorMatrix;
TCofactor
=
Matrix
.
Convert
([[1, 2, 3], [0, 4, 5], [1, 0, 6]])
.
CofactorMatrix
;
d
ā
c
ā
b
a
1
-3
-4
1
24
5
-4
-12
3
2
-2
-5
4
Automatic Equation Typesetting
Unresolved square roots are automatically typeset
x
=
Symbol
(
"x"
);
y
=
Symbol
(
"y"
);
SquareRoot
=
x
^
(1
over
2);
x
MatemƔticas
PƔgina 98 de
108
Higher roots are also typeset
CubeRoot
=
x
^
(1
over
3);
x
3
Equations of arbitray complexity will be typeset
Part1
=
(
x
/
y
)
^
(1
over
3);
Part2
=
Part1
+
x
/
y
+
x
^
2
/
y
+
(
x
^
3
/
y
^
5)
^
(1
over
3)
+
x
;
x
y
3
Ā +Ā
x
y
Ā +Ā
x
2
y
Ā +Ā
x
3
y
5
3
Ā +Ā
x
Expressions can be combined to form larger formulas
LargeEquation
=
Symbolic
.
Sqrt
(
Part1
/
Part2
);
x
y
3
x
y
3
Ā +Ā
x
y
Ā +Ā
x
2
y
Ā +Ā
x
3
y
5
3
Ā +Ā
x
PƔgina 99 de
108
Local Resources
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 1523497824 1883472662
Unicast packets 13273524 8620120
Non-unicast packets 112104 17646
Discards 0 0
Errors 0 0
Unknown protocols 0
File System
Get a listing of files with the
EnumerateFiles
function.
FileListing
=
Table
(0.5,
PadLR
(3), [3
inch
, 1",
new
(1",
null
,
null
,
HAligns
.
Right
)]) {
TextHeight
:
11pt;
var
list
=
EnumerateFiles
(
RootFolderPath
,
"*.nytril"
);
Row
{
Background
:
NytrilPalette
.
TableTitleBack
;
TextColor
:
NytrilPalette
.
TableTitleFore
;
"File Name"
;
"Created"
;
"Size"
;
};
foreach
(
var
e
in
list
) {
Row
{
if
(
each0
mod
2
==
0)
Background
:
95%;
e
.
FileName
;
Cell
{
TextFormat
:
"MM-dd-yyyy"
;
e
.
Created
;
Local Resources
PƔgina 100 de
108
};
e
.
Size
;
}
}
};
File Name
Created
Size
Angle Calculator.nytril
02-16-2025
7624
Body Mass Index.nytril
09-24-2025
1873
Chemistry.nytril
09-24-2025
4316
Color Picker.nytril
09-20-2023
1662
Data Tables.nytril
09-24-2025
3885
Doc With Sidebar.nytril
11-29-2021
849
Embedded Data.nytril
11-29-2021
1604
Equations.nytril
06-18-2025
9619
Examples Home.nytril
05-05-2026
2097
Finance.nytril
09-16-2025
899
Finger Binary.nytril
05-10-2026
3313
FizzBuzz.nytril
02-08-2024
650
Font Families.nytril
05-06-2026
1196
Hello World.nytril
10-06-2018
247
Input Form.nytril
09-24-2025
6443
International.nytril
08-30-2026
2987
Mad Lib.nytril
09-24-2025
5050
Matrix Calculations.nytril
03-08-2022
1955
Mortgage Calculator.nytril
09-24-2025
6781
Opacity Examples.nytril
09-24-2025
3296
Paragraph Examples.nytril
11-03-2021
1277
Party Signs.nytril
09-24-2025
1827
Random Walk.nytril
09-24-2025
7265
Read Text File.nytril
10-01-2023
308
SieveOfEratosthenes.nytril
02-09-2024
1213
Simple Document.nytril
09-24-2025
807
Source Reflection.nytril
09-24-2025
1192
Split The Bill.nytril
11-29-2021
3913
Sub Realm United States.nytril
05-06-2026
456
Table Edges.nytril
09-06-2020
4798
Time Sheet.nytril
09-24-2025
4021
White Paper.nytril
03-25-2026
12433
Get a listing of folders with the
EnumerateFolders
function.
readonly
FolderListing
=
Table
(0.5,
PadLR
(3), [3
inch
, 1"]) {
TextHeight
:
11pt;
var
list
=
EnumerateFolders
(
RootFolderPath
);
Row
{
Background
:
NytrilPalette
.
TableTitleBack
;
TextColor
:
NytrilPalette
.
TableTitleFore
;
"Folder Name"
;
"Created"
;
};
foreach
(
var
e
in
list
) {
Row
{
if
(
each0
mod
2
==
0)
Background
:
90%;
e
.
FileName
;
Cell
{
El lenguaje de programación Nytril
Ā®
PƔgina 101 de
108
TextFormat
:
"MM-dd-yyyy"
;
e
.
Created
;
};
}
}
};
Folder Name
Created
Citations
07-23-2021
Database
06-13-2024
Documentation Workflow
02-22-2026
Family Tree
08-07-2020
History
11-23-2021
Import
09-16-2025
JSON
04-22-2024
Mail Merge
07-14-2020
Map
08-09-2024
Math Homework
07-23-2021
Phylo
07-14-2020
Quotations
04-02-2025
Recipes
07-14-2020
Resumes
06-18-2020
Scuba Watch
06-03-2025
Web
04-29-2025
XML
09-25-2023
PƔgina 103 de
108
GenƩtica
Bases
Bases can be specified by using built-in symbols joined together with a + sign to form a sequence
Base1
=
Dna
.
Cytosine
+
Dna
.
Guanine
;
CG
Bases can be combined into a base set using the binary or operator
|
Set1
=
Dna
.
Thymine
|
Dna
.
Guanine
;
K
Longer sequences can be input by using the correct string prefix
DNA1
=
dna
"ACTG"
;
RNA1
=
rna
"UGAC"
;
Codons1
=
codon
"<MDI><AIHHPWIRR>"
;
Protein1
=
protein
"MDIAIHHPWIRR"
;
ACTG
UGAC
<MDI><AIHHPWIRR>
MDIAIHHPWIRR
Use string functions to generate several variations of a sequence
S1
DNAFunc
=
dna
"AC
{0}
TG"
;
Call
=
DNAFunc
(
Dna
.
N
);
Iterate
=
DNAFunc
(
each
[
dna
"-AA-"
,
dna
"-CC-"
,
dna
"-TT-"
,
dna
"-GG-"
]);
AC
N
TG
AC-AA-TG
AC-CC-TG
AC-TT-TG
AC-GG-TG
Sequences can be repeated by using using the
*
operator. with an integer
Promoter
=
dna
"TATAAA"
;
Repeats
=
Promoter
+
Dna
.
Gap
*
4
+
dna
"-ACTG-"
*
5
+
10;
TATAAA????-ACTG--ACTG--ACTG--ACTG--ACTG-----------
Sequences can also be constructed by placing the components adjacent to each other
Gene2
=
Promoter
30
dna
"CCTCCCAGG"
;
TATAAA------------------------------CCTCCCAGG
Common variants can be constucted without repeating or losing information
Highlight
=
{
TextBackground
:
Colors
.
LightGray
};
Original
=
dna
"ATTGGCCTTAACCCCCGATTATCAGGAT"
;
GenƩtica
PƔgina 104 de
108
class
VariantClass
{
var
Name
,
Sequence
;
Constructor
(
name
,
sequence
) {
Name
=
name
;
Sequence
=
sequence
;
}
}
VariantClass
[]
Variants
=
[
new
(
"Substitution"
,
Original
.
Substitute(14,
Highlight
Dna
.
Thymine
)),
new
(
"Insertion"
,
Original
.
Insert(15
..
17,
Highlight
dna
Dna
.
Gap
)),
new
(
"Deletion"
,
Original
.
Remove(15
..
17)),
new
(
"Inversion"
,
Original
.
Substitute(9
..
16,
Highlight
Original
[9
..
16]
.
Reverse
)),
new
(
"Copy Number"
,
Original
.
Remove(3
..
9)
.
Insert(3
..
16,
Highlight
Original
[3
..
9]
*
2)),
];
VarTable
=
Table
(
new
Edge
(2, 0,
Colors
.
LightGray
),
PadLR
(3), [1.5", 3"]) {
TextHeight
:
10pt;
NytrilStyle
.
HeaderRow
{
"Type"
;
"Variant"
};
foreach
(
var
v
in
Variants
) {
Row
{
v
.
Name
;
Original
;
};
Row
(
BorderB
(
new
(1pt, 0,
Colors
.
LightGray
))) {
Paragraph
{
ParAlignment
:
Right
;
RightIndent
:
5pt;
Tex
.
Rightarrow
;
};
v
.
Sequence
;
};
}
};
Type
Variant
Substitution
ATTGGCCTTAACCCCCGATTATCAGGAT
Ā āĀ
ATTGGCCTTAACCC
T
CGATTATCAGGAT
Insertion
ATTGGCCTTAACCCCCGATTATCAGGAT
Ā āĀ
ATTGGCCTTAACCCC
---
CGATTATCAGGAT
Deletion
ATTGGCCTTAACCCCCGATTATCAGGAT
Ā āĀ
ATTGGCCTTAACCCCTTATCAGGAT
Inversion
ATTGGCCTTAACCCCCGATTATCAGGAT
Ā āĀ
ATTGGCCTT
GCCCCCAA
ATTATCAGGAT
Copy Number
ATTGGCCTTAACCCCCGATTATCAGGAT
Ā āĀ
ATT
GGCCTTAGGCCTTA
ACCCCCGATTATCAGGAT
Sequences can also be read from files with the
ReadDocument
function.
readonly
GeneFile
=
IO
.
ReadDocument
(
res
"Sequences.fasta
");
readonly
WholeGene
=
GeneFile
.
BTBSCRYR;
readonly
GeneSlice
=
WholeGene
[10
..
99];
ShowGene
=
Block
{
Paragraph
{
Underline
;
WholeGene
.
Comment;
};
GeneSlice
;
};
El lenguaje de programación Nytril
Ā®
PƔgina 105 de
108
sample gene
atgtctaaagctggaaccaaaattactttctttgaagacaaaaactttcaaggccgccactatgacagcg
attgcgactgtgcagatttc
Revisions are used to control sequence formatting
GeneFormatted
=
Span
{
TextColumns
:
30;
TextDivision
:
5;
GeneSlice
;
};
atgtc taaag ctgga accaa aatta ctttc
tttga agaca aaaac tttca aggcc gccac
tatga cagcg attgc gactg tgcag atttc
Sections of a sequence can be formatted with the
Revise
function.
GeneStained1
=
GeneSlice
.
Revise([3
..
11, 72
..
74],
Stain1
);
GeneStained
=
GeneStained1
.
Revise(18
..
20,
Stain2
);
atgtctaaagctggaaccaaaattactttctttgaagacaaaaactttcaaggccgccactatgacagcg
attgcgactgtgcagatttc
RNA sequences are constructed in the same way using the operator
rna
RNASequence
=
rna
"ACUG"
+
Rna
.
Uracil
+
Rna
.
Adenine
;
ACUG
UA
DNA can be transcribed into RNA using the operator
rna
ComputedRNA
=
rna
GeneStained
;
AUGUCUAAAGCUGGAACCAAAAUUACUUUCUUUGAAGACAAAAACUUUCAAGGCCGCCACUAUGACAGCG
AUUGCGACUGUGCAGAUUUC
RNA can be converted into codons using the operator
codon
ComputedCodons
=
codon
ComputedRNA
;
<SKAGTKITFFEDKNFQGRHYDSDCDCADF
RNA or codons can be translated into a protein using the operator
protein
ComputedProtein
=
protein
ComputedRNA
;
SKAGTKITFFEDKNFQGRHYDSDCDCADF
Proteins can be transcribed back into RNA, creating an array of RNA sequences that could yield the
protein
[
UCU
,
AGU
,
UCC
,
AGC
,
UCA
,
UCG
,
AAA
,
AAG
,
GCU
,
GCC
,
GCA
,
GCG
,
GGU
,
GGC
,
GGA
,
GGG
,
ACU
,
ACC
,
ACA
,
ACG
,
AAA
,
AAG
,
AUU
,
AUC
,
AUA
,
ACU
,
ACC
,
ACA
,
ACG
,
UUU
,
UUC
,
UUU
,
UUC
,
GAA
,
GAG
,
GAU
,
GAC
,
AAA
,
AAG
,
AAU
,
AAC
,
UUU
,
UUC
,
GenƩtica
PƔgina 106 de
108
CAA
,
CAG
,
GGU
,
G
GC
,
GGA
,
GGG
,
CGU
,
CGC
,
CGA
,
AGA
,
CGG
,
AGG
,
CAU
,
CAC
,
UAU
,
UAC
,
GAU
,
GAC
,
UCU
,
AGU
,
UCC
,
AGC
,
UCA
,
UCG
,
GAU
,
GAC
,
UG
U
,
UGC
,
GAU
,
GAC
,
UGU
,
UGC
,
GCU
,
GCC
,
GCA
,
GCG
,
GAU
,
GAC
,
UUU
,
UUC
]
Proteins
Proteins can be input directly using using the operator
protein
Protein1
=
protein
"AVG"
;
AVG
Proteins can also be built up from smaller segments using the same rules as for dna and rna
Protein2
=
Protein1
Amino
.
Phenylalanine
Amino
.
Aspartate
;
AVG
FD
Codons can be computed from RNA sequences
AllRNATriplets
=
rna
AAGAGGGUGGCGGAGGG"
AAGAGGGUGGCGGAGGG"
AAGAGGGUGGCGGAGGG"
;
RNACodons
=
codon
AllRNATriplets
;
FFLLSSSSYY>>CC>WLLLLPPPPHHQQRRRRIIIMTTTTNNKKSSRRVVVVAAAADDEEGGGG
If the RNA sequence contains OR'd elements, the result will be an array of all possible codons
[A, R, N, D, C, E, Q, G, H, I, L, K, F, P, S, T, W, Y, V, >, <]
Proteins can also be created from a sequence of codons using the operator
codon
Codons
=
codon
"<FTGN>"
;
Protein3
=
protein
Codons
;
FTGN
Arrays of proteins can also be created from back-to-back sequences of codons
ProteinArray
=
protein
codon
"--<FTGN>----<MQS>--"
;
FTGN
MQS
A protein can be decomposed into its corresponding RNA sequence using using the operator
rna
[
GCU
,
GCC
,
GCA
,
GCG
,
GUU
,
GUC
,
GUA
,
GUG
,
GGU
,
GGC
,
GGA
,
GGG
,
UUU
,
UUC
,
GAU
,
GAC
]
This array can, in turn, be converted to DNA using the operator
dna
[
GCT
,
GCC
,
GCA
,
GCG
,
GTT
,
GTC
,
GTA
,
GTG
,
GGT
,
GGC
,
GGA
,
GGG
,
TTT
,
TTC
,
GAT
,
GAC
]
El lenguaje de programación Nytril
Ā®
PƔgina 107 de
108
Mutations
Long sequences can be built up from short sequences using the
+
operator.
CompleteRegion
=
dna
"TATAAA"
+
20
+
Gene2
;
TATAAA--------------------GCTGATTC
Sections can be inserted into existing sequences with the
Insert
function.
InsertedRegion
=
CompleteRegion
.
Insert(10,
dna
"AACCTTGG"
);
TATAAA----A----------------GCTGATTC
Sections can be removed from existing sequences with the
Remove
function.
DeletedRegion
=
InsertedRegion
.
Remove(16
..
28);
TATAAA----A-----TGATTC
Sections can be replaced with the
Substitute
function.
Substitution
=
DeletedRegion
.
Substitute(12
..
17,
dna
"GGGGG"
);
TATAAA----A-GGGGGGATTC
Repetitive sequences like Alu elements can be encoded to highlight unique sections
S1
AluElement
=
dna
"GCCGGGCGCGGTGGCGCGTGCCTGTAGTCCC
{0}
ACTCGGGAGGCTGAGGCTGGAGGATCGCTTGAGTCCAGGAGTTCTGGGCTG"
;
Stain
=
{
TextColor
:
Colors
.
White
;
TextBackground
:
Colors
.
Red
};
AluExample
=
AluElement
(
Stain
dna
"AGCT"
)
*
5;
GCCGGGCGCGGTGGCGCGTGCCTGTAGTCCC
AGCT
ACTCGGGAGGCTGAGGCTGGAGGATCGCTTGAGTC
CAGGAGTTCTGGGCTGGCCGGGCGCGGTGGCGCGTGCCTGTAGTCCC
AGCT
ACTCGGGAGGCTGAGGCTG
GAGGATCGCTTGAGTCCAGGAGTTCTGGGCTGGCCGGGCGCGGTGGCGCGTGCCTGTAGTCCC
AGCT
ACT
CGGGAGGCTGAGGCTGGAGGATCGCTTGAGTCCAGGAGTTCTGGGCTGGCCGGGCGCGGTGGCGCGTGCC
TGTAGTCCC
AGCT
ACTCGGGAGGCTGAGGCTGGAGGATCGCTTGAGTCCAGGAGTTCTGGGCTGGCCGGG
CGCGGTGGCGCGTGCCTGTAGTCCC
AGCT
ACTCGGGAGGCTGAGGCTGGAGGATCGCTTGAGTCCAGGAG
TTCTGGGCTG
Sequences can be formatted to fit in regular columns
AluFormat
=
Span
{
TextColumns
:
40;
TextDivision
:
5;
TextHeight
:
8pt;
AluExample
;
};
GCCGG GCGCG GTGGC GCGTG CCTGT AGTCC C
AGCT
ACTCG
GGAGG CTGAG GCTGG AGGAT CGCTT GAGTC CAGGA GTTCT
GGGCT GGCCG GGCGC GGTGG CGCGT GCCTG TAGTC CC
AGC
T
ACTC GGGAG GCTGA GGCTG GAGGA TCGCT TGAGT CCAGG
AGTTC TGGGC TGGCC GGGCG CGGTG GCGCG TGCCT GTAGT
CCC
AG CT
ACT CGGGA GGCTG AGGCT GGAGG ATCGC TTGAG
TCCAG GAGTT CTGGG CTGGC CGGGC GCGGT GGCGC GTGCC
TGTAG TCCC
A GCT
AC TCGGG AGGCT GAGGC TGGAG GATCG
CTTGA GTCCA GGAGT TCTGG GCTGG CCGGG CGCGG TGGCG
CGTGC CTGTA GTCCC
AGCT
A CTCGG GAGGC TGAGG CTGGA
GenƩtica
PƔgina 108 de
108
GGATC GCTTG AGTCC AGGAG TTCTG GGCTG