diff --git a/Cargo.lock b/Cargo.lock index eb55d8050..bd5f7c0c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2309,7 +2309,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "steel-core" version = "0.6.0" -source = "git+https://github.com/mattwparas/steel.git#1fb88e561474c723a4fd2675553d6091a380aef1" +source = "git+https://github.com/mattwparas/steel.git#01e42f435de3f6ca8cf083fdfc422d2a445d5bc9" dependencies = [ "abi_stable", "anyhow", @@ -2345,7 +2345,7 @@ dependencies = [ [[package]] name = "steel-derive" version = "0.5.0" -source = "git+https://github.com/mattwparas/steel.git#1fb88e561474c723a4fd2675553d6091a380aef1" +source = "git+https://github.com/mattwparas/steel.git#01e42f435de3f6ca8cf083fdfc422d2a445d5bc9" dependencies = [ "proc-macro2", "quote", @@ -2355,7 +2355,7 @@ dependencies = [ [[package]] name = "steel-gen" version = "0.2.0" -source = "git+https://github.com/mattwparas/steel.git#1fb88e561474c723a4fd2675553d6091a380aef1" +source = "git+https://github.com/mattwparas/steel.git#01e42f435de3f6ca8cf083fdfc422d2a445d5bc9" dependencies = [ "codegen", "serde", @@ -2365,7 +2365,7 @@ dependencies = [ [[package]] name = "steel-parser" version = "0.6.0" -source = "git+https://github.com/mattwparas/steel.git#1fb88e561474c723a4fd2675553d6091a380aef1" +source = "git+https://github.com/mattwparas/steel.git#01e42f435de3f6ca8cf083fdfc422d2a445d5bc9" dependencies = [ "fxhash", "lasso", diff --git a/helix-core/src/extensions.rs b/helix-core/src/extensions.rs index 7e8081a91..8657c527e 100644 --- a/helix-core/src/extensions.rs +++ b/helix-core/src/extensions.rs @@ -5,10 +5,13 @@ pub mod steel_implementations { use smallvec::SmallVec; use steel::{ - rvals::{Custom, SteelString}, + rvals::{as_underlying_type, Custom, SteelString}, steel_vm::{builtin::BuiltInModule, register_fn::RegisterFn}, + SteelVal, }; + use helix_stdx::rope::RopeSliceExt; + use crate::syntax::{AutoPairConfig, SoftWrap}; impl steel::rvals::Custom for crate::Position {} @@ -16,20 +19,38 @@ pub mod steel_implementations { impl steel::rvals::Custom for AutoPairConfig {} impl steel::rvals::Custom for SoftWrap {} - #[derive(Clone, Copy, Debug)] + #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum SliceKind { Normal(usize, usize), Byte(usize, usize), Line(usize), } - #[derive(Clone)] + #[derive(Clone, PartialEq, Eq)] pub struct SteelRopeSlice { text: crate::Rope, ranges: SmallVec<[SliceKind; 5]>, } - impl Custom for SteelRopeSlice {} + impl Custom for SteelRopeSlice { + // `equal?` on two ropes should return true if they are the same + fn equality_hint(&self, other: &dyn steel::rvals::CustomType) -> bool { + if let Some(other) = as_underlying_type::(other) { + self == other + } else { + false + } + } + + fn equality_hint_general(&self, other: &steel::SteelVal) -> bool { + match other { + SteelVal::StringV(s) => self.to_slice() == s.as_str(), + SteelVal::Custom(c) => Self::equality_hint(&self, c.borrow().as_ref()), + + _ => false, + } + } + } impl SteelRopeSlice { pub fn from_string(string: SteelString) -> Self { @@ -95,30 +116,48 @@ pub mod steel_implementations { self.to_slice().len_lines() } + pub fn trim_start(mut self) -> Self { + for (idx, c) in self.to_slice().chars().enumerate() { + if !c.is_whitespace() { + self.ranges.push(SliceKind::Normal(0, idx)); + break; + } + } + + self + } + pub fn trimmed_starts_with(&self, pat: SteelString) -> bool { let maybe_owned = Cow::from(self.to_slice()); maybe_owned.trim_start().starts_with(pat.as_str()) } + + pub fn starts_with(&self, pat: SteelString) -> bool { + self.to_slice().starts_with(pat.as_str()) + } + + pub fn ends_with(&self, pat: SteelString) -> bool { + self.to_slice().ends_with(pat.as_str()) + } } pub fn rope_module() -> BuiltInModule { let mut module = BuiltInModule::new("helix/core/text"); module - .register_fn("string->slice", SteelRopeSlice::from_string) - .register_fn("slice->slice", SteelRopeSlice::slice) - .register_fn("slice-char->byte", SteelRopeSlice::char_to_byte) - .register_fn("slice->byte-slice", SteelRopeSlice::byte_slice) - .register_fn("slice->line", SteelRopeSlice::line) - .register_fn("slice->string", SteelRopeSlice::to_string) - .register_fn("slice-len-chars", SteelRopeSlice::len_chars) - .register_fn("slice-char-ref", SteelRopeSlice::get_char) - .register_fn("slice-len-lines", SteelRopeSlice::len_lines) - .register_fn( - "slice-trim-and-starts-with?", - SteelRopeSlice::trimmed_starts_with, - ); + .register_fn("string->rope", SteelRopeSlice::from_string) + .register_fn("rope->slice", SteelRopeSlice::slice) + .register_fn("rope-char->byte", SteelRopeSlice::char_to_byte) + .register_fn("rope->byte-slice", SteelRopeSlice::byte_slice) + .register_fn("rope->line", SteelRopeSlice::line) + .register_fn("rope->string", SteelRopeSlice::to_string) + .register_fn("rope-len-chars", SteelRopeSlice::len_chars) + .register_fn("rope-char-ref", SteelRopeSlice::get_char) + .register_fn("rope-len-lines", SteelRopeSlice::len_lines) + .register_fn("rope-starts-with?", SteelRopeSlice::starts_with) + .register_fn("rope-ends-with?", SteelRopeSlice::ends_with) + .register_fn("rope-trim-start", SteelRopeSlice::trim_start); module }