├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── checkstyle.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── maven_push.gradle ├── settings.gradle └── src ├── main └── java │ └── com │ └── github │ └── pwittchen │ └── kirai │ └── library │ ├── Formatter.java │ ├── Kirai.java │ ├── Piece.java │ ├── Preconditions.java │ ├── Syntax.java │ ├── html │ ├── HtmlPiece.java │ └── HtmlSyntax.java │ └── terminal │ ├── TerminalBgColor.java │ ├── TerminalColor.java │ ├── TerminalPiece.java │ └── TerminalSyntax.java └── test └── java └── com └── github └── pwittchen └── kirai └── library ├── HtmlPieceTest.java ├── KiraiTest.java ├── PreconditionsTest.java ├── TerminalPieceTest.java └── TerminalSyntaxTest.java /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [pwittchen] 2 | custom: ['https://paypal.me/pwittchen'] 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle 2 | /local.properties 3 | /.idea 4 | /.DS_Store 5 | /build 6 | *.iml 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | install: 4 | # Check install section: http://docs.travis-ci.com/user/build-configuration/#install 5 | # If you'd like to skip the install stage entirely, set it to true and nothing will be run. 6 | - true 7 | 8 | after_success: 9 | - bash <(curl -s https://codecov.io/bash) 10 | 11 | script: 12 | - ./gradlew clean build test check 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | v. 1.4.1 5 | -------- 6 | *05 Dec 2015* 7 | 8 | - renamed `Utils` class to `Preconditions` class 9 | - improved validation of input data 10 | - increased code coverage 11 | - updated project configuration 12 | - removed `app` module 13 | - removed remaining Android dependencies located in classpath of Gradle configuration 14 | - removed Android related stuff from `.travis.yml` 15 | - added Java related stuff to `.travis.yml` 16 | - removed top-level `build.gradle` script and `library` directory to simplify project configuration 17 | - added Static Code Analysis (CheckStyle, PMD, FindBugs) 18 | 19 | v. 1.4.0 20 | -------- 21 | *22 Nov 2015* 22 | 23 | - added support for formatting text in Unix terminal (bold, underline, color and background color) 24 | - created separate packages for classes responsible for HTML formatting and terminal formatting 25 | - added `TerminalColor` and `TerminalBgColor` enums with predefined terminal color codes 26 | - updated `README.md` and prepared more code samples 27 | - added test coverage with codecov.io 28 | 29 | v. 1.3.1 30 | -------- 31 | *21 Nov 2015* 32 | 33 | Changed `syntax`, `key` and `value` fields from `private` to `protected` in `Piece` class. 34 | 35 | v. 1.3.0 36 | -------- 37 | *18 Nov 2015* 38 | 39 | - `Piece` is now an abstract class 40 | - created `HtmlPiece` extending Piece `class`, which uses `HtmlSyntax` class 41 | - updated documentation and tests 42 | 43 | v. 1.2.0 44 | -------- 45 | *15 Nov 2015* 46 | 47 | - changed library type from `aar` (Android packaging) to `jar` (pure Java packaging) 48 | 49 | v. 1.1.0 50 | -------- 51 | *06 Nov 2015* 52 | 53 | - removed `formatter(...)` method from `Kirai` class 54 | - added `format(...)` method accepting implementation of `Formatter` interface to `Kirai` class 55 | - added `Syntax` interface and `HtmlSyntax` class implementing this interface 56 | - added `put(String key, Object value, Syntax syntax)` method to `Piece` class 57 | - set `HtmlSyntax` as default `Syntax` implementation in `Piece` class 58 | - removed dependencies to Android SDK 59 | - updated project dependencies 60 | - applied `Square` code style 61 | - updated tests, sample app and code snippets in `README.md` 62 | - added gh-pages with JavaDoc 63 | 64 | v. 1.0.1 65 | -------- 66 | *03 Apr 2015* 67 | 68 | - updated existing unit tests to JUnit4 69 | - added Google Truth library for test assertions 70 | - added more unit tests 71 | - added `Kirai formatter(Formatter formatter)` method in `Kirai` class for setting custom `Formatter` implementation. 72 | 73 | v. 1.0.0 74 | -------- 75 | *12 Jan 2015* 76 | 77 | First version of the library released to Maven Central Repository. 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Kirai 2 | ===== 3 | 4 | [![Build Status](https://travis-ci.org/pwittchen/kirai.svg?branch=master)](https://travis-ci.org/pwittchen/kirai) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Kirai-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1391) ![Maven Central](https://img.shields.io/maven-central/v/com.github.pwittchen.kirai/library.svg?style=flat) [![codecov](https://codecov.io/gh/pwittchen/kirai/branch/master/graph/badge.svg)](https://codecov.io/gh/pwittchen/kirai) 5 | 6 | Kirai means *phrase* in Swahili language. It's string formatting library for Java, Android, Web and Unix Terminal. 7 | 8 | Project is inspired by [phrase](https://github.com/square/phrase), [TaggerString](https://github.com/polok/TaggerString) and [BabushkaText](https://github.com/quiqueqs/BabushkaText). 9 | Kirai has fluent API similar to phrase with additional formatting similar to TaggerString and allows to add formatted pieces of text like BabushkaText. 10 | 11 | JavaDoc is available at: http://pwittchen.github.io/kirai/ 12 | 13 | Library is compatible with Java 1.7 and higher. It should work with Java 1.6 and is compatible with Android applications. 14 | 15 | Contents 16 | -------- 17 | - [Usage](#usage) 18 | - [Basic](#basic) 19 | - [Android](#android) 20 | - [Web](#web) 21 | - [Terminal](#terminal) 22 | - [Download](#download) 23 | - [Building project](#building-project) 24 | - [Tests](#tests) 25 | - [Static Code Analysis](#static-code-analysis) 26 | - [Code style](#code-style) 27 | - [License](#license) 28 | 29 | Usage 30 | ----- 31 | 32 | ### Basic 33 | 34 | ```java 35 | CharSequence formatted = Kirai 36 | .from("Hi {first_name}, your are {age} years old.") 37 | .put("first_name", firstName) 38 | .put("age", age) 39 | .format(); 40 | ``` 41 | 42 | ### Android 43 | 44 | ```java 45 | CharSequence formatted = Kirai 46 | .from("Hi {first_name}, your are {age} years old.") 47 | .put(HtmlPiece.put("first_name", firstName).bold().italic().big()) 48 | .put(HtmlPiece.put("age", age).underline().color("#FF0000")) 49 | .format(new Formatter() { 50 | @Override public CharSequence format(String input) { 51 | return Html.fromHtml(input); 52 | } 53 | }); 54 | ``` 55 | 56 | Code above will generate formatted text and can be used in **Android TextView** as follows: 57 | 58 | ```java 59 | textView.setText(formatted); 60 | ``` 61 | 62 | ### Web 63 | 64 | ```java 65 | CharSequence formatted = Kirai 66 | .from("Hi {first_name}, your are {age} years old.") 67 | .put(HtmlPiece.put("first_name", firstName).bold().italic().big()) 68 | .put(HtmlPiece.put("age", age).underline().color("#FF0000")) 69 | .format(); 70 | ``` 71 | 72 | Code above will generate text formatted with **HTML tags**. 73 | 74 | ### Terminal 75 | 76 | ```java 77 | CharSequence formatted = Kirai 78 | .from("Hi {first_name}, your are {age} years old.") 79 | .put(TerminalPiece.put("first_name", firstName).background(TerminalBgColor.DARK_GRAY).bold()) 80 | .put(TerminalPiece.put("age", age).color(TerminalColor.CYAN).underline()) 81 | .format(); 82 | ``` 83 | 84 | Code above will generate formatted text ready to display in **Unix terminal** as follows: 85 | 86 | ```java 87 | System.out.println(formatted); 88 | ``` 89 | 90 | instead of `TerminalColor` and `TerminalBgColor` enums we can pass color code as a string to `color(string)` method and it will work as well. We can use it for setting foreground and background color. For the reference of color codes take a look at http://misc.flogisoft.com/bash/tip_colors_and_formatting website. 91 | 92 | Download 93 | -------- 94 | 95 | You can depend on the library through Maven: 96 | 97 | ```xml 98 | 99 | com.github.pwittchen.kirai 100 | library 101 | 1.4.1 102 | 103 | ``` 104 | 105 | or through Gradle: 106 | 107 | ```groovy 108 | dependencies { 109 | compile 'com.github.pwittchen.kirai:library:1.4.1' 110 | } 111 | ``` 112 | 113 | Building project 114 | ---------------- 115 | 116 | To build project, run the following command: 117 | 118 | ``` 119 | ./gradlew build 120 | ``` 121 | 122 | Tests 123 | ----- 124 | 125 | Unit Tests are available in `library/src/test` directory. They can be run from IntelliJ IDEA or CLI with Gradle Wrapper. Tests were written according to TDD methodology. They determine library specification and check if project is fault-tolerant. Code Coverage is monitored by [codecov.io](https://codecov.io/github/pwittchen/kirai?branch=master) integrated with Travis CI. 126 | 127 | To execute tests, run the following command: 128 | 129 | ``` 130 | ./gradlew test 131 | ``` 132 | 133 | To generate code coverage report, run the following command: 134 | 135 | ``` 136 | ./gradlew jacocoTestReport 137 | ``` 138 | 139 | All reports are generated in `build/reports/` directory. 140 | 141 | Static Code Analysis 142 | -------------------- 143 | 144 | Project has Static Code Analysis configured in `build.gradle` file. It consists of CheckStyle, PMD and FindBugs. 145 | 146 | Static Code Analysis can be executed with the following command: 147 | 148 | ``` 149 | ./gradlew check 150 | ``` 151 | 152 | Code style 153 | ---------- 154 | 155 | Code style used in the project is called `Square` from Java Code Styles repository by Square available at: https://github.com/square/java-code-styles. 156 | 157 | License 158 | ------- 159 | 160 | Copyright 2015 Piotr Wittchen 161 | 162 | Licensed under the Apache License, Version 2.0 (the "License"); 163 | you may not use this file except in compliance with the License. 164 | You may obtain a copy of the License at 165 | 166 | http://www.apache.org/licenses/LICENSE-2.0 167 | 168 | Unless required by applicable law or agreed to in writing, software 169 | distributed under the License is distributed on an "AS IS" BASIS, 170 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 171 | See the License for the specific language governing permissions and 172 | limitations under the License. 173 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'idea' 3 | apply plugin: 'jacoco' 4 | apply plugin: 'checkstyle' 5 | apply plugin: 'findbugs' 6 | apply plugin: 'pmd' 7 | 8 | apply from: 'maven_push.gradle' 9 | 10 | sourceCompatibility = 1.7 11 | targetCompatibility = 1.7 12 | 13 | repositories { 14 | mavenCentral() 15 | jcenter() 16 | } 17 | 18 | dependencies { 19 | testCompile 'junit:junit:4.13' 20 | testCompile 'com.google.truth:truth:1.0.1' 21 | } 22 | 23 | sourceSets { 24 | main { 25 | java { 26 | srcDirs 'src/main/java' 27 | } 28 | } 29 | 30 | test { 31 | java { 32 | srcDir 'src/test/java' 33 | } 34 | } 35 | } 36 | 37 | jacocoTestReport { 38 | reports { 39 | xml.enabled = true 40 | html.enabled = true 41 | } 42 | } 43 | 44 | checkstyle { 45 | toolVersion = '6.0' 46 | configFile = new File(rootDir, 'checkstyle.xml') 47 | } 48 | 49 | tasks.withType(FindBugs) { 50 | reports { 51 | xml.enabled = false 52 | html.enabled = true 53 | } 54 | } 55 | 56 | check.dependsOn jacocoTestReport 57 | 58 | 59 | -------------------------------------------------------------------------------- /checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | VERSION_NAME=1.4.1 2 | VERSION_CODE=8 3 | GROUP=com.github.pwittchen.kirai 4 | 5 | POM_NAME=kirai 6 | POM_ARTIFACT_ID=library 7 | POM_PACKAGING=jar 8 | 9 | POM_DESCRIPTION=Kirai is flavored string formatting library 10 | POM_URL=https://github.com/pwittchen/kirai 11 | POM_SCM_URL=https://github.com/pwittchen/kirai 12 | POM_SCM_CONNECTION=scm:git@github.com:pwittchen/kirai.git 13 | POM_SCM_DEV_CONNECTION=scm:git@github.com:pwittchen/kirai.git 14 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 15 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 16 | POM_LICENCE_DIST=repo 17 | POM_DEVELOPER_ID=pwittchen 18 | POM_DEVELOPER_NAME=Piotr Wittchen 19 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pwittchen/kirai/2874bcde3dbb882c788ab89240d7613010ff353c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jun 12 22:36:00 CEST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /maven_push.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Chris Banes 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 | apply plugin: 'maven' 18 | apply plugin: 'signing' 19 | 20 | def isReleaseBuild() { 21 | return VERSION_NAME.contains("SNAPSHOT") == false 22 | } 23 | 24 | def getReleaseRepositoryUrl() { 25 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL : 26 | "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 27 | } 28 | 29 | def getSnapshotRepositoryUrl() { 30 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL : 31 | "https://oss.sonatype.org/content/repositories/snapshots/" 32 | } 33 | 34 | def getRepositoryUsername() { 35 | return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" 36 | } 37 | 38 | def getRepositoryPassword() { 39 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 40 | } 41 | 42 | afterEvaluate { project -> 43 | uploadArchives { 44 | repositories { 45 | mavenDeployer { 46 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 47 | 48 | pom.groupId = GROUP 49 | pom.artifactId = POM_ARTIFACT_ID 50 | pom.version = VERSION_NAME 51 | 52 | repository(url: getReleaseRepositoryUrl()) { 53 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 54 | } 55 | snapshotRepository(url: getSnapshotRepositoryUrl()) { 56 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) 57 | } 58 | 59 | pom.project { 60 | name POM_NAME 61 | packaging POM_PACKAGING 62 | description POM_DESCRIPTION 63 | url POM_URL 64 | 65 | scm { 66 | url POM_SCM_URL 67 | connection POM_SCM_CONNECTION 68 | developerConnection POM_SCM_DEV_CONNECTION 69 | } 70 | 71 | licenses { 72 | license { 73 | name POM_LICENCE_NAME 74 | url POM_LICENCE_URL 75 | distribution POM_LICENCE_DIST 76 | } 77 | } 78 | 79 | developers { 80 | developer { 81 | id POM_DEVELOPER_ID 82 | name POM_DEVELOPER_NAME 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | signing { 91 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") } 92 | sign configurations.archives 93 | } 94 | 95 | task javadocJar(type: Jar, dependsOn: javadoc) { 96 | classifier = 'javadoc' 97 | from javadoc.destinationDir 98 | } 99 | 100 | task sourceJar(type: Jar) { 101 | classifier = 'sources' 102 | from sourceSets.main.allSource 103 | } 104 | 105 | artifacts { 106 | archives sourceJar 107 | archives javadocJar 108 | } 109 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pwittchen/kirai/2874bcde3dbb882c788ab89240d7613010ff353c/settings.gradle -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/Formatter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | public interface Formatter { 19 | CharSequence format(String input); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/Kirai.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.Stack; 21 | import java.util.regex.Matcher; 22 | import java.util.regex.Pattern; 23 | 24 | /** 25 | * Kirai ("phrase" in Swahili language) - string formatting library. Basic usage: 26 | *
 27 |  *   CharSequence formatted = Kirai.from("Hi {first_name}, you are {age} years old.")
 28 |  *     .put("first_name", firstName)
 29 |  *     .put("age", age)
 30 |  *     .format();
 31 |  * 
