#clipboard #mouse #keyboard #keyboard-input #state-management #mouse-position #macro

bin+lib doe

doe is a powerful Rust crate designed to enhance development workflow by providing an extensive collection of useful macros and utility functions. It not only simplifies common tasks but also offers convenient features for clipboard management,state management,keyboard input, and mouse interaction.

158 releases (21 stable)

new 1.1.20 Apr 17, 2024
1.1.10 Mar 11, 2024
0.3.49 Jan 6, 2024
0.3.39 Dec 31, 2023
0.1.32 Nov 5, 2022

#20 in Development tools

Download history 55/week @ 2023-12-22 80/week @ 2023-12-29 92/week @ 2024-01-05 45/week @ 2024-01-12 20/week @ 2024-01-19 27/week @ 2024-01-26 17/week @ 2024-02-02 51/week @ 2024-02-09 333/week @ 2024-02-16 236/week @ 2024-02-23 86/week @ 2024-03-01 311/week @ 2024-03-08 99/week @ 2024-03-15 66/week @ 2024-03-22 227/week @ 2024-03-29 847/week @ 2024-04-05

1,263 downloads per month
Used in 31 crates (30 directly)

MIT and maybe GPL-3.0-or-later

350KB
6K SLoC

doe

Crates.io Rust license

doe is a powerful Rust crate designed to enhance development workflow by providing an extensive collection of useful macros and utility functions.

Features

ctf

cargo add doe -F ctf

allow you to perform various operations with ease, such as string manipulation, urlencode urldecode,hex encode decode,base43 encode decode, and error management.

clip

cargo add doe -F clip

simplifies clipboard management, enabling you to effortlessly interact with the system clipboard.

mouse

cargo add doe -F mouse

offers intuitive and easy-to-use functions for simulating mouse actions.

keyboard

cargo add doe -F keyboard

offers simulating keyboard input action with easy-to-use functions.

kcm

kcm is short feature for keyboard clipboard mouse together

cargo add doe -F kcm

xlsx

read edit write xlsx file

cargo add doe -F xlsx

docx

read edit docx file

cargo add doe -F docx

date

get and read edit date string

cargo add doe -F date

screenshot

screenshot and get hex from screenshot image

cargo add doe -F screenshot

images

resize add paddings,convert image format

cargo add doe -F images

Examples

keyboard example

// cargo add doe -F kcm
use doe::keyboard::key_click;
use doe::keyboard::key_press;
use doe::keyboard::key_release;
use doe::keyboard::KeyCode;
use doe::mouse::mouse_drag;
use doe::mouse::move_to_paste;
use doe::mouse::move_to_press_left;
use doe::*;
use keyboard::exit_if_click_esc;
let list = vec!["iphone","ipad","macbook"];

// crete new baogao
move_to_press_left(857, 588).sleep(1.0); //#000000

// create fengmian
move_to_paste(1540, 853, "Apple").sleep(1.0); //#000000
move_to_paste(1360, 882, "ID").sleep(1.0); //#000000

// add shuoming
move_to_paste(772, 464, "Discription").sleep(1.0); //#ffffff
mouse_drag((894, 719).into(), (821, 716).into()).sleep(1.0); //#f0f0f0
key_click("2024-01-23").sleep(1.0);
move_to_press_left(740, 305).sleep(1.0); //#f0f0f0

for name in list {
    // add baobao
    move_to_press_left(476, 253).sleep(1.0); //#ffffff

    // name
    move_to_press_left(796, 331).sleep(1.0); //#ffffff
    key_click("end");
    key_click("shift+home");
    set_clipboard(name).unwrap().sleep(0.5);
    key_click("ctrl+v");

    // add fujian
    move_to_press_left(870, 587).sleep(1.0); //#000000
    mouse_drag((893, 818).into(), (814, 816).into()).sleep(1.0); //#f0f0f0
    key_click("2024-01-23").sleep(1.0);
    move_to_press_left(723, 206).sleep(1.0); //#000000
}

