OpenShot Library | libopenshot-audio  0.2.0
juce_ConsoleApplication.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 static inline File resolveFilename (const String& name)
27 {
28  return File::getCurrentWorkingDirectory().getChildFile (name.unquoted());
29 }
30 
31 static inline void checkFileExists (const File& f)
32 {
33  if (! f.exists())
34  ConsoleApplication::fail ("Could not find file: " + f.getFullPathName());
35 }
36 
37 static inline void checkFolderExists (const File& f)
38 {
39  if (! f.isDirectory())
40  ConsoleApplication::fail ("Could not find folder: " + f.getFullPathName());
41 }
42 
44 {
45  return resolveFilename (text);
46 }
47 
49 {
50  auto f = resolveAsFile();
51  checkFileExists (f);
52  return f;
53 }
54 
56 {
57  auto f = resolveAsFile();
58 
59  if (! f.isDirectory())
60  ConsoleApplication::fail ("Could not find folder: " + f.getFullPathName());
61 
62  return f;
63 }
64 
65 static inline bool isShortOptionFormat (StringRef s) { return s[0] == '-' && s[1] != '-'; }
66 static inline bool isLongOptionFormat (StringRef s) { return s[0] == '-' && s[1] == '-' && s[2] != '-'; }
67 static inline bool isOptionFormat (StringRef s) { return s[0] == '-'; }
68 
69 bool ArgumentList::Argument::isLongOption() const { return isLongOptionFormat (text); }
70 bool ArgumentList::Argument::isShortOption() const { return isShortOptionFormat (text); }
71 bool ArgumentList::Argument::isOption() const { return isOptionFormat (text); }
72 
73 bool ArgumentList::Argument::isLongOption (const String& option) const
74 {
75  if (! isLongOptionFormat (option))
76  {
77  jassert (! isShortOptionFormat (option)); // this will always fail to match
78  return isLongOption ("--" + option);
79  }
80 
81  return text.upToFirstOccurrenceOf ("=", false, false) == option;
82 }
83 
85 {
86  if (isLongOption())
87  if (auto equalsIndex = text.indexOfChar ('='))
88  return text.substring (equalsIndex + 1);
89 
90  return {};
91 }
92 
93 bool ArgumentList::Argument::isShortOption (char option) const
94 {
95  jassert (option != '-'); // this is probably not what you intended to pass in
96 
97  return isShortOption() && text.containsChar (option);
98 }
99 
101 {
102  for (auto& o : StringArray::fromTokens (wildcard, "|", {}))
103  {
104  if (text == o)
105  return true;
106 
107  if (isShortOptionFormat (o) && o.length() == 2 && isShortOption ((char) o[1]))
108  return true;
109 
110  if (isLongOptionFormat (o) && isLongOption (o))
111  return true;
112  }
113 
114  return false;
115 }
116 
117 bool ArgumentList::Argument::operator!= (StringRef s) const { return ! operator== (s); }
118 
119 //==============================================================================
121  : executableName (std::move (exeName))
122 {
123  args.trim();
124  args.removeEmptyStrings();
125 
126  for (auto& a : args)
127  arguments.add ({ a });
128 }
129 
130 ArgumentList::ArgumentList (int argc, char* argv[])
131  : ArgumentList (argv[0], StringArray (argv + 1, argc - 1))
132 {
133 }
134 
135 ArgumentList::ArgumentList (const String& exeName, const String& args)
136  : ArgumentList (exeName, StringArray::fromTokens (args, true))
137 {
138 }
139 
140 int ArgumentList::size() const { return arguments.size(); }
141 ArgumentList::Argument ArgumentList::operator[] (int index) const { return arguments[index]; }
142 
143 void ArgumentList::checkMinNumArguments (int expectedMinNumberOfArgs) const
144 {
145  if (size() < expectedMinNumberOfArgs)
146  ConsoleApplication::fail ("Not enough arguments!");
147 }
148 
150 {
151  jassert (option == String (option).trim()); // passing non-trimmed strings will always fail to find a match!
152 
153  for (int i = 0; i < arguments.size(); ++i)
154  if (arguments.getReference(i) == option)
155  return i;
156 
157  return -1;
158 }
159 
161 {
162  return indexOfOption (option) >= 0;
163 }
164 
166 {
167  if (! containsOption (option))
168  ConsoleApplication::fail ("Expected the option " + option);
169 }
170 
172 {
173  jassert (isOptionFormat (option)); // the thing you're searching for must be an option
174 
175  for (int i = 0; i < arguments.size(); ++i)
176  {
177  auto& arg = arguments.getReference(i);
178 
179  if (arg == option)
180  {
181  if (arg.isShortOption())
182  {
183  if (i < arguments.size() - 1 && ! arguments.getReference (i + 1).isOption())
184  return arguments.getReference (i + 1).text;
185 
186  return {};
187  }
188 
189  if (arg.isLongOption())
190  return arg.getLongOptionValue();
191  }
192  }
193 
194  return {};
195 }
196 
198 {
199  auto text = getValueForOption (option);
200 
201  if (text.isEmpty())
202  {
203  failIfOptionIsMissing (option);
204  ConsoleApplication::fail ("Expected a filename after the " + option + " option");
205  }
206 
207  return resolveFilename (text);
208 }
209 
211 {
212  auto file = getFileForOption (option);
213  checkFileExists (file);
214  return file;
215 }
216 
218 {
219  auto file = getFileForOption (option);
220  checkFolderExists (file);
221  return file;
222 }
223 
224 //==============================================================================
226 {
227  String errorMessage;
228  int returnCode;
229 };
230 
231 void ConsoleApplication::fail (String errorMessage, int returnCode)
232 {
233  throw ConsoleAppFailureCode { std::move (errorMessage), returnCode };
234 }
235 
236 int ConsoleApplication::invokeCatchingFailures (std::function<int()>&& f)
237 {
238  int returnCode = 0;
239 
240  try
241  {
242  returnCode = f();
243  }
244  catch (const ConsoleAppFailureCode& error)
245  {
246  std::cout << error.errorMessage << std::endl;
247  returnCode = error.returnCode;
248  }
249 
250  return returnCode;
251 }
252 
253 const ConsoleApplication::Command* ConsoleApplication::findCommand (const ArgumentList& args, bool optionMustBeFirstArg) const
254 {
255  for (auto& c : commands)
256  {
257  auto index = args.indexOfOption (c.commandOption);
258 
259  if (optionMustBeFirstArg ? (index == 0) : (index >= 0))
260  return &c;
261  }
262 
263  if (commandIfNoOthersRecognised >= 0)
264  return &commands[(size_t) commandIfNoOthersRecognised];
265 
266  return {};
267 }
268 
269 int ConsoleApplication::findAndRunCommand (const ArgumentList& args, bool optionMustBeFirstArg) const
270 {
271  if (auto c = findCommand (args, optionMustBeFirstArg))
272  return invokeCatchingFailures ([=] { c->command (args); return 0; });
273 
274  fail ("Unrecognised arguments");
275  return 0;
276 }
277 
278 int ConsoleApplication::findAndRunCommand (int argc, char* argv[]) const
279 {
280  return findAndRunCommand (ArgumentList (argc, argv));
281 }
282 
284 {
285  commands.emplace_back (std::move (c));
286 }
287 
289 {
290  commandIfNoOthersRecognised = (int) commands.size();
291  addCommand (std::move (c));
292 }
293 
294 void ConsoleApplication::addHelpCommand (String arg, String helpMessage, bool makeDefaultCommand)
295 {
296  Command c { arg, arg, "Prints the list of commands", {},
297  [this, helpMessage] (const ArgumentList& args)
298  {
299  std::cout << helpMessage << std::endl;
300  printCommandList (args);
301  }};
302 
303  if (makeDefaultCommand)
304  addDefaultCommand (std::move (c));
305  else
306  addCommand (std::move (c));
307 }
308 
310 {
311  addCommand ({ arg, arg, "Prints the current version number", {},
312  [versionText] (const ArgumentList&)
313  {
314  std::cout << versionText << std::endl;
315  }});
316 }
317 
318 const std::vector<ConsoleApplication::Command>& ConsoleApplication::getCommands() const
319 {
320  return commands;
321 }
322 
324 {
325  auto exeName = args.executableName.fromLastOccurrenceOf ("/", false, false)
326  .fromLastOccurrenceOf ("\\", false, false);
327 
328  StringArray namesAndArgs;
329  int descriptionIndent = 0;
330 
331  for (auto& c : commands)
332  {
333  auto nameAndArgs = exeName + " " + c.argumentDescription;
334  namesAndArgs.add (nameAndArgs);
335  descriptionIndent = std::max (descriptionIndent, nameAndArgs.length());
336  }
337 
338  descriptionIndent = std::min (descriptionIndent + 1, 40);
339 
340  for (size_t i = 0; i < commands.size(); ++i)
341  {
342  auto nameAndArgs = namesAndArgs[(int) i];
343  std::cout << ' ';
344 
345  if (nameAndArgs.length() > descriptionIndent)
346  std::cout << nameAndArgs << std::endl << String::repeatedString (" ", descriptionIndent + 1);
347  else
348  std::cout << nameAndArgs.paddedRight (' ', descriptionIndent);
349 
350  std::cout << commands[i].shortDescription << std::endl;
351  }
352 
353  std::cout << std::endl;
354 }
355 
356 } // namespace juce
juce::StringArray
A special array for holding a list of strings.
Definition: juce_StringArray.h:38
juce::ArgumentList::ArgumentList
ArgumentList(String executable, StringArray arguments)
Creates an argument list for a given executable.
Definition: juce_ConsoleApplication.cpp:120
juce::ArgumentList::Argument::operator!=
bool operator!=(StringRef stringToCompare) const
Compares this argument against a string.
Definition: juce_ConsoleApplication.cpp:117
juce::StringRef
A simple class for holding temporary references to a string literal or String.
Definition: juce_StringRef.h:65
juce::ArgumentList
Holds a list of command-line arguments, and provides useful methods for searching and operating on th...
Definition: juce_ConsoleApplication.h:40
juce::ArgumentList::getValueForOption
String getValueForOption(StringRef option) const
Looks for a given argument and returns either its assigned value (for long options) or the string tha...
Definition: juce_ConsoleApplication.cpp:171
juce::ArgumentList::operator[]
Argument operator[](int index) const
Returns one of the arguments.
Definition: juce_ConsoleApplication.cpp:141
juce::ArgumentList::size
int size() const
Returns the number of arguments in the list.
Definition: juce_ConsoleApplication.cpp:140
juce::ArgumentList::Argument::resolveAsExistingFile
File resolveAsExistingFile() const
Resolves this argument as an absolute File, using the current working directory as a base for resolvi...
Definition: juce_ConsoleApplication.cpp:48
juce::StringArray::trim
void trim()
Deletes any whitespace characters from the starts and ends of all the strings.
Definition: juce_StringArray.cpp:265
juce::StringArray::removeEmptyStrings
void removeEmptyStrings(bool removeWhitespaceStrings=true)
Removes empty strings from the array.
Definition: juce_StringArray.cpp:249
juce::ConsoleApplication::Command
Represents a command that can be executed if its command-line arguments are matched.
Definition: juce_ConsoleApplication.h:208
juce::ConsoleApplication::addVersionCommand
void addVersionCommand(String versionArgument, String versionText)
Adds a command that will print the given text in response to the "--version" option.
Definition: juce_ConsoleApplication.cpp:309
juce::File::getCurrentWorkingDirectory
static File getCurrentWorkingDirectory()
Returns the current working directory.
juce::ArgumentList::failIfOptionIsMissing
void failIfOptionIsMissing(StringRef option) const
Throws an error unless the given option is found in the argument list.
Definition: juce_ConsoleApplication.cpp:165
juce::ConsoleApplication::getCommands
const std::vector< Command > & getCommands() const
Gives read-only access to the list of registered commands.
Definition: juce_ConsoleApplication.cpp:318
juce::ArgumentList::getFileForOption
File getFileForOption(StringRef option) const
Looks for the value of argument using getValueForOption() and tries to parse that value as a file.
Definition: juce_ConsoleApplication.cpp:197
juce::ConsoleApplication::findCommand
const Command * findCommand(const ArgumentList &, bool optionMustBeFirstArg) const
Looks for the first command in the list which matches the given arguments.
Definition: juce_ConsoleApplication.cpp:253
juce::StringArray::fromTokens
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
Returns an array containing the tokens in a given string.
Definition: juce_StringArray.cpp:386
juce::ArgumentList::Argument::getLongOptionValue
String getLongOptionValue() const
If this argument is a long option with a value, this returns the value.
Definition: juce_ConsoleApplication.cpp:84
juce::ArgumentList::indexOfOption
int indexOfOption(StringRef option) const
Returns the index of the given string if it matches one of the arguments, or -1 if it doesn't.
Definition: juce_ConsoleApplication.cpp:149
juce::ConsoleApplication::invokeCatchingFailures
static int invokeCatchingFailures(std::function< int()> &&functionToCall)
Invokes a function, catching any fail() calls that it might trigger, and handling them by printing th...
Definition: juce_ConsoleApplication.cpp:236
juce::ArgumentList::Argument::resolveAsFile
File resolveAsFile() const
Resolves this argument as an absolute File, using the current working directory as a base for resolvi...
Definition: juce_ConsoleApplication.cpp:43
juce::String::repeatedString
static String repeatedString(StringRef stringToRepeat, int numberOfTimesToRepeat)
Creates a string which is a version of a string repeated and joined together.
Definition: juce_String.cpp:1153
juce::ArgumentList::executableName
String executableName
The name or path of the executable that was invoked, as it was specified on the command-line.
Definition: juce_ConsoleApplication.h:167
juce::ArgumentList::Argument::operator==
bool operator==(StringRef stringToCompare) const
Compares this argument against a string.
Definition: juce_ConsoleApplication.cpp:100
juce::ConsoleApplication::findAndRunCommand
int findAndRunCommand(const ArgumentList &, bool optionMustBeFirstArg=false) const
Looks for the first command in the list which matches the given arguments, and tries to invoke it.
Definition: juce_ConsoleApplication.cpp:269
juce::ArgumentList::Argument::isOption
bool isOption() const
Returns true if this argument starts with one or more dashes.
Definition: juce_ConsoleApplication.cpp:71
juce::File
Represents a local file or directory.
Definition: juce_File.h:44
juce::ArgumentList::Argument
One of the arguments in an ArgumentList.
Definition: juce_ConsoleApplication.h:58
juce::ConsoleApplication::addDefaultCommand
void addDefaultCommand(Command)
Adds a command to the list, and marks it as one which is invoked if no other command matches.
Definition: juce_ConsoleApplication.cpp:288
juce::ConsoleApplication::fail
static void fail(String errorMessage, int returnCode=1)
Throws a failure exception to cause a command-line app to terminate.
Definition: juce_ConsoleApplication.cpp:231
juce::String::paddedRight
String paddedRight(juce_wchar padCharacter, int minimumLength) const
Returns a copy of this string with the specified character repeatedly added to its end until the tota...
Definition: juce_String.cpp:1194
juce::ArgumentList::getExistingFileForOption
File getExistingFileForOption(StringRef option) const
Looks for a file argument using getFileForOption() and fails with a suitable error if the file doesn'...
Definition: juce_ConsoleApplication.cpp:210
juce::ConsoleApplication::addHelpCommand
void addHelpCommand(String helpArgument, String helpMessage, bool makeDefaultCommand)
Adds a help command to the list.
Definition: juce_ConsoleApplication.cpp:294
juce::ArgumentList::Argument::text
String text
The original text of this argument.
Definition: juce_ConsoleApplication.h:61
juce::ConsoleAppFailureCode
Definition: juce_ConsoleApplication.cpp:225
juce::ConsoleApplication::printCommandList
void printCommandList(const ArgumentList &) const
Prints out the list of commands and their short descriptions in a format that's suitable for use as h...
Definition: juce_ConsoleApplication.cpp:323
juce::ArgumentList::arguments
Array< Argument > arguments
The list of arguments (not including the name of the executable that was invoked).
Definition: juce_ConsoleApplication.h:170
juce::String
The JUCE String class!
Definition: juce_String.h:42
juce::String::substring
String substring(int startIndex, int endIndex) const
Returns a subsection of the string.
Definition: juce_String.cpp:1504
juce::StringArray::add
void add(String stringToAdd)
Appends a string at the end of the array.
Definition: juce_StringArray.cpp:135
juce::ArgumentList::checkMinNumArguments
void checkMinNumArguments(int expectedMinNumberOfArgs) const
Throws an error unless there are at least the given number of arguments.
Definition: juce_ConsoleApplication.cpp:143
juce::ConsoleApplication::addCommand
void addCommand(Command)
Adds a command to the list.
Definition: juce_ConsoleApplication.cpp:283
juce::ArgumentList::containsOption
bool containsOption(StringRef option) const
Returns true if the given string matches one of the arguments.
Definition: juce_ConsoleApplication.cpp:160
juce::ArgumentList::getExistingFolderForOption
File getExistingFolderForOption(StringRef option) const
Looks for a filename argument using getFileForOption() and fails with a suitable error if the file is...
Definition: juce_ConsoleApplication.cpp:217
juce::ArgumentList::Argument::isLongOption
bool isLongOption() const
Returns true if this argument starts with a double dash.
Definition: juce_ConsoleApplication.cpp:69
juce::ArgumentList::Argument::resolveAsExistingFolder
File resolveAsExistingFolder() const
Resolves a user-supplied folder name into an absolute File, using the current working directory as a ...
Definition: juce_ConsoleApplication.cpp:55
juce::ArgumentList::Argument::isShortOption
bool isShortOption() const
Returns true if this argument starts with a single dash.
Definition: juce_ConsoleApplication.cpp:70
juce::String::fromLastOccurrenceOf
String fromLastOccurrenceOf(StringRef substringToFind, bool includeSubStringInResult, bool ignoreCase) const
Returns a section of the string starting from the last occurrence of a given substring.
Definition: juce_String.cpp:1581
juce::File::getChildFile
File getChildFile(StringRef relativeOrAbsolutePath) const
Returns a file that represents a relative (or absolute) sub-path of the current one.
Definition: juce_File.cpp:394