From 1a87f44325327aff426118da1d9fdf8ac01f67a9 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 19 Mar 2012 11:52:18 -0700 Subject: [PATCH] Re-implement $history variable Added -L option to set to mean "don't abbreviate" --- builtin_set.cpp | 28 +++++---- common.cpp | 3 +- common.h | 1 + env.cpp | 156 ++++-------------------------------------------- history.cpp | 26 ++++++++ history.h | 3 + 6 files changed, 60 insertions(+), 157 deletions(-) diff --git a/builtin_set.cpp b/builtin_set.cpp index 7eec8eb4b..a02bc94f1 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -298,10 +298,10 @@ static void erase_values(wcstring_list_t &list, std::vector &indexes) /** - Print the names of all environment variables in the scope, with or without values, - with or without escaping + Print the names of all environment variables in the scope, with or without shortening, + with or without values, with or without escaping */ -static void print_variables(int include_values, int esc, int scope) +static void print_variables(int include_values, int esc, bool shorten_ok, int scope) { wcstring_list_t names = env_get_names(scope); sort(names.begin(), names.end()); @@ -320,7 +320,7 @@ static void print_variables(int include_values, int esc, int scope) { int shorten = 0; - if( value.length() > 64 ) + if( shorten_ok && value.length() > 64 ) { shorten = 1; value.resize(60); @@ -383,7 +383,11 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) } , { - L"universal", no_argument, 0, 'U' + L"universal", no_argument, 0, 'U' + } + , + { + L"long", no_argument, 0, 'L' } , { @@ -400,7 +404,7 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) } ; - const wchar_t *short_options = L"+xglenuUqh"; + const wchar_t *short_options = L"+xglenuULqh"; int argc = builtin_count_args(argv); @@ -410,7 +414,7 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) int local = 0, global = 0, exportv = 0; int erase = 0, list = 0, unexport=0; int universal = 0, query=0; - + bool shorten_ok = true; /* Variables used for performing the actual work @@ -467,6 +471,10 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) case 'U': universal = 1; break; + + case 'L': + shorten_ok = false; + break; case 'q': query = 1; @@ -574,8 +582,6 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) wcstring_list_t result; size_t j; -// al_init( &result ); -// al_init( &indexes ); env_var_t dest_str = env_get_string(dest); if (! dest_str.missing()) tokenize_variable_array( dest_str, result ); @@ -612,7 +618,7 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) if( list ) { /* Maybe we should issue an error if there are any other arguments? */ - print_variables(0, 0, scope); + print_variables(0, 0, shorten_ok, scope); return 0; } @@ -633,7 +639,7 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) } else { - print_variables( 1, 1, scope ); + print_variables( 1, 1, shorten_ok, scope ); } return retcode; diff --git a/common.cpp b/common.cpp index 50b5e7974..2124fe678 100644 --- a/common.cpp +++ b/common.cpp @@ -1969,7 +1969,6 @@ void set_main_thread() { main_thread_id = pthread_self(); } - /* Notice when we've forked */ static pid_t initial_pid; @@ -1987,7 +1986,7 @@ void setup_fork_guards(void) { initial_pid = getpid(); } -static bool is_main_thread() { +bool is_main_thread() { assert (main_thread_id != 0); return main_thread_id == pthread_self(); } diff --git a/common.h b/common.h index 4c24afdbb..0055cc679 100644 --- a/common.h +++ b/common.h @@ -739,6 +739,7 @@ double timef(); This is our replacement for pthread_main_np(). */ void set_main_thread(); +bool is_main_thread(); /** Set up a guard to complain if we try to do certain things (like take a lock) after calling fork */ void setup_fork_guards(void); diff --git a/env.cpp b/env.cpp index 47dd777cd..205562a14 100644 --- a/env.cpp +++ b/env.cpp @@ -1072,39 +1072,18 @@ const wchar_t *env_var_t::c_str(void) const { } env_var_t env_get_string( const wcstring &key ) -{ - scoped_lock lock(env_lock); - - if( key == L"history" ) +{ + /* Big hack...we only allow getting the history on the main thread. Note that history_t may ask for an environment variable, so don't take the lock here (we don't need it) */ + if( key == L"history" && is_main_thread()) { - wcstring result; - const wchar_t *current; - int i; - int add_current=0; - - current = reader_get_buffer(); - if( current && wcslen( current ) ) - { - add_current=1; - result += current; - } - - for( i=add_current;; i++ ) - { - // PCA This looks bad! We can't do this off of the main thread. - wchar_t *next = NULL;//history_get( i-add_current ); - if( !next ) - { - break; - } - - if( i!=0) - { - result += ARRAY_SEP_STR; - } - result += next; - } + env_var_t result; + history_t *history = reader_get_history(); + if (! history) { + history = &history_t::history_with_name(L"fish"); + } + if (history) + history->get_string_representation(result, ARRAY_SEP_STR); return result; } else if( key == L"COLUMNS" ) @@ -1125,6 +1104,8 @@ env_var_t env_get_string( const wcstring &key ) } else { + scoped_lock lock(env_lock); + var_entry_t *res; env_node_t *env = top; wchar_t *item; @@ -1183,119 +1164,6 @@ env_var_t env_get_string( const wcstring &key ) } } -const wchar_t *env_get( const wchar_t *key ) -{ - ASSERT_IS_MAIN_THREAD(); - - var_entry_t *res; - env_node_t *env = top; - wchar_t *item; - - CHECK( key, 0 ); - - if( wcscmp( key, L"history" ) == 0 ) - { - const wchar_t *current; - dyn_var.clear(); - - current = reader_get_buffer(); - if( current && wcslen( current ) ) - { - dyn_var.append(current); - dyn_var.append(ARRAY_SEP_STR); - } - - history_t *history = reader_get_history(); - if (history) { - for (size_t idx = 1; idx < (size_t)(-1); idx++) { - history_item_t item = history->item_at_index(idx); - if (item.empty()) break; - - dyn_var.append(item.str()); - dyn_var.append(ARRAY_SEP_STR); - } - } - - /* We always have a trailing ARRAY_SEP_STR; get rid of it */ - if (dyn_var.size() >= wcslen(ARRAY_SEP_STR)) { - dyn_var.resize(dyn_var.size() - wcslen(ARRAY_SEP_STR)); - } - - return dyn_var.c_str(); - } - else if( wcscmp( key, L"COLUMNS" )==0 ) - { - dyn_var = to_string(common_get_width()); - return dyn_var.c_str(); - } - else if( wcscmp( key, L"LINES" )==0 ) - { - dyn_var = to_string(common_get_height()); - return dyn_var.c_str(); - } - else if( wcscmp( key, L"status" )==0 ) - { - dyn_var = to_string(proc_get_last_status()); - return dyn_var.c_str(); - } - else if( wcscmp( key, L"umask" )==0 ) - { - dyn_var = format_string(L"0%0.3o", get_umask()); - return dyn_var.c_str(); - } - - while( env != 0 ) - { - var_table_t::iterator result = env->env.find(key); - if ( result != env->env.end() ) - { - res = result->second; - } - else - { - res = 0; - } - - - if( res != 0 ) - { - if( res->val == ENV_NULL ) - { - return 0; - } - else - { - return res->val.c_str(); - } - } - - if( env->new_scope ) - { - env = global_env; - } - else - { - env = env->next; - } - } - if( !proc_had_barrier) - { - proc_had_barrier=1; - env_universal_barrier(); - } - - item = env_universal_get( key ); - - if( !item || (wcscmp( item, ENV_NULL )==0)) - { - return 0; - } - else - { - return item; - } -} - int env_exist( const wchar_t *key, int mode ) { var_entry_t *res; diff --git a/history.cpp b/history.cpp index b3a71ddc3..1884c2633 100644 --- a/history.cpp +++ b/history.cpp @@ -271,6 +271,32 @@ void history_t::add(const wcstring &str, const path_list_t &valid_paths) this->add(history_item_t(str, time(NULL), valid_paths)); } +void history_t::get_string_representation(wcstring &result, const wcstring &separator) +{ + scoped_lock locker(lock); + + bool first = true; + + /* Append new items */ + for (size_t i=0; i < new_items.size(); i++) { + if (! first) + result.append(separator); + result.append(new_items.at(i).str()); + first = false; + } + + /* Append old items */ + load_old_if_needed(); + for (std::deque::const_reverse_iterator iter = old_item_offsets.rbegin(); iter != old_item_offsets.rend(); ++iter) { + size_t offset = *iter; + const history_item_t item = history_t::decode_item(mmap_start + offset, mmap_length - offset); + if (! first) + result.append(separator); + result.append(item.str()); + first = false; + } +} + history_item_t history_t::item_at_index(size_t idx) { scoped_lock locker(lock); diff --git a/history.h b/history.h index 4e825fdb7..e49ad4f36 100644 --- a/history.h +++ b/history.h @@ -147,6 +147,9 @@ public: /** Irreversibly clears history */ void clear(); + /* Gets all the history into a string with ARRAY_SEP_STR. This is intended for the $history environment variable. This may be long! */ + void get_string_representation(wcstring &str, const wcstring &separator); + /** Return the specified history at the specified index. 0 is the index of the current commandline. (So the most recent item is at index 1.) */ history_item_t item_at_index(size_t idx); };