[util] Añade indoc para indentar código bien

This commit is contained in:
Manuel Cillero 2025-09-12 01:13:17 +02:00
parent e3ca6079ff
commit 940e6aaf18
4 changed files with 75 additions and 63 deletions

7
Cargo.lock generated
View file

@ -1307,6 +1307,12 @@ dependencies = [
"hashbrown 0.15.4", "hashbrown 0.15.4",
] ]
[[package]]
name = "indoc"
version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
[[package]] [[package]]
name = "inout" name = "inout"
version = "0.1.4" version = "0.1.4"
@ -1568,6 +1574,7 @@ dependencies = [
"config", "config",
"figlet-rs", "figlet-rs",
"fluent-templates", "fluent-templates",
"indoc",
"itoa", "itoa",
"pagetop-build", "pagetop-build",
"pagetop-macros", "pagetop-macros",

View file

@ -20,6 +20,7 @@ colored = "3.0.0"
concat-string = "1.0.1" concat-string = "1.0.1"
config = { version = "0.15.13", default-features = false, features = ["toml"] } config = { version = "0.15.13", default-features = false, features = ["toml"] }
figlet-rs = "0.1.5" figlet-rs = "0.1.5"
indoc = "2.0.6"
itoa = "1.0.15" itoa = "1.0.15"
parking_lot = "0.12.4" parking_lot = "0.12.4"
paste = { package = "pastey", version = "0.1.0" } paste = { package = "pastey", version = "0.1.0" }

View file

@ -138,7 +138,7 @@ pub type Weight = i8;
// API ********************************************************************************************* // API *********************************************************************************************
// Funciones y macros útiles. // Macros y funciones útiles.
pub mod util; pub mod util;
// Carga las opciones de configuración. // Carga las opciones de configuración.
pub mod config; pub mod config;

View file

@ -1,4 +1,4 @@
//! Funciones y macros útiles. //! Macros y funciones útiles.
use crate::trace; use crate::trace;
@ -6,67 +6,7 @@ use std::env;
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
// FUNCIONES ÚTILES ******************************************************************************** // MACROS INTEGRADAS *******************************************************************************
/// Resuelve y valida la ruta de un directorio existente, devolviendo una ruta absoluta.
///
/// - Si la ruta es relativa, se resuelve respecto al directorio del proyecto según la variable de
/// entorno `CARGO_MANIFEST_DIR` (si existe) o, en su defecto, respecto al directorio actual de
/// trabajo.
/// - Normaliza y valida la ruta final (resuelve `.`/`..` y enlaces simbólicos).
/// - Devuelve error si la ruta no existe o no es un directorio.
///
/// # Ejemplos
///
/// ```rust,no_run
/// use pagetop::prelude::*;
///
/// // Ruta relativa, se resuelve respecto a CARGO_MANIFEST_DIR o al directorio actual (`cwd`).
/// println!("{:#?}", util::resolve_absolute_dir("documents"));
///
/// // Ruta absoluta, se normaliza y valida tal cual.
/// println!("{:#?}", util::resolve_absolute_dir("/var/www"));
/// ```
pub fn resolve_absolute_dir<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
let path = path.as_ref();
let candidate = if path.is_absolute() {
path.to_path_buf()
} else {
// Directorio base CARGO_MANIFEST_DIR si está disponible; o current_dir() en su defecto.
env::var_os("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.or_else(|| env::current_dir().ok())
.unwrap_or_else(|| PathBuf::from("."))
.join(path)
};
// Resuelve `.`/`..`, enlaces simbólicos y obtiene la ruta absoluta en un único paso.
let absolute_dir = candidate.canonicalize()?;
// Asegura que realmente es un directorio existente.
if absolute_dir.is_dir() {
Ok(absolute_dir)
} else {
Err({
let msg = format!("Path \"{}\" is not a directory", absolute_dir.display());
trace::warn!(msg);
io::Error::new(io::ErrorKind::InvalidInput, msg)
})
}
}
/// **Obsoleto desde la versión 0.3.0**: usar [`resolve_absolute_dir()`] en su lugar.
#[deprecated(since = "0.3.0", note = "Use `resolve_absolute_dir()` instead")]
pub fn absolute_dir<P, Q>(root_path: P, relative_path: Q) -> io::Result<PathBuf>
where
P: AsRef<Path>,
Q: AsRef<Path>,
{
resolve_absolute_dir(root_path.as_ref().join(relative_path.as_ref()))
}
// MACROS ÚTILES ***********************************************************************************
#[doc(hidden)] #[doc(hidden)]
pub use paste::paste; pub use paste::paste;
@ -74,6 +14,10 @@ pub use paste::paste;
#[doc(hidden)] #[doc(hidden)]
pub use concat_string::concat_string; pub use concat_string::concat_string;
pub use indoc::{concatdoc, formatdoc, indoc};
// MACROS ÚTILES ***********************************************************************************
#[macro_export] #[macro_export]
/// Macro para construir una colección de pares clave-valor. /// Macro para construir una colección de pares clave-valor.
/// ///
@ -253,3 +197,63 @@ macro_rules! join_strict {
} }
}}; }};
} }
// FUNCIONES ÚTILES ********************************************************************************
/// Resuelve y valida la ruta de un directorio existente, devolviendo una ruta absoluta.
///
/// - Si la ruta es relativa, se resuelve respecto al directorio del proyecto según la variable de
/// entorno `CARGO_MANIFEST_DIR` (si existe) o, en su defecto, respecto al directorio actual de
/// trabajo.
/// - Normaliza y valida la ruta final (resuelve `.`/`..` y enlaces simbólicos).
/// - Devuelve error si la ruta no existe o no es un directorio.
///
/// # Ejemplos
///
/// ```rust,no_run
/// use pagetop::prelude::*;
///
/// // Ruta relativa, se resuelve respecto a CARGO_MANIFEST_DIR o al directorio actual (`cwd`).
/// println!("{:#?}", util::resolve_absolute_dir("documents"));
///
/// // Ruta absoluta, se normaliza y valida tal cual.
/// println!("{:#?}", util::resolve_absolute_dir("/var/www"));
/// ```
pub fn resolve_absolute_dir<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
let path = path.as_ref();
let candidate = if path.is_absolute() {
path.to_path_buf()
} else {
// Directorio base CARGO_MANIFEST_DIR si está disponible; o current_dir() en su defecto.
env::var_os("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.or_else(|| env::current_dir().ok())
.unwrap_or_else(|| PathBuf::from("."))
.join(path)
};
// Resuelve `.`/`..`, enlaces simbólicos y obtiene la ruta absoluta en un único paso.
let absolute_dir = candidate.canonicalize()?;
// Asegura que realmente es un directorio existente.
if absolute_dir.is_dir() {
Ok(absolute_dir)
} else {
Err({
let msg = format!("Path \"{}\" is not a directory", absolute_dir.display());
trace::warn!(msg);
io::Error::new(io::ErrorKind::InvalidInput, msg)
})
}
}
/// **Obsoleto desde la versión 0.3.0**: usar [`resolve_absolute_dir()`] en su lugar.
#[deprecated(since = "0.3.0", note = "Use `resolve_absolute_dir()` instead")]
pub fn absolute_dir<P, Q>(root_path: P, relative_path: Q) -> io::Result<PathBuf>
where
P: AsRef<Path>,
Q: AsRef<Path>,
{
resolve_absolute_dir(root_path.as_ref().join(relative_path.as_ref()))
}