rsformat 0.2.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -170
- package/lib/format.d.ts +39 -11
- package/lib/format.js +309 -182
- package/lib/index.d.ts +14 -1
- package/lib/index.js +28 -3
- package/lib/print.d.ts +24 -57
- package/lib/print.js +54 -100
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -1,170 +1,161 @@
|
|
|
1
|
-
# RSFormat
|
|
2
|
-
|
|
3
|
-
RSFormat is a string formatting/printing library for JavaScript. It offers a minimal, yet powerful and flexible alternative to the string formatting and printing provided by `console.log`.
|
|
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
|
-
format
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
```
|
|
163
|
-
> node benchmark.mjs
|
|
164
|
-
...After a lot of output...
|
|
165
|
-
|
|
166
|
-
console.log time for 100000 executions: 7217ms
|
|
167
|
-
rsformat.println time for 100000 executions: 5900ms
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
_Tested on node.js using a Windows laptop on an Intel core I7-1360P, on battery power. Performance will vary, but this benchmark was just to show that RSFormat has no performance penalty._
|
|
1
|
+
# RSFormat
|
|
2
|
+
|
|
3
|
+
RSFormat is a string formatting/printing library for JavaScript. It offers a minimal, yet powerful and flexible alternative to the string formatting and printing provided by `console.log`.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
import { rs, println } from 'rsformat';
|
|
7
|
+
|
|
8
|
+
let s = rs`${15} is ${15}:#X in hex`;
|
|
9
|
+
// s == '15 is 0xF in hex'
|
|
10
|
+
|
|
11
|
+
println(rs`${'a'}:^5`);
|
|
12
|
+
// Prints ' a '
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Motivation
|
|
16
|
+
|
|
17
|
+
`console.log` is an odd method: its output can be affected by functions called before/after it (such as `console.group`), or their order affected by what parameters there are. For example, when calling `console.log(string, number)`, number can come either after or inside `string` depending on the value of `string`.
|
|
18
|
+
|
|
19
|
+
This behaviour has largely been superseded at a language level by template literals, which allow formatting of parameters directly inside the templates, causing these methods to have unnecessary overhead and undesired behaviour.
|
|
20
|
+
|
|
21
|
+
RSFormat builds onto template literals by implementing Rust-style format specifiers and lightweight printing functions. Rust formatting includes a lot of convenient operators for formatting text, such as padding/alignment, printing numbers in a given base, specifying decimal precision, etc.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
You can install RSFormat from [npm](https://www.npmjs.com/package/rsformat):
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm install rsformat
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Basic formatting and printing to console
|
|
32
|
+
|
|
33
|
+
The `rs` template tag can be used to enable rust-style formatting in a template.
|
|
34
|
+
To reference a previous or following argument, use `rs.ref` with the parameter number.
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import { rs, println } from 'rsformat'; // ESM
|
|
38
|
+
const { rs, println } = require('rsformat'); // CommonJS
|
|
39
|
+
|
|
40
|
+
let number = 15;
|
|
41
|
+
|
|
42
|
+
let info = rs`${number} is ${rs.ref(0)}:x in hex`; // info == '15 is f in hex'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> NB: templates tagged with `rs` are instances of a special class `RsString` that extends `String`, rather than a primitive value. This is to enable colors for debug formatting inside the printing functions. This difference should not affect normal usage, but `rs.raw` can be used as an alternative tag to get a primitive `string`.
|
|
46
|
+
|
|
47
|
+
The printing functions can be called with plain strings, instances of `String` or templates formatted with `rs`:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
println('Hello World');
|
|
51
|
+
println(rs`...`);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Format Specifiers
|
|
55
|
+
|
|
56
|
+
Format specifiers can be used by adding `:` after the format argument, and will format the value differently inside the string. See the [rust format docs](https://doc.rust-lang.org/std/fmt/) for more detailed information on format specifiers.
|
|
57
|
+
|
|
58
|
+
This implementation differs from the Rust one in a few ways:
|
|
59
|
+
|
|
60
|
+
- Rather than escaping the braces using `{{` or `}}`, the formatting colon can be escaped using `::`.
|
|
61
|
+
- Different parameters are referenced using `rs.ref(n)` rather than the number literal `n`.
|
|
62
|
+
- To separate a formatting specifier from the rest of the string without adding a space, an extra closing colon must be added (eg. `:#?:foo` - specifier gets parsed as `:#?`)
|
|
63
|
+
- The `-` sign (unused in Rust) will add a space if the number is positive to align it with negative numbers without showing a `+`.
|
|
64
|
+
- Pointer format type `p` is unsupported.
|
|
65
|
+
- Hexadecimal debug types `x?` and `X?` are unsupported.
|
|
66
|
+
- Specifying precision dynamically with `*` is unsupported. Instead, precision and width can both be specified dynamically by using a separate number parameter in place of the number.
|
|
67
|
+
- New format types have been added:
|
|
68
|
+
- `N` for uppercase ordinal suffixing of numbers (rounded to integers)
|
|
69
|
+
- `n` for lowercase ordinal suffixing of numbers (rounded to integers)
|
|
70
|
+
|
|
71
|
+
#### Different formatting types
|
|
72
|
+
|
|
73
|
+
The debug format specifier `?` uses `util.inspect` to stringify the parameter rather than `toString`.
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
let obj = { a: 1 };
|
|
77
|
+
println(rs`${obj}`); // prints '[object Object]'
|
|
78
|
+
println(rs`${obj}:?`); // prints '{ a: 1 }'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The provided printing functions will display colors in the output of `util.inspect`, but otherwise it will be formatted without color.
|
|
82
|
+
|
|
83
|
+
The specifiers `b`,`o`,`x`,`X`,`e`,`E`,`n`,`N` will convert a `number` or `bigint` parameter to:
|
|
84
|
+
- `b`: binary
|
|
85
|
+
- `o`: octal
|
|
86
|
+
- `x`/`X`: lowercase/uppercase hexadecimal
|
|
87
|
+
- `e`/`E`: lowercase/uppercase scientific notation
|
|
88
|
+
- `n`/`N`: lowercase/uppercase ordinal suffixed string (rounded to integer)
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
let advancedInfo = (n) => rs`${n} is ${n}:x in hex, ${n}:b in binary and ${n}:o in octal`;
|
|
92
|
+
|
|
93
|
+
advancedInfo(15); // '15 is f in hex, 1111 in binary and 17 in octal'
|
|
94
|
+
|
|
95
|
+
let hugeNumber = 1000n;
|
|
96
|
+
let science = rs`${hugeNumber}:E`; // '1E3'
|
|
97
|
+
let ordinal = rs`${hugeNumber}:n`; // '1000th'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Padding, Alignment
|
|
101
|
+
|
|
102
|
+
Values can be aligned using any fill character (will default to a space ` `), and either left, center or right aligned with `<`, `^` or `>` respectively (will default to right alignment `>`). You will also have to specify a width with an integer after the alignment, or provide a separate number parameter.
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
/*
|
|
106
|
+
Will print a pyramid of 'a's:
|
|
107
|
+
' a '
|
|
108
|
+
' aaa '
|
|
109
|
+
'aaaaa'
|
|
110
|
+
*/
|
|
111
|
+
let pyramidLevels = ['a', 'aaa', 'aaaaa'];
|
|
112
|
+
for(let value of pyramidLevels) {
|
|
113
|
+
println(rs`${value}:^5`);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
rs`${[1,2]}:.>${7}` // '....1,2'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Pretty Printing
|
|
122
|
+
|
|
123
|
+
In some instances (namely debug, binary, octal and hexadecimal formatting), adding a `#` before the format specifier will use an alternative 'pretty' printing style. This amounts to using multiline `util.inspect` for debug printing (spanning multiple lines), and adding `0b`/`0o`/`0x` as a prefix for the numbers in the respective bases.
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
rs`${255}:#X` // '0xFF'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Specific Number Formatting
|
|
130
|
+
|
|
131
|
+
Specifically for `number` and `bigint` values, a `0` can be placed before the width to pad the number with zeroes instead. This will account for signs and possible formatting differences.
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
rs`${15}:#07x` // '0x0000F'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Decimal precision can be specified for numbers by adding a `.` and specifying an integer for precision. An additional parameter can also be provided to do this dynamically.
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
rs`${1.23456789}:.3` // '1.234'
|
|
141
|
+
rs`${-1}:.${3}` // '-1.000'
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Adding a `+` to the formatting specifier will print the sign regardless of whether the number is negative.
|
|
145
|
+
Adding a `-` will instead add a space if the number is positive.
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
rs`${1}:+` // '+1'
|
|
149
|
+
rs`${1}:-` // ' 1'
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Older versions of RSFormat
|
|
153
|
+
|
|
154
|
+
Versions of RSFormat on npm prior to `1.0.0` provide formatting and printing functions that are more similar in syntax to Rust, using plain strings instead of tagged templates:
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
import { format } from 'rsformat';
|
|
158
|
+
format('{} is {0:#x} in hex', 15); // '15 is 0xf in hex'
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
See the `old` branch for more detailed documentation. The last version to use this formatting was `0.2.5`.
|
package/lib/format.d.ts
CHANGED
|
@@ -1,17 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Type representing a string formatted by `rs`.
|
|
3
|
+
* An extension of `String`.
|
|
4
|
+
*/
|
|
5
|
+
export declare class RsString extends String {
|
|
6
|
+
__debugColors: boolean;
|
|
7
|
+
private cachedColor;
|
|
8
|
+
private cachedPlain;
|
|
9
|
+
private strings;
|
|
10
|
+
private params;
|
|
11
|
+
constructor(strings: TemplateStringsArray, params: any[]);
|
|
12
|
+
toString(): string;
|
|
13
|
+
valueOf(): string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Format a template literal with rust-style formatting and return it as a string.
|
|
3
17
|
*
|
|
4
|
-
* @param
|
|
5
|
-
* @param params
|
|
18
|
+
* @param strings String parts of the template
|
|
19
|
+
* @param params Template parameters
|
|
20
|
+
* @returns a string primitive of the formatted string
|
|
6
21
|
*/
|
|
7
|
-
export declare function
|
|
22
|
+
export declare function buildString(strings: TemplateStringsArray, params: any[], debugColors?: boolean): string;
|
|
23
|
+
type AlignDirection = '<' | '^' | '>';
|
|
24
|
+
type Sign = '-' | '+' | '';
|
|
25
|
+
type FormatType = '?' | 'o' | 'x' | 'X' | 'b' | 'e' | 'E' | 'n' | 'N' | '';
|
|
26
|
+
type FormatSpecifier = {
|
|
27
|
+
fill: string;
|
|
28
|
+
align: AlignDirection;
|
|
29
|
+
force_sign: Sign;
|
|
30
|
+
pretty: boolean;
|
|
31
|
+
pad_zeroes: boolean;
|
|
32
|
+
width: number;
|
|
33
|
+
precision: number;
|
|
34
|
+
type: FormatType;
|
|
35
|
+
};
|
|
8
36
|
/**
|
|
9
|
-
*
|
|
37
|
+
* Format a parameter as a string according to a specifier.
|
|
10
38
|
*
|
|
11
|
-
* @param
|
|
12
|
-
* @param
|
|
13
|
-
* @param
|
|
39
|
+
* @param param parameter to format
|
|
40
|
+
* @param format format specifier object
|
|
41
|
+
* @param debugColors whether to use colors in debug formatting
|
|
42
|
+
* @returns `param` as a formatted string
|
|
14
43
|
*/
|
|
15
|
-
export declare function
|
|
16
|
-
|
|
17
|
-
}): string;
|
|
44
|
+
export declare function formatParam(param: any, format: FormatSpecifier, debugColors: boolean): string;
|
|
45
|
+
export {};
|
package/lib/format.js
CHANGED
|
@@ -1,212 +1,339 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
+
exports.formatParam = exports.buildString = exports.RsString = void 0;
|
|
7
|
+
const node_util_1 = __importDefault(require("node:util"));
|
|
8
|
+
const is_digit = (c) => c >= '0' && c <= '9';
|
|
9
|
+
const error = (param, char, reason) => new Error(`rs[param ${param}, char ${char}] ${reason}`);
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* but with a few key differences:
|
|
10
|
-
* - Named arguments before format specifiers aren't allowed, only numbers can be used.
|
|
11
|
-
* - The - sign (unused in rust) is unsupported.
|
|
12
|
-
* - Pointer format type 'p' is unsupported.
|
|
13
|
-
* - Hexadecimal debug types 'x?' and 'X?' are unsupported.
|
|
14
|
-
* - Specifying precision with * is unsupported.
|
|
15
|
-
*
|
|
16
|
-
* The formatter currently matches with a regex
|
|
17
|
-
* instead of a full-blown parser for simplicity
|
|
18
|
-
* and performance, as built-in regex matching is
|
|
19
|
-
* likely to be faster than a js-implemented parser.
|
|
20
|
-
* However, this will not match incorrectly formatted
|
|
21
|
-
* insertion points.
|
|
11
|
+
* Type representing a string formatted by `rs`.
|
|
12
|
+
* An extension of `String`.
|
|
22
13
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
class RsString extends String {
|
|
15
|
+
__debugColors = false;
|
|
16
|
+
cachedColor = null;
|
|
17
|
+
cachedPlain = null;
|
|
18
|
+
strings;
|
|
19
|
+
params;
|
|
20
|
+
constructor(strings, params) {
|
|
21
|
+
super('[use rs.raw to get string primitive]');
|
|
22
|
+
Object.defineProperties(this, {
|
|
23
|
+
strings: { value: strings, enumerable: false },
|
|
24
|
+
params: { value: params, enumerable: false },
|
|
25
|
+
cachedPlain: { value: null, writable: true, enumerable: false },
|
|
26
|
+
cachedColor: { value: null, writable: true, enumerable: false },
|
|
27
|
+
__debugColors: { value: false, writable: true, enumerable: false },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
toString() {
|
|
31
|
+
if (this.__debugColors) {
|
|
32
|
+
if (this.cachedColor === null)
|
|
33
|
+
this.cachedColor = buildString(this.strings, this.params, true);
|
|
34
|
+
return this.cachedColor;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (this.cachedPlain === null)
|
|
38
|
+
this.cachedPlain = buildString(this.strings, this.params, false);
|
|
39
|
+
return this.cachedPlain;
|
|
40
|
+
}
|
|
41
|
+
;
|
|
42
|
+
}
|
|
43
|
+
valueOf() {
|
|
44
|
+
return this.toString();
|
|
45
|
+
}
|
|
32
46
|
}
|
|
47
|
+
exports.RsString = RsString;
|
|
33
48
|
/**
|
|
34
|
-
*
|
|
49
|
+
* Format a template literal with rust-style formatting and return it as a string.
|
|
35
50
|
*
|
|
36
|
-
* @param
|
|
37
|
-
* @param params
|
|
38
|
-
* @
|
|
51
|
+
* @param strings String parts of the template
|
|
52
|
+
* @param params Template parameters
|
|
53
|
+
* @returns a string primitive of the formatted string
|
|
39
54
|
*/
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
let
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
function buildString(strings, params, debugColors = false) {
|
|
56
|
+
let out = [strings[0]];
|
|
57
|
+
for (let i = 1; i < strings.length; ++i) {
|
|
58
|
+
let string = strings[i];
|
|
59
|
+
let param = params[i - 1];
|
|
60
|
+
// Resolve parameter references recursively
|
|
61
|
+
while (typeof param == 'object' && '__rs_param_ref' in param) {
|
|
62
|
+
let ref_number = param.__rs_param_ref;
|
|
63
|
+
if (typeof ref_number != 'number'
|
|
64
|
+
|| ref_number < 0 || ref_number >= params.length) {
|
|
65
|
+
throw new Error(`Parameter ${i - 1}: Invalid reference`);
|
|
66
|
+
}
|
|
67
|
+
if (ref_number == i - 1)
|
|
68
|
+
throw new Error(`Parameter ${i - 1} references itself recursively`);
|
|
69
|
+
param = params[param.__rs_param_ref];
|
|
70
|
+
}
|
|
71
|
+
// Parse format specifier
|
|
72
|
+
// If the string starts with a single : it has a format specifier,
|
|
73
|
+
// If it has two the first : is being escaped and can be removed
|
|
74
|
+
if (string[0] == ':') {
|
|
75
|
+
if (string[1] == ':') {
|
|
76
|
+
out.push(param.toString() + string.substring(1));
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
out.push(param.toString() + string);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
;
|
|
85
|
+
// Keep track of our index in the string to slice the format specifier later
|
|
86
|
+
let idx = 1;
|
|
87
|
+
// Compute format based on string
|
|
88
|
+
let fill = ' ', align = '>', force_sign = '', pretty = false, pad_zeroes = false, width = 0, precision = -1, format_type = '';
|
|
89
|
+
// Fill/align
|
|
90
|
+
// If the next character is align, then the current is the fill
|
|
91
|
+
if (string[idx + 1] == '<' || string[idx + 1] == '^' || string[idx + 1] == '>') {
|
|
92
|
+
fill = string[idx++];
|
|
93
|
+
}
|
|
94
|
+
if (string[idx] == '<' || string[idx] == '^' || string[idx] == '>') {
|
|
95
|
+
align = string[idx++];
|
|
96
|
+
}
|
|
97
|
+
// Force sign
|
|
98
|
+
if (string[idx] == '+' || string[idx] == '-')
|
|
99
|
+
force_sign = string[idx++];
|
|
100
|
+
// Pretty formatting
|
|
101
|
+
if (string[idx] == '#')
|
|
102
|
+
pretty = true, idx++;
|
|
103
|
+
// Padding numbers with zeroes
|
|
104
|
+
if (string[idx] == '0')
|
|
105
|
+
pad_zeroes = true, idx++;
|
|
106
|
+
// Width
|
|
107
|
+
if (is_digit(string[idx])) {
|
|
108
|
+
let width_substring_start = idx++;
|
|
109
|
+
while (is_digit(string[idx]))
|
|
110
|
+
idx++;
|
|
111
|
+
width = Number(string.substring(width_substring_start, idx));
|
|
112
|
+
}
|
|
113
|
+
else if (idx == string.length) {
|
|
114
|
+
// Grab the next parameter and fuse the string with the next one
|
|
115
|
+
width = params[i];
|
|
116
|
+
if (typeof width != 'number')
|
|
117
|
+
throw error(i - 1, idx, `Expected a number or number parameter for width specifier (found ${string[idx] ? "'" + string[idx] + "'" : typeof width + ' parameter'}).\nIf the next parameter was not meant to be a width number, add a : to the end of the formatting specifier.`);
|
|
118
|
+
string += strings[++i];
|
|
119
|
+
}
|
|
120
|
+
// Precision
|
|
121
|
+
if (string[idx] == '.') {
|
|
122
|
+
if (!is_digit(string[++idx])) {
|
|
123
|
+
// Grab the next parameter and fuse the string with the next one
|
|
124
|
+
precision = params[i];
|
|
125
|
+
if (typeof precision != 'number')
|
|
126
|
+
throw error(i - 1, idx, `Expected a number or number parameter for precision specifier after . (found ${string[idx] ? "'" + string[idx] + "'" : typeof width + ' parameter'}).\nIf the next parameter was not meant to be a precision number, add a : to the end of the formatting specifier.`);
|
|
127
|
+
string += strings[++i];
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
let precision_substring_start = idx;
|
|
131
|
+
while (is_digit(string[idx]))
|
|
132
|
+
idx++;
|
|
133
|
+
precision = Number(string.substring(precision_substring_start, idx));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Format type
|
|
137
|
+
switch (string[idx]) {
|
|
138
|
+
case '?':
|
|
62
139
|
case 'o':
|
|
63
|
-
param = param.toString(8);
|
|
64
|
-
break;
|
|
65
140
|
case 'x':
|
|
66
|
-
param = param.toString(16);
|
|
67
|
-
break;
|
|
68
141
|
case 'X':
|
|
69
|
-
param = param.toString(16).toUpperCase();
|
|
70
|
-
break;
|
|
71
142
|
case 'b':
|
|
72
|
-
param = param.toString(2);
|
|
73
|
-
break;
|
|
74
143
|
case 'e':
|
|
75
|
-
switch (param_type) {
|
|
76
|
-
case 'number':
|
|
77
|
-
param = param.toExponential();
|
|
78
|
-
break;
|
|
79
|
-
case 'bigint':
|
|
80
|
-
param = param.toLocaleString('en-US', {
|
|
81
|
-
notation: 'scientific',
|
|
82
|
-
maximumFractionDigits: 20,
|
|
83
|
-
}).toLowerCase();
|
|
84
|
-
break;
|
|
85
|
-
default:
|
|
86
|
-
param = param.toString();
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
144
|
case 'E':
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
break;
|
|
95
|
-
case 'bigint':
|
|
96
|
-
param = param.toLocaleString('en-US', {
|
|
97
|
-
notation: 'scientific',
|
|
98
|
-
maximumFractionDigits: 20
|
|
99
|
-
});
|
|
100
|
-
break;
|
|
101
|
-
default:
|
|
102
|
-
param = param.toString();
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
break;
|
|
106
|
-
case '?':
|
|
107
|
-
// Do not force sign or align to precision when using inspect
|
|
108
|
-
$sign = undefined;
|
|
109
|
-
$precision = undefined;
|
|
110
|
-
true_length = (0, node_util_1.inspect)(param, {
|
|
111
|
-
depth: Infinity,
|
|
112
|
-
colors: false,
|
|
113
|
-
compact: $pretty !== '#'
|
|
114
|
-
}).length;
|
|
115
|
-
param = (0, node_util_1.inspect)(param, {
|
|
116
|
-
depth: Infinity,
|
|
117
|
-
colors: options.colors,
|
|
118
|
-
compact: $pretty !== '#'
|
|
119
|
-
});
|
|
120
|
-
break;
|
|
121
|
-
default:
|
|
122
|
-
param = param.toString();
|
|
123
|
-
break;
|
|
145
|
+
case 'n':
|
|
146
|
+
case 'N':
|
|
147
|
+
format_type = string[idx++];
|
|
124
148
|
}
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
// Compute radix-point precision on numbers
|
|
130
|
-
if (param_type == 'number' && $precision) {
|
|
131
|
-
let [pre, post] = param.split('.');
|
|
132
|
-
let precision = +$precision.substring(1, $precision.length);
|
|
133
|
-
if (!precision) { // precision = 0, do not include radix point
|
|
134
|
-
param = pre;
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
post = ((post || '') + '0'.repeat(precision)).slice(0, precision);
|
|
138
|
-
param = pre + '.' + post;
|
|
139
|
-
}
|
|
149
|
+
// End of specifier
|
|
150
|
+
if (string[idx] == ':') {
|
|
151
|
+
idx++;
|
|
140
152
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
width = 0;
|
|
153
|
+
else if (string[idx] != ' ' && string[idx] !== undefined) {
|
|
154
|
+
throw error(i - 1, idx, `Expected colon (':') or space (' ') at end of formatting specifier (found '${string[idx]}')`);
|
|
144
155
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
// Format parameter according to specifier
|
|
157
|
+
let formatted = formatParam(param, {
|
|
158
|
+
fill,
|
|
159
|
+
align,
|
|
160
|
+
force_sign,
|
|
161
|
+
pretty,
|
|
162
|
+
pad_zeroes,
|
|
163
|
+
width,
|
|
164
|
+
precision,
|
|
165
|
+
type: format_type
|
|
166
|
+
}, debugColors);
|
|
167
|
+
out.push(formatted + string.substring(idx));
|
|
168
|
+
}
|
|
169
|
+
return out.join('');
|
|
170
|
+
}
|
|
171
|
+
exports.buildString = buildString;
|
|
172
|
+
/**
|
|
173
|
+
* Format a parameter as a string according to a specifier.
|
|
174
|
+
*
|
|
175
|
+
* @param param parameter to format
|
|
176
|
+
* @param format format specifier object
|
|
177
|
+
* @param debugColors whether to use colors in debug formatting
|
|
178
|
+
* @returns `param` as a formatted string
|
|
179
|
+
*/
|
|
180
|
+
function formatParam(param, format, debugColors) {
|
|
181
|
+
let param_type = typeof param;
|
|
182
|
+
let true_length = -1;
|
|
183
|
+
// Process parameter type
|
|
184
|
+
switch (format.type) {
|
|
185
|
+
case 'o':
|
|
186
|
+
param = param.toString(8);
|
|
187
|
+
break;
|
|
188
|
+
case 'x':
|
|
189
|
+
param = param.toString(16);
|
|
190
|
+
break;
|
|
191
|
+
case 'X':
|
|
192
|
+
param = param.toString(16).toUpperCase();
|
|
193
|
+
break;
|
|
194
|
+
case 'b':
|
|
195
|
+
param = param.toString(2);
|
|
196
|
+
break;
|
|
197
|
+
case 'e':
|
|
198
|
+
case 'E':
|
|
199
|
+
if (param_type != 'number' && param_type != 'bigint') {
|
|
200
|
+
param = param.toString();
|
|
201
|
+
break;
|
|
156
202
|
}
|
|
157
|
-
|
|
158
|
-
|
|
203
|
+
param = param.toLocaleString('en-US', { notation: 'scientific', maximumFractionDigits: 20 });
|
|
204
|
+
if (format.type == 'e')
|
|
205
|
+
param = param.toLowercase();
|
|
206
|
+
break;
|
|
207
|
+
case 'n':
|
|
208
|
+
case 'N':
|
|
209
|
+
if (param_type != 'number' && param_type != 'bigint') {
|
|
210
|
+
param = param.toString();
|
|
211
|
+
break;
|
|
159
212
|
}
|
|
160
|
-
|
|
161
|
-
|
|
213
|
+
// Round and add suffix
|
|
214
|
+
if (param_type == 'number')
|
|
215
|
+
param = Math.round(param);
|
|
216
|
+
param = param.toString();
|
|
217
|
+
let last_2_digits = param.substring(param.length - 2);
|
|
218
|
+
if (last_2_digits == '11' || last_2_digits == '12' || last_2_digits == '13') {
|
|
219
|
+
param = param + 'th';
|
|
162
220
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
maybe_sign += "0o";
|
|
221
|
+
else
|
|
222
|
+
switch (last_2_digits[last_2_digits.length - 1]) {
|
|
223
|
+
case '1':
|
|
224
|
+
param = param + 'st';
|
|
168
225
|
break;
|
|
169
|
-
case '
|
|
170
|
-
|
|
171
|
-
maybe_sign += "0x";
|
|
226
|
+
case '2':
|
|
227
|
+
param = param + 'nd';
|
|
172
228
|
break;
|
|
173
|
-
case '
|
|
174
|
-
|
|
229
|
+
case '3':
|
|
230
|
+
param = param + 'rd';
|
|
175
231
|
break;
|
|
232
|
+
default: param = param + 'th';
|
|
176
233
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
234
|
+
if (format.type == 'N')
|
|
235
|
+
param = param.toUpperCase();
|
|
236
|
+
// Do not pad with zeroes or align to precision when using ordinal formatting
|
|
237
|
+
format.pad_zeroes = false;
|
|
238
|
+
format.precision = -1;
|
|
239
|
+
break;
|
|
240
|
+
case '?':
|
|
241
|
+
true_length = node_util_1.default.inspect(param, {
|
|
242
|
+
depth: Infinity,
|
|
243
|
+
colors: false,
|
|
244
|
+
compact: !format.pretty
|
|
245
|
+
}).length;
|
|
246
|
+
param = node_util_1.default.inspect(param, {
|
|
247
|
+
depth: Infinity,
|
|
248
|
+
colors: debugColors,
|
|
249
|
+
compact: !format.pretty
|
|
250
|
+
});
|
|
251
|
+
// Do not force sign, pad with zeroes or align to precision when using debug formatting
|
|
252
|
+
param_type = 'string';
|
|
253
|
+
break;
|
|
254
|
+
default:
|
|
255
|
+
param = param.toString();
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
;
|
|
259
|
+
if (true_length == -1) {
|
|
260
|
+
true_length = param.length;
|
|
261
|
+
}
|
|
262
|
+
// Compute radix-point precision on numbers
|
|
263
|
+
if (param_type == 'number' && format.precision != -1) {
|
|
264
|
+
let [pre, post] = param.split('.');
|
|
265
|
+
if (!format.precision) { // precision = 0, do not include radix point
|
|
266
|
+
param = pre;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
post = ((post || '') + '0'.repeat(format.precision)).slice(0, format.precision);
|
|
270
|
+
param = pre + '.' + post;
|
|
271
|
+
}
|
|
272
|
+
// Update true length for fill/align
|
|
273
|
+
true_length = param.length;
|
|
274
|
+
}
|
|
275
|
+
let filled = false;
|
|
276
|
+
if ((param_type == 'number') || (param_type == 'bigint')) {
|
|
277
|
+
// Compute parameter sign
|
|
278
|
+
let maybe_sign = param.substring(0, 1);
|
|
279
|
+
if (maybe_sign === '-') {
|
|
280
|
+
param = param.substring(1, param.length);
|
|
281
|
+
}
|
|
282
|
+
else if (format.force_sign == '+') {
|
|
283
|
+
maybe_sign = '+';
|
|
284
|
+
}
|
|
285
|
+
else if (format.force_sign == '-') {
|
|
286
|
+
maybe_sign = ' ';
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
maybe_sign = '';
|
|
290
|
+
}
|
|
291
|
+
// If pretty printing is enabled and the formating calls for a prefix, add it
|
|
292
|
+
if (format.pretty) {
|
|
293
|
+
switch (format.type) {
|
|
294
|
+
case 'o':
|
|
295
|
+
maybe_sign += '0o';
|
|
197
296
|
break;
|
|
198
|
-
case '
|
|
199
|
-
|
|
297
|
+
case 'x':
|
|
298
|
+
case 'X':
|
|
299
|
+
maybe_sign += '0x';
|
|
200
300
|
break;
|
|
201
|
-
case '
|
|
202
|
-
|
|
203
|
-
// Prioritise right-aligment on uneven length
|
|
204
|
-
right = $fill_character.repeat(diff / 2 + diff % 2);
|
|
301
|
+
case 'b':
|
|
302
|
+
maybe_sign += '0b';
|
|
205
303
|
break;
|
|
206
304
|
}
|
|
207
|
-
param = left + param + right;
|
|
208
305
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
306
|
+
//pad with zeroes if specified
|
|
307
|
+
if (format.pad_zeroes) {
|
|
308
|
+
filled = true;
|
|
309
|
+
while (param.length < format.width - maybe_sign.length) {
|
|
310
|
+
param = '0' + param;
|
|
311
|
+
true_length++;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
true_length += maybe_sign.length;
|
|
315
|
+
param = maybe_sign + param;
|
|
316
|
+
}
|
|
317
|
+
if (!filled && format.width > true_length) {
|
|
318
|
+
// Compute fill/align
|
|
319
|
+
let left = '';
|
|
320
|
+
let right = '';
|
|
321
|
+
let diff = format.width - true_length;
|
|
322
|
+
switch (format.align) {
|
|
323
|
+
case '>':
|
|
324
|
+
left = format.fill.repeat(diff);
|
|
325
|
+
break;
|
|
326
|
+
case '<':
|
|
327
|
+
right = format.fill.repeat(diff);
|
|
328
|
+
break;
|
|
329
|
+
case '^':
|
|
330
|
+
left = format.fill.repeat(diff - diff / 2);
|
|
331
|
+
// Prioritise right-aligment on uneven length
|
|
332
|
+
right = format.fill.repeat(diff / 2 + diff % 2);
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
param = left + param + right;
|
|
336
|
+
}
|
|
337
|
+
return param;
|
|
212
338
|
}
|
|
339
|
+
exports.formatParam = formatParam;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { RsString } from './format';
|
|
2
2
|
export { print, println, eprint, eprintln } from './print';
|
|
3
|
+
/**
|
|
4
|
+
* Tag to use Rust-style formatting in a template literal.
|
|
5
|
+
* Returns an extended `String` object.
|
|
6
|
+
*
|
|
7
|
+
* @returns a String object with the formatted string
|
|
8
|
+
*/
|
|
9
|
+
export declare function rs(strings: TemplateStringsArray, ...params: any[]): RsString;
|
|
10
|
+
export declare namespace rs {
|
|
11
|
+
var raw: (strings: TemplateStringsArray, ...params: any[]) => string;
|
|
12
|
+
var ref: (n: number) => {
|
|
13
|
+
__rs_param_ref: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "format", { enumerable: true, get: function () { return format_1.format; } });
|
|
3
|
+
exports.rs = exports.eprintln = exports.eprint = exports.println = exports.print = void 0;
|
|
4
|
+
const format_1 = require("./format");
|
|
6
5
|
var print_1 = require("./print");
|
|
7
6
|
Object.defineProperty(exports, "print", { enumerable: true, get: function () { return print_1.print; } });
|
|
8
7
|
Object.defineProperty(exports, "println", { enumerable: true, get: function () { return print_1.println; } });
|
|
9
8
|
Object.defineProperty(exports, "eprint", { enumerable: true, get: function () { return print_1.eprint; } });
|
|
10
9
|
Object.defineProperty(exports, "eprintln", { enumerable: true, get: function () { return print_1.eprintln; } });
|
|
10
|
+
/**
|
|
11
|
+
* Tag to use Rust-style formatting in a template literal.
|
|
12
|
+
* Returns an extended `String` object.
|
|
13
|
+
*
|
|
14
|
+
* @returns a String object with the formatted string
|
|
15
|
+
*/
|
|
16
|
+
function rs(strings, ...params) {
|
|
17
|
+
return new format_1.RsString(strings, params);
|
|
18
|
+
}
|
|
19
|
+
exports.rs = rs;
|
|
20
|
+
/**
|
|
21
|
+
* Tag to use Rust-style formatting in a template literal.
|
|
22
|
+
* Returns a `string` primitive.
|
|
23
|
+
*
|
|
24
|
+
* @returns a string primitive of the formatted string
|
|
25
|
+
*/
|
|
26
|
+
rs.raw = function (strings, ...params) {
|
|
27
|
+
return (0, format_1.buildString)(strings, params);
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Reference another parameter in a `rs`-tagged template.
|
|
31
|
+
*
|
|
32
|
+
* @param n Number of parameter to reference
|
|
33
|
+
* @returns A reference to the `n`th parameter
|
|
34
|
+
*/
|
|
35
|
+
rs.ref = (n) => ({ __rs_param_ref: n });
|
package/lib/print.d.ts
CHANGED
|
@@ -1,74 +1,41 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { Writable } from 'node:stream';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
+
* Print a string (or instance of String/RsString) to a stream.
|
|
4
5
|
*
|
|
5
|
-
* @param
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
6
|
+
* @param stream Stream to print the string to
|
|
7
|
+
* @param string String to print
|
|
8
|
+
* @param newline Whether to append a newline after the string
|
|
9
|
+
* @param colored Whether to use colors for `rs` debug formatting
|
|
10
|
+
*/
|
|
11
|
+
export declare function printToStream(stream: Writable, string: string | String, newline?: boolean, colored?: boolean): void;
|
|
12
|
+
/**
|
|
13
|
+
* Print a string to stdout.
|
|
8
14
|
*
|
|
9
|
-
* @
|
|
15
|
+
* @param string String to print
|
|
10
16
|
*/
|
|
11
|
-
export declare function
|
|
12
|
-
debugColors: boolean;
|
|
13
|
-
}): {
|
|
14
|
-
/**
|
|
15
|
-
* Print a format string to an output stream (usually process.stdout).
|
|
16
|
-
*
|
|
17
|
-
* @param format_string String used for formatting
|
|
18
|
-
* @param params Parameters to be inserted into the format string
|
|
19
|
-
*/
|
|
20
|
-
print: (format_string: string, ...params: any[]) => void;
|
|
21
|
-
/**
|
|
22
|
-
* Print a format string to an output stream (usually process.stdout)
|
|
23
|
-
* and append a newline.
|
|
24
|
-
*
|
|
25
|
-
* @param format_string String used for formatting
|
|
26
|
-
* @param params Parameters to be inserted into the format string
|
|
27
|
-
*/
|
|
28
|
-
println: (format_string: string, ...params: any[]) => void;
|
|
29
|
-
/**
|
|
30
|
-
* Print a format string to an error stream (usually process.stderr).
|
|
31
|
-
*
|
|
32
|
-
* @param format_string String used for formatting
|
|
33
|
-
* @param params Parameters to be inserted into the format string
|
|
34
|
-
*/
|
|
35
|
-
eprint: (format_string: string, ...params: any[]) => void;
|
|
36
|
-
/**
|
|
37
|
-
* Print a format string to an error stream (usually process.stderr)
|
|
38
|
-
* and append a newline.
|
|
39
|
-
*
|
|
40
|
-
* @param format_string String used for formatting
|
|
41
|
-
* @param params Parameters to be inserted into the format string
|
|
42
|
-
*/
|
|
43
|
-
eprintln: (format_string: string, ...params: any[]) => void;
|
|
44
|
-
};
|
|
17
|
+
export declare function print(string: string | String): void;
|
|
45
18
|
/**
|
|
46
|
-
* Print a
|
|
19
|
+
* Print a string to stdout and append a newline.
|
|
47
20
|
*
|
|
48
|
-
* @param
|
|
49
|
-
* @param params Parameters to be inserted into the format string
|
|
21
|
+
* @param string String to print
|
|
50
22
|
*/
|
|
51
|
-
export declare
|
|
23
|
+
export declare function println(string: string | String): void;
|
|
52
24
|
/**
|
|
53
|
-
* Print a
|
|
54
|
-
* and append a newline.
|
|
25
|
+
* Print a string to stderr.
|
|
55
26
|
*
|
|
56
|
-
* @param
|
|
57
|
-
* @param params Parameters to be inserted into the format string
|
|
27
|
+
* @param string String to print
|
|
58
28
|
*/
|
|
59
|
-
export declare
|
|
29
|
+
export declare function eprint(string: string | String): void;
|
|
60
30
|
/**
|
|
61
|
-
* Print a
|
|
31
|
+
* Print a string to stderr and append a newline.
|
|
62
32
|
*
|
|
63
|
-
* @param
|
|
64
|
-
* @param params Parameters to be inserted into the format string
|
|
33
|
+
* @param string String to print
|
|
65
34
|
*/
|
|
66
|
-
export declare
|
|
35
|
+
export declare function eprintln(string: string | String): void;
|
|
67
36
|
/**
|
|
68
|
-
*
|
|
69
|
-
* and append a newline.
|
|
37
|
+
* Debug print a value to stderr and return it.
|
|
70
38
|
*
|
|
71
|
-
* @param
|
|
72
|
-
* @param params Parameters to be inserted into the format string
|
|
39
|
+
* @param value Value to debug print
|
|
73
40
|
*/
|
|
74
|
-
export declare
|
|
41
|
+
export declare function dbg(value: any): any;
|
package/lib/print.js
CHANGED
|
@@ -3,121 +3,75 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.eprintln = exports.eprint = exports.println = exports.print = void 0;
|
|
7
|
-
exports.Printer = Printer;
|
|
8
|
-
const node_process_1 = __importDefault(require("node:process"));
|
|
6
|
+
exports.dbg = exports.eprintln = exports.eprint = exports.println = exports.print = exports.printToStream = void 0;
|
|
9
7
|
const format_1 = require("./format");
|
|
8
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
9
|
+
const _1 = require(".");
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Print a string (or instance of String/RsString) to a stream.
|
|
12
12
|
*
|
|
13
|
-
* @param
|
|
14
|
-
* @param
|
|
15
|
-
* @param
|
|
13
|
+
* @param stream Stream to print the string to
|
|
14
|
+
* @param string String to print
|
|
15
|
+
* @param newline Whether to append a newline after the string
|
|
16
|
+
* @param colored Whether to use colors for `rs` debug formatting
|
|
17
|
+
*/
|
|
18
|
+
function printToStream(stream, string, newline = false, colored = false) {
|
|
19
|
+
if (string instanceof format_1.RsString) {
|
|
20
|
+
let previousColors = string.__debugColors;
|
|
21
|
+
if (colored)
|
|
22
|
+
string.__debugColors = true;
|
|
23
|
+
let stringified = string.toString();
|
|
24
|
+
string.__debugColors = previousColors;
|
|
25
|
+
string = stringified;
|
|
26
|
+
}
|
|
27
|
+
if (newline)
|
|
28
|
+
string = string + '\n';
|
|
29
|
+
stream.write(string);
|
|
30
|
+
}
|
|
31
|
+
exports.printToStream = printToStream;
|
|
32
|
+
/**
|
|
33
|
+
* Print a string to stdout.
|
|
16
34
|
*
|
|
17
|
-
* @
|
|
35
|
+
* @param string String to print
|
|
18
36
|
*/
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Print a format string to an output stream (usually process.stdout).
|
|
23
|
-
*
|
|
24
|
-
* @param format_string String used for formatting
|
|
25
|
-
* @param params Parameters to be inserted into the format string
|
|
26
|
-
*/
|
|
27
|
-
print: function print(format_string, ...params) {
|
|
28
|
-
outStream.write((0, format_1.fmt_raw)(format_string, params, { colors: options.debugColors }));
|
|
29
|
-
},
|
|
30
|
-
/**
|
|
31
|
-
* Print a format string to an output stream (usually process.stdout)
|
|
32
|
-
* and append a newline.
|
|
33
|
-
*
|
|
34
|
-
* @param format_string String used for formatting
|
|
35
|
-
* @param params Parameters to be inserted into the format string
|
|
36
|
-
*/
|
|
37
|
-
println: function println(format_string, ...params) {
|
|
38
|
-
outStream.write((0, format_1.fmt_raw)(format_string, params, { colors: options.debugColors }) + '\n');
|
|
39
|
-
},
|
|
40
|
-
/**
|
|
41
|
-
* Print a format string to an error stream (usually process.stderr).
|
|
42
|
-
*
|
|
43
|
-
* @param format_string String used for formatting
|
|
44
|
-
* @param params Parameters to be inserted into the format string
|
|
45
|
-
*/
|
|
46
|
-
eprint: function eprint(format_string, ...params) {
|
|
47
|
-
errStream.write((0, format_1.fmt_raw)(format_string, params, { colors: options.debugColors }));
|
|
48
|
-
},
|
|
49
|
-
/**
|
|
50
|
-
* Print a format string to an error stream (usually process.stderr)
|
|
51
|
-
* and append a newline.
|
|
52
|
-
*
|
|
53
|
-
* @param format_string String used for formatting
|
|
54
|
-
* @param params Parameters to be inserted into the format string
|
|
55
|
-
*/
|
|
56
|
-
eprintln: function eprintln(format_string, ...params) {
|
|
57
|
-
errStream.write((0, format_1.fmt_raw)(format_string, params, { colors: options.debugColors }) + '\n');
|
|
58
|
-
},
|
|
59
|
-
};
|
|
37
|
+
function print(string) {
|
|
38
|
+
printToStream(node_process_1.default.stdout, string, false, true);
|
|
60
39
|
}
|
|
61
|
-
|
|
62
|
-
// /**
|
|
63
|
-
// * Print a format string to process.stdout.
|
|
64
|
-
// *
|
|
65
|
-
// * @param format_string String used for formatting
|
|
66
|
-
// * @param params Parameters to be inserted into the format string
|
|
67
|
-
// */
|
|
68
|
-
// print,
|
|
69
|
-
// /**
|
|
70
|
-
// * Print a format string to process.stdout
|
|
71
|
-
// * and append a newline.
|
|
72
|
-
// *
|
|
73
|
-
// * @param format_string String used for formatting
|
|
74
|
-
// * @param params Parameters to be inserted into the format string
|
|
75
|
-
// */
|
|
76
|
-
// println,
|
|
77
|
-
// /**
|
|
78
|
-
// * Print a format string to process.stderr.
|
|
79
|
-
// *
|
|
80
|
-
// * @param format_string String used for formatting
|
|
81
|
-
// * @param params Parameters to be inserted into the format string
|
|
82
|
-
// */
|
|
83
|
-
// eprint,
|
|
84
|
-
// /**
|
|
85
|
-
// * Print a format string to process.stderr
|
|
86
|
-
// * and append a newline.
|
|
87
|
-
// *
|
|
88
|
-
// * @param format_string String used for formatting
|
|
89
|
-
// * @param params Parameters to be inserted into the format string
|
|
90
|
-
// */
|
|
91
|
-
// eprintln
|
|
92
|
-
// } = Printer();
|
|
93
|
-
const default_printer = Printer();
|
|
40
|
+
exports.print = print;
|
|
94
41
|
/**
|
|
95
|
-
* Print a
|
|
42
|
+
* Print a string to stdout and append a newline.
|
|
96
43
|
*
|
|
97
|
-
* @param
|
|
98
|
-
* @param params Parameters to be inserted into the format string
|
|
44
|
+
* @param string String to print
|
|
99
45
|
*/
|
|
100
|
-
|
|
46
|
+
function println(string) {
|
|
47
|
+
printToStream(node_process_1.default.stdout, string, true, true);
|
|
48
|
+
}
|
|
49
|
+
exports.println = println;
|
|
101
50
|
/**
|
|
102
|
-
* Print a
|
|
103
|
-
* and append a newline.
|
|
51
|
+
* Print a string to stderr.
|
|
104
52
|
*
|
|
105
|
-
* @param
|
|
106
|
-
* @param params Parameters to be inserted into the format string
|
|
53
|
+
* @param string String to print
|
|
107
54
|
*/
|
|
108
|
-
|
|
55
|
+
function eprint(string) {
|
|
56
|
+
printToStream(node_process_1.default.stderr, string, false, true);
|
|
57
|
+
}
|
|
58
|
+
exports.eprint = eprint;
|
|
109
59
|
/**
|
|
110
|
-
* Print a
|
|
60
|
+
* Print a string to stderr and append a newline.
|
|
111
61
|
*
|
|
112
|
-
* @param
|
|
113
|
-
* @param params Parameters to be inserted into the format string
|
|
62
|
+
* @param string String to print
|
|
114
63
|
*/
|
|
115
|
-
|
|
64
|
+
function eprintln(string) {
|
|
65
|
+
printToStream(node_process_1.default.stderr, string, true, true);
|
|
66
|
+
}
|
|
67
|
+
exports.eprintln = eprintln;
|
|
116
68
|
/**
|
|
117
|
-
*
|
|
118
|
-
* and append a newline.
|
|
69
|
+
* Debug print a value to stderr and return it.
|
|
119
70
|
*
|
|
120
|
-
* @param
|
|
121
|
-
* @param params Parameters to be inserted into the format string
|
|
71
|
+
* @param value Value to debug print
|
|
122
72
|
*/
|
|
123
|
-
|
|
73
|
+
function dbg(value) {
|
|
74
|
+
eprintln((0, _1.rs) `${value}:?`);
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
exports.dbg = dbg;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rsformat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Formatting/printing library for JavaScript that takes after rust's string formatting ",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib",
|
|
@@ -16,10 +16,6 @@
|
|
|
16
16
|
"default": "./lib/*.js"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
|
-
"scripts": {
|
|
20
|
-
"build": "tsc",
|
|
21
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
22
|
-
},
|
|
23
19
|
"keywords": [
|
|
24
20
|
"fmt",
|
|
25
21
|
"format",
|
|
@@ -36,5 +32,8 @@
|
|
|
36
32
|
"devDependencies": {
|
|
37
33
|
"@types/node": "^22.8.6"
|
|
38
34
|
},
|
|
39
|
-
"
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
38
|
+
}
|
|
40
39
|
}
|