Elvis can evaluate expressions involving numbers, strings, and boolean values, using a C-like syntax. These are used in several EX commands, one VI command, and a couple of other situations.
There are two syntaxes. The normal syntax is extremely similar to C, and is used in circumstances where you probably would never use a literal value, such as for the :if command. The simpler syntax makes literal values easier to enter, while still making the full power of the expression evaluator available if you need it.
The normal syntax is intended to resemble the syntax of the C programming language very closely. You can't define your own functions or use flow-control constructs though; you can only use expressions. In traditional C documentation, these would be called "rvalues." Basically that means you can use literal values, option names, operators, parentheses, and some built-in functions.
There is no special way to enter Boolean literals. All of the boolean operators accept "false", "0", and "" as Boolean false values, and anything else as a Boolean true value. If you want to enter a Boolean literal, just use the string literals "true" and "false".
The following examples produce exactly identical results.
You can also use option names in elvis the same way you would use variable names in C.
Additionally, a dollar sign followed by the name of an environment variable is replaced by the value of that environment variable. If there is no such environment variable, then elvis will act as though it exists and has a null value.
In some circumstances, you can use a dollar sign followed by a digit to access special arguments. This is used in error messages and also in the values of a few options, as described in section 13.5. These special arguments can only be supplied by elvis' internal code, and it only supplies them in a few special circumstances so you can't use them in :calculate, for example.
The :eval command uses the simpler syntax, and the :echo command displays its arguments. These commands can be used together to experiment with the simpler syntax, the same way we used :calculate to experiment with the normal syntax.
.------------------.--------------------------------------------. | FUNCTION(ARG) | RETURN VALUE | |------------------|--------------------------------------------| | strlen(string) | number of characters in the string | | toupper(string) | uppercase version of string | | tolower(string) | lowercase version of string | | isnumber(string) | "true" iff string is a decimal number | | hex(number) | string of hex digits representing number | | octal(number) | string of octal digits representing number | | char(number) | convert number to 1 ASCII char, as a string| | exists(path) | "true" iff file exists | | dirperm(path) | string indicating file attributes | | dirfile(path) | filename.ext part of a path | | dirname(path) | directory part of a pathname | | dirdir(path) | directory, like dirname(file) | | dirext(path) | extension (including the . ) | | basename(path) | filename without extension | | elvispath(file) | locate a file in elvis' configuration path | | knownsyntax(file)| "true" iff file's extension is in elvis.syn| | buffer(bufname) | "true" iff buffer exists | | feature(name) | "true" iff a given feature is supported | ^------------------^--------------------------------------------^Some of these deserve further comment.
The isnumber() uses the same test that the operators use when deciding whether to use the string version or the number version of their behavior. You can use isnumber() to predict how operators will behave.
The hex() and octal() functions return strings which look like C-style hex or octal constants, respectively. The isnumber() function will return false when passed one of these strings; they are no longer considered to be numbers. In fact, the only reason you can use hex and octal literals is because they are converted into decimal strings by the parser, before evaluation even begins. The following example demonstrates that hex literals are converted to decimal, and that the value returned by hex() is something else.
The char() function returns a one-character string; that character's decimal value will be the argument number. For example, "char(65)" returns "A". Note that the returned value does not look quite like a character constant.
The dirperm() function returns one of the following strings to indicate the file's type and permissions:
The elvispath() function searches through the directories listed in the elvispath option's value, looking for the argument file name. If it is found, then the full pathname of the file is returned; otherwise it returns a null string.
The knownsyntax() function determines whether the given file can be displayed in the syntax display mode. It does this by looking for the file name extension in the elvis.syn configuration file.
The feature() function is intended to allow you to write EX scripts which work with different configurations of elvis. For example, you can compile elvis without support for the hex display mode; if you do that, then feature("hex") will return false. Currently feature() returns true for all supported display modes, and false for anything else. As new features (not necessarily display modes) are added to future versions of elvis, I expect to add them to feature()'s list.
The :if command evaluates its argument using the normal syntax. If the resulting value is any Boolean true value then a flag is set; otherwise the flag is reset. After that, you can use :then and :else commands to conditionally execute some commands, depending on the state of that flag.
The :eval command evaluates its arguments using the simpler syntax. The resulting string value is then interpreted as an EX command line. This gives you a way to use the expression evaluator with commands which otherwise wouldn't evaluate expressions.
The :let command allows you to change the values of options. Its syntax is ":let option=expression", where expression is any expression using the normal syntax. You can use this to change the value of any option.
Note that the = operator only works this way when used with the v command for marking characters. If you visibly mark lines, or use the traditional =movement syntax, then elvis will send the selected lines though the external filter program named in the equalprg option.
The # command doesn't use expressions, but it does perform some simple math.
The full power of the expression evaluator is available; you can use it to do more than just expand environment variable names. For example, you could store the name of a file in one of the user options, and then later use that option name in parentheses wherever a filename was expected.
If you use this trick, remember that it only works when elvis is expecting a file name. It won't work when invoking external programs, because elvis doesn't know which program arguments are supposed to be file names. Elvis always passes program arguments literally.
Recall that when a backslash character is followed by an alphanumeric character, both the backslash and the alphanumeric character become part of the resulting value. This was done mostly for the benefit of file names. If the backslash was always dropped then MS-DOS users would have a heck of a time entering pathnames of files! By making the backslash a little smarter, we avoid that problem.
To simplify the task of writing portable ex scripts, elvis sets the $1 parameter to either a slash or a backslash, depending on the operating system. For example, the default "elvis.ini" file uses this trick to execute the customization file in the user's home directory, via the command shown below. The f option has been set to either ".exrc" or "elvis.rc" by this point.