// set taoshu
move_to_paste(1341, 910, "New_name").sleep(1.0); //#000000

docx_replace

//finds all 'name' and replace with 'andrew'
use doe::*;
docx::docx_replace("./name.docx","name","andrew").unwrap();
docx::docx_get_content("./name.docx").unwrap().dprintln();
docx::docx_remove_read_only("./name.docx").unwrap();

Spawn trait

use doe::*;
use doe::keyboard::exit_if_click_esc;
let t1 = run.spawn();
let t2 = exit_if_click_esc.spawn();
t1.join();
t2.join();

listen keybord and mouse

fn main() {
    use doe::keyboard::listen_keybord;
    use doe::mouse::listen_mouse_position;
    use doe::mouse::listen_mouse_scroll;
    use doe::mouse::listen_mouse_click;
    let t1 = std::thread::spawn(||{
        listen_keybord();
    });
    let t2 = std::thread::spawn(||{
        listen_mouse_position();
    });
    let t3 = std::thread::spawn(||{
        listen_mouse_scroll();
    });
    let t4 = std::thread::spawn(||{
        listen_mouse_click();
    });
    t1.join().unwrap();
    t2.join().unwrap();
    t3.join().unwrap();
    t4.join().unwrap();
}

automater

generate script

fn main(){
    use doe::mouse::listen_all;
    listen_all();
}

run to generate script

cargo r > script.m

script.m

 move_to(1562,6);
 press("left");
 move_to(1453,20);
 press("left");
 move_to(342,515);
 scoll_down();
 move_to(496,560);
 press("left");
 move_to(304,454);
 key_press(8);
 key_release(8);
 press("left");
 key_press(162);
 key_press(67);

run script

 use doe::mouse::automater;
 let script =  include_str!("../script.m");
 automater(script);

mouse automater

fn main() {
    use doe::mouse;
    let script = r#"
        move_to::217::135
        sleep::1
        move_to_press_left::189::137
        sleep::1
        move_to_press_left::198::185
        sleep::1
        move_drag::655::343::678::330
        sleep::1
        // script comment
        move_to_paste::479::715::page demo is ok
    "#
    .trim();
    mouse::mouse_automater(script);
}

mouse press left drag

fn main(){
   use doe::mouse::mouse_drag;
   mouse_press_left_drag((543,446).into(), (590,460).into());
   mouse_drag((543,446).into(), (590,460).into(),"left");
}
fn main()->doe::DynError{
    use doe::clipboard::get_clipboard;
    use doe::clipboard::set_clipboard;
    set_clipboard("rust").unwrap();
    let clip = get_clipboard().unwrap();
    assert_eq!("rust",clip);
    Ok(())
}
cargo add doe -F keyboard

keyboard example

fn main(){
   use doe::keyboard::key_press;
   use doe::keyboard::key_release;
   use doe::keyboard::listen_mouse_position;
   use doe::keyboard::get_mouse_position;
   use doe::keyboard::listen_keybord;

   use doe::keyboard::KeyCode;
   key_press(KeyCode::COMMAND);
   key_press(KeyCode::V);
   key_release(KeyCode::V);
   // listen key press and release
   listen_keybord();
}

control mouse

cargo add doe -F mouse
#arch linux
sudo pacman -S xdotool
#Fedora OR Red Hat
sudo dnf install libxdo-devel
#Ubuntu OR Debian 
sudo apt install libxdo-dev
#Cargo.toml add
[build]
rustflags = ["-L", "/usr/local/lib"]
#OR Cargo.toml add
[build]
rustflags = ["-l", "xdo"]
fn main()->doe::DynError{
    use std::time::Duration;
    use doe::mouse::press;
    move_to(300, 700);
    press("left");
    move_to_with_duration(0, 0,Duration::from_secs(5));
    move_and_press_right(800,900);
    press("right");
    Ok(())
}

implments Bts struct and bts! macro for Box<dyn Fn()> trait object

