From 8e139a80e1eb954226714de9e75246ba1f4addc9 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 9 Dec 2020 06:27:11 +0300 Subject: [PATCH] added cli progress reporting... Signed-off-by: Alex A. Naanou --- Viewer/features/cli.js | 127 ++++++++++++++++++++++++++------- Viewer/features/sharp.js | 21 +++--- Viewer/features/ui-progress.js | 1 - Viewer/package-lock.json | 73 ++++++++++++++----- Viewer/package.json | 2 + 5 files changed, 172 insertions(+), 52 deletions(-) diff --git a/Viewer/features/cli.js b/Viewer/features/cli.js index c366d021..e11e873a 100755 --- a/Viewer/features/cli.js +++ b/Viewer/features/cli.js @@ -21,6 +21,8 @@ var base = require('features/base') if(typeof(process) != 'undefined'){ var pathlib = requirejs('path') var argv = requirejs('lib/argv') + var progress = requirejs('cli-progress') + var colors = requirejs('colors') } @@ -61,6 +63,8 @@ var CLIActions = actions.Actions({ // XXX should this be here??? // ...move this to progress... + // XXX we are missing some beats, is this because we do not let the + // bar update before closing??? __progress: null, showProgress: ['- System/', function(text, value, max){ @@ -71,38 +75,102 @@ var CLIActions = actions.Actions({ text[0] : text - var state = this.__progress = this.__progress || {} - state = state[text] = state[text] || {} + var settings = this.__progress = this.__progress || {} + var state = settings[text] = settings[text] || {} + + var l = Math.max(text.length, settings.__text_length || 0) + // length changed -> update the bars... + l != settings.__text_length + && Object.entries(settings) + .forEach(function([key, value]){ + value instanceof Object + && 'bar' in value + && value.bar.update({text: key.padEnd(l)}) }) + settings.__text_length = l // normalize max and value... - max = state.max = max != null ? - (typeof(max) == typeof('str') && /[+-][0-9]+/.test(max) ? - (state.max || 0) + parseInt(max) - : max) - : state.max - value = state.value = value != null ? + value = state.value = + value != null ? (typeof(value) == typeof('str') && /[+-][0-9]+/.test(value) ? (state.value || 0) + parseInt(value) - : value) - : state.value + : value) + : state.value + max = state.max = + max != null ? + (typeof(max) == typeof('str') && /[+-][0-9]+/.test(max) ? + (state.max || 0) + parseInt(max) + : max) + : state.max - // format the message... - msg = msg ? ': '+msg : '' - msg = ' '+ msg - //+ (value && value >= (max || 0) ? ' ('+value+' done)' - + (value && value >= (max || 0) ? - ' (done)' - : value && max && value != max ? - ' ('+ value +' of '+ max +')' - : '...') + var container = settings.__multi_bar = + settings.__multi_bar + || new progress.MultiBar({ + // XXX make this simpler... + format: '{text} {bar} {percentage}% ' + +'| ETA: {eta_formatted} | {value}/{total}', + autopadding: true, + }, + progress.Presets.rect) + var bar = state.bar = + state.bar || container.create(0, 0, {text: text.padEnd(l)}) - // XXX do a better printout -- ncurses??? - msg != state.msg - && console.log(text + msg) - - state.msg = msg + bar.setTotal(Math.max(max, value)) + bar.update(value) }], + // handle logger progress... + // XXX this is a copy from ui-progress -- need to reuse... + handleLogItem: ['- System/', + function(logger, path, status, ...rest){ + var msg = path.join(': ') + var l = (rest.length == 1 && rest[0] instanceof Array) ? + rest[0].length + : rest.length + + // only pass the relevant stuff... + var attrs = {} + logger.ondone + && (attrs.ondone = logger.ondone) + logger.onclose + && (attrs.onclose = logger.onclose) + + // get keywords... + var {add, done, skip, reset, close, error} = + this.config['progress-logger-keywords'] + || {} + // setup default aliases... + add = new Set([...(add || []), 'added']) + done = new Set([...(done || [])]) + skip = new Set([...(skip || []), 'skipped']) + reset = new Set([...(reset || [])]) + close = new Set([...(close || []), 'closed']) + error = new Set([...(error || [])]) + + // close... + if(status == 'close' || close.has(status)){ + //this.showProgress(path, 'close') + // reset... + } else if(status == 'reset' || reset.has(status)){ + //this.showProgress(path, 'reset') + // added new item -- increase max... + // XXX show msg in the progress bar??? + } else if(status == 'add' || add.has(status)){ + this.showProgress(path, '+0', '+'+l) + // resolved item -- increase done... + } else if(status == 'done' || done.has(status)){ + this.showProgress(path, '+'+l) + // skipped item -- increase done... + // XXX should we instead decrease max here??? + // ...if not this is the same as done -- merge... + } else if(status == 'skip' || skip.has(status)){ + this.showProgress(path, '+'+l) + // error... + // XXX STUB... + } else if(status == 'error' || error.has(status)){ + this.showProgress(['Error'].concat(msg), '+0', '+'+l) } + }], + + startREPL: ['- System/Start CLI interpreter', {cli: '@repl'}, @@ -142,6 +210,10 @@ var CLIActions = actions.Actions({ // XXX }], + // XXX metadata caching and preview creation are not in sync, can + // this be a problem??? + // ...if not, add a note... + // XXX should we support creating multiple indexes at the same time??? // XXX this is reletively generic, might be useful globally... // XXX add support for cwd and relative paths... // XXX should we use a clean index or do this in-place??? @@ -156,7 +228,7 @@ var CLIActions = actions.Actions({ path = util.normalizePath(path) // XXX should we use a clean index or do this in-place??? - //var index = this.constructor() + //var index = this.constructor(..) var index = this return index.loadImages(path) // save base index... @@ -166,7 +238,8 @@ var CLIActions = actions.Actions({ .then(function(){ if(index.makePreviews){ return Promise.all([ - index.cacheMetadata('all'), + // NOTE: this is already running after .loadImages(..) + //index.cacheMetadata('all'), index.makePreviews('all') ])} }) .then(function(){ return index @@ -216,7 +289,7 @@ module.CLI = core.ImageGridFeatures.Feature({ license: pkg.license, '-verbose': { - doc: 'Enable verbose output', + doc: 'Enable verbose (very) output', handler: function(){ that.logger && (that.logger.quiet = false) } }, diff --git a/Viewer/features/sharp.js b/Viewer/features/sharp.js index 8cdf1ce2..1f6a6de8 100755 --- a/Viewer/features/sharp.js +++ b/Viewer/features/sharp.js @@ -490,14 +490,19 @@ var SharpActions = actions.Actions({ : logger, }) // XXX handle errors -- rejected because image exists... - .then(function(res){ - // update metadata... - if(!base_path){ - var preview = img.preview = img.preview || {} - preview[parseInt(size) + 'px'] = name - that.markChanged - && that.markChanged('images', [gid]) } - return [gid, size, name] }) })) })], + .then( + function(res){ + // update metadata... + if(!base_path){ + var preview = img.preview = img.preview || {} + preview[parseInt(size) + 'px'] = name + that.markChanged + && that.markChanged('images', [gid]) } + return [gid, size, name] }, + function(err){ + // XXX error + logger && logger.emit('skipped', gid) + }) })) })], // XXX add support for offloading the processing to a thread/worker... // XXX revise logging and logger passing... diff --git a/Viewer/features/ui-progress.js b/Viewer/features/ui-progress.js index dfc7c8b1..98369ab0 100755 --- a/Viewer/features/ui-progress.js +++ b/Viewer/features/ui-progress.js @@ -303,7 +303,6 @@ var ProgressActions = actions.Actions({ this.config['progress-done-delay'] || 1000))) } }], // handle logger progress... - // XXX show progress after a timeout if still not finished... handleLogItem: ['- System/', function(logger, path, status, ...rest){ var msg = path.join(': ') diff --git a/Viewer/package-lock.json b/Viewer/package-lock.json index abc89e71..fb4e66b2 100755 --- a/Viewer/package-lock.json +++ b/Viewer/package-lock.json @@ -368,6 +368,50 @@ "restore-cursor": "^2.0.0" } }, + "cli-progress": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.8.2.tgz", + "integrity": "sha512-qRwBxLldMSfxB+YGFgNRaj5vyyHe1yMpVeDL79c+7puGujdKJHQHydgqXDcrkvQgJ5U/d3lpf6vffSoVVUftVQ==", + "requires": { + "colors": "^1.1.2", + "string-width": "^4.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "cli-spinners": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz", @@ -446,12 +490,12 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", - "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", "requires": { "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "color-string": "^1.5.4" } }, "color-convert": { @@ -468,9 +512,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", + "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -479,8 +523,7 @@ "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "combined-stream": { "version": "1.0.8", @@ -1144,6 +1187,11 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -2085,13 +2133,6 @@ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - } } }, "source-map": { diff --git a/Viewer/package.json b/Viewer/package.json index 5a8db603..d34d539b 100755 --- a/Viewer/package.json +++ b/Viewer/package.json @@ -20,6 +20,8 @@ "dependencies": { "app-module-path": "^1.0.6", "async-json": "0.0.2", + "cli-progress": "^3.8.2", + "colors": "^1.4.0", "electron": "^9.3.5", "exif-reader": "^1.0.3", "exiftool": "^0.0.3",