# HG changeset patch # User František Kučera # Date 1606606236 -3600 # Node ID f686bdaeb9e0562283cb465a9d7c23ce14342324 # Parent 06aaad12c207a37968c07f79c7a43872f2f7ac59 add --parser-option diff -r 06aaad12c207 -r f686bdaeb9e0 bash-completion.sh --- a/bash-completion.sh Sat Nov 28 21:09:18 2020 +0100 +++ b/bash-completion.sh Sun Nov 29 00:30:36 2020 +0100 @@ -28,7 +28,7 @@ "boolean" ) - XINCLUDE=( + BOOLEAN_VALUES=( "true" "false" ) @@ -59,6 +59,26 @@ "http://docbook.org/ns/docbook" ) + # TODO: introspection: after moving to alt2xml the available options and their values should be provided by the parser + + PARSER_OPTIONS=( + "trim-continuing-lines" + "allow-sections" + "allow-section-tags" + "allow-sub-keys" + "comment-separators" + "key-value-separators" + "quotes" + "dialect" + "unescape-basic" + "unescape-java-properties" + "unescape-backspace" + ); + + DIALECTS=( + "java-properties" + ); + if [[ "$w1" == "--relation" && "x$w0" == "x" ]]; then COMPREPLY=("''") elif [[ "$w1" == "--records" && "x$w0" == "x" ]]; then COMPREPLY=("'/'") @@ -67,7 +87,7 @@ elif [[ "$w3" == "--attribute" && "x$w0" == "x" ]]; then COMPREPLY=("''") elif [[ "$w1" == "--namespace" && "x$w0" == "x" ]]; then COMPREPLY=("''") elif [[ "$w2" == "--namespace" ]]; then COMPREPLY=($(compgen -W "${XMLNS[*]}" -- "$w0")) - elif [[ "$w1" == "--xinclude" ]]; then COMPREPLY=($(compgen -W "${XINCLUDE[*]}" -- "$w0")) + elif [[ "$w1" == "--xinclude" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) elif [[ "$w1" == "--mode" ]]; then COMPREPLY=($(compgen -W "${MODE[*]}" -- "$w0")) elif [[ "$w1" == "--raw-xml-nodelist-wrapper" ]]; then COMPREPLY=("'xml'") elif [[ "$w2" == "--raw-xml-nodelist-wrapper" && "x$w0" == "x" ]]; then COMPREPLY=("''") @@ -76,9 +96,24 @@ elif [[ "$w1" == "--raw-xml-attribute-wrapper" ]]; then COMPREPLY=("'attribute'") elif [[ "$w2" == "--raw-xml-attribute-wrapper" && "x$w0" == "x" ]]; then COMPREPLY=("''") elif [[ "$w3" == "--raw-xml-attribute-wrapper" && "x$w0" == "x" ]]; then COMPREPLY=("''") + + elif [[ "$w1" == "--parser-option" ]]; then COMPREPLY=($(compgen -W "${PARSER_OPTIONS[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "trim-continuing-lines" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "allow-sections" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "allow-section-tags" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "allow-sub-keys" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "unescape-basic" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "unescape-java-properties" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "unescape-backspace" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "dialect" ]]; then COMPREPLY=($(compgen -W "${DIALECTS[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "comment-separators" && "x$w0" == "x" ]]; then COMPREPLY=("'#;'") + elif [[ "$w2" == "--parser-option" && "$w1" == "key-value-separators" && "x$w0" == "x" ]]; then COMPREPLY=("'=:'") + elif [[ "$w2" == "--parser-option" && "$w1" == "quotes" && "x$w0" == "x" ]]; then COMPREPLY=("\$'\"\\''") + else OPTIONS=( "--namespace" + "--parser-option" "--relation" "--records" "--name-is-xpath" diff -r 06aaad12c207 -r f686bdaeb9e0 src/CLIParser.h --- a/src/CLIParser.h Sat Nov 28 21:09:18 2020 +0100 +++ b/src/CLIParser.h Sun Nov 29 00:30:36 2020 +0100 @@ -63,6 +63,7 @@ public: static const string_t OPTION_NAMESPACE; + static const string_t OPTION_PARSER_OPTION; static const string_t OPTION_RELATION; static const string_t OPTION_NAME_IS_XPATH; static const string_t OPTION_RECORDS; @@ -82,6 +83,8 @@ if (option == OPTION_NAMESPACE) { c.namespaceMappings.push_back(readNext(arguments, i)); c.namespaceMappings.push_back(readNext(arguments, i)); + } else if (option == OPTION_PARSER_OPTION) { + c.parserOptions.push_back({readNext(arguments, i), readNext(arguments, i)}); } else if (option == OPTION_XINCLUDE) { c.xinclude = parseBoolean(readNext(arguments, i)); } else if (option == OPTION_RELATION) { @@ -131,6 +134,7 @@ }; const string_t CLIParser::OPTION_NAMESPACE = L"--namespace"; +const string_t CLIParser::OPTION_PARSER_OPTION = L"--parser-option"; const string_t CLIParser::OPTION_RELATION = L"--relation"; const string_t CLIParser::OPTION_NAME_IS_XPATH = L"--name-is-xpath"; const string_t CLIParser::OPTION_RECORDS = L"--records"; diff -r 06aaad12c207 -r f686bdaeb9e0 src/Configuration.h --- a/src/Configuration.h Sat Nov 28 21:09:18 2020 +0100 +++ b/src/Configuration.h Sun Nov 29 00:30:36 2020 +0100 @@ -65,6 +65,15 @@ }; +class ParserOptionRecipe { +public: + relpipe::writer::string_t uri; + relpipe::writer::string_t value; + + ParserOptionRecipe(relpipe::writer::string_t uri, relpipe::writer::string_t value) : uri(uri), value(value) { + } +}; + class RelationConfiguration { public: @@ -86,6 +95,7 @@ public: std::vector relationConfigurations; std::vector namespaceMappings; + std::vector parserOptions; bool xinclude = false; virtual ~Configuration() { @@ -94,4 +104,4 @@ } } -} \ No newline at end of file +} diff -r 06aaad12c207 -r f686bdaeb9e0 src/XMLDocumentConstructor.h --- a/src/XMLDocumentConstructor.h Sat Nov 28 21:09:18 2020 +0100 +++ b/src/XMLDocumentConstructor.h Sun Nov 29 00:30:36 2020 +0100 @@ -106,22 +106,24 @@ private: std::istream* input = nullptr; xmlpp::DomParser* parser = nullptr; + std::shared_ptr reader; public: XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) { + reader.reset(INIReader::create(*input)); + reader->addUnescapingProcessor(std::make_shared(), unescaping::Basic, true); + reader->addUnescapingProcessor(std::make_shared(), unescaping::JavaProperties, false); + reader->addUnescapingProcessor(std::make_shared(), unescaping::Backspace, true); + reader->addDialect(std::make_shared(), dialect::JavaProperties, false); + } + + void setOption(const std::string& uri, const std::string& value) { + reader->setOption(uri, value); } void process() { HierarchicalINIContentHandler handler(parser); - std::shared_ptr reader(INIReader::create(*input)); - reader->addUnescapingProcessor(std::make_shared(), unescaping::Basic, true); - reader->addUnescapingProcessor(std::make_shared(), unescaping::JavaProperties, false); - reader->addUnescapingProcessor(std::make_shared(), unescaping::Backspace, true); - reader->addDialect(std::make_shared(), dialect::JavaProperties, false); reader->addHandler(&handler); - // TODO: smart pointers vs. references: are we going to call addUnescapingProcessor() dynamically/conditionally or share instances? Then pointers will be better. - // TODO: call setOption() according to the configuration - // for (ParserOptionRecipe option : configuration.parserOptions) reader->setOption(convertor.to_bytes(option.uri), convertor.to_bytes(option.value)); reader->process(); } }; diff -r 06aaad12c207 -r f686bdaeb9e0 src/XMLTableCommand.h --- a/src/XMLTableCommand.h Sat Nov 28 21:09:18 2020 +0100 +++ b/src/XMLTableCommand.h Sun Nov 29 00:30:36 2020 +0100 @@ -88,6 +88,7 @@ xmlpp::DomParser parser; XMLDocumentConstructor documentConstructor(&input, &parser); + for (ParserOptionRecipe o : configuration.parserOptions) documentConstructor.setOption(convertor.to_bytes(o.uri), convertor.to_bytes(o.value)); documentConstructor.process(); if (configuration.xinclude) parser.get_document()->process_xinclude(true); xmlpp::Element* root = parser.get_document()->get_root_node();