fn main() {
    use doe::DebugPrint;
    use doe::bfn;
    use doe::Bfn;
    #[derive(Debug)]
    struct Demo<'a>{
        name:&'a str
    }
    let f0 = bfn!(||{println!("ok");});
    f0.call();
    fn func()->Demo<'static>{
        let d = Demo{name: "andrew"};
        d
    }
    let f1 = bfn!(func);
    f1.call().println();

    fn sum()->usize{
        9+89
    }
    let f2 = Bfn::new(Box::new(sum));//or bfn!(sum);
    f2.call().println();
}

implments Bts struct and bts! macro for Box<dyn ToString> trait object

fn main() {
    use doe::DebugPrint;
    use doe::Bts;
    use doe::bts;
    let mut s:Bts =  bts!("Trait Object, it's ");
    s.push(bts!(100));
    s.push_str("% safe");
    s.println();//"Trait Object, it's 100% safe"
    s.as_bytes().println();//[84, 114, 97, 105, 116, 32, 79, 98, 106, 101, 99, 116, 44, 32, 105, 116, 39, 115, 32, 49, 48, 48, 37, 32, 115, 97, 102, 101]
    s.chars().println();//['T', 'r', 'a', 'i', 't', ' ', 'O', 'b', 'j', 'e', 'c', 't', ',', ' ', 'i', 't', '\'', 's', ' ', '1', '0', '0', '%', ' ', 's', 'a', 'f', 'e']
    let b = Into::<Bts>::into("b".to_string());
    let b = Bts::from("demo");
}

implmemt Debug,Display,Clone,Default,Drop trait for Struct

fn main() {
    use std::sync::{Arc, Mutex};
    use doe::*;
    struct Doe{
        pub name:String,
        pub nickname: Box<str>,
        key:Arc<Mutex<usize>>
    }
    impl_display!(Doe,name,nickname,key);
    impl_debug!(Doe,name,nickname,key);
    impl_default!(Doe,name,nickname,key);
    impl_clone!(Doe,name,nickname,key);
    impl_drop!(Doe,name,nickname,key);
    let d = Doe{name:"andrew".to_string(), nickname: Box::from("func"),key:Arc::new(Mutex::new(15))};
    let d1 = Doe::default();
    println!("{:?}",d);
    println!("{}",d1);
}

implment format for impl ToString

fn main() {
    use doe::Print;
    use doe::Str;
    use doe::targets;
    "this is a {s},I like Trait Object {p}%"
    .format(vec![(Box::new("{s}"),Box::new("demo")),(Box::new("{p}"),Box::new(100))]).println();//this is a demo,I like Trait Object 100%
    "this is a {d},I like Trait Object {p}}%"
        .format(targets!{"{d}"=>"demo","{p}"=>100})
        .println(); //this is a demo,I like Trait Object 100%
}

implment print println eprint eprintln for impl Display, impl Debug

use doe::Print;
use doe::DebugPrint;
"printable text".print();//impl Display
"printable text".println();
"printable text".eprintln();
#[derive(Debug)]
struct DebugPrintDemo{}//impl Debug
let d = DebugPrintDemo{};
d.dprint();
d.dprintln();
d.deprintln();

implment targets! for return Vec<(Box<dyn ToString>,Box<dyn ToString>)>

fn main() {
    use doe::targets;
    use doe::Print;
    use doe::Str;
    "this is a {d},I like Trait Object {p}}%"
        .format(targets!{"{d}"=>"demo","{p}"=>100})
        .println(); //this is a demo,I like Trait Object 100%
}

run timer by send stop_massge by channel

use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    let (sender, receiver) = mpsc::channel::<bool>();
    let t1 = thread::spawn(move || {
        thread::sleep(Duration::from_secs(5));
        sender.send(true).unwrap();
    });
    let t2 = thread::spawn(move || {
        run_timer_by_channel(Duration::from_secs(1), receiver, Box::new(|| {
            println!("running..");
        }));
    });
    t1.join().expect("Thread panicked");
    t2.join().expect("Thread panicked");
}

