Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r65281 - in branches/quickbook-1.5-spirit2: . doc src test
From: dnljms_at_[hidden]
Date: 2010-09-05 04:37:06


Author: danieljames
Date: 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
New Revision: 65281
URL: http://svn.boost.org/trac/boost/changeset/65281

Log:
Merge nested code snippet support from trunk.

Fully merged now.

Properties modified:
   branches/quickbook-1.5-spirit2/ (props changed)
Text files modified:
   branches/quickbook-1.5-spirit2/doc/quickbook.qbk | 1
   branches/quickbook-1.5-spirit2/src/code_snippet_actions.cpp | 141 ++++++++++++++++++++++++++++-----------
   branches/quickbook-1.5-spirit2/src/code_snippet_grammar.cpp | 80 +++++++++++++---------
   branches/quickbook-1.5-spirit2/src/code_snippet_types.hpp | 43 ++++++++---
   branches/quickbook-1.5-spirit2/test/callouts.cpp | 15 ++++
   branches/quickbook-1.5-spirit2/test/callouts.gold | 46 +++++++++++++
   branches/quickbook-1.5-spirit2/test/callouts.quickbook | 5 +
   7 files changed, 247 insertions(+), 84 deletions(-)

Modified: branches/quickbook-1.5-spirit2/doc/quickbook.qbk
==============================================================================
--- branches/quickbook-1.5-spirit2/doc/quickbook.qbk (original)
+++ branches/quickbook-1.5-spirit2/doc/quickbook.qbk 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
@@ -229,6 +229,7 @@
 * Better generated markup for callout lists.
 * In docbook, variable list entries can only have one `listitem`, so if an
   entry has multiple values, merge them into one `listitem`.
+* Support nested code snippets.
 * Revert xml escaping document info, it broke some documentation files
   (now a 1.6 feature).
 * Further work on quickbook 1.6, still not stable.

