Added parsing, usage() generation and removed debugging.
authorSebastian Goth <seezer@roath.org>
Mon, 14 Jul 2008 16:46:33 +0000 (18:46 +0200)
committerSebastian Goth <seezer@roath.org>
Wed, 16 Jul 2008 22:57:29 +0000 (00:57 +0200)
src/common/cliparser.cpp
src/common/cliparser.h

index ad02b96..fc29f0e 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 #include "cliparser.h"
-#include <QDebug>
 
-CliParser::CliParser(int argc, char *argv[])
+#include <QString>
+#include <QFileInfo>
+
+CliParser::CliParser(QStringList arguments)
 {
-  if(argc) {
-    for (int i=0; i < argc; ++i)
-      argsRaw.append(QString::fromUtf8(argv[i]));
-  }
+  argsRaw = arguments;
 }
 
+void CliParser::addSwitch(QString longName, char shortName, QVariant def) {
+  addArgument(CliParserArg::CliArgSwitch, longName, shortName, def);
+}
 
-CliParser::~CliParser()
-{
+void CliParser::addOption(QString longName, char shortName, QVariant def) {
+  addArgument(CliParserArg::CliArgOption, longName, shortName, def);
 }
 
-void CliParser::addArgument(QString longName, char shortName = 0, QVariant def = QVariant()) {
-  CliParserArg arg = CliParserArg(longName, shortName, def);
+void CliParser::addArgument(CliParserArg::CliArgType type, QString longName, char shortName, QVariant def) {
+  CliParserArg arg = CliParserArg(type, longName, shortName, def);
   argsHash.insert(longName, arg);
-  qDebug() << "Added Argument: " << longName << " with arg-addr: " << &arg;
+  if(shortName && !shortHash.contains(shortName)) shortHash.insert(shortName, argsHash.find(longName));
+}
+
+void CliParser::addHelp(QString key, QString txt) {
+  if(argsHash.contains(key)) argsHash[key].shortHelp = txt;
+  else qWarning("Warning: Helptext for unknown argument '%s' given",key.toLatin1().constData());
 }
 
 bool CliParser::parse() {
-  qDebug() << "Parse results: ";
-  qDebug() << argsHash.value("logfile").value;
-  argsHash[QString("logfile")].value = "BOOYA";
+  QStringList::const_iterator currentArg;
+  for (currentArg = argsRaw.constBegin(); currentArg != argsRaw.constEnd(); ++currentArg) {
+    if(currentArg->startsWith("--")) {
+      QString name;
+      // long
+      if(currentArg->contains("=")) {
+        // option
+        QStringList tmp = currentArg->mid(2).split("=");
+        name = tmp.at(0);
+        QString value = tmp.at(1);
+        if(argsHash.contains(name) && !value.isEmpty()){ 
+          argsHash[name].value = value;
+        }
+        else return false;
+      }
+      else {
+        // switch
+        name = currentArg->mid(2);
+        if(argsHash.contains(name)) {
+            argsHash[name].value = true;
+        }
+        else return false;
+      }
+    }
+    else if(currentArg->startsWith("-")) {
+    char name;
+        // short
+      bool bla = true;
+      if(++currentArg == argsRaw.constEnd()) {
+        --currentArg;
+        bla = false;
+      }
+      // if next arg is a short/long option/switch the current arg is one too
+      if(currentArg->startsWith("-")) {
+        // switch
+        if(bla) --currentArg;
+        for (int i = 0; i < currentArg->mid(1).toAscii().size(); i++) {
+          name = currentArg->mid(1).toAscii().at(i);
+          if(shortHash.contains(name) && shortHash.value(name).value().type == CliParserArg::CliArgSwitch) {
+            shortHash[name].value().value = true;
+          }
+          else return false;
+        }
+      }
+      // if next arg is is no option/switch it's an argument to a shortoption
+      else {
+        // option
+        QString value = currentArg->toUtf8();
+        if(bla) --currentArg;
+        name = currentArg->mid(1).toAscii().at(0);
+        if(bla) currentArg++;
+        if(shortHash.contains(name) && shortHash.value(name).value().type == CliParserArg::CliArgOption) {
+          shortHash[name].value().value = value;
+        }
+        else return false;
+      }
+    }
+    else {
+      // we don't support plain arguments without -/--
+      if(currentArg->toLatin1() != argsRaw.at(0)) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+void CliParser::usage() {
+  qWarning("Usage: %s [arguments]",QFileInfo(argsRaw.at(0)).completeBaseName().toLatin1().constData());
+  
+  // get size of longName field
+  QStringList keys = argsHash.keys();
+  uint lnameFieldSize = 0;
+  foreach (QString key, keys) {
+    uint size = 0;
+    if(argsHash.value(key).type == CliParserArg::CliArgOption)
+      size += key.size()*2;
+    else
+      size += key.size();
+    // this is for " --...=[....] "
+    size += 8;
+    if(size > lnameFieldSize) lnameFieldSize = size;
+  }
+  
+  QHash<QString, CliParserArg>::const_iterator arg;
+  for(arg = argsHash.constBegin(); arg != argsHash.constEnd(); ++arg) {
+    QString output;
+    QString lnameField;
+    
+    if(arg.value().sname) {
+      output.append(" -").append(arg.value().sname).append(",");
+    }
+    else output.append("    ");
+    lnameField.append(" --").append(arg.key().toLatin1().constData());
+    if(arg.value().type == CliParserArg::CliArgOption) {
+      lnameField.append("=[").append(arg.value().lname.toUpper()).append("]");
+    }
+    output.append(lnameField.leftJustified(lnameFieldSize));
+    if(!arg.value().shortHelp.isEmpty()) {
+      output.append(arg.value().shortHelp);
+    }
+    if(arg.value().type == CliParserArg::CliArgOption) {
+      output.append(". Default is: ").append(arg.value().def.toString());
+    }
+    qWarning(output.toLatin1());
+  }
 }
 
 QVariant CliParser::value(QString key) {
-  return argsHash.value(key).value;
+  if(argsHash.contains(key)) {
+    if(argsHash.value(key).value.isValid())
+      return argsHash.value(key).value;
+    else
+      return argsHash.value(key).def;
+  }
+  else {
+    qWarning("Warning: Requested value of not defined argument '%s'",key.toLatin1().constData());
+    return QVariant();
+  }
 }
 
-CliParserArg::CliParserArg(QString longName, char shortName = 0, QVariant _def = QVariant() )
-  : lname(longName),
+CliParserArg::CliParserArg(CliArgType _type, QString longName, char shortName, QVariant _def)
+  : type(_type),
+    lname(longName),
     sname(shortName),
+    shortHelp(QString()),
     def(_def),
-    value(0) {
-    
+    value(QVariant()) {
 }
 
 CliParserArg::CliParserArg(const CliParserArg &other) {
+  type = other.type;
   lname = other.lname;
   sname = other.sname;
+  shortHelp = other.shortHelp;
   def = other.def;
   value = other.value;
 }
 
 CliParserArg &CliParserArg::operator=(const CliParserArg &other) {
+  type = other.type;
   lname = other.lname;
   sname = other.sname;
+  shortHelp = other.shortHelp;
   def = other.def;
   value = other.value;
   return *this;
 }
-
index 6872f77..00f22b9 100644 (file)
 #include <QHash>
 #include <QVariant>
 
-class CliParserArg;
-
-class CliParser{
-public:
-    inline CliParser() {};
-    CliParser(int argc, char *argv[]);
-
-    ~CliParser();
-    bool parse();
-    QVariant value(QString key);
-    void addArgument(QString longName, char shortName, QVariant def);
-private:
-  QStringList argsRaw;
-  QHash<QString, QVariant*> savedValues;
-  QHash<QString, CliParserArg> argsHash;
-  QHash<QString, QHash<QString, CliParserArg>::iterator> shortHash;
-};
-
 class CliParserArg {
 public:
+  enum CliArgType {
+    CliArgInvalid,
+    CliArgSwitch,
+    CliArgOption
+  };
+  typedef CliArgType CliArgTypes;
+  
   inline CliParserArg() {};
   CliParserArg(const CliParserArg &other);
-  CliParserArg(QString longName, char shortName, QVariant _def);
+  CliParserArg(CliArgType type, QString longName, char shortName = 0, QVariant _def = QVariant());
   CliParserArg &operator=(const CliParserArg &other);
-// private:
+
+  CliArgType type;
   QString lname;
   char sname;
+  QString shortHelp;
   QVariant def;
   QVariant value;
 };
 Q_DECLARE_METATYPE(CliParserArg);
 
+class CliParser{
+public:
+  inline CliParser() {};
+  CliParser(QStringList arguments);
+  bool parse();
+  QVariant value(QString key);
+  void addSwitch(QString longName, char shortName = 0, QVariant def = false);
+  void addOption(QString longName, char shortName = 0, QVariant def = QVariant());
+  void addHelp(QString key, QString txt);
+  void usage();
+private:
+  void addArgument(CliParserArg::CliArgType type, QString longName, char shortName, QVariant def);
+  QStringList argsRaw;
+  QHash<QString, CliParserArg> argsHash;
+  QHash<const char, QHash<QString, CliParserArg>::iterator> shortHash;
+};
+
+
 #endif