diff --git a/src/app_state.rs b/src/app_state.rs index 5979150f..7de17543 100644 --- a/src/app_state.rs +++ b/src/app_state.rs @@ -20,7 +20,7 @@ use crate::{ embedded::EMBEDDED_FILES, exercise::{Exercise, RunnableExercise}, info_file::ExerciseInfo, - term::{self, CheckProgressVisualizer}, + term::{self, CheckProgressVisualizer}, url_replacer::UrlReplacer, }; const STATE_FILE_NAME: &str = ".rustlings-state.txt"; @@ -68,6 +68,7 @@ impl AppState { pub fn new( exercise_infos: Vec, final_message: String, + base_url: Option, ) -> Result<(Self, StateFileStatus)> { let cmd_runner = CmdRunner::build()?; let mut state_file = OpenOptions::new() @@ -80,6 +81,13 @@ impl AppState { format!("Failed to open or create the state file {STATE_FILE_NAME}") })?; + // replacer for rustbook url + let url_replacer = if let Some(url) = &base_url { + Some(UrlReplacer::new(&url)) + } else { + None + }; + let dir_canonical_path = term::canonicalize("exercises"); let mut exercises = exercise_infos .into_iter() @@ -90,7 +98,11 @@ impl AppState { let path = exercise_info.path().leak(); let name = exercise_info.name.leak(); let dir = exercise_info.dir.map(|dir| &*dir.leak()); - let hint = exercise_info.hint.leak().trim_ascii(); + let mut hint = exercise_info.hint.leak().trim_ascii(); + + if let Some(replacer) = &url_replacer { + hint = replacer.replace(&hint).leak(); + } let canonical_path = dir_canonical_path.as_deref().map(|dir_canonical_path| { let mut canonical_path; diff --git a/src/main.rs b/src/main.rs index c27bfa89..2ee376b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ use std::{ }; use term::{clear_terminal, press_enter_prompt}; -use self::{app_state::AppState, dev::DevCommands, info_file::InfoFile, url_replacer::UrlReplacer}; +use self::{app_state::AppState, dev::DevCommands, info_file::InfoFile}; mod app_state; mod cargo_toml; @@ -99,6 +99,7 @@ fn main() -> Result { let (mut app_state, state_file_status) = AppState::new( info_file.exercises, info_file.final_message.unwrap_or_default(), + args.base_url, )?; // Show the welcome message if the state file doesn't exist yet. @@ -186,13 +187,7 @@ fn main() -> Result { app_state.set_current_exercise_by_name(&name)?; } - let hint = app_state.current_exercise().hint; - if let Some(base_url) = args.base_url { - let replacer = UrlReplacer::new(base_url); - println!("{}", replacer.replace(hint)); - } else { - println!("{}", hint); - }; + println!("{}", app_state.current_exercise().hint); } // Handled in an earlier match. Some(Subcommands::Init | Subcommands::Dev(_)) => (), diff --git a/src/url_replacer.rs b/src/url_replacer.rs index 97977305..b32a8495 100644 --- a/src/url_replacer.rs +++ b/src/url_replacer.rs @@ -5,18 +5,20 @@ pub struct UrlReplacer { const EN_BASE_URL: &str = "https://doc.rust-lang.org/book"; impl UrlReplacer { - pub fn new(mut base_url: String) -> Self { - base_url = if base_url.ends_with('/') { + /// this fn will trim url end with '/' + pub fn new(base_url: &String) -> Self { + let url = if base_url.ends_with('/') { base_url.trim_end_matches('/').to_owned() } else { - base_url + base_url.clone() }; Self { - base_url + base_url: url } } + /// replace rustbook url pub fn replace(&self, hint: &str) -> String { hint.replace(EN_BASE_URL, &self.base_url) } @@ -30,7 +32,7 @@ mod test { #[test] fn non_rustbook_url() { - let replacer = UrlReplacer::new(String::from(TEST_DOMAIN)); + let replacer = UrlReplacer::new(&String::from(TEST_DOMAIN)); let hint = "\ hints (...) lines (...) @@ -42,7 +44,7 @@ link: https://example.com/ch03-02-data-types.html"; #[test] fn replace_rustbook_url() { - let replacer = UrlReplacer::new(String::from(TEST_DOMAIN)); + let replacer = UrlReplacer::new(&String::from(TEST_DOMAIN)); let hint = "\ hints (...) lines (...) @@ -55,7 +57,10 @@ link: https://doc.rust-kr.org/ch03-02-data-types.html", replacer.replace(hint)); #[test] fn trim_end_with_slash() { - let replacer = UrlReplacer::new(String::from(TEST_DOMAIN)); + let mut domain = String::from(TEST_DOMAIN); + domain.push('/'); + + let replacer = UrlReplacer::new(&domain); assert_eq!(TEST_DOMAIN, replacer.base_url); }