Re-implement $history variable

Added -L option to set to mean "don't abbreviate"
This commit is contained in:
ridiculousfish 2012-03-19 11:52:18 -07:00
parent c8bc535f22
commit 1a87f44325
6 changed files with 60 additions and 157 deletions

View file

@ -298,10 +298,10 @@ static void erase_values(wcstring_list_t &list, std::vector<long> &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;

View file

@ -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();
}

View file

@ -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);

156
env.cpp
View file

@ -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<int>(common_get_width());
return dyn_var.c_str();
}
else if( wcscmp( key, L"LINES" )==0 )
{
dyn_var = to_string<int>(common_get_height());
return dyn_var.c_str();
}
else if( wcscmp( key, L"status" )==0 )
{
dyn_var = to_string<int>(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;

View file

@ -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<size_t>::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);

View file

@ -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);
};