Unify imports

This commit is contained in:
mo8it 2026-04-05 17:19:11 +02:00
parent 7ed2316040
commit c466d01da9
9 changed files with 66 additions and 60 deletions

41
src/cli.rs Normal file
View 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),
}

View File

@ -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 } => {

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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,