diff --git a/doc/change_log.qbk b/doc/change_log.qbk index c3835c4..74ca7f7 100644 --- a/doc/change_log.qbk +++ b/doc/change_log.qbk @@ -239,6 +239,7 @@ Boost 1.46.1: * Use relative paths for `__FILENAME__` macro. * Rewrite xinclude path generator so that it doesn't use deprecated filesystem functions. +* Allow quickbook escapes inside comments in syntax highlighted code. * Quickbook 1.6: * Scope source mode changes to the file they're made in. * Explicit markup for lists. e.g. diff --git a/src/Jamfile.v2 b/src/Jamfile.v2 index e7ead94..736c19f 100644 --- a/src/Jamfile.v2 +++ b/src/Jamfile.v2 @@ -14,7 +14,6 @@ project quickbook darwin:300 gcc:-g0 darwin:-g0 - all msvc:/wd4709 ; diff --git a/src/actions.cpp b/src/actions.cpp index 849714a..02a651d 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -59,7 +59,7 @@ namespace quickbook { tgt << "\n"; + tgt << "\"/>"; } actions.anchors.clear(); @@ -190,9 +190,8 @@ namespace quickbook if(!actions.warned_about_breaks) { detail::outwarn(actions.filename, pos.line) - << "line breaks generate invalid boostbook" - << " (will only note first occurrence)." - << "\n"; + << "line breaks generate invalid boostbook " + "(will only note first occurrence).\n"; actions.warned_about_breaks = true; } @@ -368,14 +367,7 @@ namespace quickbook values.finish(); out << markup.pre; - if (std::string const* ptr = find(macro, content.get_quickbook().c_str())) - { - out << *ptr; - } - else - { - out << content.get_boostbook(); - } + out << content.get_boostbook(); out << markup.post; } @@ -523,12 +515,26 @@ namespace quickbook } // TODO: No need to check suppress since this is only used in the syntax - // highlighter. I should moved this or something. + // highlighter. I should move this or something. void span::operator()(iterator first, iterator last) const + { + if (name) out << ""; + while (first != last) + detail::print_char(*first++, out.get()); + if (name) out << ""; + } + + void span_start::operator()(iterator first, iterator last) const { out << ""; while (first != last) detail::print_char(*first++, out.get()); + } + + void span_end::operator()(iterator first, iterator last) const + { + while (first != last) + detail::print_char(*first++, out.get()); out << ""; } diff --git a/src/actions.hpp b/src/actions.hpp index dc50fc3..a48975d 100644 --- a/src/actions.hpp +++ b/src/actions.hpp @@ -124,16 +124,13 @@ namespace quickbook simple_phrase_action( collector& out - , string_symbols const& macro , quickbook::actions& actions) : out(out) - , macro(macro) , actions(actions) {} void operator()(char) const; collector& out; - string_symbols const& macro; quickbook::actions& actions; }; @@ -163,6 +160,27 @@ namespace quickbook collector& out; }; + struct span_start + { + span_start(char const* name, collector& out) + : name(name), out(out) {} + + void operator()(iterator first, iterator last) const; + + char const* name; + collector& out; + }; + + struct span_end + { + span_end(collector& out) + : out(out) {} + + void operator()(iterator first, iterator last) const; + + collector& out; + }; + struct unexpected_char { // Handles unexpected chars in c++ syntax diff --git a/src/actions_class.cpp b/src/actions_class.cpp index 0f67201..19f74db 100644 --- a/src/actions_class.cpp +++ b/src/actions_class.cpp @@ -71,7 +71,7 @@ namespace quickbook , raw_char(phrase, *this) , escape_unicode(phrase, *this) - , simple_markup(phrase, macro, *this) + , simple_markup(phrase, *this) , break_(phrase, *this) , do_macro(phrase, *this) diff --git a/src/main_grammar.cpp b/src/main_grammar.cpp index 5918a97..76764d1 100644 --- a/src/main_grammar.cpp +++ b/src/main_grammar.cpp @@ -89,7 +89,7 @@ namespace quickbook top_level, blocks, paragraph_separator, code, code_line, blank_line, hr, list, list_item, - nested_char, escape, + escape, inline_code, template_, code_block, macro, @@ -369,10 +369,10 @@ namespace quickbook ; local.simple_markup = - cl::chset<>("*/_=") [local.simple_markup.mark = ph::arg1] - >> cl::eps_p(cl::graph_p) // graph_p must follow first mark + cl::chset<>("*/_=") [local.simple_markup.mark = ph::arg1] + >> cl::eps_p(cl::graph_p) // graph_p must follow first mark >> lookback - [ cl::anychar_p + [ cl::anychar_p // skip back over the markup >> ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark)) // first mark not be preceeded by // the same character. @@ -385,11 +385,18 @@ namespace quickbook [ actions.scoped_output() [ - (+( ~cl::eps_p(local.simple_markup_end) - >> local.nested_char - )) [actions.docinfo_value(ph::arg1, ph::arg2)] - ] - >> cl::f_ch_p(local.simple_markup.mark) + ( cl::eps_p(actions.macro >> local.simple_markup_end) + >> actions.macro [actions.do_macro] + | ~cl::eps_p(cl::f_ch_p(local.simple_markup.mark)) + >> +( ~cl::eps_p + ( lookback [~cl::f_ch_p(local.simple_markup.mark)] + >> local.simple_markup_end + ) + >> cl::anychar_p [actions.plain_char] + ) + ) [actions.to_value] + ] + >> cl::f_ch_p(local.simple_markup.mark) [actions.simple_markup] ] ; @@ -448,19 +455,6 @@ namespace quickbook ] ; - local.nested_char = - cl::str_p("\\n") [actions.break_] - | "\\ " // ignore an escaped space - | '\\' >> cl::punct_p [actions.raw_char] - | "\\u" >> cl::repeat_p(4) - [cl::chset<>("0-9a-fA-F")] - [actions.escape_unicode] - | "\\U" >> cl::repeat_p(8) - [cl::chset<>("0-9a-fA-F")] - [actions.escape_unicode] - | cl::anychar_p [actions.plain_char] - ; - local.escape = cl::str_p("\\n") [actions.break_] | cl::str_p("\\ ") // ignore an escaped space diff --git a/src/syntax_highlight.cpp b/src/syntax_highlight.cpp index 98fa4bb..bacb23f 100644 --- a/src/syntax_highlight.cpp +++ b/src/syntax_highlight.cpp @@ -7,42 +7,394 @@ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ -#include "syntax_highlight.hpp" +#include +#include +#include +#include +#include +#include "grammar.hpp" +#include "grammar_impl.hpp" // Just for context stuff. Should move? #include "actions_class.hpp" namespace quickbook -{ - typedef cpp_highlight< - span - , space - , string_symbols - , do_macro_action - , pre_escape_back - , post_escape_back - , unexpected_char - , collector> - cpp_p_type; +{ + namespace cl = boost::spirit::classic; + + // Grammar for C++ highlighting + struct cpp_highlight + : public cl::grammar + { + cpp_highlight(collector& out, actions& escape_actions) + : out(out), escape_actions(escape_actions) {} + + template + struct definition + { + definition(cpp_highlight const& self) + : g(self.escape_actions.grammar()) + { + program + = + *( (+cl::space_p) [space(self.out)] + | macro + | escape + | preprocessor [span("preprocessor", self.out)] + | comment + | keyword [span("keyword", self.out)] + | identifier [span("identifier", self.out)] + | special [span("special", self.out)] + | string_ [span("string", self.out)] + | char_ [span("char", self.out)] + | number [span("number", self.out)] + | cl::repeat_p(1)[cl::anychar_p] + [unexpected_char(self.out, self.escape_actions)] + ) + ; + + macro = + // must not be followed by alpha or underscore + cl::eps_p(self.escape_actions.macro + >> (cl::eps_p - (cl::alpha_p | '_'))) + >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)] + ; + + qbk_phrase = + self.escape_actions.scoped_context(element_info::in_phrase) + [ *( g.common + | (cl::anychar_p - cl::str_p("``")) + [self.escape_actions.plain_char] + ) + ] + ; + + escape = + cl::str_p("``") [pre_escape_back(self.escape_actions, save)] + >> + ( + ( + ( + (+(cl::anychar_p - "``") >> cl::eps_p("``")) + & qbk_phrase + ) + >> cl::str_p("``") + ) + | + ( + cl::eps_p [self.escape_actions.error] + >> *cl::anychar_p + ) + ) [post_escape_back(self.out, self.escape_actions, save)] + ; + + preprocessor + = '#' >> *cl::space_p >> ((cl::alpha_p | '_') >> *(cl::alnum_p | '_')) + ; + + comment + = cl::str_p("//") [span_start("comment", self.out)] + >> *( escape + | (+(cl::anychar_p - (cl::eol_p | "``"))) + [span(0, self.out)] + ) + >> cl::eps_p [span_end(self.out)] + | cl::str_p("/*") [span_start("comment", self.out)] + >> *( escape + | (+(cl::anychar_p - (cl::str_p("*/") | "``"))) + [span(0, self.out)] + ) + >> (!cl::str_p("*/")) [span_end(self.out)] + ; + + keyword + = keyword_ >> (cl::eps_p - (cl::alnum_p | '_')) + ; // make sure we recognize whole words only + + keyword_ + = "and_eq", "and", "asm", "auto", "bitand", "bitor", + "bool", "break", "case", "catch", "char", "class", + "compl", "const_cast", "const", "continue", "default", + "delete", "do", "double", "dynamic_cast", "else", + "enum", "explicit", "export", "extern", "false", + "float", "for", "friend", "goto", "if", "inline", + "int", "long", "mutable", "namespace", "new", "not_eq", + "not", "operator", "or_eq", "or", "private", + "protected", "public", "register", "reinterpret_cast", + "return", "short", "signed", "sizeof", "static", + "static_cast", "struct", "switch", "template", "this", + "throw", "true", "try", "typedef", "typeid", + "typename", "union", "unsigned", "using", "virtual", + "void", "volatile", "wchar_t", "while", "xor_eq", "xor" + ; + + special + = +cl::chset_p("~!%^&*()+={[}]:;,<.>?/|\\-") + ; + + string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\'); + + string_ + = !cl::as_lower_d['l'] >> cl::confix_p('"', *string_char, '"') + ; + + char_ + = !cl::as_lower_d['l'] >> cl::confix_p('\'', *string_char, '\'') + ; + + number + = ( + cl::as_lower_d["0x"] >> cl::hex_p + | '0' >> cl::oct_p + | cl::real_p + ) + >> *cl::as_lower_d[cl::chset_p("ldfu")] + ; + + identifier + = (cl::alpha_p | '_') >> *(cl::alnum_p | '_') + ; + } + + cl::rule + program, macro, preprocessor, comment, special, string_, + char_, number, identifier, keyword, qbk_phrase, escape, + string_char; + + cl::symbols<> keyword_; + quickbook_grammar& g; + std::string save; + + cl::rule const& + start() const { return program; } + }; + + collector& out; + actions& escape_actions; + }; + + // Grammar for Python highlighting + // See also: The Python Reference Manual + // http://docs.python.org/ref/ref.html + struct python_highlight + : public cl::grammar + { + python_highlight(collector& out, actions& escape_actions) + : out(out), escape_actions(escape_actions) {} + + template + struct definition + { + definition(python_highlight const& self) + : g(self.escape_actions.grammar()) + { + program + = + *( (+cl::space_p) [space(self.out)] + | macro + | escape + | comment + | keyword [span("keyword", self.out)] + | identifier [span("identifier", self.out)] + | special [span("special", self.out)] + | string_ [span("string", self.out)] + | number [span("number", self.out)] + | cl::repeat_p(1)[cl::anychar_p] + [unexpected_char(self.out, self.escape_actions)] + ) + ; + + macro = + // must not be followed by alpha or underscore + cl::eps_p(self.escape_actions.macro + >> (cl::eps_p - (cl::alpha_p | '_'))) + >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)] + ; + + qbk_phrase = + self.escape_actions.scoped_context(element_info::in_phrase) + [ + *( g.common + | (cl::anychar_p - cl::str_p("``")) + [self.escape_actions.plain_char] + ) + ] + ; + + escape = + cl::str_p("``") [pre_escape_back(self.escape_actions, save)] + >> + ( + ( + ( + (+(cl::anychar_p - "``") >> cl::eps_p("``")) + & qbk_phrase + ) + >> cl::str_p("``") + ) + | + ( + cl::eps_p [self.escape_actions.error] + >> *cl::anychar_p + ) + ) [post_escape_back(self.out, self.escape_actions, save)] + ; + + comment + = cl::str_p("#") [span_start("comment", self.out)] + >> *( escape + | (+(cl::anychar_p - (cl::eol_p | "``"))) + [span(0, self.out)] + ) + >> cl::eps_p [span_end(self.out)] + ; + + keyword + = keyword_ >> (cl::eps_p - (cl::alnum_p | '_')) + ; // make sure we recognize whole words only + + keyword_ + = + "and", "del", "for", "is", "raise", + "assert", "elif", "from", "lambda", "return", + "break", "else", "global", "not", "try", + "class", "except", "if", "or", "while", + "continue", "exec", "import", "pass", "yield", + "def", "finally", "in", "print", + + // Technically "as" and "None" are not yet keywords (at Python + // 2.4). They are destined to become keywords, and we treat them + // as such for syntax highlighting purposes. + + "as", "None" + ; + + special + = +cl::chset_p("~!%^&*()+={[}]:;,<.>/|\\-") + ; + + string_prefix + = cl::as_lower_d[cl::str_p("u") >> ! cl::str_p("r")] + ; + + string_ + = ! string_prefix >> (long_string | short_string) + ; + + string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\'); + + short_string + = cl::confix_p('\'', * string_char, '\'') | + cl::confix_p('"', * string_char, '"') + ; + + long_string + // Note: the "cl::str_p" on the next two lines work around + // an INTERNAL COMPILER ERROR when using VC7.1 + = cl::confix_p(cl::str_p("'''"), * string_char, "'''") | + cl::confix_p(cl::str_p("\"\"\""), * string_char, "\"\"\"") + ; + + number + = ( + cl::as_lower_d["0x"] >> cl::hex_p + | '0' >> cl::oct_p + | cl::real_p + ) + >> *cl::as_lower_d[cl::chset_p("lj")] + ; + + identifier + = (cl::alpha_p | '_') >> *(cl::alnum_p | '_') + ; + } + + cl::rule + program, macro, comment, special, string_, string_prefix, + short_string, long_string, number, identifier, keyword, + qbk_phrase, escape, string_char; + + cl::symbols<> keyword_; + quickbook_grammar& g; + std::string save; + + cl::rule const& + start() const { return program; } + }; + + collector& out; + actions& escape_actions; + }; + + // Grammar for plain text (no actual highlighting) + struct teletype_highlight + : public cl::grammar + { + teletype_highlight(collector& out, actions& escape_actions) + : out(out), escape_actions(escape_actions) {} + + template + struct definition + { + definition(teletype_highlight const& self) + : g(self.escape_actions.grammar()) + { + program + = + *( macro + | escape + | cl::repeat_p(1)[cl::anychar_p] [plain_char_action(self.out, self.escape_actions)] + ) + ; + + macro = + // must not be followed by alpha or underscore + cl::eps_p(self.escape_actions.macro + >> (cl::eps_p - (cl::alpha_p | '_'))) + >> self.escape_actions.macro [do_macro_action(self.out, self.escape_actions)] + ; + + qbk_phrase = + self.escape_actions.scoped_context(element_info::in_phrase) + [ + *( g.common + | (cl::anychar_p - cl::str_p("``")) + [self.escape_actions.plain_char] + ) + ] + ; + + escape = + cl::str_p("``") [pre_escape_back(self.escape_actions, save)] + >> + ( + ( + ( + (+(cl::anychar_p - "``") >> cl::eps_p("``")) + & qbk_phrase + ) + >> cl::str_p("``") + ) + | + ( + cl::eps_p [self.escape_actions.error] + >> *cl::anychar_p + ) + ) [post_escape_back(self.out, self.escape_actions, save)] + ; + } + + cl::rule program, macro, qbk_phrase, escape; + + quickbook_grammar& g; + std::string save; + + cl::rule const& + start() const { return program; } + }; + + collector& out; + actions& escape_actions; + }; - typedef python_highlight< - span - , space - , string_symbols - , do_macro_action - , pre_escape_back - , post_escape_back - , unexpected_char - , collector> - python_p_type; - - typedef teletype_highlight< - plain_char_action - , string_symbols - , do_macro_action - , pre_escape_back - , post_escape_back - , collector> - teletype_p_type; - std::string syntax_highlight( iterator first, iterator last, actions& escape_actions, @@ -53,17 +405,17 @@ namespace quickbook // print the code with syntax coloring if (source_mode == "c++") { - cpp_p_type cpp_p(temp, escape_actions.macro, do_macro_action(temp, escape_actions), escape_actions); + cpp_highlight cpp_p(temp, escape_actions); boost::spirit::classic::parse(first, last, cpp_p); } else if (source_mode == "python") { - python_p_type python_p(temp, escape_actions.macro, do_macro_action(temp, escape_actions), escape_actions); + python_highlight python_p(temp, escape_actions); boost::spirit::classic::parse(first, last, python_p); } else if (source_mode == "teletype") { - teletype_p_type teletype_p(temp, escape_actions.macro, do_macro_action(temp, escape_actions), escape_actions); + teletype_highlight teletype_p(temp, escape_actions); boost::spirit::classic::parse(first, last, teletype_p); } else diff --git a/src/syntax_highlight.hpp b/src/syntax_highlight.hpp deleted file mode 100644 index 3a16c99..0000000 --- a/src/syntax_highlight.hpp +++ /dev/null @@ -1,417 +0,0 @@ -/*============================================================================= - Copyright (c) 2002 2004 2006 Joel de Guzman - Copyright (c) 2004 Eric Niebler - http://spirit.sourceforge.net/ - - Use, modification and distribution is subject to the Boost Software - License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -=============================================================================*/ -#if !defined(BOOST_SPIRIT_QUICKBOOK_SYNTAX_HIGHLIGHT_HPP) -#define BOOST_SPIRIT_QUICKBOOK_SYNTAX_HIGHLIGHT_HPP - -#include -#include -#include -#include -#include -#include "grammar.hpp" -#include "grammar_impl.hpp" // Just for context stuff. Should move? - -namespace quickbook -{ - namespace cl = boost::spirit::classic; - - // Grammar for C++ highlighting - template < - typename Process - , typename Space - , typename Macro - , typename DoMacro - , typename PreEscape - , typename PostEscape - , typename Unexpected - , typename Out> - struct cpp_highlight - : public cl::grammar > - { - cpp_highlight(Out& out, Macro const& macro, DoMacro do_macro, actions& escape_actions) - : out(out), macro(macro), do_macro(do_macro), escape_actions(escape_actions) {} - - template - struct definition - { - definition(cpp_highlight const& self) - : g(self.escape_actions.grammar()) - { - program - = - *( (+cl::space_p) [Space(self.out)] - | macro - | escape - | preprocessor [Process("preprocessor", self.out)] - | comment [Process("comment", self.out)] - | keyword [Process("keyword", self.out)] - | identifier [Process("identifier", self.out)] - | special [Process("special", self.out)] - | string_ [Process("string", self.out)] - | char_ [Process("char", self.out)] - | number [Process("number", self.out)] - | cl::repeat_p(1)[cl::anychar_p] - [Unexpected(self.out, self.escape_actions)] - ) - ; - - macro = - // must not be followed by alpha or underscore - cl::eps_p(self.macro - >> (cl::eps_p - (cl::alpha_p | '_'))) - >> self.macro [self.do_macro] - ; - - qbk_phrase = - self.escape_actions.scoped_context(element_info::in_phrase) - [ *( g.common - | (cl::anychar_p - cl::str_p("``")) - [self.escape_actions.plain_char] - ) - ] - ; - - escape = - cl::str_p("``") [PreEscape(self.escape_actions, save)] - >> - ( - ( - ( - (+(cl::anychar_p - "``") >> cl::eps_p("``")) - & qbk_phrase - ) - >> cl::str_p("``") - ) - | - ( - cl::eps_p [self.escape_actions.error] - >> *cl::anychar_p - ) - ) [PostEscape(self.out, self.escape_actions, save)] - ; - - preprocessor - = '#' >> *cl::space_p >> ((cl::alpha_p | '_') >> *(cl::alnum_p | '_')) - ; - - comment - = cl::comment_p("//") | cl::comment_p("/*", "*/") - ; - - keyword - = keyword_ >> (cl::eps_p - (cl::alnum_p | '_')) - ; // make sure we recognize whole words only - - keyword_ - = "and_eq", "and", "asm", "auto", "bitand", "bitor", - "bool", "break", "case", "catch", "char", "class", - "compl", "const_cast", "const", "continue", "default", - "delete", "do", "double", "dynamic_cast", "else", - "enum", "explicit", "export", "extern", "false", - "float", "for", "friend", "goto", "if", "inline", - "int", "long", "mutable", "namespace", "new", "not_eq", - "not", "operator", "or_eq", "or", "private", - "protected", "public", "register", "reinterpret_cast", - "return", "short", "signed", "sizeof", "static", - "static_cast", "struct", "switch", "template", "this", - "throw", "true", "try", "typedef", "typeid", - "typename", "union", "unsigned", "using", "virtual", - "void", "volatile", "wchar_t", "while", "xor_eq", "xor" - ; - - special - = +cl::chset_p("~!%^&*()+={[}]:;,<.>?/|\\-") - ; - - string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\'); - - string_ - = !cl::as_lower_d['l'] >> cl::confix_p('"', *string_char, '"') - ; - - char_ - = !cl::as_lower_d['l'] >> cl::confix_p('\'', *string_char, '\'') - ; - - number - = ( - cl::as_lower_d["0x"] >> cl::hex_p - | '0' >> cl::oct_p - | cl::real_p - ) - >> *cl::as_lower_d[cl::chset_p("ldfu")] - ; - - identifier - = (cl::alpha_p | '_') >> *(cl::alnum_p | '_') - ; - } - - cl::rule - program, macro, preprocessor, comment, special, string_, - char_, number, identifier, keyword, qbk_phrase, escape, - string_char; - - cl::symbols<> keyword_; - quickbook_grammar& g; - std::string save; - - cl::rule const& - start() const { return program; } - }; - - Out& out; - Macro const& macro; - DoMacro do_macro; - actions& escape_actions; - }; - - // Grammar for Python highlighting - // See also: The Python Reference Manual - // http://docs.python.org/ref/ref.html - template < - typename Process - , typename Space - , typename Macro - , typename DoMacro - , typename PreEscape - , typename PostEscape - , typename Unexpected - , typename Out> - struct python_highlight - : public cl::grammar > - { - python_highlight(Out& out, Macro const& macro, DoMacro do_macro, actions& escape_actions) - : out(out), macro(macro), do_macro(do_macro), escape_actions(escape_actions) {} - - template - struct definition - { - definition(python_highlight const& self) - : g(self.escape_actions.grammar()) - { - program - = - *( (+cl::space_p) [Space(self.out)] - | macro - | escape - | comment [Process("comment", self.out)] - | keyword [Process("keyword", self.out)] - | identifier [Process("identifier", self.out)] - | special [Process("special", self.out)] - | string_ [Process("string", self.out)] - | number [Process("number", self.out)] - | cl::repeat_p(1)[cl::anychar_p] - [Unexpected(self.out, self.escape_actions)] - ) - ; - - macro = - // must not be followed by alpha or underscore - cl::eps_p(self.macro - >> (cl::eps_p - (cl::alpha_p | '_'))) - >> self.macro [self.do_macro] - ; - - qbk_phrase = - self.escape_actions.scoped_context(element_info::in_phrase) - [ - *( g.common - | (cl::anychar_p - cl::str_p("``")) - [self.escape_actions.plain_char] - ) - ] - ; - - escape = - cl::str_p("``") [PreEscape(self.escape_actions, save)] - >> - ( - ( - ( - (+(cl::anychar_p - "``") >> cl::eps_p("``")) - & qbk_phrase - ) - >> cl::str_p("``") - ) - | - ( - cl::eps_p [self.escape_actions.error] - >> *cl::anychar_p - ) - ) [PostEscape(self.out, self.escape_actions, save)] - ; - - comment - = cl::comment_p("#") - ; - - keyword - = keyword_ >> (cl::eps_p - (cl::alnum_p | '_')) - ; // make sure we recognize whole words only - - keyword_ - = - "and", "del", "for", "is", "raise", - "assert", "elif", "from", "lambda", "return", - "break", "else", "global", "not", "try", - "class", "except", "if", "or", "while", - "continue", "exec", "import", "pass", "yield", - "def", "finally", "in", "print", - - // Technically "as" and "None" are not yet keywords (at Python - // 2.4). They are destined to become keywords, and we treat them - // as such for syntax highlighting purposes. - - "as", "None" - ; - - special - = +cl::chset_p("~!%^&*()+={[}]:;,<.>/|\\-") - ; - - string_prefix - = cl::as_lower_d[cl::str_p("u") >> ! cl::str_p("r")] - ; - - string_ - = ! string_prefix >> (long_string | short_string) - ; - - string_char = ('\\' >> cl::anychar_p) | (cl::anychar_p - '\\'); - - short_string - = cl::confix_p('\'', * string_char, '\'') | - cl::confix_p('"', * string_char, '"') - ; - - long_string - // Note: the "cl::str_p" on the next two lines work around - // an INTERNAL COMPILER ERROR when using VC7.1 - = cl::confix_p(cl::str_p("'''"), * string_char, "'''") | - cl::confix_p(cl::str_p("\"\"\""), * string_char, "\"\"\"") - ; - - number - = ( - cl::as_lower_d["0x"] >> cl::hex_p - | '0' >> cl::oct_p - | cl::real_p - ) - >> *cl::as_lower_d[cl::chset_p("lj")] - ; - - identifier - = (cl::alpha_p | '_') >> *(cl::alnum_p | '_') - ; - } - - cl::rule - program, macro, comment, special, string_, string_prefix, - short_string, long_string, number, identifier, keyword, - qbk_phrase, escape, string_char; - - cl::symbols<> keyword_; - quickbook_grammar& g; - std::string save; - - cl::rule const& - start() const { return program; } - }; - - Out& out; - Macro const& macro; - DoMacro do_macro; - actions& escape_actions; - }; - - // Grammar for plain text (no actual highlighting) - template < - typename CharProcess - , typename Macro - , typename DoMacro - , typename PreEscape - , typename PostEscape - , typename Out> - struct teletype_highlight - : public cl::grammar > - { - teletype_highlight(Out& out, Macro const& macro, DoMacro do_macro, actions& escape_actions) - : out(out), macro(macro), do_macro(do_macro), escape_actions(escape_actions) {} - - template - struct definition - { - definition(teletype_highlight const& self) - : g(self.escape_actions.grammar()) - { - program - = - *( macro - | escape - | cl::repeat_p(1)[cl::anychar_p] [CharProcess(self.out, self.escape_actions)] - ) - ; - - macro = - // must not be followed by alpha or underscore - cl::eps_p(self.macro - >> (cl::eps_p - (cl::alpha_p | '_'))) - >> self.macro [self.do_macro] - ; - - qbk_phrase = - self.escape_actions.scoped_context(element_info::in_phrase) - [ - *( g.common - | (cl::anychar_p - cl::str_p("``")) - [self.escape_actions.plain_char] - ) - ] - ; - - escape = - cl::str_p("``") [PreEscape(self.escape_actions, save)] - >> - ( - ( - ( - (+(cl::anychar_p - "``") >> cl::eps_p("``")) - & qbk_phrase - ) - >> cl::str_p("``") - ) - | - ( - cl::eps_p [self.escape_actions.error] - >> *cl::anychar_p - ) - ) [PostEscape(self.out, self.escape_actions, save)] - ; - } - - cl::rule program, macro, qbk_phrase, escape; - - quickbook_grammar& g; - std::string save; - - cl::rule const& - start() const { return program; } - }; - - Out& out; - Macro const& macro; - DoMacro do_macro; - actions& escape_actions; - }; - -} - -#endif // BOOST_SPIRIT_QUICKBOOK_SYNTAX_HIGHLIGHT_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5f37bf2..b719e9d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -26,6 +26,8 @@ test-suite quickbook.test : [ quickbook-test code-block-2 ] [ quickbook-test code-block-3 ] [ quickbook-test code-block-teletype ] + [ quickbook-test code-block-cpp ] + [ quickbook-test code-block-python ] [ quickbook-test code-snippet ] [ quickbook-test preformatted ] [ quickbook-test link ] diff --git a/test/anchor.gold b/test/anchor.gold index 1aca95b..03f35ce 100644 --- a/test/anchor.gold +++ b/test/anchor.gold @@ -6,42 +6,42 @@
Anchors - A paragraph containing several anchors. - We want to make sure they appear in the correct place. + A paragraph containing several anchors. We + want to make sure they appear in the correct place. This heading shouldn't pick up the previous anchor - + This heading should pick up the previous anchor - + And this one - + Also this one - + Finally this
- <anchor id="a9"/> Section Anchor + <anchor id="a9"/>Section Anchor
- <anchor id="a10"/> Nested Section + <anchor id="a10"/>Nested Section
- <anchor id="a12"/> Conditional Section Anchor + <anchor id="a12"/>Conditional Section Anchor
Lists diff --git a/test/code-block-cpp.gold b/test/code-block-cpp.gold new file mode 100644 index 0000000..793bf65 --- /dev/null +++ b/test/code-block-cpp.gold @@ -0,0 +1,29 @@ + + +
+ C++ Code Blocks +// No escape +/* No escape */ +/* No escape + * with newlines + */ +// In Header: <boost/optional/optional.hpp> +/* In Header: <boost/optional/optional.hpp> */ +/* Multiple escapes: italic + * underlinebold + */ + + + A badly formed comment: + + +/* Oh dear + + + A badly formed comment with an escape: + + +/* Oh dear bold + +
diff --git a/test/code-block-cpp.quickbook b/test/code-block-cpp.quickbook new file mode 100644 index 0000000..be8043a --- /dev/null +++ b/test/code-block-cpp.quickbook @@ -0,0 +1,22 @@ +[article C++ Code Blocks +[quickbook 1.5] +] + + // No escape + /* No escape */ + /* No escape + * with newlines + */ + // In Header: <``[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]``> + /* In Header: <``[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]``> */ + /* Multiple escapes: ``/italic/`` + * ``_underline_````*bold*`` + */ + +A badly formed comment: + + /* Oh dear + +A badly formed comment with an escape: + + /* Oh dear ``*bold*`` diff --git a/test/code-block-python.gold b/test/code-block-python.gold new file mode 100644 index 0000000..ec6c845 --- /dev/null +++ b/test/code-block-python.gold @@ -0,0 +1,10 @@ + + +
+ Python Code Blocks +# No escape +# Escape: bold +# Escape: underlineitalic + +
diff --git a/test/code-block-python.quickbook b/test/code-block-python.quickbook new file mode 100644 index 0000000..45e700e --- /dev/null +++ b/test/code-block-python.quickbook @@ -0,0 +1,8 @@ +[article Python Code Blocks +[quickbook 1.5] +[source-mode python] +] + + # No escape + # Escape: ``*bold*`` + # Escape: ``_underline_````/italic/`` diff --git a/test/include/code-import.gold b/test/include/code-import.gold index 88083ee..5da7949 100644 --- a/test/include/code-import.gold +++ b/test/include/code-import.gold @@ -27,8 +27,8 @@ std::string foo() { - // return 'em, foo man! - return "foo"; + // return 'em, foo man! + return "foo"; } @@ -57,8 +57,8 @@ def foo(): - # return 'em, foo man! - return "foo" + # return 'em, foo man! + return "foo" @@ -87,8 +87,8 @@ char* foo() { - // return 'em, foo man! - return "foo"; + // return 'em, foo man! + return "foo"; } diff --git a/test/include/code-include.gold b/test/include/code-include.gold index 603c52e..d12dd39 100644 --- a/test/include/code-include.gold +++ b/test/include/code-include.gold @@ -40,19 +40,19 @@ char* foo() { - // return 'em, foo man! - return "foo"; + // return 'em, foo man! + return "foo"; } -# Copyright 2009 Daniel James -# -# Use, modification and distribution is subject to the Boost Software -# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - +# Copyright 2009 Daniel James +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + @@ -80,8 +80,8 @@ def foo(): - # return 'em, foo man! - return "foo" + # return 'em, foo man! + return "foo" print foo() @@ -106,8 +106,8 @@ std::string bar() { - // return 'em, bar man! - return "bar"; + // return 'em, bar man! + return "bar"; } @@ -138,8 +138,8 @@ std::string foo() { - // return 'em, foo man! - return "foo"; + // return 'em, foo man! + return "foo"; } std::string foo_bar() { diff --git a/test/include/macros-1.5.gold b/test/include/macros-1.5.gold index c62cd65..d5e8a51 100644 --- a/test/include/macros-1.5.gold +++ b/test/include/macros-1.5.gold @@ -12,7 +12,7 @@ - _foo_ + __foo__ @@ -22,7 +22,7 @@ - _defined_macro_ + __defined_macro__ diff --git a/test/include/macros-1.6.gold b/test/include/macros-1.6.gold index f505402..ec93c05 100644 --- a/test/include/macros-1.6.gold +++ b/test/include/macros-1.6.gold @@ -12,7 +12,7 @@ - _foo_ + __foo__ @@ -22,7 +22,7 @@ - _defined_macro_ + __defined_macro__ diff --git a/test/link.gold b/test/link.gold index 3b3e2a1..8a64fcf 100644 --- a/test/link.gold +++ b/test/link.gold @@ -7,7 +7,7 @@ http://www.boost.org/ Boost link-id Link Text - foo foo link text foo link text foo link text foo int main() { - // Sample code - std::cout << "Hello, World\n"; + // Sample code + std::cout << "Hello, World\n"; return 0; } @@ -2714,8 +2714,8 @@ for the journey to old age.]]] std::string foo() { - // return 'em, foo man! - return "foo"; + // return 'em, foo man! + return "foo"; } @@ -2726,8 +2726,8 @@ for the journey to old age.]]] std::string bar() { - // return 'em, bar man! - return "bar"; + // return 'em, bar man! + return "bar"; } @@ -2743,10 +2743,10 @@ for the journey to old age.]]] get marked up. We use distinguishable comments following the form: -//[id -some code here -//] - +//[id +some code here +//] + The first comment line above initiates a named code-snippet. This prefix will not be visible in quickbook. The entire code-snippet in between -//` some [*quickbook] markup here - +//` some [*quickbook] markup here + and: @@ -3029,8 +3029,8 @@ for the journey to old age.]]] : /usr/share/xml/docbook/schema/dtd/4.2 ; -# Remove this line if you're not using doxygen -using doxygen ; +# Remove this line if you're not using doxygen +using doxygen ; The above steps are enough to get a functional BoostBook setup. Quickbook diff --git a/test/simple_markup.gold b/test/simple_markup.gold index 7acaa98..e08f596 100644 --- a/test/simple_markup.gold +++ b/test/simple_markup.gold @@ -10,8 +10,10 @@ role="underline">underline teletype - /italic/ *bold* _underline_ =teletype= + //not italic// **not bold** __not underline__ ==not teletype== + + + odd__ edge case not__underlined__hopefully @@ -32,7 +34,7 @@ _Should not underline escaped markup_. _or this escaped_ markup form. - Matti Meikäläinen + Matti Meik\u00E4l\u00E4inen replaced @@ -41,13 +43,16 @@ replaced - _macro_ + _mac\ ro_ - /not italic/ + not italic\ These shouldn't be interepted as markup: == // ** + + < \< \\< +
diff --git a/test/simple_markup.quickbook b/test/simple_markup.quickbook index b2f6c7a..61da0ab 100644 --- a/test/simple_markup.quickbook +++ b/test/simple_markup.quickbook @@ -8,7 +8,9 @@ /italic/ *bold* _underline_ =teletype= -//italic// **bold** __underline__ ==teletype== +//not italic// **not bold** __not underline__ ==not teletype== + +_odd__ edge case_ not__underlined__hopefully @@ -35,4 +37,6 @@ __macro__ These shouldn't be interepted as markup: == // ** -[endsect] \ No newline at end of file +=<= =\<= =\\<= + +[endsect] diff --git a/test/snippets/pass_thru.cpp b/test/snippets/pass_thru.cpp index f85522c..bdd9b79 100644 --- a/test/snippets/pass_thru.cpp +++ b/test/snippets/pass_thru.cpp @@ -1,3 +1,11 @@ +/*============================================================================= + Copyright (c) 2011 Daniel James + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + //[foo_cpp struct Foo{ @@ -11,4 +19,4 @@ struct Foo{ int x; //-> }; -//] \ No newline at end of file +//] diff --git a/test/snippets/pass_thru.py b/test/snippets/pass_thru.py index d8e847d..412cee4 100644 --- a/test/snippets/pass_thru.py +++ b/test/snippets/pass_thru.py @@ -1,3 +1,9 @@ +# Copyright (c) 2011 Daniel James +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + #[foo_py def foo: #=print('foo') diff --git a/test/src/Jamfile.v2 b/test/src/Jamfile.v2 index f3469c1..f90ba25 100644 --- a/test/src/Jamfile.v2 +++ b/test/src/Jamfile.v2 @@ -1 +1,9 @@ +# +# Copyright (c) 2011 Daniel James +# +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# + exe line-compare-tool : text_diff.cpp ; diff --git a/test/table_1_5.gold b/test/table_1_5.gold index 86c1c67..a15b2d4 100644 --- a/test/table_1_5.gold +++ b/test/table_1_5.gold @@ -306,7 +306,7 @@ - a + a diff --git a/test/unit/Jamfile.v2 b/test/unit/Jamfile.v2 index 9001289..19b4d1a 100644 --- a/test/unit/Jamfile.v2 +++ b/test/unit/Jamfile.v2 @@ -1,3 +1,11 @@ +# +# Copyright (c) 2011 Daniel James +# +# Distributed under the Boost Software License, Version 1.0. (See +# accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# + import testing ; project quickbook-unit-tests diff --git a/test/variablelist.gold b/test/variablelist.gold index 8bd1ec1..08d6613 100644 --- a/test/variablelist.gold +++ b/test/variablelist.gold @@ -96,10 +96,10 @@ Variable List with anchors - a + a - b + b