diff --git a/src/builtin_set.cpp b/src/builtin_set.cpp index a179da5da..c21c886d8 100644 --- a/src/builtin_set.cpp +++ b/src/builtin_set.cpp @@ -482,8 +482,12 @@ static int builtin_set_list(const wchar_t *cmd, set_cmd_opts_t &opts, int argc, if (!names_only) { wcstring val; - if (key == L"history") { - val = history_variable_description; + if (opts.shorten_ok && key == L"history") { + history_t *history = &history_t::history_with_name(history_session_id(env_stack_t::principal())); + for (size_t i = 1; i < history->size() && val.size() < 64; i++) { + if (i > 1) val += L' '; + val += expand_escape_string(history->item_at_index(i).str()); + } } else { auto var = parser.vars().get(key, compute_scope(opts)); if (!var.missing_or_empty()) { diff --git a/src/complete.cpp b/src/complete.cpp index 2707931fd..7a7c3dbc1 100644 --- a/src/complete.cpp +++ b/src/complete.cpp @@ -1193,9 +1193,13 @@ bool completer_t::complete_variable(const wcstring &str, size_t start_offset) { wcstring desc; if (this->wants_descriptions()) { if (this->type() != COMPLETE_AUTOSUGGEST) { - // $history can be huge, don't put it in the completion description; see #6288. + // $history can be huge, don't put all of it in the completion description; see #6288. if (env_name == L"history") { - desc = history_variable_description; + history_t *history = &history_t::history_with_name(history_session_id(env_stack_t::principal())); + for (size_t i = 1; i < history->size() && desc.size() < 64; i++) { + if (i > 1) desc += L' '; + desc += expand_escape_string(history->item_at_index(i).str()); + } } else { // Can't use this->vars here, it could be any variable. auto var = vars.get(env_name); diff --git a/src/expand.cpp b/src/expand.cpp index f1334cb41..a13b02da1 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -145,6 +145,19 @@ wcstring expand_escape_variable(const env_var_t &var) { return buff; } +wcstring expand_escape_string(const wcstring &el) { + wcstring buff; + bool prefer_quotes = el.find(L' ') != wcstring::npos; + if (prefer_quotes && is_quotable(el)) { + buff.append(L"'"); + buff.append(el); + buff.append(L"'"); + } else { + buff.append(escape_string(el, 1)); + } + return buff; +} + /// Parse an array slicing specification Returns 0 on success. If a parse error occurs, returns the /// index of the bad token. Note that 0 can never be a bad index because the string always starts /// with [. diff --git a/src/expand.h b/src/expand.h index be08676b3..8a0380dea 100644 --- a/src/expand.h +++ b/src/expand.h @@ -164,6 +164,10 @@ expand_result_t expand_to_command_and_args(const wcstring &instr, const environm /// Suitable for pretty-printing. wcstring expand_escape_variable(const env_var_t &var); +/// Convert a string value to a human readable form, i.e. escape things, handle arrays, etc. +/// Suitable for pretty-printing. +wcstring expand_escape_string(const wcstring &str); + /// Perform tilde expansion and nothing else on the specified string, which is modified in place. /// /// \param input the string to tilde expand diff --git a/src/history.h b/src/history.h index 17410e8f7..6f7e30590 100644 --- a/src/history.h +++ b/src/history.h @@ -294,8 +294,4 @@ void start_private_mode(); /// Queries private mode status. bool in_private_mode(); -/// The description of the $history environment variable, as offered in completions and -/// the output of builtin set. -constexpr const wchar_t *history_variable_description = L"Full history of interactive commands"; - #endif