diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e4d2546d0..a5ca50404 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -90,6 +90,7 @@ Scripting improvements - ``string pad`` no longer allows non-printable characters as padding. (:issue:`9854`) - ``string repeat`` now allows omission of ``-n`` when the first argument is an integer. (:issue:`10282`) - ``functions --handlers-type caller-exit`` once again lists functions defined as ``function --on-job-exit caller``, rather than them being listed by ``functions --handlers-type process-exit``. +- Add ``history append`` subcommand to append a command to the history without executing it (:issue:`4506`). Interactive improvements ------------------------ diff --git a/doc_src/cmds/history.rst b/doc_src/cmds/history.rst index 0deebd795..5e7660389 100644 --- a/doc_src/cmds/history.rst +++ b/doc_src/cmds/history.rst @@ -17,6 +17,7 @@ Synopsis history save history clear history clear-session + history append COMMAND ... Description ----------- @@ -43,6 +44,9 @@ The following operations (sub-commands) are available: **clear-session** Clears the history file from all activity of the current session. Note: If ``history merge`` or ``builtin history merge`` is run in a session, only the history after this will be erased. +**append** + Appends commands to the history without needing to execute them. + The following options are available: These flags can appear before or immediately after one of the sub-commands listed above. @@ -83,10 +87,10 @@ Example history clear # Deletes all history items - + history search --contains "foo" # Outputs a list of all previous commands containing the string "foo". - + history delete --prefix "foo" # Interactively deletes commands which start with "foo" from the history. # You can select more than one entry by entering their IDs separated by a space. diff --git a/share/completions/history.fish b/share/completions/history.fish index 6b58ec411..3a55e69e4 100644 --- a/share/completions/history.fish +++ b/share/completions/history.fish @@ -1,5 +1,5 @@ # Note that when a completion file is sourced a new block scope is created so `set -l` works. -set -l __fish_history_all_commands search delete save merge clear clear-session +set -l __fish_history_all_commands search delete save merge clear clear-session append complete -c history -s h -l help -d "Display help and exit" @@ -35,3 +35,5 @@ complete -f -c history -n "not __fish_seen_subcommand_from $__fish_history_all_c -a clear -d "Clears history file" complete -f -c history -n "not __fish_seen_subcommand_from $__fish_history_all_commands" \ -a clear-session -d "Clears all history from the current session" +complete -f -c history -n "not __fish_seen_subcommand_from $__fish_history_all_commands" \ + -a append -d "Appends commands to the history without needing to execute them" diff --git a/share/functions/history.fish b/share/functions/history.fish index 2bb9fdd4a..b69013ccd 100644 --- a/share/functions/history.fish +++ b/share/functions/history.fish @@ -70,7 +70,7 @@ function history --description "display or manipulate interactive command histor # command. This allows the flags to appear before or after the subcommand. if not set -q hist_cmd[1] and set -q argv[1] - if contains $argv[1] search delete merge save clear clear-session + if contains $argv[1] search delete merge save clear clear-session append set hist_cmd $argv[1] set -e argv[1] end @@ -226,6 +226,13 @@ function history --description "display or manipulate interactive command histor builtin history clear-session -- $argv printf (_ "Command history for session cleared!\n") + case append + set -l newitem $argv + if not set -q argv[1] + read -P "Command: " newitem + end + + builtin history append -- $newitem case '*' printf "%ls: unexpected subcommand '%ls'\n" $cmd $hist_cmd return 2 diff --git a/src/builtins/history.rs b/src/builtins/history.rs index 4ff6af130..d280d687b 100644 --- a/src/builtins/history.rs +++ b/src/builtins/history.rs @@ -16,6 +16,7 @@ enum HistCmd { #[default] HIST_UNDEF, HIST_CLEAR_SESSION, + HIST_APPEND, } impl HistCmd { @@ -28,6 +29,7 @@ impl HistCmd { HistCmd::HIST_SAVE => L!("save"), HistCmd::HIST_UNDEF => panic!(), HistCmd::HIST_CLEAR_SESSION => L!("clear-session"), + HistCmd::HIST_APPEND => L!("append"), } } } @@ -42,6 +44,7 @@ impl TryFrom<&wstr> for HistCmd { _ if val == "merge" => Ok(HistCmd::HIST_MERGE), _ if val == "save" => Ok(HistCmd::HIST_SAVE), _ if val == "clear-session" => Ok(HistCmd::HIST_CLEAR_SESSION), + _ if val == "append" => Ok(HistCmd::HIST_APPEND), _ => Err(()), } } @@ -343,6 +346,11 @@ pub fn history(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> history.save(); } HistCmd::HIST_UNDEF => panic!("Unexpected HIST_UNDEF seen"), + HistCmd::HIST_APPEND => { + for &arg in args { + history.add_commandline(arg.to_owned()); + } + } } status diff --git a/src/history.rs b/src/history.rs index 90478e315..e94a8e830 100644 --- a/src/history.rs +++ b/src/history.rs @@ -1493,7 +1493,6 @@ impl History { self.imp().add(item, pending, true) } - /// Exposed for testing. pub fn add_commandline(&self, s: WString) { let mut imp = self.imp(); let when = imp.timestamp_now(); diff --git a/src/tests/history.rs b/src/tests/history.rs index 9d9485ec2..543875250 100644 --- a/src/tests/history.rs +++ b/src/tests/history.rs @@ -197,6 +197,10 @@ fn test_history() { assert_eq!(bef.get_required_paths(), aft.get_required_paths()); } + // Items should be explicitly added to the history. + history.add_commandline(L!("test-command").into()); + assert!(history_contains(&history, L!("test-command"))); + // Clean up after our tests. history.clear(); }