예제 #1
0
void history_add( const wchar_t *str )
{
    item_t *i;

    if( !current_mode )
        return;

    i = halloc( current_mode->item_context, sizeof(item_t));
    i->data = (wchar_t *)halloc_wcsdup( current_mode->item_context, str );
    i->timestamp = time(0);

    al_push( &current_mode->item, i );
    hash_put( &current_mode->session_item, i, i );

    al_truncate( &current_mode->used, 0 );
    current_mode->pos = al_get_count( &current_mode->item );

    current_mode->new_count++;

    if( (time(0) > current_mode->save_timestamp+SAVE_INTERVAL) || (current_mode->new_count >= SAVE_COUNT) )
    {
        history_save_mode( 0, current_mode );
    }

}
예제 #2
0
파일: input.c 프로젝트: cardmagic/lucash
int input_mapping_erase( const wchar_t *sequence )
{
	int ok = 0;
	int i;
	size_t sz = al_get_count( &mappings );
	
	for( i=0; i<sz; i++ )
	{
		input_mapping_t *m = (input_mapping_t *)al_get( &mappings, i );
		if( !wcscmp( sequence, m->seq ) )
		{
			if( i != (sz-1 ) )
			{
				al_set( &mappings, i, al_get( &mappings, sz -1 ) );
			}
			al_truncate( &mappings, sz-1 );
			ok = 1;
			
			free( m );
			
			break;
			
		}
		
	}

	return ok;
	
}
예제 #3
0
void history_reset()
{
    if( current_mode )
    {
        current_mode->pos = al_get_count( &current_mode->item );
        /*
          Clear list of search matches
        */
        al_truncate( &current_mode->used, 0 );
    }
}
예제 #4
0
파일: exec.c 프로젝트: CodeMonk/fish
void exec_close( int fd )
{
	int i;

	if( fd < 0 )
	{
		debug( 0, L"Called close on invalid file descriptor " );
		return;
	}
	
	while( close(fd) == -1 )
	{
		if( errno != EINTR )
		{
			debug( 1, FD_ERROR, fd );
			wperror( L"close" );
			break;
		}
	}
	
	if( open_fds )
	{
		for( i=0; i<al_get_count( open_fds ); i++ )
		{
			int n = (int)al_get_long( open_fds, i );
			if( n == fd )
			{
				al_set_long( open_fds,
					     i,
					     al_get_long( open_fds, al_get_count( open_fds ) -1 ) );
				al_truncate( open_fds, 
					     al_get_count( open_fds ) -1 );
				break;
			}
		}
	}
}
예제 #5
0
파일: screen.c 프로젝트: brentdax/fishfish
/**
   Clear the specified array of line_t structs.
*/
static void s_reset_arr( array_list_t *l )
{
	al_foreach( l, &free_line );
	al_truncate( l, 0 );
}
예제 #6
0
/**
   Complete the specified command name. Search for executables in the
   path, executables defined using an absolute path, functions,
   builtins and directories for implicit cd commands.

   \param cmd the command string to find completions for

   \param comp the list to add all completions to
*/
static void complete_cmd( const wchar_t *cmd,
						  array_list_t *comp,
						  int use_function,
						  int use_builtin,
						  int use_command )
{
	wchar_t *path;
	wchar_t *path_cpy;
	wchar_t *nxt_path;
	wchar_t *state;
	array_list_t possible_comp;
	wchar_t *nxt_completion;

	wchar_t *cdpath = env_get(L"CDPATH");
	wchar_t *cdpath_cpy = wcsdup( cdpath?cdpath:L"." );

	if( (wcschr( cmd, L'/') != 0) || (cmd[0] == L'~' ) )
	{

		if( use_command )
		{

			if( expand_string( 0,
							   wcsdup(cmd),
							   comp,
							   ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR )
			{
				complete_cmd_desc( cmd, comp );
			}
		}
	}
	else
	{
		if( use_command )
		{

			path = env_get(L"PATH");
			if( path )
			{

				path_cpy = wcsdup( path );

				for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
				     nxt_path != 0;
				     nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
				{
					int prev_count;
					int i;
					int path_len = wcslen(nxt_path);
					int add_slash;

					if( !path_len )
					{
						continue;
					}

					add_slash = nxt_path[path_len-1]!=L'/';
					nxt_completion = wcsdupcat( nxt_path,
												add_slash?L"/":L"",
												cmd );
					if( ! nxt_completion )
						continue;

					prev_count = al_get_count( comp );

					if( expand_string( 0,
									   nxt_completion,
									   comp,
									   ACCEPT_INCOMPLETE |
									   EXECUTABLES_ONLY ) != EXPAND_ERROR )
					{
						for( i=prev_count; i<al_get_count( comp ); i++ )
						{
							completion_t *c = (completion_t *)al_get( comp, i );
							if(c->flags & COMPLETE_NO_CASE )
							{
								c->completion = halloc_wcsdup( comp, c->completion + path_len + add_slash );
							}
						}
					}
				}
				free( path_cpy );
				complete_cmd_desc( cmd, comp );
			}
		}

		/*
		  These return the original strings - don't free them
		*/

		al_init( &possible_comp );

		if( use_function )
		{
			function_get_names( &possible_comp, cmd[0] == L'_' );
			complete_strings( comp, cmd, 0, &complete_function_desc, &possible_comp, 0 );
		}

		al_truncate( &possible_comp, 0 );

		if( use_builtin )
		{
			builtin_get_names( &possible_comp );
			complete_strings( comp, cmd, 0, &builtin_get_desc, &possible_comp, 0 );
		}
		al_destroy( &possible_comp );

	}

	if( use_builtin || (use_function && function_exists( L"cd") ) )
	{
		/*
		  Tab complete implicit cd for directories in CDPATH
		*/
		if( cmd[0] != L'/' && ( wcsncmp( cmd, L"./", 2 )!=0) )
		{
			for( nxt_path = wcstok( cdpath_cpy, ARRAY_SEP_STR, &state );
				 nxt_path != 0;
				 nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
			{
				wchar_t *nxt_completion=
					wcsdupcat( nxt_path,
							   (nxt_path[wcslen(nxt_path)-1]==L'/'?L"":L"/"),
							   cmd );
				if( ! nxt_completion )
				{
					continue;
				}

				if( expand_string( 0,
								   nxt_completion,
								   comp,
								   ACCEPT_INCOMPLETE | DIRECTORIES_ONLY ) != EXPAND_ERROR )
				{
				}
			}
		}
	}

	free( cdpath_cpy );
}
예제 #7
0
/**
   Save the specified mode to file
*/
static void history_save_mode( void *n, history_mode_t *m )
{
    FILE *out;
    history_mode_t *on_disk;
    int i;
    int has_new=0;
    wchar_t *tmp_name;

    int ok = 1;

    /*
      First check if there are any new entries to save. If not, then
      we can just return
    */
    for( i=0; i<al_get_count(&m->item); i++ )
    {
        void *ptr = al_get( &m->item, i );
        has_new = item_is_new( m, ptr );
        if( has_new )
        {
            break;
        }
    }

    if( !has_new )
    {
        return;
    }

    signal_block();

    /*
      Set up on_disk variable to describe the current contents of the
      history file
    */
    on_disk = history_create_mode( m->name );
    history_load( on_disk );

    tmp_name = history_filename( on_disk, m->name, L".tmp" );

    if( tmp_name )
    {
        tmp_name = wcsdup(tmp_name );

        if( (out=wfopen( tmp_name, "w" ) ) )
        {
            hash_table_t mine;

            hash_init( &mine, &hash_item_func, &hash_item_cmp );

            for( i=0; i<al_get_count(&m->item); i++ )
            {
                void *ptr = al_get( &m->item, i );
                int is_new = item_is_new( m, ptr );
                if( is_new )
                {
                    hash_put( &mine, item_get( m, ptr ), L"" );
                }
            }

            /*
              Re-save the old history
            */
            for( i=0; ok && (i<al_get_count(&on_disk->item)); i++ )
            {
                void *ptr = al_get( &on_disk->item, i );
                item_t *i = item_get( on_disk, ptr );
                if( !hash_get( &mine, i ) )
                {
                    if( item_write( out, on_disk, ptr ) == -1 )
                    {
                        ok = 0;
                        break;
                    }
                }

            }

            hash_destroy( &mine );

            /*
              Add our own items last
            */
            for( i=0; ok && (i<al_get_count(&m->item)); i++ )
            {
                void *ptr = al_get( &m->item, i );
                int is_new = item_is_new( m, ptr );
                if( is_new )
                {
                    if( item_write( out, m, ptr ) == -1 )
                    {
                        ok = 0;
                    }
                }
            }

            if( fclose( out ) || !ok )
            {
                /*
                  This message does not have high enough priority to
                  be shown by default.
                */
                debug( 2, L"Error when writing history file" );
            }
            else
            {
                wrename( tmp_name, history_filename( on_disk, m->name, 0 ) );
            }
        }
        free( tmp_name );
    }

    halloc_free( on_disk);

    if( ok )
    {

        /*
          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 );
        }

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

    signal_unblock();
}
예제 #8
0
/**
   Go through the mmaped region and insert pointers to suitable loacations into the item list
*/
static void history_populate_from_mmap( history_mode_t *m )
{
    char *begin = m->mmap_start;
    char *end = begin + m->mmap_length;
    char *pos;

    array_list_t old_item;
    array_list_t session_item_list;
    int ignore_newline = 0;
    int do_push = 1;

    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++ )
    {

        if( do_push )
        {
            item_t *i;
            item_t *i_orig;

            ignore_newline = *pos == '#';

            i = item_get( m, pos );

            if( (i_orig=hash_get( &current_mode->session_item, i ) ) )
            {
                /*
                  This item comes from this session. Insert the
                  original item at the end of the item list.
                */
                al_push( &session_item_list, i_orig );
            }
            else
            {
                /*
                  Old item. Insert pointer directly to the item list
                */
                al_push( &m->item, pos );
            }

            do_push = 0;
        }

        switch( *pos )
        {
        case '\\':
        {
            pos++;
            break;
        }

        case '\n':
        {
            if( ignore_newline )
            {
                ignore_newline = 0;
            }
            else
            {
                do_push = 1;
            }
            break;
        }
        }
    }

    al_push_all(  &m->item, &session_item_list );
    m->pos += al_get_count( &m->item );
    al_push_all(  &m->item, &old_item );


    al_destroy( &session_item_list );
    al_destroy( &old_item );
}
예제 #9
0
파일: fish_tests.c 프로젝트: CodeMonk/fish
/**
   Test speed of completion calculations
*/
void perf_complete()
{
	wchar_t c;
	array_list_t out;
	long long t1, t2;
	int matches=0;
	double t;
	wchar_t str[3]=
	{
		0, 0, 0 
	}
	;
	int i;
	
	
	say( L"Testing completion performance" );
	al_init( &out );
	
	reader_push(L"");
	say( L"Here we go" );
	 	
	t1 = get_time();
	
	
	for( c=L'a'; c<=L'z'; c++ )
	{
		str[0]=c;
		reader_set_buffer( str, 0 );
		
		complete( str, &out );
	
		matches += al_get_count( &out );
		
		al_foreach( &out, &free );
		al_truncate( &out, 0 );
	}
	t2=get_time();
	
	t = (double)(t2-t1)/(1000000*26);
	
	say( L"One letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
	
	matches=0;
	t1 = get_time();
	for( i=0; i<LAPS; i++ )
	{
		str[0]='a'+(rand()%26);
		str[1]='a'+(rand()%26);
		
		reader_set_buffer( str, 0 );
		
		complete( str, &out );
	
		matches += al_get_count( &out );
		
		al_foreach( &out, &free );
		al_truncate( &out, 0 );
	}
	t2=get_time();
	
	t = (double)(t2-t1)/(1000000*LAPS);
	
	say( L"Two letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
	
	al_destroy( &out );

	reader_pop();
	
}