Leap
(Lua extension accessibility pre-processor) is a fast pre-processor of a "modernized" and extended version of lua that pre-processes in pure executable lua.
Think of it as an effective "modernity" leap into the future to make lua a feature-rich language.
Leap is inspired by the functionality and syntax found in JS and is primarily intended for FiveM, this however does not deny the possibility of extension to wider horizons.
Leap uses a shadow writing system (we called it that) that works in the following way: After preprocessing the files, FiveM will read the files, cache them and start the resource with those cached files as soon as we start the resource, we instantly rewrite the old files so that it looks like nothing happened. This will be done in very few ms (5/10), so from VSC or any other IDE that has the auto refresh feature when updating a file it will look like it was never overwritten
leap restart <resource>
restarts the resource by preprocessing it before restarting it using shadow writing, this command is quite useful when creating a resource, since you don't have to rebuild it every time and restart the resource but it's like everything in one command.
TIP: these commands can also be used in the cfg after the leap startup.
leap build <resource>
pre-processes the resource by creating a subfolder named build
that contains the pre-processed version of the resource
resource structure tree after build:
│ fxmanifest.lua
│
├───build
│ └───server
│ main.lua
│
└───server
main.lua
Warning Command designed only for development
leap rebuild
rebuild with esbuild directly from fxserver instead of having to open a separate process (simply run npm run build
)
An arrow function expression is a compact alternative to a traditional function expression. Is simply an alternative to writing anonymous functions
Syntaxes:
(param1, paramN) => {
-- code
}
param => {
-- code
}
Example:
Citizen.CreateThread(() => {
print("test")
})
AddEventHandler("eventName", (text) => {
print(('I just received %s'):format(text))
})
Classes are a model for creating objects (a particular data structure), providing initial values for state (member variables or attributes), and implementing behavior (member functions or methods).
It is possible as well to extend already existing classes, each method of the class that extends the other class will have as a base a variable named super
which is an instantiated object of the original class, calling this variable as a function will call the constructor of the original class, otherwise the data of the original class can be accessed.
Constructor parameters are those passed when a new object is instantiated.
Syntax:
Note Methods automatically hold the
self
variable referring to the instantiated object
class className {
var1 = 1,
constructor = function()
print(self.var1)
end
}
Example:
class BaseClass {
someVariable = 100,
constructor = function()
print("instantiated base class")
end
}
class AdvancedClass extends BaseClass {
constructor = function()
print("instantiated advanced class")
self.super()
-- right now they should printout the same value, since they have not been touched
print(self.super.someVariable)
print(self.someVariable)
end
}
AdvancedClass()
-- output:
--[[
instantiated advanced class
instantiated base class
100
100
]]
By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it. Its like wrappers You can also pass parameters to the decorators.
Syntax:
function decoratorName(func, a, b)
return function(c, d)
func(c,d)
end
end
@decoratorName(a, b)
function fnName(c, d)
-- code
end
Example:
function stopwatch(func)
return function(...)
local time = GetGameTimer()
local data = func(...)
print(func.name.." taken "..(GetGameTimer() - time).."ms to execute")
return data
end
end
@stopwatch
function someMathIntensiveFunction(a, b, pow)
for i=1, 500000 do
math.pow(a*b, pow)
end
return math.pow(a*b, pow)
end
someMathIntensiveFunction(10, 50, 100)
-- output:
--[[
someMathIntensiveFunction taken 2ms to execute
]]
Default function parameters allow named parameters to be initialized with default values if no value or nil is passed.
Syntax:
function fnName(param1 = defaultValue1, ..., paramN = defaultValueN) {
-- code
}
Example:
function multiply(a, b = 1)
return a * b
end
print(multiply(5, 2))
-- Expected output: 10
print(multiply(5))
-- Expected output: 5
The new operator lets create an instance of an object. Is actually converted during the preprocessing process with an empty string, so it is simply eliminated. Its use is simply to make it clear in the code when you are instantiating an object or calling a function
Syntax:
new Class()
Example:
class BaseClass {
someVariable = 100,
constructor = function()
print("instantiated base class")
end
}
local base = new BaseClass()
Another method of writing the not equal operator (~=)
Syntax:
if true != false then
-- code
end
Example:
local a = 10
local b = 20
if a != b then
print("not equal")
end
Warning for now this operator only works with variables, so writing
...{100, 200, 300}
will not work
This operator allows you to unpack arrays (not hashmaps) into multiple variables.
The preprocessor converts this operator into the table.unpack
function.
Syntax:
a,b,c = ...array
Example:
local numbers = {100, 200, 300}
local number1, number2, number3 = ...numbers
console.log(number1, number2, number3)
-- output
--[[
100 200 300
]]
as first thing, thank you for coming down this far and thus wanting to contribute to leap development ❤️.
To develop leap you just need to download or clone the repository and edit the files inside the src
folder, the files are divided by feature and by supporting modules, the out.js
file is the output file after building everything with the npm run build
command or on the server leap rebuild
.
We use esbuild since fivem (from what we have tested and understood) doesnt support ES (ECMAScript) or just doesnt support the import declaration.
after building everything you just need to rebuild the resource and build or restart with leap the interested resource.