diff --git a/doc/1_6.qbk b/doc/1_6.qbk
index 653508d..370b198 100644
--- a/doc/1_6.qbk
+++ b/doc/1_6.qbk
@@ -330,4 +330,13 @@ and lists. I'm not sure if it would be a good idea.
[endsect]
+[section:callouts Callouts in code block]
+
+Currently callouts can only be used in code snippets. 1.7 add
+support in normal code blocks. The same syntax is used as in
+code snippets, the callout descriptions appear immediately
+after the code block.
+
+[endsect]
+
[endsect] [/ Quickbok 1.7]
diff --git a/src/actions.cpp b/src/actions.cpp
index 63d443a..4332ed4 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -536,6 +536,83 @@ namespace quickbook
out << "";
}
+ namespace
+ {
+ bool parse_template(value const&, quickbook::actions& actions);
+ }
+
+ void actions::start_callouts()
+ {
+ ++callout_depth;
+ }
+
+ std::string actions::add_callout(value v)
+ {
+ std::string callout_id1 = ids.add_id("c", id_category::numbered);
+ std::string callout_id2 = ids.add_id("c", id_category::numbered);
+
+ callouts.insert(encoded_value(callout_id1));
+ callouts.insert(encoded_value(callout_id2));
+ callouts.insert(v);
+
+ std::string code;
+ code += "";
+
+ return code;
+ }
+
+ std::string actions::end_callouts()
+ {
+ assert(callout_depth > 0);
+ std::string block;
+
+ --callout_depth;
+ if (callout_depth > 0) return block;
+
+ value_consumer c = callouts.release();
+ if (!c.check()) return block;
+
+ block += "";
+ while (c.check())
+ {
+ std::string callout_id1 = c.consume().get_encoded();
+ std::string callout_id2 = c.consume().get_encoded();
+ value callout_body = c.consume();
+
+ std::string callout_value;
+
+ {
+ template_state state(*this);
+ ++template_depth;
+
+ bool r = parse_template(callout_body, *this);
+
+ if(!r)
+ {
+ detail::outerr(callout_body.get_file(), callout_body.get_position())
+ << "Expanding callout." << std::endl
+ << "------------------begin------------------" << std::endl
+ << detail::utf8(callout_body.get_quickbook())
+ << std::endl
+ << "------------------end--------------------" << std::endl
+ ;
+ ++error_count;
+ }
+
+ out.swap(callout_value);
+ }
+
+ block += "";
+ block += callout_value;
+ block += "";
+ }
+ block += "";
+
+ return block;
+ }
+
void explicit_list_action(quickbook::actions& actions, value list)
{
write_anchors(actions, actions.out);
@@ -645,6 +722,8 @@ namespace quickbook
if (f->source.empty())
return; // Nothing left to do here. The program is empty.
+ if (qbk_version_n >= 107u) actions.start_callouts();
+
parse_iterator first_(f->source.begin());
parse_iterator last_(f->source.end());
@@ -653,7 +732,7 @@ namespace quickbook
// print the code with syntax coloring
std::string str = syntax_highlight(first_, last_, actions,
- source_mode);
+ source_mode, block);
boost::swap(actions.current_file, saved_file);
@@ -665,12 +744,14 @@ namespace quickbook
output << "";
output << str;
output << "\n";
+
+ if (qbk_version_n >= 107u) output << actions.end_callouts();
}
else {
parse_iterator first_(code_value.begin());
parse_iterator last_(code_value.end());
std::string str = syntax_highlight(first_, last_, actions,
- source_mode);
+ source_mode, block);
actions.phrase << "";
actions.phrase << str;
@@ -1118,9 +1199,9 @@ namespace quickbook
parse_iterator last(source.end());
bool r = cl::parse(first, last,
- content.get_tag() == template_tags::block ?
- actions.grammar().block :
- actions.grammar().inline_phrase
+ content.get_tag() == template_tags::phrase ?
+ actions.grammar().inline_phrase :
+ actions.grammar().block
).full;
boost::swap(actions.current_file, saved_current_file);
@@ -1134,12 +1215,14 @@ namespace quickbook
std::vector const& args,
string_iterator first)
{
+ bool is_block = symbol->content.get_tag() != template_tags::phrase;
+
// If this template contains already encoded text, then just
// write it out, without going through any of the rigamarole.
if (symbol->content.is_encoded())
{
- if (symbol->content.get_tag() == template_tags::block)
+ if (is_block)
{
actions.paragraph();
actions.out << symbol->content.get_encoded();
@@ -1200,7 +1283,7 @@ namespace quickbook
{
detail::outerr(actions.current_file, first)
<< "Expanding "
- << (symbol->content.get_tag() == template_tags::block ? "block" : "phrase")
+ << (is_block ? "block" : "phrase")
<< " template: " << detail::utf8(symbol->identifier) << std::endl
<< std::endl
<< "------------------begin------------------" << std::endl
@@ -1225,7 +1308,7 @@ namespace quickbook
actions.phrase.swap(phrase);
}
- if(symbol->content.get_tag() == template_tags::block || !block.empty()) {
+ if(is_block || !block.empty()) {
actions.paragraph(); // For paragraphs before the template call.
actions.out << block;
actions.phrase << phrase;
@@ -1240,81 +1323,19 @@ namespace quickbook
template_symbol const* symbol,
string_iterator first)
{
- value_consumer values = symbol->content;
- value content = values.consume(template_tags::block);
- value callouts = values.consume();
- values.finish();
-
- std::vector callout_ids;
+ assert(symbol->params.size() == 0);
std::vector args;
- unsigned int size = symbol->params.size();
- std::string callout_base("c");
-
- for(unsigned int i = 0; i < size; ++i)
- {
- std::string callout_id1 = actions.ids.add_id(callout_base, id_category::numbered);
- std::string callout_id2 = actions.ids.add_id(callout_base, id_category::numbered);
-
- std::string code;
- code += "";
-
- args.push_back(encoded_value(code, template_tags::phrase));
- callout_ids.push_back(callout_id1);
- callout_ids.push_back(callout_id2);
- }
// Create a fake symbol for call_template
template_symbol t(
symbol->identifier,
symbol->params,
- content,
+ symbol->content,
symbol->lexical_parent);
+
+ actions.start_callouts();
call_template(actions, &t, args, first);
-
- std::string block;
-
- if(!callouts.empty())
- {
- block += "";
- int i = 0;
- BOOST_FOREACH(value c, callouts)
- {
- std::string callout_id1 = callout_ids[i++];
- std::string callout_id2 = callout_ids[i++];
-
- std::string callout_value;
- {
- template_state state(actions);
- ++actions.template_depth;
-
- bool r = parse_template(c, actions);
-
- if(!r)
- {
- detail::outerr(c.get_file(), c.get_position())
- << "Expanding callout." << std::endl
- << "------------------begin------------------" << std::endl
- << detail::utf8(c.get_quickbook())
- << std::endl
- << "------------------end--------------------" << std::endl
- ;
- ++actions.error_count;
- return;
- }
-
- actions.out.swap(callout_value);
- }
-
- block += "";
- block += callout_value;
- block += "";
- }
- block += "";
- }
-
- actions.out << block;
+ actions.out << actions.end_callouts();
}
void do_template_action(quickbook::actions& actions, value template_list,
diff --git a/src/actions.hpp b/src/actions.hpp
index 409bbb8..3fce5ce 100644
--- a/src/actions.hpp
+++ b/src/actions.hpp
@@ -62,7 +62,8 @@ namespace quickbook
std::string syntax_highlight(
parse_iterator first, parse_iterator last,
actions& escape_actions,
- std::string const& source_mode);
+ std::string const& source_mode,
+ bool is_block);
struct xinclude_path {
xinclude_path(fs::path const& path, std::string const& uri) :
diff --git a/src/actions_class.cpp b/src/actions_class.cpp
index ac54c20..84bb99f 100644
--- a/src/actions_class.cpp
+++ b/src/actions_class.cpp
@@ -32,6 +32,8 @@ namespace quickbook
, warned_about_breaks(false)
, conditional(true)
, ids(ids)
+ , callouts()
+ , callout_depth(0)
, imported(false)
, macro()
diff --git a/src/actions_class.hpp b/src/actions_class.hpp
index 1ad3843..75498ec 100644
--- a/src/actions_class.hpp
+++ b/src/actions_class.hpp
@@ -46,6 +46,8 @@ namespace quickbook
bool warned_about_breaks;
bool conditional;
id_manager& ids;
+ value_builder callouts; // callouts are global as
+ int callout_depth; // they don't nest.
// state saved for files and templates.
bool imported;
@@ -77,6 +79,10 @@ namespace quickbook
void start_list_item();
void end_list_item();
+ void start_callouts();
+ std::string add_callout(value);
+ std::string end_callouts();
+
scoped_parser
to_value;
scoped_parser
diff --git a/src/code_snippet.cpp b/src/code_snippet.cpp
index 8d9484c..b7af1b7 100644
--- a/src/code_snippet.cpp
+++ b/src/code_snippet.cpp
@@ -31,13 +31,13 @@ namespace quickbook
char const* source_type)
: last_code_pos(source_file->source.begin())
, in_code(false)
- , callout_id(0)
, snippet_stack()
, storage(storage)
, source_file(source_file)
, source_type(source_type)
, error_count(0)
{
+ source_file->is_code_snippets = true;
content.start(source_file);
}
@@ -48,7 +48,6 @@ namespace quickbook
void start_snippet_impl(std::string const&, string_iterator);
void end_snippet(string_iterator first, string_iterator last);
void end_snippet_impl(string_iterator);
- void callout(string_iterator first, string_iterator last);
void end_file(string_iterator, string_iterator);
void append_code(string_iterator first, string_iterator last);
@@ -56,26 +55,22 @@ namespace quickbook
struct snippet_data
{
- snippet_data(std::string const& id, int callout_base_id)
+ snippet_data(std::string const& id)
: id(id)
- , callout_base_id(callout_base_id)
, start_code(false)
{}
std::string id;
- int callout_base_id;
bool start_code;
std::string::const_iterator source_pos;
mapped_file_builder::pos start_pos;
- value_builder callouts;
boost::shared_ptr next;
};
- void push_snippet_data(std::string const& id, int callout_base_id,
+ void push_snippet_data(std::string const& id,
std::string::const_iterator pos)
{
- boost::shared_ptr new_snippet(
- new snippet_data(id, callout_base_id));
+ boost::shared_ptr new_snippet(new snippet_data(id));
new_snippet->next = snippet_stack;
snippet_stack = new_snippet;
snippet_stack->start_code = in_code;
@@ -95,7 +90,6 @@ namespace quickbook
std::string::const_iterator mark_begin, mark_end;
std::string::const_iterator last_code_pos;
bool in_code;
- int callout_id;
boost::shared_ptr snippet_stack;
std::vector& storage;
file_ptr source_file;
@@ -240,8 +234,6 @@ namespace quickbook
| escaped_comment [boost::bind(&actions_type::escaped_comment, &actions, _1, _2)]
| ignore [boost::bind(&actions_type::append_code, &actions, _1, _2)]
| pass_thru_comment [boost::bind(&actions_type::pass_thru, &actions, _1, _2)]
- | line_callout [boost::bind(&actions_type::callout, &actions, _1, _2)]
- | inline_callout [boost::bind(&actions_type::callout, &actions, _1, _2)]
| cl::anychar_p
;
@@ -287,23 +279,6 @@ namespace quickbook
"/*[*/"
;
- inline_callout
- = cl::confix_p(
- "/*<" >> *cl::space_p,
- (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
- ">*/"
- )
- ;
-
- line_callout
- = cl::confix_p(
- "/*<<" >> *cl::space_p,
- (*cl::anychar_p) [boost::bind(&actions_type::mark, &actions, _1, _2)],
- ">>*/"
- )
- >> *cl::space_p
- ;
-
ignore
= cl::confix_p(
*cl::blank_p >> "//<-",
@@ -354,7 +329,7 @@ namespace quickbook
cl::rule
start_, identifier, code_elements, start_snippet, end_snippet,
- escaped_comment, pass_thru_comment, inline_callout, line_callout, ignore;
+ escaped_comment, pass_thru_comment, ignore;
cl::rule const&
start() const { return start_; }
@@ -447,27 +422,6 @@ namespace quickbook
content.add(mark_begin, mark_end);
}
- void code_snippet_actions::callout(string_iterator first, string_iterator last)
- {
- if(!snippet_stack) return;
- append_code(first, last);
-
- if (!in_code)
- {
- content.add("\n\n", first);
- content.add(source_type, first);
- content.add("```\n", first);
- in_code = true;
- }
-
- content.add(
- "``[[callout" + boost::lexical_cast(callout_id) + "]]``",
- first);
-
- snippet_stack->callouts.insert(qbk_value(source_file, mark_begin, mark_end, template_tags::block));
- ++callout_id;
- }
-
void code_snippet_actions::escaped_comment(string_iterator first, string_iterator last)
{
append_code(first, last);
@@ -549,7 +503,7 @@ namespace quickbook
void code_snippet_actions::start_snippet_impl(std::string const& id,
string_iterator position)
{
- push_snippet_data(id, callout_id, position);
+ push_snippet_data(id, position);
}
void code_snippet_actions::end_snippet_impl(string_iterator position)
@@ -557,7 +511,6 @@ namespace quickbook
assert(snippet_stack);
boost::shared_ptr snippet = pop_snippet_data();
- value callouts = snippet->callouts.release();
mapped_file_builder f;
f.start(source_file);
@@ -572,29 +525,11 @@ namespace quickbook
}
std::vector params;
- int i = 0;
- for(value::iterator it = callouts.begin(); it != callouts.end(); ++it)
- {
- params.push_back("[callout" + boost::lexical_cast(snippet->callout_base_id + i) + "]");
- ++i;
- }
file_ptr body = f.release();
- value_builder builder;
- builder.set_tag(template_tags::snippet);
- builder.insert(qbk_value(body, body->source.begin(), body->source.end(),
- template_tags::block));
- builder.insert(callouts);
-
- template_symbol symbol(snippet->id, params, builder.release());
- storage.push_back(symbol);
-
- // Copy the snippet's callouts to its parent
-
- if(snippet_stack)
- {
- snippet_stack->callouts.extend(callouts);
- }
+ storage.push_back(template_symbol(snippet->id, params,
+ qbk_value(body, body->source.begin(), body->source.end(),
+ template_tags::snippet)));
}
}
diff --git a/src/files.cpp b/src/files.cpp
index ce63c84..02ada8b 100644
--- a/src/files.cpp
+++ b/src/files.cpp
@@ -285,8 +285,9 @@ namespace quickbook
struct mapped_file : file
{
mapped_file(file_ptr original) :
- file(original->path, std::string(), original->version()),
- original(original), mapped_sections() {}
+ file(*original, std::string()),
+ original(original), mapped_sections()
+ {}
file_ptr original;
std::vector mapped_sections;
diff --git a/src/files.hpp b/src/files.hpp
index 1b0ef28..7475c10 100644
--- a/src/files.hpp
+++ b/src/files.hpp
@@ -38,13 +38,20 @@ namespace quickbook {
{
fs::path const path;
std::string source;
+ bool is_code_snippets;
private:
unsigned qbk_version;
public:
file(fs::path const& path, std::string const& source,
unsigned qbk_version) :
- path(path), source(source), qbk_version(qbk_version)
+ path(path), source(source), is_code_snippets(false),
+ qbk_version(qbk_version)
+ {}
+
+ file(file const& f, std::string const& source) :
+ path(f.path), source(source), is_code_snippets(f.is_code_snippets),
+ qbk_version(f.qbk_version)
{}
virtual ~file() {}
diff --git a/src/syntax_highlight.cpp b/src/syntax_highlight.cpp
index 8eecde7..a0a3bda 100644
--- a/src/syntax_highlight.cpp
+++ b/src/syntax_highlight.cpp
@@ -93,9 +93,17 @@ namespace quickbook
quickbook::actions& escape_actions;
do_macro_action do_macro_impl;
- syntax_highlight_actions(quickbook::actions& escape_actions) :
+ // State
+ bool support_callouts;
+ string_ref marked_text;
+
+ syntax_highlight_actions(quickbook::actions& escape_actions,
+ bool is_block) :
out(), escape_actions(escape_actions),
- do_macro_impl(out, escape_actions)
+ do_macro_impl(out, escape_actions),
+ support_callouts(is_block && (qbk_version_n >= 107u ||
+ escape_actions.current_file->is_code_snippets)),
+ marked_text()
{}
void span(parse_iterator, parse_iterator, char const*);
@@ -106,6 +114,9 @@ namespace quickbook
void pre_escape_back(parse_iterator, parse_iterator);
void post_escape_back(parse_iterator, parse_iterator);
void do_macro(std::string const&);
+
+ void mark_text(parse_iterator, parse_iterator);
+ void callout(parse_iterator, parse_iterator);
};
void syntax_highlight_actions::span(parse_iterator first,
@@ -175,6 +186,19 @@ namespace quickbook
do_macro_impl(v);
}
+ void syntax_highlight_actions::mark_text(parse_iterator first,
+ parse_iterator last)
+ {
+ marked_text = string_ref(first.base(), last.base());
+ }
+
+ void syntax_highlight_actions::callout(parse_iterator, parse_iterator)
+ {
+ out << escape_actions.add_callout(qbk_value(escape_actions.current_file,
+ marked_text.begin(), marked_text.end()));
+ marked_text.clear();
+ }
+
// Syntax
struct keywords_holder
@@ -242,7 +266,9 @@ namespace quickbook
unexpected_char(self.actions, &syntax_highlight_actions::unexpected_char),
plain_char(self.actions, &syntax_highlight_actions::plain_char),
pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
- post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back);
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back),
+ mark_text(self.actions, &syntax_highlight_actions::mark_text),
+ callout(self.actions, &syntax_highlight_actions::callout);
member_action_value
do_macro(self.actions, &syntax_highlight_actions::do_macro);
@@ -252,6 +278,10 @@ namespace quickbook
| macro
| escape
| preprocessor [span("preprocessor")]
+ | cl::eps_p(ph::var(self.actions.support_callouts))
+ >> ( line_callout [callout]
+ | inline_callout [callout]
+ )
| comment
| keyword [span("keyword")]
| identifier [span("identifier")]
@@ -294,6 +324,23 @@ namespace quickbook
= '#' >> *cl::space_p >> ((cl::alpha_p | '_') >> *(cl::alnum_p | '_'))
;
+ inline_callout
+ = cl::confix_p(
+ "/*<" >> *cl::space_p,
+ (*cl::anychar_p) [mark_text],
+ ">*/"
+ )
+ ;
+
+ line_callout
+ = cl::confix_p(
+ "/*<<" >> *cl::space_p,
+ (*cl::anychar_p) [mark_text],
+ ">>*/"
+ )
+ >> *cl::space_p
+ ;
+
comment
= cl::str_p("//") [span_start("comment")]
>> *( escape
@@ -342,7 +389,9 @@ namespace quickbook
}
cl::rule
- program, macro, preprocessor, comment, special, string_,
+ program, macro, preprocessor,
+ inline_callout, line_callout, comment,
+ special, string_,
char_, number, identifier, keyword, escape,
string_char;
@@ -377,7 +426,9 @@ namespace quickbook
unexpected_char(self.actions, &syntax_highlight_actions::unexpected_char),
plain_char(self.actions, &syntax_highlight_actions::plain_char),
pre_escape_back(self.actions, &syntax_highlight_actions::pre_escape_back),
- post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back);
+ post_escape_back(self.actions, &syntax_highlight_actions::post_escape_back),
+ mark_text(self.actions, &syntax_highlight_actions::mark_text),
+ callout(self.actions, &syntax_highlight_actions::callout);
member_action_value
do_macro(self.actions, &syntax_highlight_actions::do_macro);
@@ -560,9 +611,10 @@ namespace quickbook
parse_iterator first,
parse_iterator last,
actions& escape_actions,
- std::string const& source_mode)
+ std::string const& source_mode,
+ bool is_block)
{
- syntax_highlight_actions syn_actions(escape_actions);
+ syntax_highlight_actions syn_actions(escape_actions, is_block);
// print the code with syntax coloring
if (source_mode == "c++")
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 6d8b11a..ef9e068 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -26,6 +26,7 @@ test-suite quickbook.test :
[ quickbook-test anchor-1_6 ]
[ quickbook-test blocks-1_5 ]
[ quickbook-test callouts-1_5 ]
+ [ quickbook-test callouts-1_7 ]
[ quickbook-test code-1_1 ]
[ quickbook-test code-1_5 ]
[ quickbook-test code_cpp-1_5 ]
diff --git a/test/callouts-1_7.gold b/test/callouts-1_7.gold
new file mode 100644
index 0000000..5cf0dc5
--- /dev/null
+++ b/test/callouts-1_7.gold
@@ -0,0 +1,247 @@
+
+
+
+ Callout Tests
+
+ Example 1:
+
+
+ Now we can define a function that simulates an ordinary six-sided die.
+
+int roll_die() {
+ boost::uniform_int<> dist(1, 6);
+}
+
+
+
+
+ create a uniform_int distribution
+
+
+
+
+ Example 2:
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+
+
+
+
+ test
+
+
+
+
+
+ Example 3:
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+
+
+
+
+ test
+
+
+
+
+
+ Example 3 (again!):
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+
+
+
+
+ test
+
+
+
+
+
+ Example 4:
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+ boost::uniform_int<> dist(1, 6);
+}
+
+
+
+
+ callout 1
+
+
+
+
+ callout 2
+
+
+
+
+ create a uniform_int distribution
+
+
+
+boost::uniform_int<> dist(1, 6);
+
+
+
+
+ callout 2
+
+
+
+
+ create a uniform_int distribution
+
+
+
+
+ Try callouts in a section
+
+ Example 1:
+
+
+ Now we can define a function that simulates an ordinary six-sided die.
+
+int roll_die() {
+ boost::uniform_int<> dist(1, 6);
+}
+
+
+
+
+ create a uniform_int distribution
+
+
+
+
+ Example 2:
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+
+
+
+
+ test
+
+
+
+
+
+ Example 3:
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+
+
+
+
+ test
+
+
+
+
+
+ Example 3 (again!):
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+
+
+
+
+ test
+
+
+
+
+
+ Example 4:
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+ boost::uniform_int<> dist(1, 6);
+}
+
+
+
+
+ callout 1
+
+
+
+
+ callout 2
+
+
+
+
+ create a uniform_int distribution
+
+
+
+boost::uniform_int<> dist(1, 6);
+
+
+
+
+ callout 2
+
+
+
+
+ create a uniform_int distribution
+
+
+
+
+
+ Callouts in code blocks
+int roll_die() {
+ boost::uniform_int<> dist(1, 6);
+}
+
+
+
+
+ create a uniform_int distribution
+
+
+
+int roll_die() {
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
+}
+
+
+
+
+
+ test
+
+
+
+
+
+ /*< This shouldn't be a callout >*/
+
+
+
diff --git a/test/callouts-1_7.quickbook b/test/callouts-1_7.quickbook
new file mode 100644
index 0000000..fd3d9ee
--- /dev/null
+++ b/test/callouts-1_7.quickbook
@@ -0,0 +1,68 @@
+[article Callout Tests
+ [quickbook 1.7]
+]
+
+[import callouts.cpp]
+
+Example 1:
+
+[example1]
+
+Example 2:
+
+[example2]
+
+Example 3:
+
+[example3]
+
+Example 3 (again!):
+
+[example3]
+
+Example 4:
+
+[example4]
+[example4a]
+
+[section:test_section Try callouts in a section]
+
+Example 1:
+
+[example1]
+
+Example 2:
+
+[example2]
+
+Example 3:
+
+[example3]
+
+Example 3 (again!):
+
+[example3]
+
+Example 4:
+
+[example4]
+[example4a]
+
+[endsect]
+
+[section:blocks Callouts in code blocks]
+
+ int roll_die() {
+ boost::uniform_int<> dist(1, 6); /*< create a uniform_int distribution >*/
+ }
+
+```
+int roll_die() {
+ /*<< [important test] >>*/
+ boost::variate_generator > die(gen, dist);
+}
+```
+
+`/*< This shouldn't be a callout >*/`
+
+[endsect]
\ No newline at end of file