32 | * On the Web: 33 | *
 34 |  *   CharSequence formatted = Kirai.from("Hi {first_name}, you are {age} years old.")
 35 |  *     .put(HtmlPiece.put("first_name", firstName).bold().italic().big())
 36 |  *     .put(HtmlPiece.put("age", age).underline().color("#FF0000"))
 37 |  *     .format(new Formatter() {
 38 |  *     .format();
 39 |  * 
40 | * On Android: 41 | *
 42 |  *   CharSequence formatted = Kirai.from("Hi {first_name}, you are {age} years old.")
 43 |  *     .put(HtmlPiece.put("first_name", firstName).bold().italic().big())
 44 |  *     .put(HtmlPiece.put("age", age).underline().color("#FF0000"))
 45 |  *     .format(new Formatter() {
 46 |  *       public CharSequence format(String input) {
 47 |  *         return Html.fromHtml(input);
 48 |  *        }
 49 |  *      });
 50 |  * 
51 | * In Unix terminal: 52 | *
 53 |  *   CharSequence formatted = Kirai.from("Hi {first_name}, you are {age} years old.")
 54 |  *     .put(TerminalPiece.put("first_name", firstName).bold())
 55 |  *     .put(TerminalPiece.put("age", age).underline().color(TerminalColor.RED))
 56 |  *     .format();
 57 |  * 
58 | *
  • Surround keys with curly braces
  • Keys start with lowercase letters followed by 59 | * lowercase letters and underscores.
  • Can be formatted for TextView (bold, italic, 60 | * underline, big, small, sub, sup).
  • Can be colored for TextView with HEX value followed by 61 | * hash sign.
  • Fails on any mismatched keys.
  • Fails on not balanced braces in 62 | * input.
  • Fails on incorrect, empty or null input data.
63 | */ 64 | public final class Kirai { 65 | private final static char BRACE_START = '{'; 66 | private final static char BRACE_END = '}'; 67 | private final static String REGEX_VALID_TAG = "[a-z]{1}[a-z0-9_]*"; 68 | private final static Pattern REGEX_TAG = 69 | Pattern.compile("\\" + BRACE_START + "(.+?)\\" + BRACE_END); 70 | private String input; //NOPMD 71 | private List tags; //NOPMD 72 | private List pieces = new ArrayList<>(); //NOPMD 73 | 74 | private Kirai(String string) { 75 | Preconditions.checkNotEmpty(string, "string is empty"); 76 | input = string; 77 | 78 | if (!isInputBalanced()) { 79 | throw new IllegalArgumentException("Braces in provided string are not balanced"); 80 | } 81 | 82 | if (!areTagsValid()) { 83 | throw new IllegalArgumentException( 84 | "Tags have to start from lower case letter and can contain " 85 | + "only lower case letters [a-z] numbers [0-9] and underscore [_]"); 86 | } 87 | } 88 | 89 | public static Kirai from(String string) { 90 | return new Kirai(string); 91 | } 92 | 93 | public Kirai put(String key, Object value) { 94 | Preconditions.checkNotEmpty(key, "key is empty"); 95 | Preconditions.checkNotEmpty(String.valueOf(value), "value is empty"); 96 | 97 | if (!tags.contains(key)) { 98 | throw new IllegalArgumentException("Tag {" + key + "} was not defined in input string"); 99 | } 100 | 101 | input = input.replace(BRACE_START + key + BRACE_END, String.valueOf(value)); 102 | return this; 103 | } 104 | 105 | public Kirai put(Piece piece) { 106 | Preconditions.checkNotNull(piece, "piece == null"); 107 | 108 | if (!tags.contains(piece.getKey())) { 109 | throw new IllegalArgumentException( 110 | "Tag {" + piece.getKey() + "} was not defined in input string"); 111 | } 112 | 113 | pieces.add(piece); 114 | return this; 115 | } 116 | 117 | /** 118 | * Returns CharSequence formatted with custom formatter implementation 119 | * 120 | * @param formatter implementation 121 | * @return formatted CharSequence 122 | */ 123 | public CharSequence format(Formatter formatter) { 124 | CharSequence input = format(); 125 | return formatter.format(String.valueOf(input)); 126 | } 127 | 128 | /** 129 | * Returns formatted CharSequence without additional operations 130 | * 131 | * @return formatted CharSequence 132 | */ 133 | public CharSequence format() { //NOPMD 134 | if (pieces.isEmpty()) { 135 | return input; 136 | } 137 | 138 | String target; 139 | 140 | for (Piece piece : pieces) { 141 | target = BRACE_START + piece.getKey() + BRACE_END; 142 | input = input.replace(target, String.valueOf(piece.getValue())); 143 | } 144 | 145 | return input; 146 | } 147 | 148 | /** 149 | * Checks whether input string is balanced Analyzes only curly braces like { and } and ignores 150 | * other characters 151 | * 152 | * @return true if string is balanced 153 | */ 154 | private boolean isInputBalanced() { 155 | Stack stack = new Stack<>(); 156 | int length = input.length(); 157 | for (int i = 0; i < length; i++) { 158 | char currentChar = input.charAt(i); 159 | if (currentChar == BRACE_START) { 160 | stack.push(currentChar); 161 | } else if (currentChar == BRACE_END) { 162 | if (stack.empty()) return false; 163 | if (stack.pop() != BRACE_START) return false; 164 | } 165 | } 166 | return stack.empty(); 167 | } 168 | 169 | @SuppressWarnings("PMD") 170 | private boolean areTagsValid() { 171 | tags = getTags(input); 172 | for (String tag : tags) { 173 | if (tag.matches(REGEX_VALID_TAG)) continue; 174 | return false; 175 | } 176 | return true; 177 | } 178 | 179 | private static List getTags(final String string) { 180 | final List tags = new ArrayList<>(); 181 | final Matcher matcher = REGEX_TAG.matcher(string); 182 | while (matcher.find()) { 183 | tags.add(matcher.group(1)); 184 | } 185 | return tags; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/Piece.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | public abstract class Piece { 19 | protected final Syntax syntax; //NOPMD 20 | protected final String key; //NOPMD 21 | protected Object value; //NOPMD 22 | 23 | public Piece(String key, Object value, Syntax syntax) { 24 | validatePair(key, value); 25 | Preconditions.checkNotNull(syntax, "syntax == null"); 26 | this.key = key; 27 | this.value = value; 28 | this.syntax = syntax; 29 | } 30 | 31 | private static void validatePair(String key, Object value) { 32 | Preconditions.checkNotEmpty(key, "key is empty"); 33 | Preconditions.checkNotEmpty(String.valueOf(value), "value is empty"); 34 | } 35 | 36 | public Piece bold() { 37 | value = String.format(syntax.getBoldFormat(), value); 38 | return this; 39 | } 40 | 41 | public Piece italic() { 42 | value = String.format(syntax.getItalicFormat(), value); 43 | return this; 44 | } 45 | 46 | public Piece underline() { 47 | value = String.format(syntax.getUnderlineFormat(), value); 48 | return this; 49 | } 50 | 51 | public Piece big() { 52 | value = String.format(syntax.getBigFormat(), value); 53 | return this; 54 | } 55 | 56 | public Piece small() { 57 | value = String.format(syntax.getSmallFormat(), value); 58 | return this; 59 | } 60 | 61 | public Piece sub() { 62 | value = String.format(syntax.getSubFormat(), value); 63 | return this; 64 | } 65 | 66 | public Piece sup() { 67 | value = String.format(syntax.getSupFormat(), value); 68 | return this; 69 | } 70 | 71 | public Piece color(String code) { 72 | syntax.validateColorCode(code); 73 | value = String.format(syntax.getColorFormat(), code, value); 74 | return this; 75 | } 76 | 77 | public String getKey() { 78 | return key; 79 | } 80 | 81 | public Object getValue() { 82 | return value; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/Preconditions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | public final class Preconditions { 19 | /** 20 | * Throws an exception with a message, when CharSequence is null 21 | * 22 | * @param str is a CharSequence to examine 23 | * @param message for IllegalArgumentException 24 | */ 25 | public static void checkNotEmpty(CharSequence str, String message) { 26 | if (str == null || str.length() == 0) { 27 | throw new IllegalArgumentException(message); 28 | } 29 | } 30 | 31 | /** 32 | * Throws an exception with a message, when object is null 33 | * 34 | * @param object to examine 35 | * @param message for IllegalArgumentException 36 | */ 37 | public static void checkNotNull(Object object, String message) { 38 | if (object == null) { 39 | throw new IllegalArgumentException(message); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/Syntax.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | public interface Syntax { 19 | String getBoldFormat(); 20 | 21 | String getItalicFormat(); 22 | 23 | String getUnderlineFormat(); 24 | 25 | String getColorFormat(); 26 | 27 | void validateColorCode(String code); 28 | 29 | String getBigFormat(); 30 | 31 | String getSmallFormat(); 32 | 33 | String getSubFormat(); 34 | 35 | String getSupFormat(); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/html/HtmlPiece.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library.html; 17 | 18 | import com.github.pwittchen.kirai.library.Piece; 19 | 20 | public final class HtmlPiece extends Piece { 21 | private HtmlPiece(String key, Object value) { 22 | super(key, value, new HtmlSyntax()); 23 | } 24 | 25 | public static Piece put(String key, Object value) { 26 | return new HtmlPiece(key, value); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/html/HtmlSyntax.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library.html; 17 | 18 | import com.github.pwittchen.kirai.library.Syntax; 19 | import com.github.pwittchen.kirai.library.Preconditions; 20 | 21 | public final class HtmlSyntax implements Syntax { 22 | private static final int COLOR_CODE_LENGTH = 7; 23 | private static final char COLOR_PREFIX = '#'; 24 | 25 | private final static String STRONG_FORMAT = "%s"; 26 | private final static String ITALIC_FORMAT = "%s"; 27 | private final static String UNDERLINE_FORMAT = "%s"; 28 | private final static String COLOR_FORMAT = "%s"; 29 | private final static String BIG_FORMAT = "%s"; 30 | private final static String SMALL_FORMAT = "%s"; 31 | private final static String SUB_FORMAT = "%s"; 32 | private final static String SUP_FORMAT = "%s"; 33 | 34 | @Override 35 | public String getBoldFormat() { 36 | return STRONG_FORMAT; 37 | } 38 | 39 | @Override 40 | public String getItalicFormat() { 41 | return ITALIC_FORMAT; 42 | } 43 | 44 | @Override 45 | public String getUnderlineFormat() { 46 | return UNDERLINE_FORMAT; 47 | } 48 | 49 | @Override 50 | public String getColorFormat() { 51 | return COLOR_FORMAT; 52 | } 53 | 54 | @Override 55 | public void validateColorCode(String code) { 56 | Preconditions.checkNotEmpty(code, "color code is empty"); 57 | 58 | if (code.length() != COLOR_CODE_LENGTH) { 59 | throw new IllegalArgumentException( 60 | "Hex value have to contain " 61 | + COLOR_CODE_LENGTH 62 | + " characters including hash sign (" 63 | + COLOR_PREFIX 64 | + ")"); 65 | } 66 | 67 | if (code.charAt(0) != COLOR_PREFIX) { 68 | throw new IllegalArgumentException( 69 | "Hex value have to start from hash sign (" + COLOR_PREFIX + ")"); 70 | } 71 | } 72 | 73 | @Override 74 | public String getBigFormat() { 75 | return BIG_FORMAT; 76 | } 77 | 78 | @Override 79 | public String getSmallFormat() { 80 | return SMALL_FORMAT; 81 | } 82 | 83 | @Override 84 | public String getSubFormat() { 85 | return SUB_FORMAT; 86 | } 87 | 88 | @Override 89 | public String getSupFormat() { 90 | return SUP_FORMAT; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/terminal/TerminalBgColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library.terminal; 17 | 18 | public enum TerminalBgColor { 19 | DEFAULT(49), WHITE(40), RED(41), GREEN(42), YELLOW(43), BLUE(44), MAGENTA(45), CYAN(46), 20 | LIGHT_GRAY(47), DARK_GRAY(100), LIGHT_RED(101), LIGHT_GREEN(102), LIGHT_YELLOW(103), 21 | LIGHT_BLUE(104), LIGHT_MAGENTA(105), LIGHT_CYAN(106), BLACK(107); 22 | 23 | private final int code; 24 | 25 | TerminalBgColor(int code) { 26 | this.code = code; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/terminal/TerminalColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library.terminal; 17 | 18 | public enum TerminalColor { 19 | DEFAULT(39), WHITE(30), RED(31), GREEN(32), YELLOW(33), BLUE(34), MAGENTA(35), CYAN(36), 20 | LIGHT_GRAY(37), DARK_GRAY(90), LIGHT_RED(91), LIGHT_GREEN(92), LIGHT_YELLOW(93), LIGHT_BLUE(94), 21 | LIGHT_MAGENTA(95), LIGHT_CYAN(96), BLACK(97); 22 | 23 | private final int code; 24 | 25 | TerminalColor(int code) { 26 | this.code = code; 27 | } 28 | 29 | public int getCode() { 30 | return code; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/terminal/TerminalPiece.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library.terminal; 17 | 18 | import com.github.pwittchen.kirai.library.Piece; 19 | 20 | public class TerminalPiece extends Piece { 21 | private TerminalPiece(String key, Object value) { 22 | super(key, value, new TerminalSyntax()); 23 | } 24 | 25 | public static TerminalPiece put(String key, Object value) { 26 | return new TerminalPiece(key, value); 27 | } 28 | 29 | public TerminalPiece color(TerminalColor color) { 30 | value = String.format(syntax.getColorFormat(), color.getCode(), value); 31 | return this; 32 | } 33 | 34 | public TerminalPiece background(TerminalBgColor color) { 35 | value = String.format(syntax.getColorFormat(), color.getCode(), value); 36 | return this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/pwittchen/kirai/library/terminal/TerminalSyntax.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library.terminal; 17 | 18 | import com.github.pwittchen.kirai.library.Preconditions; 19 | import com.github.pwittchen.kirai.library.Syntax; 20 | 21 | public class TerminalSyntax implements Syntax { 22 | private final static String ERROR_MSG_FORMAT = "%s format is currently not supported in Terminal"; 23 | private final static String STRONG_FORMAT = "\033[1m%s\033[21m"; 24 | private final static String UNDERLINE_FORMAT = "\033[39;4m%s\033[0m"; 25 | private final static String COLOR_FORMAT = "\033[%sm%s\033[0m"; 26 | 27 | @Override 28 | public String getBoldFormat() { 29 | return STRONG_FORMAT; 30 | } 31 | 32 | @Override 33 | public String getItalicFormat() { 34 | throw new UnsupportedOperationException(String.format(ERROR_MSG_FORMAT, "italic")); 35 | } 36 | 37 | @Override 38 | public String getUnderlineFormat() { 39 | return UNDERLINE_FORMAT; 40 | } 41 | 42 | @Override 43 | public String getColorFormat() { 44 | return COLOR_FORMAT; 45 | } 46 | 47 | /** 48 | * Validates terminal color code For reference check website: 49 | * http://misc.flogisoft.com/bash/tip_colors_and_formatting 50 | * 51 | * @param code numeric value as a String 52 | */ 53 | @Override 54 | public void validateColorCode(String code) { 55 | Preconditions.checkNotEmpty(code, "color code is empty"); 56 | Integer numericColorCode = Integer.valueOf(code); 57 | boolean isColorCodeValid = numericColorCode > 0 && numericColorCode < 257; 58 | if (!isColorCodeValid) { 59 | throw new IllegalArgumentException("color code should be a number between 1 and 256"); 60 | } 61 | } 62 | 63 | @Override 64 | public String getBigFormat() { 65 | throw new UnsupportedOperationException(String.format(ERROR_MSG_FORMAT, "big")); 66 | } 67 | 68 | @Override 69 | public String getSmallFormat() { 70 | throw new UnsupportedOperationException(String.format(ERROR_MSG_FORMAT, "small")); 71 | } 72 | 73 | @Override 74 | public String getSubFormat() { 75 | throw new UnsupportedOperationException(String.format(ERROR_MSG_FORMAT, "sub")); 76 | } 77 | 78 | @Override 79 | public String getSupFormat() { 80 | throw new UnsupportedOperationException(String.format(ERROR_MSG_FORMAT, "sup")); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/com/github/pwittchen/kirai/library/HtmlPieceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | import com.github.pwittchen.kirai.library.html.HtmlPiece; 19 | import com.github.pwittchen.kirai.library.html.HtmlSyntax; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import static com.google.common.truth.Truth.assertThat; 24 | 25 | @SuppressWarnings("PMD") 26 | public class HtmlPieceTest { 27 | 28 | private String testKey; 29 | private String testValue; 30 | private Syntax htmlSyntax; 31 | 32 | @Before 33 | public void setUp() { 34 | testKey = "testKey"; 35 | testValue = "testValue"; 36 | htmlSyntax = new HtmlSyntax(); 37 | } 38 | 39 | @Test 40 | public void testPut() throws Exception { 41 | // given 42 | // data in setUp() method 43 | 44 | // when 45 | Piece piece = HtmlPiece.put(testKey, testValue); 46 | 47 | // then 48 | assertThat(piece.getKey()).isEqualTo(testKey); 49 | assertThat(piece.getValue()).isEqualTo(testValue); 50 | } 51 | 52 | @Test(expected = IllegalArgumentException.class) 53 | public void testPutShouldThrowExceptionWhenKeyAndValueAreNull() throws Exception { 54 | // given 55 | String nullTestKey = null; 56 | String nullTestValue = null; 57 | 58 | // when 59 | HtmlPiece.put(nullTestKey, nullTestValue); 60 | 61 | // then 62 | // throw an exception 63 | } 64 | 65 | @Test(expected = IllegalArgumentException.class) 66 | public void testPutShouldThrowExceptionWhenKeyAndValueAreEmpty() throws Exception { 67 | // given 68 | String emptyTestKey = ""; 69 | String emptyTestValue = ""; 70 | 71 | // when 72 | HtmlPiece.put(emptyTestKey, emptyTestValue); 73 | 74 | // then 75 | // throw an exception 76 | } 77 | 78 | @Test 79 | public void testBoldHtml() throws Exception { 80 | // given 81 | String expectedFormattedValue = String.format(htmlSyntax.getBoldFormat(), testValue); 82 | 83 | // when 84 | Piece piece = HtmlPiece.put(testKey, testValue).bold(); 85 | 86 | // then 87 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 88 | } 89 | 90 | @Test 91 | public void testItalicHtml() throws Exception { 92 | // given 93 | String expectedFormattedValue = String.format(htmlSyntax.getItalicFormat(), testValue); 94 | 95 | // when 96 | Piece piece = HtmlPiece.put(testKey, testValue).italic(); 97 | 98 | // then 99 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 100 | } 101 | 102 | @Test 103 | public void testUnderlineHtml() throws Exception { 104 | // given 105 | String expectedFormattedValue = String.format(htmlSyntax.getUnderlineFormat(), testValue); 106 | 107 | // when 108 | Piece piece = HtmlPiece.put(testKey, testValue).underline(); 109 | 110 | // then 111 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 112 | } 113 | 114 | @Test 115 | public void testBigHtml() throws Exception { 116 | // given 117 | String expectedFormattedValue = String.format(htmlSyntax.getBigFormat(), testValue); 118 | 119 | // when 120 | Piece piece = HtmlPiece.put(testKey, testValue).big(); 121 | 122 | // then 123 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 124 | } 125 | 126 | @Test 127 | public void testSmallHtml() throws Exception { 128 | // given 129 | String expectedFormattedValue = String.format(htmlSyntax.getSmallFormat(), testValue); 130 | 131 | // when 132 | Piece piece = HtmlPiece.put(testKey, testValue).small(); 133 | 134 | // then 135 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 136 | } 137 | 138 | @Test 139 | public void testSubHtml() throws Exception { 140 | // given 141 | String expectedFormattedValue = String.format(htmlSyntax.getSubFormat(), testValue); 142 | 143 | // when 144 | Piece piece = HtmlPiece.put(testKey, testValue).sub(); 145 | 146 | // then 147 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 148 | } 149 | 150 | @Test 151 | public void testSupHtml() throws Exception { 152 | // given 153 | String expectedFormattedValue = String.format(htmlSyntax.getSupFormat(), testValue); 154 | 155 | // when 156 | Piece piece = HtmlPiece.put(testKey, testValue).sup(); 157 | 158 | // then 159 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 160 | } 161 | 162 | @Test 163 | public void testColorHtml() throws Exception { 164 | // given 165 | String testColorHexValue = "#FF0000"; 166 | String colorFormat = htmlSyntax.getColorFormat(); 167 | String expectedFormattedValue = String.format(colorFormat, testColorHexValue, testValue); 168 | 169 | // when 170 | Piece piece = HtmlPiece.put(testKey, testValue).color(testColorHexValue); 171 | 172 | // then 173 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 174 | } 175 | 176 | @Test(expected = IllegalArgumentException.class) 177 | public void testColorShouldThrowExceptionWhenHexIsNullForHtml() throws Exception { 178 | // given 179 | String nullTestColorHexValue = null; 180 | 181 | // when 182 | HtmlPiece.put(testKey, testValue).color(nullTestColorHexValue); 183 | 184 | // then 185 | // throw an exception 186 | } 187 | 188 | @Test(expected = IllegalArgumentException.class) 189 | public void testColorShouldThrowExceptionWhenHexIsEmptyForHtml() throws Exception { 190 | // given 191 | String emptyTestColorHexValue = ""; 192 | 193 | // when 194 | HtmlPiece.put(testKey, testValue).color(emptyTestColorHexValue); 195 | 196 | // then 197 | // throw an exception 198 | } 199 | 200 | @Test 201 | public void testColorHexShouldContainSevenCharactersForHtml() throws Exception { 202 | // given 203 | String correctTestColorHexValue = "#FFFFFF"; 204 | 205 | // when 206 | Piece piece = HtmlPiece.put(testKey, testValue).color(correctTestColorHexValue); 207 | 208 | // then 209 | // no exception occurs and object is created 210 | assertThat(piece).isNotNull(); 211 | } 212 | 213 | @Test(expected = IllegalArgumentException.class) 214 | public void testColorShouldThrowExceptionWhenHexDoesNotContainSevenCharacters() throws Exception { 215 | // given 216 | String incorrectTestColorHexValue = "#FFFFFFF"; 217 | 218 | // when 219 | HtmlPiece.put(testKey, testValue).color(incorrectTestColorHexValue); 220 | 221 | // then 222 | // throw an exception 223 | } 224 | 225 | @Test(expected = IllegalArgumentException.class) 226 | public void testColorShouldThrowExceptionWhenHexDoesNotStartFromHashForHtml() throws Exception { 227 | // given 228 | String incorrectTestColorHexValue = "F#FFFFF"; 229 | 230 | // when 231 | HtmlPiece.put(testKey, testValue).color(incorrectTestColorHexValue); 232 | 233 | // then 234 | // throw an exception 235 | } 236 | 237 | @Test 238 | public void testAllFormatsHtml() { 239 | /** 240 | * I realize that setting big and small at the same time doesn't make sense 241 | * as well as setting sub and sup at the same time. 242 | * This is done just for testing purposes in order to check 243 | * correctness of the formatting with all possible methods. 244 | */ 245 | 246 | // given 247 | String expectedFormattedValue; 248 | String testColorHexValue = "#FF0000"; 249 | expectedFormattedValue = String.format(htmlSyntax.getBoldFormat(), testValue); 250 | expectedFormattedValue = String.format(htmlSyntax.getItalicFormat(), expectedFormattedValue); 251 | expectedFormattedValue = String.format(htmlSyntax.getUnderlineFormat(), expectedFormattedValue); 252 | expectedFormattedValue = String.format(htmlSyntax.getBigFormat(), expectedFormattedValue); 253 | expectedFormattedValue = String.format(htmlSyntax.getSmallFormat(), expectedFormattedValue); 254 | expectedFormattedValue = String.format(htmlSyntax.getSubFormat(), expectedFormattedValue); 255 | expectedFormattedValue = String.format(htmlSyntax.getSupFormat(), expectedFormattedValue); 256 | expectedFormattedValue = 257 | String.format(htmlSyntax.getColorFormat(), testColorHexValue, expectedFormattedValue); 258 | 259 | // when 260 | Piece piece = HtmlPiece.put(testKey, testValue) 261 | .bold() 262 | .italic() 263 | .underline() 264 | .big() 265 | .small() 266 | .sub() 267 | .sup() 268 | .color(testColorHexValue); 269 | 270 | // then 271 | assertThat(piece.getValue()).isEqualTo(expectedFormattedValue); 272 | } 273 | } -------------------------------------------------------------------------------- /src/test/java/com/github/pwittchen/kirai/library/KiraiTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | import com.github.pwittchen.kirai.library.html.HtmlPiece; 19 | import org.junit.Test; 20 | 21 | import static com.google.common.truth.Truth.assertThat; 22 | 23 | @SuppressWarnings("PMD") 24 | public class KiraiTest { 25 | 26 | @Test 27 | public void testKiraiShouldSetAnInputAndNotBeNull() { 28 | // given 29 | String sampleString = "sample string"; 30 | 31 | // when 32 | Kirai kirai = Kirai.from(sampleString); 33 | 34 | // then 35 | // no exception is thrown and object is created 36 | assertThat(kirai).isNotNull(); 37 | } 38 | 39 | @Test 40 | public void testStringShouldBeBalanced() { 41 | // given 42 | String testTagOne = "tag_one"; 43 | String testTagTwo = "tag_two"; 44 | String testBalancedString = 45 | "Sample text {" + testTagOne + "} and {" + testTagTwo + "} rest of the sentence."; 46 | 47 | // when 48 | Kirai kirai = Kirai.from(testBalancedString); 49 | 50 | // then 51 | // no exception is thrown and object is created 52 | assertThat(kirai).isNotNull(); 53 | } 54 | 55 | @Test(expected = IllegalArgumentException.class) 56 | public void testShouldThrowExceptionWhenStringIsNotBeBalanced() { 57 | // given 58 | String testTagOne = "tag_one"; 59 | String testTagTwo = "tag_two"; 60 | String testNotBalancedString = 61 | "Sample text } {{ {" + testTagOne + "} and {" + testTagTwo + "} { rest of the sentence."; 62 | 63 | // when 64 | Kirai.from(testNotBalancedString); 65 | 66 | // then 67 | // throw an exception 68 | } 69 | 70 | @Test(expected = IllegalArgumentException.class) 71 | public void testShouldThrowExceptionWhenStringHasNoStartingBrace() { 72 | // given 73 | String testTag = "tag_one"; 74 | String testNotBalancedString = testTag + "}"; 75 | 76 | // when 77 | Kirai.from(testNotBalancedString); 78 | 79 | // then 80 | // throw an exception 81 | } 82 | 83 | @Test(expected = IllegalArgumentException.class) 84 | public void testShouldThrowExceptionWhenStringHasNoEndingBrace() { 85 | // given 86 | String testTag = "tag_one"; 87 | String testNotBalancedString = "{" + testTag; 88 | 89 | // when 90 | Kirai.from(testNotBalancedString); 91 | 92 | // then 93 | // throw an exception 94 | } 95 | 96 | @Test(expected = IllegalArgumentException.class) 97 | public void testShouldThrowExceptionWhenInputStringIsNull() { 98 | // given 99 | String testInputString = null; 100 | 101 | // when 102 | Kirai.from(testInputString); 103 | 104 | // then 105 | // throw an exception 106 | } 107 | 108 | @Test(expected = IllegalArgumentException.class) 109 | public void testShouldThrowExceptionWhenInputStringIsEmpty() { 110 | // given 111 | String testInputString = ""; 112 | 113 | // when 114 | Kirai.from(testInputString); 115 | 116 | // then 117 | // throw an exception 118 | } 119 | 120 | @Test(expected = IllegalArgumentException.class) 121 | public void testShouldThrowExceptionWhenKeyAndValueAreNull() { 122 | // given 123 | String testTagOne = "tag_one"; 124 | String testTagTwo = "tag_two"; 125 | String testBalancedString = 126 | "Sample text {" + testTagOne + "} and {" + testTagTwo + "} rest of the sentence."; 127 | String nullTestKey = null; 128 | String nullTestValue = null; 129 | 130 | // when 131 | Kirai.from(testBalancedString).put(nullTestKey, nullTestValue); 132 | 133 | // then 134 | // throw an exception 135 | } 136 | 137 | @Test(expected = IllegalArgumentException.class) 138 | public void testShouldThrowExceptionWhenKeyAndValueAreEmpty() { 139 | // given 140 | String testTagOne = "tag_one"; 141 | String testTagTwo = "tag_two"; 142 | String testBalancedString = 143 | "Sample text {" + testTagOne + "} and {" + testTagTwo + "} rest of the sentence."; 144 | String emptyTestKey = ""; 145 | String emptyTestValue = ""; 146 | 147 | // when 148 | Kirai.from(testBalancedString).put(emptyTestKey, emptyTestValue); 149 | 150 | // then 151 | // throw an exception 152 | } 153 | 154 | @Test(expected = IllegalArgumentException.class) 155 | public void testShouldThrowExceptionWhenPieceIsNull() { 156 | // given 157 | Piece nullPiece = null; 158 | String testTagOne = "tag_one"; 159 | String testInputString = "Sample text {" + testTagOne + "} rest of the sentence."; 160 | 161 | // when 162 | Kirai.from(testInputString).put(nullPiece); 163 | 164 | // then 165 | // throw an exception 166 | } 167 | 168 | @Test(expected = IllegalArgumentException.class) 169 | public void testShouldThrowExceptionWhenPieceHasKeyNotDefinedInInputString() { 170 | // given 171 | String testValue = "test value"; 172 | String notPresentTestTag = "test_tag_NOT_present"; 173 | Piece testPiece = HtmlPiece.put(notPresentTestTag, testValue); 174 | String testTagOne = "tag_one"; 175 | String testInputString = "Sample text {" + testTagOne + "} rest of the sentence."; 176 | 177 | // when 178 | Kirai.from(testInputString).put(testPiece); 179 | 180 | // then 181 | // throw an exception 182 | } 183 | 184 | @Test 185 | public void testPutShouldAddKeyAndValue() { 186 | // given 187 | String testKey = "test_tag_present"; 188 | String testValue = "test value"; 189 | String testInputString = "Sample text {" + testKey + "} rest of the sentence."; 190 | String expectedOutPutString = "Sample text " + testValue + " rest of the sentence."; 191 | 192 | // when 193 | CharSequence generatedCharSequence = 194 | Kirai.from(testInputString).put(testKey, testValue).format(); 195 | 196 | // then 197 | assertThat(generatedCharSequence).isEqualTo(expectedOutPutString); 198 | } 199 | 200 | @Test 201 | public void testPutShouldAddPiece() { 202 | // given 203 | String testKey = "test_tag_present"; 204 | String testValue = "test value"; 205 | String testInputString = "Sample text {" + testKey + "} rest of the sentence."; 206 | String expectedOutPutString = "Sample text " + testValue + " rest of the sentence."; 207 | 208 | // when 209 | CharSequence generatedCharSequence = Kirai.from(testInputString) 210 | .put(HtmlPiece.put(testKey, testValue)) 211 | .format(); 212 | 213 | // then 214 | assertThat(generatedCharSequence).isEqualTo(expectedOutPutString); 215 | } 216 | 217 | @Test(expected = IllegalArgumentException.class) 218 | public void testPutShouldThrowExceptionWhenKeyIsNotDefinedInInputString() { 219 | // given 220 | String presentTestTag = "test_tag_present"; 221 | String notPresentTestTag = "test_tag_NOT_present"; 222 | String testValue = "test value"; 223 | String testInputString = "Sample text {" + presentTestTag + "} rest of the sentence."; 224 | 225 | // when 226 | Kirai.from(testInputString).put(notPresentTestTag, testValue); 227 | 228 | // then throw an exception 229 | } 230 | 231 | @Test(expected = IllegalArgumentException.class) 232 | public void testPutShouldThrowAnExceptionWhenKeyIsAnEmptyString() { 233 | // given 234 | String testKey = ""; 235 | String testValue = "test value"; 236 | String testInputString = "Sample text {" + testKey + "} rest of the sentence."; 237 | 238 | // when 239 | Kirai.from(testInputString).put(testKey, testValue).format(); 240 | 241 | // then throw an exception 242 | } 243 | 244 | @Test(expected = IllegalArgumentException.class) 245 | public void testPutShouldThrowAnExceptionWhenKeyIsNull() { 246 | // given 247 | String testKey = null; 248 | String testValue = "test value"; 249 | String testInputString = "Sample text {" + testKey + "} rest of the sentence."; 250 | 251 | // when 252 | Kirai.from(testInputString).put(testKey, testValue).format(); 253 | 254 | // then throw an exception 255 | } 256 | 257 | @Test(expected = IllegalArgumentException.class) 258 | public void testPutShouldThrowAnExceptionWhenValueIsAnEmptyString() { 259 | String testKey = "testKey"; 260 | String testValue = ""; 261 | String testInputString = "Sample text {" + testKey + "} rest of the sentence."; 262 | 263 | // when 264 | Kirai.from(testInputString).put(testKey, testValue).format(); 265 | 266 | // then throw an exception 267 | } 268 | 269 | @Test(expected = IllegalArgumentException.class) 270 | public void testPutShouldThrowAnExceptionWhenValueIsNull() { 271 | String testKey = "testKey"; 272 | String testValue = null; 273 | String testInputString = "Sample text {" + testKey + "} rest of the sentence."; 274 | 275 | // when 276 | Kirai.from(testInputString).put(testKey, testValue).format(); 277 | 278 | // then throw an exception 279 | } 280 | 281 | @Test(expected = IllegalArgumentException.class) 282 | public void testFromShouldThrowExceptionWhenKeyStartsFromNumber() { 283 | // given 284 | String incorrectTestTag = "1_incorrect_tag"; 285 | String testInputString = "Sample text {" + incorrectTestTag + "} rest of the sentence."; 286 | 287 | // when 288 | Kirai.from(testInputString); 289 | 290 | // then 291 | // throw an exception 292 | } 293 | 294 | @Test(expected = IllegalArgumentException.class) 295 | public void testFromShouldThrowExceptionWhenKeyStartsFromUnderscore() { 296 | // given 297 | String incorrectTestTag = "_incorrect_tag"; 298 | String testInputString = "Sample text {" + incorrectTestTag + "} rest of the sentence."; 299 | 300 | // when 301 | Kirai.from(testInputString); 302 | 303 | // then 304 | // throw an exception 305 | } 306 | 307 | @Test(expected = IllegalArgumentException.class) 308 | public void testFromShouldThrowExceptionWhenKeyStartsFromSpecialCharacter() { 309 | // given 310 | String incorrectTestTag = "!_incorrect_tag"; 311 | String testInputString = "Sample text {" + incorrectTestTag + "} rest of the sentence."; 312 | 313 | // when 314 | Kirai.from(testInputString); 315 | 316 | // then 317 | // throw an exception 318 | } 319 | 320 | @Test(expected = IllegalArgumentException.class) 321 | public void testFromShouldThrowExceptionWhenKeyContainsSpecialCharacters() { 322 | // given 323 | String incorrectTestTag = "#!@ tag &^*_"; 324 | String testInputString = "Sample text {" + incorrectTestTag + "} rest of the sentence."; 325 | 326 | // when 327 | Kirai.from(testInputString); 328 | 329 | // then 330 | // throw an exception 331 | } 332 | 333 | @Test 334 | public void testFormatterShouldFormatInput() { 335 | // given 336 | // formatter below is created for test purposes and it can do anything 337 | Formatter upperCaseTestFormatter = new Formatter() { 338 | @Override 339 | public CharSequence format(String input) { 340 | return input.toString().toUpperCase(); 341 | } 342 | }; 343 | 344 | String input = "value"; 345 | String expectedOutput = "VALUE"; 346 | 347 | // when 348 | CharSequence output = Kirai.from(input).format(upperCaseTestFormatter); 349 | 350 | // then 351 | assertThat(output).isEqualTo(expectedOutput); 352 | } 353 | } -------------------------------------------------------------------------------- /src/test/java/com/github/pwittchen/kirai/library/PreconditionsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Piotr Wittchen 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 | package com.github.pwittchen.kirai.library; 17 | 18 | import org.junit.Test; 19 | 20 | import static com.google.common.truth.Truth.assertThat; 21 | 22 | public class PreconditionsTest { 23 | 24 | @Test 25 | public void testShouldInitializePreconditions() { 26 | Preconditions preconditions = new Preconditions(); 27 | assertThat(preconditions).isNotNull(); 28 | } 29 | 30 | @Test(expected = IllegalArgumentException.class) 31 | public void testStringShouldBeEmpty() { 32 | // given 33 | String emptyString = ""; 34 | 35 | // when 36 | Preconditions.checkNotEmpty(emptyString, "string is empty"); 37 | 38 | // then 39 | // an exception is thrown 40 | } 41 | 42 | @Test(expected = IllegalArgumentException.class) 43 | public void testNullStringShouldBeEmpty() { 44 | // given 45 | String emptyString = null; 46 | 47 | // when 48 | Preconditions.checkNotEmpty(emptyString, "string is empty"); 49 | 50 | // then 51 | // an exception is thrown 52 | } 53 | 54 | @Test 55 | public void testStringShouldNotBeEmpty() { 56 | // given 57 | String notEmptyString = "not empty string"; 58 | 59 | // when 60 | Preconditions.checkNotEmpty(notEmptyString, "string is empty"); 61 | 62 | // then 63 | // no exception is thrown 64 | } 65 | 66 | @Test 67 | public void testShouldNotThrowAnyExceptionWhenObjectIsNotNull() { 68 | // given 69 | Object object = new Object(); 70 | 71 | // when 72 | Preconditions.checkNotNull(object, "object == null"); 73 | 74 | // then 75 | assertThat(object).isNotNull(); // and no exception is thrown 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/com/github/pwittchen/kirai/library/TerminalPieceTest.java: -------------------------------------------------------------------------------- 1 | package com.github.pwittchen.kirai.library; 2 | 3 | import com.github.pwittchen.kirai.library.terminal.TerminalBgColor; 4 | import com.github.pwittchen.kirai.library.terminal.TerminalColor; 5 | import com.github.pwittchen.kirai.library.terminal.TerminalPiece; 6 | import org.junit.Test; 7 | 8 | import static com.google.common.truth.Truth.assertThat; 9 | 10 | public class TerminalPieceTest { 11 | 12 | @Test 13 | public void testShouldPutTerminalPiece() { 14 | // given 15 | String key = "key"; 16 | String value = "value"; 17 | 18 | // when 19 | TerminalPiece piece = TerminalPiece.put(key, value); 20 | 21 | // then 22 | assertThat(piece).isNotNull(); 23 | } 24 | 25 | @Test 26 | public void testShouldPutTerminalPieceWithTerminalColor() { 27 | // given 28 | String key = "key"; 29 | String value = "value"; 30 | 31 | // when 32 | TerminalPiece piece = TerminalPiece.put(key, value).color(TerminalColor.BLACK); 33 | 34 | // then 35 | assertThat(piece).isNotNull(); 36 | } 37 | 38 | @Test 39 | public void testShouldPutTerminalPieceWithTerminalBackgroundColor() { 40 | // given 41 | String key = "key"; 42 | String value = "value"; 43 | 44 | // when 45 | TerminalPiece piece = TerminalPiece.put(key, value).background(TerminalBgColor.BLACK); 46 | 47 | // then 48 | assertThat(piece).isNotNull(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/github/pwittchen/kirai/library/TerminalSyntaxTest.java: -------------------------------------------------------------------------------- 1 | package com.github.pwittchen.kirai.library; 2 | 3 | import com.github.pwittchen.kirai.library.terminal.TerminalSyntax; 4 | import org.junit.Test; 5 | 6 | import static com.google.common.truth.Truth.assertThat; 7 | 8 | @SuppressWarnings("PMD") 9 | public class TerminalSyntaxTest { 10 | 11 | private Syntax syntax = new TerminalSyntax(); 12 | 13 | @Test(expected = UnsupportedOperationException.class) 14 | public void testItalicFormatShouldNotBeSupported() { 15 | syntax.getItalicFormat(); 16 | } 17 | 18 | @Test(expected = UnsupportedOperationException.class) 19 | public void testBigFormatShouldNotBeSupported() { 20 | syntax.getBigFormat(); 21 | } 22 | 23 | @Test(expected = UnsupportedOperationException.class) 24 | public void testSmallFormatShouldNotBeSupported() { 25 | syntax.getSmallFormat(); 26 | } 27 | 28 | @Test(expected = UnsupportedOperationException.class) 29 | public void testSubFormatShouldNotBeSupported() { 30 | syntax.getSubFormat(); 31 | } 32 | 33 | @Test(expected = UnsupportedOperationException.class) 34 | public void testSupFormatShouldNotBeSupported() { 35 | syntax.getSupFormat(); 36 | } 37 | 38 | @Test 39 | public void testColorCodeShouldBeValid() { 40 | // given 41 | String validColorCode = "150"; // number greater than 0 and lower than 257 42 | 43 | // when 44 | syntax.validateColorCode(validColorCode); 45 | 46 | // then no exception is thrown 47 | } 48 | 49 | @Test(expected = IllegalArgumentException.class) 50 | public void testColorCodeShouldBeInValidForZero() { 51 | // given 52 | String invalidColorCode = "0"; 53 | 54 | // when 55 | syntax.validateColorCode(invalidColorCode); 56 | 57 | // then an exception is thrown 58 | } 59 | 60 | @Test(expected = IllegalArgumentException.class) 61 | public void testColorCodeShouldBeInValidForNumberLowerThanZero() { 62 | // given 63 | String invalidColorCode = "-3"; 64 | 65 | // when 66 | syntax.validateColorCode(invalidColorCode); 67 | 68 | // then an exception is thrown 69 | } 70 | 71 | @Test(expected = IllegalArgumentException.class) 72 | public void testColorCodeShouldBeInValidForNumberGreaterThan256() { 73 | // given 74 | String invalidColorCode = "258"; 75 | 76 | // when 77 | syntax.validateColorCode(invalidColorCode); 78 | 79 | // then an exception is thrown 80 | } 81 | 82 | @Test 83 | public void testShouldHaveCorrectBoldFormat() { 84 | // given 85 | String expectedFormat = "\033[1m%s\033[21m"; 86 | 87 | // when 88 | String format = syntax.getBoldFormat(); 89 | 90 | // then 91 | assertThat(format).isEqualTo(expectedFormat); 92 | } 93 | 94 | @Test 95 | public void testShouldHaveCorrectUnderlineFormat() { 96 | // given 97 | String expectedFormat = "\033[39;4m%s\033[0m"; 98 | 99 | // when 100 | String format = syntax.getUnderlineFormat(); 101 | 102 | // then 103 | assertThat(format).isEqualTo(expectedFormat); 104 | } 105 | 106 | @Test 107 | public void testShouldHaveCorrectColorFormat() { 108 | // given 109 | String expectedFormat = "\033[%sm%s\033[0m"; 110 | 111 | // when 112 | String format = syntax.getColorFormat(); 113 | 114 | // then 115 | assertThat(format).isEqualTo(expectedFormat); 116 | } 117 | } 118 | --------------------------------------------------------------------------------