Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## [0.5.3] - 2025-11-05

### Fixed

- Added interactive check when rFortune is launched without an existing configuration directory:
- If run in an interactive terminal, the user is asked to confirm initialization (`Initialize rFortune now? [Y/n]`).
- If run in a non-interactive context (script, CI, etc.), initialization proceeds automatically.
- Prevents unintended directory creation and improves transparency during the first launch.

### Changed

- Initialization flow is now clearer and reports actions through `ConsoleLog` messages.

---

## [0.5.2] - 2025-11-04

### Added
Expand Down
98 changes: 65 additions & 33 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rfortune"
version = "0.5.2"
version = "0.5.3"
edition = "2024"
authors = ["Umpire274 <umpire274@gmail.com>"]
description = "A Rust-based clone of the classic UNIX 'fortune' command"
Expand All @@ -19,7 +19,7 @@ include = [
]

[build-dependencies]
winresource = "0.1.23"
winresource = "0.1.26"

[package.metadata.winresource]
Icon = "res/rfortune.ico"
Expand All @@ -30,4 +30,5 @@ rand = "0.9.2"
dirs = "6.0.0"
serde = { version = "1.0.228", features = ["derive"] }
serde_yaml = "0.9.33"
atty = "0.2.14"

32 changes: 19 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,20 @@ scripting, or just a bit of inspiration.

---

## ✨ New in v0.5.2
### ✨ New in v0.5.3

### 🆕 Configuration system improvements
**🧭 Smarter first-time initialization**

- Configuration filename renamed from config.yaml → rfortune.conf for better clarity and portability.
- Automatic migration from legacy config.yaml to the new format — the old file is safely backed up as config.yaml.bak.
- Added the new subcommand config edit:
- rfortune config edit → opens rfortune.conf using the system’s default text editor.
- rfortune config edit --editor <name|path> → opens it with a specific editor (e.g. vi, nano, code).
- Automatic detection of preferred editors via $VISUAL and $EDITOR environment variables.
- Default fallback editors are nano (macOS/Linux) and notepad (Windows).
- Added an interactive prompt when `rfortune` is launched for the first time and no configuration directory exists.
- In interactive terminals, users are asked: `Initialize rFortune now? [Y/n]`.
- In non-interactive contexts (scripts, CI, etc.), initialization happens automatically.
- Prevents unintended directory creation and improves transparency during first setup.
- Initialization progress and results are displayed using `ConsoleLog` messages for consistency.

### 🎨 Improved CLI feedback
**⚙️ Improved startup behavior**

- Introduced the new ConsoleLog class for rich, colored terminal output:
- ℹ Info, ✅ Success, ⚠️ Warning, ❌ Error
- Unified message style and improved feedback during configuration, cache, and fortune file operations.
- The application now clearly reports which configuration directory is being used (`dirs::data_dir()` path).
- Overall initialization flow refined for clarity and better UX.

---

Expand Down Expand Up @@ -145,6 +142,15 @@ Running `rfortune` without subcommands prints a random fortune from the default

---

## ⚙️ First-time setup

When `rfortune` is launched for the first time and no configuration directory exists,
the application will ask whether to initialize its environment (creating the default
configuration and fortune files).
In non-interactive contexts, initialization happens automatically.

---

## 🧩 Options & Subcommands

| Command / Option | Description |
Expand Down
6 changes: 6 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use clap::Parser;
use rfortune::log::ConsoleLog;
use rfortune::utils::ensure_app_initialized;
use rfortune::{config, loader, utils};

mod cli;
Expand All @@ -12,6 +13,11 @@ fn main() {

println!();

if let Err(e) = ensure_app_initialized() {
ConsoleLog::ko(format!("Initialization error: {e}"));
return;
}

match cli.command {
// ---------------- CONFIG ----------------
Some(Commands::Config { action }) => match action {
Expand Down
37 changes: 34 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use crate::config;
use crate::loader::FortuneFile;
use crate::log::ConsoleLog;
use rand::seq::IndexedRandom;
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::{fs, io};

/// Estrae una citazione casuale dalla lista
pub fn random_quote(quotes: &[String]) -> &str {
Expand Down Expand Up @@ -99,7 +99,7 @@ fn get_cache_dir() -> PathBuf {
}

/// Svuota completamente la cache
pub fn clear_cache_dir() -> std::io::Result<()> {
pub fn clear_cache_dir() -> io::Result<()> {
let dir = get_cache_dir();
if dir.exists() {
fs::remove_dir_all(&dir)?;
Expand All @@ -111,7 +111,7 @@ pub fn clear_cache_dir() -> std::io::Result<()> {
}

/// Salva l’ultima citazione usata in un file di cache
pub fn save_last_cache(file_path: &Path, quote: &str) -> std::io::Result<()> {
pub fn save_last_cache(file_path: &Path, quote: &str) -> io::Result<()> {
let cache_path = get_cache_path(file_path);
if let Some(parent) = cache_path.parent() {
fs::create_dir_all(parent)?; // assicura che la cartella esista
Expand All @@ -122,3 +122,34 @@ pub fn save_last_cache(file_path: &Path, quote: &str) -> std::io::Result<()> {

Ok(())
}

pub fn ensure_app_initialized() -> io::Result<()> {
let dir = config::app_dir();

if dir.exists() {
return Ok(()); // tutto a posto
}

// Se il processo è interattivo (TTY), chiedi conferma
if atty::is(atty::Stream::Stdin) {
print!("Configuration directory not found. Initialize rFortune now? [Y/n]: ");
io::stdout().flush()?;

let mut input = String::new();
io::stdin().read_line(&mut input)?;
let answer = input.trim().to_lowercase();

if answer == "n" || answer == "no" {
ConsoleLog::warn("Initialization aborted by user.");
std::process::exit(0);
}
} else {
ConsoleLog::info("Configuration directory missing — initializing automatically.");
}

// Esegui l’inizializzazione completa
ConsoleLog::info("Initializing rFortune environment...");
config::init_config_file()?;
ConsoleLog::ok("rFortune initialized successfully.");
Ok(())
}