--- a/bash-completion.sh Sat Dec 12 14:42:36 2020 +0100
+++ b/bash-completion.sh Sat Dec 12 19:52:38 2020 +0100
@@ -61,6 +61,8 @@
"quotes-pattern-for-sections"
"quotes-pattern-for-keys"
"quotes-pattern-for-values"
+ "allow-sections"
+ "hierarchy-separator"
);
@@ -78,6 +80,8 @@
elif [[ "$w2" == "--writer-option" && "$w1" == "quotes-type-for-sections" ]]; then COMPREPLY=($(compgen -W "${QUOTING_TYPES[*]}" -- "$w0"))
elif [[ "$w2" == "--writer-option" && "$w1" == "quotes-type-for-keys" ]]; then COMPREPLY=($(compgen -W "${QUOTING_TYPES[*]}" -- "$w0"))
elif [[ "$w2" == "--writer-option" && "$w1" == "quotes-type-for-values" ]]; then COMPREPLY=($(compgen -W "${QUOTING_TYPES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--writer-option" && "$w1" == "allow-sections" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--writer-option" && "$w1" == "hierarchy-separator" ]]; then COMPREPLY=("'/'")
elif [[ "$w2" == "--writer-option" && "x$w0" == "x" ]]; then COMPREPLY=("''")
else
--- a/src/INIDispatchHandler.h Sat Dec 12 14:42:36 2020 +0100
+++ b/src/INIDispatchHandler.h Sat Dec 12 19:52:38 2020 +0100
@@ -105,6 +105,7 @@
void endOfPipe() {
if (currentHandler) currentHandler->endOfPipe();
currentHandler.reset();
+ writer.endDocument();
output.flush();
}
--- a/src/INIWriter.h Sat Dec 12 14:42:36 2020 +0100
+++ b/src/INIWriter.h Sat Dec 12 19:52:38 2020 +0100
@@ -41,8 +41,26 @@
std::string commentSeparatorForEntries = " ; ";
std::string commentSeparatorStandalone = "; ";
+ relpipe::common::type::StringX hierarchySeparator = L"/";
+ bool allowSections = true;
+
bool hasContent = false;
+ std::vector<relpipe::common::type::StringX> currentSection;
+
+ relpipe::common::type::StringX getCurrentSectionFullName() {
+ std::wstringstream result;
+
+ // TODO: configurable hierarchy delimiter
+ // TODO: escape delimiter characters that are part of the section names
+ for (int i = 0; i < currentSection.size(); i++) {
+ if (i > 0)result << hierarchySeparator;
+ result << currentSection[i];
+ }
+
+ return result.str();
+ }
+
/**
* TODO: use a common method
*/
@@ -176,7 +194,8 @@
else if (uri == option::CommentSeparatorForEntries) commentSeparatorForEntries = convertor.to_bytes(value);
else if (uri == option::CommentSeparatorStandalone) commentSeparatorStandalone = convertor.to_bytes(value);
else if (uri == option::KeyValueSeparator) keyValueSeparator = convertor.to_bytes(value);
- else if (uri == option::AllowSections); // TODO: allow sections
+ else if (uri == option::HierarchySeparator) hierarchySeparator = value;
+ else if (uri == option::AllowSections) allowSections = parseBoolean(value);
else if (uri == option::QuotesTypeForSections) quotingForSections.type = parseQuotingType(value);
else if (uri == option::QuotesTypeForKeys) quotingForKeys.type = parseQuotingType(value);
else if (uri == option::QuotesTypeForValues) quotingForValues.type = parseQuotingType(value);
@@ -200,23 +219,32 @@
}
void endDocument() {
+ if (currentSection.size()) throw relpipe::reader::RelpipeReaderException(L"There are still " + std::to_wstring(currentSection.size()) + L" open sections during the endDocument() call. Need to call endSection() before.");
output.flush();
}
void startSection(const SectionStartEvent& event) {
- if (hasContent) output << std::endl;
- output << "[" << escape(event.name, EscapingProcessor::TextType::SectionName) << "]";
- if (event.tag.size()) output << "[" << escape(event.tag, EscapingProcessor::TextType::SectionTag) << "]";
- if (event.comment.size()) output << commentSeparatorForSections << escape(event.comment, EscapingProcessor::TextType::SectionComment);
- output << std::endl;
+ currentSection.push_back(event.name);
+
+ if (allowSections) {
+ if (hasContent) output << std::endl;
+ output << "[" << escape(getCurrentSectionFullName(), EscapingProcessor::TextType::SectionName) << "]";
+ if (event.tag.size()) output << "[" << escape(event.tag, EscapingProcessor::TextType::SectionTag) << "]";
+ if (event.comment.size()) output << commentSeparatorForSections << escape(event.comment, EscapingProcessor::TextType::SectionComment);
+ output << std::endl;
+ }
+
hasContent = true;
}
void endSection() {
+ currentSection.pop_back();
output.flush();
}
void entry(const EntryEvent& event) {
+ // TODO: escape/quote parts separately + configurable quoting of parts or whole + the same for sub keys
+ if (!allowSections && currentSection.size()) output << escape(getCurrentSectionFullName(), EscapingProcessor::TextType::EntryKey) << convertor.to_bytes(hierarchySeparator);
output << escape(event.key, EscapingProcessor::TextType::EntryKey);
if (event.subKey.size()) output << "[" << escape(event.subKey, EscapingProcessor::TextType::EntrySubKey) << "]";
output << keyValueSeparator << escape(event.value, EscapingProcessor::TextType::EntryValue);
--- a/src/JavaManifestMFDialect.h Sat Dec 12 14:42:36 2020 +0100
+++ b/src/JavaManifestMFDialect.h Sat Dec 12 19:52:38 2020 +0100
@@ -31,6 +31,7 @@
void apply(INIWriter& writer) override {
writer.setOption(option::Dialect, dialect::JavaProperties);
writer.setOption(option::KeyValueSeparator, L": ");
+ writer.setOption(option::HierarchySeparator, L"-");
}
};
--- a/src/JavaPropertiesDialect.h Sat Dec 12 14:42:36 2020 +0100
+++ b/src/JavaPropertiesDialect.h Sat Dec 12 19:52:38 2020 +0100
@@ -30,6 +30,7 @@
void apply(INIWriter& writer) override {
writer.setOption(option::AllowSections, L"false");
+ writer.setOption(option::HierarchySeparator, L".");
writer.setOption(option::QuotesTypeForSections, quoting::None);
writer.setOption(option::QuotesTypeForKeys, quoting::None);
writer.setOption(option::QuotesTypeForValues, quoting::None);
@@ -37,7 +38,7 @@
writer.setOption(option::CommentSeparatorForSections, L"");
writer.setOption(option::CommentSeparatorForEntries, L"");
writer.setOption(option::CommentSeparatorStandalone, L"# ");
- // writer.setOption(escaping::Basic, L"false"); // TODO: basic vs. .properties
+ writer.setOption(escaping::Basic, L"false");
writer.setOption(escaping::JavaProperties, L"true");
}
--- a/src/uri.h Sat Dec 12 14:42:36 2020 +0100
+++ b/src/uri.h Sat Dec 12 19:52:38 2020 +0100
@@ -24,7 +24,9 @@
/** general options of the INI writer */
namespace option {
+// TODO: „allow sections“ vs. „enable sections“, see also relpipe-in-ini
static const wchar_t* AllowSections = L"allow-sections";
+static const wchar_t* HierarchySeparator = L"hierarchy-separator";
// static const wchar_t* AllowSectionTags = L"allow-section-tags";
// static const wchar_t* AllowSubKeys = L"allow-sub-keys";
static const wchar_t* CommentSeparatorForSections = L"comment-separator-for-sections";