【问题标题】:how to restart a lua program using the script in the lua script如何使用 lua 脚本中的脚本重新启动 lua 程序
【发布时间】:2021-03-02 23:20:36
【问题描述】:

又是我

我正在尝试用 Lua 制作一个终端程序,因为它是我所知道的最好的语言,我正在用它制作计算器程序,并且我正在尝试制作它,所以如果用户键入“exit”,程序将重启会回到终端,但是不知道怎么通过代码重置程序。如果有人能提供帮助,我们将不胜感激。

这是代码:

io.write("Terminal is starting up --- done!")
io.write("Making sure everything works --- Done!")
cmd = io.read()
io.write(">")

if cmd == "" then 
    io.write(">\n")
end

if cmd == "cal"then
    io.write("Calculator Terminal Program v1.0")
    io.write("what operation?/n")
    op = io.read()
    
    if op == "exit"then
        io.write("Exiting")
    end
end

【问题讨论】:

    标签: lua application-restart


    【解决方案1】:

    你可能想要os.exit(),它会终止整个程序。

    【讨论】:

      【解决方案2】:

      我认为这可以通过创造性地使用 load() 和协程来实现 当总共发生 3 个错误时,这将停止自行重启

      if innerProgram == nil then --innerProgram will set to true when it load itself
        local filename = nil
        local errorLimit = 3 --Change this to any value to enable this code to restart itself when error occur until this amount of time set zero or below to exit instantly when error occur
        local errors = 0
        local filename = function()
          local str = debug.getinfo(2, "S").source:sub(2)
          return str:match("^.*/(.*)") or str
        end
        filename = filename()
        local src_h = io.open(filename, "r") --open in read mode
        local src = src_h:read("*a")
        src_h:close()
        local G = _G
        local quit = false --set true when you want to exit instead restart
        local code = nil
        local request = false
        local restart = false --set true when you want restart
        local program
        local yield = coroutine.yield --Incase when coroutine get removed in your calculator code for no reason
        local running = coroutine.running
        local exit = os.exit
        function G.restart()
          restart = true --Always refer to restart variable above
          request = true
          yield() --Always refer to yield above
        end
        function G.os.exit(exitcode) --Replace os.exit with this
          quit = true --Always refer to quit variable above
          reuqest = true
          code = exitcode or nil
          yield() --Always refer to yield above
        end
        function G.coroutine.yield()
          if running() == program and request == false then --Emulating coroutine.yield when it not run inside coroutine
            error("attempt to yield from outside a coroutine")
          end
        end
        G.innerProgram = true --So the inner program not keep loading itself forever
        function copy(obj, seen)
          if type(obj) ~= 'table' then return obj end --got from https://stackoverflow.com/questions/640642/how-do-you-copy-a-lua-table-by-value for us to clone _G variable without reference to original _G thus we can do total restart without using same _G
          if seen and seen[obj] then return seen[obj] end
          local s = seen or {}
          local res = setmetatable({}, getmetatable(obj))
          s[obj] = res
          for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
          return res
        end
        print("Loading "..filename)
        program = coroutine.create(load(src, filename, "bt", copy(G)))
        while errors < errorLimit do
          restart = false
          local status, err = coroutine.resume(program)
      
          if restart == true then
            print("Restarting...")
            program = coroutine.create(load(src, filename, "bt", copy(G)))
            --Put errors = errors + 1 if you want errors counter to reset every time the program request restart
          end
          
          if status == false and restart ~= true then
            print(filename.." errored with "..err.."\nRestarting...")
            program = coroutine.create(load(src, filename, "bt", copy(G)))
            errors = errors + 1
          elseif restart ~= true then
            print(filename.." done executing.")
            exit()
          end
        end
        return
      else
        innerProgram = nil --Nil-ing the variable
      end
      

      特点

      1. 总共出现 3 个错误时自动退出(配置 errorLimit 变量)
      2. _G 未共享(与程序开头的_G 相同,但未与实际的_G 链接)
      3. 在协程之外模拟让步
      4. 替换了 os.exit 使其屈服,然后自加载器运行 os.exit

      如何使用

      将我上面给出的代码放在代码的第一行

      功能编号 1 和 3 测试

      a 内容出错,每次错误重启时值都会不同

      if a == nil then --Only set a when a equal nil so if _G was shared the error value will be same 
        a = math.random() --Set global a to a random value
      end
      error(a) --Error with number a
      os.exit()
      

      【讨论】:

        【解决方案3】:

        要直接回答您的问题,我不认为可以“重新启动程序”。但是,通过利用loops,您可以获得相同的结果。

        例如,此代码可能会执行您想要的操作:

        print('Terminal is starting up --- done!')
        print('Making sure everything works --- Done!')
        
        repeat
            io.write('>')
            cmd = io.read()
        
            if cmd == 'cal' then
                print('Calculator Terminal Program v1.0')
                repeat
                    io.write('Operation: ')
                    op = io.read()
                until op == 'exit'
                print('Exiting')
            elseif cmd == 'command' then
                --another command
            else
                print('Unknown command.')
            end
        
        until cmd == 'exit'
        

        其他提示:

        • 您应该利用elseif 而不是编写多个单独的if 语句来提高可读性。
        • 如果您在编写一些文本后想要换行以获得更好的终端体验,请考虑使用print 函数。你也可以使用io.write('\n')

        【讨论】:

          猜你喜欢
          • 2021-08-26
          • 2023-01-01
          • 2013-09-28
          • 2019-07-30
          • 2015-07-31
          • 2020-07-02
          • 2018-11-20
          • 2017-01-20
          • 2016-06-03
          相关资源
          最近更新 更多