⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 actions.hpp

📁 C++的一个好库。。。现在很流行
💻 HPP
📖 第 1 页 / 共 3 页
字号:
/*=============================================================================
    Copyright (c) 2002 2004 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_ACTIONS_HPP)
#define BOOST_SPIRIT_QUICKBOOK_ACTIONS_HPP

#include <time.h>
#include <string>
#include <vector>
#include <stack>
#include <algorithm>
#include <sstream>
#include <boost/spirit/iterator/position_iterator.hpp>
#include "../syntax_highlight.hpp"
#include "utils.hpp"

namespace quickbook
{
    struct error_action
    {
        // Prints an error message to std::cerr

        template <typename Iterator>
        void operator()(Iterator const& first, Iterator const& /*last*/) const
        {
            boost::spirit::file_position const pos = first.get_position();
            std::cerr
                << "Syntax Error at \"" << pos.file
                << "\" line " << pos.line
                << ", column " << pos.column << ".\n";
        }
    };

    struct phrase_action
    {
        //  Handles paragraph, h1, h2, h3, h4, h5, h6,
        //  blurb, blockquote, preformatted, list_item,
        //  unordered_list, ordered_list

        phrase_action(
            std::ostream&       out,
            std::stringstream&  phrase,
            std::string&        section_id,
            std::string const&  pre,
            std::string const&  post,
            bool                anchor = false)
        : out(out)
        , phrase(phrase)
        , section_id(section_id)
        , pre(pre)
        , post(post)
        , anchor(anchor) {}

        template <typename Iterator>
        void operator()(Iterator const& first, Iterator const& last) const
        {
            if (out)
            {
                std::string  str = phrase.str();
                if (anchor)
                    out << "<anchor id=\""
                        << section_id << '.'
                        << detail::make_identifier(str.begin(), str.end())
                        << "\" />";
                phrase.str(std::string());
                out << pre << str << post;
            }
        }

        std::ostream&       out;
        std::stringstream&  phrase;
        std::string&        section_id;
        std::string         pre;
        std::string         post;
        bool                anchor;
    };

    struct simple_phrase_action
    {
        //  Handles simple text formats

        simple_phrase_action(
            std::ostream&       out,
            std::string const&  pre,
            std::string const&  post)
        : out(out)
        , pre(pre)
        , post(post) {}

        template <typename Iterator>
        void operator()(Iterator first, Iterator const& last) const
        {
            if (out)
            {
                out << pre;
                while (first != last)
                    detail::print_char(*first++, out);
                out << post;
            }
        }

        std::ostream&   out;
        std::string     pre;
        std::string     post;
    };

    struct list_action
    {
        //  Handles lists

        typedef std::pair<char, int> mark_type;
        list_action(
            std::ostream& out
          , std::stringstream& list_buffer
          , int& indent
          , std::stack<mark_type>& list_marks)
        : out(out)
        , list_buffer(list_buffer)
        , indent(indent)
        , list_marks(list_marks) {}

        template <typename Iterator>
        void operator()(Iterator const& first, Iterator const& last) const
        {
            assert(!list_marks.empty()); // there must be at least one item in the stack
            std::string  str = list_buffer.str();
            list_buffer.str(std::string());
            out << str;

            while (!list_marks.empty())
            {
                char mark = list_marks.top().first;
                list_marks.pop();
                out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
                if (list_marks.size() >= 1)
                    out << std::string("\n</listitem>");
            }

            indent = -1; // reset
        }

        std::ostream& out;
        std::stringstream& list_buffer;
        int& indent;
        std::stack<mark_type>& list_marks;
    };

    struct list_format_action
    {
        //  Handles list formatting and hierarchy

        typedef std::pair<char, int> mark_type;
        list_format_action(
            std::stringstream& out
          , int& indent
          , std::stack<mark_type>& list_marks)
        : out(out)
        , indent(indent)
        , list_marks(list_marks) {}

        template <typename Iterator>
        void operator()(Iterator first, Iterator const& last) const
        {
            int new_indent = 0;
            while (first != last && (*first == ' ' || *first == '\t'))
            {
                char mark = *first++;
                if (mark == ' ')
                {
                    ++new_indent;
                }
                else // must be a tab
                {
                    assert(mark == '\t');
                    // hardcoded tab to 4 for now
                    new_indent = ((new_indent + 4) / 4) * 4;
                }
            }

            char mark = *first;
            assert(mark == '#' || mark == '*'); // expecting a mark

            if (indent == -1) // the very start
            {
                assert(new_indent == 0);
            }

            if (new_indent > indent)
            {
                //~ char parent_mark = 0;
                //~ if (list_marks.size() >= 1)
                    //~ parent_mark = list_marks.top().first;
                indent = new_indent;
                list_marks.push(mark_type(mark, indent));
                if (list_marks.size() > 1)
                {
                    // Make this new list a child of the previous list.
                    // The previous listelem has already ended so we erase
                    // </listitem> to accomodate this sub-list. We'll close
                    // the listelem later.

                    std::string str = out.str();
                    std::string::size_type pos = str.rfind("\n</listitem>");
                    assert(pos <= str.size());
                    str.erase(str.begin()+pos, str.end());
                    out.str(std::string());
                    out << str;
                    //~ out << std::string((parent_mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
                }
                //~ else
                //~ {
                    out << std::string((mark == '#') ? "<orderedlist>\n" : "<itemizedlist>\n");
                //~ }
            }

            else if (new_indent < indent)
            {
                assert(!list_marks.empty());
                indent = new_indent;
                //~ list_marks.pop();
                //~ out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
                //~ if (list_marks.size() >= 1)
                    //~ out << std::string("\n</listitem>");

                while (!list_marks.empty() && (indent < list_marks.top().second))
                {
                    char mark = list_marks.top().first;
                    list_marks.pop();
                    out << std::string((mark == '#') ? "\n</orderedlist>" : "\n</itemizedlist>");
                    if (list_marks.size() >= 1)
                        out << std::string("\n</listitem>");
                }
            }

            if (mark != list_marks.top().first) // new_indent == indent
            {
                boost::spirit::file_position const pos = first.get_position();
                std::cerr
                    << "Illegal change of list style at \"" << pos.file
                    << "\" line " << pos.line
                    << ", column " << pos.column << ".\n";
                std::cerr << "Ignoring change of list style" << std::endl;
            }
        }

        std::stringstream& out;
        int& indent;
        std::stack<mark_type>& list_marks;
    };

    struct span
    {
        // Decorates c++ code fragments

        span(char const* name, std::ostream& out)
        : name(name), out(out) {}

        template <typename Iterator>
        void operator()(Iterator first, Iterator last) const
        {
            if (out)
            {
                out << "<phrase role=\"" << name << "\">";
                while (first != last)
                    detail::print_char(*first++, out);
                out << "</phrase>";
            }
        }

        char const* name;
        std::ostream& out;
    };

    struct unexpected_char
    {
        // Handles unexpected chars in c++ syntax

        unexpected_char(std::ostream& out)
        : out(out) {}

        template <typename Char>
        void operator()(Char) const
        {
            if (out)
                out << '#'; // print out an unexpected character
        }

        std::ostream& out;
    };

    struct anchor_action
    {
        // Handles anchors

        anchor_action(std::ostream& out)
            : out(out) {}

        template <typename Iterator>
        void operator()(Iterator first, Iterator last) const
        {
            if (out)
            {
                out << "<anchor id=\"";
                while (first != last)
                    detail::print_char(*first++, out);
                out << "\" />\n";
            }
        }

        std::ostream& out;
    };

    char const* quickbook_get_date = "__quickbook_get_date__";
    char const* quickbook_get_time = "__quickbook_get_time__";

    struct do_macro_action
    {
        // Handles macro substitutions

        do_macro_action(std::ostream& phrase)
        : phrase(phrase) {}

        void operator()(std::string const& str) const
        {
            if (str == quickbook_get_date)
            {
                char strdate[ 64 ];
                time_t t = time(0);
                strftime( strdate, sizeof(strdate), "%Y-%b-%d", localtime(&t) );
                phrase << strdate;
            }
            else if (str == quickbook_get_time)
            {
                char strdate[ 64 ];
                time_t t = time(0);
                strftime( strdate, sizeof(strdate), "%I:%M:%S %p", localtime(&t) );
                phrase << strdate;
            }
            else
            {
                phrase << str;
            }
        }

        std::ostream& phrase;
    };

    struct space
    {
        // Prints a space

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -