copas.lua

local sys = require("system")
-- local UI = require("ui")
local copas = require("copas")


-- define the UI library in line here
local UI = {}

function UI.progressBar(current, total)
  local widthOfBar = 50
  local progress = math.floor((current / total) * widthOfBar)
  local remaining = widthOfBar - progress
  local bar = "[" .. string.rep("=", progress) .. string.rep(" ", remaining) .. "]"
  io.write("\r" .. bar .. math.floor((current / total) * 100) .. "%") -- carriage return for progress bar to stay on the same line
  io.flush()
end

function UI.prompt(message)
  print(message .. " (y/n):")
  --local response = io.read() -- io.read is blocking, use readansi instead
  local response = sys.readansi(math.huge, copas.pause)  -- use readansi, and pass a NON-blocking sleep function for use with Copas
  if response == "y" then -- readansi only return 1 character
      return true
  elseif response == "n" then -- check for the other result as well
      return false
  else  -- report an error and retry the prompt
      print("Invalid input")
      return UI.prompt(message)
  end
end


-- end of UI library definition

local function displayMenu()
    print("=============")
    print("1. Check Time")
    print("2. Get Mono Time")
    print("3. Give Feedback")
    print("4. Progress Bar Demo")
    print("6. Exit")
    print("=============")
end

local function getTime()
    local time = math.floor(sys.gettime())  -- wrapped in math.floor to make it an integer
    local date = os.date("Current Time: %Y-%m-%d %H:%M:%S", time)
    print(date)
end


local function monoTime()
    local response = sys.monotime()
    print(response)
end

local function uiPrompt()
    local response = UI.prompt("Do you like lua?")
    if response == true then
        print("Thats great!")
    else
        print("So sad to hear :(")
    end
end


-- instead of just running this loop, wrap it in a Copas task.
-- when calling copas.loop() below, execution will start. Copas will
-- keep running until all tasks have exited.
copas.addthread(function ()  -- added
while true do
    displayMenu()
    io.write("Select an Option: ")
    --local choice = tonumber(io.read())  -- io.read is blocking, nothing will ever run until the user presses enter. so we shouldn't use it.
    local char = sys.readansi(math.huge, copas.pause)  -- use readansi, and pass a NON-blocking sleep function for use with Copas
    -- if no input is available, it will call copas.pause to wait a bit, and then try again, until a key was actually pressed,
    -- or a timeout occurs (but since we pass "math.huge" here, it will wait forever).
    -- copas.pause (when called by readansi) will not just sleep (and block the current thread), but will yield to the Copas scheduler, the scheduler will
    -- then check if there are any other tasks that need to run, and if so, it will run them. Only when the sleep period
    -- has passed, will the current task be resumed by the scheduler. The effects:
    -- 1. from the perspective of the code here, it looks like the code blocks, it will not return until a key is pressed
    -- 2. from the perspective of readansi, it will try in a loop, and sleep (copas pause) short periods in between.
    -- 3. from the perspective of the Copas scheduler, it will not block, it will keep running other tasks, everytime readansi
    --    calls copas.pause, and then resume the readansi task when the sleep period has passed.
    local choice = tonumber(char) -- convert the string to an actual number

    if choice == 1 then
        getTime()
    elseif choice == 2 then
        monoTime()
    elseif choice == 3 then
        uiPrompt()
    elseif choice == 4 then
        copas.addthread(function ()
            local total = 100
            for i=1, total do
                UI.progressBar(i, total)
                copas.pause(0.1)
            end
            print()
        end)
    elseif choice == 6 then
        break
    end
end
end)  -- added: end of copas.addthread


-- before starting the loop, we must configure the terminal

-- setup Windows console to handle ANSI processing
sys.setconsoleflags(io.stdout, sys.getconsoleflags(io.stdout) + sys.COF_VIRTUAL_TERMINAL_PROCESSING)
sys.setconsoleflags(io.stdin, sys.getconsoleflags(io.stdin) + sys.CIF_VIRTUAL_TERMINAL_INPUT)

-- setup Posix to disable canonical mode and echo
local of_attr = sys.tcgetattr(io.stdin)
sys.setnonblock(io.stdin, true)
sys.tcsetattr(io.stdin, sys.TCSANOW, {
  lflag = of_attr.lflag - sys.L_ICANON - sys.L_ECHO, -- disable canonical mode and echo
})

copas.loop() -- this will exit once all tasks defined are finished

-- after exiting restore terminal configuration

-- windows
sys.setconsoleflags(io.stdout, sys.getconsoleflags(io.stdout) - sys.COF_VIRTUAL_TERMINAL_PROCESSING)
sys.setconsoleflags(io.stdin, sys.getconsoleflags(io.stdin) - sys.CIF_VIRTUAL_TERMINAL_INPUT)

-- posix
local of_attr = sys.tcgetattr(io.stdin)
sys.setnonblock(io.stdin, false)
sys.tcsetattr(io.stdin, sys.TCSANOW, {
  lflag = of_attr.lflag + sys.L_ICANON + sys.L_ECHO,
})
generated by LDoc 1.5.0