diff --git a/builtin.c b/builtin.c index fe59ce292..7b73d24f3 100644 --- a/builtin.c +++ b/builtin.c @@ -1252,6 +1252,7 @@ static int builtin_functions( wchar_t **argv ) int show_hidden=0; int res = STATUS_BUILTIN_OK; int query = 0; + int rename = 0; woptind=0; @@ -1282,6 +1283,10 @@ static int builtin_functions( wchar_t **argv ) L"query", no_argument, 0, 'q' } , + { + L"rename", no_argument, 0, 'r' + } + , { 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:nahqr", 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 'r': + rename = 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, rename and list are mutually exclusive */ - if( (erase + (!!desc) + list + query) > 1 ) + if( (erase + (!!desc) + list + query + rename) > 1 ) { sb_printf( sb_err, _( L"%ls: Invalid combination of options\n" ), @@ -1434,6 +1443,50 @@ static int builtin_functions( wchar_t **argv ) al_destroy( &names ); return STATUS_BUILTIN_OK; } + else if( rename ) + { + 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; + } + + // keep things simple: don't allow existing names to be rename targets. + if( function_exists( new_func ) ) + { + sb_printf( sb_err, + _( L"%ls: Function '%ls' already exists. Cannot rename '%ls'\n" ), + argv[0], + new_func, + current_func ); + builtin_print_help( argv[0], sb_err ); + + return STATUS_BUILTIN_ERROR; + } + + function_rename( current_func, new_func ); + return STATUS_BUILTIN_OK; + } for( i=woptind; idefinition_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; inamed_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->definition_file = 0; + d->is_autoload = 0; + d->shadows = orig_d->shadows; + } + + hash_put( &function, intern(new_name), d ); + + // wire up the same events... if any. + ev.type = EVENT_ANY; + ev.function_name = name; + event_get(&ev, fn_events); + + if( fn_events ) + { + ev.function_name = new_name; + + for( i=0; itype; + ev.param1 = orig_ev->param1; + event_add_handler( &ev ); + } + } + return 1; +} + +void function_rename( const wchar_t *name, const wchar_t *new_name ) +{ + if( function_copy( name, new_name ) ) + function_remove( name ); +} + + int function_exists( const wchar_t *cmd ) { diff --git a/function.h b/function.h index 7e1729486..31243663f 100644 --- a/function.h +++ b/function.h @@ -131,4 +131,15 @@ 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 ); + +/** + Renames the specified function. +*/ +void function_rename( const wchar_t *name, const wchar_t *new_name ); + #endif