Modified: branches/quickbook-1.5-spirit2/src/code_snippet_actions.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/src/code_snippet_actions.cpp (original)
+++ branches/quickbook-1.5-spirit2/src/code_snippet_actions.cpp 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
@@ -22,72 +22,135 @@
 
 namespace quickbook
 {
+ void code_snippet_actions::append_code()
+ {
+ if(snippet_stack.empty()) return;
+ snippet_data& snippet = snippet_stack.top();
+
+ if (!code.empty())
+ {
+ detail::unindent(code); // remove all indents
+
+ if(snippet.content.empty())
+ {
+ snippet.start_code = true;
+ }
+ else if(!snippet.end_code)
+ {
+ snippet.content += "\n\n";
+ snippet.content += source_type;
+ snippet.content += "```\n";
+ }
+
+ snippet.content += code;
+ snippet.end_code = true;
+
+ code.clear();
+ }
+ }
+
+ void code_snippet_actions::close_code()
+ {
+ if(snippet_stack.empty()) return;
+ snippet_data& snippet = snippet_stack.top();
+
+ if(snippet.end_code)
+ {
+ snippet.content += "```\n\n";
+ snippet.end_code = false;
+ }
+ }
+
     void code_snippet_actions::process_action::operator()(char x, unused_type, unused_type) const
     {
+ if(actions.snippet_stack.empty()) return;
         actions.code += x;
     }
 
     void code_snippet_actions::process_action::operator()(callout const& x, unused_type, unused_type) const
     {
- actions.code += "``[[callout" + boost::lexical_cast<std::string>(actions.callouts.size()) + "]]``";
-
+ if(actions.snippet_stack.empty()) return;
+ actions.code += "``[[callout" + boost::lexical_cast<std::string>(actions.callout_id) + "]]``";
+
         callout_source item;
         item.body = template_body(x.content, x.position, true);
         item.role = x.role;
- actions.callouts.push_back(item);
+ actions.snippet_stack.top().callouts.push_back(item);
+ ++actions.callout_id;
     }
 
     void code_snippet_actions::process_action::operator()(escaped_comment const& x, unused_type, unused_type) const
     {
- if (!actions.code.empty())
- {
- detail::unindent(actions.code); // remove all indents
- if (actions.code.size() != 0)
- {
- actions.snippet += "\n\n";
- actions.snippet += actions.source_type;
- actions.snippet += "``\n" + actions.code + "``\n\n";
- actions.code.clear();
- }
- }
+ if(actions.snippet_stack.empty()) return;
+ snippet_data& snippet = actions.snippet_stack.top();
+ actions.append_code();
+ actions.close_code();
+
         std::string temp(x.content);
         detail::unindent(temp); // remove all indents
         if (temp.size() != 0)
         {
- actions.snippet += "\n" + temp; // add a linebreak to allow block marskups
+ snippet.content += "\n" + temp; // add a linebreak to allow block marskups
         }
     }
 
- void code_snippet_actions::output_action::operator()(code_snippet const& x, unused_type, unused_type) const
+ void code_snippet_actions::process_action::operator()(start_snippet const& x, unused_type, unused_type) const
+ {
+ actions.append_code();
+ actions.snippet_stack.push(snippet_data(x.identifier, actions.callout_id, x.position));
+ }
+
+ void code_snippet_actions::process_action::operator()(end_snippet const& x, unused_type, unused_type) const
     {
- std::vector<std::string> params;
+ // TODO: Error?
+ if(actions.snippet_stack.empty()) return;
 
- if (!actions.code.empty())
- {
- detail::unindent(actions.code); // remove all indents
- if (actions.code.size() != 0)
- {
- actions.snippet += "\n\n";
- actions.snippet += actions.source_type;
- actions.snippet += "```\n" + actions.code + "```\n\n";
- }
+ actions.append_code();
 
- if(actions.callouts.size() > 0)
- {
- for (size_t i = 0; i < actions.callouts.size(); ++i)
- {
- params.push_back("[callout" + boost::lexical_cast<std::string>(i) + "]");
- }
- }
+ snippet_data snippet = actions.snippet_stack.top();
+ actions.snippet_stack.pop();
+
+ std::string body;
+ if(snippet.start_code) {
+ body += "\n\n";
+ body += actions.source_type;
+ body += "```\n";
+ }
+ body += snippet.content;
+ if(snippet.end_code) {
+ body += "```\n\n";
+ }
+
+ std::vector<std::string> params;
+ for (size_t i = 0; i < snippet.callouts.size(); ++i)
+ {
+ params.push_back("[callout" + boost::lexical_cast<std::string>(snippet.callout_base_id + i) + "]");
         }
 
- define_template d(x.identifier, params,
- template_body(actions.snippet, x.position, true));
- d.callouts = actions.callouts;
+ define_template d(snippet.id, params, template_body(body, snippet.position, true));
+ d.callouts = snippet.callouts;
         actions.storage.push_back(d);
 
- actions.callouts.clear();
- actions.code.clear();
- actions.snippet.clear();
+ // Merge the snippet into its parent
+
+ if(!actions.snippet_stack.empty())
+ {
+ snippet_data& next = actions.snippet_stack.top();
+ if(!snippet.content.empty()) {
+ if(!snippet.start_code) {
+ actions.close_code();
+ }
+ else if(!next.end_code) {
+ next.content += "\n\n";
+ next.content += actions.source_type;
+ next.content += "```\n";
+ }
+
+ next.content += snippet.content;
+ next.end_code = snippet.end_code;
+ }
+
+ next.callouts.insert(next.callouts.end(), snippet.callouts.begin(), snippet.callouts.end());
+ }
     }
 }

Modified: branches/quickbook-1.5-spirit2/src/code_snippet_grammar.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/src/code_snippet_grammar.cpp (original)
+++ branches/quickbook-1.5-spirit2/src/code_snippet_grammar.cpp 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
@@ -35,8 +35,10 @@
 
         qi::rule<iterator>
             start_, ignore;
- qi::rule<iterator, quickbook::code_snippet()>
- snippet;
+ qi::rule<iterator, quickbook::start_snippet()>
+ start_snippet;
+ qi::rule<iterator, quickbook::end_snippet()>
+ end_snippet;
         qi::rule<iterator>
             code_elements;
         qi::rule<iterator, std::string()>
@@ -55,16 +57,13 @@
     python_code_snippet_grammar::rules::rules(actions_type& actions)
         : actions(actions)
     {
- start_ =
- +( snippet [actions.output]
- | qi::char_
- )
- ;
+ start_ = *code_elements;
 
         identifier =
             (qi::alpha | '_') >> *(qi::alnum | '_')
             ;
 
+ /*
         snippet =
                 position [member_assign(&quickbook::code_snippet::position)]
>> repo::confix("#[", "#]")
@@ -73,14 +72,28 @@
>> *(!qi::lit("#]") >> code_elements)
                 ]
             ;
+ */
 
         code_elements =
- escaped_comment [actions.process]
+ start_snippet [actions.process]
+ | end_snippet [actions.process]
+ | escaped_comment [actions.process]
             | ignore
             | +qi::blank [actions.process]
             | qi::char_ [actions.process]
             ;
 
+ start_snippet =
+ position [member_assign(&quickbook::start_snippet::position)]
+ >> "#["
+ >> *qi::space
+ >> identifier [member_assign(&quickbook::start_snippet::identifier)]
+ ;
+
+ end_snippet =
+ qi::lit("#]")
+ >> qi::attr(quickbook::end_snippet());
+
         ignore
             = ( repo::confix(*qi::blank >> "#<-", "#->" >> *qi::blank >> qi::eol)
                         [*(qi::char_ - "#->")]
@@ -110,8 +123,10 @@
 
         qi::rule<iterator>
             start_, code_elements, ignore;
- qi::rule<iterator, quickbook::code_snippet()>
- snippet;
+ qi::rule<iterator, quickbook::start_snippet()>
+ start_snippet;
+ qi::rule<iterator, quickbook::end_snippet()>
+ end_snippet;
         qi::rule<iterator, std::string()>
             identifier;
         qi::rule<iterator, quickbook::callout()>
@@ -130,35 +145,16 @@
     cpp_code_snippet_grammar::rules::rules(actions_type & actions)
         : actions(actions)
     {
- start_ =
- +( snippet [actions.output]
- | qi::char_
- )
- ;
+ start_ = *code_elements;
 
         identifier =
             (qi::alpha | '_') >> *(qi::alnum | '_')
             ;
 
- snippet
- = position [member_assign(&quickbook::code_snippet::position)]
- >> ( repo::confix("//[", "//]")
- [ *qi::space
- >> identifier [member_assign(&quickbook::code_snippet::identifier)]
- >> *(!qi::lit("//]") >> code_elements)
- ]
- | repo::confix("/*[", "/*]*/")
- [ *qi::space
- >> identifier [member_assign(&quickbook::code_snippet::identifier)]
- >> *qi::space
- >> "*/"
- >> *(!qi::lit("/*]*/") >> code_elements)
- ]
- )
- ;
-
         code_elements =
- escaped_comment [actions.process]
+ start_snippet [actions.process]
+ | end_snippet [actions.process]
+ | escaped_comment [actions.process]
             | ignore
             | line_callout [actions.process]
             | inline_callout [actions.process]
@@ -166,6 +162,24 @@
             | qi::char_ [actions.process]
             ;
 
+ start_snippet
+ = position [member_assign(&quickbook::start_snippet::position)]
+ >> ( "//["
+ >> *qi::space
+ >> identifier [member_assign(&quickbook::start_snippet::identifier)]
+ | "/*["
+ >> *qi::space
+ >> identifier [member_assign(&quickbook::start_snippet::identifier)]
+ >> *qi::space
+ >> "*/"
+ )
+ ;
+
+ end_snippet =
+ (qi::lit("//]") | qi::lit("/*]*/"))
+ >> qi::attr(quickbook::end_snippet());
+ ;
+
         inline_callout
             = repo::confix("/*<" >> *qi::space, ">*/")
                 [ position [member_assign(&quickbook::callout::position)]

Modified: branches/quickbook-1.5-spirit2/src/code_snippet_types.hpp
==============================================================================
--- branches/quickbook-1.5-spirit2/src/code_snippet_types.hpp (original)
+++ branches/quickbook-1.5-spirit2/src/code_snippet_types.hpp 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
@@ -14,6 +14,7 @@
 
 #include <vector>
 #include <string>
+#include <stack>
 #include <boost/spirit/include/support_unused.hpp>
 #include "fwd.hpp"
 #include "template.hpp"
@@ -21,11 +22,15 @@
 
 namespace quickbook
 {
- struct code_snippet
+ struct start_snippet
     {
         file_position position;
         std::string identifier;
     };
+
+ struct end_snippet
+ {
+ };
     
     struct callout
     {
@@ -50,7 +55,6 @@
                                  std::string const& doc_id,
                                  char const* source_type)
             : process(*this)
- , output(*this)
             , storage(storage)
             , doc_id(doc_id)
             , source_type(source_type)
@@ -64,25 +68,40 @@
             void operator()(char x, unused_type, unused_type) const;
             void operator()(callout const& x, unused_type, unused_type) const;
             void operator()(escaped_comment const& x, unused_type, unused_type) const;
+ void operator()(start_snippet const& x, unused_type, unused_type) const;
+ void operator()(end_snippet const& x, unused_type, unused_type) const;
 
             code_snippet_actions& actions;
         };
 
- struct output_action
- {
- explicit output_action(code_snippet_actions& a)
- : actions(a) {}
-
- void operator()(code_snippet const& x, unused_type, unused_type) const;
+ void append_code();
+ void close_code();
 
- code_snippet_actions& actions;
+ struct snippet_data
+ {
+ snippet_data(std::string const& id, int callout_base_id, file_position position)
+ : id(id)
+ , callout_base_id(callout_base_id)
+ , position(position)
+ , content()
+ , start_code(false)
+ , end_code(false)
+ {}
+
+ std::string id;
+ int callout_base_id;
+ file_position position;
+ std::string content;
+ bool start_code;
+ bool end_code;
+ quickbook::callouts callouts;
         };
 
         process_action process;
- output_action output;
+
+ int callout_id;
+ std::stack<snippet_data> snippet_stack;
         std::string code;
- std::string snippet;
- quickbook::callouts callouts;
         std::vector<define_template>& storage;
         std::string const doc_id;
         char const* const source_type;

Modified: branches/quickbook-1.5-spirit2/test/callouts.cpp
==============================================================================
--- branches/quickbook-1.5-spirit2/test/callouts.cpp (original)
+++ branches/quickbook-1.5-spirit2/test/callouts.cpp 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
@@ -3,6 +3,8 @@
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
 
+/*< This shouldn't be used. >*/
+
 //[ example1
 
 /*`
@@ -33,3 +35,16 @@
 }
 
 //]
+
+//[ example4
+
+int roll_die() {
+ /*<< callout 1 >>*/
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+//[ example4a
+ /*<< callout 2 >>*/
+ boost::uniform_int<> dist(1, 6); /*< create a uniform_int distribution >*/
+//]
+}
+
+//]

Modified: branches/quickbook-1.5-spirit2/test/callouts.gold
==============================================================================
--- branches/quickbook-1.5-spirit2/test/callouts.gold (original)
+++ branches/quickbook-1.5-spirit2/test/callouts.gold 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
@@ -84,4 +84,50 @@
       </important>
     </callout>
   </calloutlist>
+ <para>
+ Example 4:
+ </para>
+ <para>
+
+<programlisting><phrase role="keyword">int</phrase> <phrase role="identifier">roll_die</phrase><phrase role="special">()</phrase> <phrase role="special">{</phrase>
+ <co id="callout_tests4co" linkends="callout_tests4" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">variate_generator</phrase><phrase role="special">&lt;</phrase><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">mt19937</phrase><phrase role="special">&amp;,</phrase> <phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="special">&gt;</phrase> <phrase role="identifier">die</phrase><phrase role="special">(</phrase><phrase role="identifier">gen</phrase><phrase role="special">,</phrase> <phrase role="identifier">dist</phrase><phrase role="special">);</phrase>
+<co id="callout_tests5co" linkends="callout_tests5" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests6co" linkends="callout_tests6" />
+<phrase role="special">}</phrase>
+
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests4co" id="callout_tests4">
+ <para>
+ callout 1
+ </para>
+ </callout>
+ <callout arearefs="callout_tests5co" id="callout_tests5">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests6co" id="callout_tests6">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
+ <para>
+
+<programlisting><co id="callout_tests7co" linkends="callout_tests7" /><phrase role="identifier">boost</phrase><phrase role="special">::</phrase><phrase role="identifier">uniform_int</phrase><phrase role="special">&lt;&gt;</phrase> <phrase role="identifier">dist</phrase><phrase role="special">(</phrase><phrase role="number">1</phrase><phrase role="special">,</phrase> <phrase role="number">6</phrase><phrase role="special">);</phrase> <co id="callout_tests8co" linkends="callout_tests8" />
+</programlisting>
+ </para>
+ <calloutlist>
+ <callout arearefs="callout_tests7co" id="callout_tests7">
+ <para>
+ callout 2
+ </para>
+ </callout>
+ <callout arearefs="callout_tests8co" id="callout_tests8">
+ <para>
+ create a uniform_int distribution
+ </para>
+ </callout>
+ </calloutlist>
 </article>

Modified: branches/quickbook-1.5-spirit2/test/callouts.quickbook
==============================================================================
--- branches/quickbook-1.5-spirit2/test/callouts.quickbook (original)
+++ branches/quickbook-1.5-spirit2/test/callouts.quickbook 2010-09-05 04:37:05 EDT (Sun, 05 Sep 2010)
@@ -19,3 +19,8 @@
 Example 3 (again!):
 
 [example3]
+
+Example 4:
+
+[example4]
+[example4a]


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk