unknown_document

We couldn't find that page... Were you looking for one of these?


Lua's Concatenation Operator
Concatenation refers to the common operation of joining of two strings . In Lua, when two strings are concatenated the result is a third string that contains the characters of the first string followed by the characters contained in the second string: local x = "left side" local y = "right side" print ( x .. y ) -- left sideright side -- separating strings with a literal " " print ( x .. " " .. y ) -- left side right side Note that the concatenation is literal: no space is added between two concatenated strings. When concatenating sentences be sure to include a literal space between the two strings. Concatenation also works with numbers , by first coercing each value to its string-equivalent then concatenating those values: local x = 2 local y = 3 print ( x .. y ) -- 23 Note that concatenation won't work with other value fundamentals, such as booleans or nil .
Lua's Relational Operators
Relational Lua's relational operators are more or less the same as in most other languages: local x = 2 local y = 3 print ( x > y ) -- false print ( x < y ) -- true print ( x >= y ) -- false print ( x <= y ) -- true print ( x <= x ) -- true print ( x >= x ) -- true The relational operators allow one to determine when values are greater-than or less-than others, and include a variant that also allows the variables to be equal. Equality Lua's equality operator uses two equal signs == , which is differentiated from the variable assignment operator = which uses a single equal sign: local x = 2 local y = 3 print ( x == y ) -- false print ( x == x ) -- true This operator returns true when the two values are equal, otherwise it returns false . Inequality Like equality , it can often be useful to know when two values are not equal. Lua implements this using the ~= operator: local x = 2 local y = 3 print ( x ~= y ) -- true print ( x ~= x ) -- false This operator returns false when the two values are equal, otherwise it returns true .
Lua's Arithmetic Operators
Basics Let's first take a look at the basics, addition , subtraction , multiplication , and division . These work as one would expect: local x = 2 local y = 3 print ( x + y ) -- 5 print ( x - y ) -- -1 print ( x * y ) -- 6 print ( x / y ) -- 0.66666666666667 Negation Whereas almost all languages allow a value to be negated by multiplying it by -1 to negative it, Lua additionally allows a value to be negated by simply prefixing it with - . local x = 2 local y = 3 print ( - x ) -- -2 print ( - y ) -- -3 print ( x + - y ) -- -1 Note that negation occurs independently of other operators, as shown in the last case. We will learn more about this in a moment when we discuss precedence . Exponentiation Lua supports exponentiation with the ^ operator: local x = 2 local y = 3 print ( x ^ y ) -- 8.0 print ( y ^ - x ) -- 0.11111111111111 Modulus Like many programming languages modular arithmetic in Lua uses the % operator. While the topic of modular arithmetic is well outside the scope of learning about Lua, this is a useful but often misunderstood function, so let's give it a quick review. To calculate a % b, one first finds the largest integer k such that multiplying k by b is less than a , then the result is the difference or remainder, a - kb . local x = 2 local y = 3 print ( x % y ) -- 2 print ( y % x ) -- 1 In the first example y is greater than x , so the remainder is simply x . In the second example the largest integer k is 1 , so that the remainder is 3-2=1 . Bitwise Lua also supports the basic bitwise operations. While bitwise operations are very important in computing, they are used in a fairly narrow range of applications so we won't spend too much time on them other than to show which operations are supported and a simple example of how they work: local x = 2 local y = 3 print ( x & y ) -- 2 print ( x | y ) -- 3 print ( x ~ y ) -- 1 You can learn more about bitwise operations here .
Lua's Length Operator
Lua includes a length operator # which (in theory) returns the number of items contained in the value to which it is applied. However, it is frankly a bit wonky and can give unexpected results if used outside of a fairly narrow range of applications. Part of the wonkiness is that it behaves differently depending on the type it is acting upon. For this reason, we look at how it behavior with each of the following types: List-like Tables Map-like Tables Set-like Tables Strings
Lua's Logic Operators
Boolean Values In order to provide a baseline for the examples below, let's start with a quick look at the boolean values of true and false : print ( true ) -- true print ( false ) -- false As we discussed earlier , when a non-boolean value is evaluated in a boolean context that value is coerced to its boolean equivalent. It is common to refer to values that are coerced to true as being truthy , while those that are coerced to false are falsy . not The first and most simple Boolean operator is the not operator, which simply inverts the truthiness of the value it operates on and returns a boolean value: print ( not true ) -- false print ( not false ) -- true print ( not nil ) -- true -- careful! print ( not 0 ) -- false print ( not "" ) -- false print ( not {}) -- false We included a few examples of type coercion to show how it works. If you are familiar with boolean coercion in other programming languages, be careful when evaluating 0 , "" , and {} , as they may provide unexpected results. and The next operator is the and operator, which evaluates to truthy when both inputs are truthy , and otherwise evaluates to falsy : print ( true and true ) -- true print ( true and false ) -- false print ( false and true ) -- false print ( false and false ) -- false The previous examples shows that the and operator evaluates boolean values in the expected way. The following examples demonstrate how it evaluates non-boolean values: print ( false and nil ) -- false print ( true and nil ) -- nil print ( true and 0 and nil ) -- nil print ( true and nil and 0 ) -- nil Note that the and operator returns either the first non- truthy value, or the last truthy value if all values are truthy . This behavior allows the and operator to both provide logical operators and provide a simple control structure . or Complementary to the and operator is the or operator, which evaluates to truthy if either of the inputs are truthy , and evaluates to falsy otherwise. print ( true or true ) -- true print ( true or false ) -- true print ( false or true ) -- true print ( false or false ) -- false As with the and operator, the or operator performs logical operations as expected, and also operates on non-boolean values: print ( nil or false ) -- false print ( nil or true ) -- true print ( nil or 0 or true ) -- 0 print ( 0 or nil or true ) -- 0 The or operator returns either the first truthy value it encounters, or the last falsy value if all values are falsy . Like the and operator, this allows the or operator to both provide logical operators and provide a simple control structure that is often very convenient. Compound Boolean operators can be chained together to create "compound" operations: print ( true and not true ) -- false print ( true or not true ) -- true How this works will become clean in the next section, where we discuss precedence .
Operator Precedence in Lua
As we all learned in algebra, it is not only important to understand how operators work, but also understand the order in which operators are applied. The order in which operators are applied is governed by their precedence and their association . Lua operators have the following precedence, ordered from highest to lowest priority, and association: Group Operators Association Exponentiation ^ Right Unary Operators not # - ~ Left Arithmetic * / % Left Arithmetic + - Left Concatenation .. Right Bitwise & Left Bitwise ~ Left Bitwise | Left Relational < > <= >= ~= == Left Logical and Left Logical or Left As with algebra, parentheses can be used to override the order of precedence of an expression.
Lua
Lua is a lightweight, cross-platform, high-level programming language that has become increasingly-popular as an embedded scripting language. Lua is often praised as a clean, simple, easy to learn scripting language that is applicable to a wide range of tasks. Today Lua can be found in a wide range of applications ranging from wezterm to xplr and neovim . Let's get started.
Alternation in Neovim Patterns
If it often helpful for patterns to allow multiple atoms to match in a specific location. In patterns, this concept is often called "alternation", or the ability to have alternate atoms match in a particular location. Alternatives are specified by separating them with "|": Pattern Matches (a|b) a or b (a|b|c) a, b, or c where a, b, and c represent any atoms. Atoms are evaluated from left to right, and first match is returned. Lets demonstrate how to use alternation with the following buffer, which contains a list of English language codes. Initial Conditions e n-au en-ca en-ie en-jm en-nz en-za en-gb en-us COMMAND Top 1:1 /au\|ca As a simple example, lets first demonstrate how to select either of the literal strings "au" or "ca": au\|ca Simple alternate e n- a u en- ca en-ie en-jm en-nz en-za en-gb en-us NORMAL Top 1:4 Next, lets try an example with nested alternation. Suppose we want to select a literal "au" or any other code that ends with "a" or "m". We start by creating the nested alternation: \w\(a\|m\) then create the outer alternation: au\|\w\%(a\|m\) and finally execute the search: Nested alternate en- a u en- c a en-ie en- jm en-nz en- za en-gb en-us NORMAL 22% 2:4
Format Strings
We have already learned that Lua strings are immutable , and that changing a string produces a copy of the string which can make string construction through concatenation inefficient. String buffers can provide a more efficient means of constructing a string from one or more sub-strings in many situations. Lua format strings are another option that can provide a flexible and more efficient alternative. Format strings are strings that contain "placeholders" that identify where values are to be inserted, and a simple "format specifier" that defines how each value should be formatted. These strings are then passed to the string.format library function with the values to be used to render the final string. Let's look at an example: print ( string.format ( "%s %d %f" , "hello" , 123 , math.pi )) -- hello 123 3.141593 This example used a simple template, consisting of placeholders %s , %d , and %f , which were populated by the values "hello" , 123 , and math.pi , respectively. Placeholders are defined by % , followed by the format specifier that has the format: %[flags][width][.precision]type where specifiers in brackets are optional, and behave slightly differently depending on the type specifier. Learning to use Format strings effectively takes some experience, trial, and error, so we will touch on the highlights and provide examples to show some common use-cases. Type Specifier The type specifier indicates how the corresponding value should be formatted. Most of the type options relate to numerical values, and render them in various ways: Type Meaning Example Value Result s String %s abc abc d or i Decimal or integer %d 123 123 f Float %f math.pi 3.141593 e Scientific notation %e math.pi 3.141593e+00 E Scientific notation %E math.pi 3.141593E+00 g Autoformat %g math.pi 3.141593 G Autoformat %G math.pi 3.141593 o Octal %o 123 173 x Hexadecimal %x 123 7b c Character %c 97 a q Lua code %q "abc" "abc" Two Scientific notation options are available, with the difference being whether e or E are used to identify the exponent. There are also two Autoformat options, which evaluate the value and automatically determine whether to format the value as a float or using scientific notation . The two autoformat options differ in how they format the value when scientific notation is used, where g and G correspond to e and E format, respectively. Character formatting converts a character code (typically an ASCII code) into the corresponding character, and behaves like the string.char library function. Finally, the q type specified is a Lua-specific option that renders the value in a format that can be parsed and executed by Lua. Width The width field specifies the minimum number of characters of width the value should occupy. If the value requires fewer than the specified number of characters, then this many characters are occupied. If the value requires more characters, then use the required number of characters. We can see how this behaves by formatting math.pi to a range of widths : print ( string.format ( "%1f" , math.pi )) -- 3.141593 print ( string.format ( "%2f" , math.pi )) -- 3.141593 print ( string.format ( "%3f" , math.pi )) -- 3.141593 print ( string.format ( "%4f" , math.pi )) -- 3.141593 print ( string.format ( "%5f" , math.pi )) -- 3.141593 print ( string.format ( "%6f" , math.pi )) -- 3.141593 print ( string.format ( "%7f" , math.pi )) -- 3.141593 print ( string.format ( "%8f" , math.pi )) -- 3.141593 print ( string.format ( "%9f" , math.pi )) -- 3.141593 print ( string.format ( "%10f" , math.pi )) -- 3.141593 print ( string.format ( "%11f" , math.pi )) -- 3.141593 Not much happens when small width values are specified, then as the width exceeds 8 characters the value becomes "padded" with empty spaces. This is the default behavior, though we can change that with the Flags specifier. Flags As we saw in the previous section, when a value requires fewer characters of width that are specified the value becomes "left-padded" with spaces. Format strings provide a few flags that allow this behavior to be changed: Flag Meaning Example Value Result None Default %4d 1 1 - Left Align %-4d 1 1 + Show both + and - signs %+4d 1 +1 0 When width is present, zero-pad the value. %04d 1 0001 space prepend a space ( " " ) for positive values % 4d 1 1 Precision The precision field usually specifies a maximum limit of the output, depending on the particular formatting type. The precision specifier defines the maximum width of the output, which is accomplished by rounding the value to the right of the decimal point to the specified number of digits: print ( string.format ( "%4.0f" , math.pi )) -- 3 print ( string.format ( "%4.1f" , math.pi )) -- 3.1 print ( string.format ( "%4.2f" , math.pi )) -- 3.14 print ( string.format ( "%4.3f" , math.pi )) -- 3.142 print ( string.format ( "%4.4f" , math.pi )) -- 3.1416 print ( string.format ( "%4.5f" , math.pi )) -- 3.14159 print ( string.format ( "%4.6f" , math.pi )) -- 3.141593 print ( string.format ( "%4.7f" , math.pi )) -- 3.1415927 print ( string.format ( "%4.8f" , math.pi )) -- 3.14159265 print ( string.format ( "%4.9f" , math.pi )) -- 3.141592654 print ( string.format ( "%4.10f" , math.pi )) -- 3.1415926536 print ( string.format ( "%4.11f" , math.pi )) -- 3.14159265359
Repetition in Lua Patterns
The next step to understanding patterns is repetition , which specify not only the class of the character, but how sequences of those characters should be matched. Repetition specifications are indicated by placing one of the following characters immediately after a character class Specifier Description Greedy Default matches any single character in the class * matches a sequence consisting of 0 or more characters in the class Yes - matches a sequence consisting of 0 or more characters in the class No + matches a sequence consisting of 1 or more characters in the class Yes ? matches 0 or 1 character in the class Greedy refers to how variable counts treat a matching sequence of characters. "Greedy" matching indicates that the pattern will always match the longest possible sequence, while "non-greedy" matching indicates that the pattern always match the shortest possible sequence. Let's look at each of these to get a better idea of how this works. First, let's look at the default behavior, when no repetition is specified: local pattern = "%d" print ( string.match ( "abc" , pattern )) -- nil print ( string.match ( "1abc" , pattern )) -- 1 print ( string.match ( "12abc" , pattern )) -- 1 print ( string.match ( "123abc" , pattern )) -- 1 When no repetition specifications are defined, by default a character class matches a single character. In the first example no match was made because there are no digits in the target, and therefore the call to match returned nil , while the pattern was able to match a single character of the other targets. Next, let's look at * which greedily matches 0 or more characters from the character class : local pattern = "%d*" print ( string.match ( "abc" , pattern )) -- print ( string.match ( "1abc" , pattern )) -- 1 print ( string.match ( "12abc" , pattern )) -- 12 print ( string.match ( "123abc" , pattern )) -- 123 Notice that although there are no digits in the first target, the pattern still matched (it did not return nil ). Instead, it matched an empty string. This is due to the repetition specification which allows the pattern to match 0 characters. For each of the other targets, this pattern matched all available digits. Now let's compare that behavior to that of a non-greedy match: local pattern = "%d-" print ( string.match ( "abc" , pattern )) -- print ( string.match ( "1abc" , pattern )) -- print ( string.match ( "12abc" , pattern )) -- print ( string.match ( "123abc" , pattern )) -- What is interesting in the case is that the pattern matched, but returned just an empty string. It is difficult to see this behavior with such a simple pattern, so let's repeat with a slightly more complicated pattern: local pattern = "%d-%a" print ( string.match ( "abc" , pattern )) -- a print ( string.match ( "1abc" , pattern )) -- 1a print ( string.match ( "12abc" , pattern )) -- 12a print ( string.match ( "123abc" , pattern )) -- 123a In this case, the pattern matched the fewest number of digits required to additionally match a single letter. In order to match the letter, the pattern had to match all numbers leading up to it. Another variation on the * specifier is the + specifier, which greedily-matches at least 1 character from the character class : local pattern = "%d+" print ( string.match ( "abc" , pattern )) -- nil print ( string.match ( "1abc" , pattern )) -- 1 print ( string.match ( "12abc" , pattern )) -- 12 print ( string.match ( "123abc" , pattern )) -- 123 The main difference is shown in the top line, where * matches an empty string, while + simply won't match. Finally, the ? specifier matches 0 or 1 repetitions of the character_classes : local pattern = "%d?" print ( string.match ( "abc" , pattern )) -- print ( string.match ( "1abc" , pattern )) -- 1 print ( string.match ( "12abc" , pattern )) -- 1 print ( string.match ( "123abc" , pattern )) -- 1 Now that we have the tools we need to understand and create patterns, let's move on to the next topic, captures .