atuin_client/import/
nu.rs

1// import old shell history!
2// automatically hoover up all that we can find
3
4use std::path::PathBuf;
5
6use async_trait::async_trait;
7use directories::BaseDirs;
8use eyre::{eyre, Result};
9use time::OffsetDateTime;
10
11use super::{unix_byte_lines, Importer, Loader};
12use crate::history::History;
13use crate::import::read_to_end;
14
15#[derive(Debug)]
16pub struct Nu {
17    bytes: Vec<u8>,
18}
19
20fn get_histpath() -> Result<PathBuf> {
21    let base = BaseDirs::new().ok_or_else(|| eyre!("could not determine data directory"))?;
22    let config_dir = base.config_dir().join("nushell");
23
24    let histpath = config_dir.join("history.txt");
25    if histpath.exists() {
26        Ok(histpath)
27    } else {
28        Err(eyre!("Could not find history file."))
29    }
30}
31
32#[async_trait]
33impl Importer for Nu {
34    const NAME: &'static str = "nu";
35
36    async fn new() -> Result<Self> {
37        let bytes = read_to_end(get_histpath()?)?;
38        Ok(Self { bytes })
39    }
40
41    async fn entries(&mut self) -> Result<usize> {
42        Ok(super::count_lines(&self.bytes))
43    }
44
45    async fn load(self, h: &mut impl Loader) -> Result<()> {
46        let now = OffsetDateTime::now_utc();
47
48        let mut counter = 0;
49        for b in unix_byte_lines(&self.bytes) {
50            let s = match std::str::from_utf8(b) {
51                Ok(s) => s,
52                Err(_) => continue, // we can skip past things like invalid utf8
53            };
54
55            let cmd: String = s.replace("<\\n>", "\n");
56
57            let offset = time::Duration::nanoseconds(counter);
58            counter += 1;
59
60            let entry = History::import().timestamp(now - offset).command(cmd);
61
62            h.push(entry.build().into()).await?;
63        }
64
65        Ok(())
66    }
67}