pax_global_header00006660000000000000000000000064132215025060014506gustar00rootroot0000000000000052 comment=fee4df906ac3e1a24de4670f130db0a93bdad6a9 node-cliui-4.0.0/000077500000000000000000000000001322150250600135375ustar00rootroot00000000000000node-cliui-4.0.0/.coveralls.yml000066400000000000000000000000561322150250600163330ustar00rootroot00000000000000repo_token: NiRhyj91Z2vtgob6XdEAqs83rzNnbMZUu node-cliui-4.0.0/.gitignore000066400000000000000000000000431322150250600155240ustar00rootroot00000000000000.DS_Store node_modules .nyc_output node-cliui-4.0.0/.travis.yml000066400000000000000000000001221322150250600156430ustar00rootroot00000000000000language: node_js node_js: - "4" - "6" - "8" after_script: npm run coverage node-cliui-4.0.0/CHANGELOG.md000066400000000000000000000024141322150250600153510ustar00rootroot00000000000000# Change Log All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. # [4.0.0](https://github.com/yargs/cliui/compare/v3.2.0...v4.0.0) (2017-12-18) ### Bug Fixes * downgrades strip-ansi to version 3.0.1 ([#54](https://github.com/yargs/cliui/issues/54)) ([5764c46](https://github.com/yargs/cliui/commit/5764c46)) * set env variable FORCE_COLOR. ([#56](https://github.com/yargs/cliui/issues/56)) ([7350e36](https://github.com/yargs/cliui/commit/7350e36)) ### Chores * drop support for node < 4 ([#53](https://github.com/yargs/cliui/issues/53)) ([b105376](https://github.com/yargs/cliui/commit/b105376)) ### Features * add fallback for window width ([#45](https://github.com/yargs/cliui/issues/45)) ([d064922](https://github.com/yargs/cliui/commit/d064922)) ### BREAKING CHANGES * officially drop support for Node < 4 # [3.2.0](https://github.com/yargs/cliui/compare/v3.1.2...v3.2.0) (2016-04-11) ### Bug Fixes * reduces tarball size ([acc6c33](https://github.com/yargs/cliui/commit/acc6c33)) ### Features * adds standard-version for release management ([ff84e32](https://github.com/yargs/cliui/commit/ff84e32)) node-cliui-4.0.0/LICENSE.txt000066400000000000000000000013331322150250600153620ustar00rootroot00000000000000Copyright (c) 2015, Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. node-cliui-4.0.0/README.md000066400000000000000000000047351322150250600150270ustar00rootroot00000000000000# cliui [![Build Status](https://travis-ci.org/yargs/cliui.svg)](https://travis-ci.org/yargs/cliui) [![Coverage Status](https://coveralls.io/repos/yargs/cliui/badge.svg?branch=)](https://coveralls.io/r/yargs/cliui?branch=) [![NPM version](https://img.shields.io/npm/v/cliui.svg)](https://www.npmjs.com/package/cliui) [![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version) easily create complex multi-column command-line-interfaces. ## Example ```js var ui = require('cliui')() ui.div('Usage: $0 [command] [options]') ui.div({ text: 'Options:', padding: [2, 0, 2, 0] }) ui.div( { text: "-f, --file", width: 20, padding: [0, 4, 0, 4] }, { text: "the file to load." + chalk.green("(if this description is long it wraps).") , width: 20 }, { text: chalk.red("[required]"), align: 'right' } ) console.log(ui.toString()) ``` ## Layout DSL cliui exposes a simple layout DSL: If you create a single `ui.row`, passing a string rather than an object: * `\n`: characters will be interpreted as new rows. * `\t`: characters will be interpreted as new columns. * `\s`: characters will be interpreted as padding. **as an example...** ```js var ui = require('./')({ width: 60 }) ui.div( 'Usage: node ./bin/foo.js\n' + ' \t provide a regex\n' + ' \t provide a glob\t [required]' ) console.log(ui.toString()) ``` **will output:** ```shell Usage: node ./bin/foo.js provide a regex provide a glob [required] ``` ## Methods ```js cliui = require('cliui') ``` ### cliui({width: integer}) Specify the maximum width of the UI being generated. If no width is provided, cliui will try to get the current window's width and use it, and if that doesn't work, width will be set to `80`. ### cliui({wrap: boolean}) Enable or disable the wrapping of text in a column. ### cliui.div(column, column, column) Create a row with any number of columns, a column can either be a string, or an object with the following options: * **text:** some text to place in the column. * **width:** the width of a column. * **align:** alignment, `right` or `center`. * **padding:** `[top, right, bottom, left]`. * **border:** should a border be placed around the div? ### cliui.span(column, column, column) Similar to `div`, except the next row will be appended without a new line being created. node-cliui-4.0.0/index.js000066400000000000000000000200271322150250600152050ustar00rootroot00000000000000var stringWidth = require('string-width') var stripAnsi = require('strip-ansi') var wrap = require('wrap-ansi') var align = { right: alignRight, center: alignCenter } var top = 0 var right = 1 var bottom = 2 var left = 3 function UI (opts) { this.width = opts.width this.wrap = opts.wrap this.rows = [] } UI.prototype.span = function () { var cols = this.div.apply(this, arguments) cols.span = true } UI.prototype.div = function () { if (arguments.length === 0) this.div('') if (this.wrap && this._shouldApplyLayoutDSL.apply(this, arguments)) { return this._applyLayoutDSL(arguments[0]) } var cols = [] for (var i = 0, arg; (arg = arguments[i]) !== undefined; i++) { if (typeof arg === 'string') cols.push(this._colFromString(arg)) else cols.push(arg) } this.rows.push(cols) return cols } UI.prototype._shouldApplyLayoutDSL = function () { return arguments.length === 1 && typeof arguments[0] === 'string' && /[\t\n]/.test(arguments[0]) } UI.prototype._applyLayoutDSL = function (str) { var _this = this var rows = str.split('\n') var leftColumnWidth = 0 // simple heuristic for layout, make sure the // second column lines up along the left-hand. // don't allow the first column to take up more // than 50% of the screen. rows.forEach(function (row) { var columns = row.split('\t') if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) { leftColumnWidth = Math.min( Math.floor(_this.width * 0.5), stringWidth(columns[0]) ) } }) // generate a table: // replacing ' ' with padding calculations. // using the algorithmically generated width. rows.forEach(function (row) { var columns = row.split('\t') _this.div.apply(_this, columns.map(function (r, i) { return { text: r.trim(), padding: _this._measurePadding(r), width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined } })) }) return this.rows[this.rows.length - 1] } UI.prototype._colFromString = function (str) { return { text: str, padding: this._measurePadding(str) } } UI.prototype._measurePadding = function (str) { // measure padding without ansi escape codes var noAnsi = stripAnsi(str) return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length] } UI.prototype.toString = function () { var _this = this var lines = [] _this.rows.forEach(function (row, i) { _this.rowToString(row, lines) }) // don't display any lines with the // hidden flag set. lines = lines.filter(function (line) { return !line.hidden }) return lines.map(function (line) { return line.text }).join('\n') } UI.prototype.rowToString = function (row, lines) { var _this = this var padding var rrows = this._rasterize(row) var str = '' var ts var width var wrapWidth rrows.forEach(function (rrow, r) { str = '' rrow.forEach(function (col, c) { ts = '' // temporary string used during alignment/padding. width = row[c].width // the width with padding. wrapWidth = _this._negatePadding(row[c]) // the width without padding. ts += col for (var i = 0; i < wrapWidth - stringWidth(col); i++) { ts += ' ' } // align the string within its column. if (row[c].align && row[c].align !== 'left' && _this.wrap) { ts = align[row[c].align](ts, wrapWidth) if (stringWidth(ts) < wrapWidth) ts += new Array(width - stringWidth(ts)).join(' ') } // apply border and padding to string. padding = row[c].padding || [0, 0, 0, 0] if (padding[left]) str += new Array(padding[left] + 1).join(' ') str += addBorder(row[c], ts, '| ') str += ts str += addBorder(row[c], ts, ' |') if (padding[right]) str += new Array(padding[right] + 1).join(' ') // if prior row is span, try to render the // current row on the prior line. if (r === 0 && lines.length > 0) { str = _this._renderInline(str, lines[lines.length - 1]) } }) // remove trailing whitespace. lines.push({ text: str.replace(/ +$/, ''), span: row.span }) }) return lines } function addBorder (col, ts, style) { if (col.border) { if (/[.']-+[.']/.test(ts)) return '' else if (ts.trim().length) return style else return ' ' } return '' } // if the full 'source' can render in // the target line, do so. UI.prototype._renderInline = function (source, previousLine) { var leadingWhitespace = source.match(/^ */)[0].length var target = previousLine.text var targetTextWidth = stringWidth(target.trimRight()) if (!previousLine.span) return source // if we're not applying wrapping logic, // just always append to the span. if (!this.wrap) { previousLine.hidden = true return target + source } if (leadingWhitespace < targetTextWidth) return source previousLine.hidden = true return target.trimRight() + new Array(leadingWhitespace - targetTextWidth + 1).join(' ') + source.trimLeft() } UI.prototype._rasterize = function (row) { var _this = this var i var rrow var rrows = [] var widths = this._columnWidths(row) var wrapped // word wrap all columns, and create // a data-structure that is easy to rasterize. row.forEach(function (col, c) { // leave room for left and right padding. col.width = widths[c] if (_this.wrap) wrapped = wrap(col.text, _this._negatePadding(col), {hard: true}).split('\n') else wrapped = col.text.split('\n') if (col.border) { wrapped.unshift('.' + new Array(_this._negatePadding(col) + 3).join('-') + '.') wrapped.push("'" + new Array(_this._negatePadding(col) + 3).join('-') + "'") } // add top and bottom padding. if (col.padding) { for (i = 0; i < (col.padding[top] || 0); i++) wrapped.unshift('') for (i = 0; i < (col.padding[bottom] || 0); i++) wrapped.push('') } wrapped.forEach(function (str, r) { if (!rrows[r]) rrows.push([]) rrow = rrows[r] for (var i = 0; i < c; i++) { if (rrow[i] === undefined) rrow.push('') } rrow.push(str) }) }) return rrows } UI.prototype._negatePadding = function (col) { var wrapWidth = col.width if (col.padding) wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0) if (col.border) wrapWidth -= 4 return wrapWidth } UI.prototype._columnWidths = function (row) { var _this = this var widths = [] var unset = row.length var unsetWidth var remainingWidth = this.width // column widths can be set in config. row.forEach(function (col, i) { if (col.width) { unset-- widths[i] = col.width remainingWidth -= col.width } else { widths[i] = undefined } }) // any unset widths should be calculated. if (unset) unsetWidth = Math.floor(remainingWidth / unset) widths.forEach(function (w, i) { if (!_this.wrap) widths[i] = row[i].width || stringWidth(row[i].text) else if (w === undefined) widths[i] = Math.max(unsetWidth, _minWidth(row[i])) }) return widths } // calculates the minimum width of // a column, based on padding preferences. function _minWidth (col) { var padding = col.padding || [] var minWidth = 1 + (padding[left] || 0) + (padding[right] || 0) if (col.border) minWidth += 4 return minWidth } function getWindowWidth () { if (typeof process === 'object' && process.stdout && process.stdout.columns) return process.stdout.columns } function alignRight (str, width) { str = str.trim() var padding = '' var strWidth = stringWidth(str) if (strWidth < width) { padding = new Array(width - strWidth + 1).join(' ') } return padding + str } function alignCenter (str, width) { str = str.trim() var padding = '' var strWidth = stringWidth(str.trim()) if (strWidth < width) { padding = new Array(parseInt((width - strWidth) / 2, 10) + 1).join(' ') } return padding + str } module.exports = function (opts) { opts = opts || {} return new UI({ width: (opts || {}).width || getWindowWidth() || 80, wrap: typeof opts.wrap === 'boolean' ? opts.wrap : true }) } node-cliui-4.0.0/package.json000066400000000000000000000023551322150250600160320ustar00rootroot00000000000000{ "name": "cliui", "version": "4.0.0", "description": "easily create complex multi-column command-line-interfaces", "main": "index.js", "scripts": { "pretest": "standard", "test": "nyc mocha", "coverage": "nyc --reporter=text-lcov mocha | coveralls", "release": "standard-version" }, "repository": { "type": "git", "url": "http://github.com/yargs/cliui.git" }, "config": { "blanket": { "pattern": [ "index.js" ], "data-cover-never": [ "node_modules", "test" ], "output-reporter": "spec" } }, "standard": { "ignore": [ "**/example/**" ], "globals": [ "it" ] }, "keywords": [ "cli", "command-line", "layout", "design", "console", "wrap", "table" ], "author": "Ben Coe ", "license": "ISC", "dependencies": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", "wrap-ansi": "^2.0.0" }, "devDependencies": { "chai": "^3.5.0", "chalk": "^1.1.2", "coveralls": "^2.11.8", "mocha": "^3.0.0", "nyc": "^10.0.0", "standard": "^8.0.0", "standard-version": "^3.0.0" }, "files": [ "index.js" ], "engine": { "node": ">=4" } } node-cliui-4.0.0/screenshot.png000066400000000000000000000435151322150250600164320ustar00rootroot00000000000000PNG  IHDR86YPiCCPICC ProfileX YgTsQrs .IP"D FDD@" (*@{}s<[]]TuOT-djll$ @Tt^੆''`F"XH@d O/2[kǿ?Ə0j巧ilF_Q StpҐ&gC8n?Pi@Oq7M(=:넿埸ѣ̚Y HZ@ ԲOM, na&ZIǿ9[F'\V#}R2__PBg@8ヶLcbia!pPZ# }MeuF{Q#QY \j>L|\r H%p`o@>087 6¨(: l;A&@8 P΃Khmpo{0" Dp |"( j1GCBh$نBr$R\D#{H?yL!_(QNTFQE hMA3h ZC[}1:Gg11aܘ`#c4,rkcŦǁ)is6Rq{qGpUz\!nO zxk>O;?G  2mnz [ { G uVB?a0K$ D#J'f[7$&IdA!EIŤfi ŠȐ̐PaQрэ1q'c c-c'sƯLLLLLLaLiL%L2bZ ɦd_ry? BHS(>x~J52Blȼy# 1Fb,,Ӭ ҬTTRCllllQl{βcd'KgWq`8*9:9p8e899s9sppsipypm*5ʍqKs[sGrq_#cēS33+kě[(9__>58~y~g$c9QAyA݂BBBBڅÅ D8D։5-K;)#(.#..^'BQBG"XPMbFRD^rdT!;R2Ҟ{IOXˤ<n-}$Gӑ;*'kʇʗ* Z a G讉^SfHhXJ[N)]GeIe|;?U4U"U*Uڨ6~QW P+U{NQPߡޠYCA#HMM{=mZZ4Z)mIm?2!N':wu&;tt.}Wԏ??VfmʵcTD;nP̐jXnH(фq9&*&4&zM[03Ksvsw##!53[-[VVVCB366m:lɶGl_Q{Rc 'N7 NΥo]T]qpzu-홻{{GǼAQ/e^ü|>>}fכ/ZW7wp̆-m&MM~~grꬿLiFSAA& OLN n~<|>1LJgd])/z4{tDtGp̖Xz6li㐸 q ;A6aw«uߓ<.oa;Y>9;y""VրmĶjHj;ޤYUdAJo~Z6PqI&ͼf敖[!6=kjiy;wZmwzN׵Z5>|pGWOmfo?~tA'CCOL>|y8qxYs/GG_ʽUkޏǍ/xKy[,}Xs?84T$0a_'^菌7?.cXݸ›·k޶LLORW>zZ}zCǀOl8ͼ ϗ_ER<ѹ:4S&qi/IAQIBcvf `Me;1ʭC?"$.^$MX3Y)&iMYk9?d5&Upbjk}45s*<}m-@`Qq>$K!+5kswh-v;gduL v1[okgcҦ" 6Ae[Cp: pU>Zi@#FӦO46:v}{GRg;GV;ֵ~B\p量;%["/@l'hFp ^| A0Eeke(c+ŷ?)0 ,T+\!R*Z,V(')(E6.-w\>Nj"84|WQZzAWHKOQjuyFf&ҦfŠ b )Q;G{}.Gk'^w.nۼl_T†6ekɁAg7,EȝQѸΘݱƱ7м]-$qmHR-7RSl۵+U6unG{Zΐt]2A=cYrRj#!/@DA L:L:S:~q'5˕+d+Nf;XPg9{j=tIϕWq6x_/kjߔkloqX[sˎbwLu`r\C#{qagE/_2JϝLen>jo=@3=s kH' nS PZD H0"@hLy Ȇ9 `d aG#!`>؉* ?0 K! U0#k' #B'H DO*'8?"Eɦ|dvcnN>+`:n~CS˅k;S+7ɟ%*0&x\_XAm"@q 3Ryґ2 r 7SLUUUTQ}vV=[#TFKIK{Eހ~Nuw {'M̀9s$+5 ٖN^1کй]s  _ *=6m r #4pBt@f ZSFB]▋)km!6^a{nOaνA^?(xQR"zDئ'*(V8R;z䕍ט6mhQh鴸[M{?$^ZMeNw~e!G⣥?cWWd45{ k T nDAaEV^8TCi b62\. [7KC.="+ћxdL* eg(`fctf4#.3 oV Vul-]/`f+[>f^nz>gJA#q|afIHJ)}@&XDNJ]HRbVfWaS%.MitiҺݥL>ZuaF4P/SK3]s KKM֩6'm88;E=[{ >|l/Xt5'd~yANE "EU$x% R?|]gV\c觔|TAW ~Mktv]"Vm67)06f;:ep}j@НQ1 -&^8=)!9pʴ䝃KnR&G{gPZU_2ƣgkYnXztWSs}u/^:ttu{RCv􍾛-ZSmeqwn܋=sk!'+;|0:}{>Nz{cGO3G?B秾~]0]Ac`QsdROV VJx dX~YY* ++++0x@ks^Q4iTXtXML:com.adobe.xmp 568 157 9\-IDATx XSW4Q~Y -N/N;G4LεpNw^{=-3N9X=u`Zi ALh:nԠDMlI;N`zxkb D+)ѪfCF9$,\,P@^E^N7D,H &pahkh5uF0y/^>A"|P,ʼ#i{殆CF?:ޱ@ƛQm11emf {sbbrV(?~WzG͛YTۉ@H1y)-KZT;곏YI2m!!s+;&M%% bvr\uc% @` oAy.CcoQNܺ·23s*yu//yVQumMe [8%IZۚ*>a)'(%5+#Uh Nء(di/jZkFUGio@ x9*u +2 ~u4Wtal-r^**+)ipu]y Y.QST'ai-S %{g7޷gc+4mkIZkh i.1֮ 7<+-3r)*И(@ܬ5E@I.-չ%i9E6֒9BM7g;>P}2srxy]|-3cҞzn!̺ <^%!+z9m {GG @n<lZh֚LiJnNd:>vRm3ԀF>FESE9/ĉ$W)"^gaK)WwNj}Z*i\b< l}T@>[IJSSO"\A„-*.s>j1Ӳ/7ҩ?d3NRXOYZXHKTZN}@4GnJQܡO^SϥP Pjeq~Dz}6*0:M5Yye c:h|@ t9  0q!U;btCɝG&ERN['Xrږ3\F[51Rp ӑ}ZmKF[-ndєg6@)"^k⵲uVӨJ-ӆ*iNGH3ޯB^MJAqir6Q해rࠎҚ8G%ύs c4\n#n} `>=3 ֲB+V[Kn5| S9fJ $5j)7+zyqt5gȉdTs݋/qNH/u۹Q/+*ީ[\Ҕ[6f2OBݛ7[g6o#[S9H'F=ŦzPRa="u8 ,(J TA -Ox>!o> f`l|Zg͆p1>!~ Tܞjjt\1iD~J\,ijGoȭRy%lK٧mZ5ME4׳4q';Je^1: LKZķV tI錒%/{YRzκ=e::XE~%s7H;)t&FݡONs>A 3 g 6l>.L3svz;X8ݙ琽 %A,U\rBVCDk٦-vxHѣǭUth7Zj\әuY yC]Fְlh\Rҧ!,0)khӞ8sK9*]F {mkVs ] R'{heݭex=m|~h5w5n"k|]!-PVǨYw[ٮ7P RsOvu̶50xn͟ ?fhRu F%ZoB@8\ib9|甔:_ЗP[XU >(鼎{Ӓ!+]&ry~g95RﱝV)=) ;!F}Ϲ&dxk@W8\Q5%\&` sTZk OgYpgʩ.pZs{T{R ym+j-ֹmqnKpT}ϼƝtN-7FGc/@&0b v6ھ6m&xrZxl6n4>]o-Z]Zn₟~<Y,p]Yz{{-aLة#)Hx07aZ+㭋˻Q $<46:{ @ Ցo_[YֺK׃Wz-5f4&Y*~z-XD:=*CdHKGMxA Q@ "Pj?~zך-/O&aWoo\뺤?I]qI]G6o>3';z!D? xx'.%d3Jo=zXX:X*dmݚ1CE@@`rTqs8.}nD6vUNJܗdw? \ EbȖe6 -ܐcܪ#KtPp s  ,{N m{g[jIl\n0xiQop@@@` (@@G,?@D QE/K*\  QpT   DUDB8@%  %GQ  .8p "?@D QE/K*\  QpT   DUDB8@%  %GQ  .8p "?@D QE/K*\  QpT   DUDB8@%  %GQ  .8p "?@D QE/K*\  QpT   DUDB8@%  %GQ  .8p "?@D QE/K*\  QpT  +AƈY[lJJ,ct24l&Lp4餸UV[w !1 㒥Uv>=zi\nxsן}[nHƶz:#%b%q㙫H3klk˕3 ŷ lnK`;z ]v/Bp<U狛i3?2-V L ߚn8@[Õ+ xyE Lr i XESLi T:5TCȦo,.c*mQSTaTǷ]#6"UӻZt㧵Ÿhk`?(](}tT(-t \bL~luSm7zg撎CU܆;}:@+K{QӢ]7"A[ *ڱCu1d= xџvԈHo|R"O˒~Yک>֘e/`u?8h^ܢm$i/.P;ScR(1)B"fELKI[8|ɻM'.RP+/Y㢽A؎1iO=b^A1mw昞@SF-H*i7̮3]UQ嬗oU_q98f\)opw[ i9E6֒9^X6EyiJ7h:wD]i_*Lcisψ`:Vͅ_O9re: o11'sX;L.g:εS]NeXtu7'l'N~779ed[?H~TtvJwhq8ݷ1k阖JRz輇ƨ?1˵Sh|ڣR]TS[{bߒ{ JVS]HlatVwf'zS[6ڎԮ3]&5 MҵTr!ԂHcU׶t!nz(5z2eM?Up5J4 {t0ޥ~݇uWڙ+\o8d,c5n1#B 27M`no՞6mGu>59eժ{zUthB }JRӓtBN Q6ͳ8#mvykr HSRSSń̑?J0npB*+S I-Tk5*3nvIcDy|f:V>2uAWrdK+G;:Ȍ䒪9n_X,%/,wK(Ɇ%>{SRg'Sȥ3P2]yOH[83H3 pݑG˗[נ/2ٱJ }~~,~څqO)w}ͼu$O:'UF7v\6l=6/I'݌OHNb4C/w/'.U9*KWu\KVuT.;ݫc1@WOevA ]vGeE_K-,Ii/{c\FQӼ#uK-FiWz(OgZB^t/Ä4pɼ q`9Ɗy[";7mnSŃKH?DfBhV*廬^/BGC)i&4 ۏdo4.5Vq ZZIBI~#jyOr4Lb%  M .k׿rpkďO|kUp]MTQW-x嵏4d+BX6&%T9g )+YtB}&7,I;v.G(:FCZ8u^sxcXZ~\I(fѩ&FůGpf׎/FT&iR|N~@9Е! (m<~FUB7K$];Z4aaJ.~eyOi;*)R_et߇l}>G &;wTk&}DW"" nԢֹXY{q{5 h+肋g*K6)\)ݹκÑkg;\'6IwT1Z]ߩh*||g3u`[ӣmq//+} ,irckufD4|gc؁jD7!ͬ4)Y|ZXͣY_p͒~uכ)Ip ַ>2›){Hʒ oEu: +* *XS|{r씤d@G{-;+OhYQ %1 wσ/̈H.XJ}<>y8nۄfJ {k6Q%d[4DM~M5)/[,/ɄQ&0eǚq$S6X?+nQT=*ܘ  w:J   Q烫  m  Up>wUGJ7k+]:&hZDl!cX j* ਢRC%'|vă :L|V_+V*}DrFqB%d(!G%1NjH];#o.U$>6 |xB2%a<1"E8Ma(]|2Ĩdl}쩓k{:˵yNӧfsUbZצ}wi{&nk_$E׼#{z 5'9d{z ?>Vp w\`t NOxiOE nSm9b>ps9{tud!ON' 9FLpTCA:QʷvΧSW{Wd(~׹d@sW|/ݽ5pU0ZȜ/ٜ֟ܲ#?ykf'o%;qt#O>k&+?]:tp_o-]ص0Kz &m^xH&L3ۘ~e=@ G\yzKu\>gNn,SeZ0ߏq9 @ Ln93IFuSZM 9kW ~~'ʂ-L]{|{}ͫSh4W`R2򾏶>uKxxޭs4t 4yZ {H [>* {N+8|ߋܥYnOm:؀|9 zATvEQݣ+n>>9Q=G["@`R@jRUƸvtYLq닛C7N߸%W}I^kn菶R/b\}g;CՅTW$Q/O+ι;ϋi|X3J'7YÀp_|ظm: Mi4'A*Jn;uplw醓b Ls $%%;5Y/N:{=?G+׿~H+zƙO>S? $_joJ]yO7ij/"YjrŚ4mfH%7ؤӒe~}x$I*D~&$cVI7sɤ~{d'LILK'_A8(@`W} $0E4m0)3.MF L*._x-NWB$KGb,`ůIlc"B@`">N}#K@8/&W  i  0*Q 28"r@@FEjTؐ"0^;kN,rƂXP 2+׿Ww<7t|v;~~YC pG-T_R6]E7 QkD3l'C8>Kԃ_ݎj0FQOz y|kTie@!p;Z;m)'c~Ķ @mT菎JW^Zf6Nt-͢w7x9qzƉ 6L.vTb@ " x|C]i?oSTmT/i¥)5df%q"{ΪLLnH,<3ƉR  {#g$8qE mxϪy9d9 9=.¤9nH6B-Xi\am Iܶ7ryW%MVbGam,a~6~\tgў3f]`#̍sf5XOu?B_8q'Ɖ'rт nᓜnR J`f\uAaso646s[!Χj?U C vŰ|zҧ9~mv&1Ɖ5G~ߓpHYjrnro֍`M.*O~=:H\n;J46I:Эd7*f>Uo >A`\ ǵP6 =w*O_,eQoh6NKE}BILCraLQMZ  0 QMʅi  0QMZ  0 Q\1oYc[]޽k~FO 5Mc ;fCB߇SC[p"?h uQ%IENDB`node-cliui-4.0.0/test/000077500000000000000000000000001322150250600145165ustar00rootroot00000000000000node-cliui-4.0.0/test/cliui.js000066400000000000000000000277251322150250600161760ustar00rootroot00000000000000/* global describe, it */ require('chai').should() // Force chalk to enable color, if it's disabled the test fails. process.env['FORCE_COLOR'] = 1 var chalk = require('chalk') var cliui = require('../') var stripAnsi = require('strip-ansi') describe('cliui', function () { describe('div', function () { it("wraps text at 'width' if a single column is given", function () { var ui = cliui({ width: 10 }) ui.div('i am a string that should be wrapped') ui.toString().split('\n').forEach(function (row) { row.length.should.be.lte(10) }) }) it('evenly divides text across columns if multiple columns are given', function () { var ui = cliui({ width: 40 }) ui.div( {text: 'i am a string that should be wrapped', width: 15}, 'i am a second string that should be wrapped', 'i am a third string that should be wrapped' ) // total width of all columns is <= // the width cliui is initialized with. ui.toString().split('\n').forEach(function (row) { row.length.should.be.lte(40) }) // it should wrap each column appropriately. var expected = [ 'i am a string i am a i am a third', 'that should be second string that', 'wrapped string that should be', ' should be wrapped', ' wrapped' ] ui.toString().split('\n').should.eql(expected) }) it('allows for a blank row to be appended', function () { var ui = cliui({ width: 40 }) ui.div() // it should wrap each column appropriately. var expected = [''] ui.toString().split('\n').should.eql(expected) }) }) describe('_columnWidths', function () { it('uses same width for each column by default', function () { var ui = cliui({ width: 40 }) var widths = ui._columnWidths([{}, {}, {}]) widths[0].should.equal(13) widths[1].should.equal(13) widths[2].should.equal(13) }) it('divides width over remaining columns if first column has width specified', function () { var ui = cliui({ width: 40 }) var widths = ui._columnWidths([{width: 20}, {}, {}]) widths[0].should.equal(20) widths[1].should.equal(10) widths[2].should.equal(10) }) it('divides width over remaining columns if middle column has width specified', function () { var ui = cliui({ width: 40 }) var widths = ui._columnWidths([{}, {width: 10}, {}]) widths[0].should.equal(15) widths[1].should.equal(10) widths[2].should.equal(15) }) it('keeps track of remaining width if multiple columns have width specified', function () { var ui = cliui({ width: 40 }) var widths = ui._columnWidths([{width: 20}, {width: 12}, {}]) widths[0].should.equal(20) widths[1].should.equal(12) widths[2].should.equal(8) }) it('uses a sane default if impossible widths are specified', function () { var ui = cliui({ width: 40 }) var widths = ui._columnWidths([{width: 30}, {width: 30}, {padding: [0, 2, 0, 1]}]) widths[0].should.equal(30) widths[1].should.equal(30) widths[2].should.equal(4) }) }) describe('alignment', function () { it('allows a column to be right aligned', function () { var ui = cliui({ width: 40 }) ui.div( 'i am a string', {text: 'i am a second string', align: 'right'}, 'i am a third string that should be wrapped' ) // it should right-align the second column. var expected = [ 'i am a stringi am a secondi am a third', ' stringstring that', ' should be', ' wrapped' ] ui.toString().split('\n').should.eql(expected) }) it('allows a column to be center aligned', function () { var ui = cliui({ width: 60 }) ui.div( 'i am a string', {text: 'i am a second string', align: 'center', padding: [0, 2, 0, 2]}, 'i am a third string that should be wrapped' ) // it should right-align the second column. var expected = [ 'i am a string i am a second i am a third string', ' string that should be', ' wrapped' ] ui.toString().split('\n').should.eql(expected) }) }) describe('padding', function () { it('handles left/right padding', function () { var ui = cliui({ width: 40 }) ui.div( {text: 'i have padding on my left', padding: [0, 0, 0, 4]}, {text: 'i have padding on my right', padding: [0, 2, 0, 0], align: 'center'}, {text: 'i have no padding', padding: [0, 0, 0, 0]} ) // it should add left/right padding to columns. var expected = [ ' i have i have i have no', ' padding padding on padding', ' on my my right', ' left' ] ui.toString().split('\n').should.eql(expected) }) it('handles top/bottom padding', function () { var ui = cliui({ width: 40 }) ui.div( 'i am a string', {text: 'i am a second string', padding: [2, 0, 0, 0]}, {text: 'i am a third string that should be wrapped', padding: [0, 0, 1, 0]} ) // it should add top/bottom padding to second // and third columns. var expected = [ 'i am a string i am a third', ' string that', ' i am a secondshould be', ' string wrapped', '' ] ui.toString().split('\n').should.eql(expected) }) it('preserves leading whitespace as padding', function () { var ui = cliui() ui.div(' LEADING WHITESPACE') ui.div('\u001b[34m with ansi\u001b[39m') var expected = [ ' LEADING WHITESPACE', ' with ansi' ] ui.toString().split('\n').map(function (l) { return stripAnsi(l) }).should.eql(expected) }) }) describe('border', function () { it('allows a border to be placed around a div', function () { var ui = cliui({ width: 40 }) ui.div( {text: 'i am a first string', padding: [0, 0, 0, 0], border: true}, {text: 'i am a second string', padding: [1, 0, 0, 0], border: true} ) var expected = [ '.------------------.', '| i am a first |.------------------.', '| string || i am a second |', "'------------------'| string |", " '------------------'" ] ui.toString().split('\n').should.eql(expected) }) }) describe('wrap', function () { it('allows wordwrap to be disabled', function () { var ui = cliui({ wrap: false }) ui.div( {text: 'i am a string', padding: [0, 1, 0, 0]}, {text: 'i am a second string', padding: [0, 2, 0, 0]}, {text: 'i am a third string that should not be wrapped', padding: [0, 0, 0, 2]} ) ui.toString().should.equal('i am a string i am a second string i am a third string that should not be wrapped') }) }) describe('span', function () { it('appends the next row to the end of the prior row if it fits', function () { var ui = cliui({ width: 40 }) ui.span( {text: 'i am a string that will be wrapped', width: 30} ) ui.div( {text: ' [required] [default: 99]', align: 'right'} ) var expected = [ 'i am a string that will be', 'wrapped [required] [default: 99]' ] ui.toString().split('\n').should.eql(expected) }) it('does not append the string if it does not fit on the prior row', function () { var ui = cliui({ width: 40 }) ui.span( {text: 'i am a string that will be wrapped', width: 30} ) ui.div( {text: 'i am a second row', align: 'left'} ) var expected = [ 'i am a string that will be', 'wrapped', 'i am a second row' ] ui.toString().split('\n').should.eql(expected) }) it('always appends text to prior span if wrap is disabled', function () { var ui = cliui({ wrap: false, width: 40 }) ui.span( {text: 'i am a string that will be wrapped', width: 30} ) ui.div( {text: 'i am a second row', align: 'left', padding: [0, 0, 0, 3]} ) ui.div('a third line') var expected = [ 'i am a string that will be wrapped i am a second row', 'a third line' ] ui.toString().split('\n').should.eql(expected) }) it('appends to prior line appropriately when strings contain ansi escape codes', function () { var ui = cliui({ width: 40 }) ui.span( {text: chalk.green('i am a string that will be wrapped'), width: 30} ) ui.div( {text: chalk.blue(' [required] [default: 99]'), align: 'right'} ) var expected = [ 'i am a string that will be', 'wrapped [required] [default: 99]' ] ui.toString().split('\n').map(function (l) { return stripAnsi(l) }).should.eql(expected) }) }) describe('layoutDSL', function () { it('turns tab into multiple columns', function () { var ui = cliui({ width: 60 }) ui.div( ' \tmy awesome regex\n \tanother row\t a third column' ) var expected = [ ' my awesome regex', ' another row a third column' ] ui.toString().split('\n').should.eql(expected) }) it('turns newline into multiple rows', function () { var ui = cliui({ width: 40 }) ui.div( 'Usage: $0\n \t my awesome regex\n \t my awesome glob\t [required]' ) var expected = [ 'Usage: $0', ' my awesome regex', ' my awesome [required]', ' glob' ] ui.toString().split('\n').should.eql(expected) }) it('aligns rows appropriately when they contain ansi escape codes', function () { var ui = cliui({ width: 40 }) ui.div( ' \t ' + chalk.red('my awesome regex') + '\t [regex]\n ' + chalk.blue('') + '\t my awesome glob\t [required]' ) var expected = [ ' my awesome [regex]', ' regex', ' my awesome [required]', ' glob' ] ui.toString().split('\n').map(function (l) { return stripAnsi(l) }).should.eql(expected) }) it('ignores ansi escape codes when measuring padding', function () { var ui = cliui({ width: 25 }) // using figlet font 'Shadow' rendering of text 'true' here ui.div( chalk.blue(' | \n __| __| | | _ \\ \n | | | | __/ \n \\__| _| \\__,_| \\___| \n ') ) // relevant part is first line - leading whitespace should be preserved as left padding var expected = [ ' |', ' __| __| | | _ \\', ' | | | | __/', ' \\__| _| \\__,_| \\___|', ' ' ] ui.toString().split('\n').map(function (l) { return stripAnsi(l) }).should.eql(expected) }) it('does not apply DSL if wrap is false', function () { var ui = cliui({ width: 40, wrap: false }) ui.div( 'Usage: $0\ttwo\tthree' ) ui.toString().should.eql('Usage: $0\ttwo\tthree') }) }) })