run timer by shared state

fn main() {
   use std::sync::{Arc, Mutex};
   let run_state = Arc::new(Mutex::new(true));

   let t1 = std::thread::spawn({
       let run_state = Arc::clone(&run_state);
       move || {
           std::thread::sleep(std::time::Duration::from_secs(5));
           *run_state.lock().unwrap() = false;
       }
   });

   let t2 = std::thread::spawn({
       let run_state = Arc::clone(&run_state);
       move || {
           run_timer_by_state(
               std::time::Duration::from_secs(1),
               run_state,
               Box::new(|| {
                   // Function body goes here
                   println!("Running...");
               }),
           );
       }
   });

   // Wait for the threads to finish
   t1.join().expect("Thread panicked");
   t2.join().expect("Thread panicked");

}

run timer anguments :start_time:Instant,step_time:Duration,stop_time:Duration,func:Box<dyn Fn()>

fn run(){
    println!("running ");
}
run_timer(std::time::Instant::now(),std::time::Duration::from_secs(1),std::time::Duration::from_secs(5),Box::new(run));

useage of fs module

fn main() {
    use doe::fs::*;
    use doe::DebugPrint;
    use doe::Str;
    use std::ops::Deref;
    use doe::fs::home_dir;
    use doe::DebugPrint;
    home_dir().display().dprintln();

    // append data to file
    append_data_to_file("demo.txt", "demo".as_bytes().to_vec()).unwrap();

    // get all files and folders
    walk_dir(".".to_path().deref()).unwrap().println();

    // get all folders
    walk_dir_get_files(".".to_path().deref()).unwrap().println();

    // get all folders
    walk_dir_get_folders(".".to_path().deref())
        .unwrap()
        .println();

    //move file the directory to a new directory
    move_file(
        "/Users/ryanandrew/code/test/t1/demo.zip".to_path().deref(),
        "/Users/ryanandrew/code/test/t2/d2.zip".to_path().deref(),
    )
    .unwrap();

    //copy file the directory to a new directory
    copy_file(
        "/Users/ryanandrew/code/test/t1/demo.zip".to_path().deref(),
        "/Users/ryanandrew/code/test/t2/d2.zip".to_path().deref(),
    )
    .unwrap();
    //move all files in the directory to a new directory
    move_folder(
        "/Users/ryanandrew/code/test/t1".to_path().deref(),
        "/Users/ryanandrew/code/test/t2/t1".to_path().deref(),
    )
    .unwrap();

    //copy all files in the directory to a new directory
    copy_folder(
        "/Users/ryanandrew/code/test/d1".to_path().deref(),
        "/Users/ryanandrew/code/test/d2".to_path().deref(),
    )
    .unwrap();
}

like pythons os.system() function

pub fn run() {
    //linux and macos
    system!("ping bing.com");
    // in windows
    system_powershell!("ls");
    system!("python -m http.server"); //run in cmd
}

implment cut format for str and String

use doe::Str;
let a = "this is a demo {}";
let c = a.cut(-1,-2,1);
let f = a.format("so {}").format("how good is");
println!("{:?}",f);
println!("{:?}",c);

convert type

 use doe::*;
 let s = as_to!(5., i64);
 assert_eq!(5, s);

if type is i8 return true

use doe::*;
assert_eq!(macros::is_i8(&5_i8),true);

if type is i16 return true

use doe::*;
assert_eq!(macros::is_i16(&5_i16),true);

if type is i32 return true

use doe::*;
assert_eq!(macros::is_i32(&5_i32),true);

if type is i64 return true

use doe::*;
assert_eq!(macros::is_i64(&5_i64),true);

if type is i128 return true

use doe::*;
assert_eq!(macros::is_i128(&5_i128),true);

if type is f32 return true

use doe::*;
assert_eq!(macros::is_f32(&5.0_f32),true);

if type is f64 return true

use doe::*;
assert_eq!(macros::is_f64(&5.0_f64),true);

returns a raised to the b power

