support optional output args in the cli
the cli interface now supports optional output args ... C API next
This commit is contained in:
parent
bbaef3dad1
commit
7fe104fee6
@ -4,6 +4,7 @@
|
||||
- added VIPS_ARGUMENT_APPEND to help control arg ordering
|
||||
- generate has a 'stop' param to signal successful early termination
|
||||
- added optional output args, eg. x/y for min
|
||||
- CLI supports optional output args
|
||||
|
||||
10/8/11 started 7.26.3
|
||||
- don't use G_VALUE_COLLECT_INIT(), many platforms do not have a glib this
|
||||
|
31
TODO
31
TODO
@ -1,34 +1,3 @@
|
||||
- see TODO comment on vips_call_options_set()
|
||||
|
||||
|
||||
|
||||
|
||||
- cmd line interface needs to print optional output args, if requested
|
||||
|
||||
eg.
|
||||
|
||||
$ vips min fred.v
|
||||
12
|
||||
$ vips min -x fred.v
|
||||
12
|
||||
300
|
||||
|
||||
the switch is there, but breaks an assert:
|
||||
|
||||
$ vips min -x babe.jpg
|
||||
VIPS:ERROR:object.c:1178:vips_object_set_argument_from_string: assertion
|
||||
failed: (argument_class->flags & VIPS_ARGUMENT_INPUT)
|
||||
Aborted
|
||||
|
||||
options are being made incorrectly:
|
||||
|
||||
$ vips min --help
|
||||
-y, --y=gint Vertical position of minimum
|
||||
|
||||
--y should not have an arg
|
||||
|
||||
|
||||
|
||||
- C interface needs to look for optional output args in final psss, eg.
|
||||
|
||||
vips_min( im, &min,
|
||||
|
@ -134,6 +134,10 @@ typedef struct _VipsArgumentClass {
|
||||
typedef struct _VipsArgumentInstance {
|
||||
VipsArgument parent;
|
||||
|
||||
/* The class we are part of.
|
||||
*/
|
||||
VipsArgumentClass *argument_class;
|
||||
|
||||
/* The object we are attached to.
|
||||
*/
|
||||
VipsObject *object;
|
||||
@ -154,9 +158,9 @@ typedef struct _VipsArgumentInstance {
|
||||
typedef GHashTable VipsArgumentTable;
|
||||
|
||||
VipsArgumentInstance *vips__argument_get_instance( VipsArgumentClass *,
|
||||
VipsObject *);
|
||||
VipsObject * );
|
||||
VipsArgument *vips__argument_table_lookup( VipsArgumentTable *,
|
||||
GParamSpec *);
|
||||
GParamSpec * );
|
||||
void vips__object_set_member( VipsObject *object, GParamSpec *pspec,
|
||||
GObject **member, GObject *argument );
|
||||
typedef void *(*VipsArgumentMapFn)( VipsObject *, GParamSpec *,
|
||||
|
@ -366,6 +366,7 @@ vips_argument_init( VipsObject *object )
|
||||
argument_instance = g_new( VipsArgumentInstance, 1 );
|
||||
|
||||
((VipsArgument *) argument_instance)->pspec = pspec;
|
||||
argument_instance->argument_class = argument_class;
|
||||
argument_instance->object = object;
|
||||
argument_instance->assigned = FALSE;
|
||||
argument_instance->close_id = 0;
|
||||
|
@ -504,7 +504,7 @@ vips_call_split( const char *operation_name, va_list optional, ... )
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_call_find_pspec_char( VipsObject *object,
|
||||
vips_call_find_pspec( VipsObject *object,
|
||||
GParamSpec *pspec,
|
||||
VipsArgumentClass *argument_class,
|
||||
VipsArgumentInstance *argument_instance,
|
||||
@ -512,31 +512,42 @@ vips_call_find_pspec_char( VipsObject *object,
|
||||
{
|
||||
const char *name = (const char *) a;
|
||||
|
||||
/* One char names we assume are "-x" style abbreviations, longer names
|
||||
* we match the whole string.
|
||||
*/
|
||||
if( !(argument_class->flags & VIPS_ARGUMENT_REQUIRED) &&
|
||||
(argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) &&
|
||||
!argument_instance->assigned &&
|
||||
g_param_spec_get_name( pspec )[0] == name[0] )
|
||||
return( pspec );
|
||||
!argument_instance->assigned )
|
||||
if( (strlen( name ) == 1 &&
|
||||
g_param_spec_get_name( pspec )[0] == name[0]) ||
|
||||
strcmp( g_param_spec_get_name( pspec ), name ) == 0 )
|
||||
return( argument_instance );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_call_find_pspec_name( VipsObject *object,
|
||||
GParamSpec *pspec,
|
||||
VipsArgumentClass *argument_class,
|
||||
VipsArgumentInstance *argument_instance,
|
||||
void *a, void *b )
|
||||
/* Keep this stuff around for output args.
|
||||
*/
|
||||
typedef struct _VipsCallOptionOutput {
|
||||
VipsArgumentInstance *argument_instance;
|
||||
const char *value;
|
||||
} VipsCallOptionOutput;
|
||||
|
||||
static void
|
||||
vips_call_option_output( VipsObject *object,
|
||||
VipsCallOptionOutput *output )
|
||||
{
|
||||
const char *name = (const char *) a;
|
||||
VipsArgumentInstance *argument_instance = output->argument_instance;
|
||||
GParamSpec *pspec = ((VipsArgument *) argument_instance)->pspec;
|
||||
|
||||
if( !(argument_class->flags & VIPS_ARGUMENT_REQUIRED) &&
|
||||
(argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) &&
|
||||
!argument_instance->assigned &&
|
||||
strcmp( g_param_spec_get_name( pspec ), name ) == 0 )
|
||||
return( pspec );
|
||||
if( vips_object_get_argument_to_string( object,
|
||||
g_param_spec_get_name( pspec ), output->value ) ) {
|
||||
/* FIXME .. Hmm what can we do here? If an arg is image
|
||||
* output, for example, we will lose the error.
|
||||
*/
|
||||
}
|
||||
|
||||
return( NULL );
|
||||
g_free( output );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -545,6 +556,8 @@ vips_call_options_set( const gchar *option_name, const gchar *value,
|
||||
{
|
||||
VipsOperation *operation = (VipsOperation *) data;
|
||||
const char *name;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
VipsArgumentClass *argument_class;
|
||||
GParamSpec *pspec;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_call_options_set: %s = %s\n",
|
||||
@ -555,34 +568,39 @@ vips_call_options_set( const gchar *option_name, const gchar *value,
|
||||
for( name = option_name; *name == '-'; name++ )
|
||||
;
|
||||
|
||||
/* If this is a single-character name, find the first unset pspec with
|
||||
* that initial. Otherwise, search for a spec of that name.
|
||||
*/
|
||||
if( strlen( name ) == 1 )
|
||||
pspec = (GParamSpec *) vips_argument_map(
|
||||
if( !(argument_instance = (VipsArgumentInstance *)
|
||||
vips_argument_map(
|
||||
VIPS_OBJECT( operation ),
|
||||
vips_call_find_pspec_char,
|
||||
(void *) name, NULL );
|
||||
else
|
||||
pspec = (GParamSpec *) vips_argument_map(
|
||||
VIPS_OBJECT( operation ),
|
||||
vips_call_find_pspec_name,
|
||||
(void *) name, NULL );
|
||||
if( !pspec ) {
|
||||
vips_call_find_pspec, (void *) name, NULL )) ) {
|
||||
vips_error( VIPS_OBJECT( operation )->nickname,
|
||||
_( "unknown argument '%s'" ), name );
|
||||
return( FALSE );
|
||||
}
|
||||
argument_class = argument_instance->argument_class;
|
||||
pspec = ((VipsArgument *) argument_instance)->pspec;
|
||||
|
||||
/*
|
||||
*
|
||||
* FIXME ... for output args, need to attach a close callback to
|
||||
* operation to write the value
|
||||
*
|
||||
*/
|
||||
if( vips_object_set_argument_from_string( VIPS_OBJECT( operation ),
|
||||
name, value ) )
|
||||
return( FALSE );
|
||||
if( (argument_class->flags & VIPS_ARGUMENT_INPUT) ) {
|
||||
if( vips_object_set_argument_from_string(
|
||||
VIPS_OBJECT( operation ),
|
||||
g_param_spec_get_name( pspec ), value ) )
|
||||
return( FALSE );
|
||||
}
|
||||
else if( (argument_class->flags & VIPS_ARGUMENT_OUTPUT) ) {
|
||||
VipsCallOptionOutput *output;
|
||||
|
||||
/* We can't do output now, we have to attach a callback to do
|
||||
* the processing after the operation has run.
|
||||
*
|
||||
* FIXME ... something like posteval or postbuild might be
|
||||
* better for this?
|
||||
*/
|
||||
output = g_new( VipsCallOptionOutput, 1 );
|
||||
output->argument_instance = argument_instance;
|
||||
output->value = value;
|
||||
g_signal_connect( operation, "preclose",
|
||||
G_CALLBACK( vips_call_option_output ),
|
||||
output );
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user