Lua: getting the latest line in external txt file - lua

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

Related

Lua local require of modules in different files

I learned that require only loads a file once it's loaded (in package.loaded). However I see the following behavior and would like to get some pointers on what is happening.
Say I have a file lib/q.lua:
local q = {}
local function dep()
return 1;
end
q.dep = dep;
return q;
Another file lib/p.lua:
local q = require('./lib/q');
local p = {}
local function result()
return q;
end
p.result = result;
return p;
Another file main.lua:
local p = require('./lib/p');
local q = require('./lib/q');
local assert = require('luassert');
local result = p.result();
print(result);
print(package.loaded['./lib/q']);
print(q);
assert.is_equal(q, result);
The value of package.loaded['./lib/q'] is the same as result. However its value is different from the local q in main.lua. I expected them to be the same. Is there documentation on this or I'm missing something.
New to Lua. Any help is greatly appreciated. Thanks.

Lua Script in suricata to detect the change in file

I am new in lua programming. I was looking for a lua script that can read the file being downloaded through Suricata from the internet and detect if file is changed. Any help would be appreciated. Thanks in advance.
Something like this:
function init(args)
return {http.response_body = tostring(true)}
end
local function read_file(path)
local file = open(path, "rb") -- r read mode and b binary mode
if not file then return nil end
local content = file:read "*a" -- *a or *all reads the whole file
file:close()
return content
end
local fileContent = read_file(path-to-where-previous-file-is-stored);
local fileContent2 = read_file(init());
if fileContent != fileContent2:
print("File changed")
and block if contents are same
drop http any any -> any any (msg:"NVISO PDF file lua"; flow:established,to_client; luajit:pdfcheckname.lua; classtype:policy-violation; sid:1000000; rev:1;)
Unless you have some other open function that is now shown in your snippet local file = open(path, "rb") should be replaced with local file = io.open(path, "rb")
local fileContent2 = read_file(init()); will cause problems as init() will return a table, not a path string. This will cause an error when calling io.open
if fileContent != fileContent2:
print("File changed")
is syntactically incorrect.
Replace it with
if fileContent != fileContent2 then
print("File Changed")
end
Also a name like file2Content would make more sense as it is not the second content of file but the content of file 2. But that's just my personal opinion.

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

lua: how can i get the raw string in __tostring metamethod?

code below:
local t = {}
setmetatable(t, {__tostring = function(self) return 'MyTable is: '..tostring(self) end})
print(t)
running the code will cause error: "C stack overflow". Because in __tostring metamethod, tostring(self) will invoke the __tostring metamethod, that's a dead loop.
Is there a way to get the raw string of the value "t"?
To do what you're trying to do from Lua, you basically have to unset the metatable from the main table, then call tostring on it, then set the metatable back. Like this:
setmetatable(t, {__tostring = function(self)
local temp = getmetatable(self)
setmetatable(self, nil)
local ret = 'MyTable is: ' .. tostring(self)
setmetatable(self, temp)
return ret
end,
})
Also, note that the __tostring metafunction is supposed to return the string, not merely print it.

Error: attempt to index local 'self' (a nil value)

I am following a tutorial on Lua, specifically for making a gamemode in the game Garry's Mod. I've been looking at this for a while and I simply can't find what's wrong.
function ply:databaseFolders()
return "server/example/players/" .. self:ShortSteamID() .. "/" --ref. A
end
function ply:databasePath()
return self:databaseFolders() .. "database.txt" --ERROR line here, goes up
end
function ply:databaseExists()
local f = file.Exists(self.databasePath(), "DATA") --goes up here
return f
end
function ply:databaseCheck()
self.database = {}
local f = self:databaseExists() --goes up here
...
end
function GM:PlayerAuthed(ply, steamID, uniqueID)
ply:databaseCheck() --goes up here
print("Player: " .. ply:Nick() .. " has gotten authed.")
end
Summary of code: I want to create a database.txt file at the directory above.
Edit1: When all players leave the game, ref. A is reached, but no file created in directory.
When you are calling the function databasePath, you are not using the OOP syntax; and therefore self is not implicitly passed to the function. Henceforth, the error. Change the following:
function ply:databaseExists()
local f = file.Exists(self:databasePath(), "DATA")
-- notice the use of ---> : <--- here
return f
end

Resources