osenv/src/main.rs

134 lines
3.8 KiB
Rust

extern crate clap;
use clap::{App, Arg, ArgMatches};
use isatty::stdout_isatty;
use std::env;
use std::fs::File;
use std::io::{prelude::*, BufReader};
use std::path::{Path, PathBuf};
fn current_args() -> String {
let mut out = String::from("osenv");
for argument in env::args().skip(1) {
out += format!(" {}", argument).as_str();
}
out
}
fn get_file(cmd: &ArgMatches) -> Option<PathBuf> {
let dir = cmd.value_of("directory")?;
let file = cmd.value_of("file")?;
let env = cmd.value_of("environment");
// If -env was specified, add it as a suffix
let filename = if env.is_some() {
format!("{}.{}", file, env.unwrap())
} else {
String::from(file)
};
// Join directory and file
Some(Path::new(dir).join(filename))
}
fn escape(raw: &str) -> String {
raw.replace("\"", "`\"")
}
fn main() -> std::io::Result<()> {
#[cfg(target_os = "macos")]
static OS_DEFAULT_SHELL: &str = "sh";
#[cfg(target_os = "linux")]
static OS_DEFAULT_SHELL: &str = "sh";
#[cfg(target_os = "windows")]
static OS_DEFAULT_SHELL: &str = "ps1";
let cmd = App::new("osenv")
.version("0.1")
.author("Alessandro Gatti <hamcha@crunchy.rocks>")
.about("Cross-platform env helper")
.arg(
Arg::with_name("directory")
.short("d")
.long("directory")
.value_name("DIRECTORY")
.help("Directory to scan for .env files")
.default_value(".")
.takes_value(true),
)
.arg(
Arg::with_name("file")
.short("f")
.long("file")
.value_name("ENVFILE")
.help("Env file")
.default_value(".env")
.takes_value(true),
)
.arg(
Arg::with_name("environment")
.short("e")
.long("env")
.value_name("ENVIRONMENT")
.help("If provided, will look for .env.ENVIRONMENT")
.takes_value(true),
)
.arg(
Arg::with_name("shell")
.short("s")
.long("shell")
.help("Output format")
.takes_value(true)
.default_value(OS_DEFAULT_SHELL)
.possible_values(&["ps1", "sh"]),
)
.get_matches();
let path = get_file(&cmd).unwrap();
let shell = cmd.value_of("shell").unwrap();
if !path.exists() {
println!("{}: file not found", path.display());
std::process::exit(1);
}
let file = File::open(path)?;
let reader = BufReader::new(file);
// Print help messages if printing to terminal
if stdout_isatty() {
println!("# It looks like you are not running osenv properly");
match shell {
"ps1" => println!(
"# The proper command on Powershell is:\n# {} | iex",
current_args()
),
"sh" => println!(
"# The proper command on unix shells is:\n# eval $({})",
current_args()
),
_ => (),
}
}
for line in reader.lines() {
let envline = line.unwrap();
let idx = envline.find('=');
if idx.is_some() {
match shell {
"ps1" => {
// val needs to be shifted to remove the separator
println!(
"$env:{} = \"{}\"; ",
envline.get(..idx.unwrap()).unwrap(),
escape(envline.get(idx.unwrap() + 1..).unwrap())
)
}
"sh" => println!("export {}", envline),
_ => (),
}
}
}
Ok(())
}