aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Tham <[email protected]>2022-01-05 04:01:48 +0000
committerGitHub <[email protected]>2022-01-05 04:01:48 +0000
commit9fa2823b3916184dbfbb9c704ab34ae79c0c1038 (patch)
tree597a3ac1bad860fa62737faa58aeb71184c249be
parent3f52f6f2ce8408350fcdc180d416e63dd627d93f (diff)
parent3f0f8d9f0f910b4c9477297049d4a508eacc3734 (diff)
Merge pull request #51 from Ma27/exp-and-round
Add functions `exp()`, `exp2()` & `round()`; fix minor readline issues
-rw-r--r--Cargo.lock188
-rw-r--r--Cargo.toml2
-rw-r--r--src/lex.rs25
-rw-r--r--src/main.rs31
-rw-r--r--src/readline.rs42
5 files changed, 238 insertions, 50 deletions
diff --git a/Cargo.lock b/Cargo.lock
index de51705..287db82 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,5 +1,7 @@
1# This file is automatically @generated by Cargo. 1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing. 2# It is not intended for manual editing.
3version = 3
4
3[[package]] 5[[package]]
4name = "aho-corasick" 6name = "aho-corasick"
5version = "0.7.10" 7version = "0.7.10"
@@ -55,9 +57,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
55 57
56[[package]] 58[[package]]
57name = "bitflags" 59name = "bitflags"
58version = "1.2.1" 60version = "1.3.2"
59source = "registry+https://github.com/rust-lang/crates.io-index" 61source = "registry+https://github.com/rust-lang/crates.io-index"
60checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 62checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
61 63
62[[package]] 64[[package]]
63name = "blake2b_simd" 65name = "blake2b_simd"
@@ -83,6 +85,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
83checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 85checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
84 86
85[[package]] 87[[package]]
88name = "cfg-if"
89version = "1.0.0"
90source = "registry+https://github.com/rust-lang/crates.io-index"
91checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
92
93[[package]]
86name = "clap" 94name = "clap"
87version = "2.33.0" 95version = "2.33.0"
88source = "registry+https://github.com/rust-lang/crates.io-index" 96source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -98,6 +106,17 @@ dependencies = [
98] 106]
99 107
100[[package]] 108[[package]]
109name = "clipboard-win"
110version = "4.2.2"
111source = "registry+https://github.com/rust-lang/crates.io-index"
112checksum = "3db8340083d28acb43451166543b98c838299b7e0863621be53a338adceea0ed"
113dependencies = [
114 "error-code",
115 "str-buf",
116 "winapi",
117]
118
119[[package]]
101name = "constant_time_eq" 120name = "constant_time_eq"
102version = "0.1.5" 121version = "0.1.5"
103source = "registry+https://github.com/rust-lang/crates.io-index" 122source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -110,7 +129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
110checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" 129checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
111dependencies = [ 130dependencies = [
112 "autocfg", 131 "autocfg",
113 "cfg-if", 132 "cfg-if 0.1.10",
114 "lazy_static", 133 "lazy_static",
115] 134]
116 135
@@ -120,31 +139,36 @@ version = "2.0.2"
120source = "registry+https://github.com/rust-lang/crates.io-index" 139source = "registry+https://github.com/rust-lang/crates.io-index"
121checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c" 140checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
122dependencies = [ 141dependencies = [
123 "cfg-if", 142 "cfg-if 0.1.10",
124 "dirs-sys", 143 "dirs-sys",
125] 144]
126 145
127[[package]] 146[[package]]
128name = "dirs" 147name = "dirs-sys"
129version = "1.0.5" 148version = "0.3.4"
130source = "registry+https://github.com/rust-lang/crates.io-index" 149source = "registry+https://github.com/rust-lang/crates.io-index"
131checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" 150checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
132dependencies = [ 151dependencies = [
152 "cfg-if 0.1.10",
133 "libc", 153 "libc",
134 "redox_users", 154 "redox_users",
135 "winapi", 155 "winapi",
136] 156]
137 157
138[[package]] 158[[package]]
139name = "dirs-sys" 159name = "endian-type"
140version = "0.3.4" 160version = "0.1.2"
141source = "registry+https://github.com/rust-lang/crates.io-index" 161source = "registry+https://github.com/rust-lang/crates.io-index"
142checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" 162checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
163
164[[package]]
165name = "error-code"
166version = "2.3.0"
167source = "registry+https://github.com/rust-lang/crates.io-index"
168checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff"
143dependencies = [ 169dependencies = [
144 "cfg-if",
145 "libc", 170 "libc",
146 "redox_users", 171 "str-buf",
147 "winapi",
148] 172]
149 173
150[[package]] 174[[package]]
@@ -162,12 +186,23 @@ dependencies = [
162] 186]
163 187
164[[package]] 188[[package]]
189name = "fd-lock"
190version = "3.0.2"
191source = "registry+https://github.com/rust-lang/crates.io-index"
192checksum = "a16910e685088843d53132b04e0f10a571fdb193224fc589685b3ba1ce4cb03d"
193dependencies = [
194 "cfg-if 1.0.0",
195 "libc",
196 "windows-sys",
197]
198
199[[package]]
165name = "getrandom" 200name = "getrandom"
166version = "0.1.14" 201version = "0.1.14"
167source = "registry+https://github.com/rust-lang/crates.io-index" 202source = "registry+https://github.com/rust-lang/crates.io-index"
168checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" 203checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
169dependencies = [ 204dependencies = [
170 "cfg-if", 205 "cfg-if 0.1.10",
171 "libc", 206 "libc",
172 "wasi", 207 "wasi",
173] 208]
@@ -189,9 +224,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
189 224
190[[package]] 225[[package]]
191name = "libc" 226name = "libc"
192version = "0.2.68" 227version = "0.2.112"
193source = "registry+https://github.com/rust-lang/crates.io-index" 228source = "registry+https://github.com/rust-lang/crates.io-index"
194checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" 229checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
195 230
196[[package]] 231[[package]]
197name = "log" 232name = "log"
@@ -199,7 +234,7 @@ version = "0.4.8"
199source = "registry+https://github.com/rust-lang/crates.io-index" 234source = "registry+https://github.com/rust-lang/crates.io-index"
200checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 235checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
201dependencies = [ 236dependencies = [
202 "cfg-if", 237 "cfg-if 0.1.10",
203] 238]
204 239
205[[package]] 240[[package]]
@@ -209,16 +244,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
209checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" 244checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
210 245
211[[package]] 246[[package]]
247name = "memoffset"
248version = "0.6.5"
249source = "registry+https://github.com/rust-lang/crates.io-index"
250checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
251dependencies = [
252 "autocfg",
253]
254
255[[package]]
256name = "nibble_vec"
257version = "0.1.0"
258source = "registry+https://github.com/rust-lang/crates.io-index"
259checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
260dependencies = [
261 "smallvec",
262]
263
264[[package]]
212name = "nix" 265name = "nix"
213version = "0.13.1" 266version = "0.23.1"
214source = "registry+https://github.com/rust-lang/crates.io-index" 267source = "registry+https://github.com/rust-lang/crates.io-index"
215checksum = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b" 268checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
216dependencies = [ 269dependencies = [
217 "bitflags", 270 "bitflags",
218 "cc", 271 "cc",
219 "cfg-if", 272 "cfg-if 1.0.0",
220 "libc", 273 "libc",
221 "void", 274 "memoffset",
222] 275]
223 276
224[[package]] 277[[package]]
@@ -305,6 +358,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
305checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426" 358checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426"
306 359
307[[package]] 360[[package]]
361name = "radix_trie"
362version = "0.2.1"
363source = "registry+https://github.com/rust-lang/crates.io-index"
364checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
365dependencies = [
366 "endian-type",
367 "nibble_vec",
368]
369
370[[package]]
308name = "redox_syscall" 371name = "redox_syscall"
309version = "0.1.56" 372version = "0.1.56"
310source = "registry+https://github.com/rust-lang/crates.io-index" 373source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -353,15 +416,21 @@ dependencies = [
353 416
354[[package]] 417[[package]]
355name = "rustyline" 418name = "rustyline"
356version = "4.1.0" 419version = "9.1.1"
357source = "registry+https://github.com/rust-lang/crates.io-index" 420source = "registry+https://github.com/rust-lang/crates.io-index"
358checksum = "0f47ea1ceb347d2deae482d655dc8eef4bd82363d3329baffa3818bd76fea48b" 421checksum = "6c38cfbd0a4d7df7aab7cf53732d5d43449d0300358fd15cd4e8c8468a956aca"
359dependencies = [ 422dependencies = [
360 "dirs", 423 "bitflags",
424 "cfg-if 1.0.0",
425 "clipboard-win",
426 "fd-lock",
361 "libc", 427 "libc",
362 "log", 428 "log",
363 "memchr", 429 "memchr",
364 "nix", 430 "nix",
431 "radix_trie",
432 "scopeguard",
433 "smallvec",
365 "unicode-segmentation", 434 "unicode-segmentation",
366 "unicode-width", 435 "unicode-width",
367 "utf8parse", 436 "utf8parse",
@@ -369,6 +438,24 @@ dependencies = [
369] 438]
370 439
371[[package]] 440[[package]]
441name = "scopeguard"
442version = "1.1.0"
443source = "registry+https://github.com/rust-lang/crates.io-index"
444checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
445
446[[package]]
447name = "smallvec"
448version = "1.7.0"
449source = "registry+https://github.com/rust-lang/crates.io-index"
450checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
451
452[[package]]
453name = "str-buf"
454version = "1.0.5"
455source = "registry+https://github.com/rust-lang/crates.io-index"
456checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
457
458[[package]]
372name = "strsim" 459name = "strsim"
373version = "0.8.0" 460version = "0.8.0"
374source = "registry+https://github.com/rust-lang/crates.io-index" 461source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -416,9 +503,9 @@ checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
416 503
417[[package]] 504[[package]]
418name = "utf8parse" 505name = "utf8parse"
419version = "0.1.1" 506version = "0.2.0"
420source = "registry+https://github.com/rust-lang/crates.io-index" 507source = "registry+https://github.com/rust-lang/crates.io-index"
421checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" 508checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
422 509
423[[package]] 510[[package]]
424name = "vec_map" 511name = "vec_map"
@@ -427,12 +514,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
427checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 514checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
428 515
429[[package]] 516[[package]]
430name = "void"
431version = "1.0.2"
432source = "registry+https://github.com/rust-lang/crates.io-index"
433checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
434
435[[package]]
436name = "wasi" 517name = "wasi"
437version = "0.9.0+wasi-snapshot-preview1" 518version = "0.9.0+wasi-snapshot-preview1"
438source = "registry+https://github.com/rust-lang/crates.io-index" 519source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -459,3 +540,46 @@ name = "winapi-x86_64-pc-windows-gnu"
459version = "0.4.0" 540version = "0.4.0"
460source = "registry+https://github.com/rust-lang/crates.io-index" 541source = "registry+https://github.com/rust-lang/crates.io-index"
461checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 542checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
543
544[[package]]
545name = "windows-sys"
546version = "0.28.0"
547source = "registry+https://github.com/rust-lang/crates.io-index"
548checksum = "82ca39602d5cbfa692c4b67e3bcbb2751477355141c1ed434c94da4186836ff6"
549dependencies = [
550 "windows_aarch64_msvc",
551 "windows_i686_gnu",
552 "windows_i686_msvc",
553 "windows_x86_64_gnu",
554 "windows_x86_64_msvc",
555]
556
557[[package]]
558name = "windows_aarch64_msvc"
559version = "0.28.0"
560source = "registry+https://github.com/rust-lang/crates.io-index"
561checksum = "52695a41e536859d5308cc613b4a022261a274390b25bd29dfff4bf08505f3c2"
562
563[[package]]
564name = "windows_i686_gnu"
565version = "0.28.0"
566source = "registry+https://github.com/rust-lang/crates.io-index"
567checksum = "f54725ac23affef038fecb177de6c9bf065787c2f432f79e3c373da92f3e1d8a"
568
569[[package]]
570name = "windows_i686_msvc"
571version = "0.28.0"
572source = "registry+https://github.com/rust-lang/crates.io-index"
573checksum = "51d5158a43cc43623c0729d1ad6647e62fa384a3d135fd15108d37c683461f64"
574
575[[package]]
576name = "windows_x86_64_gnu"
577version = "0.28.0"
578source = "registry+https://github.com/rust-lang/crates.io-index"
579checksum = "bc31f409f565611535130cfe7ee8e6655d3fa99c1c61013981e491921b5ce954"
580
581[[package]]
582name = "windows_x86_64_msvc"
583version = "0.28.0"
584source = "registry+https://github.com/rust-lang/crates.io-index"
585checksum = "3f2b8c7cbd3bfdddd9ab98769f9746a7fad1bca236554cd032b78d768bc0e89f"
diff --git a/Cargo.toml b/Cargo.toml
index 4527862..4be652d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@ categories = ["command-line-interface", "science", "parser-implementations"]
12license = "MIT" 12license = "MIT"
13 13
14[dependencies] 14[dependencies]
15rustyline = "4.1.0" 15rustyline = { version = "9.1.1", default-features = false }
16clap = "2.32.0" 16clap = "2.32.0"
17radix_fmt = "1.0.0" 17radix_fmt = "1.0.0"
18lazy_static = "1.3.0" 18lazy_static = "1.3.0"
diff --git a/src/lex.rs b/src/lex.rs
index 76f61a0..1220a1f 100644
--- a/src/lex.rs
+++ b/src/lex.rs
@@ -101,6 +101,9 @@ lazy_static! {
101 m.insert("acsc", Function::token_from_fn("acsc".into(), |x| (1./x).asin())); 101 m.insert("acsc", Function::token_from_fn("acsc".into(), |x| (1./x).asin()));
102 m.insert("asec", Function::token_from_fn("asec".into(), |x| (1./x).acos())); 102 m.insert("asec", Function::token_from_fn("asec".into(), |x| (1./x).acos()));
103 m.insert("acot", Function::token_from_fn("acot".into(), |x| (1./x).atan())); 103 m.insert("acot", Function::token_from_fn("acot".into(), |x| (1./x).atan()));
104 m.insert("exp", Function::token_from_fn("exp".into(), |x| x.exp()));
105 m.insert("exp2", Function::token_from_fn("exp2".into(), |x| x.exp2()));
106 m.insert("round", Function::token_from_fn("round".into(), |x| x.round()));
104 // single arg function s can be added here 107 // single arg function s can be added here
105 m 108 m
106 }; 109 };
@@ -134,19 +137,29 @@ pub fn lexer(input: &str, prev_ans: Option<f64>) -> Result<Vec<Token>, CalcError
134 '0'..='9' | '.' => { 137 '0'..='9' | '.' => {
135 if !char_vec.is_empty() { 138 if !char_vec.is_empty() {
136 if FUNCTIONS.get(&char_vec[..]).is_some() { 139 if FUNCTIONS.get(&char_vec[..]).is_some() {
137 return Err(CalcError::Syntax(format!( 140 char_vec.push(letter);
138 "Function '{}' expected parentheses", 141 if !FUNCTIONS.get(&char_vec[..]).is_some() {
139 char_vec 142 return Err(CalcError::Syntax(format!(
140 ))); 143 "Function '{}' expected parentheses",
144 &char_vec[..char_vec.chars().count()-1]
145 )));
146 }
147 } else if CONSTANTS.get(&char_vec[..]).is_some() {
148 result.push(CONSTANTS.get(&char_vec[..]).unwrap().clone());
149 result.push(OPERATORS.get(&'*').unwrap().clone());
150 char_vec.clear();
151 num_vec.push(letter);
152 last_char_is_op = false;
141 } else { 153 } else {
142 return Err(CalcError::Syntax(format!( 154 return Err(CalcError::Syntax(format!(
143 "Unexpected character '{}'", 155 "Unexpected character '{}'",
144 char_vec 156 char_vec
145 ))); 157 )));
146 } 158 }
159 } else {
160 num_vec.push(letter);
161 last_char_is_op = false;
147 } 162 }
148 num_vec.push(letter);
149 last_char_is_op = false;
150 } 163 }
151 '_' => { 164 '_' => {
152 if prev_ans.is_none() { 165 if prev_ans.is_none() {
diff --git a/src/main.rs b/src/main.rs
index 75c33bb..e6a865e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -259,4 +259,35 @@ mod tests {
259 let evaled = eval_math_expression("9 + _ ", Some(0f64)).unwrap(); 259 let evaled = eval_math_expression("9 + _ ", Some(0f64)).unwrap();
260 assert_eq!(9., evaled); 260 assert_eq!(9., evaled);
261 } 261 }
262 #[test]
263 fn eval_const_multiplication() {
264 let evaled = eval_math_expression("e2", None).unwrap();
265 assert_eq!(5.4365636569, evaled);
266 }
267 #[test]
268 fn eval_round() {
269 let evaled = eval_math_expression("round(0.5)+round(2.4)", None).unwrap();
270 assert_eq!(3., evaled);
271 }
272 #[test]
273 fn eval_exp2() {
274 assert_eq!(
275 256.,
276 eval_math_expression("exp2(8)", None).unwrap()
277 );
278 }
279 #[test]
280 fn eval_exp() {
281 assert_eq!(
282 20.0855369232 as f64,
283 eval_math_expression("exp(3)", None).unwrap()
284 );
285 }
286 #[test]
287 fn eval_e_times_n() {
288 assert_eq!(
289 0. as f64,
290 eval_math_expression("e0", None).unwrap()
291 );
292 }
262} 293}
diff --git a/src/readline.rs b/src/readline.rs
index d689f95..8906a4f 100644
--- a/src/readline.rs
+++ b/src/readline.rs
@@ -7,6 +7,7 @@ use rustyline::error::ReadlineError;
7use rustyline::highlight::Highlighter; 7use rustyline::highlight::Highlighter;
8use rustyline::hint::{Hinter, HistoryHinter}; 8use rustyline::hint::{Hinter, HistoryHinter};
9use rustyline::{Context, Editor, Helper}; 9use rustyline::{Context, Editor, Helper};
10use rustyline::validate::Validator;
10 11
11use directories::ProjectDirs; 12use directories::ProjectDirs;
12 13
@@ -14,6 +15,7 @@ use regex::Regex;
14 15
15use crate::error::CalcError; 16use crate::error::CalcError;
16use crate::eval_math_expression; 17use crate::eval_math_expression;
18use crate::lex::{CONSTANTS, FUNCTIONS};
17 19
18pub struct RLHelper { 20pub struct RLHelper {
19 completer: FilenameCompleter, 21 completer: FilenameCompleter,
@@ -51,20 +53,34 @@ impl Highlighter for LineHighlighter {
51 let op = eval_math_expression(line, prev_ans); 53 let op = eval_math_expression(line, prev_ans);
52 match op { 54 match op {
53 Ok(_) => { 55 Ok(_) => {
54 let constants = ["e", "pi"]; 56 let constants = CONSTANTS.keys();
55 let functions = [ 57 let functions = FUNCTIONS.keys();
56 "sin", "cos", "tan", "csc", "sec", "cot", "sinh", "cosh", "tanh", "ln", "log",
57 "sqrt", "ceil", "floor", "rad", "deg", "abs", "asin", "acos", "atan", "acsc",
58 "asec", "acot",
59 ];
60 let ops = Regex::new(r"(?P<o>[\+-/\*%\^!])").unwrap(); 58 let ops = Regex::new(r"(?P<o>[\+-/\*%\^!])").unwrap();
61 let mut coloured: String = ops.replace_all(line, "\x1b[35m$o\x1b[0m").into(); 59 let mut coloured: String = ops.replace_all(line, "\x1b[35m$o\x1b[0m").into();
62 60
63 for c in &constants { 61 for c in constants {
64 coloured = coloured.replace(c, &format!("\x1b[33m{}\x1b[0m", c)); 62 // This regex consists of the following pieces:
63 // * the constant (`o`) to highlight (to be substituted as `{}` via `format!`),
64 // e.g. `e` or `pi`.
65 // * (optionally) an ANSI escape-code (`\x1b\[35m`) that is used to highlight
66 // a binary operator (e.g. `+`/`-`/...). With this one it is ensured that
67 // binary operators are always correctly detected after a constant
68 // (see the next bullet-point for why that's needed).
69 // * the following operator (e.g. `+`/`-`/...), a space or the end
70 // of the expression (to highlight e.g. `1+e` correctly). This is
71 // required to distinguish a constant in an expression from a function-call,
72 // e.g. `e+1` from `exp(1)`, without this matching logic, the `e` from
73 // `exp` would be improperly interpreted as constant.
74 //
75 // To make sure none of existing highlighting (i.e. highlighting
76 // of binary operators that happens before) breaks, the escape-codes & operator
77 // (called `r`) are appended after the highlighted constant.
78 let re = Regex::new(format!("(?P<o>{})(?P<r>(\x1b\\[35m)?([\\+-/\\*%\\^! ]|$))", c).as_str()).unwrap();
79 coloured = re.replace_all(&coloured, "\x1b[33m$o\x1b[0m$r").into();
65 } 80 }
66 for f in &functions { 81 for f in functions {
67 coloured = coloured.replace(f, &format!("\x1b[34m{}\x1b[0m", f)); 82 let re = Regex::new(format!("(?P<o>{})(?P<r>(\\(|$))", f).as_str()).unwrap();
83 coloured = re.replace_all(&coloured, "\x1b[34m$o\x1b[0m$r").into();
68 } 84 }
69 Owned(coloured) 85 Owned(coloured)
70 } 86 }
@@ -75,6 +91,7 @@ impl Highlighter for LineHighlighter {
75} 91}
76 92
77impl Highlighter for RLHelper { 93impl Highlighter for RLHelper {
94 fn highlight_char(&self, _: &str, _: usize) -> bool { true }
78 fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> { 95 fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
79 self.highlighter.highlight_hint(hint) 96 self.highlighter.highlight_hint(hint)
80 } 97 }
@@ -96,11 +113,14 @@ impl Completer for RLHelper {
96} 113}
97 114
98impl Hinter for RLHelper { 115impl Hinter for RLHelper {
99 fn hint(&self, line: &str, a: usize, b: &Context) -> Option<String> { 116 type Hint = String;
117 fn hint(&self, line: &str, a: usize, b: &Context) -> Option<Self::Hint> {
100 self.hinter.hint(line, a, b) 118 self.hinter.hint(line, a, b)
101 } 119 }
102} 120}
103 121
122impl Validator for RLHelper {}
123
104impl Helper for RLHelper {} 124impl Helper for RLHelper {}
105 125
106pub fn create_readline() -> Editor<RLHelper> { 126pub fn create_readline() -> Editor<RLHelper> {