loading all lua files in a directory - lua

I am trying to "import" every file in the specified directory to a table but when i look at the output it only shows one imported file.
with "import" I mean require(dir.."/"..name) this will return a value witch will be put in the $table at position "name" so this looks like $table[name]
I have made the following code but it does not work for me.. I hope someone can tell me what I am doing wrong..
(the code below is simplified but does include all the files, structures and code associated with this function, also i have inserted print() and printTable() for debugging purposes)
I work on a Debian Jessie machine
file structure
~/x/main.lua
~/x/folder/file1.lua
~/x/folder/file2.lua
~/x/folder/file3.lua
~/x/folder/file4.lua
~/x/folder/file5.lua
./main.lua (printTable script)
local printTable = require "printTable"
-- scan dir and add the file contents (name ,function(if .lua), filepath from script) to a table
function appendDir(functiontable,dir)
for filename in io.popen('dir "'..dir..'" -1'):lines() do
print(filename)
local path = dir.."/"..filename
local name = filename:sub(1,filename:len()-4)
print(name)
local tempValue = false
if filename:sub(filename:len()-3,filename:len()) == ".lua" then tempValue = require(dir.."/"..name) end
functiontable[name]={["value"]=tempValue,["path"]=path}
printTable(functiontable)
end
print("---")
printTable(functiontable)
end
local table1 = {}
appendDir(table1,"./folder")
print("")
print("table1:")
printTable(table1)
for key,value in pairs(table1) do
value.value()
end
./folder/file*.lua all the files are build in the same way only the function returns a different string.
function func()
return "$string"
end
return func
the following strings are for the different files and are inserted in the $string position
~/x/folder/file1.lua $string=string of file 1
~/x/folder/file2.lua $string=string of file 2
~/x/folder/file3.lua $string=string of file 3
~/x/folder/file4.lua $string=string of file 4
~/x/folder/file5.lua $string=string of file 5
now when i execute the main.lua script i get:
~/x $ lua -v
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
~/x $dir folder -1
file1.lua
file2.lua
file3.lua
file4.lua
file5.lua
~/x $ lua main.lua
file1.lua
file1
[file1][value] -> TYPE == function
[file1][path] -> VALUE == ./folder/file1.lua
file2.lua
file2
[file1][value] -> TYPE == function
[file1][path] -> VALUE == ./folder/file1.lua
file3.lua
file3
[file3][value] -> TYPE == function
[file3][path] -> VALUE == ./folder/file3.lua
file4.lua
file4
[file3][value] -> TYPE == function
[file3][path] -> VALUE == ./folder/file3.lua
file5.lua
file5
[file4][value] -> TYPE == function
[file4][path] -> VALUE == ./folder/file4.lua
---
[file4][value] -> TYPE == function
[file4][path] -> VALUE == ./folder/file4.lua
table1:
[file4][value] -> TYPE == function
[file4][path] -> VALUE == ./folder/file4.lua

as #EgorSkriptunoff pointed out in the comment section of the original post it was a bug in the printTable function where the function returned to the for loop instead of the internal function. this has been resolved and committed to github!
Thank you for your help!

Related

I made a (very simple) programming language in Lua, but I can only execute one command

Hello people of stackoverflow, I've made a (very) simple programming language, it kind of looks like minecraft commands. Here is the code
function wait(cmdSleepGetNum)-- you can name this function
--what ever you want, it doesnt matter
local start = os.time()
repeat until os.time() > start + cmdSleepGetNum
end
local input = io.read()
if input == "/help" then
print"you'll find it out"
else if input == "/say" then
print"what do you want to say?"
local cmdSay = io.read()
print(cmdSay)
else if input == "/stop" then
os.exit()
else if input == "/sleep" then
print"how long?"
local cmdSleepGetNum = io.read()
wait(cmdSleepGetNum)
else if input == "/rand" then
local randNum = math.random()
print(randNum)
end
end
end
end
end
Now I know what you are thinking "what is the problem here?" the problem is that I can only execute one command and after that command is finished by the Lua interpreter, I cannot execute any other commands.
for example:
/rand
0.84018771715471 (the /rand command is executed and prints out a random number)
/rand
stdin:1: unexpected symbol near '/' (this happens when i try to execute another command)
If you replace else if with elseif, you won't need so many end's,
You can get rid of if's altogether, is you use a table,
As #Egor Skriptunoff said, you need to create a main loop to run many commands,
I suggest that you add an optional argument to /sleep and /say.
local function wait (cmdSleepGetNum) -- you can name this function
-- whatever you want, it doesn't matter.
local start = os.time ()
repeat until os.time () > start + cmdSleepGetNum
end
local commands = {
help = function ()
print "you'll find it out"
end,
say = function (arg)
if arg == '' then
print 'what do you want to say?'
arg = io.read ()
end
print (arg)
end,
stop = function ()
os.exit ()
end,
sleep = function (arg)
if arg == '' then
print 'how long?'
arg = tonumber (io.read ())
end
wait (tonumber (arg))
end,
rand = function ()
local randNum = math.random ()
print (randNum)
end,
[false] = function () -- fallback.
print 'Unknown command'
end
}
-- Main loop:
while true do
io.write '> '
local key, _, arg = io.read ():match '^%s*/(%S+)(%s*(.*))$' -- you can type /sleep 1, etc. in one line.
local command = key and key ~= '' and commands [key] or commands [false]
command (arg)
end

