aboutsummaryrefslogtreecommitdiffstats
path: root/src/command/client/history.rs
diff options
context:
space:
mode:
authorVladislav Stepanov <8uk.8ak@gmail.com>2023-04-14 23:18:58 +0400
committerGitHub <noreply@github.com>2023-04-14 20:18:58 +0100
commitc05d2850420a2c163b8f62c33a6cef7c0ae1ad8d (patch)
tree2c44a44eda7e76fa74e78ac1fd02f55c1ed4d804 /src/command/client/history.rs
parentSwitch to uuidv7 (#864) (diff)
downloadatuin-c05d2850420a2c163b8f62c33a6cef7c0ae1ad8d.zip
Workspace reorder (#868)
* Try different workspace structure Move main crate (atuin) to be on the same level with other crates in this workspace * extract common dependencies to the workspace definition * fix base64 v0.21 deprecation warning * questionable: update deps & fix chrono deprecations possible panic sites are unchanged, they're just more visible now * Revert "questionable: update deps & fix chrono deprecations" This reverts commit 993e60f8dea81a1625a04285a617959ad09a0866.
Diffstat (limited to 'src/command/client/history.rs')
-rw-r--r--src/command/client/history.rs298
1 files changed, 0 insertions, 298 deletions
diff --git a/src/command/client/history.rs b/src/command/client/history.rs
deleted file mode 100644
index 76c796ef..00000000
--- a/src/command/client/history.rs
+++ /dev/null
@@ -1,298 +0,0 @@
-use std::{
- env,
- fmt::{self, Display},
- io::{StdoutLock, Write},
- time::Duration,
-};
-
-use atuin_common::utils;
-use clap::Subcommand;
-use eyre::Result;
-use runtime_format::{FormatKey, FormatKeyError, ParsedFmt};
-
-use atuin_client::{
- database::{current_context, Database},
- history::History,
- settings::Settings,
-};
-
-#[cfg(feature = "sync")]
-use atuin_client::sync;
-use log::debug;
-
-use super::search::format_duration;
-use super::search::format_duration_into;
-
-#[derive(Subcommand)]
-#[command(infer_subcommands = true)]
-pub enum Cmd {
- /// Begins a new command in the history
- Start { command: Vec<String> },
-
- /// Finishes a new command in the history (adds time, exit code)
- End {
- id: String,
- #[arg(long, short)]
- exit: i64,
- },
-
- /// List all items in history
- List {
- #[arg(long, short)]
- cwd: bool,
-
- #[arg(long, short)]
- session: bool,
-
- #[arg(long)]
- human: bool,
-
- /// Show only the text of the command
- #[arg(long)]
- cmd_only: bool,
-
- /// Available variables: {command}, {directory}, {duration}, {user}, {host} and {time}.
- /// Example: --format "{time} - [{duration}] - {directory}$\t{command}"
- #[arg(long, short)]
- format: Option<String>,
- },
-
- /// Get the last command ran
- Last {
- #[arg(long)]
- human: bool,
-
- /// Show only the text of the command
- #[arg(long)]
- cmd_only: bool,
-
- /// Available variables: {command}, {directory}, {duration}, {user}, {host} and {time}.
- /// Example: --format "{time} - [{duration}] - {directory}$\t{command}"
- #[arg(long, short)]
- format: Option<String>,
- },
-}
-
-#[derive(Clone, Copy, Debug)]
-pub enum ListMode {
- Human,
- CmdOnly,
- Regular,
-}
-
-impl ListMode {
- pub const fn from_flags(human: bool, cmd_only: bool) -> Self {
- if human {
- ListMode::Human
- } else if cmd_only {
- ListMode::CmdOnly
- } else {
- ListMode::Regular
- }
- }
-}
-
-#[allow(clippy::cast_sign_loss)]
-pub fn print_list(h: &[History], list_mode: ListMode, format: Option<&str>) {
- let w = std::io::stdout();
- let mut w = w.lock();
-
- match list_mode {
- ListMode::Human => print_human_list(&mut w, h, format),
- ListMode::CmdOnly => print_cmd_only(&mut w, h),
- ListMode::Regular => print_regular(&mut w, h, format),
- }
-
- w.flush().expect("failed to flush history");
-}
-
-/// type wrapper around `History` so we can implement traits
-struct FmtHistory<'a>(&'a History);
-
-/// defines how to format the history
-impl FormatKey for FmtHistory<'_> {
- #[allow(clippy::cast_sign_loss)]
- fn fmt(&self, key: &str, f: &mut fmt::Formatter<'_>) -> Result<(), FormatKeyError> {
- match key {
- "command" => f.write_str(self.0.command.trim())?,
- "directory" => f.write_str(self.0.cwd.trim())?,
- "exit" => f.write_str(&self.0.exit.to_string())?,
- "duration" => {
- let dur = Duration::from_nanos(std::cmp::max(self.0.duration, 0) as u64);
- format_duration_into(dur, f)?;
- }
- "time" => self.0.timestamp.format("%Y-%m-%d %H:%M:%S").fmt(f)?,
- "relativetime" => {
- let since = chrono::Utc::now() - self.0.timestamp;
- let time = format_duration(since.to_std().unwrap_or_default());
- f.write_str(&time)?;
- }
- "host" => f.write_str(
- self.0
- .hostname
- .split_once(':')
- .map_or(&self.0.hostname, |(host, _)| host),
- )?,
- "user" => f.write_str(self.0.hostname.split_once(':').map_or("", |(_, user)| user))?,
- _ => return Err(FormatKeyError::UnknownKey),
- }
- Ok(())
- }
-}
-
-fn print_list_with(w: &mut StdoutLock, h: &[History], format: &str) {
- let fmt = match ParsedFmt::new(format) {
- Ok(fmt) => fmt,
- Err(err) => {
- eprintln!("ERROR: History formatting failed with the following error: {err}");
- println!("If your formatting string contains curly braces (eg: {{var}}) you need to escape them this way: {{{{var}}.");
- std::process::exit(1)
- }
- };
-
- for h in h.iter().rev() {
- writeln!(w, "{}", fmt.with_args(&FmtHistory(h))).expect("failed to write history");
- }
-}
-
-pub fn print_human_list(w: &mut StdoutLock, h: &[History], format: Option<&str>) {
- let format = format
- .unwrap_or("{time} ยท {duration}\t{command}")
- .replace("\\t", "\t");
- print_list_with(w, h, &format);
-}
-
-pub fn print_regular(w: &mut StdoutLock, h: &[History], format: Option<&str>) {
- let format = format
- .unwrap_or("{time}\t{command}\t{duration}")
- .replace("\\t", "\t");
- print_list_with(w, h, &format);
-}
-
-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 {
- pub async fn run(&self, settings: &Settings, db: &mut impl Database) -> Result<()> {
- let context = current_context();
-
- match self {
- Self::Start { command: words } => {
- let command = words.join(" ");
-
- if command.starts_with(' ') || settings.history_filter.is_match(&command) {
- return Ok(());
- }
-
- // It's better for atuin to silently fail here and attempt to
- // store whatever is ran, than to throw an error to the terminal
- let cwd = utils::get_current_dir();
-
- let h = History::new(chrono::Utc::now(), command, cwd, -1, -1, None, None, None);
-
- // print the ID
- // we use this as the key for calling end
- println!("{}", h.id);
- db.save(&h).await?;
- Ok(())
- }
-
- Self::End { id, exit } => {
- if id.trim() == "" {
- return Ok(());
- }
-
- let mut h = db.load(id).await?;
-
- if h.duration > 0 {
- debug!("cannot end history - already has duration");
-
- // returning OK as this can occur if someone Ctrl-c a prompt
- return Ok(());
- }
-
- h.exit = *exit;
- h.duration = chrono::Utc::now().timestamp_nanos() - h.timestamp.timestamp_nanos();
-
- db.update(&h).await?;
-
- if settings.should_sync()? {
- #[cfg(feature = "sync")]
- {
- debug!("running periodic background sync");
- sync::sync(settings, false, db).await?;
- }
- #[cfg(not(feature = "sync"))]
- debug!("not compiled with sync support");
- } else {
- debug!("sync disabled! not syncing");
- }
-
- Ok(())
- }
-
- Self::List {
- session,
- cwd,
- human,
- cmd_only,
- format,
- } => {
- let session = if *session {
- Some(env::var("ATUIN_SESSION")?)
- } else {
- None
- };
- let cwd = if *cwd {
- Some(utils::get_current_dir())
- } else {
- None
- };
-
- let history = match (session, cwd) {
- (None, None) => db.list(settings.filter_mode, &context, None, false).await?,
- (None, Some(cwd)) => {
- let query = format!("select * from history where cwd = '{cwd}';");
- db.query_history(&query).await?
- }
- (Some(session), None) => {
- let query = format!("select * from history where session = '{session}';");
- db.query_history(&query).await?
- }
- (Some(session), Some(cwd)) => {
- let query = format!(
- "select * from history where cwd = '{cwd}' and session = '{session}';",
- );
- db.query_history(&query).await?
- }
- };
-
- print_list(
- &history,
- ListMode::from_flags(*human, *cmd_only),
- format.as_deref(),
- );
-
- Ok(())
- }
-
- Self::Last {
- human,
- cmd_only,
- format,
- } => {
- let last = db.last().await?;
- print_list(
- &[last],
- ListMode::from_flags(*human, *cmd_only),
- format.as_deref(),
- );
-
- Ok(())
- }
- }
- }
-}