Repository: casey/just
File: src/function.rs (Rust)

Code before:
    ("trim_end_matches", Binary(trim_end_matches)),
    ("trim_start", Unary(trim_start)),
    ("trim_start_match", Binary(trim_start_match)),
    ("trim_start_matches", Binary(trim_start_matches)),
    ("uppercase", Unary(uppercase)),
    ("without_extension", Unary(without_extension)),
  ]
  .into_iter()
  .collect();
}

impl Function {
  pub(crate) fn argc(&self) -> Range<usize> {
    match *self {
      Nullary(_) => 0..0,
      Unary(_) => 1..1,
      Binary(_) => 2..2,
      BinaryPlus(_) => 2..usize::MAX,
      Ternary(_) => 3..3,
    }
  }
}

fn abs_path(context: &FunctionContext, path: &str) -> Result<String, String> {
  let corrected_path = context.invocation_directory.join(path);
  match corrected_path.canonicalize() {
    Ok(p) => Ok(p.to_string_lossy().into()),
    Err(e) => Err(format!("Error getting absolute path: {}", e)),
  }
}

fn arch(_context: &FunctionContext) -> Result<String, String> {
  Ok(target::arch().to_owned())
}

fn clean(_context: &FunctionContext, path: &str) -> Result<String, String> {
  Ok(Path::new(path).lexiclean().to_str().unwrap().to_owned())
}

fn env_var(context: &FunctionContext, key: &str) -> Result<String, String> {
  use std::env::VarError::*;

  if let Some(value) = context.dotenv.get(key) {
    return Ok(value.clone());
  }

  match env::var(key) {
    Err(NotPresent) => Err(format!("environment variable `{}` not present", key)),
    Err(NotUnicode(os_string)) => Err(format!(
      "environment variable `{}` not unicode: {:?}",
      key, os_string

Review comment (suggestion):
Call `.lexiclean()` instead of canonicalize. The paths that canonicalize produces are a bit weird.

Code after:
    ("trim_end_matches", Binary(trim_end_matches)),
    ("trim_start", Unary(trim_start)),
    ("trim_start_match", Binary(trim_start_match)),
    ("trim_start_matches", Binary(trim_start_matches)),
    ("uppercase", Unary(uppercase)),
    ("without_extension", Unary(without_extension)),
  ]
  .into_iter()
  .collect();
}

impl Function {
  pub(crate) fn argc(&self) -> Range<usize> {
    match *self {
      Nullary(_) => 0..0,
      Unary(_) => 1..1,
      Binary(_) => 2..2,
      BinaryPlus(_) => 2..usize::MAX,
      Ternary(_) => 3..3,
    }
  }
}

fn absolute_path(context: &FunctionContext, path: &str) -> Result<String, String> {
  let abs_path_unchecked = context.search.working_directory.join(path).lexiclean();
  match abs_path_unchecked.to_str() {
    Some(absolute_path) => Ok(absolute_path.to_owned()),
    None => Err(format!(
      "Working directory is not valid unicode: {}",
      context.search.working_directory.display()
    )),
  }
}

fn arch(_context: &FunctionContext) -> Result<String, String> {
  Ok(target::arch().to_owned())
}

fn clean(_context: &FunctionContext, path: &str) -> Result<String, String> {
  Ok(Path::new(path).lexiclean().to_str().unwrap().to_owned())
}

fn env_var(context: &FunctionContext, key: &str) -> Result<String, String> {
  use std::env::VarError::*;

  if let Some(value) = context.dotenv.get(key) {
    return Ok(value.clone());
  }

  match env::var(key) {
    Err(NotPresent) => Err(format!("environment variable `{}` not present", key)),