Let’s make the main function a tokio entry point.
Add the #[tokio::main] macro to the main function and make the function async. This allows you
to use async and await inside main. You can also now spawn tokio tasks within your
application.
#[tokio :: main] 
async   fn   main ()  ->  color_eyre :: Result<()> { 
     println! ( " Sleeping for 5 seconds... " ); 
    tokio :: time :: sleep (tokio :: time :: Duration :: from_secs ( 5 )) . await ; 
    Ok(()) 
} 
 
You can run this with cargo run, and you’ll see that the terminal prints and then blocks for 5
seconds before returning control.
$   cargo   run 
    Compiling   crates-tui   v0.1.0  (~/gitrepos/crates-tui-tutorial) 
     Finished   dev  [unoptimized  +   debuginfo]   target ( s )  in   0.31 s 
      Running   ` target/debug/crates-tui-tutorial ` 
Sleeping   for   5   seconds... 
$ 
 
 Tip
On UNIX systems, you can use time cargo run to see how long a process takes to run.
$   time   cargo   run 
     Finished   dev  [unoptimized  +   debuginfo]   target ( s )  in   0.08 s 
      Running   ` target/debug/crates-tui-tutorial ` 
Sleeping   for   5   seconds... 
cargo   run    0.09 s   user   0.05 s   system   2 %   cpu   5.262   total 
$ 
In this case, it took 5.262 seconds to run cargo run.
 
 Homework
Try to predicate what happens if you spawn multiple tokio tasks? e.g.
#[tokio :: main] 
async   fn   main ()  ->  color_eyre :: Result<()> { 
     println! ( " Spawning a task that sleeps 5 seconds... " ); 
     let   mut   tasks   =   vec! []; 
     for   i   in   0 .. 10  { 
         tasks . push (tokio :: spawn ( async   move  { 
             println! ( " Sleeping for 5 seconds in a tokio task {i}... " ); 
            tokio :: time :: sleep (tokio :: time :: Duration :: from_secs ( 5 )) . await ; 
             i 
        })); 
    } 
     println! ( " Getting return values from tasks... " ); 
     while   let  Some( task )  =   tasks . pop () { 
         let   return_value_from_task   =   task . await ? ; 
         println! ( " Got i = {return_value_from_task} " ); 
    } 
    Ok(()) 
} 
Now, what happens if you run the following instead?
#[tokio :: main] 
async   fn   main ()  ->  color_eyre :: Result<()> { 
     println! ( " Spawning a task that sleeps 5 seconds... " ); 
     let   mut   tasks   =   vec! []; 
     for   i   in   0 .. 10  { 
         tasks . push ( async   move  { 
             println! ( " Sleeping for 5 seconds in a tokio task {i}... " ); 
            tokio :: time :: sleep (tokio :: time :: Duration :: from_secs ( 5 )) . await ; 
             i 
        }); 
    } 
     println! ( " Getting return values from tasks... " ); 
     while   let  Some( task )  =   tasks . pop () { 
         let   return_value_from_task   =   task . await ; 
         println! ( " Got i = {return_value_from_task} " ); 
    } 
    Ok(()) 
} 
Do you understand the different between creating a future and awaiting on it later versus 
spawning a future and awaiting on the spawn’s JoinHandle later?
 
Conclusion 
We will expand on main.rs in the following sections. Right now, your project should look like
this:
. 
├── Cargo.lock 
├── Cargo.toml 
└── src 
   └── main.rs