You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
phetch/src/utils.rs

91 lines
2.5 KiB
Rust

4 years ago
//! Helper functions and macros.
use std::{
io::{Result, Write},
process::{self, Stdio},
};
4 years ago
4 years ago
/// Debug macro that appends a line to `phetch.log`.
/// Useful for printf-style debugging - add your `log!()` calls,
/// and `tail -f phetch.log` while running phetch to peek inside.
5 years ago
#[allow(unused_macros)]
macro_rules! log {
($e:expr) => {{
if cfg!(debug_assertions) {
if let Ok(mut file) = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open("phetch.log")
{
use std::io::prelude::*;
5 years ago
file.write($e.as_ref());
file.write(b"\n");
}
}
}};
($e:expr, $($y:expr),*) => {
if cfg!(debug_assertions) {
log!(format!($e, $($y),*));
}
};
}
4 years ago
4 years ago
/// Creates an Other kind of io::Error.
5 years ago
macro_rules! error {
($e:expr) => {
std::io::Error::new(std::io::ErrorKind::Other, $e)
};
($e:expr, $($y:expr),*) => {
error!(format!($e, $($y),*));
};
}
5 years ago
4 years ago
/// Number of bytes in a human-ish readable format.
5 years ago
pub fn human_bytes(bytes: usize) -> String {
let (count, tag) = if bytes < 1000 {
(bytes, " bytes")
} else if bytes < 1_000_000 {
(bytes / 1000, "Kb")
} else if bytes < 1_000_000_000 {
(bytes / 1_000_000, "Mb")
} else {
5 years ago
(bytes / 1_000_000_000, "Gb")
5 years ago
};
format!("{}{}", count, tag)
}
/// Copies data to the system clipboard, if possible.
/// Uses `pbcopy` on macOS or `xclip -sel clip` on Linux.
pub fn copy_to_clipboard(data: &str) -> Result<()> {
#[cfg(target_os = "macos")]
let mut cmd = process::Command::new("pbcopy");
#[cfg(not(target_os = "macos"))]
let mut cmd = process::Command::new("xclip").args(&["-sel", "clip"]);
cmd.stdin(Stdio::piped()).spawn().and_then(|mut child| {
let child_stdin = child.stdin.as_mut().unwrap();
child_stdin.write_all(data.as_bytes())
})
}
/// Used to open non-Gopher URLs.
/// Runs `open` command on macOS or `xdg-open` on Linux.
pub fn open_external(url: &str) -> Result<()> {
#[cfg(target_os = "macos")]
let cmd = "open";
#[cfg(not(target_os = "macos"))]
let cmd = "xdg-open";
let output = process::Command::new(cmd).arg(url).output()?;
if output.stderr.is_empty() {
Ok(())
} else {
Err(error!(
"`open` error: {}",
String::from_utf8(output.stderr)
.unwrap_or_else(|_| "?".into())
.trim_end()
))
}
}