├── .github └── FUNDING.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── DOCUMENTATION.md ├── LICENSE ├── README.md ├── example └── index.js ├── lib └── index.js ├── package-lock.json ├── package.json └── test └── index.js /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: ionicabizau 2 | patreon: ionicabizau 3 | open_collective: ionicabizau 4 | custom: https://www.buymeacoffee.com/h96wwchmy -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | *~ 4 | *.log 5 | node_modules 6 | *.env 7 | .DS_Store 8 | package-lock.json 9 | .bloggify/* 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 🌟 Contributing 2 | 3 | Want to contribute to this project? Great! Please read these quick steps to streamline the process and avoid unnecessary tasks. ✨ 4 | 5 | ## 💬 Discuss Changes 6 | Start by opening an issue in the repository using the [bug tracker][1]. Describe your proposed contribution or the bug you've found. If relevant, include platform info and screenshots. 🖼️ 7 | 8 | Wait for feedback before proceeding unless the fix is straightforward, like a typo. 📝 9 | 10 | ## 🔧 Fixing Issues 11 | 12 | Fork the project and create a branch for your fix, naming it `some-great-feature` or `some-issue-fix`. Commit changes while following the [code style][2]. If the project has tests, add one. ✅ 13 | 14 | If a `package.json` or `bower.json` exists, add yourself to the `contributors` array; create it if it doesn't. 🙌 15 | 16 | ```json 17 | { 18 | "contributors": [ 19 | "Your Name (http://your.website)" 20 | ] 21 | } 22 | ``` 23 | 24 | ## 📬 Creating a Pull Request 25 | Open a pull request and reference the initial issue (e.g., *fixes #*). Provide a clear title and consider adding visual aids for clarity. 📊 26 | 27 | ## ⏳ Wait for Feedback 28 | Your contributions will be reviewed. If feedback is given, update your branch as needed, and the pull request will auto-update. 🔄 29 | 30 | ## 🎉 Everyone Is Happy! 31 | Your contributions will be merged, and everyone will appreciate your effort! 😄❤️ 32 | 33 | Thanks! 🤩 34 | 35 | [1]: /issues 36 | [2]: https://github.com/IonicaBizau/code-style -------------------------------------------------------------------------------- /DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | You can see below the API reference of this module. 4 | 5 | ### `CliPie(r, data, options)` 6 | Creates a new instance of `CliPie`. 7 | 8 | #### Params 9 | 10 | - **Number** `r`: The radius value. 11 | - **Array** `data`: An array of objects in the following format: 12 | - **Object** `options`: An object containing the following fields: 13 | - `flat` (Boolean): If `true`, flat colors will be used (default: `true`). 14 | - `chr` (String): The character to draw the pie (default: `" "`). 15 | - `no_ansi` (Boolean): If `true`, ansi styles will not be used. 16 | - `legend` (Boolean): If `true`, a legend is added next to the pie. 17 | - `display_total` (Boolean): If `true`, the total is added to the legend. 18 | - `total_label` (String): The label for the total (default: `Total`) 19 | - `circle_opts` (Object): The options passed to the 20 | [`cli-circle`](https://github.com/IonicaBizau/node-cli-circle) module, 21 | which uses the 22 | [`cli-graph`](https://github.com/IonicaBizau/node-cli-graph) module to 23 | build the graph. 24 | 25 | #### Return 26 | - **CliPie** The `CliPie` instance. 27 | 28 | ### `CLiPie.Item(obj)` 29 | CliPie.Item 30 | Creates a new `CliPie.Item` instance. 31 | 32 | #### Params 33 | 34 | - **Object** `obj`: The `CliPie.Item` data containing: 35 | - `value` (Number): The item value. 36 | - `label` (String): The item label. 37 | - `color` (String): The item color (used in ansi graphs). 38 | - `letter` (String): The item letter (used on non-ansi graphs). 39 | 40 | #### Return 41 | - **CliPieItem** The `CliPieItem` containing: 42 | 43 | ### `add(item)` 44 | Adds new items in the cli pie. 45 | 46 | #### Params 47 | 48 | - **Object** `item`: The item data. 49 | 50 | #### Return 51 | - **CliPie** The `CliPie` instance. 52 | 53 | ### `textColor(text, color, fg, bg)` 54 | Adds foreground or/and background color(s) to the provided text. 55 | 56 | #### Params 57 | 58 | - **String** `text`: The text to color. 59 | - **String** `color`: The color value. 60 | - **Boolean** `fg`: If `true`, the function will modify the foreground color of the text (default: `true`). 61 | - **Boolean** `bg`: If `true`, the function will modify the background color of the text. 62 | 63 | #### Return 64 | - **String** The colored text. 65 | 66 | ### `uniqueColor(cColor)` 67 | Generates an unique color. 68 | 69 | #### Params 70 | 71 | - **String** `cColor`: The provided color. 72 | 73 | #### Return 74 | - **String** The unique color. 75 | 76 | ### `toString()` 77 | Stringifies the pie. 78 | 79 | #### Return 80 | - **String** The stringified pie. 81 | 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-25 Ionică Bizău (https://ionicabizau.net) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | [![cli-pie](http://i.imgur.com/FcSpq0W.png)](#) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | # cli-pie 23 | 24 | [![Support me on Patreon][badge_patreon]][patreon] [![Buy me a book][badge_amazon]][amazon] [![PayPal][badge_paypal_donate]][paypal-donations] [![Ask me anything](https://img.shields.io/badge/ask%20me-anything-1abc9c.svg)](https://github.com/IonicaBizau/ama) [![Travis](https://img.shields.io/travis/IonicaBizau/node-cli-pie.svg)](https://travis-ci.org/IonicaBizau/node-cli-pie/) [![Version](https://img.shields.io/npm/v/cli-pie.svg)](https://www.npmjs.com/package/cli-pie) [![Downloads](https://img.shields.io/npm/dt/cli-pie.svg)](https://www.npmjs.com/package/cli-pie) [![Get help on Codementor](https://cdn.codementor.io/badges/get_help_github.svg)](https://www.codementor.io/@johnnyb?utm_source=github&utm_medium=button&utm_term=johnnyb&utm_campaign=github) 25 | 26 | Buy Me A Coffee 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | > Generate pie charts in terminal and text mode. 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | [![cli-pie](http://i.imgur.com/6VA7578.png)](#) 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ## :cloud: Installation 55 | 56 | ```sh 57 | # Using npm 58 | npm install --save cli-pie 59 | 60 | # Using yarn 61 | yarn add cli-pie 62 | ``` 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | ## :clipboard: Example 77 | 78 | 79 | 80 | ```js 81 | // Dependencies 82 | var Pie = require("cli-pie"); 83 | 84 | // Generate a new pie, with radius 5 characters 85 | var p = new Pie(5, [ 86 | { label: "Water", value: 70, color: [ 0, 0, 255] } 87 | , { label: "Land", value: 30, color: [255, 240, 0] } 88 | ], { 89 | legend: true 90 | }); 91 | 92 | // Stringify 93 | console.log(p.toString()); 94 | 95 | // Stringify, after disabling the ansi styles 96 | p.options.no_ansi = true; 97 | console.log(p.toString()); 98 | 99 | // Add a new item 100 | p.add({ 101 | label: "Test" 102 | , value: 20 103 | }); 104 | 105 | // Enable the ansi styles 106 | p.options.no_ansi = false; 107 | console.log(p.toString()); 108 | 109 | // Disable the ansi styles and reset colors 110 | p.options.no_ansi = true; 111 | p.colors = {}; 112 | console.log(p.toString()); 113 | ``` 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | ## :question: Get Help 127 | 128 | There are few ways to get help: 129 | 130 | 131 | 132 | 1. Please [post questions on Stack Overflow](https://stackoverflow.com/questions/ask). You can open issues with questions, as long you add a link to your Stack Overflow question. 133 | 2. For bug reports and feature requests, open issues. :bug: 134 | 3. For direct and quick help, you can [use Codementor](https://www.codementor.io/johnnyb). :rocket: 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | ## :memo: Documentation 143 | 144 | 145 | ### `CliPie(r, data, options)` 146 | Creates a new instance of `CliPie`. 147 | 148 | #### Params 149 | 150 | - **Number** `r`: The radius value. 151 | - **Array** `data`: An array of objects in the following format: 152 | - **Object** `options`: An object containing the following fields: 153 | - `flat` (Boolean): If `true`, flat colors will be used (default: `true`). 154 | - `chr` (String): The character to draw the pie (default: `" "`). 155 | - `no_ansi` (Boolean): If `true`, ansi styles will not be used. 156 | - `legend` (Boolean): If `true`, a legend is added next to the pie. 157 | - `display_total` (Boolean): If `true`, the total is added to the legend. 158 | - `total_label` (String): The label for the total (default: `Total`) 159 | - `circle_opts` (Object): The options passed to the 160 | [`cli-circle`](https://github.com/IonicaBizau/node-cli-circle) module, 161 | which uses the 162 | [`cli-graph`](https://github.com/IonicaBizau/node-cli-graph) module to 163 | build the graph. 164 | 165 | #### Return 166 | - **CliPie** The `CliPie` instance. 167 | 168 | ### `CLiPie.Item(obj)` 169 | CliPie.Item 170 | Creates a new `CliPie.Item` instance. 171 | 172 | #### Params 173 | 174 | - **Object** `obj`: The `CliPie.Item` data containing: 175 | - `value` (Number): The item value. 176 | - `label` (String): The item label. 177 | - `color` (String): The item color (used in ansi graphs). 178 | - `letter` (String): The item letter (used on non-ansi graphs). 179 | 180 | #### Return 181 | - **CliPieItem** The `CliPieItem` containing: 182 | 183 | ### `add(item)` 184 | Adds new items in the cli pie. 185 | 186 | #### Params 187 | 188 | - **Object** `item`: The item data. 189 | 190 | #### Return 191 | - **CliPie** The `CliPie` instance. 192 | 193 | ### `textColor(text, color, fg, bg)` 194 | Adds foreground or/and background color(s) to the provided text. 195 | 196 | #### Params 197 | 198 | - **String** `text`: The text to color. 199 | - **String** `color`: The color value. 200 | - **Boolean** `fg`: If `true`, the function will modify the foreground color of the text (default: `true`). 201 | - **Boolean** `bg`: If `true`, the function will modify the background color of the text. 202 | 203 | #### Return 204 | - **String** The colored text. 205 | 206 | ### `uniqueColor(cColor)` 207 | Generates an unique color. 208 | 209 | #### Params 210 | 211 | - **String** `cColor`: The provided color. 212 | 213 | #### Return 214 | - **String** The unique color. 215 | 216 | ### `toString()` 217 | Stringifies the pie. 218 | 219 | #### Return 220 | - **String** The stringified pie. 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | ## :yum: How to contribute 236 | Have an idea? Found a bug? See [how to contribute][contributing]. 237 | 238 | 239 | ## :sparkling_heart: Support my projects 240 | I open-source almost everything I can, and I try to reply to everyone needing help using these projects. Obviously, 241 | this takes time. You can integrate and use these projects in your applications *for free*! You can even change the source code and redistribute (even resell it). 242 | 243 | However, if you get some profit from this or just want to encourage me to continue creating stuff, there are few ways you can do it: 244 | 245 | 246 | - Starring and sharing the projects you like :rocket: 247 | - [![Buy me a book][badge_amazon]][amazon]—I love books! I will remember you after years if you buy me one. :grin: :book: 248 | - [![PayPal][badge_paypal]][paypal-donations]—You can make one-time donations via PayPal. I'll probably buy a ~~coffee~~ tea. :tea: 249 | - [![Support me on Patreon][badge_patreon]][patreon]—Set up a recurring monthly donation and you will get interesting news about what I'm doing (things that I don't share with everyone). 250 | - **Bitcoin**—You can send me bitcoins at this address (or scanning the code below): `1P9BRsmazNQcuyTxEqveUsnf5CERdq35V6` 251 | 252 | ![](https://i.imgur.com/z6OQI95.png) 253 | 254 | 255 | Thanks! :heart: 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | ## :dizzy: Where is this library used? 273 | If you are using this library in one of your projects, add it in this list. :sparkles: 274 | 275 | - `@childduckling/school-loop` 276 | - `@tool3/kpods` 277 | - `android-api-versions-console-chart` 278 | - `cabdriver` 279 | - `dupie` 280 | - `files-extensions` 281 | - `free-pie` 282 | - `gdf` 283 | - `gh-polyglot` 284 | - `git-stats` 285 | - `github-stats` 286 | - `how-dep` 287 | - `learn-memory-statistics-cli` 288 | - `neobrag` 289 | - `pie-my-vulns` 290 | - `productivity-timer` 291 | - `tempera` 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | ## :scroll: License 304 | 305 | [MIT][license] © [Ionică Bizău][website] 306 | 307 | 308 | 309 | 310 | 311 | 312 | [license]: /LICENSE 313 | [website]: https://ionicabizau.net 314 | [contributing]: /CONTRIBUTING.md 315 | [docs]: /DOCUMENTATION.md 316 | [badge_patreon]: https://ionicabizau.github.io/badges/patreon.svg 317 | [badge_amazon]: https://ionicabizau.github.io/badges/amazon.svg 318 | [badge_paypal]: https://ionicabizau.github.io/badges/paypal.svg 319 | [badge_paypal_donate]: https://ionicabizau.github.io/badges/paypal_donate.svg 320 | [patreon]: https://www.patreon.com/ionicabizau 321 | [amazon]: http://amzn.eu/hRo9sIZ 322 | [paypal-donations]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RVXDDLKKLQRJW 323 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | var Pie = require("../lib"); 3 | 4 | // Generate a new pie, with radius 5 characters 5 | var p = new Pie(5, [ 6 | { label: "Water", value: 70, color: [ 0, 0, 255] } 7 | , { label: "Land", value: 30, color: [255, 240, 0] } 8 | ], { 9 | legend: true 10 | }); 11 | 12 | // Stringify 13 | console.log(p.toString()); 14 | 15 | // Stringify, after disabling the ansi styles 16 | p.options.no_ansi = true; 17 | console.log(p.toString()); 18 | 19 | // Add a new item 20 | p.add({ 21 | label: "Test" 22 | , value: 20 23 | }); 24 | 25 | // Enable the ansi styles 26 | p.options.no_ansi = false; 27 | console.log(p.toString()); 28 | 29 | // Disable the ansi styles and reset colors 30 | p.options.no_ansi = true; 31 | p.colors = {}; 32 | console.log(p.toString()); 33 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | var Ul = require("ul") 3 | , FlatColors = require("flatcolors") 4 | , CliCircle = require("cli-circle") 5 | , Couleurs = require("couleurs") 6 | ; 7 | 8 | /** 9 | * CliPie 10 | * Creates a new instance of `CliPie`. 11 | * 12 | * @name CliPie 13 | * @function 14 | * @param {Number} r The radius value. 15 | * @param {Array} data An array of objects in the following format: 16 | * @param {Object} options An object containing the following fields: 17 | * 18 | * - `flat` (Boolean): If `true`, flat colors will be used (default: `true`). 19 | * - `chr` (String): The character to draw the pie (default: `" "`). 20 | * - `no_ansi` (Boolean): If `true`, ansi styles will not be used. 21 | * - `legend` (Boolean): If `true`, a legend is added next to the pie. 22 | * - `display_total` (Boolean): If `true`, the total is added to the legend. 23 | * - `total_label` (String): The label for the total (default: `Total`) 24 | * - `circle_opts` (Object): The options passed to the 25 | * [`cli-circle`](https://github.com/IonicaBizau/node-cli-circle) module, 26 | * which uses the 27 | * [`cli-graph`](https://github.com/IonicaBizau/node-cli-graph) module to 28 | * build the graph. 29 | * 30 | * @return {CliPie} The `CliPie` instance. 31 | */ 32 | function CliPie(r, data, options) { 33 | this.data = []; 34 | this.radius = r; 35 | this.total = 0; 36 | this.colors = {}; 37 | this.cChar = -1; 38 | this.options = Ul.deepMerge(options, { 39 | flat: true 40 | , chr: " " 41 | , no_ansi: false 42 | , circle_opts: { 43 | aRatio: 1 44 | } 45 | , chars: "abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("") 46 | }); 47 | if (Array.isArray(data)) { 48 | data.forEach(this.add.bind(this)); 49 | } else if (data && data.constructor === Object) { 50 | options = data; 51 | } 52 | } 53 | 54 | /** 55 | * CliPie.Item 56 | * Creates a new `CliPie.Item` instance. 57 | * 58 | * @name CLiPie.Item 59 | * @function 60 | * @param {Object} obj The `CliPie.Item` data containing: 61 | * 62 | * - `value` (Number): The item value. 63 | * - `label` (String): The item label. 64 | * - `color` (String): The item color (used in ansi graphs). 65 | * - `letter` (String): The item letter (used on non-ansi graphs). 66 | * 67 | * @return {CliPieItem} The `CliPieItem` containing: 68 | */ 69 | CliPie.Item = function (obj) { 70 | this.value = obj.value; 71 | this.label = obj.label; 72 | this.color = obj.color; 73 | this.percent = null; 74 | this.angle = null; 75 | this.letter = obj.letter; 76 | }; 77 | 78 | /** 79 | * add 80 | * Adds new items in the cli pie. 81 | * 82 | * @name add 83 | * @function 84 | * @param {Object} item The item data. 85 | * @return {CliPie} The `CliPie` instance. 86 | */ 87 | CliPie.prototype.add = function (item) { 88 | item.letter = item.letter || this.options.chars[++this.cChar]; 89 | var nItem = new CliPie.Item(item); 90 | this.total += nItem.value; 91 | this.data.push(nItem); 92 | return this; 93 | }; 94 | 95 | /** 96 | * textColor 97 | * Adds foreground or/and background color(s) to the provided text. 98 | * 99 | * @name textColor 100 | * @function 101 | * @param {String} text The text to color. 102 | * @param {String} color The color value. 103 | * @param {Boolean} fg If `true`, the function will modify the foreground 104 | * color of the text (default: `true`). 105 | * @param {Boolean} bg If `true`, the function will modify the background 106 | * color of the text. 107 | * @return {String} The colored text. 108 | */ 109 | CliPie.prototype.textColor = function (text, color, fg, bg) { 110 | if (color && fg === undefined) { 111 | fg = true; 112 | } 113 | if (this.options.no_ansi || !(fg || bg) || !color) { 114 | return text; 115 | } 116 | if (fg && bg) { 117 | return Couleurs(" ").bg(color).fg(color); 118 | } 119 | 120 | return Couleurs[fg ? "fg" : "bg"](text, color); 121 | }; 122 | 123 | /** 124 | * uniqueColor 125 | * Generates an unique color. 126 | * 127 | * @name uniqueColor 128 | * @function 129 | * @param {String} cColor The provided color. 130 | * @return {String} The unique color. 131 | */ 132 | CliPie.prototype.uniqueColor = function (cColor) { 133 | var self = this 134 | , color = null 135 | , clrStr = null 136 | ; 137 | 138 | if (self.options.no_ansi) { 139 | return cColor; 140 | } 141 | 142 | if (cColor === undefined) { 143 | color = FlatColors(); 144 | } else if (this.options.flat && FlatColors.colors.indexOf(cColor) === -1 || Array.isArray(cColor) && cColor.length === 3) { 145 | color = FlatColors(cColor); 146 | } else { 147 | color = FlatColors.toRgb(cColor); 148 | } 149 | 150 | clrStr = color.join(","); 151 | if (this.colors[clrStr] && Object.keys(this.colors).length !== FlatColors.colors.length) { 152 | return this.uniqueColor(); 153 | } 154 | 155 | this.colors[clrStr] = color; 156 | return color; 157 | }; 158 | 159 | /** 160 | * toString 161 | * Stringifies the pie. 162 | * 163 | * @name toString 164 | * @function 165 | * @return {String} The stringified pie. 166 | */ 167 | CliPie.prototype.toString = function () { 168 | 169 | var self = this 170 | , circle = new CliCircle(self.radius, self.options.chr, self.options.circle_opts) 171 | ; 172 | 173 | function line(x1, y1, x2, y2, chr) { 174 | circle.graph.setFunctionX(function (x) { 175 | var y = (x - x1) * (y2 - y1) / (x2 - x1) + y1; 176 | return y; 177 | }, x1, x2, chr).setFunctionY(function (y) { 178 | var x = (y - y1) * (x2 - x1) / (y2 - y1) + x1; 179 | return x; 180 | }, y1, y2, chr); 181 | } 182 | 183 | function toRad(a) { 184 | return a * (Math.PI / 180); 185 | } 186 | 187 | var cAngle = 90; 188 | function next(delta) { 189 | cAngle -= delta; 190 | return { 191 | x: self.radius * Math.cos(toRad(cAngle)) 192 | , y: self.radius * Math.sin(toRad(cAngle)) 193 | }; 194 | } 195 | 196 | var i = 0 197 | , letters = {} 198 | , cPoint = null 199 | , str = "" 200 | , legend = null 201 | , cLegend = null 202 | ; 203 | 204 | self.data.forEach(function (cItem) { 205 | cItem.percent = (100 * cItem.value) / self.total; 206 | cItem.angle = cItem.percent * 3.6; 207 | cItem.color = letters[cItem.letter] = self.uniqueColor(cItem.color); 208 | for (i = 0; i <= cItem.angle; ++i) { 209 | cPoint = next(1); 210 | line(0, 0, cPoint.x, cPoint.y, cItem.letter); 211 | } 212 | }); 213 | 214 | str = circle.toString().split("\n").map(function (c) { 215 | return c.split("").map(function (ch) { 216 | return new Array(self.options.circle_opts.aRatio + 2).join(ch); 217 | }).join(""); 218 | }).join("\n"); 219 | 220 | Object.keys(letters).forEach(function (c) { 221 | str = str.replace(new RegExp(c, "g"), self.textColor(c, letters[c], true, true)); 222 | }); 223 | 224 | if (self.options.legend) { 225 | legend = self.data.map(function (c) { 226 | return self.textColor(self.options.no_ansi ? c.letter : "▣", c.color) + " " + c.label + " (" + c.percent.toFixed(2) + "%)"; 227 | 228 | }); 229 | if (self.options.display_total) { 230 | legend.push(""); 231 | var totalLabel = self.options.total_label || 'Total'; 232 | legend.push(self.textColor(" " + totalLabel + ": " + this.total.toFixed(2))); 233 | } 234 | str = str.split("\n"); 235 | str = str.map(function (c, i) { 236 | cLegend = legend[Math.round(i - str.length / 2 + self.data.length / 2)] 237 | if (cLegend) { 238 | return c + " " + cLegend; 239 | } 240 | return c; 241 | }).join("\n"); 242 | } 243 | 244 | return str; 245 | }; 246 | 247 | module.exports = CliPie; 248 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cli-pie", 3 | "version": "2.4.3", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "cli-pie", 9 | "version": "2.4.3", 10 | "license": "MIT", 11 | "dependencies": { 12 | "cli-circle": "^3.0.0", 13 | "couleurs": "^5.0.0", 14 | "flatcolors": "^3.0.0", 15 | "ul": "^5.0.0" 16 | }, 17 | "devDependencies": { 18 | "mocha": "^2.2.5" 19 | } 20 | }, 21 | "node_modules/cli-circle": { 22 | "version": "3.2.9", 23 | "resolved": "https://registry.npmjs.org/cli-circle/-/cli-circle-3.2.9.tgz", 24 | "integrity": "sha1-BkEvRpIuZuGJdmnfuEDkzAwcYFg=", 25 | "dependencies": { 26 | "cli-graph": "^3.0.0", 27 | "typpy": "^2.3.3", 28 | "ul": "^5.0.0" 29 | } 30 | }, 31 | "node_modules/cli-graph": { 32 | "version": "3.2.2", 33 | "resolved": "https://registry.npmjs.org/cli-graph/-/cli-graph-3.2.2.tgz", 34 | "integrity": "sha1-1oEKJjqxCXG+aIJ59n+smPjfdDo=", 35 | "dependencies": { 36 | "ul": "5.0.0" 37 | } 38 | }, 39 | "node_modules/cli-graph/node_modules/typpy": { 40 | "version": "2.0.0", 41 | "resolved": "https://registry.npmjs.org/typpy/-/typpy-2.0.0.tgz", 42 | "integrity": "sha1-re87rMEv9Hr/kg+rA6j/MnnXN9Y=" 43 | }, 44 | "node_modules/cli-graph/node_modules/ul": { 45 | "version": "5.0.0", 46 | "resolved": "https://registry.npmjs.org/ul/-/ul-5.0.0.tgz", 47 | "integrity": "sha1-yoDXkwJfP9Xcm/g0aYGNMQp8mmI=", 48 | "dependencies": { 49 | "deffy": "2.0.0", 50 | "typpy": "2.0.0" 51 | } 52 | }, 53 | "node_modules/commander": { 54 | "version": "2.3.0", 55 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", 56 | "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", 57 | "dev": true, 58 | "engines": { 59 | "node": ">= 0.6.x" 60 | } 61 | }, 62 | "node_modules/couleurs": { 63 | "version": "5.2.1", 64 | "resolved": "https://registry.npmjs.org/couleurs/-/couleurs-5.2.1.tgz", 65 | "integrity": "sha1-U5n596FZhS7BQkT4Qb2FjwTcUqM=", 66 | "dependencies": { 67 | "flat-colors": "3.0.0", 68 | "typpy": "2.0.0", 69 | "x256": "0.0.2" 70 | } 71 | }, 72 | "node_modules/couleurs/node_modules/typpy": { 73 | "version": "2.0.0", 74 | "resolved": "https://registry.npmjs.org/typpy/-/typpy-2.0.0.tgz", 75 | "integrity": "sha1-re87rMEv9Hr/kg+rA6j/MnnXN9Y=" 76 | }, 77 | "node_modules/debug": { 78 | "version": "2.2.0", 79 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 80 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 81 | "dev": true, 82 | "dependencies": { 83 | "ms": "0.7.1" 84 | } 85 | }, 86 | "node_modules/deffy": { 87 | "version": "2.0.0", 88 | "resolved": "https://registry.npmjs.org/deffy/-/deffy-2.0.0.tgz", 89 | "integrity": "sha1-+C4I7qUYxKCjCx8D7FBNJIryiTI=", 90 | "dependencies": { 91 | "typpy": "^2.0.0" 92 | } 93 | }, 94 | "node_modules/diff": { 95 | "version": "1.4.0", 96 | "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", 97 | "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", 98 | "dev": true, 99 | "engines": { 100 | "node": ">=0.3.1" 101 | } 102 | }, 103 | "node_modules/escape-string-regexp": { 104 | "version": "1.0.2", 105 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", 106 | "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", 107 | "dev": true, 108 | "engines": { 109 | "node": ">=0.8.0" 110 | } 111 | }, 112 | "node_modules/flat-colors": { 113 | "version": "3.0.0", 114 | "resolved": "https://registry.npmjs.org/flat-colors/-/flat-colors-3.0.0.tgz", 115 | "integrity": "sha1-JTqxojmJwyHxOwrNS/c//0By7Lc=" 116 | }, 117 | "node_modules/flatcolors": { 118 | "version": "3.0.0", 119 | "resolved": "https://registry.npmjs.org/flatcolors/-/flatcolors-3.0.0.tgz", 120 | "integrity": "sha1-Q5MoO3M1qJsuTUcKqWb4zYofqz0=" 121 | }, 122 | "node_modules/function.name": { 123 | "version": "1.0.9", 124 | "resolved": "https://registry.npmjs.org/function.name/-/function.name-1.0.9.tgz", 125 | "integrity": "sha1-kcRcj5HyACvGgIbGc4crYH3Yc8M=", 126 | "dependencies": { 127 | "noop6": "^1.0.1" 128 | } 129 | }, 130 | "node_modules/glob": { 131 | "version": "3.2.11", 132 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", 133 | "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", 134 | "deprecated": "Glob versions prior to v9 are no longer supported", 135 | "dev": true, 136 | "dependencies": { 137 | "inherits": "2", 138 | "minimatch": "0.3" 139 | }, 140 | "engines": { 141 | "node": "*" 142 | } 143 | }, 144 | "node_modules/growl": { 145 | "version": "1.9.2", 146 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 147 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 148 | "dev": true 149 | }, 150 | "node_modules/inherits": { 151 | "version": "2.0.3", 152 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 153 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 154 | "dev": true 155 | }, 156 | "node_modules/jade": { 157 | "version": "0.26.3", 158 | "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", 159 | "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", 160 | "deprecated": "Jade has been renamed to pug, please install the latest version of pug instead of jade", 161 | "dev": true, 162 | "dependencies": { 163 | "commander": "0.6.1", 164 | "mkdirp": "0.3.0" 165 | }, 166 | "bin": { 167 | "jade": "bin/jade" 168 | } 169 | }, 170 | "node_modules/jade/node_modules/commander": { 171 | "version": "0.6.1", 172 | "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", 173 | "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", 174 | "dev": true, 175 | "engines": { 176 | "node": ">= 0.4.x" 177 | } 178 | }, 179 | "node_modules/jade/node_modules/mkdirp": { 180 | "version": "0.3.0", 181 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", 182 | "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", 183 | "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", 184 | "dev": true, 185 | "engines": { 186 | "node": "*" 187 | } 188 | }, 189 | "node_modules/lru-cache": { 190 | "version": "2.7.3", 191 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", 192 | "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", 193 | "dev": true 194 | }, 195 | "node_modules/minimatch": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", 198 | "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", 199 | "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", 200 | "dev": true, 201 | "dependencies": { 202 | "lru-cache": "2", 203 | "sigmund": "~1.0.0" 204 | }, 205 | "engines": { 206 | "node": "*" 207 | } 208 | }, 209 | "node_modules/minimist": { 210 | "version": "0.0.8", 211 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 212 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 213 | "dev": true 214 | }, 215 | "node_modules/mkdirp": { 216 | "version": "0.5.1", 217 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 218 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 219 | "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", 220 | "dev": true, 221 | "dependencies": { 222 | "minimist": "0.0.8" 223 | }, 224 | "bin": { 225 | "mkdirp": "bin/cmd.js" 226 | } 227 | }, 228 | "node_modules/mocha": { 229 | "version": "2.5.3", 230 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", 231 | "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", 232 | "dev": true, 233 | "dependencies": { 234 | "commander": "2.3.0", 235 | "debug": "2.2.0", 236 | "diff": "1.4.0", 237 | "escape-string-regexp": "1.0.2", 238 | "glob": "3.2.11", 239 | "growl": "1.9.2", 240 | "jade": "0.26.3", 241 | "mkdirp": "0.5.1", 242 | "supports-color": "1.2.0", 243 | "to-iso-string": "0.0.2" 244 | }, 245 | "bin": { 246 | "_mocha": "bin/_mocha", 247 | "mocha": "bin/mocha" 248 | }, 249 | "engines": { 250 | "node": ">= 0.8.x" 251 | } 252 | }, 253 | "node_modules/ms": { 254 | "version": "0.7.1", 255 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 256 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", 257 | "dev": true 258 | }, 259 | "node_modules/noop6": { 260 | "version": "1.0.7", 261 | "resolved": "https://registry.npmjs.org/noop6/-/noop6-1.0.7.tgz", 262 | "integrity": "sha1-lnZ78gWLpZyoy5FVk0fdyAI5+o4=" 263 | }, 264 | "node_modules/sigmund": { 265 | "version": "1.0.1", 266 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 267 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", 268 | "dev": true 269 | }, 270 | "node_modules/supports-color": { 271 | "version": "1.2.0", 272 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", 273 | "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", 274 | "dev": true, 275 | "bin": { 276 | "supports-color": "cli.js" 277 | }, 278 | "engines": { 279 | "node": ">=0.10.0" 280 | } 281 | }, 282 | "node_modules/to-iso-string": { 283 | "version": "0.0.2", 284 | "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", 285 | "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", 286 | "deprecated": "to-iso-string has been deprecated, use @segment/to-iso-string instead.", 287 | "dev": true 288 | }, 289 | "node_modules/typpy": { 290 | "version": "2.3.9", 291 | "resolved": "https://registry.npmjs.org/typpy/-/typpy-2.3.9.tgz", 292 | "integrity": "sha1-KGZP2l6nHdcYck+J0ABgrx8Jw44=", 293 | "dependencies": { 294 | "function.name": "^1.0.3" 295 | } 296 | }, 297 | "node_modules/ul": { 298 | "version": "5.2.13", 299 | "resolved": "https://registry.npmjs.org/ul/-/ul-5.2.13.tgz", 300 | "integrity": "sha1-n/BQTqNcofdMC/WeZIDe8Am617U=", 301 | "dependencies": { 302 | "deffy": "^2.2.2", 303 | "typpy": "^2.3.4" 304 | } 305 | }, 306 | "node_modules/ul/node_modules/deffy": { 307 | "version": "2.2.2", 308 | "resolved": "https://registry.npmjs.org/deffy/-/deffy-2.2.2.tgz", 309 | "integrity": "sha1-CI9AkTy0cHhlP6b2l8IG4DRx1SM=", 310 | "dependencies": { 311 | "typpy": "^2.0.0" 312 | } 313 | }, 314 | "node_modules/x256": { 315 | "version": "0.0.2", 316 | "resolved": "https://registry.npmjs.org/x256/-/x256-0.0.2.tgz", 317 | "integrity": "sha1-ya8Yh296F1gB1WT+cK2egxd4STQ=", 318 | "engines": { 319 | "node": ">=0.4.0" 320 | } 321 | } 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cli-pie", 3 | "version": "2.4.3", 4 | "description": "Generate pie charts in terminal and text mode.", 5 | "main": "lib/index.js", 6 | "directories": { 7 | "example": "example", 8 | "test": "test" 9 | }, 10 | "scripts": { 11 | "test": "mocha test/" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git@github.com:IonicaBizau/node-cli-pie.git" 16 | }, 17 | "keywords": [ 18 | "pie", 19 | "chart", 20 | "cli", 21 | "terminal", 22 | "text" 23 | ], 24 | "author": "Ionică Bizău (https://ionicabizau.net)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/IonicaBizau/node-cli-pie/issues" 28 | }, 29 | "homepage": "https://github.com/IonicaBizau/node-cli-pie", 30 | "dependencies": { 31 | "cli-circle": "^3.0.0", 32 | "couleurs": "^5.0.0", 33 | "flatcolors": "^3.0.0", 34 | "ul": "^5.0.0" 35 | }, 36 | "devDependencies": { 37 | "mocha": "^2.2.5" 38 | }, 39 | "blah": { 40 | "h_img": "http://i.imgur.com/FcSpq0W.png", 41 | "ex_img": "http://i.imgur.com/6VA7578.png" 42 | }, 43 | "files": [ 44 | "bin/", 45 | "app/", 46 | "lib/", 47 | "dist/", 48 | "src/", 49 | "scripts/", 50 | "resources/", 51 | "menu/", 52 | "cli.js", 53 | "index.js", 54 | "index.d.ts", 55 | "package-lock.json", 56 | "bloggify.js", 57 | "bloggify.json", 58 | "bloggify/" 59 | ] 60 | } -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var CliPie = require("../lib") 2 | , Assert = require("assert") 3 | ; 4 | 5 | it("should create and stringify the pie", function (cb) { 6 | var p = new CliPie(5, [ 7 | { label: "Water", value: 70, color: [ 0, 0, 255] } 8 | , { label: "Land", value: 30, color: [255, 240, 0] } 9 | ], { 10 | legend: true 11 | }); 12 | 13 | p.toString(); 14 | p.options.no_ansi = true; 15 | p.toString(); 16 | cb(); 17 | }); 18 | --------------------------------------------------------------------------------