Skip to content

Commit

Permalink
created simple layout DSL, which will give the users of yargs the opt…
Browse files Browse the repository at this point in the history
…ion to more easily create custom tables
  • Loading branch information
Benjamin Coe committed Apr 24, 2015
1 parent a306c24 commit c198d31
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,41 @@ ui.div(
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.
* ' ': characters will be interpreted as padding.

**as an example...**

```js
var ui = require('./')({
width: 60
})

ui.div(
'Usage: node ./bin/foo.js\n' +
' <regex>\t provide a regex\n' +
' <glob>\t provide a glob\t [required]'
)

console.log(ui.toString())
```

**will output:**

```shell
Usage: node ./bin/foo.js
<regex> provide a regex
<glob> provide a glob [required]
```

## Methods

```js
Expand Down
44 changes: 44 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ UI.prototype.span = function () {

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 = []

Expand All @@ -33,6 +36,47 @@ UI.prototype.div = function () {
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,
rows = str.split('\n'),
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 && columns[0].length > leftColumnWidth) {
leftColumnWidth = Math.min(
Math.floor(_this.width * 0.5),
columns[0].length
)
}
})

// 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: [0, r.match(/\s*$/)[0].length, 0, r.match(/^\s*/)[0].length],
width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
}
}))
})

return this.rows[this.rows.length - 1]
}

UI.prototype._colFromString = function (str) {
return {
text: str
Expand Down
51 changes: 51 additions & 0 deletions test/cliui.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,55 @@ describe('cliui', function () {
ui.toString().split('\n').should.eql(expected)
})
})

describe('layoutDSL', function () {
it('turns tab into multiple columns', function () {
var ui = cliui({
width: 60
})

ui.div(
' <regex> \tmy awesome regex\n <my second thing> \tanother row\t a third column'
)

var expected = [
' <regex> my awesome regex',
' <my second thing> 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 <regex>\t my awesome regex\n <glob>\t my awesome glob\t [required]'
)
var expected = [
'Usage: $0',
' <regex> my awesome regex',
' <glob> my awesome [required]',
' glob'
]

ui.toString().split('\n').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')
})

})
})

0 comments on commit c198d31

Please sign in to comment.