summaryrefslogtreecommitdiffstats
path: root/src/command/import.rs
blob: 5ece13a8d90475b90496ed8dcf6e3eda4eafec81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::env;
use std::path::PathBuf;

use eyre::{eyre, Result};
use home::home_dir;
use structopt::StructOpt;

use crate::local::database::{Database, SqliteDatabase};
use crate::local::history::History;
use crate::local::import::ImportZsh;
use indicatif::ProgressBar;

#[derive(StructOpt)]
pub enum ImportCmd {
    #[structopt(
        about="import history for the current shell",
        aliases=&["a", "au", "aut"],
    )]
    Auto,

    #[structopt(
        about="import history from the zsh history file",
        aliases=&["z", "zs"],
    )]
    Zsh,
}

impl ImportCmd {
    fn import_zsh(&self, db: &mut SqliteDatabase) -> Result<()> {
        // oh-my-zsh sets HISTFILE=~/.zhistory
        // zsh has no default value for this var, but uses ~/.zhistory.
        // we could maybe be smarter about this in the future :)

        let histpath = env::var("HISTFILE");

        let histpath = match histpath {
            Ok(p) => PathBuf::from(p),
            Err(_) => {
                let mut home = home_dir().unwrap();
                home.push(".zhistory");

                home
            }
        };

        if !histpath.exists() {
            return Err(eyre!(
                "Could not find history file at {}, try setting $HISTFILE",
                histpath.to_str().unwrap()
            ));
        }

        let zsh = ImportZsh::new(histpath.to_str().unwrap())?;

        let progress = ProgressBar::new(zsh.loc);

        let buf_size = 100;
        let mut buf = Vec::<History>::with_capacity(buf_size);

        for i in zsh {
            match i {
                Ok(h) => {
                    buf.push(h);
                }
                Err(e) => {
                    error!("{}", e);
                    continue;
                }
            }

            if buf.len() == buf_size {
                db.save_bulk(&buf)?;
                progress.inc(buf.len() as u64);

                buf = Vec::<History>::with_capacity(buf_size);
            }
        }

        if buf.len() > 0 {
            db.save_bulk(&buf)?;
            progress.inc(buf.len() as u64);
        }

        progress.finish_with_message("Imported history!");

        Ok(())
    }

    pub fn run(&self, db: &mut SqliteDatabase) -> Result<()> {
        match self {
            ImportCmd::Auto => {
                let shell = env::var("SHELL").unwrap_or(String::from("NO_SHELL"));

                match shell.as_str() {
                    "/bin/zsh" => self.import_zsh(db),

                    _ => {
                        println!("cannot import {} history", shell);
                        Ok(())
                    }
                }
            }

            ImportCmd::Zsh => Ok(()),
        }
    }
}