ALib C++ Library
Library Version: 2412 R0
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#pragma once
16#include <stack>
17
18namespace alib { namespace results { class Exception; }
19namespace lang::format {
20//==================================================================================================
21/// This class is used to format textual output, like console output.
22///
23/// One central \b static method is #Format, which formats a "paragraph" that starts at a
24/// certain index of the managed \b %AString buffer and reaches to its end.
25///
26/// When an instance of the class is created, the members of the class provide the text
27/// buffer as well as the other parameters which are needed for the static method. With methods
28/// #Add, member #Formatter is used to append the given parameters and then the new paragraph is
29/// formatted using the static method #Format.<br>
30/// This way, a longer text might be built by repetitive calls.
31//==================================================================================================
33{
34 // #############################################################################################
35 // Fields
36 // #############################################################################################
37 protected:
38 /// Allocator used for internal container types.
40
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 /// The formatter to use.
50 /// In the constructor, this shared pointer is initialized with the
51 /// - \alib{lang::format;Formatter::Default;ALib Default Formatter},
52 /// in the case that this object's template character type equals \ref alib::character, or
53 /// - A shared pointer to a newly created formatter object of a corresponding character type
54 /// otherwise.
56
57 /// Used as parameter \p{lineWidth} of static method invocations.
59
60 /// Used as parameter \p{justifyChar} of static method invocations.
61 /// Usually set to <c>' '</c> to enable paragraph width justification.<br>
62 /// Defaults to <c>'\\0'</c> which disables it.
64
65 /// Used to detect special commands given with format strings.
66 /// \see Method #AddMarked for more information.
67 ///
68 /// Defaults to <c>'@'</c>.
70
71 /// The bullet used with increasing bullet depths.
72 /// Defaults to <c>'*'</c>, <c>'-'</c>, <c>'*'</c>, <c>'-'</c>, <c>'*'</c>, <c>'-'</c>.
74
75 /// Used as parameter \p{indent} of static method invocations.<br>
76 /// The indent string of the first line.
77 ///
78 /// This field can either be manipulated by direct access or preferably with
79 /// overloaded methods #PushIndent and #PopIndent.
81
82 /// Used as parameter \p{indent} of static method invocations.<br>
83 /// The indent string of text lines, excluding the first line.
84 ///
85 /// This field can either be manipulated by direct access or preferably with
86 /// overloaded methods #PushIndent and #PopIndent.
88
89 /// The stack of indent substring sizes in string #IndentFirstLine.
90 /// Used with #PushIndent and #PopIndent.
91 std::stack<integer, StdDequeMono<integer>> IndentSizesFirstLine;
92
93 /// The stack of indent substring sizes in string #IndentOtherLines.
94 /// Used with #PushIndent and #PopIndent.
95 std::stack<integer, StdDequeMono<integer>> IndentSizesOtherLines;
96
97 /// This field is increased whenever a line of text added is longer than its current
98 /// value.
99 /// Might be used by to detect the maximum line width when field #LineWidth is set to \c 0
100 /// and hence no auto wrap is done.
102
103
104 protected:
105 /// Internally reused list of boxes.
107
108 /// Buffer for processing marked text.
110
111 /// Buffer for processing marked text.
113
114 // #############################################################################################
115 // Constructor/Destructor
116 // #############################################################################################
117 public:
118 /// Parameterless constructor.
119 /// Internal buffer #text will be used with reference #Buffer.
120 /// For field #Formatter, \alib{lang::format;Formatter::Default} will be used.
122
123 /// Alternative constructor that accepts an external buffer to use.
124 /// @param externalBuffer The external buffer to use and fill.
125 ALIB_API Paragraphs( AString& externalBuffer );
126
127 // #############################################################################################
128 // Interface
129 // #############################################################################################
130 public:
131 //==============================================================================================
132 /// Formats one or more paragraphs (separated by \b NewLine symbols) with three optional
133 /// features:
134 ///
135 /// - Wrapping of lines longer than lineWidth (word wrap)
136 /// - Justify the text, which here means "full justification", i.e., format the text to have
137 /// lines of the exact same width.
138 /// - Adding an indentation to each line with an optionally different indentation for the
139 /// first line after a \b NewLine symbol and subsequent ones.
140 ///
141 /// The paragraph starts at \p{startIdx} and all of the rest of the string is treated
142 /// as one paragraph. New-line character sequences found within the paragraph are considered
143 /// manual line ends. Hence, no block formatting for lines ending with a new line character
144 /// is performed.
145 ///
146 /// The method is static and hence can be used with arbitrary buffers.
147 /// Non-static methods #Add invoke this method after adding the given content
148 /// to the internal buffer. Furthermore, convenience functions and corresponding member
149 /// variables, simplify the use of this method, when indirectly used through an instance of
150 /// the class.
151 ///
152 /// @param text The text containing the paragraph to format.
153 /// @param startIdx The start of the paragraph.
154 /// @param lineWidth The width of the line. If \c 0 or negative, no line wrap is
155 /// performed.
156 /// @param justifyChar If this is unequal to <c>'\0'</c> it denotes the fill
157 /// character used to justify the paragraph.
158 /// Defaults to <c>'\0'</c>, which disables justification.
159 /// @param[out] maxLineWidth Provides the maximum width of all text lines written.
160 /// @param indentFirstLine The indent string of the first line. Defaults to \c nullptr.
161 /// @param indentOtherLines The indent string of subsequent lines. Defaults to \c nullptr.
162 //==============================================================================================
164 static
165 void Format( AString& text,
166 integer startIdx,
167 integer lineWidth,
168 character justifyChar,
169 integer& maxLineWidth,
170 const String& indentFirstLine = nullptr,
171 const String& indentOtherLines= nullptr );
172
173 //==============================================================================================
174 /// Appends the given objects \p{args} to the internal #Buffer with the help of member
175 /// #Formatter. Then, static method #Format is invoked, providing our public
176 /// members as parameters. Finally, a newline sequence is added to #Buffer, but only if the
177 /// buffer is not empty and if it does not already end with a newline sequence.
178 ///
179 /// @throws <b>alib::lang::format::FMTExceptions</b><br>
180 /// Rethrows exceptions from the formatter caused by errors in provided \p{args}.
181 ///
182 /// @param args The list of arguments to add.
183 //==============================================================================================
184 template<typename TAllocatorArgs>
186
187 //==============================================================================================
188 /// Variadic template argument version of #Add.
189 ///
190 /// @param args The variadic list of arguments to add.
191 /// @return A reference to ourselves to allow concatenated calls.
192 //==============================================================================================
193 template <typename... BoxedObjects>
194 Paragraphs& Add( const BoxedObjects&... args )
195 {
196 boxes.clear();
197 boxes.Add( args... );
198 Add( boxes );
199 return *this;
200 }
201
202 //==============================================================================================
203 /// This method implements a pre-processing of the text before #Add paragraphs found in
204 /// the text.
205 ///
206 /// The pre-processing is quite simple. Its purpose is to allow longer strings (e.g., loaded
207 /// from a resource pool) with multiple paragraphs to be formatted by embedded escape
208 /// sequences to include indents and nested bullet schemes.
209 ///
210 /// The escape sequences begin with the character stored in field #MarkerChar, which defaults
211 /// to <c>'@'</c>. The following table documents the sequences:
212 ///
213 /// Sequence | Description
214 /// ---------|------------------------------------------------------------------------
215 /// \@@ | Inserts the marker character itself.
216 /// \@>> | Indent text by two spaces
217 /// \@<< | Un-indent text by two spaces
218 /// \@*> | Increases bullet level.
219 /// \@<* | Decreases bullet level
220 /// \@P | Inserts a new line (like '\n') but without ending the current and starting a new bullet point.
221 /// \@HLc | Inserts a horizontal line of width #LineWidth using \p{c} as fill character.
222 ///
223 /// The nested bullet point characters are received from vector #MarkerBullets.
224 ///
225 /// @throws <b>alib::lang::format::FMTExceptions</b>
226 /// - \alib{lang::format::FMTExceptions;UnknownMarker}
227 /// - \alib{lang::format::FMTExceptions;EndmarkerWithoutStart}
228 /// - Rethrows formatter exceptions occurring due to errors in provided \p{args}.
229 ///
230 /// @param args The list of arguments to add.
231 //==============================================================================================
232 template<typename TAllocatorArgs>
234
235 //==============================================================================================
236 /// Variadic template argument version of #AddMarked.
237 ///
238 /// @throws <b>alib::lang::format::FMTExceptions</b>
239 /// - \alib{lang::format::FMTExceptions;UnknownMarker}
240 /// - \alib{lang::format::FMTExceptions;EndmarkerWithoutStart}
241 ///
242 /// @param args The variadic list of arguments to add.
243 /// @return A reference to ourselves to allow concatenated calls.
244 //==============================================================================================
245 template <typename... BoxedObjects>
246 Paragraphs& AddMarked( const BoxedObjects&... args )
247 {
248 boxes.clear();
249 boxes.Add( args... );
250 AddMarked( boxes );
251 return *this;
252 }
253
254 //==============================================================================================
255 /// Removes the last new line character at the end of the #Buffer.
256 ///
257 /// @return A reference to the text object.
258 //==============================================================================================
260 {
261 if( Buffer.EndsWith( NEW_LINE ) )
262 Buffer.template DeleteEnd<NC>( NEW_LINE.Length() );
263 return Buffer;
264 }
265
266 //==============================================================================================
267 /// Clears field #Buffer.
268 ///
269 /// @return A reference to ourselves to allow concatenated calls.
270 //==============================================================================================
272 Paragraphs& Clear();
273
274
275 //==============================================================================================
276 /// Add a given number of characters (default is spaces) to the indentation strings
277 /// #IndentFirstLine and #IndentOtherLines.
278 ///
279 /// Use #PopIndent to remove the indent.
280 ///
281 /// @param qty The quantity of characters to add or remove
282 /// @param fillChar The character (used only if \p{qty} is positive).
283 /// @return A reference to ourselves to allow concatenated calls.
284 //==============================================================================================
286 Paragraphs& PushIndent( uinteger qty, character fillChar = ' ' );
287
288 //==============================================================================================
289 /// Add the given strings to members #IndentFirstLine and #IndentOtherLines.
290 ///
291 /// @param indentFirstLine The string to add to the current indentation stored in
292 /// #IndentFirstLine.
293 /// @param indentOtherLines The string to add to the current indentation stored in
294 /// #IndentOtherLines.<br>
295 /// Defaults to \b NULL_STRING, which sets it to the same value as
296 /// \p{indentFirstLine}.
297 /// @return A reference to ourselves to allow concatenated calls.
298 //==============================================================================================
300 Paragraphs& PushIndent( const String& indentFirstLine,
301 const String& indentOtherLines=nullptr);
302
303 //==============================================================================================
304 /// Removes the most recently added indent.
305 /// @return A reference to ourselves to allow concatenated calls.
306 //==============================================================================================
309}; // class Paragraphs
310
311#if !DOXYGEN
318#endif // !DOXYGEN
319}} // namespace [alib::lang::format]
320
321#endif // HPP_ALIB_LANG_FORMAT_PARAGRAPHS
322
TBoxes & Add()
Definition boxes.inl:74
std::stack< integer, StdDequeMono< integer > > IndentSizesFirstLine
ALIB_API Paragraphs & PushIndent(uinteger qty, character fillChar=' ')
std::stack< integer, StdDequeMono< integer > > IndentSizesOtherLines
MonoAllocator allocator
Allocator used for internal container types.
AString markedBuffer
Buffer for processing marked text.
Paragraphs & Add(const BoxedObjects &... args)
BoxesMA boxes
Internally reused list of boxes.
void Add(boxing::TBoxes< TAllocatorArgs > &args)
void AddMarked(boxing::TBoxes< TAllocatorArgs > &args)
size_t markerBulletLevel
Buffer for processing marked text.
ALIB_API Paragraphs & Clear()
ALIB_API Paragraphs & PopIndent()
Paragraphs & AddMarked(const BoxedObjects &... args)
StdVectorMono< character > MarkerBullets
AString text
Internal buffer, used for field Paragraphs, if no external string object was given.
integer LineWidth
Used as parameter lineWidth of static method invocations.
constexpr integer Length() const
Definition string.hpp:326
bool EndsWith(const TString &needle) const
Definition string.hpp:854
#define ALIB_API
Definition alib.hpp:639
platform_specific integer
Definition integers.hpp:43
platform_specific uinteger
Definition integers.hpp:47
Definition alib.cpp:69
lang::Exception Exception
Type alias in namespace alib.
std::vector< T, SCAMono< T > > StdVectorMono
Type alias in namespace alib.
Definition stdvector.hpp:21
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
Definition cstring.hpp:580
strings::TFormat< character > Format
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.