Skip to content

Commit 1de6ea7

Browse files
committed
trim-newline
1 parent 43216e6 commit 1de6ea7

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

src/clojure_string.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub(crate) mod lower_case;
66
pub(crate) mod reverse;
77
pub(crate) mod starts_with_qmark_;
88
pub(crate) mod trim;
9+
pub(crate) mod trim_newline;
910
pub(crate) mod triml;
1011
pub(crate) mod trimr;
1112
pub(crate) mod upper_case;

src/clojure_string/trim_newline.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::ifn::IFn;
2+
use crate::value::{ToValue, Value};
3+
use std::rc::Rc;
4+
5+
use crate::error_message;
6+
use crate::type_tag::TypeTag;
7+
8+
/// clojure.string/trim_newline trims white space from start of string
9+
#[derive(Debug, Clone)]
10+
pub struct TrimNewlineFn {}
11+
impl ToValue for TrimNewlineFn {
12+
fn to_value(&self) -> Value {
13+
Value::IFn(Rc::new(self.clone()))
14+
}
15+
}
16+
impl IFn for TrimNewlineFn {
17+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
18+
if args.len() != 1 {
19+
return error_message::wrong_arg_count(1, args.len());
20+
} else {
21+
match args.get(0).unwrap().to_value() {
22+
Value::String(s) => {
23+
Value::String(s.trim_end_matches(|c| c == '\n' || c == '\r').to_string())
24+
}
25+
_a => error_message::type_mismatch(TypeTag::String, &_a.to_value()),
26+
}
27+
}
28+
}
29+
}
30+
31+
#[cfg(test)]
32+
mod tests {
33+
mod trim_newline_tests {
34+
use crate::clojure_string::trim_newline::TrimNewlineFn;
35+
use crate::ifn::IFn;
36+
use crate::value::Value;
37+
use std::rc::Rc;
38+
39+
#[test]
40+
fn trim_newline() {
41+
let trim_newline = TrimNewlineFn {};
42+
let s = " \r \t hello \n\r";
43+
let args = vec![Rc::new(Value::String(String::from(s)))];
44+
assert_eq!(
45+
Value::String(String::from(" \r \t hello ")),
46+
trim_newline.invoke(args)
47+
);
48+
}
49+
#[test]
50+
fn trim_newline_does_nothing() {
51+
let trim_newline = TrimNewlineFn {};
52+
let s = " \r \t hello . ";
53+
let args = vec![Rc::new(Value::String(String::from(s)))];
54+
assert_eq!(
55+
Value::String(String::from(" \r \t hello . ")),
56+
trim_newline.invoke(args)
57+
);
58+
}
59+
}
60+
}

src/environment.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ impl Environment {
214214
let trim_fn = clojure_string::trim::TrimFn {};
215215
let triml_fn = clojure_string::triml::TrimLFn {};
216216
let trimr_fn = clojure_string::trimr::TrimRFn {};
217+
let trim_newline_fn = clojure_string::trim_newline::TrimNewlineFn {};
217218

218219
// Hardcoded fns
219220
let lexical_eval_fn = Value::LexicalEvalFn {};
@@ -327,6 +328,12 @@ impl Environment {
327328
trimr_fn.to_rc_value(),
328329
);
329330

331+
environment.insert_into_namespace(
332+
&Symbol::intern("clojure.string"),
333+
Symbol::intern("trim-newline"),
334+
trim_newline_fn.to_rc_value(),
335+
);
336+
330337
environment.insert(Symbol::intern("+"), add_fn.to_rc_value());
331338
environment.insert(Symbol::intern("let"), let_macro.to_rc_value());
332339
environment.insert(Symbol::intern("str"), str_fn.to_rc_value());

0 commit comments

Comments
 (0)