mirror of https://github.com/aria2/aria2
New help messages. Added suggestion for unknown/ambiguous options.
The help messages shown when argument error were redesigned and less verbose now. When unknown or ambiguous option is given, show suggestions like "Did you mean...". Some constant values related to levenstein distance are borrowed from git help.c.pull/4/head
parent
f77da0d112
commit
6bf696ca11
|
@ -5,6 +5,9 @@ src/OptionHandler.cc
|
|||
src/OptionHandlerImpl.h
|
||||
src/usage_text.h
|
||||
src/version_usage.cc
|
||||
src/option_processing.cc
|
||||
src/OptionHandlerException.cc
|
||||
src/UnknownOptionException.cc
|
||||
src/BtSetup.cc
|
||||
src/AbstractCommand.cc
|
||||
src/AdaptiveURISelector.cc
|
||||
|
|
|
@ -224,7 +224,8 @@ SRCS = Socket.h\
|
|||
a2iterator.h\
|
||||
paramed_string.cc paramed_string.h\
|
||||
rpc_helper.cc rpc_helper.h\
|
||||
WatchProcessCommand.cc WatchProcessCommand.h
|
||||
WatchProcessCommand.cc WatchProcessCommand.h\
|
||||
UnknownOptionException.cc UnknownOptionException.h
|
||||
|
||||
if MINGW_BUILD
|
||||
SRCS += WinConsoleFile.cc WinConsoleFile.h
|
||||
|
|
|
@ -64,4 +64,17 @@ std::ostream& operator<<(std::ostream& o, const OptionHandler& optionHandler)
|
|||
return o;
|
||||
}
|
||||
|
||||
void write(const Console& out, const OptionHandler& optionHandler)
|
||||
{
|
||||
out->printf("%s\n\n", optionHandler.getDescription());
|
||||
std::string possibleValues = optionHandler.createPossibleValuesString();
|
||||
if(!possibleValues.empty()) {
|
||||
out->printf("%s%s\n", POSSIBLE_MSG, possibleValues.c_str());
|
||||
}
|
||||
if(!optionHandler.getDefaultValue().empty()) {
|
||||
out->printf("%s%s\n", DEFAULT_MSG, optionHandler.getDefaultValue().c_str());
|
||||
}
|
||||
out->printf("%s%s\n", TAGS_MSG, optionHandler.toTagString().c_str());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <functional>
|
||||
|
||||
#include "SharedHandle.h"
|
||||
#include "console.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
|
@ -114,6 +115,8 @@ public:
|
|||
|
||||
std::ostream& operator<<(std::ostream& o, const OptionHandler& optionHandler);
|
||||
|
||||
void write(const Console& out, const OptionHandler& optionHandler);
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // D_OPTION_HANDLER_H
|
||||
|
|
|
@ -38,15 +38,16 @@
|
|||
|
||||
namespace aria2 {
|
||||
|
||||
const std::string OptionHandlerException::MESSAGE
|
||||
("We encountered a problem while processing the option '--%s'.");
|
||||
namespace {
|
||||
const char* MESSAGE =
|
||||
_("We encountered a problem while processing the option '--%s'.");
|
||||
} // namespace
|
||||
|
||||
OptionHandlerException::OptionHandlerException
|
||||
(const char* file, int line,
|
||||
const Pref* pref)
|
||||
: RecoverableException
|
||||
(file, line, fmt(MESSAGE.c_str(), pref->k),
|
||||
error_code::OPTION_ERROR),
|
||||
(file, line, fmt(MESSAGE, pref->k), error_code::OPTION_ERROR),
|
||||
pref_(pref)
|
||||
{}
|
||||
|
||||
|
@ -55,8 +56,7 @@ OptionHandlerException::OptionHandlerException
|
|||
const Pref* pref,
|
||||
const Exception& cause)
|
||||
: RecoverableException
|
||||
(file, line, fmt(MESSAGE.c_str(), pref->k),
|
||||
error_code::OPTION_ERROR,
|
||||
(file, line, fmt(MESSAGE, pref->k), error_code::OPTION_ERROR,
|
||||
cause),
|
||||
pref_(pref)
|
||||
{}
|
||||
|
|
|
@ -43,8 +43,6 @@ class Pref;
|
|||
class OptionHandlerException:public RecoverableException {
|
||||
private:
|
||||
const Pref* pref_;
|
||||
|
||||
static const std::string MESSAGE;
|
||||
protected:
|
||||
virtual SharedHandle<Exception> copy() const;
|
||||
public:
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "DlAbortEx.h"
|
||||
#include "error_code.h"
|
||||
#include "prefs.h"
|
||||
#include "UnknownOptionException.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
|
@ -156,13 +157,52 @@ void OptionParser::parseArg
|
|||
SharedHandle<OptionHandler> op;
|
||||
if(c == 0) {
|
||||
op = findById(lopt);
|
||||
} else {
|
||||
} else if(c != '?') {
|
||||
op = findByShortName(c);
|
||||
} else {
|
||||
assert(c == '?');
|
||||
if(optind == 1) {
|
||||
throw DL_ABORT_EX2("Failed to parse command-line options.",
|
||||
error_code::OPTION_ERROR);
|
||||
}
|
||||
int optlen = strlen(argv[optind-1]);
|
||||
const char* optstr = argv[optind-1];
|
||||
for(; *optstr == '-'; ++optstr);
|
||||
int optstrlen = strlen(optstr);
|
||||
if(optstrlen+1 >= optlen) {
|
||||
// If this is short option form (1 '-' prefix), just throw
|
||||
// error here.
|
||||
throw DL_ABORT_EX2("Failed to parse command-line options.",
|
||||
error_code::OPTION_ERROR);
|
||||
}
|
||||
// There are 3 situations: 1) completely unknown option 2)
|
||||
// getopt_long() complained because too few arguments. 3)
|
||||
// option is ambiguous.
|
||||
int ambiguous = 0;
|
||||
for(int i = 1, len = option::countOption(); i < len; ++i) {
|
||||
const Pref* pref = option::i2p(i);
|
||||
const SharedHandle<OptionHandler>& h = find(pref);
|
||||
if(h && !h->isHidden()) {
|
||||
if(strcmp(pref->k, optstr) == 0) {
|
||||
// Exact match, this means getopt_long detected error
|
||||
// while handling this option.
|
||||
throw DL_ABORT_EX2("Failed to parse command-line options.",
|
||||
error_code::OPTION_ERROR);
|
||||
} else if(util::startsWith(pref->k, pref->k+strlen(pref->k),
|
||||
optstr, optstr+optstrlen)) {
|
||||
++ambiguous;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ambiguous == 1) {
|
||||
// This is successfully abbreviated option. So it must be case
|
||||
// 2).
|
||||
throw DL_ABORT_EX2("Failed to parse command-line options.",
|
||||
error_code::OPTION_ERROR);
|
||||
}
|
||||
throw UNKNOWN_OPTION_EXCEPTION(argv[optind-1]);
|
||||
}
|
||||
if(!op) {
|
||||
throw DL_ABORT_EX2("Failed to parse command-line options.",
|
||||
error_code::OPTION_ERROR);
|
||||
}
|
||||
assert(op);
|
||||
out << op->getName() << "=";
|
||||
if(optarg) {
|
||||
out << optarg;
|
||||
|
@ -189,8 +229,9 @@ void OptionParser::parse(Option& option, std::istream& is) const
|
|||
if(nv.first.first == nv.first.second) {
|
||||
continue;
|
||||
}
|
||||
const SharedHandle<OptionHandler>& handler =
|
||||
find(option::k2p(std::string(nv.first.first, nv.first.second)));
|
||||
const Pref* pref =
|
||||
option::k2p(std::string(nv.first.first, nv.first.second));
|
||||
const SharedHandle<OptionHandler>& handler = find(pref);
|
||||
if(handler) {
|
||||
handler->parse(option, std::string(nv.second.first, nv.second.second));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2011 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#include "UnknownOptionException.h"
|
||||
#include "fmt.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
namespace {
|
||||
const char* MESSAGE = _("Unknown option '%s'");
|
||||
} // namespace
|
||||
|
||||
UnknownOptionException::UnknownOptionException
|
||||
(const char* file, int line, const std::string& unknownOption)
|
||||
: RecoverableException
|
||||
(file, line, fmt(MESSAGE, unknownOption.c_str()), error_code::OPTION_ERROR),
|
||||
unknownOption_(unknownOption)
|
||||
{}
|
||||
|
||||
UnknownOptionException::UnknownOptionException
|
||||
(const char* file, int line, const std::string& unknownOption,
|
||||
const Exception& cause)
|
||||
: RecoverableException
|
||||
(file, line, fmt(MESSAGE, unknownOption.c_str()), error_code::OPTION_ERROR,
|
||||
cause),
|
||||
unknownOption_(unknownOption)
|
||||
{}
|
||||
|
||||
UnknownOptionException::~UnknownOptionException() throw() {}
|
||||
|
||||
SharedHandle<Exception> UnknownOptionException::copy() const
|
||||
{
|
||||
SharedHandle<Exception> e(new UnknownOptionException(*this));
|
||||
return e;
|
||||
}
|
||||
|
||||
} // namespace aria2
|
|
@ -0,0 +1,69 @@
|
|||
/* <!-- copyright */
|
||||
/*
|
||||
* aria2 - The high speed download utility
|
||||
*
|
||||
* Copyright (C) 2011 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* In addition, as a special exception, the copyright holders give
|
||||
* permission to link the code of portions of this program with the
|
||||
* OpenSSL library under certain conditions as described in each
|
||||
* individual source file, and distribute linked combinations
|
||||
* including the two.
|
||||
* You must obey the GNU General Public License in all respects
|
||||
* for all of the code used other than OpenSSL. If you modify
|
||||
* file(s) with this exception, you may extend this exception to your
|
||||
* version of the file(s), but you are not obligated to do so. If you
|
||||
* do not wish to do so, delete this exception statement from your
|
||||
* version. If you delete this exception statement from all source
|
||||
* files in the program, then also delete it here.
|
||||
*/
|
||||
/* copyright --> */
|
||||
#ifndef D_UNKNOWN_OPTION_EXCEPTION_H
|
||||
#define D_UNKNOWN_OPTION_EXCEPTION_H
|
||||
#include "RecoverableException.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
class UnknownOptionException:public RecoverableException {
|
||||
private:
|
||||
std::string unknownOption_;
|
||||
protected:
|
||||
virtual SharedHandle<Exception> copy() const;
|
||||
public:
|
||||
UnknownOptionException(const char* file, int line,
|
||||
const std::string& unknownOption);
|
||||
|
||||
UnknownOptionException(const char* file, int line,
|
||||
const std::string& unknownOption,
|
||||
const Exception& cause);
|
||||
|
||||
virtual ~UnknownOptionException() throw();
|
||||
|
||||
const std::string& getUnknownOption() const
|
||||
{
|
||||
return unknownOption_;
|
||||
}
|
||||
};
|
||||
|
||||
#define UNKNOWN_OPTION_EXCEPTION(arg) \
|
||||
UnknownOptionException(__FILE__, __LINE__, arg)
|
||||
#define UNKNOWN_OPTION_EXCEPTION2(arg1, arg2) \
|
||||
UnknownOptionException(__FILE__, __LINE__, arg1, arg2)
|
||||
|
||||
} // namespace aria2
|
||||
|
||||
#endif // D_UNKNOWN_OPTION_EXCEPTION_EX_H
|
|
@ -45,19 +45,16 @@
|
|||
|
||||
namespace aria2 {
|
||||
|
||||
#ifdef __MINGW32__
|
||||
typedef SharedHandle<WinConsoleFile> Console;
|
||||
#else // !__MINGW32__
|
||||
typedef SharedHandle<BufferedFile> Console;
|
||||
#endif // !__MINGW32__
|
||||
|
||||
namespace global {
|
||||
|
||||
#ifdef __MINGW32__
|
||||
const SharedHandle<WinConsoleFile>& cout();
|
||||
#else // !__MINGW32__
|
||||
const SharedHandle<BufferedFile>& cout();
|
||||
#endif // !__MINGW32__
|
||||
|
||||
#ifdef __MINGW32__
|
||||
const SharedHandle<WinConsoleFile>& cerr();
|
||||
#else // !__MINGW32__
|
||||
const SharedHandle<BufferedFile>& cerr();
|
||||
#endif // !__MINGW32__
|
||||
const Console& cout();
|
||||
const Console& cerr();
|
||||
|
||||
} // namespace global
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "Option.h"
|
||||
#include "prefs.h"
|
||||
|
@ -52,6 +51,7 @@
|
|||
#include "File.h"
|
||||
#include "fmt.h"
|
||||
#include "OptionHandlerException.h"
|
||||
#include "UnknownOptionException.h"
|
||||
#include "error_code.h"
|
||||
#include "SimpleRandomizer.h"
|
||||
#include "bittorrent_helper.h"
|
||||
|
@ -66,7 +66,9 @@ namespace aria2 {
|
|||
|
||||
extern void showVersion();
|
||||
extern void showUsage
|
||||
(const std::string& keyword, const SharedHandle<OptionParser>& oparser);
|
||||
(const std::string& keyword,
|
||||
const SharedHandle<OptionParser>& oparser,
|
||||
const Console& out);
|
||||
|
||||
namespace {
|
||||
void overrideWithEnv
|
||||
|
@ -81,14 +83,98 @@ void overrideWithEnv
|
|||
optionParser->find(pref)->parse(op, value);
|
||||
} catch(Exception& e) {
|
||||
global::cerr()->printf
|
||||
("Caught Error while parsing environment variable '%s'\n%s\n",
|
||||
envName.c_str(),
|
||||
e.stackTrace().c_str());
|
||||
(_("Caught Error while parsing environment variable '%s'"),
|
||||
envName.c_str());
|
||||
global::cerr()->printf("\n%s\n", e.stackTrace().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int levenstein
|
||||
(const char* a,
|
||||
const char* b,
|
||||
int swapcost,
|
||||
int subcost,
|
||||
int addcost,
|
||||
int delcost)
|
||||
{
|
||||
int alen = strlen(a);
|
||||
int blen = strlen(b);
|
||||
std::vector<std::vector<int> > dp(3, std::vector<int>(blen+1));
|
||||
for(int i = 0; i <= blen; ++i) {
|
||||
dp[1][i] = i;
|
||||
}
|
||||
for(int i = 1; i <= alen; ++i) {
|
||||
dp[0][0] = i;
|
||||
for(int j = 1; j <= blen; ++j) {
|
||||
if(a[i-1] == b[j-1]) {
|
||||
dp[0][j] = dp[1][j-1];
|
||||
} else {
|
||||
dp[0][j] = dp[1][j-1]+subcost;
|
||||
}
|
||||
if(i >= 2 && j >= 2 && a[i-1] != b[j-1] &&
|
||||
a[i-2] == b[j-1] && a[i-1] == b[j-2]) {
|
||||
dp[0][j] = std::min(dp[0][j], dp[2][j-2]+swapcost);
|
||||
}
|
||||
dp[0][j] = std::min(dp[0][j],
|
||||
std::min(dp[1][j]+delcost, dp[0][j-1]+addcost));
|
||||
}
|
||||
std::rotate(dp.begin(), dp.begin()+2, dp.end());
|
||||
}
|
||||
return dp[1][blen];
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
|
||||
void showCandidates
|
||||
(const std::string& unknownOption, const SharedHandle<OptionParser>& parser)
|
||||
{
|
||||
const char* optstr = unknownOption.c_str();
|
||||
for(; *optstr == '-'; ++optstr);
|
||||
if(*optstr == '\0') {
|
||||
return;
|
||||
}
|
||||
int optstrlen = strlen(optstr);
|
||||
std::vector<std::pair<int, const Pref*> > cands;
|
||||
for(int i = 1, len = option::countOption(); i < len; ++i) {
|
||||
const Pref* pref = option::i2p(i);
|
||||
const SharedHandle<OptionHandler>& h = parser->find(pref);
|
||||
if(!h || h->isHidden()) {
|
||||
continue;
|
||||
}
|
||||
// Use cost 0 for prefix match
|
||||
if(util::startsWith(pref->k, pref->k+strlen(pref->k),
|
||||
optstr, optstr+optstrlen)) {
|
||||
cands.push_back(std::make_pair(0, pref));
|
||||
continue;
|
||||
}
|
||||
// cost values are borrowed from git, help.c.
|
||||
int sim = levenstein(optstr, pref->k, 0, 2, 1, 4);
|
||||
cands.push_back(std::make_pair(sim, pref));
|
||||
}
|
||||
if(cands.empty()) {
|
||||
return;
|
||||
}
|
||||
std::sort(cands.begin(), cands.end());
|
||||
int threshold = cands[0].first;
|
||||
// threshold value 7 is borrowed from git, help.c.
|
||||
if(threshold >= 7) {
|
||||
return;
|
||||
}
|
||||
global::cerr()->printf("\n");
|
||||
global::cerr()->printf(_("Did you mean:"));
|
||||
global::cerr()->printf("\n");
|
||||
for(std::vector<std::pair<int, const Pref*> >::iterator i = cands.begin(),
|
||||
eoi = cands.end(); i != eoi && (*i).first <= threshold; ++i) {
|
||||
global::cerr()->printf("\t--%s\n", (*i).second->k);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void option_processing(Option& op, std::vector<std::string>& uris,
|
||||
int argc, char* argv[])
|
||||
{
|
||||
|
@ -125,7 +211,7 @@ void option_processing(Option& op, std::vector<std::string>& uris,
|
|||
keyword.erase(keyword.begin()+eqpos, keyword.end());
|
||||
}
|
||||
}
|
||||
showUsage(keyword, oparser);
|
||||
showUsage(keyword, oparser, global::cout());
|
||||
exit(error_code::FINISHED);
|
||||
}
|
||||
}
|
||||
|
@ -148,24 +234,24 @@ void option_processing(Option& op, std::vector<std::string>& uris,
|
|||
try {
|
||||
oparser->parse(op, ss);
|
||||
} catch(OptionHandlerException& e) {
|
||||
global::cerr()->printf("Parse error in %s\n%s\n",
|
||||
cfname.c_str(),
|
||||
e.stackTrace().c_str());
|
||||
global::cerr()->printf(_("Parse error in %s"), cfname.c_str());
|
||||
global::cerr()->printf("\n%s", e.stackTrace().c_str());
|
||||
const SharedHandle<OptionHandler>& h = oparser->find(e.getPref());
|
||||
if(h) {
|
||||
global::cerr()->printf("Usage:\n%s\n", h->getDescription());
|
||||
global::cerr()->printf(_("Usage:"));
|
||||
global::cerr()->printf("\n%s\n", h->getDescription());
|
||||
}
|
||||
exit(e.getErrorCode());
|
||||
} catch(Exception& e) {
|
||||
global::cerr()->printf("Parse error in %s\n%s\n",
|
||||
cfname.c_str(),
|
||||
e.stackTrace().c_str());
|
||||
global::cerr()->printf(_("Parse error in %s"), cfname.c_str());
|
||||
global::cerr()->printf("\n%s", e.stackTrace().c_str());
|
||||
exit(e.getErrorCode());
|
||||
}
|
||||
} else if(!ucfname.empty()) {
|
||||
global::cerr()->printf("Configuration file %s is not found.\n",
|
||||
global::cerr()->printf(_("Configuration file %s is not found."),
|
||||
cfname.c_str());
|
||||
showUsage(TAG_HELP, oparser);
|
||||
global::cerr()->printf("\n");
|
||||
showUsage(TAG_HELP, oparser, global::cerr());
|
||||
exit(error_code::UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
|
@ -190,17 +276,21 @@ void option_processing(Option& op, std::vector<std::string>& uris,
|
|||
}
|
||||
#endif // __MINGW32__
|
||||
} catch(OptionHandlerException& e) {
|
||||
global::cerr()->printf("%s\n", e.stackTrace().c_str());
|
||||
global::cerr()->printf("%s", e.stackTrace().c_str());
|
||||
const SharedHandle<OptionHandler>& h = oparser->find(e.getPref());
|
||||
if(h) {
|
||||
std::ostringstream ss;
|
||||
ss << *h;
|
||||
global::cerr()->printf("Usage:\n%s\n", ss.str().c_str());
|
||||
global::cerr()->printf(_("Usage:"));
|
||||
global::cerr()->printf("\n");
|
||||
write(global::cerr(), *h);
|
||||
}
|
||||
exit(e.getErrorCode());
|
||||
} catch(UnknownOptionException& e) {
|
||||
showUsage("", oparser, global::cerr());
|
||||
showCandidates(e.getUnknownOption(), oparser);
|
||||
exit(e.getErrorCode());
|
||||
} catch(Exception& e) {
|
||||
global::cerr()->printf("%s\n", e.stackTrace().c_str());
|
||||
showUsage(TAG_HELP, oparser);
|
||||
global::cerr()->printf("%s", e.stackTrace().c_str());
|
||||
showUsage("", oparser, global::cerr());
|
||||
exit(e.getErrorCode());
|
||||
}
|
||||
if(!op.getAsBool(PREF_ENABLE_RPC) &&
|
||||
|
@ -212,8 +302,9 @@ void option_processing(Option& op, std::vector<std::string>& uris,
|
|||
#endif // ENABLE_METALINK
|
||||
op.blank(PREF_INPUT_FILE)) {
|
||||
if(uris.empty()) {
|
||||
global::cerr()->printf("%s\n", MSG_URI_REQUIRED);
|
||||
showUsage(TAG_HELP, oparser);
|
||||
global::cerr()->printf(MSG_URI_REQUIRED);
|
||||
global::cerr()->printf("\n");
|
||||
showUsage("", oparser, global::cerr());
|
||||
exit(error_code::UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,76 +82,84 @@ void showVersion() {
|
|||
|
||||
void showUsage
|
||||
(const std::string& keyword,
|
||||
const SharedHandle<OptionParser>& oparser) {
|
||||
std::cout << _("Usage: aria2c [OPTIONS] [URI | MAGNET | TORRENT_FILE |"
|
||||
" METALINK_FILE]...") << "\n"
|
||||
<< "\n";
|
||||
if(!keyword.empty() && keyword[0] == '#') {
|
||||
const SharedHandle<OptionParser>& oparser,
|
||||
const Console& out) {
|
||||
out->printf(_("Usage: aria2c [OPTIONS] [URI | MAGNET | TORRENT_FILE |"
|
||||
" METALINK_FILE]..."));
|
||||
out->printf("\n");
|
||||
if(keyword.empty()) {
|
||||
// Very short version of usage.
|
||||
out->printf(_("See 'aria2c -h'."));
|
||||
out->printf("\n");
|
||||
return;
|
||||
} else if(keyword[0] == '#') {
|
||||
std::vector<SharedHandle<OptionHandler> > handlers =
|
||||
keyword == TAG_ALL ? oparser->findAll() : oparser->findByTag(keyword);
|
||||
if(keyword == TAG_ALL) {
|
||||
std::cout << _("Printing all options.");
|
||||
out->printf(_("Printing all options."));
|
||||
} else {
|
||||
std::cout << fmt(_("Printing options tagged with '%s'."),
|
||||
keyword.c_str());
|
||||
std::cout << "\n";
|
||||
const SharedHandle<OptionHandler>& help = oparser->find(PREF_HELP);
|
||||
std::cout << fmt(_("See -h option to know other command-line"
|
||||
" options(%s)."),
|
||||
help->createPossibleValuesString().c_str());
|
||||
out->printf(_("Printing options tagged with '%s'."),
|
||||
keyword.c_str());
|
||||
out->printf("\n");
|
||||
out->printf(_("See 'aria2c -h#help' to know all available tags."));
|
||||
}
|
||||
std::cout << "\n"
|
||||
<< _("Options:") << "\n";
|
||||
out->printf("\n");
|
||||
out->printf(_("Options:"));
|
||||
out->printf("\n");
|
||||
for(std::vector<SharedHandle<OptionHandler> >::const_iterator i =
|
||||
handlers.begin(), eoi = handlers.end(); i != eoi; ++i) {
|
||||
std::cout << *(*i) << "\n\n";
|
||||
write(out, *(*i));
|
||||
out->printf("\n");
|
||||
}
|
||||
} else {
|
||||
std::vector<SharedHandle<OptionHandler> > handlers =
|
||||
oparser->findByNameSubstring(keyword);
|
||||
if(!handlers.empty()) {
|
||||
std::cout << fmt(_("Printing options whose name includes '%s'."),
|
||||
keyword.c_str())
|
||||
<< "\n"
|
||||
<< _("Options:") << "\n";
|
||||
out->printf(_("Printing options whose name includes '%s'."),
|
||||
keyword.c_str());
|
||||
out->printf("\n");
|
||||
out->printf(_("Options:"));
|
||||
out->printf("\n");
|
||||
for(std::vector<SharedHandle<OptionHandler> >::const_iterator i =
|
||||
handlers.begin(), eoi = handlers.end(); i != eoi; ++i) {
|
||||
std::cout << *(*i) << "\n\n";
|
||||
write(out, *(*i));
|
||||
out->printf("\n");
|
||||
}
|
||||
} else {
|
||||
std::cout << fmt(_("No option matching with '%s'."),
|
||||
keyword.c_str())
|
||||
<< "\n" << *oparser->find(PREF_HELP) << "\n";
|
||||
out->printf(_("No option matching with '%s'."),
|
||||
keyword.c_str());
|
||||
out->printf("\n");
|
||||
write(out, *oparser->find(PREF_HELP));
|
||||
}
|
||||
}
|
||||
|
||||
if(keyword == TAG_BASIC) {
|
||||
std::cout << "URI, MAGNET, TORRENT_FILE, METALINK_FILE:" << "\n"
|
||||
<< _(" You can specify multiple HTTP(S)/FTP URIs. Unless you specify -Z option, all\n"
|
||||
" URIs must point to the same file or downloading will fail.") << "\n"
|
||||
<< _(" You can also specify arbitrary number of BitTorrent Magnet URIs, torrent/\n"
|
||||
" metalink files stored in a local drive. Please note that they are always\n"
|
||||
" treated as a separate download.") << "\n"
|
||||
|
||||
<< "\n"
|
||||
<< _(" You can specify both torrent file with -T option and URIs. By doing this,\n"
|
||||
" download a file from both torrent swarm and HTTP/FTP server at the same time,\n"
|
||||
" while the data from HTTP/FTP are uploaded to the torrent swarm. For single file\n"
|
||||
" torrents, URI can be a complete URI pointing to the resource or if URI ends\n"
|
||||
" with '/', 'name' in torrent file is added. For multi-file torrents, 'name' and\n"
|
||||
" 'path' in torrent are added to form a URI for each file.") << "\n"
|
||||
<< "\n"
|
||||
<< _(" Make sure that URI is quoted with single(\') or double(\") quotation if it\n"
|
||||
" contains \"&\" or any characters that have special meaning in shell.") << "\n"
|
||||
<< "\n";
|
||||
std::cout << "About the number of connections\n"
|
||||
<< " Since 1.10.0 release, aria2 uses 1 connection per host by default and has 20MiB\n"
|
||||
<< " segment size restriction. So whatever value you specify using -s option, it\n"
|
||||
<< " uses 1 connection per host. To make it behave like 1.9.x, use\n"
|
||||
<< " --max-connection-per-server=4 --min-split-size=1M.\n"
|
||||
<< "\n";
|
||||
out->printf("URI, MAGNET, TORRENT_FILE, METALINK_FILE:\n");
|
||||
out->printf(_(" You can specify multiple HTTP(S)/FTP URIs. Unless you specify -Z option, all\n"
|
||||
" URIs must point to the same file or downloading will fail."));
|
||||
out->printf("\n");
|
||||
out->printf(_(" You can also specify arbitrary number of BitTorrent Magnet URIs, torrent/\n"
|
||||
" metalink files stored in a local drive. Please note that they are always\n"
|
||||
" treated as a separate download."));
|
||||
out->printf("\n\n");
|
||||
out->printf(_(" You can specify both torrent file with -T option and URIs. By doing this,\n"
|
||||
" download a file from both torrent swarm and HTTP/FTP server at the same time,\n"
|
||||
" while the data from HTTP/FTP are uploaded to the torrent swarm. For single file\n"
|
||||
" torrents, URI can be a complete URI pointing to the resource or if URI ends\n"
|
||||
" with '/', 'name' in torrent file is added. For multi-file torrents, 'name' and\n"
|
||||
" 'path' in torrent are added to form a URI for each file."));
|
||||
out->printf("\n\n");
|
||||
out->printf(_(" Make sure that URI is quoted with single(\') or double(\") quotation if it\n"
|
||||
" contains \"&\" or any characters that have special meaning in shell."));
|
||||
out->printf("\n\n");
|
||||
out->printf("About the number of connections\n"
|
||||
" Since 1.10.0 release, aria2 uses 1 connection per host by default and has 20MiB\n"
|
||||
" segment size restriction. So whatever value you specify using -s option, it\n"
|
||||
" uses 1 connection per host. To make it behave like 1.9.x, use\n"
|
||||
" --max-connection-per-server=4 --min-split-size=1M.\n"
|
||||
"\n");
|
||||
}
|
||||
std::cout << _("Refer to man page for more information.") << std::endl;
|
||||
out->printf(_("Refer to man page for more information."));
|
||||
out->printf("\n");
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
Loading…
Reference in New Issue