mirror of
https://github.com/lune-org/lune.git
synced 2024-12-12 04:50:36 +00:00
Implement console global
This commit is contained in:
parent
9311edc7d8
commit
aa1804d738
8 changed files with 364 additions and 5 deletions
|
@ -169,7 +169,36 @@ assert(apiResponse.body == "bar", "Invalid json response")
|
|||
print("Got valid JSON response with changes applied")
|
||||
|
||||
--[==[
|
||||
Example #8
|
||||
EXAMPLE #8
|
||||
|
||||
Using the console library to print pretty
|
||||
]==]
|
||||
|
||||
print("\nPrinting with pretty colors and auto-formatting 🎨")
|
||||
|
||||
console.setColor("blue")
|
||||
print(string.rep("—", 22))
|
||||
console.resetColor()
|
||||
|
||||
console.info("API response:", apiResponse)
|
||||
console.warn({
|
||||
Oh = {
|
||||
No = {
|
||||
TooMuch = {
|
||||
Nesting = {
|
||||
"Will not print",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
console.setColor("blue")
|
||||
print(string.rep("—", 22))
|
||||
console.resetColor()
|
||||
|
||||
--[==[
|
||||
EXAMPLE #9
|
||||
|
||||
Saying goodbye 😔
|
||||
]==]
|
||||
|
|
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -31,6 +31,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
assert(apiResponse.body == "bar", "Invalid json response")
|
||||
```
|
||||
|
||||
- Added console logging & coloring functions under `console`
|
||||
|
||||
This piece of code:
|
||||
|
||||
```lua
|
||||
local tab = { Integer = 1234, Hello = { "World" } }
|
||||
console.log(tab)
|
||||
```
|
||||
|
||||
Will print the following formatted text to the console, **_with syntax highlighting_**:
|
||||
|
||||
```lua
|
||||
{
|
||||
Integer = 1234,
|
||||
Hello = {
|
||||
"World",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Additional utility functions exist with the same behavior but that also print out a colored
|
||||
tag together with any data given to them: `console.info`, `console.warn`, `console.error` -
|
||||
These print out prefix tags `[INFO]`, `[WARN]`, `[ERROR]` in blue, orange, and red, respectively.
|
||||
|
||||
### Changed
|
||||
|
||||
- The `json` api is now part of `net`
|
||||
|
|
34
README.md
34
README.md
|
@ -32,7 +32,27 @@ Check out the examples of how to write a script in the [.lune](.lune) folder !
|
|||
<details>
|
||||
<summary><b>🔎 Full list of APIs</b></summary>
|
||||
|
||||
### **`fs`** - Filesystem
|
||||
<details>
|
||||
<summary><b>console</b> - Logging & formatting</summary>
|
||||
|
||||
```lua
|
||||
type console = {
|
||||
resetColor: () -> (),
|
||||
setColor: (color: "black" | "red" | "green" | "yellow" | "blue" | "purple" | "cyan" | "white") -> (),
|
||||
resetStyle: () -> (),
|
||||
setStyle: (color: "bold" | "dim") -> (),
|
||||
format: (...any) -> (string),
|
||||
log: (...any) -> (),
|
||||
info: (...any) -> (),
|
||||
warn: (...any) -> (),
|
||||
error: (...any) -> (),
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>fs</b> - Filesystem</summary>
|
||||
|
||||
```lua
|
||||
type fs = {
|
||||
|
@ -47,7 +67,10 @@ type fs = {
|
|||
}
|
||||
```
|
||||
|
||||
### **`net`** - Networking
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>net</b> - Networking</summary>
|
||||
|
||||
```lua
|
||||
type net = {
|
||||
|
@ -68,7 +91,10 @@ type net = {
|
|||
}
|
||||
```
|
||||
|
||||
### **`process`** - Current process & child processes
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>process</b> - Current process & child processes</summary>
|
||||
|
||||
```lua
|
||||
type process = {
|
||||
|
@ -87,6 +113,8 @@ type process = {
|
|||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>🔀 Example translation from Bash</b></summary>
|
||||
|
||||
|
|
24
lune.yml
24
lune.yml
|
@ -1,6 +1,30 @@
|
|||
# Lune v0.0.2
|
||||
---
|
||||
globals:
|
||||
# Console
|
||||
console.resetColor:
|
||||
console.setColor:
|
||||
args:
|
||||
- type: string
|
||||
console.resetStyle:
|
||||
console.setStyle:
|
||||
args:
|
||||
- type: string
|
||||
console.format:
|
||||
args:
|
||||
- type: "..."
|
||||
console.log:
|
||||
args:
|
||||
- type: "..."
|
||||
console.info:
|
||||
args:
|
||||
- type: "..."
|
||||
console.warn:
|
||||
args:
|
||||
- type: "..."
|
||||
console.error:
|
||||
args:
|
||||
- type: "..."
|
||||
# FS (filesystem)
|
||||
fs.readFile:
|
||||
args:
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
-- Lune v0.0.2
|
||||
|
||||
declare console: {
|
||||
resetColor: () -> (),
|
||||
setColor: (color: "black" | "red" | "green" | "yellow" | "blue" | "purple" | "cyan" | "white") -> (),
|
||||
resetStyle: () -> (),
|
||||
setStyle: (color: "bold" | "dim") -> (),
|
||||
format: (...any) -> (string),
|
||||
log: (...any) -> (),
|
||||
info: (...any) -> (),
|
||||
warn: (...any) -> (),
|
||||
error: (...any) -> (),
|
||||
}
|
||||
|
||||
declare fs: {
|
||||
readFile: (path: string) -> string,
|
||||
readDir: (path: string) -> { string },
|
||||
|
|
|
@ -7,7 +7,7 @@ use clap::{CommandFactory, Parser};
|
|||
use mlua::{Lua, MultiValue, Result, ToLua};
|
||||
|
||||
use crate::{
|
||||
lune::{fs::LuneFs, net::LuneNet, process::LuneProcess},
|
||||
lune::{console::LuneConsole, fs::LuneFs, net::LuneNet, process::LuneProcess},
|
||||
utils::GithubClient,
|
||||
};
|
||||
|
||||
|
@ -101,6 +101,7 @@ impl Cli {
|
|||
// Create a new lua state and add in all lune globals
|
||||
let lua = Lua::new();
|
||||
let globals = lua.globals();
|
||||
globals.set("console", LuneConsole::new())?;
|
||||
globals.set("fs", LuneFs::new())?;
|
||||
globals.set("net", LuneNet::new())?;
|
||||
globals.set("process", LuneProcess::new())?;
|
||||
|
|
240
src/lune/console.rs
Normal file
240
src/lune/console.rs
Normal file
|
@ -0,0 +1,240 @@
|
|||
use std::{
|
||||
fmt::Write,
|
||||
io::{self, Write as IoWrite},
|
||||
};
|
||||
|
||||
use mlua::{Lua, MultiValue, Result, UserData, UserDataMethods, Value};
|
||||
|
||||
const MAX_FORMAT_DEPTH: usize = 4;
|
||||
|
||||
const INDENT: &str = " ";
|
||||
|
||||
const COLOR_RESET: &str = "\x1B[0m";
|
||||
const COLOR_BLACK: &str = "\x1B[30m";
|
||||
const COLOR_RED: &str = "\x1B[31m";
|
||||
const COLOR_GREEN: &str = "\x1B[32m";
|
||||
const COLOR_YELLOW: &str = "\x1B[33m";
|
||||
const COLOR_BLUE: &str = "\x1B[34m";
|
||||
const COLOR_PURPLE: &str = "\x1B[35m";
|
||||
const COLOR_CYAN: &str = "\x1B[36m";
|
||||
const COLOR_WHITE: &str = "\x1B[37m";
|
||||
|
||||
const STYLE_RESET: &str = "\x1B[22m";
|
||||
const STYLE_BOLD: &str = "\x1B[1m";
|
||||
const STYLE_DIM: &str = "\x1B[2m";
|
||||
|
||||
pub struct LuneConsole();
|
||||
|
||||
impl LuneConsole {
|
||||
pub fn new() -> Self {
|
||||
Self()
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for LuneConsole {
|
||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_function("resetColor", console_reset_color);
|
||||
methods.add_function("setColor", console_set_color);
|
||||
methods.add_function("resetStyle", console_reset_style);
|
||||
methods.add_function("setStyle", console_set_style);
|
||||
methods.add_function("format", console_format);
|
||||
methods.add_function("log", console_log);
|
||||
methods.add_function("info", console_info);
|
||||
methods.add_function("warn", console_warn);
|
||||
methods.add_function("error", console_error);
|
||||
}
|
||||
}
|
||||
|
||||
fn flush_stdout() -> Result<()> {
|
||||
io::stdout().flush().map_err(mlua::Error::external)
|
||||
}
|
||||
|
||||
fn can_be_plain_lua_table_key(s: &mlua::String) -> bool {
|
||||
let str = s.to_string_lossy().to_string();
|
||||
let first_char = str.chars().next().unwrap();
|
||||
if first_char.is_alphabetic() {
|
||||
str.chars().all(|c| c == '_' || c.is_alphanumeric())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_format_value(buffer: &mut String, value: &Value, depth: usize) -> anyhow::Result<()> {
|
||||
// TODO: Handle tables with cyclic references
|
||||
// TODO: Handle other types like function, userdata, ...
|
||||
match &value {
|
||||
Value::Nil => write!(buffer, "nil")?,
|
||||
Value::Boolean(true) => write!(buffer, "{}true{}", COLOR_YELLOW, COLOR_RESET)?,
|
||||
Value::Boolean(false) => write!(buffer, "{}false{}", COLOR_YELLOW, COLOR_RESET)?,
|
||||
Value::Number(n) => write!(buffer, "{}{}{}", COLOR_BLUE, n, COLOR_RESET)?,
|
||||
Value::Integer(i) => write!(buffer, "{}{}{}", COLOR_BLUE, i, COLOR_RESET)?,
|
||||
Value::String(s) => write!(
|
||||
buffer,
|
||||
"{}\"{}\"{}",
|
||||
COLOR_GREEN,
|
||||
s.to_string_lossy()
|
||||
.replace('"', r#"\""#)
|
||||
.replace('\n', r#"\n"#),
|
||||
COLOR_RESET
|
||||
)?,
|
||||
Value::Table(ref tab) => {
|
||||
if depth >= MAX_FORMAT_DEPTH {
|
||||
write!(buffer, "{}{{ ... }}{}", STYLE_DIM, STYLE_RESET)?;
|
||||
} else {
|
||||
let depth_indent = INDENT.repeat(depth);
|
||||
write!(buffer, "{}{{{}", STYLE_DIM, STYLE_RESET)?;
|
||||
for pair in tab.clone().pairs::<Value, Value>() {
|
||||
let (key, value) = pair?;
|
||||
match &key {
|
||||
Value::String(s) if can_be_plain_lua_table_key(s) => write!(
|
||||
buffer,
|
||||
"\n{}{}{} {}={} ",
|
||||
depth_indent,
|
||||
INDENT,
|
||||
s.to_string_lossy(),
|
||||
STYLE_DIM,
|
||||
STYLE_RESET
|
||||
)?,
|
||||
_ => {
|
||||
write!(buffer, "\n{}{}[", depth_indent, INDENT)?;
|
||||
pretty_format_value(buffer, &key, depth)?;
|
||||
write!(buffer, "] {}={} ", STYLE_DIM, STYLE_RESET)?;
|
||||
}
|
||||
}
|
||||
pretty_format_value(buffer, &value, depth + 1)?;
|
||||
write!(buffer, "{},{}", STYLE_DIM, STYLE_RESET)?;
|
||||
}
|
||||
write!(buffer, "\n{}{}}}{}", depth_indent, STYLE_DIM, STYLE_RESET)?;
|
||||
}
|
||||
}
|
||||
_ => write!(buffer, "?")?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pretty_format_multi_value(multi: &MultiValue) -> Result<String> {
|
||||
let mut buffer = String::new();
|
||||
let mut counter = 0;
|
||||
for value in multi {
|
||||
counter += 1;
|
||||
if let Value::String(s) = value {
|
||||
write!(buffer, "{}", s.to_string_lossy()).map_err(mlua::Error::external)?
|
||||
} else {
|
||||
pretty_format_value(&mut buffer, value, 0).map_err(mlua::Error::external)?;
|
||||
}
|
||||
if counter < multi.len() {
|
||||
write!(&mut buffer, " ").map_err(mlua::Error::external)?;
|
||||
}
|
||||
}
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn print_style<S: AsRef<str>>(s: S) -> Result<()> {
|
||||
print!(
|
||||
"{}",
|
||||
match s.as_ref() {
|
||||
"reset" => STYLE_RESET,
|
||||
"bold" => STYLE_BOLD,
|
||||
"dim" => STYLE_DIM,
|
||||
_ => {
|
||||
return Err(mlua::Error::RuntimeError(format!(
|
||||
"The style '{}' is not a valid style name",
|
||||
s.as_ref()
|
||||
)));
|
||||
}
|
||||
}
|
||||
);
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_color<S: AsRef<str>>(s: S) -> Result<()> {
|
||||
print!(
|
||||
"{}",
|
||||
match s.as_ref() {
|
||||
"reset" => COLOR_RESET,
|
||||
"black" => COLOR_BLACK,
|
||||
"red" => COLOR_RED,
|
||||
"green" => COLOR_GREEN,
|
||||
"yellow" => COLOR_YELLOW,
|
||||
"blue" => COLOR_BLUE,
|
||||
"purple" => COLOR_PURPLE,
|
||||
"cyan" => COLOR_CYAN,
|
||||
"white" => COLOR_WHITE,
|
||||
_ => {
|
||||
return Err(mlua::Error::RuntimeError(format!(
|
||||
"The color '{}' is not a valid color name",
|
||||
s.as_ref()
|
||||
)));
|
||||
}
|
||||
}
|
||||
);
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_reset_color(_: &Lua, _: ()) -> Result<()> {
|
||||
print_color("reset")?;
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_set_color(_: &Lua, color: String) -> Result<()> {
|
||||
print_color(color.trim().to_ascii_lowercase())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_reset_style(_: &Lua, _: ()) -> Result<()> {
|
||||
print_style("reset")?;
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_set_style(_: &Lua, style: String) -> Result<()> {
|
||||
print_style(style.trim().to_ascii_lowercase())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_format(_: &Lua, args: MultiValue) -> Result<String> {
|
||||
pretty_format_multi_value(&args)
|
||||
}
|
||||
|
||||
fn console_log(_: &Lua, args: MultiValue) -> Result<()> {
|
||||
let s = pretty_format_multi_value(&args)?;
|
||||
println!("{}", s);
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_info(_: &Lua, args: MultiValue) -> Result<()> {
|
||||
print!(
|
||||
"{}{}[INFO]{}{} ",
|
||||
STYLE_BOLD, COLOR_CYAN, COLOR_RESET, STYLE_RESET
|
||||
);
|
||||
let s = pretty_format_multi_value(&args)?;
|
||||
println!("{}", s);
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_warn(_: &Lua, args: MultiValue) -> Result<()> {
|
||||
print!(
|
||||
"{}{}[WARN]{}{} ",
|
||||
STYLE_BOLD, COLOR_YELLOW, COLOR_RESET, STYLE_RESET
|
||||
);
|
||||
let s = pretty_format_multi_value(&args)?;
|
||||
println!("{}", s);
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_error(_: &Lua, args: MultiValue) -> Result<()> {
|
||||
eprint!(
|
||||
"{}{}[ERROR]{}{} ",
|
||||
STYLE_BOLD, COLOR_RED, COLOR_RESET, STYLE_RESET
|
||||
);
|
||||
let s = pretty_format_multi_value(&args)?;
|
||||
eprintln!("{}", s);
|
||||
flush_stdout()?;
|
||||
Ok(())
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
pub mod console;
|
||||
pub mod fs;
|
||||
pub mod net;
|
||||
pub mod process;
|
||||
|
|
Loading…
Reference in a new issue