Fully featured wiki & slimmed down readme

This commit is contained in:
Filip Tibell 2023-02-23 18:43:18 +01:00
parent 3a57e1fdc2
commit 58ecbdb121
No known key found for this signature in database
14 changed files with 494 additions and 397 deletions

View file

@ -1,238 +0,0 @@
--> A walkthrough of all of the basic Lune features.
print("Hello, lune! 🌙")
--[==[
EXAMPLE #1
Using a function from another module
]==]
local module = require("./modules/module")
module.sayHello()
--[==[
EXAMPLE #2
Using the stdio library to prompt for input
]==]
local text = stdio.prompt("text", "Please write some text")
print("You wrote '" .. text .. "'!\n")
local confirmed = stdio.prompt("confirm", "Please confirm that you wrote some text")
if confirmed == false then
error("You didn't confirm!")
else
print("Confirmed!")
end
--[==[
EXAMPLE #3
Using arguments given to the program
]==]
if #process.args > 0 then
print("\nGot arguments while running hello_lune:")
print(process.args)
if #process.args > 3 then
error("Too many arguments!")
end
end
--[==[
EXAMPLE #4
Spawning tasks
]==]
task.spawn(function()
print("\nSpawned a task that will run instantly but not block")
task.wait(5)
end)
print("Spawning a delayed task that will run in 5 seconds")
task.delay(5, function()
print("\n...")
task.wait(1)
print("Hello again!")
task.wait(1)
print("Goodbye again! 🌙")
end)
--[==[
EXAMPLE #5
Get & set environment variables
Checks if environment variables are empty or not,
prints out if empty and if they have a value
]==]
print("\nReading current environment 🔎")
-- Environment variables can be read directly
assert(process.env.PATH ~= nil, "Missing PATH")
assert(process.env.PWD ~= nil, "Missing PWD")
-- And they can also be accessed using generalized iteration (not pairs!)
for key, value in process.env do
local box = if value and value ~= "" then "" else ""
print(string.format("[%s] %s", box, key))
end
--[==[
EXAMPLE #6
Read files in the current directory
This prints out directory & file names with some fancy icons
]==]
print("\nReading current dir 🗂️")
local entries = fs.readDir(".")
-- NOTE: We have to do this outside of the sort function
-- to avoid yielding across the metamethod boundary, any
-- calls to fs functions may yield for any reason
local entryIsDir = {}
for _, entry in entries do
entryIsDir[entry] = fs.isDir(entry)
end
-- Sort prioritizing directories first, then alphabetically
table.sort(entries, function(entry0, entry1)
if entryIsDir[entry0] ~= entryIsDir[entry1] then
return entryIsDir[entry0]
end
return entry0 < entry1
end)
-- Make sure we got some known files that should always exist
assert(table.find(entries, "Cargo.toml") ~= nil, "Missing Cargo.toml")
assert(table.find(entries, "Cargo.lock") ~= nil, "Missing Cargo.lock")
-- Print the pretty stuff
for _, entry in entries do
if fs.isDir(entry) then
print("📁 " .. entry)
else
print("📄 " .. entry)
end
end
-- NOTE: We skip the ping example in GitHub Actions
-- since the ping command does not work in azure
if not process.env.GITHUB_ACTIONS then
--[==[
EXAMPLE #7
Call out to another program / executable
Here we send some pings to google to demonstrate that programs
that yield or perform any network requests work correctly
]==]
print("\nSending 4 pings to google 🌏")
local result = process.spawn("ping", {
"google.com",
"-c 4",
})
--[==[
EXAMPLE #8
Using the result of a spawned process, exiting the process
We use the result from the above ping command and parse
it to show the results it gave us in a nicer format, here we
also exit with an error (exit code 1) if spawning the process failed
]==]
if result.ok then
assert(#result.stdout > 0, "Result output was empty")
local min, avg, max, stddev = string.match(
result.stdout,
"min/avg/max/stddev = ([%d%.]+)/([%d%.]+)/([%d%.]+)/([%d%.]+) ms"
)
print(string.format("Minimum ping time: %.3fms", assert(tonumber(min))))
print(string.format("Maximum ping time: %.3fms", assert(tonumber(max))))
print(string.format("Average ping time: %.3fms", assert(tonumber(avg))))
print(string.format("Standard deviation: %.3fms", assert(tonumber(stddev))))
else
print("\nFailed to send ping to google!")
print(result.stderr)
process.exit(result.code)
end
end
--[==[
EXAMPLE #9
Using the built-in networking library
]==]
print("\nSending PATCH request to web API 📤")
local apiResult = net.request({
url = "https://jsonplaceholder.typicode.com/posts/1",
method = "PATCH",
headers = {
["Content-Type"] = "application/json",
},
body = net.jsonEncode({
title = "foo",
body = "bar",
}),
})
if not apiResult.ok then
print("\nFailed to send network request!")
print(string.format("%d (%s)", apiResult.statusCode, apiResult.statusMessage))
print(apiResult.body)
process.exit(1)
end
type ApiResponse = {
id: number,
title: string,
body: string,
userId: number,
}
local apiResponse: ApiResponse = net.jsonDecode(apiResult.body)
assert(apiResponse.title == "foo", "Invalid json response")
assert(apiResponse.body == "bar", "Invalid json response")
print("Got valid JSON response with changes applied")
--[==[
EXAMPLE #10
Using the stdio library to print pretty
]==]
print("\nPrinting with pretty colors and auto-formatting 🎨")
print(stdio.color("blue") .. string.rep("", 22) .. stdio.color("reset"))
info("API response:", apiResponse)
warn({
Oh = {
No = {
TooMuch = {
Nesting = {
"Will not print",
},
},
},
},
})
print(stdio.color("blue") .. string.rep("", 22) .. stdio.color("reset"))
--[==[
EXAMPLE #11
Saying goodbye 😔
]==]
print("\nGoodbye, lune! 🌙")

View file

@ -1,7 +0,0 @@
local module = {}
function module.sayHello()
print("\nHello from a module! 🧩\n")
end
return module

162
README.md
View file

@ -4,153 +4,37 @@
<div align="center">
<h1> Lune 🌙 </h1>
<div>
<a href="https://crates.io/crates/lune"><img src="https://img.shields.io/crates/v/lune.svg?label=Version" alt="Current Lune library version" />
<a href="https://github.com/filiptibell/lune/actions"><img src="https://shields.io/endpoint?url=https://badges.readysetplay.io/workflow/filiptibell/lune/ci.yaml" alt="CI status" />
<a href="https://github.com/filiptibell/lune/actions"><img src="https://shields.io/endpoint?url=https://badges.readysetplay.io/workflow/filiptibell/lune/release.yaml" alt="Release status" />
<a href="https://github.com/filiptibell/lune/blob/main/LICENSE.txt"><img src="https://img.shields.io/github/license/filiptibell/lune.svg?label=License&color=informational" alt="Current Lune library version" />
<a href="https://crates.io/crates/lune">
<img src="https://img.shields.io/crates/v/lune.svg?label=Version" alt="Current Lune library version" />
</a>
<a href="https://github.com/filiptibell/lune/actions">
<img src="https://shields.io/endpoint?url=https://badges.readysetplay.io/workflow/filiptibell/lune/ci.yaml" alt="CI status" />
</a>
<a href="https://github.com/filiptibell/lune/actions">
<img src="https://shields.io/endpoint?url=https://badges.readysetplay.io/workflow/filiptibell/lune/release.yaml" alt="Release status" />
</a>
<a href="https://github.com/filiptibell/lune/blob/main/LICENSE.txt">
<img src="https://img.shields.io/github/license/filiptibell/lune.svg?label=License&color=informational" alt="Current Lune library version" />
</a>
</div>
<br /> A standalone <a href="https://luau-lang.org">Luau</a> script runner
<br /> 🚀 Use the ergonomics and readability of Luau for your shell scripts 🚀
</div>
<hr />
## ⚙️ Installation
Lune is a standalone [Luau](https://luau-lang.org) script runtime meant to be an alternative to traditional shell scripts, with the goal of drastically simplifying the typical tasks shell scripts are used for, making them easier to read and maintain.
The preferred way of installing Lune is using [Aftman](https://github.com/lpghatguy/aftman).
## Features
This will add `lune` to an `aftman.toml` file in the current directory, or create one if it does not exist:
- A strictly minimal but powerful interface that is easy to read and remember, just like Lua itself
- Fully featured APIs for the filesystem, networking, stdio, all included in the small (~1mb) executable
- World-class documentation, on the web _or_ directly in your editor, no network connection necessary
- A familiar scripting environment for Roblox developers, with an included 1-to-1 task scheduler port
```sh
aftman add filiptibell/lune
```
## Non-goals
You can also download pre-built binaries for most systems directly from the GitHub Releases page.
- Making scripts short and terse - proper autocomplete / intellisense make scripting using Lune just as quick, and readability is important
- Running full Roblox game scripts outside of Roblox - there is some compatibility here already, but Lune is meant for different purposes
## ✏️ Writing Lune Scripts
## Where do I start?
A great starting point and walkthrough of Lune can be found in [Hello, Lune](.lune/hello_lune.luau). <br />
More examples of how to write Lune scripts can be found in the [examples](.lune/examples/) folder.
<details>
<summary><b>🔎 List of APIs</b></summary>
`fs` - Filesystem <br />
`net` - Networking <br />
`process` - Current process & child processes <br />
`stdio` - Standard input / output & utility functions <br />
`task` - Task scheduler & thread spawning <br />
Documentation for individual members and types can be found using your editor of choice and [Luau LSP](https://github.com/JohnnyMorganz/luau-lsp).
</details>
<details>
<summary><b>🔀 Example translation from Bash</b></summary>
```bash
#!/bin/bash
VALID=true
COUNT=1
while [ $VALID ]
do
echo $COUNT
if [ $COUNT -eq 5 ];
then
break
fi
((COUNT++))
done
```
**_With Lune & Luau:_**
```lua
local valid = true
local count = 1
while valid do
print(count)
if count == 5 then
break
end
count += 1
end
```
</details>
<details>
<summary><b>🧑‍💻 Configuring VSCode for Lune</b></summary>
Lune puts developer experience first, and as such provides type definitions and configurations for several tools out of the box.
These steps assume you have already installed Lune and that it is available to run in the current directory.
<details>
<summary>Luau LSP</summary>
1. Run `lune --generate-luau-types` to generate a Luau type definitions file (`luneTypes.d.luau`) in the current directory
2. Run `lune --generate-docs-file` to generate a Luau LSP documentation file (`luneDocs.json`) in the current directory
3. Modify your VSCode settings, either by using the settings menu or in `settings.json`:
```json
{
"luau-lsp.require.mode": "relativeToFile", // Set the require mode to work with Lune
"luau-lsp.types.definitionFiles": ["luneTypes.d.luau"], // Add type definitions for Lune globals
"luau-lsp.types.documentationFiles": ["luneDocs.json"] // Add documentation for Lune globals
}
```
</details>
<details>
<summary>Selene</summary>
1. Run `lune --generate-selene-types` to generate a Selene type definitions file (`lune.yml`) in the current directory
2. Modify your Selene settings in `selene.toml`:
```yaml
# Use this if Lune is the only thing you use Luau files with:
std = "luau+lune"
# OR use this if your project also contains Roblox-specific Luau code:
std = "roblox+lune"
# If you are also using the Luau type definitions file, it may cause issues, and can be safely ignored:
exclude = ["luneTypes.d.luau"]
```
</details>
<br />
**_NOTE:_** _It is highly recommended to add any generated files to your `.gitignore` and to only generate them using these commands, since this guarantees that you have type definitions compatible with your installed version of Lune._
</details>
## 🏃 Running Lune Scripts
After you've written a script file, for example `script-name.luau`, you can run it:
```sh
lune script-name
```
This will look for the file `script-name.luau` in a few locations:
- The current directory
- The folder `lune` in the current directory, if it exists
- The folder `.lune` in the current directory, if it exists
If you don't want Lune to look in sub-directories you can provide a full file path with the file extension included, instead of only the file name. <br />
## 💭 Additional Commands
```sh
lune --list
```
Lists all scripts found in `lune` or `.lune` directories, including any top-level description comments. <br />
Lune description comments are always written at the top of a file and start with a lua-style comment arrow (`-->`).
---
**_NOTE:_** _Lune also supports files with the `.lua` extension but using the `.luau` extension is highly recommended._
Head over to the [wiki](https://github.com/filiptibell/lune/wiki) to get started using Lune!

View file

@ -0,0 +1,33 @@
<!-- markdownlint-disable MD033 -->
# ⚙️ Installation
The preferred way of installing Lune is using [Aftman](https://github.com/lpghatguy/aftman).
Running this command in your terminal will add `lune` to an `aftman.toml` file in the current directory, or create one if it does not exist:
```sh
aftman add filiptibell/lune
```
## Other options
### Building from source
Building and installing from source requires the latest version of [Rust & Cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html) to be installed on your system. <br />
Once installed, run the following command in your terminal:
```sh
cargo install lune --locked
```
Note that Lune does not make any minimum supported rust version (MSRV) guarantees and you may need to upgrade your version of Rust to update Lune in the future.
### Using GitHub Releases
You can download pre-built binaries for most systems directly from the [GitHub Releases](https://github.com/filiptibell/lune/releases) page. <br />
There are many tools that can install directly from releases, and it is up to you to choose what tool to use when installing using this method.
## Next steps
Now that you've installed Lune, head over to the [Writing Scripts](https://github.com/filiptibell/lune/wiki/Getting-Started---2-Writing-Scripts) page to write your first script!

View file

@ -0,0 +1,326 @@
<!-- markdownlint-disable MD033 -->
<!-- markdownlint-disable MD026 -->
# ✏️ Writing Lune Scripts
If you've already written some version of Lua (or Luau) scripts before, this walkthrough will make you feel right at home.
Once you have a script you want to run, head over to the [Running Scripts](https://github.com/filiptibell/lune/wiki/Getting-Started---3-Running-Scripts) page.
## Hello, Lune!
```lua
--[[
EXAMPLE #1
Using arguments given to the program
]]
if #process.args > 0 then
print("Got arguments:")
print(process.args)
if #process.args > 3 then
error("Too many arguments!")
end
else
print("Got no arguments ☹️")
end
--[[
EXAMPLE #2
Using the stdio library to prompt for terminal input
]]
local text = stdio.prompt("text", "Please write some text")
print("You wrote '" .. text .. "'!")
local confirmed = stdio.prompt("confirm", "Please confirm that you wrote some text")
if confirmed == false then
error("You didn't confirm!")
else
print("Confirmed!")
end
--[[
EXAMPLE #3
Get & set environment variables
Checks if environment variables are empty or not,
prints out ❌ if empty and ✅ if they have a value
]]
print("Reading current environment 🔎")
-- Environment variables can be read directly
assert(process.env.PATH ~= nil, "Missing PATH")
assert(process.env.PWD ~= nil, "Missing PWD")
-- And they can also be accessed using Luau's generalized iteration (but not pairs())
for key, value in process.env do
local box = if value and value ~= "" then "✅" else "❌"
print(string.format("[%s] %s", box, key))
end
--[[
EXAMPLE #4
Writing a module
Modularizing and splitting up your code is Lune is very straight-forward,
in contrast to other scripting languages and shells such as bash
]]
local module = {}
function module.sayHello()
print("Hello, Lune! 🌙")
end
return module
--[[
EXAMPLE #5
Using a function from another module / script
Lune has path-relative imports, similar to other popular languages such as JavaScript
]]
local module = require("../modules/module")
module.sayHello()
--[[
EXAMPLE #6
Spawning concurrent tasks
These tasks will run at the same time as other Lua code which lets you do primitive multitasking
]]
task.spawn(function()
print("Spawned a task that will run instantly but not block")
task.wait(5)
end)
print("Spawning a delayed task that will run in 5 seconds")
task.delay(5, function()
print("...")
task.wait(1)
print("Hello again!")
task.wait(1)
print("Goodbye again! 🌙")
end)
--[[
EXAMPLE #7
Read files in the current directory
This prints out directory & file names with some fancy icons
]]
print("Reading current dir 🗂️")
local entries = fs.readDir(".")
-- NOTE: We have to do this outside of the sort function
-- to avoid yielding across the metamethod boundary, all
-- of the filesystem APIs are asynchronous and yielding
local entryIsDir = {}
for _, entry in entries do
entryIsDir[entry] = fs.isDir(entry)
end
-- Sort prioritizing directories first, then alphabetically
table.sort(entries, function(entry0, entry1)
if entryIsDir[entry0] ~= entryIsDir[entry1] then
return entryIsDir[entry0]
end
return entry0 < entry1
end)
-- Make sure we got some known files that should always exist
assert(table.find(entries, "Cargo.toml") ~= nil, "Missing Cargo.toml")
assert(table.find(entries, "Cargo.lock") ~= nil, "Missing Cargo.lock")
-- Print the pretty stuff
for _, entry in entries do
if fs.isDir(entry) then
print("📁 " .. entry)
else
print("📄 " .. entry)
end
end
--[[
EXAMPLE #8
Call out to another program / executable
You can also get creative and combine this with example #6 to spawn several programs at the same time!
]]
print("Sending 4 pings to google 🌏")
local result = process.spawn("ping", {
"google.com",
"-c 4",
})
--[[
EXAMPLE #9
Using the result of a spawned process, exiting the process
This looks scary with lots of weird symbols, but, it's just some Lua-style pattern matching
to parse the lines of "min/avg/max/stddev = W/X/Y/Z ms" that the ping program outputs to us
]]
if result.ok then
assert(#result.stdout > 0, "Result output was empty")
local min, avg, max, stddev = string.match(
result.stdout,
"min/avg/max/stddev = ([%d%.]+)/([%d%.]+)/([%d%.]+)/([%d%.]+) ms"
)
print(string.format("Minimum ping time: %.3fms", assert(tonumber(min))))
print(string.format("Maximum ping time: %.3fms", assert(tonumber(max))))
print(string.format("Average ping time: %.3fms", assert(tonumber(avg))))
print(string.format("Standard deviation: %.3fms", assert(tonumber(stddev))))
else
print("Failed to send ping to google!")
print(result.stderr)
process.exit(result.code)
end
--[[
EXAMPLE #10
Using the built-in networking library, encoding & decoding json
]]
print("Sending PATCH request to web API 📤")
local apiResult = net.request({
url = "https://jsonplaceholder.typicode.com/posts/1",
method = "PATCH",
headers = {
["Content-Type"] = "application/json",
},
body = net.jsonEncode({
title = "foo",
body = "bar",
}),
})
if not apiResult.ok then
print("Failed to send network request!")
print(string.format("%d (%s)", apiResult.statusCode, apiResult.statusMessage))
print(apiResult.body)
process.exit(1)
end
type ApiResponse = {
id: number,
title: string,
body: string,
userId: number,
}
local apiResponse: ApiResponse = net.jsonDecode(apiResult.body)
assert(apiResponse.title == "foo", "Invalid json response")
assert(apiResponse.body == "bar", "Invalid json response")
print("Got valid JSON response with changes applied")
--[[
EXAMPLE #11
Using the stdio library to print pretty
]]
print("Printing with pretty colors and auto-formatting 🎨")
print(stdio.color("blue") .. string.rep("—", 22) .. stdio.color("reset"))
info("API response:", apiResponse)
warn({
Oh = {
No = {
TooMuch = {
Nesting = {
"Will not print",
},
},
},
},
})
print(stdio.color("blue") .. string.rep("—", 22) .. stdio.color("reset"))
--[[
EXAMPLE #12
Saying goodbye 😔
]]
print("Goodbye, lune! 🌙")
```
More real-world examples of how to write Lune scripts can be found in the [examples](https://github.com/filiptibell/lune/blob/main/.lune/examples/) folder.
Documentation for individual APIs and types can be found in "API Reference" in the sidebar of this wiki.
## Extras
### 🔀 Example translation from Bash
```bash
#!/bin/bash
VALID=true
COUNT=1
while [ $VALID ]
do
echo $COUNT
if [ $COUNT -eq 5 ];
then
break
fi
((COUNT++))
done
```
**_With Lune & Luau:_**
```lua
local valid = true
local count = 1
while valid do
print(count)
if count == 5 then
break
end
count += 1
end
```

View file

@ -0,0 +1,43 @@
<!-- markdownlint-disable MD033 -->
# 🏃 Running Lune Scripts
After you've written a script file, for example `script-name.luau`, you can run it:
```sh
lune script-name
```
This will look for the file `script-name.luau`**_<sup>[1]</sup>_** in a few locations:
- The current directory
- The folder `lune` in the current directory, if it exists
- The folder `.lune` in the current directory, if it exists
## 🎛️ Passing Command-Line Arguments
Arguments can be passed to a Lune script directory from the command line when running it:
```sh
lune script-name arg1 arg2 "argument three"
```
These arguments will then be available in your script using `process.args`:
```lua
print(process.args)
--> { "arg1", "arg2", "argument three" }
```
## 💭 Additional Commands
```sh
lune --list
```
Lists all scripts found in `lune` or `.lune` directories, including any top-level description comments. <br />
Lune description comments are always written at the top of a file and start with a lua-style comment arrow (`-->`).
---
**_<sup>[1]</sup>_** _Lune also supports files with the `.lua` extension but using the `.luau` extension is highly recommended. Additionally, if you don't want Lune to look in sub-directories you can provide a full file path with the file extension included, instead of only the file name._

View file

@ -0,0 +1,33 @@
# 🧑‍💻 Configuring VSCode and tooling for Lune
Lune puts developer experience first, and as such provides type definitions and configurations for several tools out of the box.
These steps assume you have already installed Lune and that it is available to run in the current directory.
## Luau LSP
1. Run `lune --generate-luau-types` to generate a Luau type definitions file (`luneTypes.d.luau`) in the current directory
2. Run `lune --generate-docs-file` to generate a Luau LSP documentation file (`luneDocs.json`) in the current directory
3. Modify your VSCode settings, either by using the settings menu or in `settings.json`:
```json
{
"luau-lsp.require.mode": "relativeToFile", // Set the require mode to work with Lune
"luau-lsp.types.definitionFiles": ["luneTypes.d.luau"], // Add type definitions for Lune globals
"luau-lsp.types.documentationFiles": ["luneDocs.json"] // Add documentation for Lune globals
}
```
## Selene
1. Run `lune --generate-selene-types` to generate a Selene type definitions file (`lune.yml`) in the current directory
2. Modify your Selene settings in `selene.toml`:
```yaml
# Use this if Lune is the only thing you use Luau files with:
std = "luau+lune"
# OR use this if your project also contains Roblox-specific Luau code:
std = "roblox+lune"
# If you are also using the Luau type definitions file, it may cause issues, and can be safely ignored:
exclude = ["luneTypes.d.luau"]
```

View file

@ -0,0 +1,25 @@
# 🏠 Home
Welcome to the Lune wiki!
Here you can find tutorials as well as a full API reference for all of Lune's built-in APIs.
If you are just getting started, head over to the [installation](https://github.com/filiptibell/lune/wiki/Getting-Started---1-Installation) page!
## Page Reference
- Getting Started
- [1. Installation](https://github.com/filiptibell/lune/wiki/Getting-Started---1-Installation)
- [2. Writing Scripts](https://github.com/filiptibell/lune/wiki/Getting-Started---2-Writing-Scripts)
- [3. Running Scripts](https://github.com/filiptibell/lune/wiki/Getting-Started---3-Running-Scripts)
- [4. Editor Setup](https://github.com/filiptibell/lune/wiki/Getting-Started---4-Editor-Setup)
- API Reference
- [FS](https://github.com/filiptibell/lune/wiki/API-Reference---FS)
- [Net](https://github.com/filiptibell/lune/wiki/API-Reference---Net)
- [Process](https://github.com/filiptibell/lune/wiki/API-Reference---Process)
- [Stdio](https://github.com/filiptibell/lune/wiki/API-Reference---Stdio)
- [Task](https://github.com/filiptibell/lune/wiki/API-Reference---Task)
- [Uncategorized](https://github.com/filiptibell/lune/wiki/API-Reference---Uncategorized)

View file

@ -2,19 +2,17 @@
# Home
- [Home](https://github.com/filiptibell/lune/wiki)
- [Getting Started](https://github.com/filiptibell/lune/wiki/getting-started)
- [1. Installation](https://github.com/filiptibell/lune/wiki/getting-started-1-installation)
- [2. Writing Scripts](https://github.com/filiptibell/lune/wiki/getting-started-2-writing-scripts)
- [3. Running Scripts](https://github.com/filiptibell/lune/wiki/getting-started-3-running-scripts)
- [4. Editor Setup](https://github.com/filiptibell/lune/wiki/getting-started-4-editor-setup)
- [Advanced Usage](https://github.com/filiptibell/lune/wiki/advanced-usage)
- [Getting Started](https://github.com/filiptibell/lune/wiki)
- [1. Installation](https://github.com/filiptibell/lune/wiki/Getting-Started---1-Installation)
- [2. Writing Scripts](https://github.com/filiptibell/lune/wiki/Getting-Started---2-Writing-Scripts)
- [3. Running Scripts](https://github.com/filiptibell/lune/wiki/Getting-Started---3-Running-Scripts)
- [4. Editor Setup](https://github.com/filiptibell/lune/wiki/Getting-Started---4-Editor-Setup)
# API Reference
- [FS](https://github.com/filiptibell/lune/wiki/api-reference-fs)
- [Net](https://github.com/filiptibell/lune/wiki/api-reference-net)
- [Process](https://github.com/filiptibell/lune/wiki/api-reference-process)
- [Stdio](https://github.com/filiptibell/lune/wiki/api-reference-stdio)
- [Task](https://github.com/filiptibell/lune/wiki/api-reference-task)
- [Uncategorized](https://github.com/filiptibell/lune/wiki/api-reference-uncategorized)
- [FS](https://github.com/filiptibell/lune/wiki/API-Reference---FS)
- [Net](https://github.com/filiptibell/lune/wiki/API-Reference---Net)
- [Process](https://github.com/filiptibell/lune/wiki/API-Reference---Process)
- [Stdio](https://github.com/filiptibell/lune/wiki/API-Reference---Stdio)
- [Task](https://github.com/filiptibell/lune/wiki/API-Reference---Task)
- [Uncategorized](https://github.com/filiptibell/lune/wiki/API-Reference---Uncategorized)