print () command and multiple items - lua

Some context, This is some of my first programming in Lua and I am doing it with QSC software.
local a = Controls.Flippy.String
local b = Controls.Flippy.Value
local c = Controls.Flippy.Position
local d = " "
print(a..d..b..d..c)
This worked but is there away I can write strings in line with a variables. Such as:
print("controls "a" "b" "c)

Same way you put the strings together--with .., the concatenation operator.
print("controls "..a.." "..b.." "..c)
It is also possible to use print with multiple arguments, though the spacing is often different (which may or may not be desirable):
print("controls",a,b,c)

You can just write the strings as
print("controls", a, b, c)
You can choose not to put spaces in between if you wish not to.
Hope that helps!

There are several ways to print multiple values in a line.
local name = "Frank"
local age = 15
-- simple, but not applicable for my example due to formatting:
print("My name is", name, "I'm", age, "years old")
-- using the concatenation operator ..
print("My name is " .. name .. ". I'm " .. age .. " years old")
-- using string.format, best for complex expressions, capable of advanced formatting
print(string.format("My name is %s. I'm %d years old.", name, age))

Related

How do I get a list of strings that are between 2 strings in Lua?

I'm trying to write a HTML parser in Lua. A major roadblock I hit almost immediately was I have no idea how to get a list of strings between 2 strings. This is important for parsing HTML, where a tag is defined by being within 2 characters (or strings of length 1), namely '<' and '>'. I am aware of this answer, but it only gets the first occurence, not all instances of a string between the 2 given strings.
What I mean by "list of strings between 2 strings" is something like this:
someFunc("<a b c> <c b a> a </c b a> </a b c>", "<", ">")
Returns:
{"a b c", "c b a", "/c b a", "/a b c"}
This does not have to parse newlines nor text in between tags, as both of those can be handled using extra logic. However, I would prefer it if it did parse newlines, so I can run the code once for the whole string returned by the first GET request.
Note: This is a experiment project to see if this is possible in the very limited Lua environment provided by the CC: Tweaked mod for Minecraft. Documentation here: https://tweaked.cc/
You can do simply:
local list = {}
local html = [[bla]]
for innerTag in html:gmatch("<(.-)>") do
list[#list] = innerTag
end
But be aware that it is weak as doesn't validade wrong things, as someone can put an < or > inside a string etc.

How to have three regexes? Lua

So, I have a project that requires lots of string manipulation. I want to match three strings in a main string by matching all the text inside a square bracket. Except this outputs 'c' as nil? Any help?
a,b,c = x:match("%[(%a+)%],%[(%a+)%]")
print(c)
print(b)
if vars[b] == vars[tc] then
print(vars[b])
end
You forgot one pattern:
x=[[
*DISPLAY[AL][DL], [XX]
]]
a,b,c = x:match("%[(%a+)%]%[(%a+)%], %[(%a+)%]")
print(a,b,c)

Using lpeg to only capture on word boundaries

I've been working on a text editor that uses LPEG to implement syntax highlighting support. Getting things up and running was pretty simple, but I've only done the minimum required.
I've defined a bunch of patterns like this:
-- Keywords
local keyword = C(
P"auto" +
P"break" +
P"case" +
P"char" +
P"int"
-- more ..
) / function() add_syntax( RED, ... )
This correctly handles input, but unfortunately matches too much. For example int matches in the middle of printf, which is expected because I'm using "P" for a literal match.
Obviously to perform "proper" highlighting I need to match on word-boundaries, such that "int" matches "int", but not "printf", "vsprintf", etc.
I tried to use this to limit the match to only occurring after "<[{ \n", but this didn't do what I want:
-- space, newline, comma, brackets followed by the keyword
S(" \n(<{,")^1 * P"auto" +
Is there a simple, obvious, solution I'm missing here to match only keywords/tokens that are surrounded by whitespace or other characters that you'd expect in C-code? I do need the captured token so I can highlight it, but otherwise I'm not married to any particular approach.
e.g. These should match:
int foo;
void(int argc,std::list<int,int> ) { .. };
But this should not:
fprintf(stderr, "blah. patterns are hard\n");
The LPeg construction -pattern (or more specifically -idchar in the following example) does a good job of making sure that the current match is not followed by pattern (i.e. idchar). Luckily this also works for empty strings at the end of the input, so we don't need special handling for that. For making sure that a match is not preceded by a pattern, LPeg provides lpeg.B(pattern). Unfortunately, this requires a pattern that matches a fixed length string, and so won't work at the beginning of the input. To fix that the following code separately tries to match without lpeg.B() at the beginning of the input before falling back to a pattern that checks suffixes and prefixes for the rest of the string:
local L = require( "lpeg" )
local function decorate( word )
-- highlighting in UNIX terminals
return "\27[32;1m"..word.."\27[0m"
end
-- matches characters that may be part of an identifier
local idchar = L.R( "az", "AZ", "09" ) + L.P"_"
-- list of keywords to be highlighted
local keywords = L.C( L.P"in" +
L.P"for" )
local function highlight( s )
local p = L.P{
(L.V"nosuffix" + "") * (L.V"exactmatch" + 1)^0,
nosuffix = (keywords / decorate) * -idchar,
exactmatch = L.B( 1 - idchar ) * L.V"nosuffix",
}
return L.match( L.Cs( p ), s )
end
-- tests:
print( highlight"" )
print( highlight"hello world" )
print( highlight"in 0in int for xfor for_ |for| in" )
I think you should negate the matching pattern similar to how it's done in the example from the documentation:
If we want to look for a pattern only at word boundaries, we can use the following transformer:
local t = lpeg.locale()
function atwordboundary (p)
return lpeg.P{
[1] = p + t.alpha^0 * (1 - t.alpha)^1 * lpeg.V(1)
}
end
This SO answer also discussed somewhat similar solution, so may be of interest.
There is also another editor component that uses LPeg for parsing with the purpose of syntax highlighting, so you may want to look at how they handle this (or use their lexers if it works for your design).

Check if variable matches pattern, LUA

So if I have the variable name. How can I check if it matches a pattern?
For instance, I would like to check if the variable name equals a pattern like text_text. So words at the beginning then underscore then words. With no numbers.
I really have no idea where to even start with this.
local pattern = something
if name == pattern then
UPDATE** I have tried the following, still nothing is working.
local pattern = "a%%sa%"
if string.match (name, pattern) then
return 1
else
return 0
end
Also tried this way
local pattern = "a%_a%"
if string.match (name, pattern) then
return 1
else
return 0
end
Can I please get some help
A pattern that matches any combination of small letters linked with an underscore would be:
"%l+_%l+"
%l specifies any lower case letter,
followed by a + which specifies the number of the symbol it follows.
So %l+ means "at least one lower case letter"
_ is simply an underscore.
So the pattern "%l+_%l+" means "at least one lower case letter followed by one underscore followed by at least one lower case letter
Please refer to https://www.lua.org/pil/20.2.html and/or https://www.lua.org/manual/5.3/manual.html#6.4.1 for all the possible bricks you can construct patterns of.
You can use those patterns in the functions provided by the string standard library. string.find, string.gsub and so on.
If you want to use that stuff more excessively checkout LPeg for example.
Try this:
function match(string)
local string = string:match('^(%a+_%a+)$')
if string then
return true
else
return false
end
end
local string = match('hi I'm webrom')
print(string)
output = false
local string = match('14545_15456')
print(string)
output = false
local string = match('hello_world')
print(string)
output = true
local string = match('HELLO_WORLD')
print(string)
output = true
The pattern %a match any letter.
in string patterns in lua,
anything between parantheses will be returned
also you do % with a special caracter afterwards like a for letters, to match ONE letter
adding + after %a would make you detect THE MOST possible letters , in the pattern before you get to the next character / set of characters
for example :
s = "Hello Julia my love ! Here's a hug!"
lovername,gift = string.match(s,"(%a+) my love ! Here's a (%a+)")
print(lovername.." was given a "..gift)
In your example, you can do this :
var = "hello_world"
if (string.match(var, "%a+_%a+")) then -- In this example, _ will be normal
print("Valid variable name !")
else
print("Invalid variable name")
end

Split lua string into characters

I only found this related to what I am looking for: Split string by count of characters but it is not useful for what I mean.
I have a string variable, which is an ammount of 3 numbers (can be from 000 to 999). I need to separate each of the numbers (characters) and get them into a table.
I am programming for a game mod which uses lua, and it has some extra functions. If you could help me to make it using: http://wiki.multitheftauto.com/wiki/Split would be amazing, but any other way is ok too.
Thanks in advance
Corrected to what the OP wanted to ask:
To just split a 3-digit number in 3 numbers, that's even easier:
s='429'
c1,c2,c3=s:match('(%d)(%d)(%d)')
t={tonumber(c1),tonumber(c2),tonumber(c3)}
The answer to "How do I split a long string composed of 3 digit numbers":
This is trivial. You might take a look at the gmatch function in the reference manual:
s="123456789"
res={}
for num in s:gmatch('%d%d%d') do
res[#res+1]=tonumber(num)
end
or if you don't like looping:
res={}
s:gsub('%d%d%d',function(n)res[#res+1]=tonumber(n)end)
I was looking for something like this, but avoiding looping - and hopefully having it as one-liner. Eventually, I found this example from lua-users wiki: Split Join:
fields = {str:match((str:gsub("[^"..sep.."]*"..sep, "([^"..sep.."]*)"..sep)))}
... which is exactly the kind of syntax I'd like - one liner, returns a table - except, I don't really understand what is going on :/ Still, after some poking about, I managed to find the right syntax to split into characters with this idiom, which apparently is:
fields = { str:match( (str:gsub(".", "(.)")) ) }
I guess, what happens is that gsub basically puts parenthesis '(.)' around each character '.' - so that match would consider those as a separate match unit, and "extract" them as separate units as well... But I still don't get why is there extra pair of parenthesis around the str:gsub(".", "(.)") piece.
I tested this with Lua5.1:
str = "a - b - c"
fields = { str:match( (str:gsub(".", "(.)")) ) }
print(table_print(fields))
... where table_print is from lua-users wiki: Table Serialization; and this code prints:
"a"
" "
"-"
" "
"b"
" "
"-"
" "
"c"

Resources