# HG changeset patch # User František Kučera # Date 1607799158 -3600 # Node ID bee7acb573300c2c2b068ea109ed95351e63e69a # Parent 372b161669e4a97b9d25ca47d2e85c60d8f75ee9 implement --writer-option allow-sections false (flat key=value output) diff -r 372b161669e4 -r bee7acb57330 bash-completion.sh --- 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 diff -r 372b161669e4 -r bee7acb57330 src/INIDispatchHandler.h --- 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(); } diff -r 372b161669e4 -r bee7acb57330 src/INIWriter.h --- 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 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); diff -r 372b161669e4 -r bee7acb57330 src/JavaManifestMFDialect.h --- 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"-"); } }; diff -r 372b161669e4 -r bee7acb57330 src/JavaPropertiesDialect.h --- 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"); } diff -r 372b161669e4 -r bee7acb57330 src/uri.h --- 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";