use doe::*;
let p = powf!(2.,2.);
assert_eq!(p,4.0);

get argument and collect into Vec<String>

use doe::*;
//cargo run -- -n 100
let arg = args!();
assert_eq!(arg,vec![format!("-n"),format!("100")]);

get user input from terminal,return String

use doe::*;
let s = input!();
println!("{:?}",s);

Spliy &str by spliter and collect into Vec<String>

use doe::*;
let s = split_to_vec!("aa.bb",".");
assert_eq!(s,vec![format!("aa"),format!("bb")]);

read .csv file and Collect into Vec<Vec<String>>

use doe::*;
let s = read_csv!("./data.csv");
assert_eq!(s,vec![vec![format!("a"), format!("b"), format!("c")],vec![format!("1"), format!("2"), format!("3")],vec![format!("10"), format!("20"), format!("30")]]);

sorted new Vec

use doe::*;
let s1 = sorted!(vec![1.2, 2.6, 0.2]);
let s2 = sorted!(vec![8, 1_i128, 5_i128]);
assert_eq!(s1,vec![0.2,1.2,2.6]);
assert_eq!(s2,vec![1,5,8]);

sorted and deduped Vec

use doe::*;
let s1 = deduped_sorted!(vec![1.2, 1.2,2.6, 0.2]);
let s2 = deduped_sorted!(vec![8, 1_i128,8,5_i128]);
assert_eq!(s1,vec![0.2,1.2,2.6]);
assert_eq!(s2,vec![1,5,8]);

parse Vec element to type, parse Vec<&str> Collect to Vec<type>

use doe::*;
let v1: Vec<f64> = vec_element_parse!(vec!["15.", "2.9"], f64);
let v2: Vec<i128> = vec_element_parse!(vec!["15", "2"], i128);
let v3: Vec<f32> = vec_element_parse!(vec![".15", ".2"], f32);
assert_eq!(vec![15.0, 2.9], v1);
assert_eq!(vec![15, 2], v2);
assert_eq!(vec![0.15, 0.2], v3);

convert vec item to String,return Vec<String>

use doe::*;
let v1 = vec_element_to_string!(vec!["15.", "2.9"]);
let v2 = vec_element_to_string!(vec![15, 2]);
let v3 = vec_element_to_string!(vec![0.15, 0.2]);
assert_eq!(vec!["15.", "2.9"], v1);
assert_eq!(vec!["15", "2"], v2);
assert_eq!(vec!["0.15", "0.2"], v3);

return the array elements arranged from outermost elements to the middle element, traveling clockwise (n x n)

use doe::*;
let v1 = snail_sort!(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]);
let v2 =  snail_sort!(vec![vec![1.1, 2.1, 3.1],vec![4.1, 5.1, 6.1],vec![7.1, 8.1, 9.1]]);
assert_eq!(vec![1, 2, 3, 6, 9, 8, 7, 4, 5], v1);
assert_eq!(vec![1.1, 2.1, 3.1, 6.1, 9.1, 8.1, 7.1, 4.1, 5.1], v2);

mutiply two matrix

use doe::*;
let m1 = [[1, 2, -1], [-1, 3, 4], [1, 1, 1]].map(|s| s.to_vec()).to_vec();
let m2 = [[5, 6], [-5, -6], [6, 0]].map(|s| s.to_vec()).to_vec();
let mul_result1 = multiply_matrix!(&m1, &m2);
assert_eq!(mul_result1, [[-11, -6], [4, -24], [6, 0]]);
let m11 = [[1., 2., -1.], [-1., 3., 4.]].map(|s| s.to_vec()).to_vec();
let m22 = [[5.5, 6.], [-5., -6.5]].map(|s| s.to_vec()).to_vec();
let mul_result2 = multiply_matrix!(&m11, &m22);
assert_eq!(mul_result2, [[-4.5, -7.0], [-20.5, -25.5]]);
let m111 = [[1., 2., -1.], [-1., 3., 4.]].map(|s| s.to_vec()).to_vec();
let m222 = [[5.5, 6.]].map(|s| s.to_vec()).to_vec();
let mul_result3 = multiply_matrix!(&m111, &m222);
assert_eq!(mul_result3, [[5.5, 6.0]]);

