Skip to content

Commit c28410d

Browse files
committed
sh: write history on exit
1 parent 59c4c04 commit c28410d

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

sh/src/shell/history.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::pattern::HistoryPattern;
1111
use crate::shell::environment::Environment;
1212
use std::collections::VecDeque;
1313
use std::io::Read;
14+
use std::io::Write;
1415
use std::path::Path;
1516

1617
#[derive(Debug, Eq, PartialEq)]
@@ -218,6 +219,30 @@ fn read_history_from_file(path: &Path, max_entries: u32) -> History {
218219
}
219220
}
220221

222+
pub fn write_history_to_file(history: &History, env: &Environment) {
223+
let path = if let Some(histfile) = env.get_str_value("HISTFILE") {
224+
histfile.to_string()
225+
} else if let Some(home) = env.get_str_value("HOME") {
226+
format!("{home}/.sh_history")
227+
} else {
228+
eprintln!("sh: HISTFILE or HOME not set, history not saved");
229+
return;
230+
};
231+
match std::fs::File::options().write(true).open(&path) {
232+
Ok(mut file) => {
233+
for entry in &history.entries {
234+
if let Err(err) = writeln!(file, "{}", entry.command) {
235+
eprintln!("sh: failed to write to history file at {} ({err})", path);
236+
return;
237+
}
238+
}
239+
}
240+
Err(err) => {
241+
eprintln!("sh: failed to open history file at {} ({err})", path);
242+
}
243+
}
244+
}
245+
221246
pub fn initialize_history_from_system(env: &Environment) -> History {
222247
let histsize = if let Some(histsize) = env.get_str_value("HISTSIZE") {
223248
histsize.parse().unwrap_or_else(|_| {

sh/src/shell/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::parse::word::WordPair;
2424
use crate::parse::word_parser::parse_word;
2525
use crate::parse::{AliasTable, ParserError};
2626
use crate::shell::environment::{CannotModifyReadonly, Environment, Value};
27-
use crate::shell::history::{initialize_history_from_system, History};
27+
use crate::shell::history::{initialize_history_from_system, write_history_to_file, History};
2828
use crate::shell::opened_files::OpenedFiles;
2929
use crate::signals::SignalManager;
3030
use crate::utils::{
@@ -194,6 +194,9 @@ impl Shell {
194194

195195
pub fn exit(&mut self, code: i32) -> ! {
196196
self.execute_action(self.exit_action.clone());
197+
if self.is_interactive && !self.is_subshell {
198+
write_history_to_file(&self.history, &self.environment);
199+
}
197200
std::process::exit(code);
198201
}
199202

0 commit comments

Comments
 (0)