fc29f0e54aab3577d7000397729052ceea049be1
[quassel.git] / src / common / cliparser.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #include "cliparser.h"
21
22 #include <QString>
23 #include <QFileInfo>
24
25 CliParser::CliParser(QStringList arguments)
26 {
27   argsRaw = arguments;
28 }
29
30 void CliParser::addSwitch(QString longName, char shortName, QVariant def) {
31   addArgument(CliParserArg::CliArgSwitch, longName, shortName, def);
32 }
33
34 void CliParser::addOption(QString longName, char shortName, QVariant def) {
35   addArgument(CliParserArg::CliArgOption, longName, shortName, def);
36 }
37
38 void CliParser::addArgument(CliParserArg::CliArgType type, QString longName, char shortName, QVariant def) {
39   CliParserArg arg = CliParserArg(type, longName, shortName, def);
40   argsHash.insert(longName, arg);
41   if(shortName && !shortHash.contains(shortName)) shortHash.insert(shortName, argsHash.find(longName));
42 }
43
44 void CliParser::addHelp(QString key, QString txt) {
45   if(argsHash.contains(key)) argsHash[key].shortHelp = txt;
46   else qWarning("Warning: Helptext for unknown argument '%s' given",key.toLatin1().constData());
47 }
48
49 bool CliParser::parse() {
50   QStringList::const_iterator currentArg;
51   for (currentArg = argsRaw.constBegin(); currentArg != argsRaw.constEnd(); ++currentArg) {
52     if(currentArg->startsWith("--")) {
53       QString name;
54       // long
55       if(currentArg->contains("=")) {
56         // option
57         QStringList tmp = currentArg->mid(2).split("=");
58         name = tmp.at(0);
59         QString value = tmp.at(1);
60         if(argsHash.contains(name) && !value.isEmpty()){ 
61           argsHash[name].value = value;
62         }
63         else return false;
64       }
65       else {
66         // switch
67         name = currentArg->mid(2);
68         if(argsHash.contains(name)) {
69             argsHash[name].value = true;
70         }
71         else return false;
72       }
73     }
74     else if(currentArg->startsWith("-")) {
75     char name;
76         // short
77       bool bla = true;
78       if(++currentArg == argsRaw.constEnd()) {
79         --currentArg;
80         bla = false;
81       }
82       // if next arg is a short/long option/switch the current arg is one too
83       if(currentArg->startsWith("-")) {
84         // switch
85         if(bla) --currentArg;
86         for (int i = 0; i < currentArg->mid(1).toAscii().size(); i++) {
87           name = currentArg->mid(1).toAscii().at(i);
88           if(shortHash.contains(name) && shortHash.value(name).value().type == CliParserArg::CliArgSwitch) {
89             shortHash[name].value().value = true;
90           }
91           else return false;
92         }
93       }
94       // if next arg is is no option/switch it's an argument to a shortoption
95       else {
96         // option
97         QString value = currentArg->toUtf8();
98         if(bla) --currentArg;
99         name = currentArg->mid(1).toAscii().at(0);
100         if(bla) currentArg++;
101         if(shortHash.contains(name) && shortHash.value(name).value().type == CliParserArg::CliArgOption) {
102           shortHash[name].value().value = value;
103         }
104         else return false;
105       }
106     }
107     else {
108       // we don't support plain arguments without -/--
109       if(currentArg->toLatin1() != argsRaw.at(0)) {
110         return false;
111       }
112     }
113   }
114   return true;
115 }
116
117 void CliParser::usage() {
118   qWarning("Usage: %s [arguments]",QFileInfo(argsRaw.at(0)).completeBaseName().toLatin1().constData());
119   
120   // get size of longName field
121   QStringList keys = argsHash.keys();
122   uint lnameFieldSize = 0;
123   foreach (QString key, keys) {
124     uint size = 0;
125     if(argsHash.value(key).type == CliParserArg::CliArgOption)
126       size += key.size()*2;
127     else
128       size += key.size();
129     // this is for " --...=[....] "
130     size += 8;
131     if(size > lnameFieldSize) lnameFieldSize = size;
132   }
133   
134   QHash<QString, CliParserArg>::const_iterator arg;
135   for(arg = argsHash.constBegin(); arg != argsHash.constEnd(); ++arg) {
136     QString output;
137     QString lnameField;
138     
139     if(arg.value().sname) {
140       output.append(" -").append(arg.value().sname).append(",");
141     }
142     else output.append("    ");
143     lnameField.append(" --").append(arg.key().toLatin1().constData());
144     if(arg.value().type == CliParserArg::CliArgOption) {
145       lnameField.append("=[").append(arg.value().lname.toUpper()).append("]");
146     }
147     output.append(lnameField.leftJustified(lnameFieldSize));
148     if(!arg.value().shortHelp.isEmpty()) {
149       output.append(arg.value().shortHelp);
150     }
151     if(arg.value().type == CliParserArg::CliArgOption) {
152       output.append(". Default is: ").append(arg.value().def.toString());
153     }
154     qWarning(output.toLatin1());
155   }
156 }
157
158 QVariant CliParser::value(QString key) {
159   if(argsHash.contains(key)) {
160     if(argsHash.value(key).value.isValid())
161       return argsHash.value(key).value;
162     else
163       return argsHash.value(key).def;
164   }
165   else {
166     qWarning("Warning: Requested value of not defined argument '%s'",key.toLatin1().constData());
167     return QVariant();
168   }
169 }
170
171 CliParserArg::CliParserArg(CliArgType _type, QString longName, char shortName, QVariant _def)
172   : type(_type),
173     lname(longName),
174     sname(shortName),
175     shortHelp(QString()),
176     def(_def),
177     value(QVariant()) {
178 }
179
180 CliParserArg::CliParserArg(const CliParserArg &other) {
181   type = other.type;
182   lname = other.lname;
183   sname = other.sname;
184   shortHelp = other.shortHelp;
185   def = other.def;
186   value = other.value;
187 }
188
189 CliParserArg &CliParserArg::operator=(const CliParserArg &other) {
190   type = other.type;
191   lname = other.lname;
192   sname = other.sname;
193   shortHelp = other.shortHelp;
194   def = other.def;
195   value = other.value;
196   return *this;
197 }