├── .gitignore ├── AUTHORS ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── ansicolor-dart.png ├── example └── ansicolor.dart ├── lib ├── ansicolor.dart └── src │ ├── supports_ansi.dart │ ├── supports_ansi_io.dart │ └── supports_ansi_web.dart ├── pubspec.yaml └── test ├── ansicolor_test.dart └── browser_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | packages 2 | pubspec.lock 3 | .project 4 | .children 5 | .dart_tool 6 | .packages 7 | *~ 8 | 9 | # Flutter/Dart/Pub related 10 | **/doc/api/ 11 | **/ios/Flutter/.last_build_id 12 | .dart_tool/ 13 | .flutter-plugins 14 | .flutter-plugins-dependencies 15 | .pub-cache/ 16 | .pub/ 17 | /build/ -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Authors: 2 | 3 | John Thomas McDole 4 | Jason Daly 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changes 2 | 3 | ## 2.0.3 4 | 5 | * WASM support 6 | 7 | ## 2.0.2 8 | 9 | * Public getters for pen colors. 10 | * Updated to Dart 3.0 11 | 12 | ## 2.0.1 13 | 14 | * Update to default `2.12.0` for null safety before publishing. 15 | 16 | ## 2.0.0-nullsafety.0 17 | 18 | * This package was already nullsafe; this just makes it official. 19 | 20 | ## 1.1.1 21 | 22 | * Pre-upgrade for nullsafety 23 | * `clamp` has a `num` signature, also doesn't follow inclusive-exclusive 24 | ranges, `[)`, and is instead inclusive-inclusive, `()`. 25 | 26 | ## 1.1.0 27 | 28 | * Round up release closing out some older issues. 29 | * Try to detect is ANSI is supported 30 | * Update naming style; deprecate the old names. 31 | * write() and call() take object now. 32 | 33 | ## 1.0.5 34 | 35 | * Add types to API calls 36 | 37 | ## 1.0.4 38 | 39 | * Update styling, remove `new`, use `final` or `var`. 40 | * Support null safety 41 | 42 | ## 1.0.3 43 | 44 | * Minor updates to optional name style (s/:/=) 45 | * Make the description better 46 | 47 | ## 1.0.2 48 | 49 | * Adding this CHANGELOG.md 50 | * Moving bin/demo.dart to examples/ansicolor.dart 51 | 52 | ## 1.0.1 53 | 54 | * Updated authors 55 | 56 | ## 1.0.0 57 | 58 | * Dart 2.0 support! 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ANSI / Xterm 256 color library for Dart 2 | ------ 3 | 4 | Feel like you're missing some color in your terminal programs? Use AnsiPen to add ANSI color codes to your log messages. 5 | 6 | Easy to disable for production, just set `color_disabled = true` and all codes will be empty - no re-writing debug messages. 7 | 8 | Note: `color_disabled` is a global variable for all pen colors. 9 | 10 | Example 11 | ------ 12 | Note: Be mindful of contrasting colors. If you set "bright white" foreground and don't adjust the background, you'll have a bad time with lighter terminals. 13 | 14 | Foreground to bright white with default background: 15 | ```dart 16 | AnsiPen pen = AnsiPen()..white(bold: true); 17 | print(pen("Bright white foreground") + " this text is default fg/bg"); 18 | ``` 19 | 20 | Background as a peach, foreground as white: 21 | ```dart 22 | AnsiPen pen = AnsiPen()..white()..rgb(r: 1.0, g: 0.8, b: 0.2, bg: true); 23 | print(pen("White foreground with a peach background")); 24 | ``` 25 | 26 | Note 27 | ------ 28 | If color isn't working for you; try setting `ansiColorDisabled = false;`. We're relying on the `stdio` object to inform us of ANSI terminal support. Sometimes this is wrong. 29 | 30 | Prior versions of this library just turned on color by default. 31 | 32 | Rainbow Demo 33 | ------ 34 | 35 | If you want a specific color, you can call the `xterm()` with the index listed in the rainbow below. To show the rainbow on your own terminal, `pub run examples/ansicolor.dart` 36 | 37 | ![alt tag](https://raw.github.com/google/ansicolor-dart/master/ansicolor-dart.png) 38 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/core.yaml 2 | 3 | #include: package:lints/recommended.yaml 4 | -------------------------------------------------------------------------------- /ansicolor-dart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/ansicolor-dart/418feb061ef27ec082f57adf4c1424821cdffc2e/ansicolor-dart.png -------------------------------------------------------------------------------- /example/ansicolor.dart: -------------------------------------------------------------------------------- 1 | import 'package:ansicolor/ansicolor.dart'; 2 | 3 | void main() { 4 | ansiColorDisabled = false; 5 | print(ansi_demo()); 6 | } 7 | 8 | /// Due to missing sprintf(), this is my cheap "%03d". 9 | String _toSpace(int i, [int width = 3]) { 10 | if (width <= 0 && i == 0) return ''; 11 | return '${_toSpace(i ~/ 10, --width)}${i % 10}'; 12 | } 13 | 14 | /// Return a reference table for foreground and background colors. 15 | String ansi_demo() { 16 | final sb = StringBuffer(); 17 | final pen = AnsiPen(); 18 | 19 | for (var c = 0; c < 16; c++) { 20 | pen 21 | ..reset() 22 | ..white(bold: true) 23 | ..xterm(c, bg: true); 24 | sb.write(pen('${_toSpace(c)} ')); 25 | pen 26 | ..reset() 27 | ..xterm(c); 28 | sb.write(pen(' ${_toSpace(c)} ')); 29 | if (c == 7 || c == 15) { 30 | sb.write('\n'); 31 | } 32 | } 33 | 34 | for (var r = 0; r < 6; r++) { 35 | sb.write('\n'); 36 | for (var g = 0; g < 6; g++) { 37 | for (var b = 0; b < 6; b++) { 38 | var c = r * 36 + g * 6 + b + 16; 39 | pen 40 | ..reset() 41 | ..rgb(r: r / 5, g: g / 5, b: b / 5, bg: true) 42 | ..white(bold: true); 43 | sb.write(pen(' ${_toSpace(c)} ')); 44 | pen 45 | ..reset() 46 | ..rgb(r: r / 5, g: g / 5, b: b / 5); 47 | sb.write(pen(' ${_toSpace(c)} ')); 48 | } 49 | sb.write('\n'); 50 | } 51 | } 52 | 53 | for (var c = 0; c < 24; c++) { 54 | if (0 == c % 8) { 55 | sb.write('\n'); 56 | } 57 | pen 58 | ..reset() 59 | ..gray(level: c / 23, bg: true) 60 | ..white(bold: true); 61 | sb.write(pen(' ${_toSpace(c + 232)} ')); 62 | pen 63 | ..reset() 64 | ..gray(level: c / 23); 65 | sb.write(pen(' ${_toSpace(c + 232)} ')); 66 | } 67 | return sb.toString(); 68 | } 69 | -------------------------------------------------------------------------------- /lib/ansicolor.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Copyright 2013 Google Inc. All Rights Reserved. 3 | /// 4 | /// ANSI/XTERM SGR (Select Graphics Rendering) support for 256 colors. 5 | /// Note: if you're using the dart editor, these won't look right in the 6 | /// terminal; disable via [ansiColorDisabled] or use Eclipse with the Dart and 7 | /// AnsiConsol plugins! 8 | library ansicolor; 9 | 10 | import 'src/supports_ansi.dart' 11 | if (dart.library.io) 'src/supports_ansi_io.dart' 12 | if (dart.library.js_interop) 'src/supports_ansi_web.dart'; 13 | 14 | /// Globally enable or disable [AnsiPen] settings. 15 | /// 16 | /// Note: defaults to environment support; but can be overridden. 17 | /// 18 | /// Handy for turning on and off embedded colors without commenting out code. 19 | bool ansiColorDisabled = !supportsAnsiColor; 20 | 21 | @Deprecated( 22 | 'Will be removed in future releases in favor of [ansiColorDisabled]') 23 | // ignore: non_constant_identifier_names 24 | bool get color_disabled => ansiColorDisabled; 25 | @Deprecated( 26 | 'Will be removed in future releases in favor of [ansiColorDisabled]') 27 | // ignore: non_constant_identifier_names 28 | set color_disabled(bool disabled) => ansiColorDisabled = disabled; 29 | 30 | /// Pen attributes for foreground and background colors. 31 | /// 32 | /// Use the pen in string interpolation to output ansi codes. 33 | /// Use [up] in string interpolation to globally reset colors. 34 | class AnsiPen { 35 | /// Treat a pen instance as a function such that `pen('msg')` is the same as 36 | /// `pen.write('msg')`. 37 | String call(Object msg) => write(msg); 38 | 39 | /// Allow pen colors to be used in a string. 40 | /// 41 | /// Note: Once the pen is down, its attributes remain in effect till they are 42 | /// changed by another pen or [up]. 43 | @override 44 | String toString() { 45 | if (ansiColorDisabled) return ''; 46 | if (!_dirty) return _pen; 47 | 48 | final sb = StringBuffer(); 49 | if (_fcolor != -1) { 50 | sb.write('${ansiEscape}38;5;${_fcolor}m'); 51 | } 52 | 53 | if (_bcolor != -1) { 54 | sb.write('${ansiEscape}48;5;${_bcolor}m'); 55 | } 56 | 57 | _dirty = false; 58 | _pen = sb.toString(); 59 | return _pen; 60 | } 61 | 62 | /// Returns control codes to change the terminal colors. 63 | String get down => '${this}'; 64 | 65 | /// Resets all pen attributes in the terminal. 66 | String get up => ansiColorDisabled ? '' : ansiDefault; 67 | 68 | /// Write the [msg.toString()] with the pen's current settings and then 69 | /// reset all attributes. 70 | String write(Object msg) => '${this}$msg$up'; 71 | 72 | void black({bool bg = false, bool bold = false}) => _std(0, bold, bg); 73 | void red({bool bg = false, bool bold = false}) => _std(1, bold, bg); 74 | void green({bool bg = false, bool bold = false}) => _std(2, bold, bg); 75 | void yellow({bool bg = false, bool bold = false}) => _std(3, bold, bg); 76 | void blue({bool bg = false, bool bold = false}) => _std(4, bold, bg); 77 | void magenta({bool bg = false, bool bold = false}) => _std(5, bold, bg); 78 | void cyan({bool bg = false, bool bold = false}) => _std(6, bold, bg); 79 | void white({bool bg = false, bool bold = false}) => _std(7, bold, bg); 80 | 81 | /// Sets the pen color to the rgb value between 0.0..1.0. 82 | void rgb({num r = 1.0, num g = 1.0, num b = 1.0, bool bg = false}) => xterm( 83 | (r.clamp(0.0, 1.0) * 5).toInt() * 36 + 84 | (g.clamp(0.0, 1.0) * 5).toInt() * 6 + 85 | (b.clamp(0.0, 1.0) * 5).toInt() + 86 | 16, 87 | bg: bg); 88 | 89 | /// Sets the pen color to a grey scale value between 0.0 and 1.0. 90 | void gray({num level = 1.0, bool bg = false}) => 91 | xterm(232 + (level.clamp(0.0, 1.0) * 23).round(), bg: bg); 92 | 93 | void _std(int color, bool bold, bool bg) => 94 | xterm(color + (bold ? 8 : 0), bg: bg); 95 | 96 | /// Directly index the xterm 256 color palette. 97 | void xterm(int color, {bool bg = false}) { 98 | _dirty = true; 99 | final c = color < 0 100 | ? 0 101 | : color > 255 102 | ? 255 103 | : color; 104 | if (bg) { 105 | _bcolor = c; 106 | } else { 107 | _fcolor = c; 108 | } 109 | } 110 | 111 | ///Resets the pen's attributes. 112 | void reset() { 113 | _dirty = false; 114 | _pen = ''; 115 | _bcolor = _fcolor = -1; 116 | } 117 | 118 | /// Returns the pen's foreground color 119 | int get fcolor => _fcolor; 120 | 121 | /// Returns the pen's background color index. 122 | int get bcolor => _bcolor; 123 | 124 | /// Returns whether the pen's attributes are dirty. 125 | bool get dirty => _dirty; 126 | 127 | int _fcolor = -1; 128 | int _bcolor = -1; 129 | String _pen = ''; 130 | bool _dirty = false; 131 | } 132 | 133 | /// ANSI Control Sequence Introducer, signals the terminal for new settings. 134 | const ansiEscape = '\x1B['; 135 | 136 | @Deprecated('Will be removed in future releases') 137 | const ansi_esc = ansiEscape; 138 | 139 | /// Reset all colors and options for current SGRs to terminal defaults. 140 | const ansiDefault = '${ansiEscape}0m'; 141 | 142 | @Deprecated('Will be removed in future releases') 143 | const ansi_default = ansiDefault; 144 | 145 | /// Ansi codes that default the terminal's foreground color without 146 | /// altering the background, when printed. 147 | /// 148 | /// Does not modify [AnsiPen]! 149 | const ansiResetForeground = '${ansiEscape}39m'; 150 | 151 | @Deprecated('Will be removed in future releases') 152 | String resetForeground() => ansiResetForeground; 153 | 154 | ///Ansi codes that default the terminal's background color without 155 | ///altering the foreground, when printed. 156 | /// 157 | /// Does not modify [AnsiPen]! 158 | const ansiResetBackground = '${ansiEscape}49m'; 159 | 160 | @Deprecated('Will be removed in future releases') 161 | String resetBackground() => ansiResetBackground; 162 | -------------------------------------------------------------------------------- /lib/src/supports_ansi.dart: -------------------------------------------------------------------------------- 1 | bool get supportsAnsiColor => false; 2 | -------------------------------------------------------------------------------- /lib/src/supports_ansi_io.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | bool get supportsAnsiColor => stdout.supportsAnsiEscapes; 4 | -------------------------------------------------------------------------------- /lib/src/supports_ansi_web.dart: -------------------------------------------------------------------------------- 1 | // Well, true for new versions of the browser; would be great to 2 | // test if console.print() supported it. 3 | bool get supportsAnsiColor => true; 4 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: ansicolor 2 | version: 2.0.3 3 | description: >- 4 | Looking to add some color to your terminal logs? `ansicolor` is an xterm-256 5 | color support library that lets you change the foreground and background 6 | color of your text. 7 | repository: https://github.com/google/ansicolor-dart 8 | environment: 9 | sdk: ">=3.0.0 <4.0.0" 10 | dev_dependencies: 11 | lints: ^4.0.0 12 | test: ^1.16.8 13 | topics: 14 | - cli 15 | -------------------------------------------------------------------------------- /test/ansicolor_test.dart: -------------------------------------------------------------------------------- 1 | @TestOn('dart-vm') 2 | library ansicolor_test; 3 | 4 | import 'package:ansicolor/ansicolor.dart'; 5 | import 'package:test/test.dart'; 6 | 7 | void main() { 8 | setUp(() { 9 | ansiColorDisabled = false; 10 | }); 11 | 12 | tearDown(() { 13 | ansiColorDisabled = false; 14 | }); 15 | 16 | test('foreground', () { 17 | final pen = AnsiPen()..rgb(r: 1.0, g: 0.8, b: 0.2); 18 | expect(pen.write('Test Text'), '\x1B[38;5;221mTest Text\x1B[0m'); 19 | }); 20 | 21 | test('background', () { 22 | final pen = AnsiPen()..rgb(r: 0.4, g: 0.8, b: 1.0, bg: true); 23 | expect(pen.write('Test Text'), '\x1B[48;5;117mTest Text\x1B[0m'); 24 | }); 25 | 26 | test('foreground and background', () { 27 | final pen = AnsiPen() 28 | ..rgb(r: 1.0, g: 0.8, b: 0.2) 29 | ..rgb(r: 0.4, g: 0.8, b: 1.0, bg: true); 30 | expect( 31 | pen.write('Test Text'), '\x1B[38;5;221m\x1B[48;5;117mTest Text\x1B[0m'); 32 | }); 33 | 34 | test('foreground and background w/ resets', () { 35 | final pen = AnsiPen() 36 | ..rgb(r: 1.0, g: 0.8, b: 0.2) 37 | ..rgb(r: 0.4, g: 0.8, b: 1.0, bg: true); 38 | expect( 39 | pen.write('Test${ansiResetBackground} Text${ansiResetForeground}Test'), 40 | '\x1B[38;5;221m\x1B[48;5;117mTest\x1B[49m Text\x1B[39mTest\x1B[0m'); 41 | }); 42 | 43 | test('direct xterm', () { 44 | final pen = AnsiPen()..xterm(200)..xterm(100, bg: true); 45 | expect( 46 | pen.write('Test Text'), '\x1B[38;5;200m\x1B[48;5;100mTest Text\x1B[0m'); 47 | }); 48 | 49 | test('xterm index clamped', () { 50 | final pen = AnsiPen()..xterm(256)..xterm(-1, bg: true); 51 | expect( 52 | pen.write('Test Text'), '\x1B[38;5;255m\x1B[48;5;0mTest Text\x1B[0m'); 53 | }); 54 | 55 | test('call() == write()', () { 56 | final pen = AnsiPen() 57 | ..rgb(r: 1.0, g: 0.8, b: 0.2) 58 | ..rgb(r: 0.4, g: 0.8, b: 1.0, bg: true); 59 | expect(pen.write('Test Text'), pen('Test Text')); 60 | }); 61 | 62 | test('interpolated == write()', () { 63 | final pen = AnsiPen() 64 | ..rgb(r: 1.0, g: 0.8, b: 0.2) 65 | ..rgb(r: 0.4, g: 0.8, b: 1.0, bg: true); 66 | expect('${pen}Test Text${pen.up}', pen('Test Text')); 67 | }); 68 | 69 | test('system colors', () { 70 | final pen = AnsiPen(); 71 | expect((pen..black()).down, '\x1B[38;5;0m'); 72 | expect((pen..red()).down, '\x1B[38;5;1m'); 73 | expect((pen..green()).down, '\x1B[38;5;2m'); 74 | expect((pen..yellow()).down, '\x1B[38;5;3m'); 75 | expect((pen..blue()).down, '\x1B[38;5;4m'); 76 | expect((pen..magenta()).down, '\x1B[38;5;5m'); 77 | expect((pen..cyan()).down, '\x1B[38;5;6m'); 78 | expect((pen..white()).down, '\x1B[38;5;7m'); 79 | 80 | expect((pen..black(bold: true)).down, '\x1B[38;5;8m'); 81 | expect((pen..red(bold: true)).down, '\x1B[38;5;9m'); 82 | expect((pen..green(bold: true)).down, '\x1B[38;5;10m'); 83 | expect((pen..yellow(bold: true)).down, '\x1B[38;5;11m'); 84 | expect((pen..blue(bold: true)).down, '\x1B[38;5;12m'); 85 | expect((pen..magenta(bold: true)).down, '\x1B[38;5;13m'); 86 | expect((pen..cyan(bold: true)).down, '\x1B[38;5;14m'); 87 | expect((pen..white(bold: true)).down, '\x1B[38;5;15m'); 88 | 89 | expect((pen..reset()).down, ''); 90 | 91 | expect((pen..black(bg: true)).down, '\x1B[48;5;0m'); 92 | expect((pen..red(bg: true)).down, '\x1B[48;5;1m'); 93 | expect((pen..green(bg: true)).down, '\x1B[48;5;2m'); 94 | expect((pen..yellow(bg: true)).down, '\x1B[48;5;3m'); 95 | expect((pen..blue(bg: true)).down, '\x1B[48;5;4m'); 96 | expect((pen..magenta(bg: true)).down, '\x1B[48;5;5m'); 97 | expect((pen..cyan(bg: true)).down, '\x1B[48;5;6m'); 98 | expect((pen..white(bg: true)).down, '\x1B[48;5;7m'); 99 | 100 | expect((pen..black(bg: true, bold: true)).down, '\x1B[48;5;8m'); 101 | expect((pen..red(bg: true, bold: true)).down, '\x1B[48;5;9m'); 102 | expect((pen..green(bg: true, bold: true)).down, '\x1B[48;5;10m'); 103 | expect((pen..yellow(bg: true, bold: true)).down, '\x1B[48;5;11m'); 104 | expect((pen..blue(bg: true, bold: true)).down, '\x1B[48;5;12m'); 105 | expect((pen..magenta(bg: true, bold: true)).down, '\x1B[48;5;13m'); 106 | expect((pen..cyan(bg: true, bold: true)).down, '\x1B[48;5;14m'); 107 | expect((pen..white(bg: true, bold: true)).down, '\x1B[48;5;15m'); 108 | }); 109 | 110 | test('rgb overflow', () { 111 | final pen = AnsiPen() 112 | ..rgb(r: 2.0, g: 2.8, b: 2.2) 113 | ..rgb(r: 2.4, g: 2.8, b: 2.0, bg: true); 114 | expect( 115 | pen.write('Test Text'), '\x1B[38;5;231m\x1B[48;5;231mTest Text\x1B[0m'); 116 | }); 117 | 118 | test('rgb underflow', () { 119 | final pen = AnsiPen() 120 | ..rgb(r: -1.0, g: -2.8, b: -2.2) 121 | ..rgb(r: -1.0, g: -2.8, b: -2.0, bg: true); 122 | expect( 123 | pen.write('Test Text'), '\x1B[38;5;16m\x1B[48;5;16mTest Text\x1B[0m'); 124 | }); 125 | 126 | test('grayscale', () { 127 | final pen = AnsiPen(); 128 | 129 | for (var i = 0; i < 24; i++) { 130 | expect((pen..gray(level: i / 23)).down, '\x1B[38;5;${232 + i}m', 131 | reason: 'fg failed at $i'); 132 | } 133 | 134 | expect((pen..reset()).down, ''); 135 | 136 | for (var i = 0; i < 24; i++) { 137 | expect((pen..gray(level: i / 23, bg: true)).down, '\x1B[48;5;${232 + i}m', 138 | reason: 'bg failed at $i'); 139 | } 140 | }); 141 | 142 | test('ansiColorDisabled', () { 143 | final pen = AnsiPen() 144 | ..rgb(r: 1.0, g: 0.8, b: 0.2) 145 | ..rgb(r: 0.4, g: 0.8, b: 1.0, bg: true); 146 | ansiColorDisabled = true; 147 | expect(pen.write('Test Text'), 'Test Text'); 148 | }); 149 | } 150 | -------------------------------------------------------------------------------- /test/browser_test.dart: -------------------------------------------------------------------------------- 1 | @TestOn('browser') 2 | 3 | import 'package:ansicolor/ansicolor.dart'; 4 | import 'package:test/test.dart'; 5 | 6 | void main() { 7 | setUp(() { 8 | ansiColorDisabled = false; 9 | }); 10 | 11 | tearDown(() { 12 | ansiColorDisabled = false; 13 | }); 14 | test('browser compiles', () { 15 | expect(ansiColorDisabled, isFalse); 16 | }); 17 | } 18 | --------------------------------------------------------------------------------