mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-05-15 17:58:44 +00:00
Unify imports
This commit is contained in:
parent
7ed2316040
commit
c466d01da9
41
src/cli.rs
Normal file
41
src/cli.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
|
||||||
|
use crate::dev::DevCommand;
|
||||||
|
|
||||||
|
/// Rustlings is a collection of small exercises to get you used to writing and reading Rust code
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(version)]
|
||||||
|
pub struct Args {
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub command: Option<Command>,
|
||||||
|
/// Manually run the current exercise using `r` in the watch mode.
|
||||||
|
/// Only use this if Rustlings fails to detect exercise file changes.
|
||||||
|
#[arg(long)]
|
||||||
|
pub manual_run: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum Command {
|
||||||
|
/// Initialize the official Rustlings exercises
|
||||||
|
Init,
|
||||||
|
/// Run a single exercise. Runs the next pending exercise if the exercise name is not specified
|
||||||
|
Run {
|
||||||
|
/// The name of the exercise
|
||||||
|
name: Option<String>,
|
||||||
|
},
|
||||||
|
/// Check all the exercises, marking them as done or pending accordingly.
|
||||||
|
CheckAll,
|
||||||
|
/// Reset a single exercise
|
||||||
|
Reset {
|
||||||
|
/// The name of the exercise
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
/// Show a hint. Shows the hint of the next pending exercise if the exercise name is not specified
|
||||||
|
Hint {
|
||||||
|
/// The name of the exercise
|
||||||
|
name: Option<String>,
|
||||||
|
},
|
||||||
|
/// Commands for developing (community) Rustlings exercises
|
||||||
|
#[command(subcommand)]
|
||||||
|
Dev(DevCommand),
|
||||||
|
}
|
||||||
@ -7,7 +7,7 @@ mod new;
|
|||||||
mod update;
|
mod update;
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
pub enum DevCommands {
|
pub enum DevCommand {
|
||||||
/// Create a new project for community exercises
|
/// Create a new project for community exercises
|
||||||
New {
|
New {
|
||||||
/// The path to create the project in
|
/// The path to create the project in
|
||||||
@ -26,7 +26,7 @@ pub enum DevCommands {
|
|||||||
Update,
|
Update,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DevCommands {
|
impl DevCommand {
|
||||||
pub fn run(self) -> Result<()> {
|
pub fn run(self) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Self::New { path, no_git } => {
|
Self::New { path, no_git } => {
|
||||||
|
|||||||
@ -11,9 +11,10 @@ use crossterm::{
|
|||||||
};
|
};
|
||||||
use std::io::{self, StdoutLock, Write};
|
use std::io::{self, StdoutLock, Write};
|
||||||
|
|
||||||
use crate::app_state::AppState;
|
use crate::{
|
||||||
|
app_state::AppState,
|
||||||
use self::state::{Filter, ListState};
|
list::state::{Filter, ListState},
|
||||||
|
};
|
||||||
|
|
||||||
mod scroll_state;
|
mod scroll_state;
|
||||||
mod state;
|
mod state;
|
||||||
|
|||||||
@ -15,11 +15,10 @@ use std::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
app_state::AppState,
|
app_state::AppState,
|
||||||
exercise::Exercise,
|
exercise::Exercise,
|
||||||
|
list::scroll_state::ScrollState,
|
||||||
term::{CountedWrite, MaxLenWriter, progress_bar},
|
term::{CountedWrite, MaxLenWriter, progress_bar},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::scroll_state::ScrollState;
|
|
||||||
|
|
||||||
const COL_SPACING: usize = 2;
|
const COL_SPACING: usize = 2;
|
||||||
const SELECTED_ROW_ATTRIBUTES: Attributes = Attributes::none()
|
const SELECTED_ROW_ATTRIBUTES: Attributes = Attributes::none()
|
||||||
.with(Attribute::Reverse)
|
.with(Attribute::Reverse)
|
||||||
|
|||||||
61
src/main.rs
61
src/main.rs
@ -1,6 +1,6 @@
|
|||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use app_state::StateFileStatus;
|
use app_state::StateFileStatus;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::Parser;
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, IsTerminal, Write},
|
io::{self, IsTerminal, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
@ -8,10 +8,15 @@ use std::{
|
|||||||
};
|
};
|
||||||
use term::{clear_terminal, press_enter_prompt};
|
use term::{clear_terminal, press_enter_prompt};
|
||||||
|
|
||||||
use self::{app_state::AppState, dev::DevCommands, info_file::InfoFile};
|
use crate::{
|
||||||
|
app_state::AppState,
|
||||||
|
cli::{Args, Command},
|
||||||
|
info_file::InfoFile,
|
||||||
|
};
|
||||||
|
|
||||||
mod app_state;
|
mod app_state;
|
||||||
mod cargo_toml;
|
mod cargo_toml;
|
||||||
|
mod cli;
|
||||||
mod cmd;
|
mod cmd;
|
||||||
mod dev;
|
mod dev;
|
||||||
mod embedded;
|
mod embedded;
|
||||||
@ -25,44 +30,6 @@ mod watch;
|
|||||||
|
|
||||||
const CURRENT_FORMAT_VERSION: u8 = 1;
|
const CURRENT_FORMAT_VERSION: u8 = 1;
|
||||||
|
|
||||||
/// Rustlings is a collection of small exercises to get you used to writing and reading Rust code
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[command(version)]
|
|
||||||
struct Args {
|
|
||||||
#[command(subcommand)]
|
|
||||||
command: Option<Subcommands>,
|
|
||||||
/// Manually run the current exercise using `r` in the watch mode.
|
|
||||||
/// Only use this if Rustlings fails to detect exercise file changes.
|
|
||||||
#[arg(long)]
|
|
||||||
manual_run: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
|
||||||
enum Subcommands {
|
|
||||||
/// Initialize the official Rustlings exercises
|
|
||||||
Init,
|
|
||||||
/// Run a single exercise. Runs the next pending exercise if the exercise name is not specified
|
|
||||||
Run {
|
|
||||||
/// The name of the exercise
|
|
||||||
name: Option<String>,
|
|
||||||
},
|
|
||||||
/// Check all the exercises, marking them as done or pending accordingly.
|
|
||||||
CheckAll,
|
|
||||||
/// Reset a single exercise
|
|
||||||
Reset {
|
|
||||||
/// The name of the exercise
|
|
||||||
name: String,
|
|
||||||
},
|
|
||||||
/// Show a hint. Shows the hint of the next pending exercise if the exercise name is not specified
|
|
||||||
Hint {
|
|
||||||
/// The name of the exercise
|
|
||||||
name: Option<String>,
|
|
||||||
},
|
|
||||||
/// Commands for developing (community) Rustlings exercises
|
|
||||||
#[command(subcommand)]
|
|
||||||
Dev(DevCommands),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<ExitCode> {
|
fn main() -> Result<ExitCode> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
@ -72,8 +39,8 @@ fn main() -> Result<ExitCode> {
|
|||||||
|
|
||||||
'priority_cmd: {
|
'priority_cmd: {
|
||||||
match args.command {
|
match args.command {
|
||||||
Some(Subcommands::Init) => init::init().context("Initialization failed")?,
|
Some(Command::Init) => init::init().context("Initialization failed")?,
|
||||||
Some(Subcommands::Dev(dev_command)) => dev_command.run()?,
|
Some(Command::Dev(dev_command)) => dev_command.run()?,
|
||||||
_ => break 'priority_cmd,
|
_ => break 'priority_cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,13 +108,13 @@ fn main() -> Result<ExitCode> {
|
|||||||
|
|
||||||
watch::watch(&mut app_state, notify_exercise_names)?;
|
watch::watch(&mut app_state, notify_exercise_names)?;
|
||||||
}
|
}
|
||||||
Some(Subcommands::Run { name }) => {
|
Some(Command::Run { name }) => {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
app_state.set_current_exercise_by_name(&name)?;
|
app_state.set_current_exercise_by_name(&name)?;
|
||||||
}
|
}
|
||||||
return run::run(&mut app_state);
|
return run::run(&mut app_state);
|
||||||
}
|
}
|
||||||
Some(Subcommands::CheckAll) => {
|
Some(Command::CheckAll) => {
|
||||||
let mut stdout = io::stdout().lock();
|
let mut stdout = io::stdout().lock();
|
||||||
if let Some(first_pending_exercise_ind) = app_state.check_all_exercises(&mut stdout)? {
|
if let Some(first_pending_exercise_ind) = app_state.check_all_exercises(&mut stdout)? {
|
||||||
if app_state.current_exercise().done {
|
if app_state.current_exercise().done {
|
||||||
@ -175,19 +142,19 @@ fn main() -> Result<ExitCode> {
|
|||||||
|
|
||||||
app_state.render_final_message(&mut stdout)?;
|
app_state.render_final_message(&mut stdout)?;
|
||||||
}
|
}
|
||||||
Some(Subcommands::Reset { name }) => {
|
Some(Command::Reset { name }) => {
|
||||||
app_state.set_current_exercise_by_name(&name)?;
|
app_state.set_current_exercise_by_name(&name)?;
|
||||||
let exercise_path = app_state.reset_current_exercise()?;
|
let exercise_path = app_state.reset_current_exercise()?;
|
||||||
println!("The exercise {exercise_path} has been reset");
|
println!("The exercise {exercise_path} has been reset");
|
||||||
}
|
}
|
||||||
Some(Subcommands::Hint { name }) => {
|
Some(Command::Hint { name }) => {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
app_state.set_current_exercise_by_name(&name)?;
|
app_state.set_current_exercise_by_name(&name)?;
|
||||||
}
|
}
|
||||||
println!("{}", app_state.current_exercise().hint);
|
println!("{}", app_state.current_exercise().hint);
|
||||||
}
|
}
|
||||||
// Handled in an earlier match.
|
// Handled in an earlier match.
|
||||||
Some(Subcommands::Init | Subcommands::Dev(_)) => (),
|
Some(Command::Init | Command::Dev(_)) => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ExitCode::SUCCESS)
|
Ok(ExitCode::SUCCESS)
|
||||||
|
|||||||
@ -13,10 +13,9 @@ use std::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
app_state::{AppState, ExercisesProgress},
|
app_state::{AppState, ExercisesProgress},
|
||||||
list,
|
list,
|
||||||
|
watch::{notify_event::NotifyEventHandler, state::WatchState, terminal_event::InputEvent},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{notify_event::NotifyEventHandler, state::WatchState, terminal_event::InputEvent};
|
|
||||||
|
|
||||||
mod notify_event;
|
mod notify_event;
|
||||||
mod state;
|
mod state;
|
||||||
mod terminal_event;
|
mod terminal_event;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{EXERCISE_RUNNING, WatchEvent};
|
use crate::watch::{EXERCISE_RUNNING, WatchEvent};
|
||||||
|
|
||||||
const DEBOUNCE_DURATION: Duration = Duration::from_millis(200);
|
const DEBOUNCE_DURATION: Duration = Duration::from_millis(200);
|
||||||
|
|
||||||
|
|||||||
@ -17,10 +17,9 @@ use crate::{
|
|||||||
clear_terminal,
|
clear_terminal,
|
||||||
exercise::{OUTPUT_CAPACITY, RunnableExercise, solution_link_line},
|
exercise::{OUTPUT_CAPACITY, RunnableExercise, solution_link_line},
|
||||||
term::progress_bar,
|
term::progress_bar,
|
||||||
|
watch::{InputPauseGuard, WatchEvent, terminal_event::terminal_event_handler},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{InputPauseGuard, WatchEvent, terminal_event::terminal_event_handler};
|
|
||||||
|
|
||||||
const HEADING_ATTRIBUTES: Attributes = Attributes::none()
|
const HEADING_ATTRIBUTES: Attributes = Attributes::none()
|
||||||
.with(Attribute::Bold)
|
.with(Attribute::Bold)
|
||||||
.with(Attribute::Underlined);
|
.with(Attribute::Underlined);
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use std::sync::{
|
|||||||
mpsc::{Receiver, Sender},
|
mpsc::{Receiver, Sender},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{EXERCISE_RUNNING, WatchEvent};
|
use crate::watch::{EXERCISE_RUNNING, WatchEvent};
|
||||||
|
|
||||||
pub enum InputEvent {
|
pub enum InputEvent {
|
||||||
Next,
|
Next,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user