rsformat 0.2.3 → 0.2.4

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 CHANGED
@@ -1,170 +1,170 @@
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
- ## Motivation
6
-
7
- `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`.
8
-
9
- RSFormat provides alternative functions with standardised behaviour: its `format`, `println` and all other functions will always output in the same manner, and have a standardised syntax which will only print the initial string, formatted with the parameters provided afterwards.
10
-
11
- Rust formatting also includes a lot of convenient operators for formatting text, such as padding/alignment, printing numbers in a given base, specifying decimal precision, etc.. This makes it a more ergonomic and convenient approach to printing things to the console.
12
-
13
- ## Usage
14
-
15
- you can install rsformat using [npm](https://www.npmjs.com/package/rsformat):
16
-
17
- ```
18
- npm install rsformat
19
- ```
20
-
21
- ### Basic formatting and printing to console
22
-
23
- RSFormat functions are called using a format string, and any number of format arguments following it.
24
-
25
- Any instance of `{}` in the format strings will get replaced with a value.
26
-
27
- You can specify what value you want in the parameters by using a number inside the insertion point.
28
-
29
- ```js
30
- import { format, println } from 'rsformat'; // ESM
31
- const { format, println } = require('rsformat'); // CommonJS
32
-
33
- let name = 'everyone';
34
-
35
- let greeting = format('Hello {}!', name); // Evaluates to the string 'Hello, everyone!'
36
-
37
- println('I have {1} apples and {0} oranges', 13, 14); // Will print 'I have 14 apples and 13 oranges' to the console
38
- ```
39
-
40
- ### Format Specifiers
41
-
42
- Format specifiers can be used by adding `:` inside the insertion point (after the optional argument number), and will format the value differently inside the string. See the [rust format docs](https://doc.rust-lang.org/std/fmt/#syntax) for more detailed information on format specifiers.
43
-
44
- This implementation differs from the rust one in a few ways:
45
-
46
- - Named arguments before or in format specifiers or in values aren't allowed, only numbers can be used.
47
- - The `-` sign (unused in rust) is unsupported.
48
- - Pointer format type `p` is unsupported.
49
- - Hexadecimal debug types `x?` and `X?` are unsupported.
50
- - Specifying precision with `*` is unsupported.
51
-
52
- #### Different formatting types
53
-
54
- ```js
55
- // Debug format specifier: ?, uses util.inspect rather than toString
56
-
57
- println('{}', { a: 1 }); //prints '[object Object]'
58
- println('{:?}', { a: 1 }); //prints "{ a:1 }"
59
-
60
- // Number base specifiers: x, X, b, o - for lower/uppercase hexadecimal, binary, octal
61
-
62
- format('{} is {0:x} in hex, {0:b} in binary and {0:o} in octal', 15); // '15 is f in hex, 1111 in binary and 17 in octal'
63
-
64
- // Scientific notation specifiers: e, E - for lower/uppercase scientific notation
65
-
66
- let hugeNumber = 1000n;
67
- format('{:E}', hugeNumber); // '1E3';
68
- ```
69
-
70
- #### Padding, Alignment
71
-
72
- 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:
73
-
74
- ```js
75
- /*
76
- Will print a pyramid of 'a's:
77
- ' a '
78
- ' aaa '
79
- 'aaaaa'
80
- */
81
- let pyramidLevels = ['a', 'aaa', 'aaaaa'];
82
- for(let value of pyramidLevels) {
83
- println('{:^5}', value);
84
- }
85
- ```
86
-
87
- ```js
88
- format('{:.>7}', [1,2]); // '....1,2'
89
- ```
90
-
91
- #### Pretty Printing
92
-
93
- 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 non-compact `util.inspect` for debug printing (spanning multiple lines), and adding 0b/0o/0x as a prefix for the numbers formatted as powers of two.
94
-
95
- ```js
96
- format('{:#X}', 255); // '0xFF'
97
- ```
98
-
99
- #### Specific Number Formatting
100
-
101
- Specifically for `number` and `bigint` values, a 0 can be placed before the width to pad the number with 0s instead. This will account for signs and possible formatting differences.
102
-
103
- ```js
104
- format('{:#07x}', 15) // '0x0000F'
105
- ```
106
-
107
- Decimal precision can be specified for numbers by adding a . and specifying an integer for precision.
108
-
109
- ```js
110
- format('{:.3}', 1.23456789); // '1.234'
111
- format('{:.3}', -1); // '-1.000'
112
- ```
113
-
114
- Adding a + to the formatting specifier will print the sign regardless of whether the number is negative.
115
-
116
- ```js
117
- format('{:+}', 1); // '+1'
118
- ```
119
-
120
- ## Custom output
121
-
122
- If you want to use the print function to output to anything other than `process.stdout` and `process.stderr`, you can import the `Printer` function to create your own print functions, using any output and error streams that are instances of node's `Writable`.
123
-
124
- ```ts
125
- // Custom output example (ts)
126
- import { Printer } from 'rsformat/print';
127
- import { Writable } from 'stream';
128
-
129
- let someOutputStream: Writable = /* ... */;
130
- let someErrorStream: Writable = /* ... */;
131
-
132
- let { print, println, eprint, eprintln } = Printer(someOutputStream, someErrorStream);
133
- ```
134
-
135
- ## A Note on Performance
136
-
137
- You might think that these utilities might have a performance impact on RSFormat's printing functions. And while they do, the functions are still consistently faster than `console.log`.
138
-
139
- A simple benchmark setup like the one below will demonstrate that `println` is more performant, even when doing things like base conversions and text alignment, compared to `console.log` logging a simple string:
140
-
141
- ```js
142
- // benchmark.mjs
143
- import { println } from 'rsformat';
144
-
145
- const time = (fn, iter) => {
146
- let time = Date.now();
147
- while (iter-- > 0) {
148
- fn();
149
- }
150
- return Date.now() - time;
151
- }
152
-
153
- let iterations = 100000;
154
-
155
- let logTime = time(() => console.log('hello'), iterations);
156
- let printlnTime = time(() => println('{:>+#7X}', 255), iterations);
157
-
158
- println('console.log time for {} executions: {}ms', iterations, logTime);
159
- println('rsformat.println time for {} executions: {}ms', iterations, printlnTime);
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
-
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
+ ## Motivation
6
+
7
+ `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`.
8
+
9
+ RSFormat provides alternative functions with standardised behaviour: its `format`, `println` and all other functions will always output in the same manner, and have a standardised syntax which will only print the initial string, formatted with the parameters provided afterwards.
10
+
11
+ Rust formatting also includes a lot of convenient operators for formatting text, such as padding/alignment, printing numbers in a given base, specifying decimal precision, etc.. This makes it a more ergonomic and convenient approach to printing things to the console.
12
+
13
+ ## Usage
14
+
15
+ you can install rsformat using [npm](https://www.npmjs.com/package/rsformat):
16
+
17
+ ```
18
+ npm install rsformat
19
+ ```
20
+
21
+ ### Basic formatting and printing to console
22
+
23
+ RSFormat functions are called using a format string, and any number of format arguments following it.
24
+
25
+ Any instance of `{}` in the format strings will get replaced with a value.
26
+
27
+ You can specify what value you want in the parameters by using a number inside the insertion point.
28
+
29
+ ```js
30
+ import { format, println } from 'rsformat'; // ESM
31
+ const { format, println } = require('rsformat'); // CommonJS
32
+
33
+ let name = 'everyone';
34
+
35
+ let greeting = format('Hello {}!', name); // Evaluates to the string 'Hello, everyone!'
36
+
37
+ println('I have {1} apples and {0} oranges', 13, 14); // Will print 'I have 14 apples and 13 oranges' to the console
38
+ ```
39
+
40
+ ### Format Specifiers
41
+
42
+ Format specifiers can be used by adding `:` inside the insertion point (after the optional argument number), and will format the value differently inside the string. See the [rust format docs](https://doc.rust-lang.org/std/fmt/#syntax) for more detailed information on format specifiers.
43
+
44
+ This implementation differs from the rust one in a few ways:
45
+
46
+ - Named arguments before or in format specifiers or in values aren't allowed, only numbers can be used.
47
+ - The `-` sign (unused in rust) is unsupported.
48
+ - Pointer format type `p` is unsupported.
49
+ - Hexadecimal debug types `x?` and `X?` are unsupported.
50
+ - Specifying precision with `*` is unsupported.
51
+
52
+ #### Different formatting types
53
+
54
+ ```js
55
+ // Debug format specifier: ?, uses util.inspect rather than toString
56
+
57
+ println('{}', { a: 1 }); //prints '[object Object]'
58
+ println('{:?}', { a: 1 }); //prints "{ a:1 }"
59
+
60
+ // Number base specifiers: x, X, b, o - for lower/uppercase hexadecimal, binary, octal
61
+
62
+ format('{} is {0:x} in hex, {0:b} in binary and {0:o} in octal', 15); // '15 is f in hex, 1111 in binary and 17 in octal'
63
+
64
+ // Scientific notation specifiers: e, E - for lower/uppercase scientific notation
65
+
66
+ let hugeNumber = 1000n;
67
+ format('{:E}', hugeNumber); // '1E3';
68
+ ```
69
+
70
+ #### Padding, Alignment
71
+
72
+ 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:
73
+
74
+ ```js
75
+ /*
76
+ Will print a pyramid of 'a's:
77
+ ' a '
78
+ ' aaa '
79
+ 'aaaaa'
80
+ */
81
+ let pyramidLevels = ['a', 'aaa', 'aaaaa'];
82
+ for(let value of pyramidLevels) {
83
+ println('{:^5}', value);
84
+ }
85
+ ```
86
+
87
+ ```js
88
+ format('{:.>7}', [1,2]); // '....1,2'
89
+ ```
90
+
91
+ #### Pretty Printing
92
+
93
+ 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 non-compact `util.inspect` for debug printing (spanning multiple lines), and adding 0b/0o/0x as a prefix for the numbers formatted as powers of two.
94
+
95
+ ```js
96
+ format('{:#X}', 255); // '0xFF'
97
+ ```
98
+
99
+ #### Specific Number Formatting
100
+
101
+ Specifically for `number` and `bigint` values, a 0 can be placed before the width to pad the number with 0s instead. This will account for signs and possible formatting differences.
102
+
103
+ ```js
104
+ format('{:#07x}', 15) // '0x0000F'
105
+ ```
106
+
107
+ Decimal precision can be specified for numbers by adding a . and specifying an integer for precision.
108
+
109
+ ```js
110
+ format('{:.3}', 1.23456789); // '1.234'
111
+ format('{:.3}', -1); // '-1.000'
112
+ ```
113
+
114
+ Adding a + to the formatting specifier will print the sign regardless of whether the number is negative.
115
+
116
+ ```js
117
+ format('{:+}', 1); // '+1'
118
+ ```
119
+
120
+ ## Custom output
121
+
122
+ If you want to use the print function to output to anything other than `process.stdout` and `process.stderr`, you can import the `Printer` function to create your own print functions, using any output and error streams that are instances of node's `Writable`.
123
+
124
+ ```ts
125
+ // Custom output example (ts)
126
+ import { Printer } from 'rsformat/print';
127
+ import { Writable } from 'stream';
128
+
129
+ let someOutputStream: Writable = /* ... */;
130
+ let someErrorStream: Writable = /* ... */;
131
+
132
+ let { print, println, eprint, eprintln } = Printer(someOutputStream, someErrorStream);
133
+ ```
134
+
135
+ ## A Note on Performance
136
+
137
+ You might think that these utilities might have a performance impact on RSFormat's printing functions. And while they do, the functions are still consistently faster than `console.log`.
138
+
139
+ A simple benchmark setup like the one below will demonstrate that `println` is more performant, even when doing things like base conversions and text alignment, compared to `console.log` logging a simple string:
140
+
141
+ ```js
142
+ // benchmark.mjs
143
+ import { println } from 'rsformat';
144
+
145
+ const time = (fn, iter) => {
146
+ let time = Date.now();
147
+ while (iter-- > 0) {
148
+ fn();
149
+ }
150
+ return Date.now() - time;
151
+ }
152
+
153
+ let iterations = 100000;
154
+
155
+ let logTime = time(() => console.log('hello'), iterations);
156
+ let printlnTime = time(() => println('{:>+#7X}', 255), iterations);
157
+
158
+ println('console.log time for {} executions: {}ms', iterations, logTime);
159
+ println('rsformat.println time for {} executions: {}ms', iterations, printlnTime);
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
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._
package/lib/format.d.ts CHANGED
@@ -10,8 +10,7 @@ export declare function format(str: string, ...params: any[]): string;
10
10
  *
11
11
  * @param str String used for formatting
12
12
  * @param params Parameters to be inserted into the format string
13
- * @param options Options passed into formatting
14
- * @param options.colors Whether to use colors in debug formatting
13
+ * @param options Options passed into formatting (Whether to use colors in debug formatting - false by default)
15
14
  */
16
15
  export declare function fmt_raw(str: string, params: any[], options?: {
17
16
  colors: boolean;
package/lib/format.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fmt_raw = exports.format = void 0;
3
+ exports.format = format;
4
+ exports.fmt_raw = fmt_raw;
4
5
  const node_util_1 = require("node:util");
5
6
  /**
6
7
  * Regex to match for possible formatting insertion points.
@@ -29,14 +30,12 @@ const FORMAT_REGEX = (/\{{2}|\}{2}|\{(\d*?)(?::(?:(.?)(\^|>|<))?(\+)?(#)?(0)?(\d
29
30
  function format(str, ...params) {
30
31
  return fmt_raw(str, params);
31
32
  }
32
- exports.format = format;
33
33
  /**
34
34
  * Raw formatting behaviour function called by `format` and printing functions.
35
35
  *
36
36
  * @param str String used for formatting
37
37
  * @param params Parameters to be inserted into the format string
38
- * @param options Options passed into formatting
39
- * @param options.colors Whether to use colors in debug formatting
38
+ * @param options Options passed into formatting (Whether to use colors in debug formatting - false by default)
40
39
  */
41
40
  function fmt_raw(str, params, options = { colors: false }) {
42
41
  // Counter used for insertion of unnumbered values
@@ -130,18 +129,14 @@ function fmt_raw(str, params, options = { colors: false }) {
130
129
  // Compute radix-point precision on numbers
131
130
  if (param_type == 'number' && $precision) {
132
131
  let [pre, post] = param.split('.');
133
- if (post === undefined) {
134
- post = '';
135
- }
136
132
  let precision = +$precision.substring(1, $precision.length);
137
- if (post.length > precision) {
138
- post = post.substring(0, precision);
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
139
  }
140
- else
141
- while (post.length < precision) {
142
- post = post + '0';
143
- }
144
- param = pre + '.' + post;
145
140
  }
146
141
  let width;
147
142
  if ($width === undefined) {
@@ -215,4 +210,3 @@ function fmt_raw(str, params, options = { colors: false }) {
215
210
  });
216
211
  return str;
217
212
  }
218
- exports.fmt_raw = fmt_raw;
package/lib/print.d.ts CHANGED
@@ -1,5 +1,13 @@
1
- /// <reference types="node" />
2
1
  import { Writable } from 'node:stream';
2
+ /**
3
+ * Create format printer functions with custom output/error streams.
4
+ *
5
+ * @param outStream Output stream (used by print and println - process.stdout by default)
6
+ * @param errStream Error stream (used by eprint and eprintln - process.stderr by default)
7
+ * @param options Options for the printer functions (Whether to color the debug formatting in the output - true by default)
8
+ *
9
+ * @returns an object with print, println, eprint and eprintln functions that print to the specified streams
10
+ */
3
11
  export declare function Printer(outStream?: Writable, errStream?: Writable, options?: {
4
12
  debugColors: boolean;
5
13
  }): {
@@ -34,4 +42,33 @@ export declare function Printer(outStream?: Writable, errStream?: Writable, opti
34
42
  */
35
43
  eprintln: (format_string: string, ...params: any[]) => void;
36
44
  };
37
- export declare const print: (format_string: string, ...params: any[]) => void, println: (format_string: string, ...params: any[]) => void, eprint: (format_string: string, ...params: any[]) => void, eprintln: (format_string: string, ...params: any[]) => void;
45
+ /**
46
+ * Print a format string to process.stdout.
47
+ *
48
+ * @param format_string String used for formatting
49
+ * @param params Parameters to be inserted into the format string
50
+ */
51
+ export declare const print: (format_string: string, ...params: any[]) => void;
52
+ /**
53
+ * Print a format string to process.stdout
54
+ * and append a newline.
55
+ *
56
+ * @param format_string String used for formatting
57
+ * @param params Parameters to be inserted into the format string
58
+ */
59
+ export declare const println: (format_string: string, ...params: any[]) => void;
60
+ /**
61
+ * Print a format string to process.stderr.
62
+ *
63
+ * @param format_string String used for formatting
64
+ * @param params Parameters to be inserted into the format string
65
+ */
66
+ export declare const eprint: (format_string: string, ...params: any[]) => void;
67
+ /**
68
+ * Print a format string to process.stderr
69
+ * and append a newline.
70
+ *
71
+ * @param format_string String used for formatting
72
+ * @param params Parameters to be inserted into the format string
73
+ */
74
+ export declare const eprintln: (format_string: string, ...params: any[]) => void;
package/lib/print.js CHANGED
@@ -2,11 +2,20 @@
2
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
- var _a;
6
5
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.eprintln = exports.eprint = exports.println = exports.print = exports.Printer = void 0;
6
+ exports.eprintln = exports.eprint = exports.println = exports.print = void 0;
7
+ exports.Printer = Printer;
8
8
  const node_process_1 = __importDefault(require("node:process"));
9
9
  const format_1 = require("./format");
10
+ /**
11
+ * Create format printer functions with custom output/error streams.
12
+ *
13
+ * @param outStream Output stream (used by print and println - process.stdout by default)
14
+ * @param errStream Error stream (used by eprint and eprintln - process.stderr by default)
15
+ * @param options Options for the printer functions (Whether to color the debug formatting in the output - true by default)
16
+ *
17
+ * @returns an object with print, println, eprint and eprintln functions that print to the specified streams
18
+ */
10
19
  function Printer(outStream = node_process_1.default.stdout, errStream = node_process_1.default.stderr, options = { debugColors: true }) {
11
20
  return {
12
21
  /**
@@ -49,5 +58,66 @@ function Printer(outStream = node_process_1.default.stdout, errStream = node_pro
49
58
  },
50
59
  };
51
60
  }
52
- exports.Printer = Printer;
53
- _a = Printer(), exports.print = _a.print, exports.println = _a.println, exports.eprint = _a.eprint, exports.eprintln = _a.eprintln;
61
+ // export const {
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();
94
+ /**
95
+ * Print a format string to process.stdout.
96
+ *
97
+ * @param format_string String used for formatting
98
+ * @param params Parameters to be inserted into the format string
99
+ */
100
+ exports.print = default_printer.print;
101
+ /**
102
+ * Print a format string to process.stdout
103
+ * and append a newline.
104
+ *
105
+ * @param format_string String used for formatting
106
+ * @param params Parameters to be inserted into the format string
107
+ */
108
+ exports.println = default_printer.println;
109
+ /**
110
+ * Print a format string to process.stderr.
111
+ *
112
+ * @param format_string String used for formatting
113
+ * @param params Parameters to be inserted into the format string
114
+ */
115
+ exports.eprint = default_printer.eprint;
116
+ /**
117
+ * Print a format string to process.stderr
118
+ * and append a newline.
119
+ *
120
+ * @param format_string String used for formatting
121
+ * @param params Parameters to be inserted into the format string
122
+ */
123
+ exports.eprintln = default_printer.eprintln;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rsformat",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Formatting/printing library for JavaScript that takes after rust's string formatting ",
5
5
  "files": [
6
6
  "lib",
@@ -16,6 +16,10 @@
16
16
  "default": "./lib/*.js"
17
17
  }
18
18
  },
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "test": "echo \"Error: no test specified\" && exit 1"
22
+ },
19
23
  "keywords": [
20
24
  "fmt",
21
25
  "format",
@@ -32,8 +36,5 @@
32
36
  "devDependencies": {
33
37
  "@types/node": "^22.8.6"
34
38
  },
35
- "scripts": {
36
- "build": "tsc",
37
- "test": "echo \"Error: no test specified\" && exit 1"
38
- }
39
+ "packageManager": "pnpm@9.14.2+sha512.6e2baf77d06b9362294152c851c4f278ede37ab1eba3a55fda317a4a17b209f4dbb973fb250a77abc463a341fcb1f17f17cfa24091c4eb319cda0d9b84278387"
39
40
  }