/** * Many different Futility's commands need to output lists of items * separated by commas, each item possibly containing comments in * the parentheses (also separated by commas). This class provides necessary * functionality. * Copyright 2022 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * * Acedia is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License, or * (at your option) any later version. * * Acedia is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Acedia. If not, see . */ class ListBuilder extends AcediaObject; /** * # `ListBuilder` * * Many different Futility's commands need to output lists of items * separated by commas, each item possibly containing comments in * the parentheses (also separated by commas). This class provides necessary * functionality. * Example of such list: * "item1, item2 (comment1, comment2), item3 (just_comment), item4, item5". * * ## Usage * * 1. Use `Item()` method to add new items (they will be listed after * list header + whitespace, separated by commas and whitespaces ", "); * 2. Use `Comment()` method to specify comments for the item (they will * be listed between the paranthesisasd after the corresponding item). * Comments will be added to the last item, added via `Item()` call. * If no items were added, specified comment will be discarded. * 3. Use `Get()` / `GetMutable()` methods to return list built so far. * 4. Use `Reset()` to forget all the items and comments * (but not list header), allowing to start forming a new report. */ // Represents one item + all of its comments struct FutilityListItem { var Text itemTitle; var array comments; }; // All items recorded reported thus far var private array collectedItems; var const int TCAUSE, TTARGET, TCOMMA, TSPACE, TCOMMA_SPACE; var const int TSPACE_OPEN_PARANSIS, TCLOSE_PARANSIS; protected function Finalizer() { Reset(); } /** * Adds new `item` to the current report. * * @param item Text to be included into the report as an item. * One should avoid using commas or parantheses inside an `item`, but * this limitation is not checked or prevented by `Item()` method. * Does nothing if `item == none` (`Comment()` will continue adding * comments to the previously added item). * @return Reference to the caller `ListBuilder` to allow for method chaining. */ public final function ListBuilder Item(BaseText item) { local FutilityListItem newItem; if (item == none) { return self; } newItem.itemTitle = item.Copy(); collectedItems[collectedItems.length] = newItem; return self; } /** * Adds new `comment` to the last added `item` in the current report. * * @param comment Text to be included into the report as a comment to * the last added item. One should avoid using commas or parantheses inside * a `comment`, but this limitation is not checked or prevented by * `Comment()` method. * Does nothing if `comment == none` or no items were added thuis far. * @return Reference to the caller `ListBuilder` to allow for method chaining. */ public final function ListBuilder Comment(BaseText comment) { local array itemComments; if (comment == none) return self; if (collectedItems.length == 0) return self; itemComments = collectedItems[collectedItems.length - 1].comments; itemComments[itemComments.length] = comment.Copy(); collectedItems[collectedItems.length - 1].comments = itemComments; return self; } /** * Returns list, assembled from items and their comment specified so far as * `Text`. * * @see `GetMutable()`, `IntoText()`, `IntoMutableText()` * * @return Assembled list of specified items with specified comments. */ public final function Text Get() { local MutableText mutableResult; mutableResult = GetMutable(); if (mutableResult != none) { return mutableResult.IntoText(); } return none; } /** * Returns list, assembled from items and their comment specified so far as * `MutableText`. * * @see `Get()`, `IntoText()`, `IntoMutableText()` * * @return Assembled list of specified items with specified comments. */ public final function MutableText GetMutable() { local int i, j; local MutableText result; local array itemComments; if (collectedItems.length == 0) { return _.text.Empty(); } result = _.text.Empty(); for (i = 0; i < collectedItems.length; i += 1) { if (i > 0) { result.Append(T(TCOMMA_SPACE)); } result.Append(collectedItems[i].itemTitle); itemComments = collectedItems[i].comments; if (itemComments.length > 0) { result.Append(T(TSPACE_OPEN_PARANSIS)); } for (j = 0; j < itemComments.length; j += 1) { if (j > 0) { result.Append(T(TCOMMA_SPACE)); } result.Append(itemComments[j]); } if (itemComments.length > 0) { result.Append(T(TCLOSE_PARANSIS)); } } return result; } /** * Converts caller `Listbuilder` into list, assembled from items and their * comment specified so far as `Text`. * Caller `ListBuilder()` is atuomatically deallocated. * * @see `Get()`, `GetMutable()`, `IntoMutableText()` * * @return Assembled list of specified items with specified comments. */ public final function Text IntoText() { local Text result; result = Get(); FreeSelf(); return result; } /** * Converts caller `Listbuilder` into list, assembled from items and their * comment specified so far as `MutableText`. * Caller `ListBuilder()` is atuomatically deallocated. * * @see `Get()`, `GetMutable()`, `IntoText()` * * @return Assembled list of specified items with specified comments. */ public final function MutableText IntoMutableText() { local MutableText result; result = GetMutable(); FreeSelf(); return result; } /** * Forgets all items or comments specified for the caller `ListBuilder` so far, * allowing to start forming a new report. Does not reset template header, * specified in the `Initialize()` method. * * @return Reference to the caller `ListBuilder` to allow for method chaining. */ public final function ListBuilder Reset() { local int i; for (i = 0; i < collectedItems.length; i += 1) { _.memory.Free(collectedItems[i].itemTitle); _.memory.FreeMany(collectedItems[i].comments); } collectedItems.length = 0; return self; } defaultproperties { TCAUSE = 0 stringConstants(0) = "%%instigator%%" TTARGET = 1 stringConstants(1) = "%%target%%" TCOMMA = 2 stringConstants(2) = "," TCOMMA_SPACE = 3 stringConstants(3) = ", " TSPACE_OPEN_PARANSIS = 4 stringConstants(4) = " (" TCLOSE_PARANSIS = 5 stringConstants(5) = ")" }