diff --git a/package-lock.json b/package-lock.json index c7ca35d..d04dc6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -328,6 +328,11 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, + "spawn-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spawn-stream/-/spawn-stream-1.0.2.tgz", + "integrity": "sha1-W9VkENXISo7N6y5jEnEWytkQUMs=" + }, "string-to-arraybuffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-to-arraybuffer/-/string-to-arraybuffer-1.0.2.tgz", diff --git a/package.json b/package.json index fac7883..d97b5a3 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "chroma-js": "^2.1.0", "image-encode": "^1.3.0", "nexline": "^1.2.1", + "spawn-stream": "^1.0.2", "terrain50": "^1.8.2" }, "bin": { diff --git a/src/Subcommands/split/index.mjs b/src/Subcommands/split/index.mjs new file mode 100644 index 0000000..15f8ffe --- /dev/null +++ b/src/Subcommands/split/index.mjs @@ -0,0 +1,65 @@ +"use strict"; + +import fs from 'fs'; +import path from 'path'; + +import Terrain50 from 'terrain50'; +import SpawnStream from 'spawn-stream'; + +import a from '../../Helpers/Ansi.mjs'; +import l from '../../Helpers/Log.mjs'; + +export default async function(settings) { + // 1: Parse settings + let stream_in = process.stdin; + if(settings.cli.input !== "-") { + l.log(`Reading from ${a.hicol}${settings.cli.input}${a.reset}`); + stream_in = fs.createReadStream(settings.cli.input); + } + else + l.log(`Reading from stdin`); + + if(typeof settings.cli.output != "string") { + l.error(`Error: No output directory specified (try the --output argument).`); + } + + let dir_out = settings.cli.output; + if(!fs.existsSync(dir_out)) + await fs.promises.mkdir(dir_out, { recursive: true, mode: 0o750 }); + l.log(`Writing to ${a.hicol}${settings.cli.output}${a.reset}`); + + // ------------------------------------------------------------------------ + + let i = 0; + for await(let next of Terrain50.ParseStream(stream_in)) { + // Determine the output filepath + let output_filename = `${i}.asc`; + if(!settings.cli.no_gzip) output_filename += `.gz`; + output_filename = path.join(dir_out, output_filename); + + // Create the output stream + let stream_out = fs.createWriteStream(output_filename), + stream_gzip = null; + if(!settings.cli.no_gzip) { + stream_gzip = SpawnStream("gzip"); + stream_gzip.pipe(stream_out); + } + + + // Write it to the output + await next.serialise(stream_gzip || stream_out, true); + + // Update the user + l.log(`Written ${i+1} objects so far`); + + if(i >= settings.cli.count - 1) { + l.log(`Reached limit of ${settings.cli.count} items, stopping here`); + break; + } + + i++; + } + l.log(`Splitting complete`); + + stream_in.destroy(); +} diff --git a/src/Subcommands/split/meta.toml b/src/Subcommands/split/meta.toml new file mode 100644 index 0000000..366817d --- /dev/null +++ b/src/Subcommands/split/meta.toml @@ -0,0 +1,26 @@ +description = "Split a single stream of Terrain50 objects into seprate files" + +[[arguments]] +name = "input" +description = "The input Terrain50 file (default: stdin)" +default_value = "-" +type = "string" + +[[arguments]] +name = "output" +description = "The output directory to write to" +# default_value = "" +type = "string" + +[[arguments]] +name = "no-gzip" +description = "Don't automatically gzip the output streams" +default_value = false +type = "boolean" + + +[[arguments]] +name = "count" +description = "The number of objects to extract (default: Infinity)" +default_value = inf # inf = Infinity +type = "integer"