Merge branch 'main' into feature/sched-return

This commit is contained in:
Filip Tibell 2024-10-16 21:24:53 +02:00 committed by GitHub
commit 93cbe12afd
Signed by: DevComp
GPG key ID: B5690EEEBB952194
41 changed files with 840 additions and 714 deletions

View file

@ -23,11 +23,8 @@ jobs:
with: with:
components: rustfmt components: rustfmt
- name: Install Just
uses: extractions/setup-just@v2
- name: Install Tooling - name: Install Tooling
uses: ok-nick/setup-aftman@v0.4.2 uses: CompeyDev/setup-rokit@v0.1.0
- name: Check Formatting - name: Check Formatting
run: just fmt-check run: just fmt-check
@ -40,11 +37,8 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install Just
uses: extractions/setup-just@v2
- name: Install Tooling - name: Install Tooling
uses: ok-nick/setup-aftman@v0.4.2 uses: CompeyDev/setup-rokit@v0.1.0
- name: Analyze - name: Analyze
run: just analyze run: just analyze

View file

@ -27,26 +27,26 @@ jobs:
file: crates/lune/Cargo.toml file: crates/lune/Cargo.toml
field: package.version field: package.version
dry-run: # dry-run:
name: Dry-run # name: Dry-run
needs: ["init"] # needs: ["init"]
runs-on: ubuntu-latest # runs-on: ubuntu-latest
steps: # steps:
- name: Checkout repository # - name: Checkout repository
uses: actions/checkout@v4 # uses: actions/checkout@v4
- name: Install Rust # - name: Install Rust
uses: dtolnay/rust-toolchain@stable # uses: dtolnay/rust-toolchain@stable
- name: Publish (dry-run) # - name: Publish (dry-run)
uses: katyo/publish-crates@v2 # uses: katyo/publish-crates@v2
with: # with:
dry-run: true # dry-run: true
check-repo: true # check-repo: true
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} # registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
build: build:
needs: ["init", "dry-run"] needs: ["init"] # , "dry-run"]
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -112,7 +112,7 @@ jobs:
release-github: release-github:
name: Release (GitHub) name: Release (GitHub)
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: ["init", "dry-run", "build"] needs: ["init", "build"] # , "dry-run", "build"]
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -139,20 +139,20 @@ jobs:
files: ./releases/*.zip files: ./releases/*.zip
draft: true draft: true
release-crates: # release-crates:
name: Release (crates.io) # name: Release (crates.io)
runs-on: ubuntu-latest # runs-on: ubuntu-latest
needs: ["init", "dry-run", "build"] # needs: ["init", "dry-run", "build"]
steps: # steps:
- name: Checkout repository # - name: Checkout repository
uses: actions/checkout@v4 # uses: actions/checkout@v4
- name: Install Rust # - name: Install Rust
uses: dtolnay/rust-toolchain@stable # uses: dtolnay/rust-toolchain@stable
- name: Publish crates # - name: Publish crates
uses: katyo/publish-crates@v2 # uses: katyo/publish-crates@v2
with: # with:
dry-run: false # dry-run: false
check-repo: true # check-repo: true
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} # registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}

View file

@ -8,6 +8,41 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## `0.8.9` - October 7th, 2024
### Changed
- Updated to Luau version `0.640`
## `0.8.8` - August 22nd, 2024
### Fixed
- Fixed errors when deserializing `Lighting.AttributesSerialize` by updating `rbx-dom` dependencies ([#245])
[#245]: https://github.com/lune-org/lune/pull/245
## `0.8.7` - August 10th, 2024
### Added
- Added a compression level option to `serde.compress` ([#224])
- Added missing vector methods to the `roblox` library ([#228])
### Changed
- Updated to Luau version `0.635`
- Updated to rbx-dom database version `0.634`
### Fixed
- Fixed `fs.readDir` with trailing forward-slash on Windows ([#220])
- Fixed `__type` and `__tostring` metamethods not always being respected when formatting tables
[#220]: https://github.com/lune-org/lune/pull/220
[#224]: https://github.com/lune-org/lune/pull/224
[#228]: https://github.com/lune-org/lune/pull/228
## `0.8.6` - June 23rd, 2024 ## `0.8.6` - June 23rd, 2024
### Added ### Added

982
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,4 +0,0 @@
[tools]
luau-lsp = "JohnnyMorganz/luau-lsp@1.29.1"
selene = "Kampfkarren/selene@0.27.1"
stylua = "JohnnyMorganz/StyLua@0.20.0"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-roblox" name = "lune-roblox"
version = "0.1.2" version = "0.1.4"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,17 +13,17 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
glam = "0.27" glam = "0.27"
rand = "0.8" rand = "0.8"
thiserror = "1.0" thiserror = "1.0"
once_cell = "1.17" once_cell = "1.17"
rbx_binary = "0.7.3" rbx_binary = "0.7.7"
rbx_dom_weak = "2.6.0" rbx_dom_weak = "2.9.0"
rbx_reflection = "4.4.0" rbx_reflection = "4.7.0"
rbx_reflection_database = "0.2.9" rbx_reflection_database = "0.2.12"
rbx_xml = "0.13.2" rbx_xml = "0.13.5"
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -52,6 +52,9 @@ impl LuaUserData for Vector2 {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
// Methods // Methods
methods.add_method("Angle", |_, this, rhs: LuaUserDataRef<Vector2>| {
Ok(this.0.angle_between(rhs.0))
});
methods.add_method("Cross", |_, this, rhs: LuaUserDataRef<Vector2>| { methods.add_method("Cross", |_, this, rhs: LuaUserDataRef<Vector2>| {
let this_v3 = Vec3::new(this.0.x, this.0.y, 0f32); let this_v3 = Vec3::new(this.0.x, this.0.y, 0f32);
let rhs_v3 = Vec3::new(rhs.0.x, rhs.0.y, 0f32); let rhs_v3 = Vec3::new(rhs.0.x, rhs.0.y, 0f32);
@ -60,6 +63,14 @@ impl LuaUserData for Vector2 {
methods.add_method("Dot", |_, this, rhs: LuaUserDataRef<Vector2>| { methods.add_method("Dot", |_, this, rhs: LuaUserDataRef<Vector2>| {
Ok(this.0.dot(rhs.0)) Ok(this.0.dot(rhs.0))
}); });
methods.add_method(
"FuzzyEq",
|_, this, (rhs, epsilon): (LuaUserDataRef<Vector2>, f32)| {
let eq_x = (rhs.0.x - this.0.x).abs() <= epsilon;
let eq_y = (rhs.0.y - this.0.y).abs() <= epsilon;
Ok(eq_x && eq_y)
},
);
methods.add_method( methods.add_method(
"Lerp", "Lerp",
|_, this, (rhs, alpha): (LuaUserDataRef<Vector2>, f32)| { |_, this, (rhs, alpha): (LuaUserDataRef<Vector2>, f32)| {
@ -72,6 +83,10 @@ impl LuaUserData for Vector2 {
methods.add_method("Min", |_, this, rhs: LuaUserDataRef<Vector2>| { methods.add_method("Min", |_, this, rhs: LuaUserDataRef<Vector2>| {
Ok(Vector2(this.0.min(rhs.0))) Ok(Vector2(this.0.min(rhs.0)))
}); });
methods.add_method("Abs", |_, this, ()| Ok(Vector2(this.0.abs())));
methods.add_method("Ceil", |_, this, ()| Ok(Vector2(this.0.ceil())));
methods.add_method("Floor", |_, this, ()| Ok(Vector2(this.0.floor())));
methods.add_method("Sign", |_, this, ()| Ok(Vector2(this.0.signum())));
// Metamethods // Metamethods
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq); methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string); methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);

View file

@ -133,6 +133,10 @@ impl LuaUserData for Vector3 {
methods.add_method("Min", |_, this, rhs: LuaUserDataRef<Vector3>| { methods.add_method("Min", |_, this, rhs: LuaUserDataRef<Vector3>| {
Ok(Vector3(this.0.min(rhs.0))) Ok(Vector3(this.0.min(rhs.0)))
}); });
methods.add_method("Abs", |_, this, ()| Ok(Vector3(this.0.abs())));
methods.add_method("Ceil", |_, this, ()| Ok(Vector3(this.0.ceil())));
methods.add_method("Floor", |_, this, ()| Ok(Vector3(this.0.floor())));
methods.add_method("Sign", |_, this, ()| Ok(Vector3(this.0.signum())));
// Metamethods // Metamethods
methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq); methods.add_meta_method(LuaMetaMethod::Eq, userdata_impl_eq);
methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string); methods.add_meta_method(LuaMetaMethod::ToString, userdata_impl_to_string);

View file

@ -26,7 +26,7 @@ pub fn add_methods<'lua, M: LuaUserDataMethods<'lua, Instance>>(m: &mut M) {
### See Also ### See Also
* [`Terrain`](https://create.roblox.com/docs/reference/engine/classes/Workspace#Terrain) * [`Terrain`](https://create.roblox.com/docs/reference/engine/classes/Workspace#Terrain)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
fn data_model_get_workspace(_: &Lua, this: &Instance) -> LuaResult<Instance> { fn data_model_get_workspace(_: &Lua, this: &Instance) -> LuaResult<Instance> {
get_or_create_property_ref_instance(this, "Workspace", "Workspace") get_or_create_property_ref_instance(this, "Workspace", "Workspace")
@ -37,7 +37,7 @@ fn data_model_get_workspace(_: &Lua, this: &Instance) -> LuaResult<Instance> {
### See Also ### See Also
* [`GetService`](https://create.roblox.com/docs/reference/engine/classes/ServiceProvider#GetService) * [`GetService`](https://create.roblox.com/docs/reference/engine/classes/ServiceProvider#GetService)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
fn data_model_get_service(_: &Lua, this: &Instance, service_name: String) -> LuaResult<Instance> { fn data_model_get_service(_: &Lua, this: &Instance, service_name: String) -> LuaResult<Instance> {
if matches!(class_is_a_service(&service_name), None | Some(false)) { if matches!(class_is_a_service(&service_name), None | Some(false)) {
@ -58,7 +58,7 @@ fn data_model_get_service(_: &Lua, this: &Instance, service_name: String) -> Lua
### See Also ### See Also
* [`FindService`](https://create.roblox.com/docs/reference/engine/classes/ServiceProvider#FindService) * [`FindService`](https://create.roblox.com/docs/reference/engine/classes/ServiceProvider#FindService)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
fn data_model_find_service( fn data_model_find_service(
_: &Lua, _: &Lua,

View file

@ -45,38 +45,26 @@ impl Instance {
Creates a new `Instance` from an existing dom object ref. Creates a new `Instance` from an existing dom object ref.
Panics if the instance does not exist in the internal dom, Panics if the instance does not exist in the internal dom,
or if the given dom object ref points to the dom root. or if the given dom object ref points to the internal dom root.
**WARNING:** Creating a new instance requires locking the internal dom, **WARNING:** Creating a new instance requires locking the internal dom,
any existing lock must first be released to prevent any deadlocking. any existing lock must first be released to prevent any deadlocking.
*/ */
pub(crate) fn new(dom_ref: DomRef) -> Self { #[must_use]
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); pub fn new(dom_ref: DomRef) -> Self {
Self::new_opt(dom_ref).expect("Failed to find instance in document")
let instance = dom
.get_by_ref(dom_ref)
.expect("Failed to find instance in document");
assert!(
!(instance.referent() == dom.root_ref()),
"Instances can not be created from dom roots"
);
Self {
dom_ref,
class_name: instance.class.clone(),
}
} }
/** /**
Creates a new `Instance` from a dom object ref, if the instance exists. Creates a new `Instance` from a dom object ref, if the instance exists.
Panics if the given dom object ref points to the dom root. Panics if the given dom object ref points to the internal dom root.
**WARNING:** Creating a new instance requires locking the internal dom, **WARNING:** Creating a new instance requires locking the internal dom,
any existing lock must first be released to prevent any deadlocking. any existing lock must first be released to prevent any deadlocking.
*/ */
pub(crate) fn new_opt(dom_ref: DomRef) -> Option<Self> { #[must_use]
pub fn new_opt(dom_ref: DomRef) -> Option<Self> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
if let Some(instance) = dom.get_by_ref(dom_ref) { if let Some(instance) = dom.get_by_ref(dom_ref) {
@ -97,12 +85,13 @@ impl Instance {
/** /**
Creates a new orphaned `Instance` with a given class name. Creates a new orphaned `Instance` with a given class name.
An orphaned instance is an instance at the root of a weak dom. An orphaned instance is an instance at the root of Lune's internal weak dom.
**WARNING:** Creating a new instance requires locking the internal dom, **WARNING:** Creating a new instance requires locking the internal dom,
any existing lock must first be released to prevent any deadlocking. any existing lock must first be released to prevent any deadlocking.
*/ */
pub(crate) fn new_orphaned(class_name: impl AsRef<str>) -> Self { #[must_use]
pub fn new_orphaned(class_name: impl AsRef<str>) -> Self {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
let class_name = class_name.as_ref(); let class_name = class_name.as_ref();
@ -122,10 +111,11 @@ impl Instance {
Creates a new orphaned `Instance` by transferring Creates a new orphaned `Instance` by transferring
it from an external weak dom to the internal one. it from an external weak dom to the internal one.
An orphaned instance is an instance at the root of a weak dom. An orphaned instance is an instance at the root of Lune's internal weak dom.
Panics if the given dom ref is the root dom ref of the external weak dom. Panics if the given dom ref is the root dom ref of the external weak dom.
*/ */
#[must_use]
pub fn from_external_dom(external_dom: &mut WeakDom, external_dom_ref: DomRef) -> Self { pub fn from_external_dom(external_dom: &mut WeakDom, external_dom_ref: DomRef) -> Self {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
let dom_root = dom.root_ref(); let dom_root = dom.root_ref();
@ -151,6 +141,12 @@ impl Instance {
cloned cloned
} }
/**
Clones multiple instances to an external weak dom.
This will place the instances as children of the
root of the weak dom, and return their referents.
*/
pub fn clone_multiple_into_external_dom( pub fn clone_multiple_into_external_dom(
referents: &[DomRef], referents: &[DomRef],
external_dom: &mut WeakDom, external_dom: &mut WeakDom,
@ -174,7 +170,7 @@ impl Instance {
### See Also ### See Also
* [`Clone`](https://create.roblox.com/docs/reference/engine/classes/Instance#Clone) * [`Clone`](https://create.roblox.com/docs/reference/engine/classes/Instance#Clone)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
#[must_use] #[must_use]
pub fn clone_instance(&self) -> Self { pub fn clone_instance(&self) -> Self {
@ -198,7 +194,7 @@ impl Instance {
### See Also ### See Also
* [`Destroy`](https://create.roblox.com/docs/reference/engine/classes/Instance#Destroy) * [`Destroy`](https://create.roblox.com/docs/reference/engine/classes/Instance#Destroy)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn destroy(&mut self) -> bool { pub fn destroy(&mut self) -> bool {
if self.is_destroyed() { if self.is_destroyed() {
@ -225,7 +221,7 @@ impl Instance {
### See Also ### See Also
* [`Instance::Destroy`] for more info about what happens when an instance gets destroyed * [`Instance::Destroy`] for more info about what happens when an instance gets destroyed
* [`ClearAllChildren`](https://create.roblox.com/docs/reference/engine/classes/Instance#ClearAllChildren) * [`ClearAllChildren`](https://create.roblox.com/docs/reference/engine/classes/Instance#ClearAllChildren)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn clear_all_children(&mut self) { pub fn clear_all_children(&mut self) {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -245,7 +241,7 @@ impl Instance {
### See Also ### See Also
* [`IsA`](https://create.roblox.com/docs/reference/engine/classes/Instance#IsA) * [`IsA`](https://create.roblox.com/docs/reference/engine/classes/Instance#IsA)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn is_a(&self, class_name: impl AsRef<str>) -> bool { pub fn is_a(&self, class_name: impl AsRef<str>) -> bool {
class_is_a(&self.class_name, class_name).unwrap_or(false) class_is_a(&self.class_name, class_name).unwrap_or(false)
@ -258,7 +254,7 @@ impl Instance {
### See Also ### See Also
* [`ClassName`](https://create.roblox.com/docs/reference/engine/classes/Instance#ClassName) * [`ClassName`](https://create.roblox.com/docs/reference/engine/classes/Instance#ClassName)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
#[must_use] #[must_use]
pub fn get_class_name(&self) -> &str { pub fn get_class_name(&self) -> &str {
@ -270,7 +266,7 @@ impl Instance {
### See Also ### See Also
* [`Name`](https://create.roblox.com/docs/reference/engine/classes/Instance#Name) * [`Name`](https://create.roblox.com/docs/reference/engine/classes/Instance#Name)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_name(&self) -> String { pub fn get_name(&self) -> String {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -286,7 +282,7 @@ impl Instance {
### See Also ### See Also
* [`Name`](https://create.roblox.com/docs/reference/engine/classes/Instance#Name) * [`Name`](https://create.roblox.com/docs/reference/engine/classes/Instance#Name)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn set_name(&self, name: impl Into<String>) { pub fn set_name(&self, name: impl Into<String>) {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -301,7 +297,7 @@ impl Instance {
### See Also ### See Also
* [`Parent`](https://create.roblox.com/docs/reference/engine/classes/Instance#Parent) * [`Parent`](https://create.roblox.com/docs/reference/engine/classes/Instance#Parent)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_parent(&self) -> Option<Instance> { pub fn get_parent(&self) -> Option<Instance> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -324,11 +320,11 @@ impl Instance {
If the provided parent is [`None`] the instance will become orphaned. If the provided parent is [`None`] the instance will become orphaned.
An orphaned instance is an instance at the root of a weak dom. An orphaned instance is an instance at the root of Lune's internal weak dom.
### See Also ### See Also
* [`Parent`](https://create.roblox.com/docs/reference/engine/classes/Instance#Parent) * [`Parent`](https://create.roblox.com/docs/reference/engine/classes/Instance#Parent)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn set_parent(&self, parent: Option<Instance>) { pub fn set_parent(&self, parent: Option<Instance>) {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -373,7 +369,7 @@ impl Instance {
### See Also ### See Also
* [`GetAttribute`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetAttribute) * [`GetAttribute`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetAttribute)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_attribute(&self, name: impl AsRef<str>) -> Option<DomValue> { pub fn get_attribute(&self, name: impl AsRef<str>) -> Option<DomValue> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -394,7 +390,7 @@ impl Instance {
### See Also ### See Also
* [`GetAttributes`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetAttributes) * [`GetAttributes`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetAttributes)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_attributes(&self) -> BTreeMap<String, DomValue> { pub fn get_attributes(&self) -> BTreeMap<String, DomValue> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -415,7 +411,7 @@ impl Instance {
### See Also ### See Also
* [`SetAttribute`](https://create.roblox.com/docs/reference/engine/classes/Instance#SetAttribute) * [`SetAttribute`](https://create.roblox.com/docs/reference/engine/classes/Instance#SetAttribute)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn set_attribute(&self, name: impl AsRef<str>, value: DomValue) { pub fn set_attribute(&self, name: impl AsRef<str>, value: DomValue) {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -470,7 +466,7 @@ impl Instance {
### See Also ### See Also
* [`AddTag`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#AddTag) * [`AddTag`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#AddTag)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn add_tag(&self, name: impl AsRef<str>) { pub fn add_tag(&self, name: impl AsRef<str>) {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -492,7 +488,7 @@ impl Instance {
### See Also ### See Also
* [`GetTags`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#GetTags) * [`GetTags`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#GetTags)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_tags(&self) -> Vec<String> { pub fn get_tags(&self) -> Vec<String> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -511,7 +507,7 @@ impl Instance {
### See Also ### See Also
* [`HasTag`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#HasTag) * [`HasTag`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#HasTag)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn has_tag(&self, name: impl AsRef<str>) -> bool { pub fn has_tag(&self, name: impl AsRef<str>) -> bool {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -531,7 +527,7 @@ impl Instance {
### See Also ### See Also
* [`RemoveTag`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#RemoveTag) * [`RemoveTag`](https://create.roblox.com/docs/reference/engine/classes/CollectionService#RemoveTag)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn remove_tag(&self, name: impl AsRef<str>) { pub fn remove_tag(&self, name: impl AsRef<str>) {
let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let mut dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -557,7 +553,7 @@ impl Instance {
### See Also ### See Also
* [`GetChildren`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetChildren) * [`GetChildren`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetChildren)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_children(&self) -> Vec<Instance> { pub fn get_children(&self) -> Vec<Instance> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -580,7 +576,7 @@ impl Instance {
### See Also ### See Also
* [`GetDescendants`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetDescendants) * [`GetDescendants`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetDescendants)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_descendants(&self) -> Vec<Instance> { pub fn get_descendants(&self) -> Vec<Instance> {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -614,7 +610,7 @@ impl Instance {
### See Also ### See Also
* [`GetFullName`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetFullName) * [`GetFullName`](https://create.roblox.com/docs/reference/engine/classes/Instance#GetFullName)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn get_full_name(&self) -> String { pub fn get_full_name(&self) -> String {
let dom = INTERNAL_DOM.lock().expect("Failed to lock document"); let dom = INTERNAL_DOM.lock().expect("Failed to lock document");
@ -704,7 +700,7 @@ impl Instance {
### See Also ### See Also
* [`FindFirstDescendant`](https://create.roblox.com/docs/reference/engine/classes/Instance#FindFirstDescendant) * [`FindFirstDescendant`](https://create.roblox.com/docs/reference/engine/classes/Instance#FindFirstDescendant)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
pub fn find_descendant<F>(&self, predicate: F) -> Option<Instance> pub fn find_descendant<F>(&self, predicate: F) -> Option<Instance>
where where

View file

@ -42,7 +42,7 @@ fn get_or_create_material_colors(instance: &Instance) -> MaterialColors {
### See Also ### See Also
* [`GetMaterialColor`](https://create.roblox.com/docs/reference/engine/classes/Terrain#GetMaterialColor) * [`GetMaterialColor`](https://create.roblox.com/docs/reference/engine/classes/Terrain#GetMaterialColor)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
fn terrain_get_material_color(_: &Lua, this: &Instance, material: EnumItem) -> LuaResult<Color3> { fn terrain_get_material_color(_: &Lua, this: &Instance, material: EnumItem) -> LuaResult<Color3> {
let material_colors = get_or_create_material_colors(this); let material_colors = get_or_create_material_colors(this);
@ -67,7 +67,7 @@ fn terrain_get_material_color(_: &Lua, this: &Instance, material: EnumItem) -> L
### See Also ### See Also
* [`SetMaterialColor`](https://create.roblox.com/docs/reference/engine/classes/Terrain#SetMaterialColor) * [`SetMaterialColor`](https://create.roblox.com/docs/reference/engine/classes/Terrain#SetMaterialColor)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
fn terrain_set_material_color( fn terrain_set_material_color(
_: &Lua, _: &Lua,

View file

@ -16,7 +16,7 @@ pub fn add_fields<'lua, F: LuaUserDataFields<'lua, Instance>>(f: &mut F) {
### See Also ### See Also
* [`Terrain`](https://create.roblox.com/docs/reference/engine/classes/Workspace#Terrain) * [`Terrain`](https://create.roblox.com/docs/reference/engine/classes/Workspace#Terrain)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
fn workspace_get_terrain(_: &Lua, this: &Instance) -> LuaResult<Instance> { fn workspace_get_terrain(_: &Lua, this: &Instance) -> LuaResult<Instance> {
get_or_create_property_ref_instance(this, "Terrain", "Terrain") get_or_create_property_ref_instance(this, "Terrain", "Terrain")
@ -27,7 +27,7 @@ fn workspace_get_terrain(_: &Lua, this: &Instance) -> LuaResult<Instance> {
### See Also ### See Also
* [`CurrentCamera`](https://create.roblox.com/docs/reference/engine/classes/Workspace#CurrentCamera) * [`CurrentCamera`](https://create.roblox.com/docs/reference/engine/classes/Workspace#CurrentCamera)
on the Roblox Developer Hub on the Roblox Developer Hub
*/ */
fn workspace_get_camera(_: &Lua, this: &Instance) -> LuaResult<Instance> { fn workspace_get_camera(_: &Lua, this: &Instance) -> LuaResult<Instance> {
get_or_create_property_ref_instance(this, "CurrentCamera", "Camera") get_or_create_property_ref_instance(this, "CurrentCamera", "Camera")

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-datetime" name = "lune-std-datetime"
version = "0.1.2" version = "0.1.3"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,10 +13,10 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
thiserror = "1.0" thiserror = "1.0"
chrono = "0.4.38" chrono = "0.4.38"
chrono_lc = "0.1.6" chrono_lc = "0.1.6"
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-fs" name = "lune-std-fs"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,11 +13,11 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
bstr = "1.9" bstr = "1.9"
tokio = { version = "1", default-features = false, features = ["fs"] } tokio = { version = "1", default-features = false, features = ["fs"] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }
lune-std-datetime = { version = "0.1.1", path = "../lune-std-datetime" } lune-std-datetime = { version = "0.1.2", path = "../lune-std-datetime" }

25
crates/lune-std-fs/src/lib.rs Normal file → Executable file
View file

@ -1,7 +1,7 @@
#![allow(clippy::cargo_common_metadata)] #![allow(clippy::cargo_common_metadata)]
use std::io::ErrorKind as IoErrorKind; use std::io::ErrorKind as IoErrorKind;
use std::path::{PathBuf, MAIN_SEPARATOR}; use std::path::PathBuf;
use bstr::{BString, ByteSlice}; use bstr::{BString, ByteSlice};
use mlua::prelude::*; use mlua::prelude::*;
@ -50,29 +50,16 @@ async fn fs_read_dir(_: &Lua, path: String) -> LuaResult<Vec<String>> {
let mut dir_strings = Vec::new(); let mut dir_strings = Vec::new();
let mut dir = fs::read_dir(&path).await.into_lua_err()?; let mut dir = fs::read_dir(&path).await.into_lua_err()?;
while let Some(dir_entry) = dir.next_entry().await.into_lua_err()? { while let Some(dir_entry) = dir.next_entry().await.into_lua_err()? {
if let Some(dir_path_str) = dir_entry.path().to_str() { if let Some(dir_name_str) = dir_entry.file_name().to_str() {
dir_strings.push(dir_path_str.to_owned()); dir_strings.push(dir_name_str.to_owned());
} else { } else {
return Err(LuaError::RuntimeError(format!( return Err(LuaError::RuntimeError(format!(
"File path could not be converted into a string: '{}'", "File name could not be converted into a string: '{}'",
dir_entry.path().display() dir_entry.file_name().to_string_lossy()
))); )));
} }
} }
let mut dir_string_prefix = path; Ok(dir_strings)
if !dir_string_prefix.ends_with(MAIN_SEPARATOR) {
dir_string_prefix.push(MAIN_SEPARATOR);
}
let dir_strings_no_prefix = dir_strings
.iter()
.map(|inner_path| {
inner_path
.trim()
.trim_start_matches(&dir_string_prefix)
.to_owned()
})
.collect::<Vec<_>>();
Ok(dir_strings_no_prefix)
} }
async fn fs_write_file(_: &Lua, (path, contents): (String, BString)) -> LuaResult<()> { async fn fs_write_file(_: &Lua, (path, contents): (String, BString)) -> LuaResult<()> {

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-luau" name = "lune-std-luau"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,6 +13,6 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau", "luau-jit"] } mlua = { version = "0.9.9", features = ["luau", "luau-jit"] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-net" name = "lune-std-net"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,7 +13,7 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" }
bstr = "1.9" bstr = "1.9"
@ -35,5 +35,5 @@ tokio = { version = "1", default-features = false, features = [
"macros", "macros",
] } ] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }
lune-std-serde = { version = "0.1.1", path = "../lune-std-serde" } lune-std-serde = { version = "0.1.2", path = "../lune-std-serde" }

View file

@ -18,6 +18,7 @@ impl LuaRequest {
let path = self.head.uri.path().to_string(); let path = self.head.uri.path().to_string();
let body = lua.create_string(&self.body)?; let body = lua.create_string(&self.body)?;
#[allow(clippy::mutable_key_type)]
let query: HashMap<LuaString, LuaString> = self let query: HashMap<LuaString, LuaString> = self
.head .head
.uri .uri
@ -32,6 +33,7 @@ impl LuaRequest {
}) })
.collect::<LuaResult<_>>()?; .collect::<LuaResult<_>>()?;
#[allow(clippy::mutable_key_type)]
let headers: HashMap<LuaString, LuaString> = self let headers: HashMap<LuaString, LuaString> = self
.head .head
.headers .headers

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-process" name = "lune-std-process"
version = "0.1.2" version = "0.1.3"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,7 +13,7 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" }
directories = "5.0" directories = "5.0"
@ -28,4 +28,4 @@ tokio = { version = "1", default-features = false, features = [
"sync", "sync",
] } ] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -42,8 +42,8 @@ pub fn module(lua: &Lua) -> LuaResult<LuaTable> {
cwd_str.push(MAIN_SEPARATOR); cwd_str.push(MAIN_SEPARATOR);
} }
// Create constants for OS & processor architecture // Create constants for OS & processor architecture
let os = lua.create_string(&OS.to_lowercase())?; let os = lua.create_string(OS.to_lowercase())?;
let arch = lua.create_string(&ARCH.to_lowercase())?; let arch = lua.create_string(ARCH.to_lowercase())?;
// Create readonly args array // Create readonly args array
let args_vec = lua let args_vec = lua
.app_data_ref::<Vec<String>>() .app_data_ref::<Vec<String>>()

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-regex" name = "lune-std-regex"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,9 +13,9 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
regex = "1.10" regex = "1.10"
self_cell = "1.0" self_cell = "1.0"
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-roblox" name = "lune-std-roblox"
version = "0.1.2" version = "0.1.4"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,11 +13,11 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" }
once_cell = "1.17" once_cell = "1.17"
rbx_cookie = { version = "0.1.4", default-features = false } rbx_cookie = { version = "0.1.4", default-features = false }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }
lune-roblox = { version = "0.1.2", path = "../lune-roblox" } lune-roblox = { version = "0.1.4", path = "../lune-roblox" }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-serde" name = "lune-std-serde"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,7 +13,7 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau", "serialize"] } mlua = { version = "0.9.9", features = ["luau", "serialize"] }
async-compression = { version = "0.4", features = [ async-compression = { version = "0.4", features = [
"tokio", "tokio",
@ -23,7 +23,7 @@ async-compression = { version = "0.4", features = [
"zlib", "zlib",
] } ] }
bstr = "1.9" bstr = "1.9"
lz4 = "1.24" lz4 = "1.26"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["preserve_order"] } serde_json = { version = "1.0", features = ["preserve_order"] }
serde_yaml = "0.9" serde_yaml = "0.9"
@ -44,4 +44,4 @@ tokio = { version = "1", default-features = false, features = [
"io-util", "io-util",
] } ] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -13,6 +13,7 @@ use async_compression::{
BrotliDecoder, BrotliEncoder, GzipDecoder, GzipEncoder, ZlibDecoder, ZlibEncoder, BrotliDecoder, BrotliEncoder, GzipDecoder, GzipEncoder, ZlibDecoder, ZlibEncoder,
}, },
Level::Best as CompressionQuality, Level::Best as CompressionQuality,
Level::Precise as PreciseCompressionQuality,
}; };
/** /**
@ -119,6 +120,7 @@ impl<'lua> FromLua<'lua> for CompressDecompressFormat {
pub async fn compress<'lua>( pub async fn compress<'lua>(
source: impl AsRef<[u8]>, source: impl AsRef<[u8]>,
format: CompressDecompressFormat, format: CompressDecompressFormat,
level: Option<i32>,
) -> LuaResult<Vec<u8>> { ) -> LuaResult<Vec<u8>> {
if let CompressDecompressFormat::LZ4 = format { if let CompressDecompressFormat::LZ4 = format {
let source = source.as_ref().to_vec(); let source = source.as_ref().to_vec();
@ -130,18 +132,22 @@ pub async fn compress<'lua>(
let mut bytes = Vec::new(); let mut bytes = Vec::new();
let reader = BufReader::new(source.as_ref()); let reader = BufReader::new(source.as_ref());
let compression_quality = match level {
Some(l) => PreciseCompressionQuality(l),
None => CompressionQuality,
};
match format { match format {
CompressDecompressFormat::Brotli => { CompressDecompressFormat::Brotli => {
let mut encoder = BrotliEncoder::with_quality(reader, CompressionQuality); let mut encoder = BrotliEncoder::with_quality(reader, compression_quality);
copy(&mut encoder, &mut bytes).await?; copy(&mut encoder, &mut bytes).await?;
} }
CompressDecompressFormat::GZip => { CompressDecompressFormat::GZip => {
let mut encoder = GzipEncoder::with_quality(reader, CompressionQuality); let mut encoder = GzipEncoder::with_quality(reader, compression_quality);
copy(&mut encoder, &mut bytes).await?; copy(&mut encoder, &mut bytes).await?;
} }
CompressDecompressFormat::ZLib => { CompressDecompressFormat::ZLib => {
let mut encoder = ZlibEncoder::with_quality(reader, CompressionQuality); let mut encoder = ZlibEncoder::with_quality(reader, compression_quality);
copy(&mut encoder, &mut bytes).await?; copy(&mut encoder, &mut bytes).await?;
} }
CompressDecompressFormat::LZ4 => unreachable!(), CompressDecompressFormat::LZ4 => unreachable!(),

View file

@ -46,9 +46,9 @@ fn serde_decode(lua: &Lua, (format, bs): (EncodeDecodeFormat, BString)) -> LuaRe
async fn serde_compress( async fn serde_compress(
lua: &Lua, lua: &Lua,
(format, bs): (CompressDecompressFormat, BString), (format, bs, level): (CompressDecompressFormat, BString, Option<i32>),
) -> LuaResult<LuaString> { ) -> LuaResult<LuaString> {
let bytes = compress(bs, format).await?; let bytes = compress(bs, format, level).await?;
lua.create_string(bytes) lua.create_string(bytes)
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-stdio" name = "lune-std-stdio"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -14,7 +14,7 @@ workspace = true
[dependencies] [dependencies]
dialoguer = "0.11" dialoguer = "0.11"
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" }
tokio = { version = "1", default-features = false, features = [ tokio = { version = "1", default-features = false, features = [
@ -22,4 +22,4 @@ tokio = { version = "1", default-features = false, features = [
"io-util", "io-util",
] } ] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -194,14 +194,14 @@ pub fn prompt(options: PromptOptions) -> LuaResult<PromptResult> {
prompt = prompt.default(b); prompt = prompt.default(b);
}; };
let result = prompt let result = prompt
.with_prompt(&options.text.expect("Missing text in prompt options")) .with_prompt(options.text.expect("Missing text in prompt options"))
.interact() .interact()
.into_lua_err()?; .into_lua_err()?;
Ok(PromptResult::Boolean(result)) Ok(PromptResult::Boolean(result))
} }
PromptKind::Select => { PromptKind::Select => {
let chosen = Select::with_theme(&theme) let chosen = Select::with_theme(&theme)
.with_prompt(&options.text.unwrap_or_default()) .with_prompt(options.text.unwrap_or_default())
.items(&options.options.expect("Missing options in prompt options")) .items(&options.options.expect("Missing options in prompt options"))
.interact_opt() .interact_opt()
.into_lua_err()?; .into_lua_err()?;
@ -212,7 +212,7 @@ pub fn prompt(options: PromptOptions) -> LuaResult<PromptResult> {
} }
PromptKind::MultiSelect => { PromptKind::MultiSelect => {
let chosen = MultiSelect::with_theme(&theme) let chosen = MultiSelect::with_theme(&theme)
.with_prompt(&options.text.unwrap_or_default()) .with_prompt(options.text.unwrap_or_default())
.items(&options.options.expect("Missing options in prompt options")) .items(&options.options.expect("Missing options in prompt options"))
.interact_opt() .interact_opt()
.into_lua_err()?; .into_lua_err()?;

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std-task" name = "lune-std-task"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,9 +13,9 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" }
tokio = { version = "1", default-features = false, features = ["time"] } tokio = { version = "1", default-features = false, features = ["time"] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-std" name = "lune-std"
version = "0.1.3" version = "0.1.5"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -38,22 +38,22 @@ stdio = ["dep:lune-std-stdio"]
task = ["dep:lune-std-task"] task = ["dep:lune-std-task"]
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
tokio = { version = "1", default-features = false, features = ["fs", "sync"] } tokio = { version = "1", default-features = false, features = ["fs", "sync"] }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }
lune-std-datetime = { optional = true, version = "0.1.2", path = "../lune-std-datetime" } lune-std-datetime = { optional = true, version = "0.1.3", path = "../lune-std-datetime" }
lune-std-fs = { optional = true, version = "0.1.1", path = "../lune-std-fs" } lune-std-fs = { optional = true, version = "0.1.2", path = "../lune-std-fs" }
lune-std-luau = { optional = true, version = "0.1.1", path = "../lune-std-luau" } lune-std-luau = { optional = true, version = "0.1.2", path = "../lune-std-luau" }
lune-std-net = { optional = true, version = "0.1.1", path = "../lune-std-net" } lune-std-net = { optional = true, version = "0.1.2", path = "../lune-std-net" }
lune-std-process = { optional = true, version = "0.1.2", path = "../lune-std-process" } lune-std-process = { optional = true, version = "0.1.3", path = "../lune-std-process" }
lune-std-regex = { optional = true, version = "0.1.1", path = "../lune-std-regex" } lune-std-regex = { optional = true, version = "0.1.2", path = "../lune-std-regex" }
lune-std-roblox = { optional = true, version = "0.1.2", path = "../lune-std-roblox" } lune-std-roblox = { optional = true, version = "0.1.4", path = "../lune-std-roblox" }
lune-std-serde = { optional = true, version = "0.1.1", path = "../lune-std-serde" } lune-std-serde = { optional = true, version = "0.1.2", path = "../lune-std-serde" }
lune-std-stdio = { optional = true, version = "0.1.1", path = "../lune-std-stdio" } lune-std-stdio = { optional = true, version = "0.1.2", path = "../lune-std-stdio" }
lune-std-task = { optional = true, version = "0.1.1", path = "../lune-std-task" } lune-std-task = { optional = true, version = "0.1.2", path = "../lune-std-task" }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune-utils" name = "lune-utils"
version = "0.1.2" version = "0.1.3"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -13,7 +13,7 @@ path = "src/lib.rs"
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau", "async"] } mlua = { version = "0.9.9", features = ["luau", "async"] }
tokio = { version = "1", default-features = false, features = ["fs"] } tokio = { version = "1", default-features = false, features = ["fs"] }

View file

@ -4,6 +4,7 @@ use std::fmt::{self, Write as _};
use mlua::prelude::*; use mlua::prelude::*;
use super::metamethods::{call_table_tostring_metamethod, get_table_type_metavalue};
use super::{ use super::{
basic::{format_value_styled, lua_value_as_plain_string_key}, basic::{format_value_styled, lua_value_as_plain_string_key},
config::ValueFormatConfig, config::ValueFormatConfig,
@ -46,7 +47,12 @@ pub(crate) fn format_value_recursive(
let mut buffer = String::new(); let mut buffer = String::new();
if let LuaValue::Table(ref t) = value { if let LuaValue::Table(ref t) = value {
if depth >= config.max_depth { if let Some(formatted) = format_typename_and_tostringed(
get_table_type_metavalue(t),
call_table_tostring_metamethod(t),
) {
write!(buffer, "{formatted}")?;
} else if depth >= config.max_depth {
write!(buffer, "{}", STYLE_DIM.apply_to("{ ... }"))?; write!(buffer, "{}", STYLE_DIM.apply_to("{ ... }"))?;
} else if !visited.insert(LuaValueId::from(t)) { } else if !visited.insert(LuaValueId::from(t)) {
write!(buffer, "{}", STYLE_DIM.apply_to("{ recursive }"))?; write!(buffer, "{}", STYLE_DIM.apply_to("{ recursive }"))?;
@ -164,3 +170,15 @@ fn format_table(
}) })
.collect() .collect()
} }
fn format_typename_and_tostringed(
typename: Option<String>,
tostringed: Option<String>,
) -> Option<String> {
match (typename, tostringed) {
(Some(typename), Some(tostringed)) => Some(format!("<{typename}({tostringed})>")),
(Some(typename), None) => Some(format!("<{typename}>")),
(None, Some(tostringed)) => Some(tostringed),
(None, None) => None,
}
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "lune" name = "lune"
version = "0.8.6" version = "0.8.9"
edition = "2021" edition = "2021"
license = "MPL-2.0" license = "MPL-2.0"
repository = "https://github.com/lune-org/lune" repository = "https://github.com/lune-org/lune"
@ -50,7 +50,7 @@ cli = ["dep:clap", "dep:include_dir", "dep:rustyline", "dep:zip_next"]
workspace = true workspace = true
[dependencies] [dependencies]
mlua = { version = "0.9.7", features = ["luau"] } mlua = { version = "0.9.9", features = ["luau"] }
mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" } mlua-luau-scheduler = { version = "0.0.2", path = "../mlua-luau-scheduler" }
anyhow = "1.0" anyhow = "1.0"
@ -71,9 +71,9 @@ reqwest = { version = "0.11", default-features = false, features = [
"rustls-tls", "rustls-tls",
] } ] }
lune-std = { optional = true, version = "0.1.3", path = "../lune-std" } lune-std = { optional = true, version = "0.1.5", path = "../lune-std" }
lune-roblox = { optional = true, version = "0.1.2", path = "../lune-roblox" } lune-roblox = { optional = true, version = "0.1.4", path = "../lune-roblox" }
lune-utils = { version = "0.1.2", path = "../lune-utils" } lune-utils = { version = "0.1.3", path = "../lune-utils" }
### CLI ### CLI

View file

@ -25,7 +25,7 @@ futures-lite = "2.2"
rustc-hash = "1.1" rustc-hash = "1.1"
tracing = "0.1" tracing = "0.1"
mlua = { version = "0.9.6", features = [ mlua = { version = "0.9.9", features = [
"luau", "luau",
"luau-jit", "luau-jit",
"async", "async",

4
rokit.toml Normal file
View file

@ -0,0 +1,4 @@
[tools]
luau-lsp = "JohnnyMorganz/luau-lsp@1.32.1"
stylua = "JohnnyMorganz/StyLua@0.20.0"
just = "casey/just@1.34.0"

View file

@ -1,6 +0,0 @@
std = "luau+lune"
exclude = ["luneTypes.d.luau"]
[lints]
high_cyclomatic_complexity = "warn"

View file

@ -42,4 +42,14 @@ assert(Vector2.new(2, 4) / 2 == Vector2.new(1, 2))
assert(Vector2.new(7, 15) // Vector2.new(3, 7) == Vector2.new(2, 2)) assert(Vector2.new(7, 15) // Vector2.new(3, 7) == Vector2.new(2, 2))
assert(Vector2.new(3, 7) // 2 == Vector2.new(1, 3)) assert(Vector2.new(3, 7) // 2 == Vector2.new(1, 3))
-- TODO: Vector math -- Vector math methods
assert(Vector2.new(-1, -2):Abs() == Vector2.new(1, 2))
assert(Vector2.new(-1.7, 2):Sign() == Vector2.new(-1, 1))
assert(Vector2.new(-1.9, 2.1):Ceil() == Vector2.new(-1, 3))
assert(Vector2.new(-1.1, 2.99):Floor() == Vector2.new(-2, 2))
assert(Vector2.new(1, 2):FuzzyEq(Vector2.new(1 - 1e-6, 2 + 1e-6), 1e-5))
assert(not Vector2.new(1, 2):FuzzyEq(Vector2.new(1.2, 2), 0.1))
local angle = Vector2.new(1, 1):Angle(Vector2.new(-1, 1))
assert(math.abs(angle - (math.pi / 2)) < 1e-5)

View file

@ -45,4 +45,10 @@ assert(Vector3.new(2, 4, 8) / 2 == Vector3.new(1, 2, 4))
assert(Vector3.new(7, 11, 15) // Vector3.new(3, 5, 7) == Vector3.new(2, 2, 2)) assert(Vector3.new(7, 11, 15) // Vector3.new(3, 5, 7) == Vector3.new(2, 2, 2))
assert(Vector3.new(3, 5, 7) // 2 == Vector3.new(1, 2, 3)) assert(Vector3.new(3, 5, 7) // 2 == Vector3.new(1, 2, 3))
-- TODO: Vector math -- Vector math methods
assert(Vector3.new(-1, -2, -3):Abs() == Vector3.new(1, 2, 3))
assert(Vector3.new(-1.7, 2, -3):Sign() == Vector3.new(-1, 1, -1))
assert(Vector3.new(-1.9, 2.1, 3.5):Ceil() == Vector3.new(-1, 3, 4))
assert(Vector3.new(-1.1, 2.99, 3.5):Floor() == Vector3.new(-2, 2, 3))
assert(Vector3.new(1, 2, 3):FuzzyEq(Vector3.new(1 - 1e-6, 2 + 1e-6, 3 + 1e-6), 1e-5))

View file

@ -87,10 +87,19 @@ export type DateTimeValueArguments = DateTimeValues & OptionalMillisecond
]=] ]=]
export type DateTimeValueReturns = DateTimeValues & Millisecond export type DateTimeValueReturns = DateTimeValues & Millisecond
--[=[
@prop unixTimestamp number
@within DateTime
Number of seconds passed since the UNIX epoch.
]=]
--[=[
@prop unixTimestampMillis number
@within DateTime
Number of milliseconds passed since the UNIX epoch.
]=]
local DateTime = { local DateTime = {
--- Number of seconds passed since the UNIX epoch.
unixTimestamp = (nil :: any) :: number, unixTimestamp = (nil :: any) :: number,
--- Number of milliseconds passed since the UNIX epoch.
unixTimestampMillis = (nil :: any) :: number, unixTimestampMillis = (nil :: any) :: number,
} }

View file

@ -19,67 +19,82 @@ local RegexMatch = {
type RegexMatch = typeof(RegexMatch) type RegexMatch = typeof(RegexMatch)
local RegexCaptures = {}
function RegexCaptures.get(self: RegexCaptures, index: number): RegexMatch?
return nil :: any
end
function RegexCaptures.group(self: RegexCaptures, group: string): RegexMatch?
return nil :: any
end
function RegexCaptures.format(self: RegexCaptures, format: string): string
return nil :: any
end
--[=[ --[=[
@class RegexCaptures @class RegexCaptures
Captures from a regular expression. Captures from a regular expression.
]=] ]=]
local RegexCaptures = {} export type RegexCaptures = typeof(setmetatable(
{} :: {
--[=[
@within RegexCaptures
@tag Method
@method get
--[=[ Returns the match at the given index, if one exists.
@within RegexCaptures
@tag Method
Returns the match at the given index, if one exists. @param index -- The index of the match to get
@return RegexMatch -- The match, if one exists
]=]
@param index -- The index of the match to get get: (self: RegexCaptures, index: number) -> RegexMatch?,
@return RegexMatch -- The match, if one exists
]=]
function RegexCaptures.get(self: RegexCaptures, index: number): RegexMatch?
return nil :: any
end
--[=[ --[=[
@within RegexCaptures @within RegexCaptures
@tag Method @tag Method
@method group
Returns the match for the given named match group, if one exists. Returns the match for the given named match group, if one exists.
@param group -- The name of the group to get @param group -- The name of the group to get
@return RegexMatch -- The match, if one exists @return RegexMatch -- The match, if one exists
]=] ]=]
function RegexCaptures.group(self: RegexCaptures, group: string): RegexMatch? group: (self: RegexCaptures, group: string) -> RegexMatch?,
return nil :: any
end
--[=[ --[=[
@within RegexCaptures @within RegexCaptures
@tag Method @tag Method
@method format
Formats the captures using the given format string. Formats the captures using the given format string.
### Example usage ### Example usage
```lua ```lua
local regex = require("@lune/regex") local regex = require("@lune/regex")
local re = regex.new("(?<day>[0-9]{2})-(?<month>[0-9]{2})-(?<year>[0-9]{4})") local re = regex.new("(?<day>[0-9]{2})-(?<month>[0-9]{2})-(?<year>[0-9]{4})")
local caps = re:captures("On 14-03-2010, I became a Tenneessee lamb."); local caps = re:captures("On 14-03-2010, I became a Tenneessee lamb.");
assert(caps ~= nil, "Example pattern should match example text") assert(caps ~= nil, "Example pattern should match example text")
local formatted = caps:format("year=$year, month=$month, day=$day") local formatted = caps:format("year=$year, month=$month, day=$day")
print(formatted) -- "year=2010, month=03, day=14" print(formatted) -- "year=2010, month=03, day=14"
``` ```
@param format -- The format string to use @param format -- The format string to use
@return string -- The formatted string @return string -- The formatted string
]=] ]=]
function RegexCaptures.format(self: RegexCaptures, format: string): string format: (self: RegexCaptures, format: string) -> string,
return nil :: any },
end {} :: {
__len: (self: RegexCaptures) -> number,
export type RegexCaptures = typeof(RegexCaptures) }
))
local Regex = {} local Regex = {}

View file

@ -136,9 +136,10 @@ end
@param format The format to use @param format The format to use
@param s The string to compress @param s The string to compress
@param level The compression level to use, clamped to the format's limits. The best compression level is used by default
@return The compressed string @return The compressed string
]=] ]=]
function serde.compress(format: CompressDecompressFormat, s: buffer | string): string function serde.compress(format: CompressDecompressFormat, s: buffer | string, level: number?): string
return nil :: any return nil :: any
end end