Hey everybody!

Created this a while ago and really liked using it in several programs. So I thought I would share this API with you guys.

Almost every program is using events (if only a timer-event as updater) and whenever an event occurs it should do something specific.
That is exactly what this API is made for. Have a snippet of example code, and I will explain how you (should) use it.

Note: Of course you have to load the API with os.loadAPI("application"), which I didn't include in the examples below!

A program, that, whenever the mouse is pressed, prints the ID of the mousebutton (1 = L, 2 = R, 3 = M) at the position of the cursor:
Spoiler

-- I am predefining the functions I give as parameters later here:
local function mouseEvent(button, x, y)
  term.setCursorPos(x, y)
  term.write(button)
end

-- Here I get an application object, that I first give all the data and then simply start it
app = application.create()

-- Whenever the application gets a "mouse_click" it should run the function with the parameters of the event
app:setEventFunc("mouse_click", mouseEvent)
-- I can easily give the same function to "mouse_drag" as well
app:setEventFunc("mouse_drag", mouseEvent)

-- Now simply start it and it will do what it got told to: wait for events and when mouse_click/drag occurs it should run the function
app:start()
And that would already be a finished program! And yes, you can only stop this program by terminating (CTRL-T)

That just, was the basics, but it can do more:
We want a program, where we can input a text using "char" events and at the same time every 0.5 seconds print a "*" random on the screen
When the screen is full, the program should stop and terminating using CTRL-T should NOT work.
Spoiler

-- We have to save the cursor position of the cursor in this
local charX = 1
term.setCursorPos(charX, 1)
local w, h = term.getSize()
-- blinking cursor looks awesome for entering text ;D
term.setCursorBlink(true)

-- Again predefine a function for input and for the timer event
local function charEntered(char)
  -- cursor already on the right position from either end of this function or end of "addStar()"
  term.write(char)
  -- move the cursor one to the left after every charPress
  charX = charX + 1
  if charX == w then
	-- whenever first line is full, program should get stopped
	app:stop()
  end
  term.setCursorPos(charX, 1)
end

-- You don't have to restart a timer in your timer function. That is done by the application API
local function addStar()
  -- print the star random on the screen, just not in the first line where you enter text
  term.setCursorPos(math.random(1, w), math.random(2, h))
  term.write("*")
  -- this is here, because of the visible blinking cursor
  term.setCursorPos(charX, 1)
end

-- create an object
app = application.create()

-- give it the charEvent function
app:addEventFunc("char", charEvent)
-- With this you can set the auto-update-interval in seconds (giving it "nil" would disable it)
app:setUpdateTimer(0.5)
-- Here I give it the function, that should get run after that interval.
app:setUpdateFunc(addStart)

-- Terminate should not automatically stop with an "app:stop()". You could still handle it with app:addEventFunc("terminate", <function>)
app:setTerminateable(false)

-- And finally start it
app:start()
-- After application gets stopped with "app:stop()" it will continue under corresponding app:start() where we could for example clear the screen and reset the cursor
As you can see, if you know the names of the functions, it is extremly easy to write event-based programs even with timer events. But it still gets better

Lastly, I even have something for you, if you have a display that you have to render.
There is a very easy way to add such a render function that will NOT just get triggered after every event with the application API
And since I am lazy (all programmers (and mathematicians) are lazy!) and you should have got the basic idea by now, I will only explain, how it works:
SpoilerSo, we get 2 more functions to create our render event.
The first one is called
app:setRenderFunc(<function>)
and you can simply give it any function you want

The second function is called
app:renderNext(...)
which you can call wherever in your program you want with any parameters you want. Those parameters get sent to the render function automatically.
The function DOESN'T just call the function immediately. It will run it, after the current event is finished.

To finish it of, have a list of all functions with a little description:
Spoiler

-- note: you can give nil as function to reset it
setEventFunc(<eventName:string>, [eventFunction:function])
setUpdateFunc([updateFunction:function])
setRenderFunc([renderFunction:function])

-- note here you can give nil as well, to disable the timer
setUpdateTimer([interval:number])

-- give this any data, and it will get send over to the render function
renderNext(...)

-- disables terminating using CTRL-T, stopping the application. You can handle it on your own with setEventFunc("terminate", <function>) now.
setTerminateable(<terminateable:boolean>)

-- note: once the application is done because of "stop()" or a terminate event with enabled terminate (which runs stop() xD) it continues after this
start()
-- stop can get run everywhere and will stop the application, once the last event is done
stop()

One last note is, that you can still change everything, that I only changed before starting the application, while the application is running!

Here the pastebin link:
pastebin get g1RALA3Q application

Wish you lots of fun with this easy way of programming using events :D/>