[vlc-devel] vlc --help is useless on windows

Brian Robb vascy at hotmail.com
Sun Sep 4 03:19:56 CEST 2005


The command: vlc --help is useless on windows, because vlc spawns a dos 
window
and prints the help info into it, leaving all but the last bit of help 
visible.

(You can't scroll up on windows...)
You can't redirect it like: "vlc --help > help.txt" so you're stuck.

Solution: print the help info to a text file...

Here's what I did:

In libvlc.c I changed the Help function to (Line 2046, libvlc.c):


static void Help( vlc_t *p_this, char const *psz_help_name )
{
	FILE* output = NULL;

#ifdef WIN32
    ShowConsole();
#endif

#ifdef WIN32
	output = fopen("vlc-help.txt", "wt+"); // wt+ rather than wb+ to convert \n 
into \r\n
#endif

	if (output == NULL) {
		output = stderr;
	}

    if( psz_help_name && !strcmp( psz_help_name, "help" ) )
    {
        fprintf( output, VLC_USAGE, p_this->psz_object_name );
        Usage( p_this, output, "help" );
        Usage( p_this, output, "main" );
    }
    else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
    {
        fprintf( stdout, VLC_USAGE, p_this->psz_object_name );
        Usage( p_this, output, NULL );
    }
    else if( psz_help_name )
    {
        Usage( p_this, output, psz_help_name );
    }

#ifdef WIN32
	if (output != NULL && (output != stderr && output != stdout)) {
		fprintf (stderr, "Created vlc-help.txt...\n");
		fclose(output);
	}
    output = NULL;
#endif

#ifdef WIN32        /* Pause the console because it's destroyed when we exit 
*/
    PauseConsole();
#endif
}

Note: If you comment out the line:
	output = fopen("vlc-help.txt", "wt+"); // wt+ rather than wb+ to convert \n 
into \r\n
It'll revert to the previous way of doing things.



-------------------------------------------------

Then change the prototype for Usage to (Line 100, libvlc.c):

static void Usage         ( vlc_t *, FILE* output, char const 
*psz_module_name );


I then changed the Usage function to (Line 2096, libvlc.c):
( Note I've just added a parameter FILE* output
  and changed fprintf (stderr, ...); to fprintf(output, ...); )


static void Usage( vlc_t *p_this, FILE* output, char const *psz_module_name 
)
{
#define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
    /* short option ------'    |     | | | |  | |
     * option name ------------'     | | | |  | |
     * <bra -------------------------' | | |  | |
     * option type or "" --------------' | |  | |
     * ket> -----------------------------' |  | |
     * padding spaces ---------------------'  | |
     * comment -------------------------------' |
     * comment suffix --------------------------'
     *
     * The purpose of having bra and ket is that we might i18n them as well.
     */
#define LINE_START 8
#define PADDING_SPACES 25
    vlc_list_t *p_list;
    module_t *p_parser;
    module_config_t *p_item;
    char psz_spaces_text[PADDING_SPACES+LINE_START+1];
    char psz_spaces_longtext[LINE_START+3];
    char psz_format[sizeof(FORMAT_STRING)];
    char psz_buffer[10000];
    char psz_short[4];
    int i_index;
    int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
    vlc_bool_t b_advanced = config_GetInt( p_this, "advanced" );
    vlc_bool_t b_description;

    memset( psz_spaces_text, ' ', PADDING_SPACES+LINE_START );
    psz_spaces_text[PADDING_SPACES+LINE_START] = '\0';
    memset( psz_spaces_longtext, ' ', LINE_START+2 );
    psz_spaces_longtext[LINE_START+2] = '\0';

    strcpy( psz_format, FORMAT_STRING );

    /* List all modules */
    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );

    /* Enumerate the config for each module */
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
    {
        vlc_bool_t b_help_module;

        p_parser = (module_t *)p_list->p_values[i_index].p_object ;

        if( psz_module_name && strcmp( psz_module_name,
                                       p_parser->psz_object_name ) )
        {
            continue;
        }

        /* Ignore modules without config options */
        if( !p_parser->i_config_items )
        {
            continue;
        }

        /* Ignore modules with only advanced config options if requested */
        if( !b_advanced )
        {
            for( p_item = p_parser->p_config;
                 p_item->i_type != CONFIG_HINT_END;
                 p_item++ )
            {
                if( (p_item->i_type & CONFIG_ITEM) &&
                    !p_item->b_advanced ) break;
            }
            if( p_item->i_type == CONFIG_HINT_END ) continue;
        }

        /* Print name of module */
        if( strcmp( "main", p_parser->psz_object_name ) )

		fprintf( output, "\n %s\n", p_parser->psz_longname );

        b_help_module = !strcmp( "help", p_parser->psz_object_name );

        /* Print module options */
        for( p_item = p_parser->p_config;
             p_item->i_type != CONFIG_HINT_END;
             p_item++ )
        {
            char *psz_text, *psz_spaces = psz_spaces_text;
            char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
            char *psz_suf = "", *psz_prefix = NULL;
            signed int i;

            /* Skip deprecated options */
            if( p_item->psz_current )
            {
                continue;
            }
            /* Skip advanced options if requested */
            if( p_item->b_advanced && !b_advanced )
            {
                continue;
            }

            switch( p_item->i_type )
            {
            case CONFIG_HINT_CATEGORY:
            case CONFIG_HINT_USAGE:
                if( !strcmp( "main", p_parser->psz_object_name ) )
                fprintf( output, "\n %s\n", p_item->psz_text );
                break;

            case CONFIG_ITEM_STRING:
            case CONFIG_ITEM_FILE:
            case CONFIG_ITEM_DIRECTORY:
            case CONFIG_ITEM_MODULE: /* We could also have "=<" here */
            case CONFIG_ITEM_MODULE_CAT:
            case CONFIG_ITEM_MODULE_LIST:
            case CONFIG_ITEM_MODULE_LIST_CAT:
                psz_bra = " <"; psz_type = _("string"); psz_ket = ">";

                if( p_item->ppsz_list )
                {
                    psz_bra = " {";
                    psz_type = psz_buffer;
                    psz_type[0] = '\0';
                    for( i = 0; p_item->ppsz_list[i]; i++ )
                    {
                        if( i ) strcat( psz_type, "," );
                        strcat( psz_type, p_item->ppsz_list[i] );
                    }
                    psz_ket = "}";
                }
                break;
            case CONFIG_ITEM_INTEGER:
            case CONFIG_ITEM_KEY: /* FIXME: do something a bit more clever 
*/
                psz_bra = " <"; psz_type = _("integer"); psz_ket = ">";

                if( p_item->i_list )
                {
                    psz_bra = " {";
                    psz_type = psz_buffer;
                    psz_type[0] = '\0';
                    for( i = 0; p_item->ppsz_list_text[i]; i++ )
                    {
                        if( i ) strcat( psz_type, ", " );
                        sprintf( psz_type + strlen(psz_type), "%i (%s)",
                                 p_item->pi_list[i],
                                 p_item->ppsz_list_text[i] );
                    }
                    psz_ket = "}";
                }
                break;
            case CONFIG_ITEM_FLOAT:
                psz_bra = " <"; psz_type = _("float"); psz_ket = ">";
                break;
            case CONFIG_ITEM_BOOL:
                psz_bra = ""; psz_type = ""; psz_ket = "";
                if( !b_help_module )
                {
                    psz_suf = p_item->i_value ? _(" (default enabled)") :
                                                _(" (default disabled)");
                }
                break;
            }

            if( !psz_type )
            {
                continue;
            }

            /* Add short option if any */
            if( p_item->i_short )
            {
                sprintf( psz_short, "-%c,", p_item->i_short );
            }
            else
            {
                strcpy( psz_short, "   " );
            }

            i = PADDING_SPACES - strlen( p_item->psz_name )
                 - strlen( psz_bra ) - strlen( psz_type )
                 - strlen( psz_ket ) - 1;

            if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
            {
                psz_prefix =  ", --no-";
                i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
            }

            if( i < 0 )
            {
                psz_spaces[0] = '\n';
                i = 0;
            }
            else
            {
                psz_spaces[i] = '\0';
            }

            if( p_item->i_type == CONFIG_ITEM_BOOL && !b_help_module )
            {
                fprintf( output, psz_format, psz_short, p_item->psz_name,
                         psz_prefix, p_item->psz_name, psz_bra, psz_type,
                         psz_ket, psz_spaces );
            }
            else
            {
                fprintf( output, psz_format, psz_short, p_item->psz_name,
                         "", "", psz_bra, psz_type, psz_ket, psz_spaces );
            }

            psz_spaces[i] = ' ';

            /* We wrap the rest of the output */
            sprintf( psz_buffer, "%s%s", p_item->psz_text, psz_suf );
            b_description = config_GetInt( p_this, "help-verbose" );

description:
            psz_text = psz_buffer;
            while( *psz_text )
            {
                char *psz_parser, *psz_word;
                size_t i_end = strlen( psz_text );

                /* If the remaining text fits in a line, print it. */
                if( i_end <= (size_t)i_width )
                {
                    fprintf( output, "%s\n", psz_text );
                    break;
                }

                /* Otherwise, eat as many words as possible */
                psz_parser = psz_text;
                do
                {
                    psz_word = psz_parser;
                    psz_parser = strchr( psz_word, ' ' );
                    /* If no space was found, we reached the end of the text
                     * block; otherwise, we skip the space we just found. */
                    psz_parser = psz_parser ? psz_parser + 1
                                            : psz_text + i_end;

                } while( psz_parser - psz_text <= i_width );

                /* We cut a word in one of these cases:
                 *  - it's the only word in the line and it's too long.
                 *  - we used less than 80% of the width and the word we are
                 *    going to wrap is longer than 40% of the width, and 
even
                 *    if the word would have fit in the next line. */
                if( psz_word == psz_text
                     || ( psz_word - psz_text < 80 * i_width / 100
                           && psz_parser - psz_word > 40 * i_width / 100 ) )
                {
                    char c = psz_text[i_width];
                    psz_text[i_width] = '\0';
                    fprintf( output, "%s\n%s", psz_text, psz_spaces );
                    psz_text += i_width;
                    psz_text[0] = c;
                }
                else
                {
                    psz_word[-1] = '\0';
                    fprintf( output, "%s\n%s", psz_text, psz_spaces );
                    psz_text = psz_word;
                }
            }

            if( b_description && p_item->psz_longtext )
            {
                sprintf( psz_buffer, "%s%s", p_item->psz_longtext, psz_suf 
);
                b_description = VLC_FALSE;
                psz_spaces = psz_spaces_longtext;
                fprintf( output, "%s", psz_spaces );
                goto description;
            }
        }
    }

    /* Release the module list */
    vlc_list_release( p_list );
}

I've put:

#ifdef WIN32
	output = fopen("vlc-help.txt", "wt+"); // wt+ rather than wb+ to convert \n 
into \r\n
#endif

In #ifdef WIN32, the unix version of that line would be:

#ifndef WIN32
	output = fopen("vlc-help.txt", "wb+");
#endif


(This fixes vlc --longhelp too.)

:)


-- 
This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
To unsubscribe, please read http://developers.videolan.org/lists.html



More information about the vlc-devel mailing list