Basic Info
#Anatomy of a Script

Each script in MicroMacro 2 has three functions to control the flow of execution:


This is the function called at the start of the script. It accepts any command-line arguments passed to it and should not return any results. This is where you want to do your setup.


This is your main loop. This will be called ~1,000 times per second. It accepts one parameter (delta time) and should return true as long as you want to continue execution. If you return false, execution ends. Unlike older versions of MicroMacro, you do not want to put a while-loop here and do not need to put a system rest command to reduce CPU usage.


All events will be passed off to this function. The first parameter is the event type as a string. The number of additional arguments passed in depend on the event type.

local running; local totalRunTime; function macro.init(script, ...) -- Print the script we are running and any arguments passed to it for debug purposes print("Running:", script, ...); running = true; -- Keep script running as long as this is true totalRunTime = 0.0; print("Hello world!"); print("Press SPACE BAR to quit"); end function macro.main(dt) -- Keep track of how long the script has been running totalRunTime = totalRunTime + dt; -- Do nothing except continue until not running anymore return running; end function macro.event(eventType, data1, data2, data3, data4) -- Handle any inputs we've received if( eventType == "keypressed" ) then if( data1 == key.VK_SPACE ) then printf("Space bar was pressed. Quitting. Script ran for %0.1f seconds.\n", totalRunTime); running = false; end end end
#Organizing Your Project

Splitting your project into multiple files

If you were to put everything into one file, you would quickly run into a gigantic mess of unreadable code that is hard to work with. For this reason, programmers have split up their work into many smaller and more concise files that work together. Lua can already allow you to do this via the dofile() or require() functions, but MicroMacro improves upon this with include().

include() differs from dofile() in two ways. First, it will attempt to pull in the script relative to the script calling include() (while dofile() is relative to the CWD that you originally started the script from, and require() searched package directories). This makes things a bit easier to work with and more portable; a small quality of life improvement. Secondly, it (by default) it prevents re-loading a script multiple time (like require()) unless you request it to re-run the script.

It is suggested that you start your project with a new folder in MicroMacro's script directory (micromacro/scripts/ by default), then placing a new file named main.lua here. In this file you should place your macro.init(), macro.main(), and macro.event() functions, but try to keep them clean and compact. Place any classes, functions, or other code into files/folders relative to your project directory, then include() them at the top of your main.lua file.

For example, your project might need to handle many different events. Instead of a nasty mess of if/else statements clogging up your macro.event() function, we can clean up the code by creating an event handler class that then delegates different event types into functions.

include("classes/eventhandler.lua"); local running; local eventHandler; function macro.init() running = true; eventHandler = EventHandler(); end function macro.main() return running; end function macro.event(e, ...) eventHandler:handle(e, ...); end
EventHandler =; function EventHandler:handle(e, ...) if( type(self[e]) == "function" ) then return self[e](self, ...); end end function EventHandler:keypressed(vk, toggleState) if( vk == key.VK_SPACE ) then print("Space bar was pressed."); end end -- We could handle any additional events here too...
#Using Libraries Libraries are essentially the same as Lua modules. In fact, everything said here libraries can almost certainly apply to Lua modules.

MicroMacro comes with several libraries to serve common use cases. These libraries are available for you to use in any of your project much like the standard MicroMacro modules, however they are entirely optional and will not be pulled-in to your project unless you specifically ask for it. You may also write your own libraries to share common code across multiple projects, or to share with others to use.

Whether you use the included MicroMacro libraries, use your own, or want to use a Lua modules, the process is the same. While it is recommended that you pull in libraries from your main.lua file, you may do so in any file in your project so long as it is called before any code that relies on the library. Use require to pull in a library/module.

-- Sets a value, 'someNumber', to cache for 5 minutes. -- The value persists even if we restart MicroMacro, as long as -- it is within the 5 minute window we have set. require "cache/cache"; local cache; function macro.init() cache = Cache(); local someNumber = cache:remember('someNumber', 5, function () return math.random(1,100); end); print(someNumber); end function macro.main() return false; end

Some libraries/modules may not be written purely in Lua and may have dependencies (such as multiple .dll files). In this case, the main file (the file you will require) should be placed into the micromacro/lib directory, and any dependencies should be placed into the root MicroMacro directory (micromacro/). If you get an error about a missing file/dll when attempting to load a library, you've probably got your files placed in the wrong directory.

Page last updated at 2018-09-25 20:47:10

Copyright 2023