Get distro name from neofetch

This commit is contained in:
Teoh Han Hui 2024-06-27 19:18:08 +08:00
parent 290445110d
commit ae1f6a2b3f
No known key found for this signature in database
GPG key ID: D43E2BABAF97DCAE
8 changed files with 157 additions and 7 deletions

2
.cargo/config.toml Normal file
View file

@ -0,0 +1,2 @@
[env]
CARGO_WORKSPACE_DIR = { value = "", relative = true }

7
Cargo.lock generated
View file

@ -125,6 +125,7 @@ dependencies = [
"indexmap",
"log",
"rgb",
"shell-words",
"strum",
]
@ -180,6 +181,12 @@ version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "shell-words"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]]
name = "strum"
version = "0.26.3"

View file

@ -20,4 +20,5 @@ env_logger = { version = "0.11.3", default-features = false }
indexmap = { version = "2.2.6", default-features = false }
log = { version = "0.4.21", default-features = false }
rgb = { version = "0.8.37", default-features = false }
shell-words = { version = "1.1.0", default-features = false }
strum = { version = "0.26.3", default-features = false }

View file

@ -17,6 +17,7 @@ env_logger = { workspace = true, features = ["auto-color", "humantime", "unstabl
indexmap = { workspace = true, features = ["std"] }
log = { workspace = true, features = ["kv"] }
rgb = { workspace = true, features = [] }
shell-words = { workspace = true, features = ["std"] }
strum = { workspace = true, features = ["derive", "std"] }
[features]

View file

@ -1,5 +1,6 @@
use anyhow::Result;
use anyhow::{Context, Result};
use hyfetch::cli_options::options;
use hyfetch::neofetch_util::get_distro_ascii;
use log::debug;
fn main() -> Result<()> {
@ -10,5 +11,15 @@ fn main() -> Result<()> {
// TODO
if options.test_print {
println!(
"{}",
get_distro_ascii(None).context("Failed to get distro ascii")?
);
return Ok(());
}
// TODO
Ok(())
}

View file

@ -1,6 +1,7 @@
use std::path::PathBuf;
use std::str::FromStr;
use anyhow::Context;
#[cfg(feature = "autocomplete")]
use bpaf::ShellComp;
use bpaf::{construct, long, OptionParser, Parser};
@ -16,7 +17,7 @@ pub struct Options {
pub preset: Option<Preset>,
pub mode: Option<AnsiMode>,
pub backend: Option<Backend>,
pub backend_args: Option<String>,
pub backend_args: Vec<String>,
pub colors_scale: Option<f32>,
pub colors_set_lightness: Option<f32>,
pub colors_use_overlay: bool,
@ -47,7 +48,9 @@ PRESET={{{}}}",
.argument("PRESET");
#[cfg(feature = "autocomplete")]
let preset = preset.complete(complete_preset);
let preset = preset.parse(|s| Preset::from_str(&s)).optional();
let preset = preset
.parse(|s| Preset::from_str(&s).with_context(|| format!("Failed to parse preset `{s}`")))
.optional();
let mode = long("mode")
.short('m')
.help(&*format!(
@ -58,7 +61,9 @@ MODE={{{}}}",
.argument("MODE");
#[cfg(feature = "autocomplete")]
let mode = mode.complete(complete_mode);
let mode = mode.parse(|s| AnsiMode::from_str(&s)).optional();
let mode = mode
.parse(|s| AnsiMode::from_str(&s).with_context(|| format!("Failed to parse mode `{s}`")))
.optional();
let backend = long("backend")
.short('b')
.help(&*format!(
@ -69,11 +74,14 @@ BACKEND={{{}}}",
.argument("BACKEND");
#[cfg(feature = "autocomplete")]
let backend = backend.complete(complete_backend);
let backend = backend.parse(|s| Backend::from_str(&s)).optional();
let backend = backend
.parse(|s| Backend::from_str(&s).with_context(|| format!("Failed to parse backend `{s}`")))
.optional();
let backend_args = long("args")
.help("Additional arguments pass-through to backend")
.argument("ARGS")
.optional();
.argument::<String>("ARGS")
.parse(|s| shell_words::split(&s).context("Failed to split args for shell"))
.fallback(vec![]);
let colors_scale = long("c-scale")
.help("Lighten colors by a multiplier")
.argument("SCALE")

View file

@ -1,4 +1,5 @@
pub mod cli_options;
pub mod color_util;
pub mod neofetch_util;
pub mod presets;
pub mod types;

View file

@ -0,0 +1,119 @@
use std::ffi::OsStr;
#[cfg(unix)]
use std::os::unix::process::ExitStatusExt as _;
use std::path::PathBuf;
use std::process::Command;
use std::{env, fmt};
use anyhow::{anyhow, Context, Result};
use log::debug;
/// Gets the absolute path of the neofetch command.
pub fn get_command_path() -> Result<PathBuf> {
if let Some(workspace_dir) = option_env!("CARGO_WORKSPACE_DIR") {
let path = PathBuf::from(workspace_dir);
if path.exists() {
let path = path.join("neofetch");
match path.try_exists() {
Ok(true) => {
return path.canonicalize().context("Failed to canonicalize path");
},
Ok(false) => {
Err(anyhow!("{path:?} does not exist or is not readable"))?;
},
Err(err) => {
Err(err)
.with_context(|| format!("Failed to check for existence of {path:?}"))?;
},
}
}
}
let Ok(path_env) = env::var("PATH") else {
return Err(anyhow!("`PATH` env var is not set or invalid"));
};
for search_path in env::split_paths(&path_env) {
let path = search_path.join("neowofetch");
if !path.is_file() {
continue;
}
return path.canonicalize().context("Failed to canonicalize path");
}
Err(anyhow!("neofetch command not found"))
}
pub fn get_distro_ascii(distro: Option<String>) -> Result<String> {
// TODO
let distro = if let Some(distro) = distro {
distro
} else {
get_distro_name().context("Failed to get distro name")?
};
debug!(distro:% = distro; "resolved distro name");
todo!()
}
/// Runs neofetch command, returning the piped stdout output.
fn run_neofetch_command_piped<S>(args: &[S]) -> Result<String>
where
S: AsRef<OsStr> + fmt::Debug,
{
let mut command = make_neofetch_command(args).context("Failed to make neofetch command")?;
let output = command
.output()
.context("Failed to execute neofetch as child process")?;
debug!(output:?, args:?; "neofetch output");
if !output.status.success() {
let err = if let Some(code) = output.status.code() {
anyhow!("neofetch process exited with status code: {code}")
} else {
#[cfg(unix)]
{
anyhow!(
"neofetch process terminated by signal: {}",
output
.status
.signal()
.expect("either one of status code or signal should be set")
)
}
#[cfg(not(unix))]
unimplemented!("status code not expected to be `None` on non-Unix platforms")
};
Err(err)?;
}
let out = String::from_utf8(output.stdout)
.context("Failed to process neofetch output as it contains invalid UTF-8")?
.trim()
.to_owned();
Ok(out)
}
fn make_neofetch_command<S>(args: &[S]) -> Result<Command>
where
S: AsRef<OsStr>,
{
#[cfg(not(windows))]
{
let mut command = Command::new("bash");
command.arg(get_command_path().context("Failed to get neofetch command path")?);
command.args(args);
Ok(command)
}
#[cfg(windows)]
{
todo!()
}
}
fn get_distro_name() -> Result<String> {
run_neofetch_command_piped(&["ascii_distro_name"])
.context("Failed to get distro name from neofetch")
}