find the fist element and remove

use doe::*;
let v1 = vec_element_remove!(vec!["15.", "2.9"], "2.9");
let v2 = vec_element_remove!(vec![15, 2, 3, 2], 2);
let v3 = vec_element_remove!(vec![0.15, 0.2, 0.2], 0.2);
assert_eq!(vec!["15."], v1);
assert_eq!(vec![15, 3, 2], v2);
assert_eq!(vec![0.15, 0.2], v3);

find element position and collect into Vec

use doe::*;
let v1 = vec_element_position_all!(vec![1, 2, 5, 3, 6, 2, 2], 2);
assert_eq!(v1, vec![1, 5, 6]);
let v2 = vec_element_position_all!(vec!["0".to_string(),"4".to_string(),"7".to_string(),"7".to_string(),], "7".to_string());
assert_eq!(v2, vec![2,3]);

slice vec by range

use doe::*;
let v1 = vec_slice!(vec![1.2, 1.5, 9.0], [..2]);
let v2 = vec_slice!(vec![1, 1, 9, 90, 87, 0, 2], [4..6]);
let v3 = vec_slice!(vec![1.2, 1.5, 9.0], [..]);
let v4 = vec_slice!(vec![1.2, 1.5, 9.0], [1..]);
let v5 = vec_slice!(vec!["1", "2", "3", "4", "5"], [2..5]);
let v6 = vec_slice!(vec!["1".to_string(),"2".to_string(),"3".to_string()], [1..]);
assert_eq!(v1, vec![1.2, 1.5]);
assert_eq!(v2, vec![87, 0]);
assert_eq!(v3, vec![1.2, 1.5, 9.0]);
assert_eq!(v4, vec![1.5, 9.0]);
assert_eq!(v5, vec!["3", "4", "5"]);
assert_eq!(v6,vec!["2".to_string(),"3".to_string()]);

clone element by index

use doe::*;
let v1 = vec_element_clone!(vec!["15.", "2.9"], 1);
let v2 = vec_element_clone!(vec![15, 2, 3, 2], 2);
let v3 = vec_element_clone!(vec![0.15, 0.2, 0.2], 0);
let v4 = vec_element_clone!(vec![format!("1"),format!("2"),format!("3"),format!("4"),format!("5")],4);
assert_eq!("2.9", v1);
assert_eq!(3, v2);
assert_eq!(0.15, v3);
assert_eq!(format!("5"), v4);

remove file or folder

remove_file_or_folder!("./demo.txt");
remove_file_or_folder!("./target");

get vec type ,return string type value

use doe::*;
assert_eq!(vec_type!(vec![0.2_f64]), format!("Vec<f64>"));
assert_eq!(vec_type!(vec![0.2_f32]), format!("Vec<f32>"));
assert_eq!(vec_type!(vec![2_i32]), format!("Vec<i32>"));
assert_eq!(vec_type!(vec![2_i128]), format!("Vec<i128>"));
assert_eq!(vec_type!(vec![2_isize]), format!("Vec<isize>"));
assert_eq!(vec_type!(vec![2_usize]), format!("Vec<usize>"));

convert vec elements type

use doe::*;
let v1: Vec<f64> = vec_element_convert!(vec![1, 2], f64);
let v2: Vec<i32> = vec_element_convert!(vec![1.0, 2.0], i32);
let v3: Vec<i128> = vec_element_convert!(vec![1.0, 2.0], i128);
let v4: Vec<i32> = vec_element_convert!(vec![1_usize, 2_usize], i32);
let v5: Vec<i64> = vec_element_convert!(vec![0.15, 2.0], i64);
assert_eq!(v1, vec![1.0, 2.0]);
assert_eq!(v2, vec![1, 2]);
assert_eq!(v3, vec![1, 2]);
assert_eq!(v4, vec![1, 2]);
assert_eq!(v5, vec![0, 2]);

