summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Kolesa <quaker66@gmail.com>2014-01-20 17:10:21 +0000
committerDaniel Kolesa <quaker66@gmail.com>2014-01-20 17:32:28 +0000
commitedc548fac5497c1bd8d7c35c2942f6686baa64c4 (patch)
treee9aa64db346d2f8f25fe5051d9662400b694f032 /src
parentf0aac1b49079185ded1bcf802e1a12467bfa4dcd (diff)
ecore_getopt: support for per-category help listing
Diffstat (limited to 'src')
-rw-r--r--src/lib/ecore/Ecore_Getopt.h11
-rw-r--r--src/lib/ecore/ecore_getopt.c149
2 files changed, 137 insertions, 23 deletions
diff --git a/src/lib/ecore/Ecore_Getopt.h b/src/lib/ecore/Ecore_Getopt.h
index d41ed3e63e..e4f5eb52b7 100644
--- a/src/lib/ecore/Ecore_Getopt.h
+++ b/src/lib/ecore/Ecore_Getopt.h
@@ -360,9 +360,9 @@ struct _Ecore_Getopt
360 ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES, \ 360 ECORE_GETOPT_DESC_ARG_REQUIREMENT_YES, \
361 NULL) 361 NULL)
362 362
363#define ECORE_GETOPT_HELP(shortname, longname) \ 363#define ECORE_GETOPT_HELP(shortname, longname) \
364 {shortname, longname, "show this message.", NULL, \ 364 {shortname, longname, "show this message.", "CATEGORY", \
365 ECORE_GETOPT_ACTION_HELP, \ 365 ECORE_GETOPT_ACTION_HELP, \
366 {.dummy = NULL}} 366 {.dummy = NULL}}
367 367
368#define ECORE_GETOPT_VERSION(shortname, longname) \ 368#define ECORE_GETOPT_VERSION(shortname, longname) \
@@ -390,8 +390,8 @@ struct _Ecore_Getopt
390 ECORE_GETOPT_ACTION_BREAK, \ 390 ECORE_GETOPT_ACTION_BREAK, \
391 {.dummy = NULL}} 391 {.dummy = NULL}}
392 392
393#define ECORE_GETOPT_CATEGORY(name) \ 393#define ECORE_GETOPT_CATEGORY(name, help) \
394 {0, NULL, name, NULL, ECORE_GETOPT_ACTION_CATEGORY, {.dummy = NULL}} 394 {0, name, help, NULL, ECORE_GETOPT_ACTION_CATEGORY, {.dummy = NULL}}
395 395
396#define ECORE_GETOPT_SENTINEL {0, NULL, NULL, NULL, 0, {.dummy = NULL}} 396#define ECORE_GETOPT_SENTINEL {0, NULL, NULL, NULL, 0, {.dummy = NULL}}
397 397
@@ -410,6 +410,7 @@ struct _Ecore_Getopt
410#define ECORE_GETOPT_VALUE_NONE {.ptrp = NULL} 410#define ECORE_GETOPT_VALUE_NONE {.ptrp = NULL}
411 411
412EAPI void ecore_getopt_help(FILE *fp, const Ecore_Getopt *info); 412EAPI void ecore_getopt_help(FILE *fp, const Ecore_Getopt *info);
413EAPI Eina_Bool ecore_getopt_help_category(FILE *fp, const Ecore_Getopt *info, const char *category);
413EAPI Eina_Bool ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser); 414EAPI Eina_Bool ecore_getopt_parser_has_duplicates(const Ecore_Getopt *parser);
414EAPI int ecore_getopt_parse(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv); 415EAPI int ecore_getopt_parse(const Ecore_Getopt *parser, Ecore_Getopt_Value *values, int argc, char **argv);
415 416
diff --git a/src/lib/ecore/ecore_getopt.c b/src/lib/ecore/ecore_getopt.c
index b2195be085..7a1505f4c2 100644
--- a/src/lib/ecore/ecore_getopt.c
+++ b/src/lib/ecore/ecore_getopt.c
@@ -355,7 +355,7 @@ _ecore_getopt_desc_arg_requirement(const Ecore_Getopt_Desc *desc)
355 return desc->action_param.callback.arg_req; 355 return desc->action_param.callback.arg_req;
356 356
357 case ECORE_GETOPT_ACTION_HELP: 357 case ECORE_GETOPT_ACTION_HELP:
358 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO; 358 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_OPTIONAL;
359 359
360 case ECORE_GETOPT_ACTION_VERSION: 360 case ECORE_GETOPT_ACTION_VERSION:
361 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO; 361 return ECORE_GETOPT_DESC_ARG_REQUIREMENT_NO;
@@ -620,9 +620,55 @@ _ecore_getopt_help_desc_choices(FILE *fp,
620 return _ecore_getopt_help_line(fp, base, total, used, ".", 1); 620 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
621} 621}
622 622
623static int
624_ecore_getopt_help_desc_categories(FILE *fp,
625 const int base,
626 const int total,
627 int used,
628 const Ecore_Getopt_Desc *desc)
629{
630 const char sep[] = ", ";
631 const int seplen = sizeof(sep) - 1;
632 Eina_Bool cat_before = EINA_FALSE;
633
634 if (used > 0)
635 {
636 fputc('\n', fp);
637 used = 0;
638 }
639 for (; used < base; used++)
640 fputc(' ', fp);
641
642 /* do not print available categories if none available */
643 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
644 if (desc->action == ECORE_GETOPT_ACTION_CATEGORY) goto hascat;
645
646 return _ecore_getopt_help_line(fp, base, total, used,
647 _("No categories available."),
648 strlen(_("No categories available.")));
649
650hascat:
651 used = _ecore_getopt_help_line
652 (fp, base, total, used, _("Categories: "), strlen(_("Categories: ")));
653
654 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
655 {
656 if (desc->action != ECORE_GETOPT_ACTION_CATEGORY || !desc->longname)
657 continue;
658 if (cat_before)
659 used = _ecore_getopt_help_line(fp, base, total, used, sep, seplen);
660 used = _ecore_getopt_help_line
661 (fp, base, total, used, desc->longname, strlen(desc->longname));
662 cat_before = EINA_TRUE;
663 }
664
665 return _ecore_getopt_help_line(fp, base, total, used, ".", 1);
666}
667
623static void 668static void
624_ecore_getopt_help_desc(FILE *fp, 669_ecore_getopt_help_desc(FILE *fp,
625 const Ecore_Getopt_Desc *desc) 670 const Ecore_Getopt_Desc *desc,
671 const Ecore_Getopt *parser)
626{ 672{
627 Ecore_Getopt_Desc_Arg_Requirement arg_req; 673 Ecore_Getopt_Desc_Arg_Requirement arg_req;
628 char metavar[32] = "ARG"; 674 char metavar[32] = "ARG";
@@ -699,6 +745,11 @@ _ecore_getopt_help_desc(FILE *fp,
699 _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc); 745 _ecore_getopt_help_desc_choices(fp, helpcol, cols, used, desc);
700 break; 746 break;
701 747
748 case ECORE_GETOPT_ACTION_HELP:
749 _ecore_getopt_help_desc_categories(fp, helpcol, cols, used,
750 parser->descs);
751 break;
752
702 default: 753 default:
703 break; 754 break;
704 } 755 }
@@ -710,7 +761,8 @@ end:
710static Eina_Bool 761static Eina_Bool
711_ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc) 762_ecore_getopt_desc_is_sentinel(const Ecore_Getopt_Desc *desc)
712{ 763{
713 return (desc->shortname == '\0') && (!desc->longname); 764 return (desc->shortname == '\0') && (!desc->longname)
765 && (desc->action != ECORE_GETOPT_ACTION_CATEGORY);
714} 766}
715 767
716static void 768static void
@@ -722,7 +774,7 @@ _ecore_getopt_help_options(FILE *fp,
722 fputs(_("Options:\n"), fp); 774 fputs(_("Options:\n"), fp);
723 775
724 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++) 776 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
725 _ecore_getopt_help_desc(fp, desc); 777 _ecore_getopt_help_desc(fp, desc, parser);
726 778
727 fputc('\n', fp); 779 fputc('\n', fp);
728 780
@@ -730,25 +782,18 @@ _ecore_getopt_help_options(FILE *fp,
730 782
731 fputs(_("Positional arguments:\n"), fp); 783 fputs(_("Positional arguments:\n"), fp);
732 for (; desc->metavar != NULL; desc++) 784 for (; desc->metavar != NULL; desc++)
733 _ecore_getopt_help_desc(fp, desc); 785 _ecore_getopt_help_desc(fp, desc, parser);
734 786
735 fputc('\n', fp); 787 fputc('\n', fp);
736} 788}
737 789
738/** 790static Eina_Bool
739 * Show nicely formatted help message for the given parser. 791_ecore_getopt_help_prepare(const Ecore_Getopt *parser)
740 *
741 * @param fp The file the message will be printed on.
742 * @param parser The parser to be used.
743 */
744EAPI void
745ecore_getopt_help(FILE *fp,
746 const Ecore_Getopt *parser)
747{ 792{
748 const char *var; 793 const char *var;
749 794
750 EINA_MAIN_LOOP_CHECK_RETURN; 795 EINA_MAIN_LOOP_CHECK_RETURN;
751 if (!parser) return; 796 if (!parser) return EINA_FALSE;
752 797
753 if (_argc < 1) 798 if (_argc < 1)
754 { 799 {
@@ -769,11 +814,75 @@ ecore_getopt_help(FILE *fp,
769 helpcol = cols / 3; 814 helpcol = cols / 3;
770 } 815 }
771 816
817 return EINA_TRUE;
818}
819
820/**
821 * Show nicely formatted help message for the given parser.
822 *
823 * @param fp The file the message will be printed on.
824 * @param parser The parser to be used.
825 *
826 * @see ecore_getopt_help_category()
827 */
828EAPI void
829ecore_getopt_help(FILE *fp,
830 const Ecore_Getopt *parser)
831{
832 if (!_ecore_getopt_help_prepare(parser))
833 return;
834
772 _ecore_getopt_help_usage(fp, parser); 835 _ecore_getopt_help_usage(fp, parser);
773 _ecore_getopt_help_description(fp, parser); 836 _ecore_getopt_help_description(fp, parser);
774 _ecore_getopt_help_options(fp, parser); 837 _ecore_getopt_help_options(fp, parser);
775} 838}
776 839
840/**
841 * Show help for a single category (along with program usage and description).
842 *
843 * @param fp The file the message will be printed on.
844 * @param parser The parser to be used.
845 * @param category The category to print.
846 *
847 * @return @c EINA_TRUE when the category exists, @c EINA_FALSE otherwise.
848 *
849 * @see ecore_getopt_help()
850 */
851EAPI Eina_Bool
852ecore_getopt_help_category(FILE *fp,
853 const Ecore_Getopt *parser,
854 const char *category)
855{
856 const Ecore_Getopt_Desc *desc;
857 Eina_Bool found = EINA_FALSE;
858
859 if (!category || !_ecore_getopt_help_prepare(parser)) return EINA_FALSE;
860 for (desc = parser->descs; !_ecore_getopt_desc_is_sentinel(desc); desc++)
861 {
862 if (desc->action != ECORE_GETOPT_ACTION_CATEGORY) continue;
863 if (!desc->longname || strcmp(desc->longname, category)) continue;
864 found = EINA_TRUE;
865 break;
866 }
867 if (!found)
868 {
869 fprintf(stderr, _("ERROR: unknown category '%s'.\n"), category);
870 return EINA_FALSE;
871 }
872
873 _ecore_getopt_help_usage(fp, parser);
874 _ecore_getopt_help_description(fp, parser);
875
876 fprintf(fp, "%s\n", (desc++)->help);
877 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
878 {
879 if (desc->action == ECORE_GETOPT_ACTION_CATEGORY) break;
880 _ecore_getopt_help_desc(fp, desc, parser);
881 }
882
883 return EINA_TRUE;
884}
885
777static const Ecore_Getopt_Desc * 886static const Ecore_Getopt_Desc *
778_ecore_getopt_parse_find_long(const Ecore_Getopt *parser, 887_ecore_getopt_parse_find_long(const Ecore_Getopt *parser,
779 const char *name) 888 const char *name)
@@ -787,7 +896,7 @@ _ecore_getopt_parse_find_long(const Ecore_Getopt *parser,
787 896
788 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++) 897 for (; !_ecore_getopt_desc_is_sentinel(desc); desc++)
789 { 898 {
790 if (!desc->longname) 899 if (!desc->longname || desc->action == ECORE_GETOPT_ACTION_CATEGORY)
791 continue; 900 continue;
792 901
793 if (p) 902 if (p)
@@ -873,7 +982,7 @@ _ecore_getopt_parse_find_nonargs_base(const Ecore_Getopt *parser,
873 goto found_nonarg; 982 goto found_nonarg;
874 } 983 }
875 984
876 985
877 986
878 if (desc->action == ECORE_GETOPT_ACTION_BREAK) 987 if (desc->action == ECORE_GETOPT_ACTION_BREAK)
879 abreak = 1; 988 abreak = 1;
@@ -1430,10 +1539,12 @@ static Eina_Bool
1430_ecore_getopt_parse_help(const Ecore_Getopt *parser, 1539_ecore_getopt_parse_help(const Ecore_Getopt *parser,
1431 const Ecore_Getopt_Desc *desc EINA_UNUSED, 1540 const Ecore_Getopt_Desc *desc EINA_UNUSED,
1432 Ecore_Getopt_Value *val, 1541 Ecore_Getopt_Value *val,
1433 const char *arg_val EINA_UNUSED) 1542 const char *arg_val)
1434{ 1543{
1435 if (val->boolp) 1544 if (val->boolp)
1436 (*val->boolp) = EINA_TRUE; 1545 (*val->boolp) = EINA_TRUE;
1546 if (arg_val)
1547 return ecore_getopt_help_category(stdout, parser, arg_val);
1437 ecore_getopt_help(stdout, parser); 1548 ecore_getopt_help(stdout, parser);
1438 return EINA_TRUE; 1549 return EINA_TRUE;
1439} 1550}
@@ -1862,6 +1973,8 @@ _ecore_getopt_parse_find_long_other(const Ecore_Getopt *parser,
1862 { 1973 {
1863 if (desc == orig) 1974 if (desc == orig)
1864 return NULL; 1975 return NULL;
1976 if (desc->action == ECORE_GETOPT_ACTION_CATEGORY)
1977 continue;
1865 1978
1866 if (desc->longname && (strcmp(name, desc->longname) == 0)) 1979 if (desc->longname && (strcmp(name, desc->longname) == 0))
1867 return desc; 1980 return desc;