brush_core/shell/
history.rs1use std::path::PathBuf;
4
5use crate::{error, openfiles};
6
7impl<SE: crate::extensions::ShellExtensions> crate::Shell<SE> {
8 pub(super) fn load_history(&self) -> Result<Option<crate::history::History>, error::Error> {
9 const MAX_FILE_SIZE_FOR_HISTORY_IMPORT: u64 = 1024 * 1024 * 1024; let Some(history_path) = self.history_file_path() else {
12 return Ok(None);
13 };
14
15 let mut options = std::fs::File::options();
16 options.read(true);
17
18 let mut history_file =
19 self.open_file(&options, history_path, &self.default_exec_params())?;
20
21 if let openfiles::OpenFile::File(file) = &mut history_file {
23 let file_metadata = file.metadata()?;
24 let file_size = file_metadata.len();
25
26 if file_size == 0 {
30 return Ok(None);
31 }
32
33 if file_size > MAX_FILE_SIZE_FOR_HISTORY_IMPORT {
35 return Err(error::ErrorKind::HistoryFileTooLargeToImport.into());
36 }
37 }
38
39 Ok(Some(crate::history::History::import(history_file)?))
40 }
41
42 pub fn history_file_path(&self) -> Option<PathBuf> {
44 self.env_str("HISTFILE")
45 .map(|s| PathBuf::from(s.into_owned()))
46 }
47
48 pub fn history_time_format(&self) -> Option<String> {
50 self.env_str("HISTTIMEFORMAT").map(|s| s.into_owned())
51 }
52
53 pub fn save_history(&mut self) -> Result<(), error::Error> {
55 if let Some(history_file_path) = self.history_file_path()
56 && let Some(history) = &mut self.history
57 {
58 let write_timestamps = self.env.is_set("HISTTIMEFORMAT");
61
62 history.flush(
64 history_file_path,
65 true, true, write_timestamps,
68 )?;
69 }
70
71 Ok(())
72 }
73
74 pub fn add_to_history(&mut self, command: &str) -> Result<(), error::Error> {
76 if let Some(history) = &mut self.history {
77 let command = command.trim();
79
80 if command.is_empty() {
82 return Ok(());
83 }
84
85 history.add(crate::history::Item {
87 id: 0,
88 command_line: command.to_owned(),
89 timestamp: Some(chrono::Utc::now()),
90 dirty: true,
91 })?;
92 }
93
94 Ok(())
95 }
96}