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 {
} else if (name == "item") {
result.items.emplace_back();
} 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);
template <class State, class 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>
void read_tex_command(State& ps, Consumer&& consumer) {
string cmd;
......@@ -481,6 +494,7 @@ void read_tex_command(State& ps, Consumer&& consumer) {
consumer.consume(text{std::move(spaces)});
}
});
sub_command_consumer scc{args};
// clang-format off
start();
state(init) {
......@@ -499,10 +513,17 @@ void read_tex_command(State& ps, Consumer&& consumer) {
transition(read_command, " \t\n", spaces += ch)
}
state(read_command_arg) {
transition(start_escaping_inside_command_arg, '\\')
fsm_epsilon(read_tex_comment(ps, consumer), read_command_arg, '%')
transition(read_command, stop_chars)
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) {
guard.disable();
}
......@@ -528,13 +549,14 @@ void read_tex(State& ps, Consumer&& consumer) {
start();
term_state(init) {
fsm_transition(read_tex_comment(ps, consumer), init, '%')
transition(start_escaping, "\\")
transition(init, "~", str += ' ')
transition(start_escaping, '\\')
transition(init, '~', str += ' ')
transition(init, any_char, str += ch)
}
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())
}
fin();
......@@ -561,8 +583,9 @@ void read_tex_list(State& ps, Consumer& consumer) {
transition_if(before_first_item(), init, " \t\n")
}
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())
}
unstable_state(after_cmd) {
......@@ -611,14 +634,15 @@ void read_tex_tabular(State& ps, Consumer&& consumer) {
start();
state(init) {
fsm_transition(read_tex_comment(ps, builder), init, '%')
transition(start_escaping, "\\")
transition(start_escaping, '\\')
transition(init, "&", next_column())
transition(init, "~", str += ' ')
transition(init, any_char, str += ch)
}
state(start_escaping) {
transition(init, "\\", next_row())
transition(init, "%", str += '%')
transition(init, '\\', next_row())
transition(init, '%', str += '%')
transition(init, '_', str += '_')
fsm_epsilon(read_tex_command(ps, builder), after_cmd, any_char, consume_str())
}
unstable_state(after_cmd) {
......@@ -918,7 +942,7 @@ Out& operator<<(Out& out, href& x) {
template <class Out>
Out& operator<<(Out& out, experimental&) {
return out << "\\ :sup:`experimental`\\ ";
return out << " :sup:`experimental`";
}
} // namespace rst_ops
......@@ -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)
void entry(const std::string& section_name, char highlighting) {
......@@ -1050,27 +1085,57 @@ BEGIN_STATE(read_body)
print_block(".. ::", x.block);
}
void operator()(itemize& x) {
template <class T, class NextLine>
void print_list(T & x, NextLine next_line) {
out() << "\n\n";
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)
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';
}
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) {
size_t num = 1;
out() << "\n\n";
for (auto& i : x.items) {
auto next_line = [&](bool new_item) {
if (new_item)
out() << num++ << ". ";
for (auto& n : i.nodes)
visit(*this, n);
out() << '\n';
}
out() << '\n';
else
out() << " "; // TODO: support more than 10 items
};
print_list(x, next_line);
}
void operator()(tabular& x) {
......
......@@ -302,15 +302,15 @@ Blocking actors simply implement their behavior in the function body. The actor
is done once it returns from that function.
Event-based actors can either return a \lstinline^behavior^
\see{message-handler} that is used to initialize the actor or explicitly set
the initial behavior by calling \lstinline^self->become(...)^. Due to the
\see{message-handler} that is used to initialize the actor or explicitly set the
initial behavior by calling \lstinline^self->become(...)^. Due to the
asynchronous, event-based nature of this kind of actor, the function usually
returns immediately after setting a behavior (message handler) for the
\emph{next} incoming message. Hence, variables on the stack will be out of
scope once a message arrives. Managing state in function-based actors can be
done either via rebinding state with \lstinline^become^, using heap-located
data referenced via \lstinline^std::shared_ptr^ or by using the ``stateful
actor'' abstraction~\see{stateful-actor}.
\emph{next} incoming message. Hence, variables on the stack will be out of scope
once a message arrives. Managing state in function-based actors can be done
either via rebinding state with \lstinline^become^, using heap-located data
referenced via \lstinline^std::shared_ptr^ or by using the \textit{stateful
actor} abstraction~\see{stateful-actor}.
The following three functions implement the prototypes shown in~\sref{spawn}
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
inheriting from the three classes directly. The class
\lstinline^composed_behavior^ ensures that the behaviors are concatenated
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^
and \lstinline^Y^ both implement the interface
\emph{first} type in declaration order wins. For example, if \lstinline^X^ and
\lstinline^Y^ both implement the interface
\lstinline^replies_to<int,int>::with<int>^, only the handler implemented in
\lstinline^X^ is active.
......
......@@ -104,16 +104,16 @@ object \emph{before} initializing an actor system with it.
\subsection{Command Line Options and INI Configuration Files}
\label{system-config-options}
CAF organizes program options in categories and parses CLI arguments as well
as INI files. CLI arguments override values in the INI file which override
CAF organizes program options in categories and parses CLI arguments as well as
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
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}
We create a new ``global'' category in \lstinline^custom_options_}^. Each
following call to \lstinline^add^ then appends individual options to the
We create a new \lstinline^global^ category in \lstinline^custom_options_}^.
Each following call to \lstinline^add^ then appends individual options to 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
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
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
application to 42 with either \lstinline^--port=42^ (long name) or
\lstinline^-p 42^ (short name). The long option name is prefixed by the
application to 42 with either \lstinline^-p 42^ (short name) or
\lstinline^--port=42^ (long name). The long option name is prefixed by the
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
by the category, but have to be unique.
......@@ -138,18 +138,18 @@ simplicity. However, this is not required. For example,
values of the configuration are accessible with \lstinline^get_or^. Note that
all global options can omit the \lstinline^"global."^ prefix.
CAF adds the program options ``help'' (with short names \lstinline^-h^ and
\lstinline^-?^) as well as ``long-help'' to the ``global'' category.
CAF adds the program options \lstinline^help^ (with short names \lstinline^-h^
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
change the file name and path by passing \lstinline^--config-file=<path>^ on
the command line.
change the file name and path by passing \lstinline^--config-file=<path>^ on the
command line.
INI files are organized in categories. No value is allowed outside of a
category (no implicit ``global'' category). The parses uses the following
syntax:
INI files are organized in categories. No value is allowed outside of a category
(no implicit \lstinline^global^ category). The parses uses the following syntax:
\begin{tabular}{p{0.3\textwidth}p{0.65\textwidth}}
\begin{tabular}{ll}
\lstinline^key=true^ & is a boolean \\
\lstinline^key=1^ & is an integer \\
\lstinline^key=1.0^ & is an floating point number \\
......@@ -253,9 +253,10 @@ with \lstinline^std::string^.
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
of ``error'', ``warning'', ``info'', ``debug'', or ``trace'' (from least output
to most). Alternatively, setting the CMake variable \lstinline^CAF_LOG_LEVEL^
to 0, 1, 2, 3, or 4 (from least output to most) has the same effect.
of \lstinline^error^, \lstinline^warning^, \lstinline^info^, \lstinline^debug^,
or \lstinline^trace^ (from least output to most). Alternatively, setting the
CMake variable \lstinline^CAF_LOG_LEVEL^ to one of these values has the same
effect.
All logger-related configuration options listed here and in
\sref{system-config-options} are silently ignored if logging is disabled.
......@@ -266,7 +267,7 @@ All logger-related configuration options listed here and in
The output file is generated from the template configured by
\lstinline^logger-file-name^. This template supports the following variables.
\begin{tabular}{|p{0.2\textwidth}|p{0.75\textwidth}|}
\begin{tabular}{ll}
\hline
\textbf{Variable} & \textbf{Output} \\
\hline
......@@ -294,15 +295,15 @@ events via \lstinline^logger-file-format^ and
\lstinline^logger-console-format^. Note that format modifiers are not supported
at the moment. The recognized field identifiers are:
\begin{tabular}{|p{0.1\textwidth}|p{0.85\textwidth}|}
\begin{tabular}{ll}
\hline
\textbf{Character} & \textbf{Output} \\
\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
\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
\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
\texttt{F} & The file name. \\
\hline
......@@ -320,7 +321,7 @@ at the moment. The recognized field identifiers are:
\hline
\texttt{t} & ID of the current thread. \\
\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
\texttt{\%} & A single percent sign. \\
\hline
......
......@@ -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
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
follows the C++ philosophy ``building the highest abstraction possible without
sacrificing performance''.
follows the C++ philosophy \textit{building the highest abstraction possible
without sacrificing performance}.
\subsection{Terminology}
......@@ -41,10 +41,10 @@ differences when comparing CAF to other actor frameworks.
\subsubsection{Dynamically Typed Actor}
A dynamically typed actor accepts any kind of message and dispatches on its
content dynamically at the receiver. This is the ``traditional'' messaging
style found in implementations like Erlang or Akka. The upside of this approach
is (usually) faster prototyping and less code. This comes at the cost of
requiring excessive testing.
content dynamically at the receiver. This is the traditional messaging style
found in implementations like Erlang or Akka. The upside of this approach is
(usually) faster prototyping and less code. This comes at the cost of requiring
excessive testing.
\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