mirror of
https://github.com/nushell/nushell
synced 2025-01-12 13:19:01 +00:00
Add config.history.path
This was originally brought up in #11962, but closed in favour of the more general #10100. However this commit doesn't address the broader theme of using alternate XDG vars for the default history path. Here is the updated `sample_config.nu` documentation for the field: > # When this config doesn't exist or is set to null, then a default path is used > # based on the OS and ENV. > # > # You will likely want to match the file extension to the `file_format` setting, > # therefore ".txt" or ".sqlite". > # > # Nushell will create the file if it doesn't exist. However it won't create the > # directory path, and will error if it doesn't exist. > $env.config.history.path = null
This commit is contained in:
parent
4d3283e235
commit
85772e0407
7 changed files with 82 additions and 13 deletions
|
@ -45,8 +45,10 @@ impl Command for History {
|
|||
return Ok(PipelineData::empty());
|
||||
};
|
||||
// todo for sqlite history this command should be an alias to `open ~/.config/nushell/history.sqlite3 | get history`
|
||||
let Some(history_path) = history.file_path() else {
|
||||
return Err(ShellError::ConfigDirNotFound { span: Some(head) });
|
||||
let result = history.file_path(Some(call.head));
|
||||
let history_path = match result {
|
||||
Ok(path) => path,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
if call.has_flag(engine_state, stack, "clear")? {
|
||||
|
|
|
@ -73,10 +73,10 @@ Note that history item IDs are ignored when importing from file."#
|
|||
let Some(history) = engine_state.history_config() else {
|
||||
return ok;
|
||||
};
|
||||
let Some(current_history_path) = history.file_path() else {
|
||||
return Err(ShellError::ConfigDirNotFound {
|
||||
span: Some(call.head),
|
||||
});
|
||||
let result = history.file_path(Some(call.head));
|
||||
let current_history_path = match result {
|
||||
Ok(path) => path,
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
if let Some(bak_path) = backup(¤t_history_path)? {
|
||||
println!("Backed history to {}", bak_path.display());
|
||||
|
|
|
@ -1126,7 +1126,7 @@ fn setup_history(
|
|||
None
|
||||
};
|
||||
|
||||
if let Some(path) = history.file_path() {
|
||||
if let Ok(path) = history.file_path(None) {
|
||||
return update_line_editor_history(
|
||||
engine_state,
|
||||
path,
|
||||
|
@ -1401,7 +1401,7 @@ fn trailing_slash_looks_like_path() {
|
|||
fn are_session_ids_in_sync() {
|
||||
let engine_state = &mut EngineState::new();
|
||||
let history = engine_state.history_config().unwrap();
|
||||
let history_path = history.file_path().unwrap();
|
||||
let history_path = history.file_path(None).unwrap();
|
||||
let line_editor = reedline::Reedline::create();
|
||||
let history_session_id = reedline::Reedline::create_history_session_id();
|
||||
let line_editor = update_line_editor_history(
|
||||
|
|
|
@ -37,20 +37,54 @@ impl UpdateFromValue for HistoryFileFormat {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct HistoryConfig {
|
||||
pub max_size: i64,
|
||||
pub sync_on_enter: bool,
|
||||
pub file_format: HistoryFileFormat,
|
||||
pub isolation: bool,
|
||||
pub path: Option<String>,
|
||||
}
|
||||
|
||||
impl HistoryConfig {
|
||||
pub fn file_path(&self) -> Option<std::path::PathBuf> {
|
||||
nu_path::nu_config_dir().map(|mut history_path| {
|
||||
pub fn file_path(&self, call_head: Option<Span>) -> Result<std::path::PathBuf, ShellError> {
|
||||
match self.path.clone() {
|
||||
None => self.system_defined_file_path(call_head),
|
||||
Some(path) => self.user_defined_file_path(path, call_head),
|
||||
}
|
||||
}
|
||||
|
||||
fn system_defined_file_path(
|
||||
&self,
|
||||
call_head: Option<Span>,
|
||||
) -> Result<std::path::PathBuf, ShellError> {
|
||||
let system_path = nu_path::nu_config_dir().map(|mut history_path| {
|
||||
history_path.push(self.file_format.default_file_name());
|
||||
history_path.into()
|
||||
})
|
||||
});
|
||||
match system_path {
|
||||
Some(path) => Ok(path),
|
||||
None => Err(ShellError::ConfigDirNotFound { span: call_head }),
|
||||
}
|
||||
}
|
||||
|
||||
fn user_defined_file_path(
|
||||
&self,
|
||||
path_from_config: String,
|
||||
call_head: Option<Span>,
|
||||
) -> Result<std::path::PathBuf, ShellError> {
|
||||
let error = Err(ShellError::HistoryDirNotFound { span: call_head });
|
||||
|
||||
let user_path = std::path::Path::new(&path_from_config);
|
||||
let dir_path = match user_path.parent() {
|
||||
Some(path) => path,
|
||||
None => return error,
|
||||
};
|
||||
|
||||
match dir_path.exists() {
|
||||
true => Ok(user_path.into()),
|
||||
false => error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,6 +95,7 @@ impl Default for HistoryConfig {
|
|||
sync_on_enter: true,
|
||||
file_format: HistoryFileFormat::Plaintext,
|
||||
isolation: false,
|
||||
path: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +119,11 @@ impl UpdateFromValue for HistoryConfig {
|
|||
"sync_on_enter" => self.sync_on_enter.update(val, path, errors),
|
||||
"max_size" => self.max_size.update(val, path, errors),
|
||||
"file_format" => self.file_format.update(val, path, errors),
|
||||
"path" => match val {
|
||||
Value::Nothing { .. } => self.path = None,
|
||||
Value::String { val, .. } => self.path = Some(val.clone()),
|
||||
_ => errors.type_mismatch(path, Type::custom("path or nothing"), val),
|
||||
},
|
||||
_ => errors.unknown_option(path, val),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -762,7 +762,7 @@ impl EngineState {
|
|||
|
||||
/// Returns the configuration settings for command history or `None` if history is disabled
|
||||
pub fn history_config(&self) -> Option<HistoryConfig> {
|
||||
self.history_enabled.then(|| self.config.history)
|
||||
self.history_enabled.then(|| self.config.history.clone())
|
||||
}
|
||||
|
||||
pub fn get_var(&self, var_id: VarId) -> &Variable {
|
||||
|
|
|
@ -1434,6 +1434,20 @@ On Windows, this would be %USERPROFILE%\AppData\Roaming"#
|
|||
span: Option<Span>,
|
||||
},
|
||||
|
||||
/// The config directory could not be found
|
||||
#[error("The base directory for the history file could not be found")]
|
||||
#[diagnostic(
|
||||
code(nu::shell::history_dir_not_found),
|
||||
help(
|
||||
r#"A user-defined path for the history file was given in the config, but the base directory for the path does not exist.
|
||||
Please create it."#
|
||||
)
|
||||
)]
|
||||
HistoryDirNotFound {
|
||||
#[label = "Could not find history directory"]
|
||||
span: Option<Span>,
|
||||
},
|
||||
|
||||
/// XDG_CONFIG_HOME was set to an invalid path
|
||||
#[error("$env.XDG_CONFIG_HOME ({xdg}) is invalid, using default config directory instead: {default}")]
|
||||
#[diagnostic(
|
||||
|
|
|
@ -63,6 +63,19 @@ $env.config.history.sync_on_enter = true
|
|||
# This setting only applies to SQLite-backed history
|
||||
$env.config.history.isolation = true
|
||||
|
||||
# path (string):
|
||||
# The absolute path to the history file.
|
||||
#
|
||||
# When this config doesn't exist or is set to null, then a default path is used
|
||||
# based on the OS and ENV.
|
||||
#
|
||||
# You will likely want to match the file extension to the `file_format` setting,
|
||||
# therefore ".txt" or ".sqlite".
|
||||
#
|
||||
# Nushell will create the file if it doesn't exist. However it won't create the
|
||||
# directory path, and will error if it doesn't exist.
|
||||
$env.config.history.path = null
|
||||
|
||||
# ----------------------
|
||||
# Miscellaneous Settings
|
||||
# ----------------------
|
||||
|
|
Loading…
Reference in a new issue