1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.metalava.cli.common 18 19 enum class TerminalColor(val value: Int) { 20 BLACK(0), 21 RED(1), 22 GREEN(2), 23 YELLOW(3), 24 BLUE(4), 25 MAGENTA(5), 26 CYAN(6), 27 WHITE(7) 28 } 29 30 val plainTerminal: Terminal = PlainTerminal() 31 val stylingTerminal: Terminal = StylingTerminal() 32 33 sealed class Terminal { attributesnull34 abstract fun attributes( 35 bold: Boolean = false, 36 italic: Boolean = false, 37 underline: Boolean = false, 38 reverse: Boolean = false, 39 foreground: TerminalColor? = null, 40 background: TerminalColor? = null 41 ): String 42 43 abstract fun reset(): String 44 45 fun bold(string: String): String { 46 return "${attributes(bold = true)}$string${reset()}" 47 } 48 italicnull49 fun italic(string: String): String { 50 return "${attributes(italic = true)}$string${reset()}" 51 } 52 colorizenull53 fun colorize(string: String, color: TerminalColor): String { 54 return "${attributes(foreground = color)}$string${reset()}" 55 } 56 } 57 58 @Suppress("CanSealedSubClassBeObject") 59 private class PlainTerminal : Terminal() { attributesnull60 override fun attributes( 61 bold: Boolean, 62 italic: Boolean, 63 underline: Boolean, 64 reverse: Boolean, 65 foreground: TerminalColor?, 66 background: TerminalColor? 67 ): String { 68 return "" 69 } 70 resetnull71 override fun reset(): String { 72 return "" 73 } 74 } 75 76 @Suppress("CanSealedSubClassBeObject") 77 private class StylingTerminal : Terminal() { attributesnull78 override fun attributes( 79 bold: Boolean, 80 italic: Boolean, 81 underline: Boolean, 82 reverse: Boolean, 83 foreground: TerminalColor?, 84 background: TerminalColor? 85 ): String { 86 val sb = StringBuilder() 87 sb.append("\u001B[") 88 if (foreground != null) { 89 sb.append('3').append('0' + foreground.value) 90 } 91 if (background != null) { 92 if (sb.last().isDigit()) sb.append(';') 93 sb.append('4').append('0' + background.value) 94 } 95 if (bold) { 96 if (sb.last().isDigit()) sb.append(';') 97 sb.append('1') 98 } 99 if (italic) { 100 if (sb.last().isDigit()) sb.append(';') 101 sb.append('3') 102 } 103 if (underline) { 104 if (sb.last().isDigit()) sb.append(';') 105 sb.append('4') 106 } 107 if (reverse) { 108 if (sb.last().isDigit()) sb.append(';') 109 sb.append('7') 110 } 111 if (sb.last() == '[') { 112 // Nothing: Reset 113 sb.append('0') 114 } 115 sb.append("m") 116 return sb.toString() 117 } 118 resetnull119 override fun reset(): String { 120 return "\u001b[0m" 121 } 122 } 123