diff options
Diffstat (limited to 'support/arara/source/src/main/kotlin/org/islandoftex/arara/utils/DisplayUtils.kt')
-rw-r--r-- | support/arara/source/src/main/kotlin/org/islandoftex/arara/utils/DisplayUtils.kt | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/support/arara/source/src/main/kotlin/org/islandoftex/arara/utils/DisplayUtils.kt b/support/arara/source/src/main/kotlin/org/islandoftex/arara/utils/DisplayUtils.kt new file mode 100644 index 0000000000..213a9a21c3 --- /dev/null +++ b/support/arara/source/src/main/kotlin/org/islandoftex/arara/utils/DisplayUtils.kt @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: BSD-3-Clause +package org.islandoftex.arara.utils + +import org.islandoftex.arara.Arara +import org.islandoftex.arara.configuration.AraraSpec +import org.islandoftex.arara.configuration.ConfigurationUtils +import org.islandoftex.arara.filehandling.FileHandlingUtils +import org.islandoftex.arara.localization.LanguageController +import org.islandoftex.arara.localization.Messages +import org.islandoftex.arara.model.AraraException +import org.islandoftex.arara.ruleset.Conditional +import org.slf4j.LoggerFactory + +/** + * Implements display utilitary methods. + * + * @author Island of TeX + * @version 5.0 + * @since 4.0 + */ +object DisplayUtils { + // the application messages obtained from the + // language controller + private val messages = LanguageController + + // get the logger context from a factory + private val logger = LoggerFactory.getLogger(DisplayUtils::class.java) + + /** + * The length of the longest result match as integer. + */ + private val longestMatch: Int = listOf( + messages.getMessage(Messages.INFO_LABEL_ON_SUCCESS), + messages.getMessage(Messages.INFO_LABEL_ON_FAILURE), + messages.getMessage(Messages.INFO_LABEL_ON_ERROR)) + .map { it.length }.max()!! + /** + * If the longest match is longer than the width, then it will be truncated + * to this length. + */ + private const val shortenedLongestMatch = 10 + + /** + * The default terminal width defined in the settings. + */ + private val width: Int + get() = Arara.config[AraraSpec.Application.width] + + /** + * Checks if the execution is in dry-run mode. + */ + private val isDryRunMode: Boolean + get() = Arara.config[AraraSpec.Execution.dryrun] + + /** + * Checks if the execution is in verbose mode. + */ + private val isVerboseMode: Boolean + get() = Arara.config[AraraSpec.Execution.verbose] + + /** + * The application path. + */ + private val applicationPath: String + get() = try { + ConfigurationUtils.applicationPath.toString() + } catch (ae: AraraException) { + "[unknown application path]" + } + + /** + * Displays the short version of the current entry in the terminal. + * + * @param name Rule name. + * @param task Task name. + */ + private fun buildShortEntry(name: String, task: String) { + val result = if (longestMatch >= width) + shortenedLongestMatch + else + longestMatch + val space = width - result - 1 + val line = "($name) $task ".abbreviate(space - "... ".length) + print(line.padEnd(space, '.') + " ") + } + + /** + * Displays the short version of the current entry result in the terminal. + * + * @param value The boolean value to be displayed. + */ + private fun buildShortResult(value: Boolean) { + val result = longestMatch + println(getResult(value).padStart(result)) + } + + /** + * Displays the current entry result in the terminal. + * + * @param value The boolean value to be displayed. + */ + fun printEntryResult(value: Boolean) { + Arara.config[AraraSpec.UserInteraction.displayLine] = false + Arara.config[AraraSpec.UserInteraction.displayResult] = true + Arara.config[AraraSpec.Execution.status] = if (value) 0 else 1 + logger.info( + messages.getMessage( + Messages.LOG_INFO_TASK_RESULT + ) + " " + getResult(value) + ) + if (!isDryRunMode) { + if (!isVerboseMode) { + buildShortResult(value) + } else { + buildLongResult(value) + } + } + } + + /** + * Displays a long version of the current entry result in the terminal. + * + * @param value The boolean value to be displayed + */ + private fun buildLongResult(value: Boolean) { + val width = width + println("\n" + (" " + getResult(value)).padStart(width, '-')) + } + + /** + * Displays the current entry in the terminal. + * + * @param name The rule name. + * @param task The task name. + */ + fun printEntry(name: String, task: String) { + logger.info( + messages.getMessage( + Messages.LOG_INFO_INTERPRET_TASK, + task, + name + ) + ) + Arara.config[AraraSpec.UserInteraction.displayLine] = true + Arara.config[AraraSpec.UserInteraction.displayResult] = false + if (!isDryRunMode) { + if (!isVerboseMode) { + buildShortEntry(name, task) + } else { + buildLongEntry(name, task) + } + } else { + buildDryRunEntry(name, task) + } + } + + /** + * Displays a long version of the current entry in the terminal. + * + * @param name Rule name. + * @param task Task name. + */ + private fun buildLongEntry(name: String, task: String) { + if (Arara.config[AraraSpec.UserInteraction.displayRolling]) { + addNewLine() + } else { + Arara.config[AraraSpec.UserInteraction.displayRolling] = true + } + println(displaySeparator()) + println("($name) $task".abbreviate(width)) + println(displaySeparator()) + } + + /** + * Displays a dry-run version of the current entry in the terminal. + * + * @param name The rule name. + * @param task The task name. + */ + private fun buildDryRunEntry(name: String, task: String) { + if (Arara.config[AraraSpec.UserInteraction.displayRolling]) { + addNewLine() + } else { + Arara.config[AraraSpec.UserInteraction.displayRolling] = true + } + println("[DR] ($name) $task".abbreviate(width)) + println(displaySeparator()) + } + + /** + * Displays the exception in the terminal. + * + * @param exception The exception object. + */ + fun printException(exception: AraraException) { + Arara.config[AraraSpec.UserInteraction.displayException] = true + Arara.config[AraraSpec.Execution.status] = 2 + + val display = Arara.config[AraraSpec.UserInteraction.displayLine] + if (Arara.config[AraraSpec.UserInteraction.displayResult]) + addNewLine() + if (display) { + if (!isDryRunMode) { + if (!isVerboseMode) { + buildShortError() + } else { + buildLongError() + } + addNewLine() + } + } + val text = (if (exception.hasException()) + exception.message + " " + messages.getMessage( + Messages.INFO_DISPLAY_EXCEPTION_MORE_DETAILS) + else + exception.message) ?: "EXCEPTION PROVIDES NO MESSAGE" + // TODO: check null handling + logger.error(text) + wrapText(text) + if (exception.hasException()) { + addNewLine() + displayDetailsLine() + val details = exception.exception!!.message!! + logger.error(details) + wrapText(details) + } + } + + /** + * Gets the string representation of the provided boolean value. + * + * @param value The boolean value. + * @return The string representation. + */ + private fun getResult(value: Boolean): String { + return if (value) + messages.getMessage( + Messages.INFO_LABEL_ON_SUCCESS + ) + else + messages.getMessage(Messages.INFO_LABEL_ON_FAILURE) + } + + /** + * Displays the short version of an error in the terminal. + */ + private fun buildShortError() { + val result = longestMatch + println(messages.getMessage(Messages.INFO_LABEL_ON_ERROR) + .padStart(result)) + } + + /** + * Displays the long version of an error in the terminal. + */ + private fun buildLongError() { + println((" " + messages.getMessage(Messages.INFO_LABEL_ON_ERROR)) + .padStart(width, '-')) + } + + /** + * Displays the provided text wrapped nicely according to the default + * terminal width. + * + * @param text The text to be displayed. + */ + fun wrapText(text: String) = println(text.wrap(width)) + + /** + * Displays the rule authors in the terminal. + * + * @param authors The list of authors. + */ + fun printAuthors(authors: List<String>) { + val line = if (authors.size == 1) + messages.getMessage(Messages.INFO_LABEL_AUTHOR) + else + messages.getMessage(Messages.INFO_LABEL_AUTHORS) + val text = if (authors.isEmpty()) + messages.getMessage(Messages.INFO_LABEL_NO_AUTHORS) + else + authors.joinToString(", ") { it.trim() } + wrapText("$line $text") + } + + /** + * Displays the current conditional in the terminal. + * + * @param conditional The conditional object. + */ + fun printConditional(conditional: Conditional) { + if (conditional.type !== Conditional.ConditionalType.NONE) { + wrapText(messages.getMessage(Messages.INFO_LABEL_CONDITIONAL) + + " (" + conditional.type + ") " + + conditional.condition) + } + } + + /** + * Displays the file information in the terminal. + */ + fun printFileInformation() { + val file = Arara.config[AraraSpec.Execution.reference] + val version = Arara.config[AraraSpec.Application.version] + val line = messages.getMessage( + Messages.INFO_DISPLAY_FILE_INFORMATION, + file.name, + CommonUtils.byteSizeToString(file.length()), + FileHandlingUtils.getLastModifiedInformation(file) + ) + logger.info(messages.getMessage( + Messages.LOG_INFO_WELCOME_MESSAGE, + version + )) + logger.info(displaySeparator()) + logger.debug("::: arara @ $applicationPath") + logger.debug("::: Java %s, %s".format( + CommonUtils.getSystemProperty("java.version", + "[unknown version]"), + CommonUtils.getSystemProperty("java.vendor", + "[unknown vendor]") + )) + logger.debug("::: %s".format( + CommonUtils.getSystemProperty("java.home", + "[unknown location]") + )) + logger.debug("::: %s, %s, %s".format( + CommonUtils.getSystemProperty("os.name", + "[unknown OS name]"), + CommonUtils.getSystemProperty("os.arch", + "[unknown OS arch]"), + CommonUtils.getSystemProperty("os.version", + "[unknown OS version]") + )) + logger.debug("::: user.home @ %s".format( + CommonUtils.getSystemProperty("user.home", + "[unknown user's home directory]") + )) + logger.debug("::: CF @ %s".format(Arara.config[AraraSpec.Execution + .configurationName])) + logger.debug(displaySeparator()) + logger.info(line) + wrapText(line) + addNewLine() + } + + /** + * Displays the elapsed time in the terminal. + * + * @param seconds The elapsed seconds. + */ + fun printTime(seconds: Double) { + val language = Arara.config[AraraSpec.Execution.language] + + if (Arara.config[AraraSpec.UserInteraction.displayTime]) { + if (Arara.config[AraraSpec.UserInteraction.displayLine] || + Arara.config[AraraSpec.UserInteraction.displayException]) + addNewLine() + + val text = messages.getMessage( + Messages.INFO_DISPLAY_EXECUTION_TIME, + "%1.2f".format(language.locale, seconds)) + logger.info(text) + wrapText(text) + } + } + + /** + * Displays the application logo in the terminal. + */ + fun printLogo() { + println(""" + __ _ _ __ __ _ _ __ __ _ + / _` | '__/ _` | '__/ _` | + | (_| | | | (_| | | | (_| | + \__,_|_| \__,_|_| \__,_| + """.trimIndent()) + addNewLine() + } + + /** + * Adds a new line in the terminal. + */ + private fun addNewLine() { + println() + } + + /** + * Displays a line containing details. + */ + private fun displayDetailsLine() { + val line = messages.getMessage( + Messages.INFO_LABEL_ON_DETAILS) + " " + println(line.abbreviate(width).padEnd(width, '-')) + } + + /** + * Gets the output separator with the provided text. + * + * @param message The provided text. + * @return A string containing the output separator with the provided text. + */ + fun displayOutputSeparator(message: String): String { + return " $message ".center(width, '-') + } + + /** + * Gets the line separator. + * + * @return A string containing the line separator. + */ + fun displaySeparator(): String { + return "-".repeat(width) + } +} |