11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/* 21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License. 61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at 71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software 111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and 141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License. 151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Flags.h" 181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/StringPiece.h" 192ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski#include "util/Util.h" 201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <iomanip> 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <iostream> 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <string> 241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <vector> 251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 281ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiFlags& Flags::requiredFlag(const StringPiece& name, const StringPiece& description, 291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string* value) { 301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto func = [value](const StringPiece& arg) -> bool { 311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *value = arg.toString(); 321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return true; 331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski }; 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mFlags.push_back(Flag{ name.toString(), description.toString(), func, true, 1, false}); 361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return *this; 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 391ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiFlags& Flags::requiredFlagList(const StringPiece& name, const StringPiece& description, 401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::vector<std::string>* value) { 411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto func = [value](const StringPiece& arg) -> bool { 421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski value->push_back(arg.toString()); 431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return true; 441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski }; 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mFlags.push_back(Flag{ name.toString(), description.toString(), func, true, 1, false }); 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return *this; 481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 501ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiFlags& Flags::optionalFlag(const StringPiece& name, const StringPiece& description, 511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Maybe<std::string>* value) { 521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto func = [value](const StringPiece& arg) -> bool { 531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *value = arg.toString(); 541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return true; 551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski }; 561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mFlags.push_back(Flag{ name.toString(), description.toString(), func, false, 1, false }); 581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return *this; 591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 611ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiFlags& Flags::optionalFlagList(const StringPiece& name, const StringPiece& description, 621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::vector<std::string>* value) { 631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto func = [value](const StringPiece& arg) -> bool { 641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski value->push_back(arg.toString()); 651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return true; 661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski }; 671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mFlags.push_back(Flag{ name.toString(), description.toString(), func, false, 1, false }); 691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return *this; 701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 721ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiFlags& Flags::optionalSwitch(const StringPiece& name, const StringPiece& description, 731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski bool* value) { 741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski auto func = [value](const StringPiece& arg) -> bool { 751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *value = true; 761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return true; 771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski }; 781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mFlags.push_back(Flag{ name.toString(), description.toString(), func, false, 0, false }); 801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return *this; 811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskivoid Flags::usage(const StringPiece& command, std::ostream* out) { 8452364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski constexpr size_t kWidth = 50; 8552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski 861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *out << command << " [options]"; 871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (const Flag& flag : mFlags) { 881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (flag.required) { 891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *out << " " << flag.name << " arg"; 901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *out << " files...\n\nOptions:\n"; 941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (const Flag& flag : mFlags) { 961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string argLine = flag.name; 971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (flag.numArgs > 0) { 981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski argLine += " arg"; 991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1002ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski 1012ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski // Split the description by newlines and write out the argument (which is empty after 1022ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski // the first line) followed by the description line. This will make sure that multiline 1032ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski // descriptions are still right justified and aligned. 1042ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski for (StringPiece line : util::tokenize<char>(flag.description, '\n')) { 10552364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski *out << " " << std::setw(kWidth) << std::left << argLine << line << "\n"; 1062ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski argLine = " "; 1072ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski } 1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 10952364f7ae31716d7827ea8f8566f4a28bd30a921Adam Lesinski *out << " " << std::setw(kWidth) << std::left << "-h" << "Displays this help menu\n"; 1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski out->flush(); 1111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskibool Flags::parse(const StringPiece& command, const std::vector<StringPiece>& args, 1141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::ostream* outError) { 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (size_t i = 0; i < args.size(); i++) { 1161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski StringPiece arg = args[i]; 1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (*(arg.data()) != '-') { 1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mArgs.push_back(arg.toString()); 1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski continue; 1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (arg == "-h" || arg == "--help") { 1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski usage(command, outError); 1241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return false; 1251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski bool match = false; 1281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (Flag& flag : mFlags) { 1291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (arg == flag.name) { 1301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (flag.numArgs > 0) { 1311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski i++; 1321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (i >= args.size()) { 1331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *outError << flag.name << " missing argument.\n\n"; 1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski usage(command, outError); 1351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return false; 1361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski flag.action(args[i]); 1381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } else { 1391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski flag.action({}); 1401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski flag.parsed = true; 1421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski match = true; 1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski break; 1441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!match) { 1481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *outError << "unknown option '" << arg << "'.\n\n"; 1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski usage(command, outError); 1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return false; 1511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (const Flag& flag : mFlags) { 1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (flag.required && !flag.parsed) { 1561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *outError << "missing required flag " << flag.name << "\n\n"; 1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski usage(command, outError); 1581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return false; 1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return true; 1621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiconst std::vector<std::string>& Flags::getArgs() { 1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return mArgs; 1661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace aapt 169