diff --git a/crates/hyfetch/src/bin/hyfetch.rs b/crates/hyfetch/src/bin/hyfetch.rs index 45f42610..b24c9bf7 100644 --- a/crates/hyfetch/src/bin/hyfetch.rs +++ b/crates/hyfetch/src/bin/hyfetch.rs @@ -149,7 +149,14 @@ fn main() -> Result<()> { }; debug!(?color_profile, "lightened color profile"); - let asc = if let Some(path) = options.ascii_file { + let asc = if let Some(path_str) = config.custom_ascii_path { + let path = PathBuf::from(path_str); + RawAsciiArt { + asc: fs::read_to_string(&path) + .with_context(|| format!("failed to read ascii from {path:?}"))?, + fg: Vec::new(), + } + } else if let Some(path) = options.ascii_file { RawAsciiArt { asc: fs::read_to_string(&path) .with_context(|| format!("failed to read ascii from {path:?}"))?, @@ -1078,6 +1085,73 @@ fn create_config( backend.as_ref(), ); + ////////////////////////////// + // 8. Custom ASCII file + let mut custom_ascii_path: Option = None; + clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?; + let choice = literal_input( + "Do you want to specify a custom ASCII file?", + &["y", "n"], + "n", + true, + color_mode, + ) + .context("failed to ask for choice input")?; + + if choice == "y" { + loop { + let path_input = input(Some("Path to custom ASCII file (must be .txt and UTF-8 encoded): ")) + .context("failed to read input")? + .trim() + .to_owned(); + + if path_input.is_empty() { + printc("&cNo path entered. Skipping custom ASCII file.", color_mode).context("failed to print message")?; + break; + } + + let custom_path = PathBuf::from(&path_input); + if !custom_path.is_file() { + printc(format!("&cError: File not found at {path_input}"), color_mode).context("failed to print message")?; + let try_again = literal_input("Try again?", &["y", "n"], "y", true, color_mode).context("failed to ask for choice input")?; + if try_again == "n" { + break; + } + continue; + } + + if custom_path.extension().map_or(true, |ext| ext != "txt") { + printc(format!("&cError: File must have a .txt extension. Found {:?}", custom_path.extension()), color_mode).context("failed to print message")?; + let try_again = literal_input("Try again?", &["y", "n"], "y", true, color_mode).context("failed to ask for choice input")?; + if try_again == "n" { + break; + } + continue; + } + + match fs::read_to_string(&custom_path) { + Ok(_) => { + custom_ascii_path = Some(path_input); + update_title( + &mut title, + &mut option_counter, + "Custom ASCII file", + custom_ascii_path.as_ref().unwrap(), + ); + break; + } + Err(e) => { + printc(format!("&cError: File is not UTF-8 encoded or an unexpected error occurred: {e}"), color_mode).context("failed to print message")?; + let try_again = literal_input("Try again?", &["y", "n"], "y", true, color_mode).context("failed to ask for choice input")?; + if try_again == "n" { + break; + } + continue; + } + } + } + } + // Create config clear_screen(Some(&title), color_mode, debug_mode).context("failed to clear screen")?; let config = Config { @@ -1091,6 +1165,7 @@ fn create_config( args: None, distro: logo_chosen, pride_month_disable: false, + custom_ascii_path, }; debug!(?config, "created config"); diff --git a/crates/hyfetch/src/models.rs b/crates/hyfetch/src/models.rs index 65fa69f4..b8780155 100644 --- a/crates/hyfetch/src/models.rs +++ b/crates/hyfetch/src/models.rs @@ -19,6 +19,7 @@ pub struct Config { pub args: Option>, pub distro: Option, pub pride_month_disable: bool, + pub custom_ascii_path: Option, } impl Config { diff --git a/hyfetch/main.py b/hyfetch/main.py index d0b4616f..fb7e1053 100755 --- a/hyfetch/main.py +++ b/hyfetch/main.py @@ -5,6 +5,7 @@ import datetime import importlib.util import json +import os import random import traceback from itertools import permutations, islice @@ -318,9 +319,49 @@ def select_backend(): backend = select_backend() update_title('Selected backend', backend) + ############################## + # 7. Custom ASCII file + custom_ascii_path = None + clear_screen(title) + if literal_input('Do you want to specify a custom ASCII file?', ['y', 'n'], 'n') == 'y': + while True: + path_input = input('Path to custom ASCII file (must be .txt and UTF-8 encoded): ').strip() + if not path_input: + printc('&cNo path entered. Skipping custom ASCII file.') + break + + custom_path = Path(path_input) + if not custom_path.is_file(): + printc(f'&cError: File not found at {path_input}') + if literal_input('Try again?', ['y', 'n'], 'y') == 'n': + break + continue + + if not custom_path.suffix == '.txt': + printc(f'&cError: File must have a .txt extension. Found {custom_path.suffix}') + if literal_input('Try again?', ['y', 'n'], 'y') == 'n': + break + continue + + try: + custom_path.read_text('utf-8') + custom_ascii_path = str(custom_path) + update_title('Custom ASCII file', custom_ascii_path) + break + except UnicodeDecodeError: + printc(f'&cError: File is not UTF-8 encoded.') + if literal_input('Try again?', ['y', 'n'], 'y') == 'n': + break + continue + except Exception as e: + printc(f'&cAn unexpected error occurred: {e}') + if literal_input('Try again?', ['y', 'n'], 'y') == 'n': + break + continue + # Create config clear_screen(title) - c = Config(preset, color_system, light_dark, lightness, color_alignment, backend) + c = Config(preset, color_system, light_dark, lightness, color_alignment, backend, custom_ascii_path=custom_ascii_path) # Save config print() @@ -463,7 +504,12 @@ def run(): # Run try: - asc = get_distro_ascii() if not args.ascii_file else Path(args.ascii_file).read_text("utf-8") + if config.custom_ascii_path: + asc = Path(config.custom_ascii_path).read_text("utf-8") + elif args.ascii_file: + asc = Path(args.ascii_file).read_text("utf-8") + else: + asc = get_distro_ascii() asc = config.color_align.recolor_ascii(asc, preset) asc = '\n'.join(asc.split('\n')[1:]) neofetch_util.run(asc, config.backend, config.args or '') diff --git a/hyfetch/models.py b/hyfetch/models.py index 9f3a747d..75095270 100644 --- a/hyfetch/models.py +++ b/hyfetch/models.py @@ -20,6 +20,7 @@ class Config: distro: str | None = None pride_month_shown: list[int] = field(default_factory=list) # This is deprecated, see issue #136 pride_month_disable: bool = False + custom_ascii_path: str | None = None @classmethod def from_dict(cls, d: dict):