ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
paragraphs.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of sub-namespace #alib::lang::format of module \alib_basecamp of
4 * the \aliblong.
5 *
6 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
7 * Published under \ref mainpage_license "Boost Software License".
8 **************************************************************************************************/
9#ifndef HPP_ALIB_LANG_FORMAT_PARAGRAPHS
10#define HPP_ALIB_LANG_FORMAT_PARAGRAPHS 1
11
12#if !defined (HPP_ALIB_LANG_FORMAT_FORMATTER_PYTHONSTYLE)
14#endif
15#if !defined (_GLIBCXX_STACK) && !defined(_STACK_)
16 #include <stack>
17#endif
18
19namespace alib {
20 namespace results { class Exception; }
21
22namespace lang::format {
23 /** ************************************************************************************************
24 * This class is used to format textual output, like console output.
25 *
26 * One central \b static method is #Format, which format a "paragraph" that starts at a
27 * certain index of the managed \b %AString buffer and reaches to its end.
28 *
29 * When an instance of the class is created, the members of the class provide the text
30 * buffer as well as the other parameters which are needed for the static method. With methods
31 * #Add, member #Formatter is used to append the given parameters and then the new paragraph is
32 * formatted using static method #Format.<br>
33 * This way, a longer text might be built by repetitive calls.
34 **************************************************************************************************/
36 {
37 // #############################################################################################
38 // Fields
39 // #############################################################################################
40 protected:
41 /** Internal buffer, used for field #Paragraphs, if no external string object was given. */
43
44 public:
45 /** A reference to the text buffer. Either refers to otherwise protected field #text or to
46 * what was given in alternative construction. */
48
49 /**
50 * The formatter to use.
51 * In the constructor, this shared pointer is initialized with the
52 * - \alib{lang::format;Formatter::GetDefault;ALib Default Formatter},
53 * in the case that this object's template character type equals \ref alib::character, or
54 * - A shared pointer to a newly created formatter object of corresponding character type
55 * otherwise.
56 */
58
59 /** Used as parameter \p{lineWidth} of static method invocations. */
61
62 /**
63 * Used as parameter \p{justifyChar} of static method invocations.
64 * Usually set to <c>' '</c> to enable paragraph width justification.<br>
65 * Defaults to <c>'\\0'</c> which disables it.
66 */
68
69 /**
70 * Used to detect special commands given with format strings.
71 * \see Method #AddMarked for more information.
72 *
73 * Defaults to <c>'@'</c>.
74 */
76
77 /** The bullet used with increasing bullet depths. */
78 std::vector<character> MarkerBullets = {'*', '-', '*', '-', '*', '-'};
79
80
81#if defined(ALIB_DOX)
82 /**
83 * Used as parameter \p{indent} of static method invocations.<br>
84 * The indent string of the first line.
85 *
86 * This field can either be manipulated by direct access or preferably with
87 * overloaded methods#PushIndent and #PopIndent.
88 *
89 * \note For technical reasons the template parameters of this member's type are missing
90 * in this documentation.
91 * In the source code, the type iss <b>%TLocalString<TChar,64></b>.
92 */
93 TLocalString IndentFirstLine;
94
95 /**
96 * Used as parameter \p{indent} of static method invocations.<br>
97 * The indent string of text lines, excluding the first line.
98 *
99 * This field can either be manipulated by direct access or preferably with
100 * overloaded methods#PushIndent and #PopIndent.
101 *
102 * \note For technical reasons the template parameters of this member's type are missing
103 * in this documentation.
104 * In the source code, the type iss <b>%TLocalString<TChar,64></b>.
105 */
106 TLocalString IndentOtherLines;
107#else
108 // As of 2017/4: When this goes to doxygen type TLocalString<TChar,64> appears
109 // in the type list, e.g. in the inheritance graph of class TString.
112#endif
113
114 /**
115 * The stack of indent sub-string sizes in string #IndentFirstLine.
116 * Used with #PushIndent and #PopIndent.
117 */
118 std::stack<integer> IndentSizesFirstLine;
119
120 /**
121 * The stack of indent sub-string sizes in string #IndentOtherLines.
122 * Used with #PushIndent and #PopIndent.
123 */
124 std::stack<integer> IndentSizesOtherLines;
125
126 /**
127 * This field is increased whenever a line of text added is longer than its current
128 * value.
129 * Might be used by to detect the maximum line width when field #LineWidth is set to \c 0
130 * and hence no auto wrap is done.
131 */
133
134
135 protected:
136 /** Internally reused list of boxes. */
138
139 /** Buffer for processing marked text. */
141
142 /** Buffer for processing marked text. */
144
145 // #############################################################################################
146 // Constructor/Destructor
147 // #############################################################################################
148 public:
149 /**
150 * Parameterless constructor. Internal buffer #text will be used with reference #Buffer.
151 */
153
154 /**
155 * Alternative constructor that accepts an external buffer to use.
156 * @param externalBuffer The external buffer to use and fill.
157 */
158 ALIB_API Paragraphs( AString& externalBuffer );
159
160 // #############################################################################################
161 // Interface
162 // #############################################################################################
163 public:
164 /** ****************************************************************************************
165 * Formats one or more paragraphs (separated by \b NewLine symbols) with three optional
166 * features:
167 *
168 * - Wrapping of lines longer than lineWidth (word wrap)
169 * - Justify the text, which here means "full justification", i.e. format the text to have
170 * lines of the exact same width.
171 * - Adding an indentation to each line with an optionally different indentation for
172 * the first line after a \b NewLine symbol and subsequent ones.
173 *
174 * The paragraph starts at \p{startIdx} and all of the rest of the string is treated
175 * as one paragraph. New-line character sequences found within the paragraph are considered
176 * manual line ends. Hence, no block formatting for lines ending with a new line character
177 * is performed.
178 *
179 * The method is static and hence can be used with arbitrary buffers.
180 * Non-static methods #Add invoke this methods after adding the given content
181 * to the internal buffer. Furthermore, convenience functions and corresponding member
182 * variables, simplify the use of this method, when indirectly used through an instance of
183 * the class.
184 *
185 * @param text The text containing the paragraph to format.
186 * @param startIdx The start of the paragraph.
187 * @param lineWidth The width of the line. If \c 0 or negative, no line wrap is
188 * performed.
189 * @param justifyChar If this is unequal to <c>'\0'</c> it denotes the fill
190 * character used to justify the paragraph.
191 * Defaults to <c>'\0'</c>, which disables justification.
192 * @param[out] maxLineWidth Provides the maximum width of all text lines written.
193 * @param indentFirstLine The indent string of the first line. Defaults to \c nullptr.
194 * @param indentOtherLines The indent string of subsequent lines. Defaults to \c nullptr.
195 *******************************************************************************************/
197 static
198 void Format( AString& text,
199 integer startIdx,
200 integer lineWidth,
201 character justifyChar,
202 integer& maxLineWidth,
203 const String& indentFirstLine = nullptr,
204 const String& indentOtherLines= nullptr );
205
206 /** ****************************************************************************************
207 * Appends the given objects \p{args} to the internal #Buffer with the help of member
208 * #Formatter. Then, static method #Format is invoked, providing our public
209 * members as parameters. Finally, a newline sequence is added to #Buffer, but only if the
210 * buffer is not empty and if it does not already end with a newline sequence.
211 *
212 * @throws <b>alib::lang::format::FMTExceptions</b><br>
213 * Rethrows exceptions from the formatter caused by errors in provided \p{args}.
214 *
215 * @param args The list of arguments to add.
216 *******************************************************************************************/
218 void Add( Boxes& args );
219
220 /** ****************************************************************************************
221 * Variadic template argument version of #Add.
222 *
223 * @param args The variadic list of arguments to add.
224 * @return A reference to ourselves to allow concatenated calls.
225 ******************************************************************************************/
226 template <typename... BoxedObjects>
227 Paragraphs& Add( const BoxedObjects&... args )
228 {
229 boxes.clear();
230 boxes.Add( args... );
231 Add( boxes );
232 return *this;
233 }
234
235 /** ****************************************************************************************
236 * This method implements a pre-processing of the text prior to #Add paragraphs found in
237 * the text.
238 *
239 * The pre-processing is quite simple. Its purpose is to allow longer strings (e.g. loaded
240 * from a resource pool) with multiple paragraphs to be formatted by embedded escape
241 * sequences to include indents and nested bullet schemes.
242 *
243 * The escape sequences begin with the character stored in field #MarkerChar, which defaults
244 * to <c>'@'</c>. The following table documents the sequences:
245 *
246 * Sequence | Description
247 * ---------|------------------------------------------------------------------------
248 * \@@ | Inserts the marker character itself.
249 * \@>> | Indent text by two spaces
250 * \@<< | Un-indent text by two spaces
251 * \@*> | Increases bullet level.
252 * \@<* | Decreases bullet level
253 * \@P | Inserts a new line (like '\n') but without ending the current and starting a new bullet point.
254 * \@HLc | Inserts a horizontal line of width #LineWidth using \p{c} as fill character.
255 *
256 * The nested bullet point characters are received from vector #MarkerBullets.
257 *
258 * @throws <b>alib::lang::format::FMTExceptions</b>
259 * - \alib{lang::format::FMTExceptions;UnknownMarker}
260 * - \alib{lang::format::FMTExceptions;EndmarkerWithoutStart}
261 * - Rethrows formatter exceptions occurring due to errors in provided \p{args}.
262 *
263 * @param args The list of arguments to add.
264 ******************************************************************************************/
266 void AddMarked( Boxes& args );
267
268 /** ****************************************************************************************
269 * Variadic template argument version of #AddMarked.
270 *
271 * @throws <b>alib::lang::format::FMTExceptions</b>
272 * - \alib{lang::format::FMTExceptions;UnknownMarker}
273 * - \alib{lang::format::FMTExceptions;EndmarkerWithoutStart}
274 *
275 * @param args The variadic list of arguments to add.
276 * @return A reference to ourselves to allow concatenated calls.
277 ******************************************************************************************/
278 template <typename... BoxedObjects>
279 Paragraphs& AddMarked( const BoxedObjects&... args )
280 {
281 boxes.clear();
282 boxes.Add( args... );
283 AddMarked( boxes );
284 return *this;
285 }
286
287 /** ****************************************************************************************
288 * Removes the last new line character at the end of the #Buffer.
289 *
290 * @return A reference to the text object.
291 ******************************************************************************************/
293 {
294 if( Buffer.EndsWith( NewLine() ) )
295 Buffer.template DeleteEnd<false>( NewLine().Length() );
296 return Buffer;
297 }
298
299 /** ****************************************************************************************
300 * Clears field #Buffer.
301 *
302 * @return A reference to ourselves to allow concatenated calls.
303 ******************************************************************************************/
305 Paragraphs& Clear();
306
307
308 /** ****************************************************************************************
309 * Add a given number of characters (default is spaces) to the indentation strings
310 * #IndentFirstLine and #IndentOtherLines.
311 *
312 * Use #PopIndent to remove the indent.
313 *
314 * @param qty The quantity of characters to add or remove
315 * @param fillChar The character (used only if \p{qty} is positive).
316 * @return A reference to ourselves to allow concatenated calls.
317 ******************************************************************************************/
319 Paragraphs& PushIndent( uinteger qty, character fillChar = ' ' );
320
321 /** ****************************************************************************************
322 * Add the given strings to members #IndentFirstLine and #IndentOtherLines.
323 *
324 * @param indentFirstLine The string to add to the current indentation stored in
325 * #IndentFirstLine.
326 * @param indentOtherLines The string to add to the current indentation stored in
327 * #IndentOtherLines.<br>
328 * Defaults to \b NullString, which sets it to the same value as
329 * \p{indentFirstLine}.
330 * @return A reference to ourselves to allow concatenated calls.
331 ******************************************************************************************/
333 Paragraphs& PushIndent( const String& indentFirstLine,
334 const String& indentOtherLines=nullptr);
335
336 /** ****************************************************************************************
337 * Removes the most recently added indent.
338 * @return A reference to ourselves to allow concatenated calls.
339 ******************************************************************************************/
342 };
343
344}} // namespace [alib::lang::format]
345
346#endif // HPP_ALIB_LANG_FORMAT_PARAGRAPHS
ALIB_API void AddMarked(Boxes &args)
std::stack< integer > IndentSizesOtherLines
ALIB_API Paragraphs & PushIndent(uinteger qty, character fillChar=' ')
std::vector< character > MarkerBullets
Paragraphs & Add(const BoxedObjects &... args)
ALIB_API Paragraphs & Clear()
ALIB_API Paragraphs & PopIndent()
std::stack< integer > IndentSizesFirstLine
Paragraphs & AddMarked(const BoxedObjects &... args)
ALIB_API void Add(Boxes &args)
bool EndsWith(const TString &needle) const
Definition string.hpp:847
#define ALIB_API
Definition alib.hpp:538
platform_specific integer
Definition integers.hpp:50
platform_specific uinteger
Definition integers.hpp:56
Definition alib.cpp:57
lang::Exception Exception
Type alias in namespace alib.
constexpr CString NewLine()
Definition cstring.hpp:528
strings::TFormat< character > Format
Type alias in namespace alib.
std::shared_ptr< lang::format::Formatter > SPFormatter
characters::character character
Type alias in namespace alib.