diff --git a/src/Jamfile.v2 b/src/Jamfile.v2 index a7b0d2e..82b16cc 100644 --- a/src/Jamfile.v2 +++ b/src/Jamfile.v2 @@ -26,6 +26,7 @@ exe quickbook post_process.cpp collector.cpp template_stack.cpp + code_snippet.cpp markups.cpp syntax_highlight.cpp block_grammar.cpp diff --git a/src/actions.cpp b/src/actions.cpp index 770202b..70eaf79 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -23,7 +22,6 @@ #include "markups.hpp" #include "actions_class.hpp" #include "grammar.hpp" -#include "code_snippet.hpp" namespace quickbook { @@ -1250,176 +1248,6 @@ namespace quickbook out << "\" />\n"; } - 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::pass_thru(iterator first, iterator last) - { - if(snippet_stack.empty()) return; - code += *first; - } - - void code_snippet_actions::pass_thru_char(char c) - { - if(snippet_stack.empty()) return; - code += c; - } - - void code_snippet_actions::callout(iterator first, iterator last) - { - if(snippet_stack.empty()) return; - code += "``[[callout" + boost::lexical_cast(callout_id) + "]]``"; - - snippet_stack.top().callouts.push_back( - template_body(std::string(first, last), first.get_position(), true)); - ++callout_id; - } - - void code_snippet_actions::escaped_comment(iterator first, iterator last) - { - if(snippet_stack.empty()) return; - snippet_data& snippet = snippet_stack.top(); - append_code(); - close_code(); - - std::string temp(first, last); - detail::unindent(temp); // remove all indents - if (temp.size() != 0) - { - snippet.content += "\n" + temp; // add a linebreak to allow block markups - } - } - - void code_snippet_actions::start_snippet(iterator first, iterator last) - { - append_code(); - snippet_stack.push(snippet_data(id, callout_id)); - id.clear(); - } - - void code_snippet_actions::end_snippet(iterator first, iterator last) - { - // TODO: Error? - if(snippet_stack.empty()) return; - - append_code(); - - snippet_data snippet = snippet_stack.top(); - snippet_stack.pop(); - - std::string body; - if(snippet.start_code) { - body += "\n\n"; - body += source_type; - body += "```\n"; - } - body += snippet.content; - if(snippet.end_code) { - body += "```\n\n"; - } - - std::vector params; - for (size_t i = 0; i < snippet.callouts.size(); ++i) - { - params.push_back("[callout" + boost::lexical_cast(snippet.callout_base_id + i) + "]"); - } - - // TODO: Save position in start_snippet - template_symbol symbol(snippet.id, params, body, first.get_position(), true); - symbol.callout = true; - symbol.callouts = snippet.callouts; - storage.push_back(symbol); - - // Merge the snippet into its parent - - if(!snippet_stack.empty()) - { - snippet_data& next = snippet_stack.top(); - if(!snippet.content.empty()) { - if(!snippet.start_code) { - close_code(); - } - else if(!next.end_code) { - next.content += "\n\n"; - next.content += 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()); - } - } - - int load_snippets( - std::string const& file - , std::vector& storage // snippets are stored in a - // vector of template_symbols - , std::string const& extension - , std::string const& doc_id) - { - std::string code; - int err = detail::load(file, code); - if (err != 0) - return err; // return early on error - - typedef position_iterator iterator_type; - iterator_type first(code.begin(), code.end(), file); - iterator_type last(code.end(), code.end()); - - size_t fname_len = file.size(); - bool is_python = fname_len >= 3 - && file[--fname_len]=='y' && file[--fname_len]=='p' && file[--fname_len]=='.'; - code_snippet_actions a(storage, doc_id, is_python ? "[python]" : "[c++]"); - // TODO: Should I check that parse succeeded? - if(is_python) { - boost::spirit::classic::parse(first, last, python_code_snippet_grammar(a)); - } - else { - boost::spirit::classic::parse(first, last, cpp_code_snippet_grammar(a)); - } - - return 0; - } - namespace { fs::path include_search(fs::path const & current, std::string const & name) diff --git a/src/actions.hpp b/src/actions.hpp index 7da7f20..601a1b5 100644 --- a/src/actions.hpp +++ b/src/actions.hpp @@ -49,6 +49,8 @@ namespace quickbook // forward declarations struct actions; int parse_file(char const* filein_, actions& actor, bool ignore_docinfo = false); + int load_snippets(std::string const& file, std::vector& storage, + std::string const& extension, std::string const& doc_id); struct error_action { diff --git a/src/code_snippet.hpp b/src/code_snippet.cpp similarity index 61% rename from src/code_snippet.hpp rename to src/code_snippet.cpp index 832679d..8419cbc 100644 --- a/src/code_snippet.hpp +++ b/src/code_snippet.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "template_stack.hpp" #include "actions.hpp" @@ -234,6 +235,176 @@ namespace quickbook actions_type& actions; }; + + int load_snippets( + std::string const& file + , std::vector& storage // snippets are stored in a + // vector of template_symbols + , std::string const& extension + , std::string const& doc_id) + { + std::string code; + int err = detail::load(file, code); + if (err != 0) + return err; // return early on error + + typedef position_iterator iterator_type; + iterator_type first(code.begin(), code.end(), file); + iterator_type last(code.end(), code.end()); + + size_t fname_len = file.size(); + bool is_python = fname_len >= 3 + && file[--fname_len]=='y' && file[--fname_len]=='p' && file[--fname_len]=='.'; + code_snippet_actions a(storage, doc_id, is_python ? "[python]" : "[c++]"); + // TODO: Should I check that parse succeeded? + if(is_python) { + boost::spirit::classic::parse(first, last, python_code_snippet_grammar(a)); + } + else { + boost::spirit::classic::parse(first, last, cpp_code_snippet_grammar(a)); + } + + return 0; + } + + 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::pass_thru(iterator first, iterator last) + { + if(snippet_stack.empty()) return; + code += *first; + } + + void code_snippet_actions::pass_thru_char(char c) + { + if(snippet_stack.empty()) return; + code += c; + } + + void code_snippet_actions::callout(iterator first, iterator last) + { + if(snippet_stack.empty()) return; + code += "``[[callout" + boost::lexical_cast(callout_id) + "]]``"; + + snippet_stack.top().callouts.push_back( + template_body(std::string(first, last), first.get_position(), true)); + ++callout_id; + } + + void code_snippet_actions::escaped_comment(iterator first, iterator last) + { + if(snippet_stack.empty()) return; + snippet_data& snippet = snippet_stack.top(); + append_code(); + close_code(); + + std::string temp(first, last); + detail::unindent(temp); // remove all indents + if (temp.size() != 0) + { + snippet.content += "\n" + temp; // add a linebreak to allow block markups + } + } + + void code_snippet_actions::start_snippet(iterator first, iterator last) + { + append_code(); + snippet_stack.push(snippet_data(id, callout_id)); + id.clear(); + } + + void code_snippet_actions::end_snippet(iterator first, iterator last) + { + // TODO: Error? + if(snippet_stack.empty()) return; + + append_code(); + + snippet_data snippet = snippet_stack.top(); + snippet_stack.pop(); + + std::string body; + if(snippet.start_code) { + body += "\n\n"; + body += source_type; + body += "```\n"; + } + body += snippet.content; + if(snippet.end_code) { + body += "```\n\n"; + } + + std::vector params; + for (size_t i = 0; i < snippet.callouts.size(); ++i) + { + params.push_back("[callout" + boost::lexical_cast(snippet.callout_base_id + i) + "]"); + } + + // TODO: Save position in start_snippet + template_symbol symbol(snippet.id, params, body, first.get_position(), true); + symbol.callout = true; + symbol.callouts = snippet.callouts; + storage.push_back(symbol); + + // Merge the snippet into its parent + + if(!snippet_stack.empty()) + { + snippet_data& next = snippet_stack.top(); + if(!snippet.content.empty()) { + if(!snippet.start_code) { + close_code(); + } + else if(!next.end_code) { + next.content += "\n\n"; + next.content += 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()); + } + } } #endif // BOOST_SPIRIT_QUICKBOOK_CODE_SNIPPET_HPP