summaryrefslogtreecommitdiffstats
path: root/source/core/slang-command-options.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2023-05-02 11:10:58 -0400
committerGitHub <noreply@github.com>2023-05-02 11:10:58 -0400
commit29cb65585782f71a9c6fa1062eaa0b8de8359604 (patch)
treecdd820f2c4a8b26933ba4f5057f92e84b8dc01eb /source/core/slang-command-options.cpp
parent19c0866b050a022406867aa650302f4efbf8e010 (diff)
Markdown CommandOptions (#2860)
* WIP CommandOptions * Fix some output issues. * Simplify word wrapping. * Add file extensions. * Change how lookup takes place. Add appendSplit functions to StringUtil. Make Categories hold the index range of their options. * Small improvement. * Lookup with partial option names. * Associate user values. * Encoding flags in the name. * Refactor setting up of command options. * Use CommandOptions in slang-options. * Remove old help text. * Cache the CommandOptions on the Session. * Range checking. Fix bug in the Options handling. * Extra checks for validity. * Get categories directly. * Slight improvements over output. * Added NameValue types. * Fix typo. Remove some now unused diagnostics. Fix diagnostic in testing, as output has changed. * Add minimal usage message. * Remove platform executable extension from diagnostics output. * Some improvements around getting names from NameValue types. * Improve some option descriptions. * Small fixes. * WIP improvements around CommandOptions. * Split out CommandOptionsWriter. * Add links to options. * Add command line options reference. * Link to the reference command line information. * Add quick links. * Improvements around lookup. Add categories to linking. * Small additional fixes. * Add LinkFlags control. * Small text fixes. * Fix typo. * Fix typo. * Fix typo. * Add support for -g and -O using CommandOptions. * Improve generated doc output/descriptions. Remove options listed directly in documentation.
Diffstat (limited to 'source/core/slang-command-options.cpp')
-rw-r--r--source/core/slang-command-options.cpp394
1 files changed, 121 insertions, 273 deletions
diff --git a/source/core/slang-command-options.cpp b/source/core/slang-command-options.cpp
index 4577bcb8e..5bbe59a0d 100644
--- a/source/core/slang-command-options.cpp
+++ b/source/core/slang-command-options.cpp
@@ -7,7 +7,37 @@
#include "slang-byte-encode-util.h"
namespace Slang {
-
+
+UnownedStringSlice CommandOptions::getFirstNameForOption(Index optionIndex)
+{
+ const auto& opt = m_options[optionIndex];
+ return StringUtil::getAtInSplit(opt.names, ',', 0);
+}
+
+UnownedStringSlice CommandOptions::getFirstNameForCategory(Index categoryIndex)
+{
+ const auto& cat = m_categories[categoryIndex];
+ return cat.name;
+}
+
+CommandOptions::NameKey CommandOptions::getNameKeyForOption(Index optionIndex)
+{
+ const auto& opt = m_options[optionIndex];
+ const auto& cat = m_categories[opt.categoryIndex];
+ NameKey key;
+ key.nameIndex = m_pool.findIndex(getFirstNameForOption(optionIndex));
+ key.kind = (cat.kind == CategoryKind::Option) ? LookupKind::Option : makeLookupKind(opt.categoryIndex);
+ return key;
+}
+
+CommandOptions::NameKey CommandOptions::getNameKeyForCategory(Index categoryIndex)
+{
+ NameKey key;
+ key.nameIndex = m_pool.findIndex(getFirstNameForCategory(categoryIndex));
+ key.kind = LookupKind::Category;
+ return key;
+}
+
SlangResult CommandOptions::_addName(LookupKind kind, const UnownedStringSlice& name, Index targetIndex)
{
NameKey nameKey;
@@ -80,7 +110,16 @@ UnownedStringSlice CommandOptions::_addString(const UnownedStringSlice& slice)
Index CommandOptions::_addOption(const UnownedStringSlice& name, const Option& inOption)
{
- return _addOption(&name, 1, inOption);
+ if (name.indexOf(',') < 0)
+ {
+ return _addOption(&name, 1, inOption);
+ }
+ else
+ {
+ List<UnownedStringSlice> names;
+ StringUtil::split(name, ',', names);
+ return _addOption(names.getBuffer(), names.getCount(), inOption);
+ }
}
Index CommandOptions::_addOption(const UnownedStringSlice* names, Count namesCount, const Option& inOption)
@@ -386,7 +425,52 @@ void CommandOptions::setCategory(const char* name)
m_currentCategoryIndex = -1;
}
-Index CommandOptions::findTargetIndexByName(LookupKind kind, const UnownedStringSlice& name) const
+Index CommandOptions::findTargetIndexByName(LookupKind kind, const UnownedStringSlice& name, NameKey* outNameKey) const
+{
+ // Look up directly
+ {
+ auto index = _findTargetIndexByName(kind, name, outNameKey);
+ if (index >= 0)
+ {
+ return index;
+ }
+ }
+
+ // Special case options, which can have prefix styles
+ if (kind == LookupKind::Option)
+ {
+ auto prefixSizes = m_prefixSizes;
+
+ while (prefixSizes)
+ {
+ auto prefixSize = ByteEncodeUtil::calcMsb32(prefixSizes);
+
+ if (prefixSize < name.getLength())
+ {
+ // Look it up
+ const auto index = _findTargetIndexByName(kind, name.head(prefixSize), outNameKey);
+ if (index >= 0)
+ {
+ auto& option = m_options[index];
+
+ // If the option accepts prefixes, we return the index
+ if (option.flags & (Flag::CanPrefix | Flag::IsPrefix))
+ {
+ return index;
+ }
+ }
+ }
+
+ // Remove the bit
+ prefixSizes &= ~(uint32_t(1) << prefixSize);
+ }
+ }
+
+ // Was not found
+ return -1;
+}
+
+Index CommandOptions::_findTargetIndexByName(LookupKind kind, const UnownedStringSlice& name, NameKey* outNameKey) const
{
const auto nameIndex = m_pool.findIndex(name);
// If the name isn't in the pool then there isn't a category with this name
@@ -401,6 +485,10 @@ Index CommandOptions::findTargetIndexByName(LookupKind kind, const UnownedString
if (auto ptr = m_nameMap.tryGetValue(key))
{
+ if (outNameKey)
+ {
+ *outNameKey = key;
+ }
return *ptr;
}
@@ -447,66 +535,31 @@ Index CommandOptions::findOptionByCategoryUserValue(UserValue categoryUserValue,
return findValueByName(categoryIndex, name);
}
-Index CommandOptions::findOptionByName(const UnownedStringSlice& name) const
-{
- {
- auto index = findTargetIndexByName(LookupKind::Option, name);
- if (index >= 0)
- {
- return index;
- }
- }
-
- // We need to search for partials
- auto prefixSizes = m_prefixSizes;
-
- while (prefixSizes)
- {
- auto prefixSize = ByteEncodeUtil::calcMsb32(prefixSizes);
-
- if (prefixSize < name.getLength())
- {
- // Look it up
- const auto index = findTargetIndexByName(LookupKind::Option, name.head(prefixSize));
- if (index >= 0)
- {
- auto& option = m_options[index];
-
- // If the option accepts prefixes, we return the index
- if (option.flags & (Flag::CanPrefix | Flag::IsPrefix))
- {
- return index;
- }
- }
- }
-
- // Remove the bit
- prefixSizes &= ~(uint32_t(1) << prefixSize);
- }
-
- // Was not found
- return -1;
-}
-
ConstArrayView<CommandOptions::Option> CommandOptions::getOptionsForCategory(Index categoryIndex) const
{
const auto& cat = m_categories[categoryIndex];
return makeConstArrayView(m_options.getBuffer() + cat.optionStartIndex, cat.optionEndIndex - cat.optionStartIndex);
}
-void CommandOptions::getCategoryOptionNames(Index categoryIndex, List<UnownedStringSlice>& outNames) const
+
+void CommandOptions::appendCategoryOptionNames(Index categoryIndex, List<UnownedStringSlice>& outNames) const
{
- outNames.clear();
for (const auto& option : getOptionsForCategory(categoryIndex))
{
StringUtil::appendSplit(option.names, ',', outNames);
}
}
-void CommandOptions::findCategoryIndicesFromUsage(const UnownedStringSlice& slice, List<Index>& outCategories) const
+void CommandOptions::getCategoryOptionNames(Index categoryIndex, List<UnownedStringSlice>& outNames) const
+{
+ outNames.clear();
+ appendCategoryOptionNames(categoryIndex, outNames);
+}
+
+void CommandOptions::splitUsage(const UnownedStringSlice& usageSlice, List<UnownedStringSlice>& outSlices) const
{
- const auto* cur = slice.begin();
- const auto* end = slice.end();
+ const auto* cur = usageSlice.begin();
+ const auto* end = usageSlice.end();
while (cur < end)
{
@@ -522,16 +575,16 @@ void CommandOptions::findCategoryIndicesFromUsage(const UnownedStringSlice& slic
{
cur++;
}
-
+
// If we hit closing > we want to lookup
if (cur < end && *cur == '>')
{
const UnownedStringSlice categoryName(start, cur);
Index categoryIndex = findCategoryByName(categoryName);
- if (categoryIndex >= 0 && outCategories.indexOf(categoryIndex) < 0)
+ if (categoryIndex >= 0)
{
- outCategories.add(categoryIndex);
+ outSlices.add(categoryName);
}
}
@@ -540,6 +593,22 @@ void CommandOptions::findCategoryIndicesFromUsage(const UnownedStringSlice& slic
}
}
+
+void CommandOptions::findCategoryIndicesFromUsage(const UnownedStringSlice& slice, List<Index>& outCategories) const
+{
+ List<UnownedStringSlice> categoryNames;
+ splitUsage(slice, categoryNames);
+
+ for (auto name : categoryNames)
+ {
+ Index categoryIndex = findCategoryByName(name);
+ if (categoryIndex >= 0 && outCategories.indexOf(categoryIndex) < 0)
+ {
+ outCategories.add(categoryIndex);
+ }
+ }
+}
+
Count CommandOptions::getOptionCountInRange(Index categoryIndex, UserValue start, UserValue nonInclEnd) const
{
const UserIndex startIndex = UserIndex(start);
@@ -616,227 +685,6 @@ bool CommandOptions::hasContiguousUserValueRange(LookupKind kind, UserValue star
return rangeCount == count;
}
-/* !!!!!!!!!!!!!!!!!!!!!!!!!!! CommandOptionsWriter !!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-void CommandOptionsWriter::appendDescriptionForCategory(const CommandOptions& options, Index categoryIndex)
-{
- const auto& categories = options.getCategories();
-
- const auto& category = categories[categoryIndex];
-
- // Header
- {
- const auto count = m_builder.getLength();
- if (category.kind == CategoryKind::Value)
- {
- m_builder << "<" << category.name << ">";
- }
- else
- {
- m_builder << category.name;
- }
-
- const auto length = m_builder.getLength() - count;
- m_builder << "\n";
-
- m_builder.appendRepeatedChar('=', length);
-
- m_builder << "\n\n";
-
- // If there is a description output it
- if (category.description.getLength() > 0)
- {
- _appendText(0, category.description);
- m_builder << "\n";
- }
- }
-
- for (auto& option : options.getOptionsForCategory(categoryIndex))
- {
- m_builder << m_indentSlice;
-
- if (option.usage.getLength())
- {
- m_builder << option.usage;
- }
- else
- {
- List<UnownedStringSlice> names;
- StringUtil::split(option.names, ',', names);
-
- _appendWithWrap(1, names, toSlice(", "));
- }
-
- if (option.description.getLength() == 0)
- {
- m_builder << "\n";
- continue;
- }
-
- m_builder << ": ";
-
- _appendText(2, option.description);
-
- if (option.usage.getLength())
- {
- List<Index> usageCategoryIndices;
- options.findCategoryIndicesFromUsage(option.usage, usageCategoryIndices);
-
- for (auto usageCategoryIndex : usageCategoryIndices)
- {
- auto& usageCat = categories[usageCategoryIndex];
-
- m_builder << m_indentSlice << m_indentSlice;
- m_builder << "<" << usageCat.name << "> can be: ";
-
- List<UnownedStringSlice> optionNames;
- options.getCategoryOptionNames(usageCategoryIndex, optionNames);
-
- _appendWithWrap(2, optionNames, toSlice(", "));
-
- m_builder << "\n";
- }
- }
- }
-
- m_builder << "\n";
-}
-
-void CommandOptionsWriter::appendDescription(const CommandOptions& options)
-{
- // Go through categories in order
-
- const auto& categories = options.getCategories();
-
- for (Index categoryIndex = 0; categoryIndex < categories.getCount(); ++categoryIndex)
- {
- appendDescriptionForCategory(options, categoryIndex);
- }
-}
-
-void CommandOptionsWriter::_appendText(Count indentCount, const UnownedStringSlice& text)
-{
- List<UnownedStringSlice> lines;
- StringUtil::calcLines(text, lines);
-
- // Remove very last line if it's empty
- if (lines.getCount() > 1 && lines.getLast().trim().getLength() == 0)
- {
- lines.removeLast();
- }
-
- _appendWithWrap(indentCount, lines);
-}
-
-Count CommandOptionsWriter::_getCurrentLineLength()
-{
- // Work out the current line length
- const char* start = m_builder.begin();
- const char* cur = m_builder.end();
-
- Count lineLength = 0;
-
- if (cur > start)
- {
- for (--cur; cur > start; --cur)
- {
- const auto c = *cur;
- if (c == '\n' || c == '\r')
- {
- ++cur;
- break;
- }
- }
-
- lineLength = Count(ptrdiff_t(m_builder.end() - cur));
- }
-
- return lineLength;
-}
-
-void CommandOptionsWriter::_requireIndent(Count indentCount)
-{
- const auto length = m_builder.getLength();
- if (length)
- {
- const auto c = m_builder[length - 1];
- if (c == '\n' || c == '\r')
- {
- for (Index j = 0; j < indentCount; j++)
- {
- m_builder.append(m_indentSlice);
- }
- }
- }
-}
-
-void CommandOptionsWriter::_appendWithWrap(Count indentCount, List<UnownedStringSlice>& lines)
-{
- List<UnownedStringSlice> words;
-
- for (auto line : lines)
- {
- if (line.trim().getLength() == 0 || line.startsWith(toSlice(" ")))
- {
- // Append the line as is after the indent
- _requireIndent(indentCount);
- m_builder << line << "\n";
- }
- else
- {
- words.clear();
- StringUtil::split(line, ' ', words);
-
- _requireIndent(indentCount);
-
- _appendWithWrap(indentCount, words, toSlice(" "));
- m_builder << "\n";
- }
- }
-}
-
-
-
-void CommandOptionsWriter::_appendWithWrap(Count indentCount, List<UnownedStringSlice>& slices, const UnownedStringSlice& delimit)
-{
- Count lineLength = _getCurrentLineLength();
-
- const auto count = slices.getCount();
-
- for (Index i = 0; i < count; ++i)
- {
- auto slice = slices[i];
-
- auto sliceLength = slice.getLength();
-
- if (i < count - 1)
- {
- sliceLength += delimit.getLength();
- }
-
- // If out of space onto the next line
- if (lineLength + sliceLength > m_lineLength)
- {
- m_builder.append("\n");
-
- lineLength = indentCount * m_indentSlice.getLength();
-
- for (Index j = 0; j < indentCount; j++)
- {
- m_builder.append(m_indentSlice);
- }
- }
-
- m_builder.append(slice);
- if (i < count - 1)
- {
- m_builder.append(delimit);
- }
-
- lineLength += sliceLength;
- }
-}
-
} // namespace Slang