add --parser-option v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 29 Nov 2020 00:30:36 +0100
branchv_0
changeset 30 f686bdaeb9e0
parent 29 06aaad12c207
child 31 c6527b45fbc2
add --parser-option
bash-completion.sh
src/CLIParser.h
src/Configuration.h
src/XMLDocumentConstructor.h
src/XMLTableCommand.h
--- 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"
--- 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";
--- 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<RelationConfiguration> relationConfigurations;
 	std::vector<relpipe::writer::string_t> namespaceMappings;
+	std::vector<ParserOptionRecipe> parserOptions;
 	bool xinclude = false;
 
 	virtual ~Configuration() {
@@ -94,4 +104,4 @@
 
 }
 }
-}
\ No newline at end of file
+}
--- 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<INIReader> reader;
 public:
 
 	XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) {
+		reader.reset(INIReader::create(*input));
+		reader->addUnescapingProcessor(std::make_shared<BasicUnescapingProcessor>(), unescaping::Basic, true);
+		reader->addUnescapingProcessor(std::make_shared<JavaPropertiesUnescapingProcessor>(), unescaping::JavaProperties, false);
+		reader->addUnescapingProcessor(std::make_shared<BackspaceUnescapingProcessor>(), unescaping::Backspace, true);
+		reader->addDialect(std::make_shared<JavaPropertiesDialect>(), 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<INIReader> reader(INIReader::create(*input));
-		reader->addUnescapingProcessor(std::make_shared<BasicUnescapingProcessor>(), unescaping::Basic, true);
-		reader->addUnescapingProcessor(std::make_shared<JavaPropertiesUnescapingProcessor>(), unescaping::JavaProperties, false);
-		reader->addUnescapingProcessor(std::make_shared<BackspaceUnescapingProcessor>(), unescaping::Backspace, true);
-		reader->addDialect(std::make_shared<JavaPropertiesDialect>(), 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();
 	}
 };
--- 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();