history list (#340)
This commit is contained in:
parent
2fd9651dea
commit
7f5310a1aa
11 changed files with 175 additions and 239 deletions
101
Cargo.lock
generated
101
Cargo.lock
generated
|
@ -93,7 +93,6 @@ dependencies = [
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tabwriter",
|
|
||||||
"termion",
|
"termion",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
@ -115,6 +114,7 @@ dependencies = [
|
||||||
"directories",
|
"directories",
|
||||||
"eyre",
|
"eyre",
|
||||||
"fs-err",
|
"fs-err",
|
||||||
|
"hex",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
|
@ -123,9 +123,9 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"rust-crypto",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"shellexpand",
|
"shellexpand",
|
||||||
"sodiumoxide",
|
"sodiumoxide",
|
||||||
"sql-builder",
|
"sql-builder",
|
||||||
|
@ -141,7 +141,6 @@ name = "atuin-common"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"rust-crypto",
|
|
||||||
"serde",
|
"serde",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
@ -160,8 +159,7 @@ dependencies = [
|
||||||
"eyre",
|
"eyre",
|
||||||
"fs-err",
|
"fs-err",
|
||||||
"http",
|
"http",
|
||||||
"rand 0.8.5",
|
"rand",
|
||||||
"rust-crypto",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sodiumoxide",
|
"sodiumoxide",
|
||||||
|
@ -724,12 +722,6 @@ version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e"
|
checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fuchsia-cprng"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.21"
|
version = "0.3.21"
|
||||||
|
@ -794,12 +786,6 @@ dependencies = [
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gcc"
|
|
||||||
version = "0.3.55"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
@ -1616,29 +1602,6 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.3.23"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"rand 0.4.6",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
|
||||||
dependencies = [
|
|
||||||
"fuchsia-cprng",
|
|
||||||
"libc",
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
"rdrand",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
@ -1647,7 +1610,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"rand_core 0.6.3",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1657,24 +1620,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core 0.6.3",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
|
@ -1684,15 +1632,6 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rdrand"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
|
@ -1834,19 +1773,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rust-crypto"
|
|
||||||
version = "0.2.36"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
|
||||||
dependencies = [
|
|
||||||
"gcc",
|
|
||||||
"libc",
|
|
||||||
"rand 0.3.23",
|
|
||||||
"rustc-serialize",
|
|
||||||
"time",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-ini"
|
name = "rust-ini"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
|
@ -1857,12 +1783,6 @@ dependencies = [
|
||||||
"ordered-multimap",
|
"ordered-multimap",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-serialize"
|
|
||||||
version = "0.3.24"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.19.1"
|
version = "0.19.1"
|
||||||
|
@ -2172,7 +2092,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"paste",
|
"paste",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand 0.8.5",
|
"rand",
|
||||||
"rustls 0.19.1",
|
"rustls 0.19.1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -2259,15 +2179,6 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
|
checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tabwriter"
|
|
||||||
version = "1.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "36205cfc997faadcc4b0b87aaef3fbedafe20d38d4959a7ca6ff803564051111"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-width",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
|
|
@ -60,7 +60,6 @@ chrono-english = "0.1.4"
|
||||||
cli-table = "0.4"
|
cli-table = "0.4"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
humantime = "2.1.0"
|
humantime = "2.1.0"
|
||||||
tabwriter = "1.2.1"
|
|
||||||
crossbeam-channel = "0.5.1"
|
crossbeam-channel = "0.5.1"
|
||||||
clap = { version = "3.1.11", features = ["derive"] }
|
clap = { version = "3.1.11", features = ["derive"] }
|
||||||
clap_complete = "3.1.2"
|
clap_complete = "3.1.2"
|
||||||
|
|
|
@ -16,7 +16,8 @@ sync = [
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
"sodiumoxide",
|
"sodiumoxide",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rust-crypto",
|
"sha2",
|
||||||
|
"hex",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"base64",
|
"base64",
|
||||||
]
|
]
|
||||||
|
@ -56,7 +57,8 @@ reqwest = { version = "0.11", features = [
|
||||||
"json",
|
"json",
|
||||||
"rustls-tls",
|
"rustls-tls",
|
||||||
], default-features = false, optional = true }
|
], default-features = false, optional = true }
|
||||||
rust-crypto = { version = "^0.2", optional = true }
|
hex = { version = "0.4", optional = true }
|
||||||
|
sha2 = { version = "0.10", optional = true }
|
||||||
rmp-serde = { version = "1.0.0", optional = true }
|
rmp-serde = { version = "1.0.0", optional = true }
|
||||||
base64 = { version = "0.13.0", optional = true }
|
base64 = { version = "0.13.0", optional = true }
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ use atuin_common::api::{
|
||||||
AddHistoryRequest, CountResponse, LoginRequest, LoginResponse, RegisterResponse,
|
AddHistoryRequest, CountResponse, LoginRequest, LoginResponse, RegisterResponse,
|
||||||
SyncHistoryResponse,
|
SyncHistoryResponse,
|
||||||
};
|
};
|
||||||
use atuin_common::utils::hash_str;
|
|
||||||
|
|
||||||
use crate::encryption::{decode_key, decrypt};
|
use crate::encryption::{decode_key, decrypt};
|
||||||
use crate::history::History;
|
use crate::history::History;
|
||||||
|
use crate::sync::hash_str;
|
||||||
|
|
||||||
static APP_USER_AGENT: &str = concat!("atuin/", env!("CARGO_PKG_VERSION"),);
|
static APP_USER_AGENT: &str = concat!("atuin/", env!("CARGO_PKG_VERSION"),);
|
||||||
|
|
||||||
|
|
|
@ -45,4 +45,8 @@ impl History {
|
||||||
hostname,
|
hostname,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn success(&self) -> bool {
|
||||||
|
self.exit == 0 || self.duration == -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,13 +3,20 @@ use std::convert::TryInto;
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
|
|
||||||
use atuin_common::{api::AddHistoryRequest, utils::hash_str};
|
use atuin_common::api::AddHistoryRequest;
|
||||||
|
|
||||||
use crate::api_client;
|
use crate::api_client;
|
||||||
use crate::database::Database;
|
use crate::database::Database;
|
||||||
use crate::encryption::{encrypt, load_encoded_key, load_key};
|
use crate::encryption::{encrypt, load_encoded_key, load_key};
|
||||||
use crate::settings::{Settings, HISTORY_PAGE_SIZE};
|
use crate::settings::{Settings, HISTORY_PAGE_SIZE};
|
||||||
|
|
||||||
|
pub fn hash_str(string: &str) -> String {
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(string.as_bytes());
|
||||||
|
hex::encode(hasher.finalize())
|
||||||
|
}
|
||||||
|
|
||||||
// Currently sync is kinda naive, and basically just pages backwards through
|
// Currently sync is kinda naive, and basically just pages backwards through
|
||||||
// history. This means newly added stuff shows up properly! We also just use
|
// history. This means newly added stuff shows up properly! We also just use
|
||||||
// the total count in each database to indicate whether a sync is needed.
|
// the total count in each database to indicate whether a sync is needed.
|
||||||
|
|
|
@ -11,7 +11,6 @@ repository = "https://github.com/ellie/atuin"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rust-crypto = "^0.2"
|
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
serde = { version = "1.0.126", features = ["derive"] }
|
serde = { version = "1.0.126", features = ["derive"] }
|
||||||
uuid = { version = "1.0", features = ["v4"] }
|
uuid = { version = "1.0", features = ["v4"] }
|
||||||
|
|
|
@ -3,15 +3,6 @@ use std::path::PathBuf;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub fn hash_str(string: &str) -> String {
|
|
||||||
use crypto::digest::Digest;
|
|
||||||
use crypto::sha2::Sha256;
|
|
||||||
let mut hasher = Sha256::new();
|
|
||||||
hasher.input_str(string);
|
|
||||||
|
|
||||||
hasher.result_str()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn uuid_v4() -> String {
|
pub fn uuid_v4() -> String {
|
||||||
Uuid::new_v4().as_simple().to_string()
|
Uuid::new_v4().as_simple().to_string()
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ serde_json = "1.0.75"
|
||||||
sodiumoxide = "0.2.6"
|
sodiumoxide = "0.2.6"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
rust-crypto = "^0.2"
|
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
sqlx = { version = "0.5", features = [ "runtime-tokio-rustls", "chrono", "postgres" ] }
|
sqlx = { version = "0.5", features = [ "runtime-tokio-rustls", "chrono", "postgres" ] }
|
||||||
async-trait = "0.1.49"
|
async-trait = "0.1.49"
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::Write;
|
use std::io::{StdoutLock, Write};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use tabwriter::TabWriter;
|
|
||||||
|
|
||||||
use atuin_client::database::{current_context, Database};
|
use atuin_client::database::{current_context, Database};
|
||||||
use atuin_client::history::History;
|
use atuin_client::history::History;
|
||||||
|
@ -53,44 +52,75 @@ pub enum Cmd {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_sign_loss)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub fn print_list(h: &[History], human: bool, cmd_only: bool) {
|
pub enum ListMode {
|
||||||
let mut writer = TabWriter::new(std::io::stdout()).padding(2);
|
Human,
|
||||||
|
CmdOnly,
|
||||||
|
Regular,
|
||||||
|
}
|
||||||
|
|
||||||
let lines = h.iter().rev().map(|h| {
|
impl ListMode {
|
||||||
|
pub const fn from_flags(human: bool, cmd_only: bool) -> Self {
|
||||||
if human {
|
if human {
|
||||||
let duration = humantime::format_duration(Duration::from_nanos(std::cmp::max(
|
ListMode::Human
|
||||||
h.duration, 0,
|
|
||||||
) as u64))
|
|
||||||
.to_string();
|
|
||||||
let duration: Vec<&str> = duration.split(' ').collect();
|
|
||||||
let duration = duration[0];
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{}\t{}\t{}\n",
|
|
||||||
h.timestamp.format("%Y-%m-%d %H:%M:%S"),
|
|
||||||
h.command.trim(),
|
|
||||||
duration,
|
|
||||||
)
|
|
||||||
} else if cmd_only {
|
} else if cmd_only {
|
||||||
format!("{}\n", h.command.trim())
|
ListMode::CmdOnly
|
||||||
} else {
|
} else {
|
||||||
format!(
|
ListMode::Regular
|
||||||
"{}\t{}\t{}\n",
|
|
||||||
h.timestamp.timestamp_nanos(),
|
|
||||||
h.command.trim(),
|
|
||||||
h.duration
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i in lines {
|
#[allow(clippy::cast_sign_loss)]
|
||||||
writer
|
pub fn print_list(h: &[History], list_mode: ListMode) {
|
||||||
.write_all(i.as_bytes())
|
let w = std::io::stdout();
|
||||||
.expect("failed to write to tab writer");
|
let mut w = w.lock();
|
||||||
|
|
||||||
|
match list_mode {
|
||||||
|
ListMode::Human => print_human_list(&mut w, h),
|
||||||
|
ListMode::CmdOnly => print_cmd_only(&mut w, h),
|
||||||
|
ListMode::Regular => print_regular(&mut w, h),
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.flush().expect("failed to flush tab writer");
|
w.flush().expect("failed to flush history");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
pub fn print_human_list(w: &mut StdoutLock, h: &[History]) {
|
||||||
|
for h in h.iter().rev() {
|
||||||
|
let duration =
|
||||||
|
humantime::format_duration(Duration::from_nanos(std::cmp::max(h.duration, 0) as u64))
|
||||||
|
.to_string();
|
||||||
|
let duration: Vec<&str> = duration.split(' ').collect();
|
||||||
|
let duration = duration[0];
|
||||||
|
|
||||||
|
let time = h.timestamp.format("%Y-%m-%d %H:%M:%S");
|
||||||
|
let cmd = h.command.trim();
|
||||||
|
|
||||||
|
writeln!(w, "{time} · {duration}\t{cmd}").expect("failed to write history");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
pub fn print_regular(w: &mut StdoutLock, h: &[History]) {
|
||||||
|
for h in h.iter().rev() {
|
||||||
|
let duration =
|
||||||
|
humantime::format_duration(Duration::from_nanos(std::cmp::max(h.duration, 0) as u64))
|
||||||
|
.to_string();
|
||||||
|
let duration: Vec<&str> = duration.split(' ').collect();
|
||||||
|
let duration = duration[0];
|
||||||
|
|
||||||
|
let time = h.timestamp.format("%Y-%m-%d %H:%M:%S");
|
||||||
|
let cmd = h.command.trim();
|
||||||
|
|
||||||
|
writeln!(w, "{time}\t{cmd}\t{duration}").expect("failed to write history");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_cmd_only(w: &mut StdoutLock, h: &[History]) {
|
||||||
|
for h in h.iter().rev() {
|
||||||
|
writeln!(w, "{}", h.command.trim()).expect("failed to write history");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cmd {
|
impl Cmd {
|
||||||
|
@ -195,14 +225,14 @@ impl Cmd {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
print_list(&history, *human, *cmd_only);
|
print_list(&history, ListMode::from_flags(*human, *cmd_only));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::Last { human, cmd_only } => {
|
Self::Last { human, cmd_only } => {
|
||||||
let last = db.last().await?;
|
let last = db.last().await?;
|
||||||
print_list(&[last], *human, *cmd_only);
|
print_list(&[last], ListMode::from_flags(*human, *cmd_only));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ use atuin_client::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::event::{Event, Events};
|
use super::event::{Event, Events};
|
||||||
|
use super::history::ListMode;
|
||||||
|
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
@ -73,21 +74,33 @@ impl Cmd {
|
||||||
db: &mut (impl Database + Send + Sync),
|
db: &mut (impl Database + Send + Sync),
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
run(
|
if self.interactive {
|
||||||
settings,
|
let item = select_history(
|
||||||
self.cwd,
|
&self.query,
|
||||||
self.exit,
|
settings.search_mode,
|
||||||
self.interactive,
|
settings.filter_mode,
|
||||||
self.human,
|
settings.style,
|
||||||
self.exclude_exit,
|
db,
|
||||||
self.exclude_cwd,
|
)
|
||||||
self.before,
|
.await?;
|
||||||
self.after,
|
eprintln!("{}", item);
|
||||||
self.cmd_only,
|
} else {
|
||||||
&self.query,
|
let list_mode = ListMode::from_flags(self.human, self.cmd_only);
|
||||||
db,
|
run_non_interactive(
|
||||||
)
|
settings,
|
||||||
.await
|
list_mode,
|
||||||
|
self.cwd,
|
||||||
|
self.exit,
|
||||||
|
self.exclude_exit,
|
||||||
|
self.exclude_cwd,
|
||||||
|
self.before,
|
||||||
|
self.after,
|
||||||
|
&self.query,
|
||||||
|
db,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +209,7 @@ impl State {
|
||||||
|
|
||||||
let duration = Span::styled(
|
let duration = Span::styled(
|
||||||
duration,
|
duration,
|
||||||
Style::default().fg(if m.exit == 0 || m.duration == -1 {
|
Style::default().fg(if m.success() {
|
||||||
Color::Green
|
Color::Green
|
||||||
} else {
|
} else {
|
||||||
Color::Red
|
Color::Red
|
||||||
|
@ -565,117 +578,98 @@ async fn select_history(
|
||||||
// This is supposed to more-or-less mirror the command line version, so ofc
|
// This is supposed to more-or-less mirror the command line version, so ofc
|
||||||
// it is going to have a lot of args
|
// it is going to have a lot of args
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn run(
|
async fn run_non_interactive(
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
|
list_mode: ListMode,
|
||||||
cwd: Option<String>,
|
cwd: Option<String>,
|
||||||
exit: Option<i64>,
|
exit: Option<i64>,
|
||||||
interactive: bool,
|
|
||||||
human: bool,
|
|
||||||
exclude_exit: Option<i64>,
|
exclude_exit: Option<i64>,
|
||||||
exclude_cwd: Option<String>,
|
exclude_cwd: Option<String>,
|
||||||
before: Option<String>,
|
before: Option<String>,
|
||||||
after: Option<String>,
|
after: Option<String>,
|
||||||
cmd_only: bool,
|
|
||||||
query: &[String],
|
query: &[String],
|
||||||
db: &mut (impl Database + Send + Sync),
|
db: &mut (impl Database + Send + Sync),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let dir = if let Some(cwd) = cwd {
|
let dir = if cwd.as_deref() == Some(".") {
|
||||||
if cwd == "." {
|
let current = std::env::current_dir()?;
|
||||||
let current = std::env::current_dir()?;
|
let current = current.as_os_str();
|
||||||
let current = current.as_os_str();
|
let current = current.to_str().unwrap();
|
||||||
let current = current.to_str().unwrap();
|
|
||||||
|
|
||||||
Some(current.to_owned())
|
Some(current.to_owned())
|
||||||
} else {
|
|
||||||
Some(cwd)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
cwd
|
||||||
};
|
};
|
||||||
|
|
||||||
if interactive {
|
let context = current_context();
|
||||||
let item = select_history(
|
|
||||||
query,
|
let results = db
|
||||||
|
.search(
|
||||||
|
None,
|
||||||
settings.search_mode,
|
settings.search_mode,
|
||||||
settings.filter_mode,
|
settings.filter_mode,
|
||||||
settings.style,
|
&context,
|
||||||
db,
|
query.join(" ").as_str(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
eprintln!("{}", item);
|
|
||||||
} else {
|
|
||||||
let context = current_context();
|
|
||||||
|
|
||||||
let results = db
|
// TODO: This filtering would be better done in the SQL query, I just
|
||||||
.search(
|
// need a nice way of building queries.
|
||||||
None,
|
let results: Vec<History> = results
|
||||||
settings.search_mode,
|
.iter()
|
||||||
settings.filter_mode,
|
.filter(|h| {
|
||||||
&context,
|
if let Some(exit) = exit {
|
||||||
query.join(" ").as_str(),
|
if h.exit != exit {
|
||||||
)
|
return false;
|
||||||
.await?;
|
|
||||||
|
|
||||||
// TODO: This filtering would be better done in the SQL query, I just
|
|
||||||
// need a nice way of building queries.
|
|
||||||
let results: Vec<History> = results
|
|
||||||
.iter()
|
|
||||||
.filter(|h| {
|
|
||||||
if let Some(exit) = exit {
|
|
||||||
if h.exit != exit {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(exit) = exclude_exit {
|
if let Some(exit) = exclude_exit {
|
||||||
if h.exit == exit {
|
if h.exit == exit {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(cwd) = &exclude_cwd {
|
if let Some(cwd) = &exclude_cwd {
|
||||||
if h.cwd.as_str() == cwd.as_str() {
|
if h.cwd.as_str() == cwd.as_str() {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(cwd) = &dir {
|
if let Some(cwd) = &dir {
|
||||||
if h.cwd.as_str() != cwd.as_str() {
|
if h.cwd.as_str() != cwd.as_str() {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(before) = &before {
|
if let Some(before) = &before {
|
||||||
let before = chrono_english::parse_date_string(
|
let before = chrono_english::parse_date_string(
|
||||||
before.as_str(),
|
before.as_str(),
|
||||||
Utc::now(),
|
Utc::now(),
|
||||||
chrono_english::Dialect::Uk,
|
chrono_english::Dialect::Uk,
|
||||||
);
|
);
|
||||||
|
|
||||||
if before.is_err() || h.timestamp.gt(&before.unwrap()) {
|
if before.is_err() || h.timestamp.gt(&before.unwrap()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(after) = &after {
|
if let Some(after) = &after {
|
||||||
let after = chrono_english::parse_date_string(
|
let after = chrono_english::parse_date_string(
|
||||||
after.as_str(),
|
after.as_str(),
|
||||||
Utc::now(),
|
Utc::now(),
|
||||||
chrono_english::Dialect::Uk,
|
chrono_english::Dialect::Uk,
|
||||||
);
|
);
|
||||||
|
|
||||||
if after.is_err() || h.timestamp.lt(&after.unwrap()) {
|
if after.is_err() || h.timestamp.lt(&after.unwrap()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
.map(std::borrow::ToOwned::to_owned)
|
.map(std::borrow::ToOwned::to_owned)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
super::history::print_list(&results, human, cmd_only);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
super::history::print_list(&results, list_mode);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue