aide/
lib.rs

1#![allow(unused_must_use)]
2
3use regex::Regex;
4use std::error::Error;
5use std::io::prelude::*;
6use std::path::Path;
7use std::borrow::Cow;
8use std::fs::File;
9use std::fs;
10
11pub mod features;
12
13const SPLIT_STR: &str = r#"//======="#;
14const FEATURE_STR: &str = r#"#[cfg(feature = "#;
15
16const END: &str = "\"#;";
17const FN_MAIN: &str = "adjoin";
18
19
20pub fn convert_all_rss() {
21    let path_str :&str = &format!("./examples");
22    let paths = fs::read_dir(path_str).unwrap();
23    for path in paths {
24        let p_name = path.unwrap().path();
25        //println!("path = {:?}", p_name.to_str());
26        match p_name.to_str() {
27            Some(folder_name) => {
28                if !folder_name.contains(".rs") {
29                    //println!("folder_name = {:?}", folder_name);
30                    let names: Vec<&str> = folder_name.split("/").collect();
31                    println!("folder_name = {:?}", names[2]);
32                    convert_rss(names[2]);
33                }
34            },
35            None => {}
36        }
37    }
38}
39
40
41pub fn convert_rss(folder_name: &str) {
42    let path_str :&str = &format!("./examples/{}", folder_name);
43    let paths = fs::read_dir(path_str).unwrap();
44
45    for path in paths {
46        //println!("path = {}", path.unwrap().path().display());
47        //let file_name :&str = path.unwrap().path().into_os_string();
48        let p = path.unwrap().path();
49        let f_name = p.file_name();
50        match f_name {
51            Some(file_name) => {
52                if file_name != "main.rs" {
53                    let str = file_name.to_string_lossy();
54                    let str :&str = &format!("{}", str);
55                    let names: Vec<&str> = str.split(".").collect();
56                    println!("file_name = {:?}", names[0]);
57                    convert_rs(folder_name, names[0]);
58                }                
59            },
60            None => {}
61        }
62    }
63}
64
65
66
67pub fn convert_rs(folder_name: &str, file_name: &str) {
68    let path_file :&str = &format!("./examples/{}/{}.rs", folder_name, file_name);
69    let source = read_rs(path_file, false);
70
71    //let destination = get_main(source, feature_name);
72    let mut split: Vec<&str> = source.split(SPLIT_STR).collect();
73    
74    let mut codes_str = String::new();
75    let split_len = split.len() - 1;
76    if split_len < 4 {
77        return;
78    }
79    let split1 = split[1];
80    for (index, item) in split.iter_mut().enumerate() {        
81        if index > 1 && index < split_len {
82            let mut f = String::new();
83            let feature_name = &mut f;
84            let destination = format!("{}\n{}", split1, item);
85            let mut tmp = create_rs(destination, feature_name);
86            
87            //println!("feature_name = {:?}", feature_name);
88            let begin_str = get_begin(file_name, feature_name);
89            tmp = format!("{}{}{}", begin_str, tmp, END);
90            codes_str = format!("{}\n\n{}", codes_str, tmp);
91
92            let path_file :&str = &format!("./src/features/rs_files.rs");
93            insert_mod_name(path_file, folder_name, file_name);
94            insert_code_name(path_file, folder_name, file_name, feature_name);
95        }
96    }
97
98    let path_file :&str = &format!("./src/features/rs_files/{}_{}.rs", folder_name, file_name);
99    write_rs(path_file, codes_str);
100    //show_rs(file_name);
101
102    let path_file :&str = &format!("./src/bin/borrow.yml");
103    insert_example_name(path_file, folder_name, file_name);
104}
105
106
107
108fn get_begin<'de>(file_name: &'de str, feature_name: &'de str) -> Cow<'de, str>{
109    const BEGIN: &str = r#"pub const ------- :&str = r#""#;
110    let re_feature = Regex::new(r"-------").unwrap();
111    let replace_str = format!(
112        "{}_{}",
113        file_name.to_uppercase(),
114        feature_name.to_uppercase()
115    );
116    let begin_str = re_feature.replace(
117        BEGIN, replace_str.as_str()
118    );
119    begin_str
120}
121
122
123fn create_rs(destination :String, feature_name :&mut String) -> String {
124    let re_main = Regex::new(r"adjoin").unwrap();
125    let re_comment = Regex::new(r"^\s*//").unwrap();
126
127    let lines = destination.lines();
128    let mut codes_str = String::new();
129    let mut result;
130    for line in lines {
131        if line.contains(FN_MAIN) {
132            result = re_main.replace(line, "main");
133            codes_str = format!("{}{}\n", codes_str, result.as_ref());
134        } else if line.contains(FEATURE_STR) {
135            if line[0..10] == FEATURE_STR[0..10] {
136                let tmp: Vec<&str> = line.split("\"").collect();
137                //println!("tmp = {:?}", tmp);
138                feature_name.push_str(tmp[1]);
139            }
140        } else {
141            if !line.is_empty() {
142                result = re_comment.replace(line, "");
143                if line == result {                
144                    codes_str = format!("{}{}\n", codes_str, result.as_ref());
145                }
146            }
147        }
148        //dbg!(&result);
149    }
150
151    codes_str
152}
153
154fn insert_example_name(path_file :&str, folder_name :&str, file_name :&str) {
155    let mut source = read_rs(path_file, false);
156    let code_name = format!( "- {}_{}", folder_name, file_name );
157    
158    if !source.contains(&code_name) {
159    //if !source.contains(&code_name) {
160        const RE_STR: &str = r#"\#\#example_name"#;
161        const MUSTER_STR: &str = r#"##example_name"#;
162        // - closure_move_vec
163        let path_code_name :&str = &format!(
164            r#"{}
165            {}"#,
166            MUSTER_STR,
167            code_name            
168        );
169        println!("path_code_name = {}", path_code_name);
170        let re_code = Regex::new(RE_STR).unwrap();
171        let result = re_code.replace_all(&source, path_code_name);
172        source = format!("{}", result);
173
174        write_rs(path_file, source);
175    } else {
176        println!("NOTHING insert_example_name !!!");
177    }
178}
179
180fn insert_code_name(path_file :&str, folder_name :&str, file_name :&str, feature_name :&str) {
181    let mut source = read_rs(path_file, false);
182    let code_name = format!(
183        "{}_{}_{}",
184        folder_name,
185        file_name,
186        feature_name
187    );
188
189    if !source.contains(&code_name) {
190        // "vec_for_err" => vec_for::VEC_FOR_ERR,
191        let comment_str: &str = &format!(r#"//{}"#, feature_name);
192        let re_str: &str = &format!("//{}\n", feature_name);
193        let path_code_name :&str = &format!(
194            r#""{}" => {}_{}::{}_{},
195        {}
196        "#,
197            code_name,
198            folder_name,
199            file_name,
200            file_name.to_uppercase(),
201            feature_name.to_uppercase(),
202            comment_str,
203        );
204        println!("path_code_name = {}", path_code_name);
205        let re_code = Regex::new(re_str).unwrap();
206        let result = re_code.replace_all(&source, path_code_name);
207        source = format!("{}", result);
208
209        write_rs(path_file, source);
210    } else {
211        //println!("NOTHING insert_code_name !!!");
212    }
213}
214
215
216
217fn insert_mod_name(path_file :&str, folder_name :&str, file_name :&str) {
218    let mut source = read_rs(path_file, false);
219    let code_name = format!(
220        "mod {}_{};",
221        folder_name,
222        file_name
223    );
224
225    if !source.contains(&code_name) {
226        // mod closure_move_vec
227        let comment_str: &str = &format!(r#"//mod"#);
228        let re_str: &str = &format!("//mod\n");
229        let path_code_name :&str = &format!(
230            r#"{}
231{}
232        "#,
233            code_name,
234            comment_str,
235        );
236        println!("path_code_name = {}", path_code_name);
237        let re_code = Regex::new(re_str).unwrap();
238        let result = re_code.replace_all(&source, path_code_name);
239        source = format!("{}", result);
240
241        write_rs(path_file, source);
242    } else {
243        //println!("NOTHING insert_mod_name !!!");
244    }
245}
246
247
248
249// https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html
250// https://doc.rust-lang.org/rust-by-example/std_misc/file/create.html
251fn read_rs(file: &str, visible: bool) -> String {
252    let path = Path::new(file);
253    let display = path.display();
254
255    // Open the path in read-only mode, returns `io::Result<File>`
256    let mut file = match File::open(&path) {
257        // The `description` method of `io::Error` returns a string that
258        // describes the error
259        Err(why) => panic!("couldn't open {}: {}", display, why.description()),
260        Ok(file) => file,
261    };
262
263    // Read the file contents into a string, returns `io::Result<usize>`
264    let mut s = String::new();
265    match file.read_to_string(&mut s) {
266        Err(why) => panic!("couldn't read {}: {}", display, why.description()),
267        Ok(_) => {
268            if visible {
269                print!("\n\n\n{} contains:\n{}\n\n\n", display, s);
270            } else {
271                print!("successfully read to\n{}\n\n", display);
272            }
273        }
274    }
275    s
276}
277
278fn write_rs(file: &str, stream: String) {
279    // Create a path to the desired file    
280    let new_path = Path::new(file);
281    let new_display = new_path.display();
282
283    // Open a file in write-only mode, returns `io::Result<File>`
284    let mut new_file = match File::create(&new_path) {
285        Err(why) => panic!("couldn't create {}: {}", new_display, why.description()),
286        Ok(new_file) => new_file,
287    };
288
289    // Write the `LOREM_IPSUM` string to `file`, returns `io::Result<()>`
290    match new_file.write_all(stream.as_bytes()) {
291        Err(why) => panic!("couldn't write to {}: {}", new_display, why.description()),
292        Ok(_) => println!("successfully wrote to\n{}\n\n", new_display),
293    }
294}
295
296/*
297fn show_rs(file_name: &str) {
298    let file = format!("./src/features/rs_files/{}.rs", file_name);
299    let new_path = Path::new(&file);
300    let new_display = new_path.display();
301
302    // Open the path in read-only mode, returns `io::Result<File>`
303    let mut new_file = match File::open(&new_path) {
304        // The `description` method of `io::Error` returns a string that
305        // describes the error
306        Err(why) => panic!("couldn't open {}: {}", new_display,
307                                                   why.description()),
308        Ok(new_file) => new_file,
309    };
310
311    let mut s = String::new();
312    match new_file.read_to_string(&mut s) {
313        Err(why) => panic!("couldn't read {}: {}", new_display,
314                                                   why.description()),
315        Ok(_) => print!("{} contains:\n{}\n\n\n", new_display, s),
316    }
317}
318*/
319
320pub fn allx_cmds(file_name: &str) {
321    let ret = format!(
322        r#"
323# Show this command
324cargo run --bin bw -- --code {0} | bat -l cmd
325cargo install borrowing_exerci
326bw --code {0}
327bw --code {0} | bat -l cmd
328
329# Show the Help for Rust File
330cargo run --bin bw -- --code <CODE>
331cargo install borrowing_exerci
332bw --code <CODE> | bat -l cmd
333
334# Run OK:
335cargo run --bin bw -- --code <CODE> --feature ok
336cargo run --example <CODE> --features ok
337cargo install borrowing_exerci
338bw --code <CODE> --feature ok
339
340# Compile-Time Error:
341cargo run --bin bw -- -c <CODE> -f err | bat -l rs
342cargo run --example <CODE> --features err
343cargo install borrowing_exerci
344bw --code <CODE> -f err | bat -l rs
345"#,
346        file_name
347    );
348    println!("{}", ret);
349}
350
351pub fn devx_cmds(file_name: &str) {
352    let ret = format!(
353        r#"
354# Show this Help for Developer
355cargo run --bin bw -- --file {0} | bat -l cmd
356../target/debug/bw --file {0} | bat -l cmd
357cargo install borrowing_exerci
358bw --file {0}
359bw --file {0} | bat -l cmd
360
361# Use the tool cargo-expand
362cargo expand --example {0} --features ok | bat -l cmd
363cargo expand --example {0} --features err | bat -l cmd
364RUSTFLAGS="--emit mir" cargo build --release --example {0} --features ok
365RUSTFLAGS="--emit mir" cargo build --release --example {0} --features err
366ls -al ../target/release/examples/{0}-*.mir
367open -t ../target/release/examples/{0}-*.mir
368
369# Show the Help for User
370cargo run --bin bw -- --file {0}
371../target/debug/bw --file {0}
372cargo install borrowing_exerci
373bw --file {0} | bat -l cmd
374
375# Run OK:
376cargo run --example {0} --features ok | bat -l cmd
377cargo run --bin bw -- --file {0} --mode ok | bat -l cmd
378../target/debug/bw --file {0} --mode ok | bat -l cmd
379cargo install borrowing_exerci
380bw --file {0} --mode ok
381
382# Compile-Time Error:
383cargo run --example {0} --features err | bat -l cmd
384cargo run --bin bw -- -f {0} -m err | bat -l rs
385../target/debug/bw --file {0} --mode err | bat -l cmd
386cargo install borrowing_exerci
387bw --file {0} -m err | bat -l rs
388"#,
389        file_name
390    );
391    println!("{}", ret);
392}
393
394pub fn user_cmds(file_name: &str) {
395    let ret = format!(
396        r#"
397// Show this command
398cargo install borrowing_exerci
399bw --code {0} | bat -l cmd
400
401// Run OK:
402cargo install borrowing_exerci
403bw --code <CODE> --feature ok | bat -l rs
404
405// Compile-Time Error:
406cargo install borrowing_exerci
407bw --code <CODE> -f err | bat -l rs
408"#,
409        file_name
410    );
411    println!("{}", ret);
412}
413
414pub fn hello() {
415    println!("{}", "Start... Hello Borrowing!");
416    println!("\n{}", "use this help for crate `borrowing_exerci`:");
417    println!("\t{}", "bw -h");
418    println!("\t{}", "bw --help");
419    println!("\n\n{}", "list all faetures for a code:");
420    println!("\t{}", "bw -- -c <code>");
421    println!("example:");
422    println!("\t{}", "bw --code closure_move_vec");
423    println!("\n\n{}", "run code for the `code` and the `feature`:");
424    println!("\t{}", "bw --code <code> --feature <feature>");
425    println!("example:");
426    println!("\t{}", "bw --code closure_move_vec --feature ok | bat -l rs ");
427    println!("\t{}", "tip: f");
428    println!("\t{}", "tip: q");
429}
430
431
432//## 题外话
433//- https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=50eaf399f641e0965e86be08a6d2d777
434
435// https://stackoverflow.com/questions/26946646/rust-package-with-both-a-library-and-a-binary
436
437// Cow, as_ref()
438// https://stackoverflow.com/questions/47147844/how-do-i-get-a-str-or-string-from-stdborrowcowstr
439// https://jwilm.io/blog/from-str-to-cow/
440
441// fn contains
442// https://stackoverflow.com/questions/48794974/how-to-check-if-a-string-contains-a-substring-in-rust
443
444// fn is_empty
445// https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.is_empty
446
447// regex
448// https://stackoverflow.com/questions/19274493/regular-expression-match-lines-starting-with-a-certain-character-or-whitespace-a
449// https://stackoverflow.com/questions/1240504/regular-expression-to-match-string-starting-with-stop
450
451// fn split
452// https://stackoverflow.com/questions/26643688/how-do-i-split-a-string-in-rust
453
454// fn to_uppercase
455// https://doc.rust-lang.org/std/char/struct.ToUppercase.html
456
457// file read write
458// https://doc.rust-lang.org/rust-by-example/std_misc/file/open.html
459// https://doc.rust-lang.org/rust-by-example/std_misc/file/create.html