Use variables inside a string in lua

In javascript we can do the following:
var someString = `some ${myVar} string`
I have the following lua code, myVar is a number that needs to be in the square brackets:
splash:evaljs('document.querySelectorAll("a[title*=further]")[myVar]')
Function that fits you description is string.format:
splash:evaljs(string.format('document.querySelectorAll("a[title*=further]")[%s]', myVar))
It is not as verbose as ${}. It is more of a good old (and hated) sprintf.
I have written an emulation of Python's f'' strings, which is a set of functions you can hide inside a require file. So, if you like Python's f'' strings, this may be what you're looking for.
(If anyone finds errors, please notify.)
It's quite big compared to the other solution, but if you hide the bulk in a library, then its use is more compact and readable, IMO.
With this library you can do the following, for example:
require 'f_strings'
a = 12345
print(f'Number: {a}, formatted with two decimals: {a::%.2f}')
-- Number: 12345, formatted with two decimals: 12345.00
Note the use of Lua string.format formatting codes, and the use of double colon (instead of Python's single colon) for format specifiers because of Lua's use of colon for methods.
I have extracted only the relevant functions from a larger library. Although some optimizations may be possible for this specific use case, I leave them unchanged as they are general purpose and may also be useful for other purposes.
And here's the required library (placed somewhere in your Lua libraries folder):
-- f_strings.lua ---
unpack = table.unpack or unpack
--------------------------------------------------------------------------------
-- Escape special pattern characters in string to be treated as simple characters
--------------------------------------------------------------------------------
local
function escape_magic(s)
local MAGIC_CHARS_SET = '[()%%.[^$%]*+%-?]'
if s == nil then return end
return (s:gsub(MAGIC_CHARS_SET,'%%%1'))
end
--------------------------------------------------------------------------------
-- Returns iterator to split string on given delimiter (multi-space by default)
--------------------------------------------------------------------------------
function string:gsplit(delimiter)
if delimiter == nil then return self:gmatch '%S+' end --default delimiter is any number of spaces
if delimiter == '' then return self:gmatch '.' end
if type(delimiter) == 'number' then --break string in equal-size chunks
local index = 1
local ans
return function()
ans = self:sub(index,index+delimiter-1)
if ans ~= '' then
index = index + delimiter
return ans
end
end
end
if self:sub(-#delimiter) ~= delimiter then self = self .. delimiter end
return self:gmatch('(.-)'..escape_magic(delimiter))
end
--------------------------------------------------------------------------------
-- Split a string on the given delimiter (comma by default)
--------------------------------------------------------------------------------
function string:split(delimiter,tabled)
tabled = tabled or false --default is unpacked
local ans = {}
for item in self:gsplit(delimiter) do
ans[#ans+1] = item
end
if tabled then return ans end
return unpack(ans)
end
--------------------------------------------------------------------------------
function copy(t) --returns a simple (shallow) copy of the table
if type(t) == 'table' then
local ans = {}
for k,v in next,t do ans[ k ] = v end
return ans
end
return t
end
--------------------------------------------------------------------------------
function eval(expr,vars)
--evaluate a string expression with optional variables
if expr == nil then return end
vars = vars or {}
assert(type(expr) == 'string','String expected as 1st arg')
assert(type(vars) == 'table','Variable table expected as 2nd arg')
local env = {abs=math.abs,acos=math.acos,asin=math.asin,atan=math.atan,
atan2=math.atan2,ceil=math.ceil,cos=math.cos,cosh=math.cosh,
deg=math.deg,exp=math.exp,floor=math.floor,fmod=math.fmod,
frexp=math.frexp,huge=math.huge,ldexp=math.ldexp,log=math.log,
max=math.max,min=math.min,modf=math.modf,pi=math.pi,pow=math.pow,
rad=math.rad,random=math.random,randomseed=math.randomseed,
sin=math.sin,sinh=math.sinh,sqrt=math.sqrt,tan=math.tan,
tanh=math.tanh}
for name,value in pairs(vars) do env[name] = value end
local a,b = pcall(load('return '..expr,nil,'t',env))
if a == false then return nil,b else return b end
end
--------------------------------------------------------------------------------
-- f'' formatted strings like those introduced in Python v3.6
-- However, you must use Lua style format modifiers as with string.format()
--------------------------------------------------------------------------------
function f(s)
local env = copy(_ENV) --start with all globals
local i,k,v,fmt = 0
repeat
i = i + 1
k,v = debug.getlocal(2,i) --two levels up (1 level is this repeat block)
if k ~= nil then env[k] = v end
until k == nil
local
function go(s)
local fmt
s,fmt = s:sub(2,-2):split('::')
if s:match '%b{}' then s = (s:gsub('%b{}',go)) end
s = eval(s,env)
if fmt ~= nil then
if fmt:match '%b{}' then fmt = eval(fmt:sub(2,-2),env) end
s = fmt:format(s)
end
return s
end
return (s:gsub('%b{}',go))
end

lua table global/local var getting confused

I have a lua table which I used to share values between files. But I am getting confused in the following case
utility.lua file
M = {}
M.host_url = '192.168.0.1'
function M.myFunc()
print(M.host_url )
end
return M
in my main.lua
utility = require('utility')
utility.myFunc() -- this gives me 'a nil value' error
I get an error (nil value) for the host_url?
In M.myFunc doing only print action that function nothing will be return.in your utility file returning whole array see he below code that will clear your doudt.
In main.lua
utility = require('util')
value = utility.host_url
print(value)

Lua: getting the latest line in external txt file

I am having a lua function to reading and writing a txt file, I need every time lua write in at a new line instead of replacing the previous write in. How do I do that? Do I need to read in and get the lines 1st every time before I write in?
Here is my code:
local function FileOutput(name)
local f = io.open(name, "w+")
local meta = {
__call = function(t, str) f:write(str .. '\n') end,
__gc = function() f:close() end
}
return setmetatable({}, meta)
end
function writeRec()
LOG("writing")
local testfile = FileOutput(getScriptDirectory()..'/textOutput.txt')
testfile('oh yes!')
testfile = nil
end
Have you tried a+ instead of w+?
http://www.lua.org/manual/5.1/manual.html#pdf-io.open

Hide password with asterisk in lua

I there a way to ask password in lua but hide with asterisks?
I'm asking about a console application
For Unix: use os.execute("stty -echo raw") to turn off echoing and enter raw mode (character-by-character input) and os.execute("stty echo cooked") to turn it on and exit raw mode when you are done. In raw mode, you can get each character of the input using io.stdin:read(1) and echo your asterisk as you go (use io.flush to ensure the character appears straight away). You will need to handle deletes and the end of line yourself.
For Windows, the situation is a bit trickier. Look at What would be the Windows batch equivalent for HTML's input type=“password”? for some approaches, the best of which seems to be a VB script.
Postscript
Thanks for lhf for pointing out that you need raw mode besides -echo on input and flush after each output asterisk to get the desired result: unless you have both, the asteriskes will not be echoed until the line is ended.
This code uses platform-specific features and works both on Linux and 32-bit Windows.
Compatible with Lua 5.1 and Lua 5.2
local console
local function enter_password(prompt_message, asterisk_char, max_length)
-- returns password string
-- "Enter" key finishes the password
-- "Backspace" key undoes last entered character
if not console then
if (os.getenv'os' or ''):lower():find'windows' then
------------------ Windows ------------------
local shift = 10
-- Create executable file which returns (getch()+shift) as exit code
local getch_filespec = 'getch.com'
-- mov AH,8
-- int 21h
-- add AL,shift
-- mov AH,4Ch
-- int 21h
local file = assert(io.open(getch_filespec, 'wb'))
file:write(string.char(0xB4,8,0xCD,0x21,4,shift,0xB4,0x4C,0xCD,0x21))
file:close()
console = {
wait_key = function()
local code_Lua51, _, code_Lua52 = os.execute(getch_filespec)
local code = (code_Lua52 or code_Lua51) - shift
assert(code >= 0, getch_filespec..' execution failed')
return string.char(code)
end,
on_start = function() end,
on_finish = function() end,
backspace_key = '\b'
}
-------------------------------------------
else
------------------ Linux ------------------
console = {
wait_key = function()
return io.read(1)
end,
on_start = function()
os.execute'stty -echo raw'
end,
on_finish = function()
os.execute'stty sane'
end,
backspace_key = '\127'
}
-------------------------------------------
end
end
io.write(prompt_message or '')
io.flush()
local pwd = ''
console.on_start()
repeat
local c = console.wait_key()
if c == console.backspace_key then
if #pwd > 0 then
io.write'\b \b'
pwd = pwd:sub(1, -2)
end
elseif c ~= '\r' and #pwd < (max_length or 32) then
io.write(asterisk_char or '*')
pwd = pwd..c
end
io.flush()
until c == '\r'
console.on_finish()
io.write'\n'
io.flush()
return pwd
end
-- Usage example
local pwd = enter_password'Enter password: '
print('You entered: '..pwd:gsub('%c','?'))
print(pwd:byte(1,-1))
Bug in code, for at least linux implementation. Need to add 'and c ~= nil`:
elseif c ~= '\r' and #pwd < (max_length or 32) and c ~= nil then

Resources