mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Make automatic history reloading actually work the way it should
darcs-hash:20061022012102-ac50b-e57a0dd2c918a2a8abd0210b9f8a2163ce664b74.gz
This commit is contained in:
parent
da81328d75
commit
b83a7cb659
1 changed files with 90 additions and 39 deletions
117
history.c
117
history.c
|
@ -58,6 +58,15 @@ typedef struct
|
|||
*/
|
||||
array_list_t item;
|
||||
|
||||
|
||||
/**
|
||||
A hash table containing all the items created by the current
|
||||
session as keys. This can be used as a lookup when loading the
|
||||
history list to ignore the on-file version of an entry from
|
||||
this session.
|
||||
*/
|
||||
hash_table_t session_item;
|
||||
|
||||
/**
|
||||
The current history position
|
||||
*/
|
||||
|
@ -129,6 +138,25 @@ static hash_table_t *mode_table=0;
|
|||
*/
|
||||
static history_mode_t *current_mode=0;
|
||||
|
||||
/**
|
||||
Hash function for item_t struct
|
||||
*/
|
||||
static int hash_item_func( void *v )
|
||||
{
|
||||
item_t *i = (item_t *)v;
|
||||
return i->timestamp ^ hash_wcs_func( i->data );
|
||||
}
|
||||
|
||||
/**
|
||||
Comparison function for item_t struct
|
||||
*/
|
||||
static int hash_item_cmp( void *v1, void *v2 )
|
||||
{
|
||||
item_t *i1 = (item_t *)v1;
|
||||
item_t *i2 = (item_t *)v2;
|
||||
return (i1->timestamp == i2->timestamp) && (wcscmp( i1->data, i2->data )==0);
|
||||
}
|
||||
|
||||
/**
|
||||
Add backslashes to all newlines, so that the returning string is
|
||||
suitable for writing to the history file. The memory for the return
|
||||
|
@ -397,6 +425,9 @@ static history_mode_t *history_create_mode( const wchar_t *name )
|
|||
halloc_register_function( new_mode, (void (*)(void *))&al_destroy, &new_mode->item );
|
||||
halloc_register_function( new_mode, (void (*)(void *))&al_destroy, &new_mode->used );
|
||||
|
||||
hash_init( &new_mode->session_item, &hash_item_func, &hash_item_cmp );
|
||||
halloc_register_function( new_mode, (void (*)(void *))&hash_destroy, &new_mode->session_item );
|
||||
|
||||
new_mode->save_timestamp=time(0);
|
||||
new_mode->item_context = halloc( 0,0 );
|
||||
|
||||
|
@ -447,12 +478,14 @@ static void history_populate_from_mmap( history_mode_t *m )
|
|||
char *end = begin + m->mmap_length;
|
||||
char *pos;
|
||||
|
||||
array_list_t tmp;
|
||||
array_list_t old_item;
|
||||
array_list_t session_item_list;
|
||||
int ignore_newline = 0;
|
||||
int do_push = 1;
|
||||
|
||||
al_init( &tmp );
|
||||
al_push_all( &tmp, &m->item );
|
||||
al_init( &old_item );
|
||||
al_init( &session_item_list );
|
||||
al_push_all( &old_item, &m->item );
|
||||
al_truncate( &m->item, 0 );
|
||||
|
||||
for( pos = begin; pos <end; pos++ )
|
||||
|
@ -460,9 +493,23 @@ static void history_populate_from_mmap( history_mode_t *m )
|
|||
|
||||
if( do_push )
|
||||
{
|
||||
item_t *i;
|
||||
item_t *i_orig;
|
||||
|
||||
ignore_newline = *pos == '#';
|
||||
|
||||
i = item_get( m, pos );
|
||||
assert( i!=pos );
|
||||
|
||||
if( (i_orig=hash_get( ¤t_mode->session_item, i ) ) )
|
||||
{
|
||||
al_push( &session_item_list, i_orig );
|
||||
}
|
||||
else
|
||||
{
|
||||
al_push( &m->item, pos );
|
||||
// debug( 0, L"Push item at offset %d", pos-begin );
|
||||
}
|
||||
|
||||
do_push = 0;
|
||||
}
|
||||
|
||||
|
@ -489,11 +536,13 @@ static void history_populate_from_mmap( history_mode_t *m )
|
|||
}
|
||||
}
|
||||
|
||||
al_push_all( &m->item, &session_item_list );
|
||||
m->pos += al_get_count( &m->item );
|
||||
al_push_all( &m->item, &tmp );
|
||||
al_destroy( &tmp );
|
||||
// debug( 0, L"History has %d items", al_get_count( &m->item ));
|
||||
al_push_all( &m->item, &old_item );
|
||||
|
||||
|
||||
al_destroy( &session_item_list );
|
||||
al_destroy( &old_item );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -510,6 +559,8 @@ static void history_load( history_mode_t *m )
|
|||
if( !m )
|
||||
return;
|
||||
|
||||
m->has_loaded=1;
|
||||
|
||||
signal_block();
|
||||
|
||||
context = halloc( 0, 0 );
|
||||
|
@ -536,31 +587,10 @@ static void history_load( history_mode_t *m )
|
|||
}
|
||||
}
|
||||
|
||||
m->has_loaded=1;
|
||||
|
||||
halloc_free( context );
|
||||
signal_unblock();
|
||||
}
|
||||
|
||||
/**
|
||||
Hash function for item_t struct
|
||||
*/
|
||||
static int hash_item_func( void *v )
|
||||
{
|
||||
item_t *i = (item_t *)v;
|
||||
return i->timestamp ^ hash_wcs_func( i->data );
|
||||
}
|
||||
|
||||
/**
|
||||
Comparison function for item_t struct
|
||||
*/
|
||||
static int hash_item_cmp( void *v1, void *v2 )
|
||||
{
|
||||
item_t *i1 = (item_t *)v1;
|
||||
item_t *i2 = (item_t *)v2;
|
||||
return (i1->timestamp == i2->timestamp) && (wcscmp( i1->data, i2->data )==0);
|
||||
}
|
||||
|
||||
/**
|
||||
Save the specified mode to file
|
||||
*/
|
||||
|
@ -657,19 +687,24 @@ static void history_save_mode( void *n, history_mode_t *m )
|
|||
}
|
||||
|
||||
halloc_free( on_disk);
|
||||
|
||||
/*
|
||||
Reset the history. The item_t entries created in this session
|
||||
are not lost or dropped, they are stored in the session_item
|
||||
hash table. On reload, they will be automatically inserted at
|
||||
the end of the history list.
|
||||
*/
|
||||
|
||||
if( m->mmap_start && (m->mmap_start != MAP_FAILED ) )
|
||||
munmap( m->mmap_start, m->mmap_length );
|
||||
|
||||
halloc_free( m->item_context );
|
||||
m->item_context = halloc( 0, 0 );
|
||||
al_truncate( &m->item, 0 );
|
||||
al_truncate( &m->used, 0 );
|
||||
m->pos = 0;
|
||||
m->has_loaded = 0;
|
||||
m->mmap_start=0;
|
||||
m->mmap_length=0;
|
||||
*/
|
||||
|
||||
m->save_timestamp=time(0);
|
||||
m->new_count = 0;
|
||||
|
||||
|
@ -689,6 +724,8 @@ void history_add( const wchar_t *str )
|
|||
i->timestamp = time(0);
|
||||
|
||||
al_push( ¤t_mode->item, i );
|
||||
hash_put( ¤t_mode->session_item, i, i );
|
||||
|
||||
al_truncate( ¤t_mode->used, 0 );
|
||||
current_mode->pos = al_get_count( ¤t_mode->item );
|
||||
|
||||
|
@ -744,7 +781,7 @@ const wchar_t *history_prev_match( const wchar_t *needle )
|
|||
there is a chance that the return value of any
|
||||
previous call to item_get will become
|
||||
invalid. The history_is_used function uses the
|
||||
istem_get() function. Therefore, we must create
|
||||
item_get() function. Therefore, we must create
|
||||
a copy of the haystack string, and if the string
|
||||
is unused, we must call item_get anew.
|
||||
*/
|
||||
|
@ -825,6 +862,9 @@ void history_reset()
|
|||
if( current_mode )
|
||||
{
|
||||
current_mode->pos = al_get_count( ¤t_mode->item );
|
||||
/*
|
||||
Clear list of search matches
|
||||
*/
|
||||
al_truncate( ¤t_mode->used, 0 );
|
||||
}
|
||||
}
|
||||
|
@ -833,6 +873,11 @@ const wchar_t *history_next_match( const wchar_t *needle)
|
|||
{
|
||||
if( current_mode )
|
||||
{
|
||||
/*
|
||||
The index of previous search matches are saved in the 'used'
|
||||
list. We just need to pop the top item and set the new
|
||||
position. Easy!
|
||||
*/
|
||||
if( al_get_count( ¤t_mode->used ) )
|
||||
{
|
||||
al_pop( ¤t_mode->used );
|
||||
|
@ -844,6 +889,10 @@ const wchar_t *history_next_match( const wchar_t *needle)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The used-list is empty. Set position to 'past end of list'
|
||||
and return the search string.
|
||||
*/
|
||||
current_mode->pos = al_get_count( ¤t_mode->item );
|
||||
|
||||
}
|
||||
|
@ -888,6 +937,8 @@ void history_destroy()
|
|||
|
||||
void history_sanity_check()
|
||||
{
|
||||
|
||||
/*
|
||||
No sanity checking implemented yet...
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue