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

Code before:
    ("trim_end", Unary(trim_end)),
    ("trim_end_match", Binary(trim_end_match)),
    ("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(ctx: &FunctionContext, path: &str) -> Result<String, String> {
  let abs_path_unchecked = ctx.search.working_directory.join(path).lexiclean();
  match abs_path_unchecked.to_str() {
    Some(wd) => Ok(wd.to_string()),
    None => Err(format!(
      "Directory path is not valid unicode: {}",
      abs_path_unchecked.to_string_lossy()
    )),
  }
}

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());
  }


Review comment (suggestion):
I think `absolute_path` is a little clearer, and the context should be named `context` to match the other functions.

```suggestion
fn absolute_path(context: &FunctionContext, path: &str) -> Result<String, String> {
```

Code after:
    ("trim_end", Unary(trim_end)),
    ("trim_end_match", Binary(trim_end_match)),
    ("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());
  }