]> gitweb.hamatoma.de Git - crepublib/commitdiff
dirtool help stuff improvements
authorkawi <winfriedkappeler@atron.de>
Sun, 4 Jan 2015 16:59:33 +0000 (17:59 +0100)
committerkawi <winfriedkappeler@atron.de>
Sun, 4 Jan 2015 16:59:33 +0000 (17:59 +0100)
base/ReProgramArgs.cpp
base/ReProgramArgs.hpp
os/ReDirTools.cpp
os/ReDirTools.hpp

index ba9d8d1ec30180317292ee707537ba3c2eb4b25e..f8dcdb4dc1edd90212a3d14a32c2ed2c63d1f2e8 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "base/rebase.hpp"
 
+const char* ReProgramArgs::PREFIX_LINE_OPTION = "   ";
 
 /** @brief Constructor.
  *
@@ -129,7 +130,11 @@ void ReProgramArgs::setUsage(const char* usage[]){
 void ReProgramArgs::addProperties(const char*name, const char* description, char shortOpt,
                const char* longOpt, DataType dataType, const char* defaultValue, size_t lengthValue){
        ReByteBuffer properties;
-       properties.append(description, strlen(description)).append("\1", 1);
+    ReByteBuffer descr(description, -1);
+    ReByteBuffer replacement("\n", 1);
+    replacement.append(PREFIX_LINE_OPTION);
+    descr.replaceAll("\n", 1, replacement.str(), replacement.length());
+       properties.append(descr).append("\1", 1);
        properties.append(&shortOpt, 1).append("\1", 1);
        properties.append(longOpt, strlen(longOpt)).append("\1", 1);
        properties.append((char*) &dataType, 1).append("\1", 1);
@@ -571,15 +576,23 @@ void ReProgramArgs::help(const char* message, bool issueLastError, ReStringList&
                        line.append(param.str(), -1).append(" ", 1).append(i18n(" or "), -1);
                }
                line.append(i18n("--"), -1).append(properties.strOf(IxLong), -1);
-               if (param.length() > 0)
-                       line.append("=", -1).append(param.str(), -1)
-                               .append(i18n(" Default value: "), -1).append(properties.strOf(IxDefault), -1);
+               if (param.length() > 0){
+                       line.append("=", -1).append(param.str(), -1);
+            if (dataType != DT_STRING || properties.strLengthOf(IxDefault) > 0){
+                               line.append(i18n(" Default value: "), -1);
+                if (dataType == DT_STRING)
+                    line.append("'", 1);
+                line.append(properties.strOf(IxDefault), -1);
+                if (dataType == DT_STRING)
+                    line.append("'", 1);
+            }
+        }
                lines.append(line.str());
-               line.set("\t", 1).append(properties.strOf(IxDescr), -1);
+               line.set(PREFIX_LINE_OPTION, -1).append(properties.strOf(IxDescr), -1);
                lines.append(line.str());
        }
        if (m_examples.count() > 0){
-               lines.append(i18n("Example:"));
+               lines.append(i18n("Example(s):"));
                lines.append(m_examples);
        }
        if (issueLastError && m_lastError.length() > 0){
@@ -587,7 +600,7 @@ void ReProgramArgs::help(const char* message, bool issueLastError, ReStringList&
                lines.append(line.str());
        }
 
-       if (message != NULL){
+       if (message != NULL && message[0] != '\0'){
                line.set("+++ ", 4).append(message, -1);
                lines.append(line.str());
        }
index b5243d428a72792269447e489e4e2c82396702c1..97e10187bb77a7aefc7acea22549ab3db2b8673c 100644 (file)
@@ -35,6 +35,7 @@ public:
  * <p>The connection between definition and retrieval are names.</p>
  */
 class ReProgramArgs {
+    static const char* PREFIX_LINE_OPTION;
 public:
        enum DataType {
                DT_UNDEF = 0,
index 0989152fe6e33f9e3736181e6632080dc8691c56..e236801877bb1f2351f9b1b4bc5ed35c0c244740 100644 (file)
 const char* ReDirTools::m_version = "2015.01.03";
 
 static const char* s_empty[] = { NULL };
-
-static const char* s_standardFilterUsage[] = {
-    "-D<n> or --max-depth=<n> Default: 512",
-    "   the depth of the subdirectory is lower or equal <n>",
-    "   0: search is done only in the base directory",
-    "-d<n> or --min-depth=<n> Default: 0",
-    "   the depth of the subdirectory is greater or equal <n>",
-    "   0: search is done in all subdirectories",
-    "-o<v> or --older-than=<v>",
-    "   the modification date is older than <v>",
-    "   <v> is a date (e.g. 2015.02.17) or number followed by an unit",
-    "   units: m(inutes) h(hours), d(days). Default: m(inutes)",
-    "   examples: -o25 --older-than=30d -o24h -o2009.3.2/12:00 -o1999.01.01",
-    "-q or --quiet",
-    "   no additional information like runtime",
-    "-P<p> or --pathname-pattern=<p>",
-    "   a list of patterns for the path (without basename) separated by ';'",
-    "   Each pattern can contain '*' as wildcard",
-    "   If the first character is '^' the pattern is a 'not pattern':"
-    "   A directory will be entered if at least one of the positive patterns",
-    "   and none of the 'not patterns' matches",
-    "   examples: '*;^*/.git/' '*/cache/;*/temp/",
-    "-p<p> or --basename-pattern=<p>",
-    "   a list of patterns for the basename (filename without path) separated by ';'",
-    "   Each pattern can contain '*' as wildcard",
-    "   If the first character is '^' the pattern is a 'not pattern':"
-    "   A file will be found if at least one of the positive patterns and none",
-    "   of the 'not patterns' matches",
-    "   examples: '*.cpp;*.hpp;Make*' '*;^*.bak;^*~",
-    "-t<n> or --trace-interval=<n> Default: 0",
-    "   all <n> seconds the current path will be traced",
-    "   0: no trace",
-    "-t<l> or --type=<l>",
-    "   the file type",
-    "   <l> is a list of <v> values:",
-    "   <v>: b(lock) c(har) d(irectory) (l)i(nkdir) l(ink) o(ther)",
-    "        p(ipe) s(ocket) r(egular)",
-    "   <v>-sets: S(pecial)=bcspo N(ondir)=Slr",
-    "   examples: -td --type=dr -tNi",
-    "-y<v> or --younger-than=<v>",
-    "   the modification date is younger than <v>",
-    "   <v> is a date (e.g. 2015.02.17) or number followed by an unit",
-    "   units: m(inutes) h(hours), d(days). Default: m(inutes)",
-    "   examples: -y25 --younger-than=30d -y1999.12.31",
-    "-Z<v> or --max-size=<v>",
-    "   the filesize is greater or equal <v>",
-    "   <v> is a number followed by an unit",
-    "   units: k(Byte) K(iByte) m(Byte), M(iByte), g(Byte) G(iByte)",
-    "   example: -Z50m --max-size=1G",
-    "-z<n> or --min-size=<n>",
-    "   the filesize is greater or equal <n>",
-    "   <v> is a number followed by an unit",
-    "   units: k(Byte) K(iByte) m(Byte), M(iByte), g(Byte) G(iByte)",
-    "   example: -z50m --min-size=1G",
-    NULL
-};
-
 const char* s_listUsage[] = {
     "<command>: list",
     "   lists the metadata (size, modification date ...) of the selected files",
@@ -100,17 +43,9 @@ static const char* s_statisticUsage[] = {
     "          n: shows the summery of each subdir until level <n> and the total",
     "          default: 1",
     "<opts_stat>:",
-    "-q or --quiet",
-    "   does not show additional information, e.g. runtime",
-    "-t<n> or --trace-interval=<n>",
-    "   trace the current path every <n> seconds.",
-    "   If n<=0: no trace. Default: 60",
-    "-k or --kbyte",
-    "   output is '<kbyte> path' (like du)",
     NULL
 };
 const char* s_statisticExamples[] = {
-    "Examples:",
     "dirtool st -q -t0 e:\\windows",  
     "dirtool statistic --quiet --kbyte --trace-interval=60 ../mail 2",  
     "dirtool stat -q --kbyte d:data 2",  
@@ -168,17 +103,68 @@ void ReDirOptions::addCompoundUsage(const char** usage){
  * Adds the standard filter options.
  */
 void ReDirOptions::addStandardFilterOptions(){
-    m_programArgs.addInt("maxdepth", "maximal subdir depth", 'D', "max-depth", 512);
-    m_programArgs.addInt("mindepth", "minimal subdir depth", 'd', "min-depth", 512);
-    m_programArgs.addString("older", "older than", 'o', "older-than", false, NULL);
-    m_programArgs.addString("nodepattern", "pattern list for the basename", 'p', "basename-pattern", false, NULL);
-    m_programArgs.addString("pathpattern", "pattern list for the path", 'P', "path-pattern", false, NULL);
-    m_programArgs.addBool("quiet", "suppress additional info", 'q', "quiet", false);
-    m_programArgs.addInt("trace", "trace interval", 'T', "trace-interval", 0);
-    m_programArgs.addString("type", "file type", 't', "type", false, NULL);
-    m_programArgs.addString("younger", "younger than", 'y', "younger-than", false, NULL);
-    m_programArgs.addString("maxsize", "maximal filesize", 'Z', "max-size", false, NULL);
-    m_programArgs.addString("minsize", "minimal filesize", 'z', "min-size", false, NULL);
+    m_programArgs.addInt("maxdepth",
+        i18n("the depth of the subdirectory is lower or equal <number>\n"
+        "0: search is done only in the base directory"),
+        'D', "max-depth", 512);
+    m_programArgs.addInt("mindepth", 
+        i18n("the depth of the subdirectory is greater or equal <number>\n"
+            "0: search is done in all subdirectories"),
+        'd', "min-depth", 512);
+    m_programArgs.addString("older", 
+        i18n("the modification date is older than <string>\n"
+            "<string> is a date (e.g. 2015.02.17) or number followed by an unit\n"
+            "units: m(inutes) h(hours), d(days). Default: m(inutes)\n"
+            "examples: -o25 --older-than=30d -o24h -o2009.3.2/12:00 -o1999.01.01"),
+        'o', "older-than", false, NULL);
+    m_programArgs.addString("pathpattern", 
+        i18n("a list of patterns for the path (without basename) separated by ';'\n"
+            "Each pattern can contain '*' as wildcard\n"
+            "If the first character is '^' the pattern is a 'not pattern':\n"
+            "A directory will be entered if at least one of the positive patterns\n"
+            "and none of the 'not patterns' matches\n"
+            "examples: '*;^*/.git/' '*/cache/;*/temp/"),
+            'P', "path-pattern", false, NULL);
+    m_programArgs.addString("nodepattern", 
+        i18n("a list of patterns for the basename (name without path) separated by ';'\n"
+            "Each pattern can contain '*' as wildcard\n"
+            "If the first character is '^' the pattern is a 'not pattern':\n"
+            "A file will be found if at least one of the positive patterns and none\n"
+            "of the 'not patterns' matches\n"
+            "examples: '*.cpp;*.hpp;Make*' '*;^*.bak;^*~"),
+        'p', "basename-pattern", false, NULL);
+    m_programArgs.addBool("quiet", 
+        i18n("no additional information like runtime"),
+        'q', "quiet", false);
+    m_programArgs.addInt("trace", 
+        i18n("all <number> seconds the current path will be traced\n"
+            "0: no trace"),
+        'T', "trace-interval", 0);
+    m_programArgs.addString("type", 
+        i18n("the file type\n"
+            "<string> is a list of <v> values:\n"
+            "<v>: b(lock) c(har) d(irectory) (l)i(nkdir) l(ink) o(ther)\n"
+            "     p(ipe) s(ocket) r(egular)\n"
+            "<v>-sets: S(pecial)=bcspo N(ondir)=Slr\n"
+            "examples: -td --type=dr -tNi"), 
+        't', "type", false, NULL);
+    m_programArgs.addString("younger", 
+        i18n("the modification date is younger than <string>\n"
+            "<string> is a date (e.g. 2015.02.17) or number followed by an unit\n"
+            "units: m(inutes) h(hours), d(days). Default: m(inutes)"),
+        'y', "younger-than", false, NULL);
+    m_programArgs.addString("maxsize", 
+        i18n("the filesize is greater or equal <string>\n"
+            "<string> is a number followed by an unit\n"
+            "units: b(yte) k(Byte) K(iByte) m(Byte), M(iByte), g(Byte) G(iByte)\n"
+            "examples: -Z50m --max-size=1G"),
+        'Z', "max-size", false, NULL);
+    m_programArgs.addString("minsize", 
+        i18n("the filesize is greater or equal <string>\n"
+            "<string> is a number followed by an unit\n"
+            "units: b(yte) k(Byte) K(iByte) m(Byte), M(iByte), g(Byte) G(iByte)\n"
+            "examples: -z50m --min-size=1G"),
+        'z', "min-size", false, NULL);
 }
 
 /**
@@ -398,7 +384,9 @@ void ReDirOptions::setFilterFromProgramArgs(ReDirEntryFilter_t& filter){
  */
 
 void ReDirOptions::help(const char* errorMessage, const char* message2 ){
-    ReByteBuffer msg(errorMessage, -1);
+    ReByteBuffer msg;
+    if (errorMessage != 0)
+        msg.append(errorMessage, -1);
     if (message2 != NULL)
         msg.append(message2, -1);
     m_programArgs.help(msg.str(), false, stdout);
@@ -480,18 +468,66 @@ ReDirStatisticData& ReDirStatisticData::add(const ReDirStatisticData& source){
  * Constructor.
  */
 ReDirStatistic::ReDirStatistic(int deltaList, int deltaBuffer) :
+    ReDirOptions(s_statisticUsage, s_statisticExamples),
        m_list(deltaList, deltaBuffer),
     m_traceInterval(0),
     m_lastTrace(0)
 {
+    m_programArgs.addBool("quiet", 
+        i18n("does not show additional information, e.g. runtime"),
+        'q', "quiet", false);
+    m_programArgs.addBool("kbyte", 
+        i18n("output is '<kbyte> <path>' (like unix 'du' command)"),
+        'k', "kbyte", false);
+    m_programArgs.addInt("trace", 
+        i18n("trace the current path every <number> seconds.\n"
+            "0: no trace"),
+        't', "trace-interval", 60);
 }
 /**
  * Destructor.
  */
 ReDirStatistic::~ReDirStatistic(){
-
 }
 
+/**
+ * Build the statistic and print the results.
+ *
+ * @param arc   count of arguments in <code>argv</code>
+ * @param argv  the program arguments. 
+ */
+void ReDirStatistic::run(int argc, char* argv[]){
+    time_t start = time(NULL);
+    try {
+        m_programArgs.init(argc, argv);
+        if (m_programArgs.getArgCount() < 1)
+            m_programArgs.help("statistic: missing path", false, stdout);
+        int depth = 1;
+        if (m_programArgs.getArgCount() > 1)
+            depth = atol(m_programArgs.getArg(1));
+        ReDirStatistic statistic;
+        statistic.setTraceInterval(m_programArgs.getInt("trace"));
+        void (*proc) (const ReDirStatisticData& data,
+                           ReDirStatistic& parent, ReByteBuffer& line) = &formatWithSizeFilesAndDirs;
+        if (m_programArgs.getBool("kbyte"))
+            proc = &formatLikeDu;
+        const ReStringList& list = statistic.calculate(m_programArgs.getArg(0), depth, proc);
+        ReByteBuffer buffer;
+        for (size_t ix = 0; ix < list.count(); ix++){
+            buffer.set(list.strOf(ix), list.strLengthOf(ix));
+            printf("%s\n", buffer.str());
+        }
+        if (! m_programArgs.getBool("quiet")){
+            int duration = int(time(NULL) - start);
+            printf("Duration: ");
+            if (duration >= 3600)
+                printf("%d:", duration / 3600);
+            printf("%02d:%02d\n", duration % 3600 / 60, duration % 60);
+        }
+    } catch (ReOptionException& exc) {
+        m_programArgs.help(exc.getMessage(), false, stdout);
+    }
+}
 /**
  * Calculates the statistic of a directory tree.
  *
@@ -650,21 +686,19 @@ static void printField(const char** lines){
  * Prints an message how to use the statistic module and exits.
  */
 void ReDirTools::statisticUsage(){
-    printField(s_statisticUsage); 
-    printField(s_statisticExamples); 
+    ReDirStatistic statistic;
+    statistic.programArgs().help(NULL, false, stdout);
 }
 
 /**
  * Constructor.
  */
 ReDirList::ReDirList() :
-    ReDirOptions(s_empty, s_listExamples)
+    ReDirOptions(s_listUsage, s_listExamples)
 {
+    m_programArgs.addBool("short", i18n("output is only path and basename"),
+        '1', "--short", false);
     addStandardFilterOptions();
-    initCompoundUsage(sizeof s_listUsage + sizeof s_standardFilterUsage);
-    addCompoundUsage(s_listUsage);
-    addCompoundUsage(s_standardFilterUsage);
-    m_programArgs.setUsage(m_compoundUsage);
 }
 
 /**
@@ -679,6 +713,7 @@ void ReDirList::list(int argc, char* argv[]){
         time_t start = time(NULL);
         m_programArgs.init(argc, argv);
         bool verbose = ! m_programArgs.getBool("quiet");
+        bool shortOutput = m_programArgs.getBool("short");
         setFilterFromProgramArgs(filter);
         if (m_programArgs.getArgCount() == 0)
             help(i18n("no arguments given (missing path)"));
@@ -700,12 +735,17 @@ void ReDirList::list(int argc, char* argv[]){
                     files++;
                     sumSizes += entry->fileSize();
                 }
-                if (! printOneFile(entry))
-                    printf("%s %12.6f %s %02x %s%s\n",
-                    entry->rightsAsString(bufferRights), entry->fileSize() / 1E6, 
-                    entry->filetimeAsString(bufferTime), 
-                    entry->type(),
-                    entry->m_path.str(), entry->node());
+                if (! printOneFile(entry)){
+                    if (shortOutput)
+                        printf("%s%s\n", entry->m_path.str(), entry->node());
+                    else
+                        printf("%s %12.6f %s %02x %s%s\n",
+                            entry->rightsAsString(bufferRights), 
+                            entry->fileSize() / 1E6, 
+                            entry->filetimeAsString(bufferTime), 
+                            entry->type(),
+                            entry->m_path.str(), entry->node());
+                }
             }
         }
         if (verbose){
@@ -729,61 +769,56 @@ void ReDirTools::list(int argc, char* argv[]){
     lister.list(argc, argv);
 }
 
+/**
+ * Tests whether a abrevation of an argument is given.
+ * @param full      the full name
+ * @param part      the part to test
+ * @return          <code>true</code>: part is a prefix of full
+ */
+static bool isArg(const char* full, const char* part){
+    ReByteBuffer fullArg(full);
+    bool rc = fullArg.startsWith(part, -1);
+    return rc;
+}
 
 /**
- * Gets the arguments for the "statistic" command and execute this.
+ * Gets the arguments for the "help" command and execute this.
  *
  * @param argc      the number of arguments
  * @param argav     the argument vector
  */
-void ReDirTools::statistic(int argc, char* argv[]){
-    time_t start = time(NULL);
-       ReProgramArgs args(s_statisticUsage, s_statisticExamples);
-    args.addBool("quiet", "no additional information", 'q', "quiet", false);
-    args.addBool("kbyte", "output is '<kbyte> <path>'", 'k', "kbyte", false);
-    args.addInt("trace", "trace each <n> seconds the current path", 't', "trace-interval", 60);
-    try {
-        args.init(argc, argv);
-        if (args.getArgCount() < 1)
-            usage("statistic: missing path");
-        int depth = 1;
-        if (args.getArgCount() > 1)
-            depth = atol(args.getArg(1));
-        ReDirStatistic statistic;
-        statistic.setTraceInterval(args.getInt("trace"));
-        void (*proc) (const ReDirStatisticData& data,
-                           ReDirStatistic& parent, ReByteBuffer& line) = &formatWithSizeFilesAndDirs;
-        if (args.getBool("kbyte"))
-            proc = &formatLikeDu;
-        const ReStringList& list = statistic.calculate(args.getArg(0), depth, proc);
-        ReByteBuffer buffer;
-        for (size_t ix = 0; ix < list.count(); ix++){
-            buffer.set(list.strOf(ix), list.strLengthOf(ix));
-            printf("%s\n", buffer.str());
-        }
-        if (! args.getBool("quiet")){
-            int duration = int(time(NULL) - start);
-            printf("Duration: ");
-            if (duration >= 3600)
-                printf("%d:", duration / 3600);
-            printf("%02d:%02d\n", duration % 3600 / 60, duration % 60);
-        }
-    } catch (ReOptionException& exc) {
-        usage(exc.getMessage());
+void ReDirTools::help(int argc, char* argv[]){
+    if (argc < 1)
+        printField(s_helpSummary);
+    else {
+        argc--;
+        argv++;
+        const char* arg0 = argv[0];
+        if (isArg("list", arg0)){
+            ReDirList list;
+            list.help(NULL);
+        } else if (isArg("help", arg0))
+            printField(s_helpSummary);
+        else if (isArg("statistic", arg0)){
+            ReDirStatistic stat;
+            stat.help(NULL);
+        } else if (isArg("test", arg0)){
+            void testAll();
+            testAll();
+        } else
+            printf("+++ unknown sub command: %s\n", arg0);
     }
 }
 
 /**
- * Tests whether a abrevation of an argument is given.
- * @param full      the full name
- * @param part      the part to test
- * @return          <code>true</code>: part is a prefix of full
+ * Gets the arguments for the "statistic" command and execute this.
+ *
+ * @param argc      the number of arguments
+ * @param argav     the argument vector
  */
-static bool isArg(const char* full, const char* part){
-    ReByteBuffer fullArg(full);
-    bool rc = fullArg.startsWith(part, -1);
-    return rc;
+void ReDirTools::statistic(int argc, char* argv[]){
 }
+
 /**
  * Gets the arguments for any command and execute this.
  *
@@ -800,7 +835,7 @@ int ReDirTools::main(int argc, char* argv[]){
     if (isArg("list", arg0))
         tools.list(argc, argv);
     else if (isArg("help", arg0))
-        printField(s_helpSummary);
+        tools.help(argc, argv);
     else if (isArg("statistic", arg0))
         tools.statistic(argc, argv);
     else if (isArg("test", arg0)){
index 7e1b2fd71979013ad7efa4449d86ff6fbc8e72d2..37c0351266e227c9603dedc7cfa3ad5d4198dee7 100644 (file)
@@ -66,7 +66,7 @@ extern void formatWithSizeFilesAndDirs(const ReDirStatisticData& data,
 /**
  * Calculates a statistic of a directory tree.
  */
-class ReDirStatistic {
+class ReDirStatistic : public ReDirOptions {
 public:
        ReDirStatistic(int deltaList = 512, int deltaBuffer = 0x10000);
        ~ReDirStatistic();
@@ -74,6 +74,7 @@ public:
        const ReStringList& calculate(const char* base, int depth,
                                void (*format)(const ReDirStatisticData& data, ReDirStatistic& parent,
                                        ReByteBuffer& line) = formatLikeDu);
+    void run(int argc, char* argv[]);
     void setTraceInterval(int interval){
         m_traceInterval = interval;
     }
@@ -88,6 +89,7 @@ class ReDirTools {
 public:
     virtual void usage(const char* msg, const char* msg2 = NULL);
     void dirListUsage();
+    void help(int argc, char* argv[]);
     void list(int argc, char* argv[]);
     void statisticUsage();
     void statistic(int argc, char* argv[]);