expr return max value

use doe::*;
let re_max = max!(1, 20);
assert_eq!(re_max,20);

expr return min value

use doe::*;
let re_min = min!(10, 2, 2, 5, 4, 6);
assert_eq!(re_min,2);

convert binary string to decimal

use doe::*;
let d1 = binary_to_decimal!("01101",i128);
assert_eq!(d1,13_i128);
let d2 = binary_to_decimal!("00000000000010100110001",i64);
assert_eq!(d2,1329_i64);
let d3 = binary_to_decimal!("000011",i32);
assert_eq!(d3,3_i32);
let d4 = binary_to_decimal!("000101",i16);
assert_eq!(d4,5_i16);
let d5 = binary_to_decimal!("001001",i8);
assert_eq!(d5,9_i8);

expr return memory address

use doe::*;
let d1 = binary_to_decimal!("01101",i128);
println!("{:?}",memory_address!(d1));//0x7ffcac734f08

Merge two Vec return merged Vec

use doe::*;
let v1 = vec_merge!(vec![0, 1, 2], vec![5, 6, 7]);
assert_eq!(vec![0, 1, 2, 5, 6, 7],v1);
let v2 = vec_merge!(vec![0., 1., 2.], vec![5., 6., 7.]);
assert_eq!(vec![0., 1., 2., 5., 6., 7.],v2);

take size of elements and return a new vec

use doe::*;
let v1 = vec_element_take!(vec![0, 1, 2],2);
assert_eq!(vec![0,1],v1);

zip two vec elements in tuple

use doe::*;
let v1 = vec_zip!(vec![0, 1, 2],vec![0, 1, 2]);
assert_eq!(vec![(0,0),(1,1),(2,2)],v1);

enumerate all indexs and elements collect tuple of vec

use doe::*;
let v1 = vec_enumerate!(vec![12, 11, 20]);
assert_eq!(vec![(0,12),(1,11),(2,20)],v1);

sort vec and return sorted vec

use doe::*;
let v1 = vec_sort!(vec![10, 2, 3]);
assert_eq!(vec![2,3,10],v1);
let v2 = vec_sort!(vec![1.8, 2.5, 0.3]);
assert_eq!(vec![0.3,1.8,2.5],v2);

has stable rust nightly return bool

use doe::*;
let v1 = has_nightly_compiler!();
assert_eq!(v1, true);

has stable rust compiler return bool

use doe::*;
let v1 = has_stable_compiler!();
assert_eq!(v1, false);

run command

use doe::*;
command!("ls -la");
command!("dust");
command!("lsd");

run a function once after a particularized delay(millis)

use doe::*;
set_timeout!(||{
   println!("ok");
},3000);

run a function after a particularized delay(millis) each run delay(millis)

use doe::*;
duration_set_timeout!(||{
    println!("ok");
},3000,1000); //from now delay 3000ms,each 1000ms run func()

run a function repeatedly, beginning after some millis, then repeating continuously at the given interval.

use doe::*;
set_interval!(||{
   println!("ok");
},3000);

get current UTC-timestamp

use doe::*;
let t = utc_timestamp!();
eprintln!("{}", t);

get Local now

use doe::*;
let t = local_now!();
eprintln!("{}", t);

get Utc now

use doe::*;
let t = utc_now!();
eprintln!("{}", t);

macro for HashMap

 use doe::*;
 use std::collections::HashMap;
 let mut map:HashMap<i32,i32> = hashmap!();
 map.insert(0, 1);
 let map1 = hashmap!(2=>5,3=>4);

macro for BTreeMap

 use doe::*;
 use std::collections::BTreeMap;
 let mut map:BTreeMap<i32,i32> = btreemap!();
 map.insert(0, 1);
 let map1 = btreemap!(2=>5,3=>4);

Dependencies

~0–44MB
~612K SLoC