zoxide/src/util.rs

92 lines
2.4 KiB
Rust

use crate::db::DB;
use crate::dir::Dir;
use crate::env::Env;
use crate::types::Epoch;
use anyhow::{anyhow, bail, Context, Result};
use std::io::{Read, Write};
use std::process::{Command, Stdio};
use std::time::SystemTime;
pub fn get_db(env: &Env) -> Result<DB> {
let path = env
.data
.as_ref()
.ok_or_else(|| anyhow!("could not locate database file"))?;
DB::open(path)
}
pub fn get_current_time() -> Result<Epoch> {
let current_time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.with_context(|| "system clock set to invalid time")?
.as_secs();
Ok(current_time as Epoch)
}
pub fn fzf_helper(now: Epoch, mut dirs: Vec<Dir>) -> Result<Option<String>> {
let mut fzf = Command::new("fzf")
.arg("-n2..")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.with_context(|| anyhow!("could not launch fzf"))?;
let fzf_stdin = fzf
.stdin
.as_mut()
.ok_or_else(|| anyhow!("could not connect to fzf stdin"))?;
for dir in dirs.iter_mut() {
dir.rank = dir.get_frecency(now);
}
dirs.sort_by_key(|dir| std::cmp::Reverse(dir.rank as i64));
for dir in dirs.iter() {
// ensure that frecency fits in 4 characters
let frecency = if dir.rank > 9999.0 {
9999
} else if dir.rank > 0.0 {
dir.rank as i32
} else {
0
};
writeln!(fzf_stdin, "{:>4} {}", frecency, dir.path)
.with_context(|| anyhow!("could not write into fzf stdin"))?;
}
let fzf_stdout = fzf
.stdout
.as_mut()
.ok_or_else(|| anyhow!("could not connect to fzf stdout"))?;
let mut output = String::new();
fzf_stdout
.read_to_string(&mut output)
.with_context(|| anyhow!("could not read from fzf stdout"))?;
let status = fzf.wait().with_context(|| "could not wait on fzf")?;
match status.code() {
// normal exit
Some(0) => match output.get(12..) {
Some(path) => Ok(Some(path.to_string())),
None => bail!("fzf returned invalid output"),
},
// no match
Some(1) => Ok(None),
// error
Some(2) => bail!("fzf returned an error"),
// terminated by a signal
Some(128..=254) | None => bail!("fzf was terminated"),
// unknown
_ => bail!("fzf returned an unknown error"),
}
}