-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathcode-builder.js
More file actions
143 lines (125 loc) · 3.58 KB
/
code-builder.js
File metadata and controls
143 lines (125 loc) · 3.58 KB
1
2
3
4
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
133
134
135
136
137
138
139
140
141
142
143
'use strict'
const { format: formatString } = require('./format')
/**
* Helper object to format and aggragate lines of code.
* Lines are aggregated in a `code` array, and need to be joined to obtain a proper code snippet.
*
* @class
*
* @param {string} indentation Desired indentation character for aggregated lines of code
* @param {string} join Desired character to join each line of code
*/
const CodeBuilder = function (indentation, join) {
this.code = []
this.indentLevel = 0
this.indentation = indentation
this.lineJoin = join || '\n'
}
/**
* Add given indentation level to given string and format the string (variadic)
* @param {number} [indentationLevel=0] - Desired level of indentation for this line
* @param {string} line - Line of code. Can contain formatting placeholders
* @param {...anyobject} - Parameter to bind to `line`'s formatting placeholders
* @return {string}
*
* @example
* var builder = CodeBuilder('\t')
*
* builder.buildLine('console.log("hello world")')
* // returns: 'console.log("hello world")'
*
* builder.buildLine(2, 'console.log("hello world")')
* // returns: 'console.log("\t\thello world")'
*
* builder.buildLine(2, 'console.log("%s %s")', 'hello', 'world')
* // returns: 'console.log("\t\thello world")'
*/
CodeBuilder.prototype.buildLine = function (indentationLevel, line) {
let lineIndentation = ''
let slice = 2
if (Object.prototype.toString.call(indentationLevel) === '[object String]') {
slice = 1
line = indentationLevel
indentationLevel = this.indentLevel
} else if (indentationLevel === null) {
return null
}
while (indentationLevel) {
lineIndentation += this.indentation
indentationLevel--
}
const format = Array.prototype.slice.call(arguments, slice, arguments.length)
format.unshift(lineIndentation + line)
return formatString.apply(this, format)
}
/**
* Invoke buildLine() and add the line at the top of current lines
* @param {number} [indentationLevel=0] Desired level of indentation for this line
* @param {string} line Line of code
* @return {this}
*/
CodeBuilder.prototype.unshift = function () {
this.code.unshift(this.buildLine.apply(this, arguments))
return this
}
/**
* Invoke buildLine() and add the line at the bottom of current lines
* @param {number} [indentationLevel=0] Desired level of indentation for this line
* @param {string} line Line of code
* @return {this}
*/
CodeBuilder.prototype.push = function () {
this.code.push(this.buildLine.apply(this, arguments))
return this
}
/**
* Add an empty line at the end of current lines
* @return {this}
*/
CodeBuilder.prototype.blank = function () {
this.code.push(null)
return this
}
/**
* Add the line to the end of the last line. Creates a new line
* if no lines exist yet.
*/
CodeBuilder.prototype.pushToLast = function (line) {
if (!this.code) {
this.push(line)
}
const updatedLine = `${this.code[this.code.length - 1]}${line}`
this.code[this.code.length - 1] = updatedLine
}
/**
* Concatenate all current lines using the given lineJoin
* @return {string}
*/
CodeBuilder.prototype.join = function () {
return this.code.join(this.lineJoin)
}
/**
* Increase indentation level
* @returns {this}
*/
CodeBuilder.prototype.indent = function () {
this.indentLevel++
return this
}
/**
* Decrease indentation level
* @returns {this}
*/
CodeBuilder.prototype.unindent = function () {
this.indentLevel--
return this
}
/**
* Reset indentation level
* @returns {this}
*/
CodeBuilder.prototype.reindent = function () {
this.indentLevel = 0
return this
}
module.exports = CodeBuilder