Implement UsageInformation Utility

This commit is contained in:
Jan 2019-09-26 21:43:25 +02:00
parent 75bd49d501
commit c76352077a
3 changed files with 201 additions and 0 deletions

View File

@ -21,6 +21,7 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="Utils\Arguments\ArgumentParser.h" /> <ClInclude Include="Utils\Arguments\ArgumentParser.h" />
<ClInclude Include="Utils\Arguments\CommandLineOption.h" /> <ClInclude Include="Utils\Arguments\CommandLineOption.h" />
<ClInclude Include="Utils\Arguments\UsageInformation.h" />
<ClInclude Include="Utils\ClassUtils.h" /> <ClInclude Include="Utils\ClassUtils.h" />
<ClInclude Include="Utils\FileAPI.h" /> <ClInclude Include="Utils\FileAPI.h" />
<ClInclude Include="Utils\PathUtils.h" /> <ClInclude Include="Utils\PathUtils.h" />
@ -28,6 +29,7 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="Utils\Arguments\ArgumentParser.cpp" /> <ClCompile Include="Utils\Arguments\ArgumentParser.cpp" />
<ClCompile Include="Utils\Arguments\CommandLineOption.cpp" /> <ClCompile Include="Utils\Arguments\CommandLineOption.cpp" />
<ClCompile Include="Utils\Arguments\UsageInformation.cpp" />
<ClCompile Include="Utils\FileAPI.cpp" /> <ClCompile Include="Utils\FileAPI.cpp" />
<ClCompile Include="Utils\PathUtils.cpp" /> <ClCompile Include="Utils\PathUtils.cpp" />
</ItemGroup> </ItemGroup>

View File

@ -0,0 +1,162 @@
#include "UsageInformation.h"
#include <iostream>
#include <map>
#include <iomanip>
UsageInformation::ArgumentUsage::ArgumentUsage(std::string name, const bool optional)
{
m_name = std::move(name);
m_optional = optional;
}
UsageInformation::UsageInformation(std::string applicationName)
{
m_application_name = std::move(applicationName);
m_var_args = false;
}
void UsageInformation::AddCommandLineOption(const CommandLineOption* option)
{
m_command_line_options.push_back(option);
}
void UsageInformation::AddArgument(std::string argumentName)
{
m_arguments.emplace_back(std::move(argumentName), false);
}
void UsageInformation::AddOptionalArgument(std::string argumentName)
{
m_arguments.emplace_back(std::move(argumentName), true);
}
void UsageInformation::SetVariableArguments(const bool enabled)
{
m_var_args = enabled;
}
void UsageInformation::Print()
{
std::stringstream str;
std::map<std::string, std::vector<const CommandLineOption*>> categories;
str << "Usage:" << std::endl;
PrintUsageOverview(str);
str << "The following options are available:" << std::endl;
str.fill(' ');
for (auto commandLineOption : m_command_line_options)
{
if(categories.find(commandLineOption->m_category) == categories.end())
categories[commandLineOption->m_category] = std::vector<const CommandLineOption*>();
categories[commandLineOption->m_category].push_back(commandLineOption);
}
size_t longestShortName = 0;
size_t longestLongName = 0;
size_t longestArgumentLength = 0;
for (auto option : m_command_line_options)
{
if(option->m_short_name.length() > longestShortName)
longestShortName = option->m_short_name.length();
if(option->m_long_name.length() > longestLongName)
longestLongName = option->m_long_name.length();
const size_t argumentLength = GetOptionArgumentLength(option);
if(argumentLength > longestArgumentLength)
longestArgumentLength = argumentLength;
}
bool firstCategory = true;
for (auto& category : categories)
{
if(!firstCategory)
str << std::endl;
else
firstCategory = false;
if(!category.first.empty())
{
str << "== " << category.first << " ==" << std::endl;
}
for (auto option : category.second)
{
str << std::setw(longestShortName + 1) << "-" + option->m_short_name;
if(!option->m_short_name.empty() && !option->m_long_name.empty())
str << ", ";
else
str << " ";
str << std::setw(longestLongName + 2) << "--" + option->m_long_name;
str << " ";
str << std::setw(longestArgumentLength) << GetOptionArgument(option);
str << " " << option->m_description << std::endl;
}
}
std::cout << str.str() << std::endl;
}
void UsageInformation::PrintUsageOverview(std::stringstream& str)
{
str << m_application_name << " [options]";
for (ArgumentUsage& argument : m_arguments)
{
if(argument.m_optional)
{
str << " [" << argument.m_name << "]";
}
else
{
str << " <" << argument.m_name << ">";
}
}
if(m_var_args)
{
str << "...";
}
str << std::endl << std::endl;
}
std::string UsageInformation::GetOptionArgument(const CommandLineOption* option)
{
std::stringstream str;
bool firstParam = true;
for (const std::string& param : option->m_parameters)
{
if(!firstParam)
str << " ";
else
firstParam = false;
str << "<" << param << ">";
}
return str.str();
}
size_t UsageInformation::GetOptionArgumentLength(const CommandLineOption* option)
{
const size_t parameterCount = option->m_parameters.size();
size_t parameterCombinedStringLength = 0;
for (const std::string& param : option->m_parameters)
{
parameterCombinedStringLength += param.length();
}
return parameterCount * 2 // < and >
+ parameterCombinedStringLength
+ (parameterCount > 1 ? parameterCount - 1 : 0); // One space between each argument
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "CommandLineOption.h"
#include <string>
#include <vector>
#include <sstream>
class UsageInformation
{
class ArgumentUsage
{
public:
std::string m_name;
bool m_optional;
ArgumentUsage(std::string name, bool optional);
};
std::string m_application_name;
std::vector<const CommandLineOption*> m_command_line_options;
std::vector<ArgumentUsage> m_arguments;
bool m_var_args;
void PrintUsageOverview(std::stringstream& str);
static std::string GetOptionArgument(const CommandLineOption* option);
static size_t GetOptionArgumentLength(const CommandLineOption* option);
public:
UsageInformation(std::string applicationName);
void AddCommandLineOption(const CommandLineOption* option);
void AddArgument(std::string argumentName);
void AddOptionalArgument(std::string argumentName);
void SetVariableArguments(bool enabled);
void Print();
};