Implement table command to parse tsv, csv, and JSON
This commit is contained in:
4
HELP.md
4
HELP.md
@@ -277,6 +277,10 @@ Destructure the current subject based on the given delimiter.
|
|||||||
If a `limit` is provided, split the subject no more than the given number of times.
|
If a `limit` is provided, split the subject no more than the given number of times.
|
||||||
Example: `foo::bar::baz::ban` -> `split :: 2` -> `[foo, bar, baz::ban]`
|
Example: `foo::bar::baz::ban` -> `split :: 2` -> `[foo, bar, baz::ban]`
|
||||||
|
|
||||||
|
#### `table <csv|tsv|json>`
|
||||||
|
Destructure the current subject into a table from the given format.
|
||||||
|
If `json`, assumes the data is a list of keyed objects (`{[string]: string|number|boolean}[]`).
|
||||||
|
|
||||||
#### `join [<on>]`
|
#### `join [<on>]`
|
||||||
Join the current destructured subject back together using the given delimiter.
|
Join the current destructured subject back together using the given delimiter.
|
||||||
If no delimiter is provided, it will preserve the existing delimiters between substrings.
|
If no delimiter is provided, it will preserve the existing delimiters between substrings.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ syn keyword strKeyword exit paste copy infile outfile assign clear show undo red
|
|||||||
syn keyword strKeyword enclose lower upper lsub rsub prefix suffix quote unquote replace rev trim indent concat
|
syn keyword strKeyword enclose lower upper lsub rsub prefix suffix quote unquote replace rev trim indent concat
|
||||||
syn keyword strKeyword line word each on drop take missing lines words split chunk join sort unique zip flatten group
|
syn keyword strKeyword line word each on drop take missing lines words split chunk join sort unique zip flatten group
|
||||||
syn match strKeyword "\<contains\>"
|
syn match strKeyword "\<contains\>"
|
||||||
syn keyword strKeyword to from set over call lipsum convert if unless while
|
syn keyword strKeyword to from set over call lipsum convert if unless while table
|
||||||
|
|
||||||
" Types
|
" Types
|
||||||
syn match strType "::\s*\zs\(string\|int\|destructured\)"
|
syn match strType "::\s*\zs\(string\|int\|destructured\)"
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fast-csv/parse": "^5.0.7",
|
||||||
"ansis": "^4.2.0",
|
"ansis": "^4.2.0",
|
||||||
"table": "^6.9.0"
|
"table": "^6.9.0"
|
||||||
}
|
}
|
||||||
|
|||||||
495
pnpm-lock.yaml
generated
495
pnpm-lock.yaml
generated
@@ -1,387 +1,232 @@
|
|||||||
lockfileVersion: '9.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
importers:
|
dependencies:
|
||||||
|
'@fast-csv/parse':
|
||||||
|
specifier: ^5.0.7
|
||||||
|
version: 5.0.7
|
||||||
|
ansis:
|
||||||
|
specifier: ^4.2.0
|
||||||
|
version: 4.3.1
|
||||||
|
table:
|
||||||
|
specifier: ^6.9.0
|
||||||
|
version: 6.9.0
|
||||||
|
|
||||||
.:
|
devDependencies:
|
||||||
dependencies:
|
'@types/node':
|
||||||
ansis:
|
specifier: ^22
|
||||||
specifier: ^4.2.0
|
version: 22.19.21
|
||||||
version: 4.2.0
|
rimraf:
|
||||||
table:
|
specifier: ^6.1.0
|
||||||
specifier: ^6.9.0
|
version: 6.1.3
|
||||||
version: 6.9.0
|
typescript:
|
||||||
devDependencies:
|
specifier: ^5.9.3
|
||||||
'@types/node':
|
version: 5.9.3
|
||||||
specifier: ^22
|
|
||||||
version: 22.19.0
|
|
||||||
rimraf:
|
|
||||||
specifier: ^6.1.0
|
|
||||||
version: 6.1.0
|
|
||||||
typescript:
|
|
||||||
specifier: ^5.9.3
|
|
||||||
version: 5.9.3
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
'@isaacs/balanced-match@4.0.1':
|
/@fast-csv/parse@5.0.7:
|
||||||
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
|
resolution: {integrity: sha512-MeuDeQj0DVmIGWky8STaKtvj232Gpq8kjrOGplHJ99Os7OO5CetVfXvUGqX/3GHYFOUsz6FK8isWtDY2XTFNWw==}
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
|
|
||||||
'@isaacs/brace-expansion@5.0.0':
|
|
||||||
resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
|
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
|
|
||||||
'@isaacs/cliui@8.0.2':
|
|
||||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
'@types/node@22.19.0':
|
|
||||||
resolution: {integrity: sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==}
|
|
||||||
|
|
||||||
ajv@8.18.0:
|
|
||||||
resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==}
|
|
||||||
|
|
||||||
ansi-regex@5.0.1:
|
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
ansi-regex@6.2.2:
|
|
||||||
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
ansi-styles@4.3.0:
|
|
||||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
ansi-styles@6.2.3:
|
|
||||||
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
ansis@4.2.0:
|
|
||||||
resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
|
|
||||||
astral-regex@2.0.0:
|
|
||||||
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
color-convert@2.0.1:
|
|
||||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
|
||||||
engines: {node: '>=7.0.0'}
|
|
||||||
|
|
||||||
color-name@1.1.4:
|
|
||||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
|
|
||||||
eastasianwidth@0.2.0:
|
|
||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
|
||||||
|
|
||||||
emoji-regex@8.0.0:
|
|
||||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
|
||||||
|
|
||||||
emoji-regex@9.2.2:
|
|
||||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
|
||||||
|
|
||||||
fast-deep-equal@3.1.3:
|
|
||||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
|
||||||
|
|
||||||
fast-uri@3.1.0:
|
|
||||||
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
|
||||||
|
|
||||||
foreground-child@3.3.1:
|
|
||||||
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
|
|
||||||
glob@11.0.3:
|
|
||||||
resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==}
|
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
is-fullwidth-code-point@3.0.0:
|
|
||||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
isexe@2.0.0:
|
|
||||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
|
||||||
|
|
||||||
jackspeak@4.1.1:
|
|
||||||
resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==}
|
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
|
|
||||||
json-schema-traverse@1.0.0:
|
|
||||||
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
|
|
||||||
|
|
||||||
lodash.truncate@4.4.2:
|
|
||||||
resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==}
|
|
||||||
|
|
||||||
lru-cache@11.2.2:
|
|
||||||
resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==}
|
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
|
|
||||||
minimatch@10.1.1:
|
|
||||||
resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
|
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
|
|
||||||
minipass@7.1.2:
|
|
||||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
|
||||||
|
|
||||||
package-json-from-dist@1.0.1:
|
|
||||||
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
|
|
||||||
|
|
||||||
path-key@3.1.1:
|
|
||||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
path-scurry@2.0.1:
|
|
||||||
resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==}
|
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
|
|
||||||
require-from-string@2.0.2:
|
|
||||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
rimraf@6.1.0:
|
|
||||||
resolution: {integrity: sha512-DxdlA1bdNzkZK7JiNWH+BAx1x4tEJWoTofIopFo6qWUU94jYrFZ0ubY05TqH3nWPJ1nKa1JWVFDINZ3fnrle/A==}
|
|
||||||
engines: {node: 20 || >=22}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
|
||||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
shebang-regex@3.0.0:
|
|
||||||
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
signal-exit@4.1.0:
|
|
||||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
|
|
||||||
slice-ansi@4.0.0:
|
|
||||||
resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
string-width@4.2.3:
|
|
||||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
string-width@5.1.2:
|
|
||||||
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
strip-ansi@6.0.1:
|
|
||||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
strip-ansi@7.1.2:
|
|
||||||
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
table@6.9.0:
|
|
||||||
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
|
|
||||||
typescript@5.9.3:
|
|
||||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
|
||||||
engines: {node: '>=14.17'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
undici-types@6.21.0:
|
|
||||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
|
||||||
|
|
||||||
which@2.0.2:
|
|
||||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
|
||||||
engines: {node: '>= 8'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
|
||||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
|
|
||||||
wrap-ansi@8.1.0:
|
|
||||||
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
|
|
||||||
engines: {node: '>=12'}
|
|
||||||
|
|
||||||
snapshots:
|
|
||||||
|
|
||||||
'@isaacs/balanced-match@4.0.1': {}
|
|
||||||
|
|
||||||
'@isaacs/brace-expansion@5.0.0':
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@isaacs/balanced-match': 4.0.1
|
lodash.escaperegexp: 4.1.2
|
||||||
|
lodash.groupby: 4.6.0
|
||||||
|
lodash.uniq: 4.5.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
'@isaacs/cliui@8.0.2':
|
/@types/node@22.19.21:
|
||||||
dependencies:
|
resolution: {integrity: sha512-VMeFBSCKQKmm2swI2kW51SFusDqekC6q9trBCvJ/JliDchFSuoYYKN7yVNjPthP1HKZcx3U1gI/wTcEBjEFKTA==}
|
||||||
string-width: 5.1.2
|
|
||||||
string-width-cjs: string-width@4.2.3
|
|
||||||
strip-ansi: 7.1.2
|
|
||||||
strip-ansi-cjs: strip-ansi@6.0.1
|
|
||||||
wrap-ansi: 8.1.0
|
|
||||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
|
||||||
|
|
||||||
'@types/node@22.19.0':
|
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.21.0
|
undici-types: 6.21.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
ajv@8.18.0:
|
/ajv@8.20.0:
|
||||||
|
resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-deep-equal: 3.1.3
|
fast-deep-equal: 3.1.3
|
||||||
fast-uri: 3.1.0
|
fast-uri: 3.1.2
|
||||||
json-schema-traverse: 1.0.0
|
json-schema-traverse: 1.0.0
|
||||||
require-from-string: 2.0.2
|
require-from-string: 2.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
ansi-regex@5.0.1: {}
|
/ansi-regex@5.0.1:
|
||||||
|
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
ansi-regex@6.2.2: {}
|
/ansi-styles@4.3.0:
|
||||||
|
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||||
ansi-styles@4.3.0:
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
color-convert: 2.0.1
|
color-convert: 2.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
ansi-styles@6.2.3: {}
|
/ansis@4.3.1:
|
||||||
|
resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
ansis@4.2.0: {}
|
/astral-regex@2.0.0:
|
||||||
|
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
astral-regex@2.0.0: {}
|
/balanced-match@4.0.4:
|
||||||
|
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
|
||||||
|
engines: {node: 18 || 20 || >=22}
|
||||||
|
dev: true
|
||||||
|
|
||||||
color-convert@2.0.1:
|
/brace-expansion@5.0.6:
|
||||||
|
resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==}
|
||||||
|
engines: {node: 18 || 20 || >=22}
|
||||||
|
dependencies:
|
||||||
|
balanced-match: 4.0.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/color-convert@2.0.1:
|
||||||
|
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||||
|
engines: {node: '>=7.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
color-name: 1.1.4
|
color-name: 1.1.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
color-name@1.1.4: {}
|
/color-name@1.1.4:
|
||||||
|
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
/emoji-regex@8.0.0:
|
||||||
|
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/fast-deep-equal@3.1.3:
|
||||||
|
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/fast-uri@3.1.2:
|
||||||
|
resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/glob@13.0.6:
|
||||||
|
resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
|
||||||
|
engines: {node: 18 || 20 || >=22}
|
||||||
dependencies:
|
dependencies:
|
||||||
path-key: 3.1.1
|
minimatch: 10.2.5
|
||||||
shebang-command: 2.0.0
|
minipass: 7.1.3
|
||||||
which: 2.0.2
|
path-scurry: 2.0.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
eastasianwidth@0.2.0: {}
|
/is-fullwidth-code-point@3.0.0:
|
||||||
|
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
emoji-regex@8.0.0: {}
|
/json-schema-traverse@1.0.0:
|
||||||
|
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
emoji-regex@9.2.2: {}
|
/lodash.escaperegexp@4.1.2:
|
||||||
|
resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
fast-deep-equal@3.1.3: {}
|
/lodash.groupby@4.6.0:
|
||||||
|
resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
fast-uri@3.1.0: {}
|
/lodash.truncate@4.4.2:
|
||||||
|
resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
foreground-child@3.3.1:
|
/lodash.uniq@4.5.0:
|
||||||
|
resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lru-cache@11.5.1:
|
||||||
|
resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==}
|
||||||
|
engines: {node: 20 || >=22}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/minimatch@10.2.5:
|
||||||
|
resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==}
|
||||||
|
engines: {node: 18 || 20 || >=22}
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-spawn: 7.0.6
|
brace-expansion: 5.0.6
|
||||||
signal-exit: 4.1.0
|
dev: true
|
||||||
|
|
||||||
glob@11.0.3:
|
/minipass@7.1.3:
|
||||||
|
resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
|
||||||
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/package-json-from-dist@1.0.1:
|
||||||
|
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/path-scurry@2.0.2:
|
||||||
|
resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
|
||||||
|
engines: {node: 18 || 20 || >=22}
|
||||||
dependencies:
|
dependencies:
|
||||||
foreground-child: 3.3.1
|
lru-cache: 11.5.1
|
||||||
jackspeak: 4.1.1
|
minipass: 7.1.3
|
||||||
minimatch: 10.1.1
|
dev: true
|
||||||
minipass: 7.1.2
|
|
||||||
|
/require-from-string@2.0.2:
|
||||||
|
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/rimraf@6.1.3:
|
||||||
|
resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==}
|
||||||
|
engines: {node: 20 || >=22}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
glob: 13.0.6
|
||||||
package-json-from-dist: 1.0.1
|
package-json-from-dist: 1.0.1
|
||||||
path-scurry: 2.0.1
|
dev: true
|
||||||
|
|
||||||
is-fullwidth-code-point@3.0.0: {}
|
/slice-ansi@4.0.0:
|
||||||
|
resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
|
||||||
isexe@2.0.0: {}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
jackspeak@4.1.1:
|
|
||||||
dependencies:
|
|
||||||
'@isaacs/cliui': 8.0.2
|
|
||||||
|
|
||||||
json-schema-traverse@1.0.0: {}
|
|
||||||
|
|
||||||
lodash.truncate@4.4.2: {}
|
|
||||||
|
|
||||||
lru-cache@11.2.2: {}
|
|
||||||
|
|
||||||
minimatch@10.1.1:
|
|
||||||
dependencies:
|
|
||||||
'@isaacs/brace-expansion': 5.0.0
|
|
||||||
|
|
||||||
minipass@7.1.2: {}
|
|
||||||
|
|
||||||
package-json-from-dist@1.0.1: {}
|
|
||||||
|
|
||||||
path-key@3.1.1: {}
|
|
||||||
|
|
||||||
path-scurry@2.0.1:
|
|
||||||
dependencies:
|
|
||||||
lru-cache: 11.2.2
|
|
||||||
minipass: 7.1.2
|
|
||||||
|
|
||||||
require-from-string@2.0.2: {}
|
|
||||||
|
|
||||||
rimraf@6.1.0:
|
|
||||||
dependencies:
|
|
||||||
glob: 11.0.3
|
|
||||||
package-json-from-dist: 1.0.1
|
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
|
||||||
dependencies:
|
|
||||||
shebang-regex: 3.0.0
|
|
||||||
|
|
||||||
shebang-regex@3.0.0: {}
|
|
||||||
|
|
||||||
signal-exit@4.1.0: {}
|
|
||||||
|
|
||||||
slice-ansi@4.0.0:
|
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
astral-regex: 2.0.0
|
astral-regex: 2.0.0
|
||||||
is-fullwidth-code-point: 3.0.0
|
is-fullwidth-code-point: 3.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
string-width@4.2.3:
|
/string-width@4.2.3:
|
||||||
|
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
emoji-regex: 8.0.0
|
emoji-regex: 8.0.0
|
||||||
is-fullwidth-code-point: 3.0.0
|
is-fullwidth-code-point: 3.0.0
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
string-width@5.1.2:
|
/strip-ansi@6.0.1:
|
||||||
dependencies:
|
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||||
eastasianwidth: 0.2.0
|
engines: {node: '>=8'}
|
||||||
emoji-regex: 9.2.2
|
|
||||||
strip-ansi: 7.1.2
|
|
||||||
|
|
||||||
strip-ansi@6.0.1:
|
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex: 5.0.1
|
ansi-regex: 5.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
strip-ansi@7.1.2:
|
/table@6.9.0:
|
||||||
|
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
|
||||||
|
engines: {node: '>=10.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex: 6.2.2
|
ajv: 8.20.0
|
||||||
|
|
||||||
table@6.9.0:
|
|
||||||
dependencies:
|
|
||||||
ajv: 8.18.0
|
|
||||||
lodash.truncate: 4.4.2
|
lodash.truncate: 4.4.2
|
||||||
slice-ansi: 4.0.0
|
slice-ansi: 4.0.0
|
||||||
string-width: 4.2.3
|
string-width: 4.2.3
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
typescript@5.9.3: {}
|
/typescript@5.9.3:
|
||||||
|
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||||
|
engines: {node: '>=14.17'}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
undici-types@6.21.0: {}
|
/undici-types@6.21.0:
|
||||||
|
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||||
which@2.0.2:
|
dev: true
|
||||||
dependencies:
|
|
||||||
isexe: 2.0.0
|
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
|
||||||
dependencies:
|
|
||||||
ansi-styles: 4.3.0
|
|
||||||
string-width: 4.2.3
|
|
||||||
strip-ansi: 6.0.1
|
|
||||||
|
|
||||||
wrap-ansi@8.1.0:
|
|
||||||
dependencies:
|
|
||||||
ansi-styles: 6.2.3
|
|
||||||
string-width: 5.1.2
|
|
||||||
strip-ansi: 7.1.2
|
|
||||||
|
|||||||
@@ -9,3 +9,15 @@ export type ElementType<T extends readonly any[]> = T extends (infer U)[] ? U :
|
|||||||
export function hasOwnProperty<X extends {}, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown> { // eslint-disable-line @typescript-eslint/ban-types
|
export function hasOwnProperty<X extends {}, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown> { // eslint-disable-line @typescript-eslint/ban-types
|
||||||
return Object.hasOwnProperty.call(obj, prop)
|
return Object.hasOwnProperty.call(obj, prop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toKeyValue<T>(obj: Record<string, T>): [string, T][] {
|
||||||
|
const kv: [string, T][] = []
|
||||||
|
for ( const prop of Object.keys(obj) ) {
|
||||||
|
if ( !hasOwnProperty(obj, prop) ) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
kv.push([prop, obj[prop]])
|
||||||
|
}
|
||||||
|
return kv
|
||||||
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import {If} from "./if.js";
|
|||||||
import {Unless} from "./unless.js";
|
import {Unless} from "./unless.js";
|
||||||
import {Convert} from "./convert.js";
|
import {Convert} from "./convert.js";
|
||||||
import {While} from "./while.js";
|
import {While} from "./while.js";
|
||||||
|
import {Table} from "./table.js";
|
||||||
|
|
||||||
export type Commands = Command<CommandData>[]
|
export type Commands = Command<CommandData>[]
|
||||||
export const commands: Commands = [
|
export const commands: Commands = [
|
||||||
@@ -108,6 +109,7 @@ export const commands: Commands = [
|
|||||||
new Sort,
|
new Sort,
|
||||||
new Split,
|
new Split,
|
||||||
new Suffix,
|
new Suffix,
|
||||||
|
new Table,
|
||||||
new Take,
|
new Take,
|
||||||
new To,
|
new To,
|
||||||
new Trim,
|
new Trim,
|
||||||
|
|||||||
114
src/vm/commands/table.ts
Normal file
114
src/vm/commands/table.ts
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import { parseString } from '@fast-csv/parse'
|
||||||
|
import {Command, ParseContext, wrapDestructured, wrapString} from "./command.js";
|
||||||
|
import {LexInput} from "../lexer.js";
|
||||||
|
import {Awaitable, JSONData} from "../../util/types.js";
|
||||||
|
import {ExecutionError, StrVM} from "../vm.js";
|
||||||
|
import {log} from "../../log.js";
|
||||||
|
|
||||||
|
export type TableData = {
|
||||||
|
source: 'json'|'csv'|'tsv',
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseJsonToTable = (json: string): string[][] => {
|
||||||
|
let data: JSONData
|
||||||
|
try {
|
||||||
|
data = JSON.parse(json)
|
||||||
|
} catch (e: unknown) {
|
||||||
|
log.debug('parseJsonToTable', e)
|
||||||
|
throw new ExecutionError('Could not parse: subject is not valid JSON')
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !Array.isArray(data) ) {
|
||||||
|
throw new ExecutionError('Could not parse: JSON must be an array of records')
|
||||||
|
}
|
||||||
|
|
||||||
|
let tableData: string[][] = []
|
||||||
|
let orderedKeys: string[] = []
|
||||||
|
for ( const row of data ) {
|
||||||
|
if (
|
||||||
|
typeof row !== 'object'
|
||||||
|
|| !row
|
||||||
|
|| Array.isArray(row)
|
||||||
|
) {
|
||||||
|
throw new ExecutionError('Could not parse: JSON must be of the type {[string]: string|number|boolean}[]')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add any keys in this row that weren't already present to the end of orderedKeys
|
||||||
|
const missingKeys = Object.keys(row)
|
||||||
|
.filter(k => !orderedKeys.includes(k))
|
||||||
|
|
||||||
|
missingKeys.forEach(k => orderedKeys.push(k))
|
||||||
|
|
||||||
|
// Backfill the missing keys on any existing data
|
||||||
|
for ( const tableRow of tableData ) {
|
||||||
|
for ( const key of missingKeys ) {
|
||||||
|
tableRow.push('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableRow: string[] = []
|
||||||
|
for ( const key of orderedKeys ) {
|
||||||
|
const val = row[key]
|
||||||
|
if ( typeof val === 'object' || typeof val === 'undefined' || typeof val === 'function' || Array.isArray(val) ) {
|
||||||
|
throw new ExecutionError('Could not parse: row values must be string|boolean|number')
|
||||||
|
}
|
||||||
|
|
||||||
|
tableRow.push(val.toString())
|
||||||
|
}
|
||||||
|
tableData.push(tableRow)
|
||||||
|
}
|
||||||
|
return tableData
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseCsvToTable = (csvString: string): Promise<string[][]> =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const rows: string[][] = [];
|
||||||
|
|
||||||
|
parseString(csvString, { headers: false })
|
||||||
|
.on('error', (error) => reject(error))
|
||||||
|
.on('data', (row: string[]) => rows.push(row))
|
||||||
|
.on('end', () => resolve(rows));
|
||||||
|
})
|
||||||
|
|
||||||
|
const parseTsvToTable = (tsvString: string): Promise<string[][]> =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const rows: string[][] = [];
|
||||||
|
|
||||||
|
parseString(tsvString, { headers: false, delimiter: '\t' })
|
||||||
|
.on('error', (error) => reject(error))
|
||||||
|
.on('data', (row: string[]) => rows.push(row))
|
||||||
|
.on('end', () => resolve(rows));
|
||||||
|
})
|
||||||
|
|
||||||
|
export class Table extends Command<TableData> {
|
||||||
|
attemptParse(context: ParseContext): Awaitable<TableData> {
|
||||||
|
return {
|
||||||
|
source: context.popKeywordInSet(['json', 'csv', 'tsv']).value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisplayName(): string {
|
||||||
|
return 'table'
|
||||||
|
}
|
||||||
|
|
||||||
|
isParseCandidate(token: LexInput): boolean {
|
||||||
|
return this.isKeyword(token, 'table')
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute(vm: StrVM, data: TableData): Promise<StrVM> {
|
||||||
|
return vm.replaceContextMatchingTerm({
|
||||||
|
destructure: async val => {
|
||||||
|
const table: string[][] =
|
||||||
|
data.source === 'json' ? parseJsonToTable(val)
|
||||||
|
: data.source === 'csv' ? (await parseCsvToTable(val))
|
||||||
|
: data.source === 'tsv' ? (await parseTsvToTable(val))
|
||||||
|
: (() => { throw new ExecutionError('Unimplemented table source format') })()
|
||||||
|
|
||||||
|
return table.map(row => {
|
||||||
|
const cells = row.map(cellVal => ({ value: wrapString(cellVal) }))
|
||||||
|
return { value: wrapDestructured(cells) }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user