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

Code before:
  }
}

fn just_executable(_context: &FunctionContext) -> Result<String, String> {
  let exe_path =
    std::env::current_exe().map_err(|e| format!("Error getting current executable: {}", e))?;

  exe_path.to_str().map(str::to_owned).ok_or_else(|| {
    format!(
      "Executable path is not valid unicode: {}",
      exe_path.to_string_lossy()
    )
  })
}

fn file_name(_context: &FunctionContext, file_path: &str) -> Result<String, String> {
  Utf8Path::new(file_path)
    .file_name()
    .map(std::borrow::ToOwned::to_owned)
    .ok_or_else(|| format!("Cannot get file name from `{}`", file_path))
}

fn parent_directory(_context: &FunctionContext, file_path: &str) -> Result<String, String> {
  Utf8Path::new(file_path)
    .parent()
    .map(Utf8Path::as_str)
    .map(std::borrow::ToOwned::to_owned)
    .ok_or_else(|| format!("Cannot get parent directory from `{}`", file_path))
}

fn file_stem(_context: &FunctionContext, file_path: &str) -> Result<String, String> {
  Utf8Path::new(file_path)
    .file_stem()
    .map(std::borrow::ToOwned::to_owned)
    .ok_or_else(|| format!("Cannot get file stem from `{}`", file_path))
}

fn without_extension(_context: &FunctionContext, file_path: &str) -> Result<String, String> {
  let path = Utf8Path::new(file_path);
  path
    .parent()
    .map(Utf8Path::as_str)
    .zip(path.file_stem())
    .map(|(p, n)| format!("{}/{}", p, n))
    .ok_or_else(|| format!("Cannot remove extension from `{}`", file_path))
}

fn extension(_context: &FunctionContext, file_path: &str) -> Result<String, String> {
  Utf8Path::new(file_path)
    .extension()
    .map(std::borrow::ToOwned::to_owned)

Review comment (suggestion):
I think these two maps can be replaced with `Utf8Path::to_string`

Code after:
}

fn just_executable(_context: &FunctionContext) -> Result<String, String> {
  let exe_path =
    std::env::current_exe().map_err(|e| format!("Error getting current executable: {}", e))?;

  exe_path.to_str().map(str::to_owned).ok_or_else(|| {
    format!(
      "Executable path is not valid unicode: {}",
      exe_path.to_string_lossy()
    )
  })
}

fn file_name(_context: &FunctionContext, path: &str) -> Result<String, String> {
  Utf8Path::new(path)
    .file_name()
    .map(str::to_owned)
    .ok_or_else(|| format!("Could not extract file name from `{}`", path))
}

fn parent_directory(_context: &FunctionContext, path: &str) -> Result<String, String> {
  Utf8Path::new(path)
    .parent()
    .map(Utf8Path::to_string)
    .ok_or_else(|| format!("Could not extract parent directory from `{}`", path))
}

fn file_stem(_context: &FunctionContext, path: &str) -> Result<String, String> {
  Utf8Path::new(path)
    .file_stem()
    .map(str::to_owned)
    .ok_or_else(|| format!("Could not extract file stem from `{}`", path))
}

fn without_extension(_context: &FunctionContext, path: &str) -> Result<String, String> {
  let parent = Utf8Path::new(path)
    .parent()
    .ok_or_else(|| format!("Could not extract parent from `{}`", path))?;

  let file_stem = Utf8Path::new(path)
    .file_stem()
    .ok_or_else(|| format!("Could not extract file stem from `{}`", path))?;

  Ok(parent.join(file_stem).to_string())
}

fn extension(_context: &FunctionContext, path: &str) -> Result<String, String> {
  Utf8Path::new(path)
    .extension()
    .map(str::to_owned)