better usage message
more sensible output for "vips max" or "vips getpoint"
This commit is contained in:
parent
b80b503474
commit
3bceb5286b
51
TODO
51
TODO
@ -24,57 +24,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- try
|
||||
|
||||
$ vips getpoint
|
||||
usage:
|
||||
getpoint in out-array x y
|
||||
read a point from an image
|
||||
where:
|
||||
in - Input image, input VipsImage
|
||||
out-array - Array of output values, output VipsArrayDouble
|
||||
x - Getpoint to read from, input gint
|
||||
y - Getpoint to read from, input gint
|
||||
|
||||
$ vips max
|
||||
usage:
|
||||
max in out
|
||||
find image maximum
|
||||
where:
|
||||
in - Input image, input VipsImage
|
||||
out - Output value, output gdouble
|
||||
optional arguments:
|
||||
x - Horizontal position of maximum, output gint
|
||||
y - Vertical position of maximum, output gint
|
||||
size - Number of maximum values to find, input gint
|
||||
out-array - Array of output values, output VipsArrayDouble
|
||||
x-array - Array of horizontal positions, output VipsArrayInt
|
||||
y-array - Array of vertical positions, output VipsArrayInt
|
||||
|
||||
don't list out-array or out as args in the usage line, since they don't need
|
||||
an arg ... these args should be in a separate section, I guess?
|
||||
|
||||
put description first
|
||||
|
||||
should be:
|
||||
|
||||
$ vips getpoint
|
||||
read a point from an image
|
||||
usage:
|
||||
getpoint in x y
|
||||
prints:
|
||||
out-array
|
||||
where:
|
||||
in - Input image, input VipsImage
|
||||
out-array - Array of output values, output VipsArrayDouble
|
||||
x - Getpoint to read from, input gint
|
||||
y - Getpoint to read from, input gint
|
||||
|
||||
|
||||
|
||||
|
||||
- need to do mosaicing
|
||||
|
||||
- now vips_linear() has uchar output, can we do something with orc?
|
||||
|
@ -304,6 +304,7 @@ typedef void *(*VipsArgumentClassMapFn)( VipsObjectClass *, GParamSpec *,
|
||||
VipsArgumentClass *, void *a, void *b );
|
||||
void *vips_argument_class_map( VipsObjectClass *object_class,
|
||||
VipsArgumentClassMapFn fn, void *a, void *b );
|
||||
gboolean vips_argument_class_needsstring( VipsArgumentClass *argument_class );
|
||||
int vips_object_get_argument( VipsObject *object, const char *name,
|
||||
GParamSpec **pspec,
|
||||
VipsArgumentClass **argument_class,
|
||||
|
@ -472,6 +472,40 @@ vips_argument_class_map( VipsObjectClass *object_class,
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* Does an vipsargument need an argument to write to? For example, an image
|
||||
* output needs a filename, a double output just prints.
|
||||
*/
|
||||
gboolean
|
||||
vips_argument_class_needsstring( VipsArgumentClass *argument_class )
|
||||
{
|
||||
GParamSpec *pspec = ((VipsArgument *) argument_class)->pspec;
|
||||
|
||||
GType otype;
|
||||
VipsObjectClass *oclass;
|
||||
|
||||
if( G_IS_PARAM_SPEC_BOOLEAN( pspec ) )
|
||||
/* Bools, input or output, don't need args.
|
||||
*/
|
||||
return( FALSE );
|
||||
|
||||
if( argument_class->flags & VIPS_ARGUMENT_INPUT )
|
||||
/* All other inputs need something.
|
||||
*/
|
||||
return( TRUE );
|
||||
|
||||
/* Just output objects.
|
||||
*/
|
||||
|
||||
if( (otype = G_PARAM_SPEC_VALUE_TYPE( pspec )) &&
|
||||
g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_ref( otype )) )
|
||||
/* For now, only vipsobject subclasses can ask for args.
|
||||
*/
|
||||
return( oclass->output_needs_arg );
|
||||
else
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
/* Create a VipsArgumentInstance for each installed argument property. Ideally
|
||||
* we'd do this during _init() but g_object_class_find_property() does not seem
|
||||
* to work then :-( so we have to delay it until first access. See
|
||||
@ -1766,8 +1800,6 @@ vips_object_argument_needsstring( VipsObject *object, const char *name )
|
||||
GParamSpec *pspec;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
GType otype;
|
||||
VipsObjectClass *oclass;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_object_argument_needsstring: %s\n", name );
|
||||
@ -1777,27 +1809,7 @@ vips_object_argument_needsstring( VipsObject *object, const char *name )
|
||||
&pspec, &argument_class, &argument_instance ) )
|
||||
return( -1 );
|
||||
|
||||
if( G_IS_PARAM_SPEC_BOOLEAN( pspec ) )
|
||||
/* Bools, input or output, don't need args.
|
||||
*/
|
||||
return( FALSE );
|
||||
|
||||
if( argument_class->flags & VIPS_ARGUMENT_INPUT )
|
||||
/* All other inputs need something.
|
||||
*/
|
||||
return( TRUE );
|
||||
|
||||
/* Just output objects.
|
||||
*/
|
||||
|
||||
if( (otype = G_PARAM_SPEC_VALUE_TYPE( pspec )) &&
|
||||
g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_ref( otype )) )
|
||||
/* For now, only vipsobject subclasses can ask for args.
|
||||
*/
|
||||
return( oclass->output_needs_arg );
|
||||
else
|
||||
return( FALSE );
|
||||
return( vips_argument_class_needsstring( argument_class ) );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -119,30 +119,67 @@ vips_operation_dispose( GObject *gobject )
|
||||
G_OBJECT_CLASS( vips_operation_parent_class )->dispose( gobject );
|
||||
}
|
||||
|
||||
/* What to show about the argument.
|
||||
/* Three basic types of command-line argument.
|
||||
*
|
||||
* INPUTS: things like an input image, there is a filename argument on the
|
||||
* command-line which is used to construct the operation argument.
|
||||
*
|
||||
* NOARG_OUTPUT: things like the result of VipsMax, there's no correspondiong
|
||||
* command-line argument, we just print the value.
|
||||
*
|
||||
* OPTIONS: optional arguments.
|
||||
*
|
||||
* NONE: hide this thing.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
USAGE_INPUTS,
|
||||
USAGE_NOARG_OUTPUT,
|
||||
USAGE_OPTIONS,
|
||||
USAGE_NONE
|
||||
} UsageType;
|
||||
|
||||
typedef struct {
|
||||
char *message; /* header message on first print */
|
||||
gboolean required; /* show required args or optional */
|
||||
gboolean oftype; /* "is of type" message */
|
||||
UsageType type; /* Type of arg to select */
|
||||
gboolean oftype; /* Show as "of type" */
|
||||
int n; /* Arg number */
|
||||
} VipsOperationClassUsage;
|
||||
|
||||
/* Put an arg into one the categories above.
|
||||
*/
|
||||
static UsageType
|
||||
vips_operation_class_usage_classify( VipsArgumentClass *argument_class )
|
||||
{
|
||||
if( !(argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) ||
|
||||
(argument_class->flags & VIPS_ARGUMENT_DEPRECATED) )
|
||||
return( USAGE_NONE );
|
||||
|
||||
if( !(argument_class->flags & VIPS_ARGUMENT_REQUIRED) )
|
||||
return( USAGE_OPTIONS );
|
||||
|
||||
if( vips_argument_class_needsstring( argument_class ) )
|
||||
return( USAGE_INPUTS );
|
||||
|
||||
if( (argument_class->flags & VIPS_ARGUMENT_OUTPUT) &&
|
||||
!vips_argument_class_needsstring( argument_class ) )
|
||||
return( USAGE_NOARG_OUTPUT );
|
||||
|
||||
return( USAGE_NONE );
|
||||
}
|
||||
|
||||
static void *
|
||||
vips_operation_class_usage_arg( VipsObjectClass *object_class,
|
||||
GParamSpec *pspec, VipsArgumentClass *argument_class,
|
||||
VipsBuf *buf, VipsOperationClassUsage *usage )
|
||||
{
|
||||
/* Only show construct args ... others are internal.
|
||||
*/
|
||||
if( usage->required ==
|
||||
((argument_class->flags & VIPS_ARGUMENT_REQUIRED) != 0) &&
|
||||
(argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) &&
|
||||
!(argument_class->flags & VIPS_ARGUMENT_DEPRECATED) ) {
|
||||
if( usage->message && usage->n == 0 )
|
||||
if( usage->type ==
|
||||
vips_operation_class_usage_classify( argument_class ) ) {
|
||||
if( usage->message &&
|
||||
usage->n == 0 )
|
||||
vips_buf_appendf( buf, "%s\n", usage->message );
|
||||
|
||||
if( usage->oftype ) {
|
||||
if( usage->oftype )
|
||||
vips_buf_appendf( buf, " %-12s - %s, %s %s\n",
|
||||
g_param_spec_get_name( pspec ),
|
||||
g_param_spec_get_blurb( pspec ),
|
||||
@ -150,11 +187,11 @@ vips_operation_class_usage_arg( VipsObjectClass *object_class,
|
||||
_( "input" ) : _( "output" ),
|
||||
g_type_name(
|
||||
G_PARAM_SPEC_VALUE_TYPE( pspec ) ) );
|
||||
}
|
||||
else {
|
||||
if( usage->n > 0 )
|
||||
vips_buf_appends( buf, " " );
|
||||
vips_buf_appends( buf, g_param_spec_get_name( pspec ) );
|
||||
if( usage->n > 0 )
|
||||
vips_buf_appends( buf, " " );
|
||||
vips_buf_appends( buf,
|
||||
g_param_spec_get_name( pspec ) );
|
||||
}
|
||||
|
||||
usage->n += 1;
|
||||
@ -170,11 +207,14 @@ vips_operation_usage( VipsOperationClass *class, VipsBuf *buf )
|
||||
|
||||
VipsOperationClassUsage usage;
|
||||
|
||||
vips_buf_appendf( buf, "%s\n", object_class->description );
|
||||
vips_buf_appendf( buf, "usage:\n" );
|
||||
|
||||
/* First pass through args: show the required names.
|
||||
*/
|
||||
vips_buf_appendf( buf, " %s ", object_class->nickname );
|
||||
usage.message = NULL;
|
||||
usage.required = TRUE;
|
||||
usage.type = USAGE_INPUTS;
|
||||
usage.oftype = FALSE;
|
||||
usage.n = 0;
|
||||
vips_argument_class_map( object_class,
|
||||
@ -182,12 +222,21 @@ vips_operation_usage( VipsOperationClass *class, VipsBuf *buf )
|
||||
buf, &usage );
|
||||
vips_buf_appends( buf, "\n" );
|
||||
|
||||
vips_buf_appendf( buf, "%s\n", object_class->description );
|
||||
|
||||
/* Show required types.
|
||||
*/
|
||||
usage.message = "where:";
|
||||
usage.required = TRUE;
|
||||
usage.type = USAGE_INPUTS;
|
||||
usage.oftype = TRUE;
|
||||
usage.n = 0;
|
||||
vips_argument_class_map( object_class,
|
||||
(VipsArgumentClassMapFn) vips_operation_class_usage_arg,
|
||||
buf, &usage );
|
||||
|
||||
/* Show outputs with no input arg (eg. output maximum value for
|
||||
* vips_max()).
|
||||
*/
|
||||
usage.message = "outputs:";
|
||||
usage.type = USAGE_NOARG_OUTPUT;
|
||||
usage.oftype = TRUE;
|
||||
usage.n = 0;
|
||||
vips_argument_class_map( object_class,
|
||||
@ -197,7 +246,7 @@ vips_operation_usage( VipsOperationClass *class, VipsBuf *buf )
|
||||
/* Show optional args.
|
||||
*/
|
||||
usage.message = "optional arguments:";
|
||||
usage.required = FALSE;
|
||||
usage.type = USAGE_OPTIONS;
|
||||
usage.oftype = TRUE;
|
||||
usage.n = 0;
|
||||
vips_argument_class_map( object_class,
|
||||
@ -367,8 +416,7 @@ vips_operation_class_print_usage( VipsOperationClass *operation_class )
|
||||
VipsBuf buf = VIPS_BUF_STATIC( str );
|
||||
|
||||
operation_class->usage( operation_class, &buf );
|
||||
printf( "%s", _( "usage:" ) );
|
||||
printf( "\n%s", vips_buf_all( &buf ) );
|
||||
printf( "%s", vips_buf_all( &buf ) );
|
||||
}
|
||||
|
||||
VipsOperation *
|
||||
|
Loading…
Reference in New Issue
Block a user