Unverified Commit 93f6d712 authored by Joseph Noir's avatar Joseph Noir Committed by GitHub

Merge pull request #1031

Fix tables, lists, and nested commands in manual
parents e06a9a6b b71531da
...@@ -328,7 +328,7 @@ struct list_builder : abstract_consumer { ...@@ -328,7 +328,7 @@ struct list_builder : abstract_consumer {
} else if (name == "item") { } else if (name == "item") {
result.items.emplace_back(); result.items.emplace_back();
} else { } else {
consumer->consume(make_node(name, std::move(args))); consume(make_node(name, std::move(args)));
} }
} }
}; };
...@@ -442,6 +442,19 @@ void read_tex_list(State& ps, Consumer&& consumer, const string& cmd_name); ...@@ -442,6 +442,19 @@ void read_tex_list(State& ps, Consumer&& consumer, const string& cmd_name);
template <class State, class Consumer> template <class State, class Consumer>
void read_tex_tabular(State& ps, Consumer&& consumer); void read_tex_tabular(State& ps, Consumer&& consumer);
struct sub_command_consumer : abstract_consumer {
std::vector<string>& args;
explicit sub_command_consumer(std::vector<string>& args) : args(args) {
// nop
}
template <class T>
void cmd(const T& x, std::vector<std::string> args);
void consume(node x);
};
template <class State, class Consumer> template <class State, class Consumer>
void read_tex_command(State& ps, Consumer&& consumer) { void read_tex_command(State& ps, Consumer&& consumer) {
string cmd; string cmd;
...@@ -481,6 +494,7 @@ void read_tex_command(State& ps, Consumer&& consumer) { ...@@ -481,6 +494,7 @@ void read_tex_command(State& ps, Consumer&& consumer) {
consumer.consume(text{std::move(spaces)}); consumer.consume(text{std::move(spaces)});
} }
}); });
sub_command_consumer scc{args};
// clang-format off // clang-format off
start(); start();
state(init) { state(init) {
...@@ -499,10 +513,17 @@ void read_tex_command(State& ps, Consumer&& consumer) { ...@@ -499,10 +513,17 @@ void read_tex_command(State& ps, Consumer&& consumer) {
transition(read_command, " \t\n", spaces += ch) transition(read_command, " \t\n", spaces += ch)
} }
state(read_command_arg) { state(read_command_arg) {
transition(start_escaping_inside_command_arg, '\\')
fsm_epsilon(read_tex_comment(ps, consumer), read_command_arg, '%') fsm_epsilon(read_tex_comment(ps, consumer), read_command_arg, '%')
transition(read_command, stop_chars) transition(read_command, stop_chars)
transition(read_command_arg, any_char, args.back() += ch) transition(read_command_arg, any_char, args.back() += ch)
} }
state(start_escaping_inside_command_arg) {
transition(read_command_arg, '\\', args.back() += '\\')
transition(read_command_arg, '%', args.back() += '%')
transition(read_command_arg, '_', args.back() += '_')
fsm_epsilon(read_tex_command(ps, scc), read_command_arg, any_char)
}
term_state(done) { term_state(done) {
guard.disable(); guard.disable();
} }
...@@ -528,13 +549,14 @@ void read_tex(State& ps, Consumer&& consumer) { ...@@ -528,13 +549,14 @@ void read_tex(State& ps, Consumer&& consumer) {
start(); start();
term_state(init) { term_state(init) {
fsm_transition(read_tex_comment(ps, consumer), init, '%') fsm_transition(read_tex_comment(ps, consumer), init, '%')
transition(start_escaping, "\\") transition(start_escaping, '\\')
transition(init, "~", str += ' ') transition(init, '~', str += ' ')
transition(init, any_char, str += ch) transition(init, any_char, str += ch)
} }
state(start_escaping) { state(start_escaping) {
transition(init, "\\", str += '\\') transition(init, '\\', str += '\\')
transition(init, "%", str += '%') transition(init, '%', str += '%')
transition(init, '_', str += '_')
fsm_epsilon(read_tex_command(ps, consumer), init, any_char, consume_str()) fsm_epsilon(read_tex_command(ps, consumer), init, any_char, consume_str())
} }
fin(); fin();
...@@ -561,8 +583,9 @@ void read_tex_list(State& ps, Consumer& consumer) { ...@@ -561,8 +583,9 @@ void read_tex_list(State& ps, Consumer& consumer) {
transition_if(before_first_item(), init, " \t\n") transition_if(before_first_item(), init, " \t\n")
} }
state(start_escaping) { state(start_escaping) {
transition_if(!before_first_item(), init, "\\", str += '\\') transition_if(!before_first_item(), init, '\\', str += '\\')
transition_if(!before_first_item(), init, "%", str += '%') transition_if(!before_first_item(), init, '%', str += '%')
transition_if(!before_first_item(), init, '_', str += '_')
fsm_epsilon(read_tex_command(ps, consumer), after_cmd, any_char, consume_str()) fsm_epsilon(read_tex_command(ps, consumer), after_cmd, any_char, consume_str())
} }
unstable_state(after_cmd) { unstable_state(after_cmd) {
...@@ -611,14 +634,15 @@ void read_tex_tabular(State& ps, Consumer&& consumer) { ...@@ -611,14 +634,15 @@ void read_tex_tabular(State& ps, Consumer&& consumer) {
start(); start();
state(init) { state(init) {
fsm_transition(read_tex_comment(ps, builder), init, '%') fsm_transition(read_tex_comment(ps, builder), init, '%')
transition(start_escaping, "\\") transition(start_escaping, '\\')
transition(init, "&", next_column()) transition(init, "&", next_column())
transition(init, "~", str += ' ') transition(init, "~", str += ' ')
transition(init, any_char, str += ch) transition(init, any_char, str += ch)
} }
state(start_escaping) { state(start_escaping) {
transition(init, "\\", next_row()) transition(init, '\\', next_row())
transition(init, "%", str += '%') transition(init, '%', str += '%')
transition(init, '_', str += '_')
fsm_epsilon(read_tex_command(ps, builder), after_cmd, any_char, consume_str()) fsm_epsilon(read_tex_command(ps, builder), after_cmd, any_char, consume_str())
} }
unstable_state(after_cmd) { unstable_state(after_cmd) {
...@@ -918,7 +942,7 @@ Out& operator<<(Out& out, href& x) { ...@@ -918,7 +942,7 @@ Out& operator<<(Out& out, href& x) {
template <class Out> template <class Out>
Out& operator<<(Out& out, experimental&) { Out& operator<<(Out& out, experimental&) {
return out << "\\ :sup:`experimental`\\ "; return out << " :sup:`experimental`";
} }
} // namespace rst_ops } // namespace rst_ops
...@@ -956,6 +980,17 @@ struct rst_ops_visitor : abstract_consumer { ...@@ -956,6 +980,17 @@ struct rst_ops_visitor : abstract_consumer {
} }
}; };
template <class T>
void sub_command_consumer::cmd(const T& x, std::vector<std::string> xs) {
consume(make_node(x, std::move(xs)));
}
void sub_command_consumer::consume(node x) {
string_stream out{args.back()};
rst_ops_visitor<string_stream> visitor{out};
visitor.consume(std::move(x));
}
BEGIN_STATE(await_section_label) BEGIN_STATE(await_section_label)
void entry(const std::string& section_name, char highlighting) { void entry(const std::string& section_name, char highlighting) {
...@@ -1050,27 +1085,57 @@ BEGIN_STATE(read_body) ...@@ -1050,27 +1085,57 @@ BEGIN_STATE(read_body)
print_block(".. ::", x.block); print_block(".. ::", x.block);
} }
void operator()(itemize& x) { template <class T, class NextLine>
void print_list(T & x, NextLine next_line) {
out() << "\n\n"; out() << "\n\n";
for (auto& i : x.items) { for (auto& i : x.items) {
out() << "* "; // lists must be aligned
std::string block;
string_stream block_stream{block};
rst_ops_visitor<string_stream> sub{block_stream};
for (auto& n : i.nodes) for (auto& n : i.nodes)
visit(*this, n); visit(sub, n);
std::vector<std::string> lines;
split(lines, block, is_any_of("\n"), token_compress_on);
for (auto i = lines.begin(); i != lines.end();) {
trim(*i);
if (i->empty())
i = lines.erase(i);
else
++i;
}
if (!lines.empty()) {
next_line(true);
out() << lines.front();
for (size_t i = 1; i < lines.size(); ++i) {
next_line(false);
out() << lines[i];
}
}
out() << '\n'; out() << '\n';
} }
out() << '\n'; out() << '\n';
} }
void operator()(itemize& x) {
auto next_line = [&](bool new_item) {
if (new_item)
out() << "* ";
else
out() << " ";
};
print_list(x, next_line);
}
void operator()(enumerate& x) { void operator()(enumerate& x) {
size_t num = 1; size_t num = 1;
out() << "\n\n"; auto next_line = [&](bool new_item) {
for (auto& i : x.items) { if (new_item)
out() << num++ << ". "; out() << num++ << ". ";
for (auto& n : i.nodes) else
visit(*this, n); out() << " "; // TODO: support more than 10 items
out() << '\n'; };
} print_list(x, next_line);
out() << '\n';
} }
void operator()(tabular& x) { void operator()(tabular& x) {
......
...@@ -302,15 +302,15 @@ Blocking actors simply implement their behavior in the function body. The actor ...@@ -302,15 +302,15 @@ Blocking actors simply implement their behavior in the function body. The actor
is done once it returns from that function. is done once it returns from that function.
Event-based actors can either return a \lstinline^behavior^ Event-based actors can either return a \lstinline^behavior^
\see{message-handler} that is used to initialize the actor or explicitly set \see{message-handler} that is used to initialize the actor or explicitly set the
the initial behavior by calling \lstinline^self->become(...)^. Due to the initial behavior by calling \lstinline^self->become(...)^. Due to the
asynchronous, event-based nature of this kind of actor, the function usually asynchronous, event-based nature of this kind of actor, the function usually
returns immediately after setting a behavior (message handler) for the returns immediately after setting a behavior (message handler) for the
\emph{next} incoming message. Hence, variables on the stack will be out of \emph{next} incoming message. Hence, variables on the stack will be out of scope
scope once a message arrives. Managing state in function-based actors can be once a message arrives. Managing state in function-based actors can be done
done either via rebinding state with \lstinline^become^, using heap-located either via rebinding state with \lstinline^become^, using heap-located data
data referenced via \lstinline^std::shared_ptr^ or by using the ``stateful referenced via \lstinline^std::shared_ptr^ or by using the \textit{stateful
actor'' abstraction~\see{stateful-actor}. actor} abstraction~\see{stateful-actor}.
The following three functions implement the prototypes shown in~\sref{spawn} The following three functions implement the prototypes shown in~\sref{spawn}
and illustrate one blocking actor and two event-based actors (statically and and illustrate one blocking actor and two event-based actors (statically and
...@@ -396,8 +396,8 @@ A behavior that combines the behaviors \lstinline^X^, \lstinline^Y^, and ...@@ -396,8 +396,8 @@ A behavior that combines the behaviors \lstinline^X^, \lstinline^Y^, and
inheriting from the three classes directly. The class inheriting from the three classes directly. The class
\lstinline^composed_behavior^ ensures that the behaviors are concatenated \lstinline^composed_behavior^ ensures that the behaviors are concatenated
correctly. In case one message handler is defined in multiple base types, the correctly. In case one message handler is defined in multiple base types, the
\emph{first} type in declaration order ``wins''. For example, if \lstinline^X^ \emph{first} type in declaration order wins. For example, if \lstinline^X^ and
and \lstinline^Y^ both implement the interface \lstinline^Y^ both implement the interface
\lstinline^replies_to<int,int>::with<int>^, only the handler implemented in \lstinline^replies_to<int,int>::with<int>^, only the handler implemented in
\lstinline^X^ is active. \lstinline^X^ is active.
......
...@@ -104,16 +104,16 @@ object \emph{before} initializing an actor system with it. ...@@ -104,16 +104,16 @@ object \emph{before} initializing an actor system with it.
\subsection{Command Line Options and INI Configuration Files} \subsection{Command Line Options and INI Configuration Files}
\label{system-config-options} \label{system-config-options}
CAF organizes program options in categories and parses CLI arguments as well CAF organizes program options in categories and parses CLI arguments as well as
as INI files. CLI arguments override values in the INI file which override INI files. CLI arguments override values in the INI file which override
hard-coded defaults. Users can add any number of custom program options by hard-coded defaults. Users can add any number of custom program options by
implementing a subtype of \lstinline^actor_system_config^. The example below implementing a subtype of \lstinline^actor_system_config^. The example below
adds three options to the ``global'' category. adds three options to the \lstinline^global^ category.
\cppexample[222-234]{remoting/distributed_calculator} \cppexample[222-234]{remoting/distributed_calculator}
We create a new ``global'' category in \lstinline^custom_options_}^. Each We create a new \lstinline^global^ category in \lstinline^custom_options_}^.
following call to \lstinline^add^ then appends individual options to the Each following call to \lstinline^add^ then appends individual options to the
category. The first argument to \lstinline^add^ is the associated variable. The category. The first argument to \lstinline^add^ is the associated variable. The
second argument is the name for the parameter, optionally suffixed with a second argument is the name for the parameter, optionally suffixed with a
comma-separated single-character short name. The short name is only considered comma-separated single-character short name. The short name is only considered
...@@ -121,10 +121,10 @@ for CLI parsing and allows users to abbreviate commonly used option names. The ...@@ -121,10 +121,10 @@ for CLI parsing and allows users to abbreviate commonly used option names. The
third and final argument to \lstinline^add^ is a help text. third and final argument to \lstinline^add^ is a help text.
The custom \lstinline^config^ class allows end users to set the port for the The custom \lstinline^config^ class allows end users to set the port for the
application to 42 with either \lstinline^--port=42^ (long name) or application to 42 with either \lstinline^-p 42^ (short name) or
\lstinline^-p 42^ (short name). The long option name is prefixed by the \lstinline^--port=42^ (long name). The long option name is prefixed by the
category when using a different category than ``global''. For example, adding category when using a different category than ``global''. For example, adding
the port option to the category ``foo'' means end users have to type the port option to the category \lstinline^foo^ means end users have to type
\lstinline^--foo.port=42^ when using the long name. Short names are unaffected \lstinline^--foo.port=42^ when using the long name. Short names are unaffected
by the category, but have to be unique. by the category, but have to be unique.
...@@ -138,18 +138,18 @@ simplicity. However, this is not required. For example, ...@@ -138,18 +138,18 @@ simplicity. However, this is not required. For example,
values of the configuration are accessible with \lstinline^get_or^. Note that values of the configuration are accessible with \lstinline^get_or^. Note that
all global options can omit the \lstinline^"global."^ prefix. all global options can omit the \lstinline^"global."^ prefix.
CAF adds the program options ``help'' (with short names \lstinline^-h^ and CAF adds the program options \lstinline^help^ (with short names \lstinline^-h^
\lstinline^-?^) as well as ``long-help'' to the ``global'' category. and \lstinline^-?^) as well as \lstinline^long-help^ to the \lstinline^global^
category.
The default name for the INI file is \lstinline^caf-application.ini^. Users can The default name for the INI file is \lstinline^caf-application.ini^. Users can
change the file name and path by passing \lstinline^--config-file=<path>^ on change the file name and path by passing \lstinline^--config-file=<path>^ on the
the command line. command line.
INI files are organized in categories. No value is allowed outside of a INI files are organized in categories. No value is allowed outside of a category
category (no implicit ``global'' category). The parses uses the following (no implicit \lstinline^global^ category). The parses uses the following syntax:
syntax:
\begin{tabular}{p{0.3\textwidth}p{0.65\textwidth}} \begin{tabular}{ll}
\lstinline^key=true^ & is a boolean \\ \lstinline^key=true^ & is a boolean \\
\lstinline^key=1^ & is an integer \\ \lstinline^key=1^ & is an integer \\
\lstinline^key=1.0^ & is an floating point number \\ \lstinline^key=1.0^ & is an floating point number \\
...@@ -253,9 +253,10 @@ with \lstinline^std::string^. ...@@ -253,9 +253,10 @@ with \lstinline^std::string^.
Logging is disabled in CAF per default. It can be enabled by setting the Logging is disabled in CAF per default. It can be enabled by setting the
\lstinline^--with-log-level=^ option of the \lstinline^configure^ script to one \lstinline^--with-log-level=^ option of the \lstinline^configure^ script to one
of ``error'', ``warning'', ``info'', ``debug'', or ``trace'' (from least output of \lstinline^error^, \lstinline^warning^, \lstinline^info^, \lstinline^debug^,
to most). Alternatively, setting the CMake variable \lstinline^CAF_LOG_LEVEL^ or \lstinline^trace^ (from least output to most). Alternatively, setting the
to 0, 1, 2, 3, or 4 (from least output to most) has the same effect. CMake variable \lstinline^CAF_LOG_LEVEL^ to one of these values has the same
effect.
All logger-related configuration options listed here and in All logger-related configuration options listed here and in
\sref{system-config-options} are silently ignored if logging is disabled. \sref{system-config-options} are silently ignored if logging is disabled.
...@@ -266,7 +267,7 @@ All logger-related configuration options listed here and in ...@@ -266,7 +267,7 @@ All logger-related configuration options listed here and in
The output file is generated from the template configured by The output file is generated from the template configured by
\lstinline^logger-file-name^. This template supports the following variables. \lstinline^logger-file-name^. This template supports the following variables.
\begin{tabular}{|p{0.2\textwidth}|p{0.75\textwidth}|} \begin{tabular}{ll}
\hline \hline
\textbf{Variable} & \textbf{Output} \\ \textbf{Variable} & \textbf{Output} \\
\hline \hline
...@@ -294,15 +295,15 @@ events via \lstinline^logger-file-format^ and ...@@ -294,15 +295,15 @@ events via \lstinline^logger-file-format^ and
\lstinline^logger-console-format^. Note that format modifiers are not supported \lstinline^logger-console-format^. Note that format modifiers are not supported
at the moment. The recognized field identifiers are: at the moment. The recognized field identifiers are:
\begin{tabular}{|p{0.1\textwidth}|p{0.85\textwidth}|} \begin{tabular}{ll}
\hline \hline
\textbf{Character} & \textbf{Output} \\ \textbf{Character} & \textbf{Output} \\
\hline \hline
\texttt{c} & The category/component. This name is defined by the macro \lstinline^CAF_LOG_COMPONENT^. Set this macro before including any CAF header. \\ \texttt{c} & The category/component. \\
\hline \hline
\texttt{C} & The full qualifier of the current function. For example, the qualifier of \lstinline^void ns::foo::bar()^ is printed as \lstinline^ns.foo^. \\ \texttt{C} & The full qualifier of the current function. For example, the qualifier of \lstinline^void ns::foo::bar()^ is printed as \lstinline^ns.foo^. \\
\hline \hline
\texttt{d} & The date in ISO 8601 format, i.e., \lstinline^"YYYY-MM-DD hh:mm:ss"^. \\ \texttt{d} & The date in ISO 8601 format, i.e., \lstinline^"YYYY-MM-DDThh:mm:ss"^. \\
\hline \hline
\texttt{F} & The file name. \\ \texttt{F} & The file name. \\
\hline \hline
...@@ -320,7 +321,7 @@ at the moment. The recognized field identifiers are: ...@@ -320,7 +321,7 @@ at the moment. The recognized field identifiers are:
\hline \hline
\texttt{t} & ID of the current thread. \\ \texttt{t} & ID of the current thread. \\
\hline \hline
\texttt{a} & ID of the current actor (or ``actor0'' when not logging inside an actor). \\ \texttt{a} & ID of the current actor (or \lstinline^actor0^ when not logging inside an actor). \\
\hline \hline
\texttt{\%} & A single percent sign. \\ \texttt{\%} & A single percent sign. \\
\hline \hline
......
...@@ -27,8 +27,8 @@ and from one node to many nodes. However, the actor model has not yet been ...@@ -27,8 +27,8 @@ and from one node to many nodes. However, the actor model has not yet been
widely adopted in the native programming domain. With CAF, we contribute a widely adopted in the native programming domain. With CAF, we contribute a
library for actor programming in C++ as open-source software to ease native library for actor programming in C++ as open-source software to ease native
development of concurrent as well as distributed systems. In this regard, CAF development of concurrent as well as distributed systems. In this regard, CAF
follows the C++ philosophy ``building the highest abstraction possible without follows the C++ philosophy \textit{building the highest abstraction possible
sacrificing performance''. without sacrificing performance}.
\subsection{Terminology} \subsection{Terminology}
...@@ -41,10 +41,10 @@ differences when comparing CAF to other actor frameworks. ...@@ -41,10 +41,10 @@ differences when comparing CAF to other actor frameworks.
\subsubsection{Dynamically Typed Actor} \subsubsection{Dynamically Typed Actor}
A dynamically typed actor accepts any kind of message and dispatches on its A dynamically typed actor accepts any kind of message and dispatches on its
content dynamically at the receiver. This is the ``traditional'' messaging content dynamically at the receiver. This is the traditional messaging style
style found in implementations like Erlang or Akka. The upside of this approach found in implementations like Erlang or Akka. The upside of this approach is
is (usually) faster prototyping and less code. This comes at the cost of (usually) faster prototyping and less code. This comes at the cost of requiring
requiring excessive testing. excessive testing.
\subsubsection{Statically Typed Actor} \subsubsection{Statically Typed Actor}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment