CX Setup Official Documentation (v2.0.N)
Table of Contents
- 1. About the Documentation
- 2. Comments
- 3. Data Types
- 4. String Escape Characters (v2.0.0+)
- 5. Keywords
- 5.1.
COUT
- 5.2.
ENDL
andENDL2
- 5.3.
STYLE
,FORE
andBACK
- 5.4.
TERMINATE
(0/1 argument overload) - 5.5.
TERMINATE
(2 arguments overload - v2.0.0+) - 5.6.
CIN
(0 arguments overload) - 5.7.
CIN
(1 argument overload) - 5.8.
RUN
- 5.9.
CIN
(2 arguments overload) - 5.10.
GETPASS
- 5.11.
SAFECIN
(1 argument overload) - 5.12.
SAFECIN
(2 arguments overload) - 5.13.
ECHO
- 5.14.
ECHORDIE
- 5.15.
PIPRUN
,PKGRUN
,NPMRUN
- 5.16.
REQUIRES
- 5.17.
REQINSTALL
- 5.1.
- 6. Cache
- 7. Environment Variables
- 8. CX Vars (v2.0.0+)
- 9. Polarity
- 10. Mathematical Operations (v2.0.0+)
- 11. File Operations (v2.0.0+)
- 12. Cache Size Declaration
- 13. Examples
- 14. Other tools
1. About the Documentation
The page/document you are currently looking at is the Official Documentation for the CX Setup scripting language. It was made primarily by Matthew (MF366) using Org Mode
on Emacs
, later exported to HTML
.
1.1. Licensing (Docs)
This documentation is licensed under the GNU Free Documentation License (GFDL). Therefore, all edits, reuses and whatnot of this documentation (valid for both Org
and HTML
versions of the docs) must comply with GFDL’s terms and conditions.
1.2. Contributing
If you wish to contribute to the documentation, I’d really appreciate it. However, there are some rules and guidelines you must follow:
- KISS: Keep It Simple, Stupid. Make sure your changes do not affect the simplicity and readability of the documentation in a negative way.
- If it ain’t broken, don’t redesign it. Do not propose changes to how the UI should look, as the current combination of HTML and CSS aims for simplicity, due to the fact it’s very objective.
- Editing the HTML export is like painting a screenshot — impressive, but pointless. Make Pull Requests for the
Org
files, not theHTML
ones. - Fixing typos is noble; flooding PRs with them is chaos. Typo squatting is perfectly fine and helpful, but don’t make too many Pull Requests to fix typos in a row, as it causes unnecessary spam. The best alternative is to “bundle” several typo fixes in one PR.
- There are no stupid questions — only unanswered ones (and I try to avoid those). If you have any questions, don’t hesitate to ask, as I try to reply to all. You can use the following e-mail:
real_mf366@yahoo.com
.
If those rules did not scare you away, the GitHub repository is right here. Thanks ahead for your contributions.
2. Comments
Just like in any other scripting language, CXSetup allows comments, albeit only single-line ones.
// This is a comment // This is another comment # This is a syntax error <!-- So is this --> // Comments must start with // // They also last until the end of the line, semicolon or not
3. Data Types
Keywords will be a matter of discussion later on, but they require arguments, which must be passed programatically. Each keyword argument must conform to a supported data type.
The available data types are:
- Bytes (rarely used - cannot be represented without a cache grab)
- String (text data -
"Hello, World"
) - Character (single character -
"a"
) - Integer (whole number, can be positive or negative -
5
) - Float (decimal number -
3.14
)
4. String Escape Characters (v2.0.0+)
This new feature available in version 2.0.0 and above is extremely useful when you need to create strings with characters CX Setup would otherwise consider to be special.
Escape Character | Conversion |
---|---|
\S |
Semicolon (; ) |
\? |
Question Mark (? ) |
\2 |
Double Quotes (" ) |
\\ |
Backslash (\ ) |
5. Keywords
In CXSetup, there are no functions, classes, or even variables. Scripts are built entirely from keywords — each acting like a mini-command that does one specific job.
Here is an example of keywords in use:
// COUT outputs something to the screen with no newline COUT ?? "Hello, World!"; // Let's try doing a neofetch RUN ?? "neofetch";
Below are the available keywords in CXSetup.
5.1. COUT
Quite possibly, one of the simplest keywords. Outputs something to the screen without a newline.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Outputs text to stdout . |
Accepts any amount of string arguments as the text to output. | None | None | COUT ?? "Hello, World!"; |
5.2. ENDL
and ENDL2
These ones are also extremely simple: all they do is output new lines to the screen. ENDL
outputs 1 newline, while ENDL2
outputs 2.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Outputs newlines to stdout (1 if ENDL , 2 if ENDL2 ). |
Does not accept or need any arguments. | None | None | ENDL; ENDL2; |
5.3. STYLE
, FORE
and BACK
These 3 keywords all serve the same general purpose: styling text. To better understand them, they’ve been split into 3 tables, one for each.
STYLE |
Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Applies a style to stdout (lasts until STYLE ?? "RESET_ALL"; ). |
Accepts one string argument representing the style to apply (must be one of: DIM , RESET , RESET_ALL , BRIGHT , NORMAL ). RESET is the same as RESET_ALL . |
None | ValueError - invalid style argument |
STYLE ?? "BRIGHT"; |
FORE |
Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Applies a foreground color to stdout (lasts until STYLE ?? "RESET_ALL"; or FORE ?? "RESET"; ). |
Accepts one string argument representing the color to apply (must be one of: RESET , BLACK , BLUE , GREEN , YELLOW , MAGENTA , RED , CYAN , WHITE , LIGHTBLACK_EX , LIGHTBLUE_EX , LIGHTGREEN_EX , LIGHTYELLOW_EX , LIGHTMAGENTA_EX , LIGHTRED_EX , LIGHTCYAN_EX , LIGHTWHITE_EX ). |
None | ValueError - invalid foreground color argument |
FORE ?? "YELLOW"; |
BACK |
Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Applies a background color to stdout (lasts until STYLE ?? "RESET_ALL"; or BACK ?? "RESET"; ). |
Accepts one string argument representing the color to apply (must be one of: RESET , BLACK , BLUE , GREEN , YELLOW , MAGENTA , RED , CYAN , WHITE , LIGHTBLACK_EX , LIGHTBLUE_EX , LIGHTGREEN_EX , LIGHTYELLOW_EX , LIGHTMAGENTA_EX , LIGHTRED_EX , LIGHTCYAN_EX , LIGHTWHITE_EX ). |
None | ValueError - invalid background color argument |
BACK ?? "LIGHTBLUE_EX"; |
5.4. TERMINATE
(0/1 argument overload)
This is the keyword responsible for terminating the script safely instead of waiting for the end of the file.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Terminates the execution of the current CX Setup script. | ExitCode - optional integer, defaults to 0 |
None | TypeError - ExitCode is not an integer |
TERMINATE ?? 4; // error code 4 |
5.5. TERMINATE
(2 arguments overload - v2.0.0+)
New in v2.0.0, this overload of TERMINATE
allows for more verbosity.
It can be given a custom exit message that will be shown if the ExitCode
is not 0.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Terminates the execution of the current CX Setup script. | ExitCode - integer; CustomMessage - string; |
None | TypeError - ExitCode is not an integer / CustomMessage is not a string/char |
TERMINATE ?? 4 ?? "Something unexpected happened!"; // error code 4 |
5.6. CIN
(0 arguments overload)
This is the overload of CIN
that requires no arguments.
CIN
is the most basic tool for getting input from the user (more specifically, stdin
).
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Reads input from the user (stdin ). |
This is the 0 arguments overload. For the other overloads, look up CIN (x arguments overload) in the Table of Contents, where x is either 0, 1 or 2. |
The user input. | None | CIN; // this will get input from the user |
5.7. CIN
(1 argument overload)
This is the overload of CIN
that requires 1 argument.
Sometimes, you might need to set a character limit on a user’s input. That way, even if they type more than that, only the first x
characters actually get cached.
If the character limit is set to 0 or a negative number, it will be ignored and it’ll be the same as calling CIN
with no arguments at all.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Reads input from the user (stdin ), while applying a character limit. |
CharLimit - integer, the character limit to apply |
The user input, with the character limit applied if greater than 0. | None | CIN ?? 4; // this will cache the first 4 characters of the user's input |
5.8. RUN
Given CXSetup is used in ContenterX’s setup scripts, it’s kind of an obligation for it to allow the creator of the script to run sub-processes programatically.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Runs a command with arguments (optional). | At least 1 argument must be given. The first argument is the command/process and the others are the arguments. Split the process’s arguments across different RUN arguments. |
None | InternalError - split process arguments across different arguments (see below) |
RUN ?? "sudo" ?? "apt" ?? "install" ?? "emacs"; // this will install Emacs. If you're root, that is :) |
5.8.1. The Number 1 cause of error when using RUN
The following statements are all incorrect:
RUN ?? "sudo apt install emacs"; RUN ?? "sudo" ?? "apt install emacs"; RUN ?? "sudo apt" ?? "install emacs"; RUN ?? "sudo" ?? "apt" ?? "install emacs"; RUN ?? "sudo" ?? "apt install" ?? "emacs"; RUN ?? "sudo apt install" ? "emacs";
The reason for it is that arguments for the process must be split across arguments for RUN
.
The correct way to do this installation would be:
RUN ?? "sudo" ?? "apt" ?? "install" ?? "emacs";
5.9. CIN
(2 arguments overload)
This is the overload of CIN
that requires 2 arguments.
Other than setting a character limit, this overload also allows you to set a custom prompt message for the input.
The only disadvantage is that applying a character limit becomes mandatory. However, you can get past that due to how the character limit works.
If the character limit is 0 or a negative number, no limit will be applied.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Reads input from the user (stdin ), while applying a character limit (if applicable) and using a custom prompt message. |
CharLimit - integer; PromptMessage - string, the custom prompt message to use |
The user input, with the character limit applied if greater than 0. | None | CIN ?? 4 ?? "Only 4 characters please: "; |
5.10. GETPASS
Sometimes, you may need to be more discreet with your inputs. For example, it’s not really a great idea to get passwords with CIN
, since it shows what is being typed.
GETPASS
solves such issue. With this keyword, you can safely get passwords without showing them on screen. This keyword’s only limitation is, unironically, the fact it cannot be limited to a certain number of characters (any amount is accepted).
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Reads input from the user (stdin ) with echo disabled, meaning it does not show on screen what is being typed by the user. |
PromptMessage - mandatory string, the custom prompt message to use |
The user input. | None | GETPASS ?? "Insert your password, please: "; |
5.11. SAFECIN
(1 argument overload)
CIN
has yet another big issue: when it is given a character limit, it makes sure the input doesn’t go beyond the limit. However, it does not make sure the input has the specified length.
This might not seem problematic, but it becomes when cache grabs are involved. Cache grabs will be a matter of discussing later, due to their complexity. However, here is a small representation of the issue.
>>> CIN ?? 4 ?? "Your input please: "; Your input please: Good >>> COUT ?? c0:4l:1:3:n; Good
No issue at first. Well let’s move on to the second example.
>>> CIN ?? 4 ?? "Input: "; Input: Ok >>> COUT ?? c0:4l:1:3:n; Ok >>> CIN ?? 1 ?? "Input: "; Input: A >>> COUT ?? c0:4l:1:3:n; OkA
Now, imagine the first input was done to ask for the path of a very important file. But, before the file is used, another input is done.
Now, CXSetup would think the file is named OkA
, when it is actually named Ok
.
To avoid this issue, we can safely use SAFECIN
. To make sure the input is as long as we want it to be, SAFECIN
pads the right of the input with spaces (if necessary) until the length of the input matches.
Then, when doing the cache grab, we can trim the spaces if necessary.
Here’s our example, but refined. To better illustrate it, the meaningful whitespace characters have been represented as [SPACE]
.
>>> SAFECIN ?? 4; An input is required (press Enter to ignore it): Ok >>> CIN; An input is required (press Enter to ignore it): A >>> COUT ?? c0:4l:1:3:n; Ok[SPACE][SPACE] >> COUT ?? c0:4l:1:3:b; // the little b means trim both sides - we'll talk about it soon Ok
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Reads input from the user (stdin ), making sure its length matches the character limit we apply. |
CharLimit - integer, length of the input |
The user input, with length matching the CharLimit . |
None | SAFECIN ?? 4; |
5.12. SAFECIN
(2 arguments overload)
Sometimes, it might also be useful to specify exactly what input must be given.
For example, which of these scenarios is clearer from the user side (a.k.a. by someone who doesn’t see the underlying script), A or B?
Scenario A:
Your input, please:
Scenario B:
Please insert a valid path to the configuration file:
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Reads input from the user (stdin ), making sure its length matches the character limit we apply. Is compatible with custom prompt messages. |
CharLimit - integer; PromptMessage - string, the prompt message to show to the user |
The user input, with length matching the CharLimit . |
None | SAFECIN ?? 8 ?? "Your username please: "; |
5.13. ECHO
ECHO
does not write to the screen by default. It is used to write to a file instead. If you wish to output tostdout
, please use theCOUT
keyword.
Another useful feature in a scripting language is the ability to write to a file. Even though ECHO
is limited, it is still a very good option when it comes to writing to files.
Note that ECHO
does not overwrite files. In fact, there are 2 special cases and a more generic one:
- Generic Case:
ECHO
successfully writes to a file. FileExistsError
:ECHO
fails and throws an Exception. This happens if the file already exists.- Reverts to
COUT
: Yes, in theory, you can useECHO
instead ofCOUT
, if you giveECHO
an empty string instead of an actual file path. However, it’s not really that good of an idea.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Writes to a file or reverts back to COUT if the file path is an empty string. |
DataToWrite - string, the data to write; FilePath - string, the file path to write to (if empty, reverts back to COUT ?? /DataToWrite/; ) |
None | FileExistsError - the file exists |
ECHO ?? "Hello, World!" ?? "hello.txt"; |
5.14. ECHORDIE
A more extreme version of ECHO
, this one is fine with the possibility of overwriting files. Due to this fact, it ought to be used carefully.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Writes to a file or reverts back to COUT if the file path is an empty string. |
DataToWrite - string, the data to write; FilePath - string, the file path to write to (if empty, reverts back to COUT ?? /DataToWrite/; ) |
None | None | ECHO ?? "Hello, World!" ?? "hello.txt"; |
5.15. PIPRUN
, PKGRUN
, NPMRUN
The main issue with RUN
is the fact it ends up hardcoding values.
For example:
RUN ?? "pip" ?? "install" ?? "simple_webbrowser";
What if we want the system to tells us exactly what version of pip
, npm
or the package manager to use?
The solution is extremely easy.
PIPRUN ?? "install" ?? "simple_webbrowser";
All of these work essentially the same way as RUN
(they’re wrappers), so their tables have been omitted (see the RUN
command for more information).
5.16. REQUIRES
Another important thing when it comes to installing software are requirements!
Note that REQUIRES
merely defines requirements, it does not install them.
Due to the slight complexity of one of its arguments, instead of just showing the table we’ll also show a demonstration with comments.
>>> REQUIRES ?? 0 ?? "neofetch"; // the 0 stands for "Install using system package manager" >>> REQUIRES ?? 0 ?? "cowsay"; // worth mentioning the command does not output anything or install anything >>> REQUIRES ?? 1 ?? "MF366-Coding/WPlugZ-CLI"; // the 1 uses ContenterX itself to install ("Install using ContenterX") >>> REQUIRES ?? 2 ?? "NCapybaraLib"; // the 2 stands for "Install using pip" >>> REQUIRES ?? 3 ?? "express"; // source number 3 stands for "Install using npm" >>> REQUIRES ?? 4 ?? "https://github.com/MF366-Coding/WriterClassic/releases/download/v11.0.0/WriterClassic_v11.0.0_SetupWizard_x64.exe"; // source number 4 stands for "Get binary from a direct link" - you'll be using this a lot in Windows >>> REQUIRES ?? 5 ?? "sl"; // this is a ValueError - only sources [0,4] are available
So, in summary:
First Argument | Meaning |
---|---|
0 | Install using the system’s package manager. |
1 | Install using ContenterX. |
2 | Install using pip. |
3 | Install using npm . |
4 | Download a binary via a direct link. |
Anything else | ValueError : only sources 0 to 4 are available. |
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Marks something as a dependency but does not install it. | Source - integer, the source to use; DependencyName - string, the name of the dependency (or its link if the Source is 4 ). |
None | ValueError - invalid source ID |
REQUIRES ?? 0 ?? "neofetch"; |
5.17. REQINSTALL
After marking all the dependencies you need, it’s time to install them. And that’s exactly what this command does. Now, you can call REQINSTALL
more than once in the same script, but keep in mind that after each call, the list of dependencies is wiped clean.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Installs previously marked dependencies. | None | None | SyntaxError - REQINSTALL takes 0 arguments, but more than 0 were given |
REQINSTALL; |
6. Cache
We have not discussed all keywords yet, but they operate on something slightly more complex: cache.
Instead of variables, in CXSetup, you have cache. We’ve already discussed certain commands that modify it (such as CIN
), but what more can be done with it?
6.1. Reading
There’s a whole new syntax when it comes to accessing caches. Its official name is cache grabbing.
A cache grab can have any data type, since it does not matter which command saved the cache.
For example, you can do a CIN
operation, which saves a string. But that hardly matters, because you can access that same cache as if it were an integer.
The syntax for cache grabs is the following and can be used as arguments for keywords:
AB:CD:E:F:G
So what does each letter stand for? Let’s see:
- A: this must always be set to a lowercase C (
c
). - B: an integer. This is used as the start index for the cache grab. For example,
0
in this case means start from the beginning. - C: an integer. Can be an end index or the length of the cache grab. For example,
5
can either mean end at the index before 5 (4) or end 5 bytes after the starting index (with 0 as the starting index, it would be 5). - D: a single character, must be one of
l
ore
. This is the value that decides whether value C is interpreted as the end index (e
) or the length of the cache grab (l
). - E: an integer. Represents the step value. This represents the pattern to perform. Let’s say we’re cache grabbing
Hello, World!
. Using a step value of 1 (default), we’d getHello, World!
but a step value of 2 would give us the same string, but skipping each odd-indexed character (indexing starts at 0). So,Hlo ol!
. - F: an integer. Represents the data type the cache grab must be casted as. (See table below.)
- G: a single character, must be one of
b
,r
,l
,n
,B
,R
,L
,N
,v
,e
,k
,m
. This value must always be set ton
if we’re not dealing with cache grabbed strings. If it’s strings we’re dealing with, however, we can use this value to decide whether spaces should be trimmed or not (n
is trim none), and from what direction (r
is trim right,l
is trim left andb
is trim both sides). This is useful when used alongsideSAFECIN
, for example (since it pads the input with spaces).
Here’s an example:
>>> SAFECIN ?? 6 ?? "6 characters only please: "; 6 characters only please: Hello! >>> COUT ?? c0:6l:1:3:b; // the first 6 characters, no pattern, output as string, trim both sides Hello!
D Value (Interpret Value C as) | Meaning |
---|---|
l |
Length of the cache grab. |
e |
End index. |
Anything Else | ValueError : only l and e are allowed as values |
F Value (Data Type Conversion) | Meaning |
---|---|
0 | Void - incompatible, will throw an error. |
1 | Integer - a whole number |
2 | Floating point - requires EXACTLY 4 bytes for a successful cache grab conversion. Any more or any less will throw an error. |
3 | String |
4 | Boolean - a True or False value. If the bytes are not empty, it will ALWAYS be True. |
5 | Single Character - a single character, not widely used |
6+ | Bytes/Garbage Values - the bytes themselves - not widely used |
-1 or lower | ValueError : only positive values are allowed |
G Value (Trim Direction) | Meaning |
---|---|
n |
Don’t trim. If dealing with anything other than strings, this is the only option that won’t raise an error. |
l |
Trim left. Trim whitespace characters to the left of the string. |
r |
Trim right. Trim whitespace characters to the right of the string. |
b |
Trim both sides. Trim whitespace characters at both ends of the string. |
N |
Don’t trim, but change to uppercase. |
L |
Trim left, but change to uppercase. |
R |
Trim right, but change to uppercase. |
B |
Trim both sides, but change to uppercase. |
m |
Don’t trim, but change to lowercase. |
k |
Trim left, but change to lowercase. |
e |
Trim right, but change to lowercase. |
v |
Trim both sides, but change to lowercase. |
Anything Else | ValueError : only the above specified values are allowed |
6.2. Writing
Writing can only be done through keywords, albeit in 2 different ways:
- Directly: A direct modification involves the script creator themselves using a method that does not require any sort of confirmation from the user when it comes to modifying the cache.
- Indirectly: An indirect modification involves obtaining input from the user or the environment.
6.2.1. Keywords that Write to the Cache Directly
CLEAR
- clears the cacheSET
- writes to the cache- All Mathematical Operations (new in version 2) - all of them write the result to the cache
CLEAR
This command clears the cache (fills it with empty bytes).
Summary Arguments Returns Exceptions Example Clears the cache. None None SyntaxError
-CLEAR
takes 0 arguments, but more than 0 were givenCLEAR;
SET
This command writes a value to the cache.
Summary Arguments Returns Exceptions Example Writes a value to the cache. Value
- the value to write to the cache, can be of any data typeNone None SET ?? 44.5;
6.2.2. List of Keywords that Write to the Cache Indirectly
CIN
(any of the overloads) - writes user input to cacheGETPASS
- writes user input to cacheSAFECIN
(any of the overloads) - writes user input to cache
6.3. Benefits of caching
Cache is an extremely powerful tool, as it allows for many things. 2 examples are shown below:
- Constants. The equivalent to constants would be this (at the start of the script):
SET ?? 7;
and accessing it like this:c0:1l:1:1:n
. - User Feedback. Hey, the user knows best, right? You can obtain file paths, make decisions and much more, based on the user input.
7. Environment Variables
Environment variables are yet another useful tool at your disposal as a creator of a CXSetup script. These are strings, but their syntax is different.
Example:
>>> COUT ?? v'HOME'; // For this example, we're on Linux /home/username >>> COUT ?? v'VAR_THAT_DOESNT_EXIST'; VAR_THAT_DOESNT_EXIST
Syntax:
v'VARNAME'
This is a great way to find values such as home directories, that are OS and usually machine-dependent.
8. CX Vars (v2.0.0+)
Other than environment variables, there are also CX Setup Variables, new to v2.0.0.
While the feature is still pretty limited, the next versions will have more variables.
Variables can be used as arguments. In such case, they’re written WITHOUT double quotes, just like regular text. They will be recognized as variables in case they are valid ones.
Variable | Data Type | Value | Example |
---|---|---|---|
polarity |
Boolean/integer | The polarity of the script. | PROD ?? 7 ?? polarity; // 0 if negative |
cxSetup.Version |
String | The version of CX Setup. | COUT ?? "You're running: CXSetup "; COUT ?? cxSetup.Version; |
9. Polarity
Alongside cache, there’s yet one more extremely useful feature that needs to be discussed: polarity. Its official name is Specialized Boolean Cache and it allows for code paths, kind of the same way if/else allows for different operations based on a comparison, in other languages.
There are exactly 2 commands that can modify the polarity of the script, but before we discuss them, we should discuss how to add polarity to our scripts.
9.1. Defining code paths
Let’s say, for example, there’s a dependency our setup script needs, but in a version of the OS, it’s named x-dev
and in another version of the very same OS, it’s named x-pkg
. Clearly, this is going to raise issues. Thankfully, we can instruct the user on how to check what the name is and then ask them if it’s one or the other. The only problem is that we cannot achieve comparisons.
Sure, we could do something like this, since both package names have exactly 5 characters:
COUT ?? "Here's how to check whether the name is x-dev or x-pkg: etc etc etc..."; ENDL; SAFECIN ?? 5 ?? "The name: "; PKGRUN ?? "install" ?? c0:5l:1:3:b; TERMINATE;
However, there are several issues with this script.
- The user can input ANY name, which is problematic: they could be installing something they don’t know is safe.
- The user isn’t restricted to 5 characters, they can insert a string with 1, 2, 3, etc.
So, how can we fix this code? Using polarity. Polarity has quite an unusual syntax.
In a script, polarity always starts off positive. Here’s an example of a positive keyword:
+ENDL; // positive keyword - can only be done like this in v2.0.0 and above
You can, however, omit the +
sign and it will still be interpreted as a positive keyword:
ENDL; // still a positive keyword - the only correct way to use one in v1.0.0
A negative keyword would look like this:
!ENDL; // negative keyword
There is also another behavior declaration available - the indifferent declaration, introduced in v2.0.0:
&ENDL; // indifferent keyword - new in v2.0.0
Indifferent keywords will run no matter what: they’re indifferent to the polarity.
Getting back to our script, here’s a refined version:
// the polarity starts off positive so we don't have to worry about COUT not running COUT ?? "Here's how to check whether the name is x-dev or x-pkg: etc etc etc..."; ENDL; // command is positive so it runs, because the polarity is also positive COUT ?? "Is the correct name 'x-dev'?"; ENDL; YAYORNAY; // polarity has now changed: YAYORNAY modified it PKGRUN ?? "install" ?? "x-dev"; // the command above is positive so it will only run if the polairty is positive (if the user pressed 'y') !PKGRUN ?? "install" ?? "x-pkg"; // the command above is negative so it will only run if the polarity is negative (if the user pressed 'n') // we can clear the polarity by doing an indifferent reset &RESET; // That way, we don't have to do TERMINATE; !TERMINATE;, because we already know the polarity is going to be positive TERMINATE; // or, better: we could have just done &TERMINATE; // Done!
Quite a complex example, I admit. Any command can be negated.
9.2. RESET
This keyword simply resets the cache back to positive.
That is why it should only be used with a !
or a &
declarations, as it does not make sense to RESET an already positive polarity.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Resets the script’s polarity back to POSITIVE. | None | None | SyntaxError - RESET takes 0 arguments, but more than 0 were given |
RESET; |
9.3. INVERT
This keyword inverts the polarity.
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Inverts the script’s polarity. | None | None | SyntaxError - INVERT takes 0 arguments, but more than 0 were given |
INVERT; |
9.4. YAYORNAY
Gets input from the user and adjusts the polarity accordingly (y
= POSITIVE, n
= NEGATIVE)
Summary | Arguments | Returns | Exceptions | Example |
---|---|---|---|---|
Changes the polarity to positive if the user input is y or to negative if it’s n. | None | None | SyntaxError - YAYORNAY takes 0 arguments, but more than 0 were given |
YAYORNAY; |
9.5. Other polarity-related keywords
There are other keywords that can affect the polarity of the script, however. They are:
PATH.EXISTS
- Verifies if a given path existsDIR.EXISTS
- Verifies if a given directory existsFILE.EXISTS
- Verifies if a given file exists
10. Mathematical Operations (v2.0.0+)
Mathematical operations, a new v2.0.0 feature, can prove themselves useful from time to time.
They are done through keywords:
Keyword | Amount of arguments | Underlying Operation (Return Result) | Example |
---|---|---|---|
SUM |
Any | Sum of all numeric values. | SUM ?? 4 ?? 7; // this will write 11 to the cache |
SUB |
2 | Subtracts the second argument from the first. | SUB ?? 4 ?? 7; // this will write -3 to the cache |
DIV |
2 | Divides the first number for the second. Truncates if they’re both integers. | DIV ?? 10 ?? 5; // this will write 2 to the cache |
PROD |
2 | Multiplies the first argument with the second one. | PROD ?? 2 ?? 7; // this will write 14 to the cache |
REM |
2 | Calculates the remainder of a division between the first argument and the second one. | REM ?? 10 ?? 7; // this will write 3 to the cache |
ABS |
1 | Calculates the absolute value of a number. | ABS ?? -5; // this will write 5 to the cache |
ROUND |
2 | Rounds a float (first argument) to N decimal digits, where N is an integer (second argument). | ROUND ?? 5.764 ?? 2; // this will write 5.76 to the cache |
11. File Operations (v2.0.0+)
What’s a setup script without file-related operations? Well, these are new in v2.0.0 and are already powerful enough for most use cases.
They can be split into 2 groups:
- The ones who modify the polarity. These evaluate a boolean value (such as: “does this file exist?”) and modify the polarity accordingly.
- The ones who modify the cache. These return a value that is written to the cache.
- The ones who don’t return anything. These operate on the environment without modifying the cache or the polarity.
They are done through keywords:
Keyword | Modifies what? | Underlying Operation (Return Result) | Example |
---|---|---|---|
PATH.EXISTS |
Polarity | Verifies if a given path (string) exists. | PATH.EXISTS ?? "/path/to/file"; |
DIR.EXISTS |
Polarity | Verifies if a given path (string) exists and is a directory. | DIR.EXISTS ?? "/path/to/dir"; |
FILE.EXISTS |
Polarity | Verifies if a given path (string) exists and is a regular file. | FILE.EXISTS ?? "/path/to/file"; |
ECHO |
N/A | Writes data (string) to a file path (string) without overwriting files. | ECHO ?? "hello" ?? "/path/to/file"; |
ECHORDIE |
N/A | Same as ECHO but overwrites files if necessary. |
ECHORDIE ?? "hello" ?? "/path/to/file"; |
12. Cache Size Declaration
By default, the cache takes up 256 bytes, which may be too much for some scenarios.
Thankfully, you can define exactly how many bytes you want using cache size declarations.
These are performed at the very start of the file (first line). If the first line is equals to an integer, that integer will be interpreted as the cache size.
You may omit it, if you’re fine with the default, but it’s good practice to always define it.
70 // that was the cache size declaration // make sure there is nothing else but the integer in the first line, as that is very important // negative cache sizes or ones that equal 0 are invalid (minimum is 1 byte) // Your code goes here... COUT ?? "Hello, World!"; // ...
13. Examples
Below, you can find example scripts.
13.1. Writing Hello, World! to a file called cxsetup-playground
200 // Constants SET ?? v'HOME'; SET ?? "/cxsetup-playground"; COUT ?? "Does a file named cxsetup-playground exist in your home directory?"; ENDL; YAYORNAY; // If it doesn't exist, we'll get rid of it. RUN ?? "rm" ?? c0:199l:1:3:b; // trim both sides -> very important // Invert the polarity to negative if positive INVERT; // now, the polarity is 100% sure negative // Let's save the file // Of coruse we could have just used ECHORDIE, but this is supposed to showoff the power of this language sooo !ECHO ?? "Hello, World!" ?? c0:199l:1:3:b; !COUT ?? "Finished."; !ENDL; !TERMINATE; // done
13.2. Global Cheat Sheet (for v1.0.0)
50 // That is a cache size declaration // This is a comment. COUT ?? "String"; COUT ?? 4; // Integer COUT ?? 5.7; // Float COUT ?? v'HOME'; // If the variable exists, its value is used COUT ?? v'TESTING'; // If it doesn't, its name is used instead COUT ?? "a"; // Single character CIN; // get input CLEAR; // clear the cache CIN ?? 5; // 5 character limit CLEAR; CIN ?? 4; CLEAR; // you don't have to split instructions across lines if you don't want to CIN ?? 4 ?? "Your input, if you may: "; // custom prompt message CLEAR; SAFECIN ?? 5; // better input management CLEAR; SAFECIN ?? 4 ?? "Better input: "; // custom prompt message ENDL2; // 2 new lines COUT ?? c0:4l:1:3:b; // Cache Grab: starts at 0, length = 4, no pattern, as string, trim both sides ENDL; // 1 new line !TERMINATE; // this won't run since the polarity is positive INVERT; // inverts the polarity TERMINATE; // this won't run because, now, the polarity is negative INVERT; // neither will this !INVERT; // but this will ECHO ?? "Back to normal." ?? ""; // the filepath is empty, so this will just COUT ENDL; ECHO ?? "Hello, World!" ?? "hello.txt"; // write to a file, as long as it does not exist ECHORDIE ?? "Hello, World!" ?? "forced_hello.txt"; // write to a file, even if that means overwriting it FORE ?? "BLUE"; BACK ?? "YELLOW"; STYLE ?? "DIM"; COUT ?? "Blue text on a yellow background, with a dim style"; STYLE ?? "RESET_ALL"; ENDL2; GETPASS ?? "Enter the secret code: "; // Same as CIN ?? 0 ?? "Enter the secret code: " but hides the characters that are being typed CLEAR; RUN ?? "neofetch"; // runs a subprocess RUN ?? "clear"; // this will clear the screen, for example PKGRUN ?? "install" ?? "figlet"; // on Debian, this would be the same as RUN ?? "apt" ?? "install" ?? "figlet"; PIPRUN ?? "install" ?? "PyLocalizer"; // same as RUN ?? "pip" ?? "install" ?? "PyLocalizer", but uses the pip version recommended by the system NPMRUN ?? "install" ?? "express"; // same as RUN ?? "npm" ?? "install" ?? "express", but makes sure the global npm installation is used CLEAR; SET ?? "sl"; // save PyLocalizer as a constant to the cache REQUIRES ?? 0 ?? c0:2l:1:3:b; // mark sl as a requirement for the package manager REQUIRES ?? 1 ?? "PyLocalizer"; // mark PyLocalizer as a requirement for PIP REQINSTALL; // install all previously marked requirements YAYORNAY; // if the user inputs y, the polarity becomes positive. Otherwise, it becomes negative !COUT ?? "Polarity is negative. Exiting with error code 1"; !ENDL; !TERMINATE ?? 1; // terminate with error code 1 TERMINATE; // terminate with success code 0, same as TERMINATE ?? 0; COUT ?? "Hi"; // this won't run
14. Other tools
CXSetup isn’t limited to the interpreter.
- CX Setup Syntax Highlighter (can be used in the terminal or imported and used from a Python file)
- CX Setup Linter (coming soon)
- CX Setup Language for VSCode (syntax highlighting for Visual Studio Code)
- CX Setup Language Major Mode for Emacs (syntax highlighting for Emacs)