diff options
-rw-r--r-- | builtin.c | 78 | ||||
-rw-r--r-- | doc_src/functions.txt | 4 | ||||
-rw-r--r-- | function.c | 37 | ||||
-rw-r--r-- | function.h | 6 |
4 files changed, 118 insertions, 7 deletions
@@ -1252,6 +1252,7 @@ static int builtin_functions( wchar_t **argv ) int show_hidden=0; int res = STATUS_BUILTIN_OK; int query = 0; + int copy = 0; woptind=0; @@ -1283,6 +1284,10 @@ static int builtin_functions( wchar_t **argv ) } , { + L"copy", no_argument, 0, 'c' + } + , + { 0, 0, 0, 0 } } @@ -1294,7 +1299,7 @@ static int builtin_functions( wchar_t **argv ) int opt = wgetopt_long( argc, argv, - L"ed:nahq", + L"ed:nahqc", long_options, &opt_index ); if( opt == -1 ) @@ -1305,10 +1310,10 @@ static int builtin_functions( wchar_t **argv ) case 0: if(long_options[opt_index].flag != 0) break; - sb_printf( sb_err, - BUILTIN_ERR_UNKNOWN, - argv[0], - long_options[opt_index].name ); + sb_printf( sb_err, + BUILTIN_ERR_UNKNOWN, + argv[0], + long_options[opt_index].name ); builtin_print_help( argv[0], sb_err ); @@ -1338,6 +1343,10 @@ static int builtin_functions( wchar_t **argv ) query = 1; break; + case 'c': + copy = 1; + break; + case '?': builtin_unknown_option( argv[0], argv[woptind-1] ); return STATUS_BUILTIN_ERROR; @@ -1347,9 +1356,9 @@ static int builtin_functions( wchar_t **argv ) } /* - Erase, desc, query and list are mutually exclusive + Erase, desc, query, copy and list are mutually exclusive */ - if( (erase + (!!desc) + list + query) > 1 ) + if( (erase + (!!desc) + list + query + copy) > 1 ) { sb_printf( sb_err, _( L"%ls: Invalid combination of options\n" ), @@ -1434,6 +1443,61 @@ static int builtin_functions( wchar_t **argv ) al_destroy( &names ); return STATUS_BUILTIN_OK; } + else if( copy ) + { + wchar_t *current_func; + wchar_t *new_func; + + if( argc-woptind != 2 ) + { + sb_printf( sb_err, + _( L"%ls: Expected exactly two names (current function name, and new function name)\n" ), + argv[0] ); + builtin_print_help ( argv[0], sb_err ); + + return STATUS_BUILTIN_ERROR; + } + current_func = argv[woptind]; + new_func = argv[woptind+1]; + + if( !function_exists( current_func ) ) + { + sb_printf( sb_err, + _( L"%ls: Function '%ls' does not exist\n" ), + argv[0], + current_func ); + builtin_print_help( argv[0], sb_err ); + + return STATUS_BUILTIN_ERROR; + } + + if( (wcsfuncname( new_func ) != 0) || parser_keywords_is_reserved( new_func ) ) + { + sb_printf( sb_err, + _( L"%ls: Illegal function name '%ls'\n"), + argv[0], + new_func ); + builtin_print_help( argv[0], sb_err ); + return STATUS_BUILTIN_ERROR; + } + + // keep things simple: don't allow existing names to be copy targets. + if( function_exists( new_func ) ) + { + sb_printf( sb_err, + _( L"%ls: Function '%ls' already exists. Cannot create copy '%ls'\n" ), + argv[0], + new_func, + current_func ); + builtin_print_help( argv[0], sb_err ); + + return STATUS_BUILTIN_ERROR; + } + + if( function_copy( current_func, new_func ) ) + return STATUS_BUILTIN_OK; + return STATUS_BUILTIN_ERROR; + } for( i=woptind; i<argc; i++ ) { diff --git a/doc_src/functions.txt b/doc_src/functions.txt index 4e5d7ddf..928cd545 100644 --- a/doc_src/functions.txt +++ b/doc_src/functions.txt @@ -8,6 +8,7 @@ This builtin command is used to print or erase functions. - <code>-a</code> or <code>--all</code> list all functions, even those whose name start with an underscore. +- <code>-c OLDNAME NEWNAME</code> or <code>--copy OLDNAME NEWNAME</code> creates a new function named NEWNAME, using the definition of the OLDNAME function. - <code>-d DESCRIPTION</code> or <code>--description=DESCRIPTION</code> change the description of this function - <code>-e</code> or <code>--erase</code> causes the specified functions to be erased. - <code>-h</code> or <code>--help</code> display a help message and exit @@ -23,5 +24,8 @@ Automatically loaded functions can not be removed using functions -e. Either remove the definition file or change the $fish_function_path variable to remove autoloaded functions. +Function copies, created with -c, will not have any event/signal/on-exit +notifications that the original may have had. + The exit status of the functions builtin is the number functions specified in the argument list that do not exist. @@ -218,6 +218,43 @@ void function_add( function_data_t *data ) } +int function_copy( const wchar_t *name, const wchar_t *new_name ) +{ + int i; + function_internal_data_t *d, *orig_d; + + CHECK( name, 0 ); + CHECK( new_name, 0 ); + + orig_d = (function_internal_data_t *)hash_get(&function, name); + if( !orig_d ) + return 0; + + d = halloc(0, sizeof( function_internal_data_t ) ); + d->definition_offset = orig_d->definition_offset; + d->definition = halloc_wcsdup( d, orig_d->definition ); + if( orig_d->named_arguments ) + { + d->named_arguments = al_halloc( d ); + for( i=0; i<al_get_count( orig_d->named_arguments ); i++ ) + { + al_push( d->named_arguments, halloc_wcsdup( d, (wchar_t *)al_get( orig_d->named_arguments, i ) ) ); + } + d->description = orig_d->description?halloc_wcsdup(d, orig_d->description):0; + d->shadows = orig_d->shadows; + + // This new instance of the function shouldn't be tied to the def + // file of the original. + d->definition_file = 0; + d->is_autoload = 0; + } + + hash_put( &function, intern(new_name), d ); + + return 1; +} + + int function_exists( const wchar_t *cmd ) { @@ -131,4 +131,10 @@ array_list_t *function_get_named_arguments( const wchar_t *name ); */ int function_get_shadows( const wchar_t *name ); +/** + Creates a new function using the same definition as the specified function. + Returns non-zero if copy is successful. +*/ +int function_copy( const wchar_t *name, const wchar_t *new_name ); + #endif |