added cli progress reporting...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2020-12-09 06:27:11 +03:00
parent 040f3a7e3a
commit 8e139a80e1
5 changed files with 172 additions and 52 deletions

View File

@ -21,6 +21,8 @@ var base = require('features/base')
if(typeof(process) != 'undefined'){ if(typeof(process) != 'undefined'){
var pathlib = requirejs('path') var pathlib = requirejs('path')
var argv = requirejs('lib/argv') 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??? // XXX should this be here???
// ...move this to progress... // ...move this to progress...
// XXX we are missing some beats, is this because we do not let the
// bar update before closing???
__progress: null, __progress: null,
showProgress: ['- System/', showProgress: ['- System/',
function(text, value, max){ function(text, value, max){
@ -71,38 +75,102 @@ var CLIActions = actions.Actions({
text[0] text[0]
: text : text
var state = this.__progress = this.__progress || {} var settings = this.__progress = this.__progress || {}
state = state[text] = state[text] || {} 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... // normalize max and value...
max = state.max = max != null ? value = state.value =
(typeof(max) == typeof('str') && /[+-][0-9]+/.test(max) ? value != null ?
(state.max || 0) + parseInt(max)
: max)
: state.max
value = state.value = value != null ?
(typeof(value) == typeof('str') && /[+-][0-9]+/.test(value) ? (typeof(value) == typeof('str') && /[+-][0-9]+/.test(value) ?
(state.value || 0) + parseInt(value) (state.value || 0) + parseInt(value)
: value) : value)
: state.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... var container = settings.__multi_bar =
msg = msg ? ': '+msg : '' settings.__multi_bar
msg = ' '+ msg || new progress.MultiBar({
//+ (value && value >= (max || 0) ? ' ('+value+' done)' // XXX make this simpler...
+ (value && value >= (max || 0) ? format: '{text} {bar} {percentage}% '
' (done)' +'| ETA: {eta_formatted} | {value}/{total}',
: value && max && value != max ? autopadding: true,
' ('+ value +' of '+ max +')' },
: '...') progress.Presets.rect)
var bar = state.bar =
state.bar || container.create(0, 0, {text: text.padEnd(l)})
// XXX do a better printout -- ncurses??? bar.setTotal(Math.max(max, value))
msg != state.msg bar.update(value)
&& console.log(text + msg)
state.msg = msg
}], }],
// 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', startREPL: ['- System/Start CLI interpreter',
{cli: '@repl'}, {cli: '@repl'},
@ -142,6 +210,10 @@ var CLIActions = actions.Actions({
// XXX // 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 this is reletively generic, might be useful globally...
// XXX add support for cwd and relative paths... // XXX add support for cwd and relative paths...
// XXX should we use a clean index or do this in-place??? // XXX should we use a clean index or do this in-place???
@ -156,7 +228,7 @@ var CLIActions = actions.Actions({
path = util.normalizePath(path) path = util.normalizePath(path)
// XXX should we use a clean index or do this in-place??? // XXX should we use a clean index or do this in-place???
//var index = this.constructor() //var index = this.constructor(..)
var index = this var index = this
return index.loadImages(path) return index.loadImages(path)
// save base index... // save base index...
@ -166,7 +238,8 @@ var CLIActions = actions.Actions({
.then(function(){ .then(function(){
if(index.makePreviews){ if(index.makePreviews){
return Promise.all([ return Promise.all([
index.cacheMetadata('all'), // NOTE: this is already running after .loadImages(..)
//index.cacheMetadata('all'),
index.makePreviews('all') ])} }) index.makePreviews('all') ])} })
.then(function(){ .then(function(){
return index return index
@ -216,7 +289,7 @@ module.CLI = core.ImageGridFeatures.Feature({
license: pkg.license, license: pkg.license,
'-verbose': { '-verbose': {
doc: 'Enable verbose output', doc: 'Enable verbose (very) output',
handler: function(){ handler: function(){
that.logger that.logger
&& (that.logger.quiet = false) } }, && (that.logger.quiet = false) } },

View File

@ -490,14 +490,19 @@ var SharpActions = actions.Actions({
: logger, : logger,
}) })
// XXX handle errors -- rejected because image exists... // XXX handle errors -- rejected because image exists...
.then(function(res){ .then(
function(res){
// update metadata... // update metadata...
if(!base_path){ if(!base_path){
var preview = img.preview = img.preview || {} var preview = img.preview = img.preview || {}
preview[parseInt(size) + 'px'] = name preview[parseInt(size) + 'px'] = name
that.markChanged that.markChanged
&& that.markChanged('images', [gid]) } && that.markChanged('images', [gid]) }
return [gid, size, name] }) })) })], 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 add support for offloading the processing to a thread/worker...
// XXX revise logging and logger passing... // XXX revise logging and logger passing...

View File

@ -303,7 +303,6 @@ var ProgressActions = actions.Actions({
this.config['progress-done-delay'] || 1000))) } }], this.config['progress-done-delay'] || 1000))) } }],
// handle logger progress... // handle logger progress...
// XXX show progress after a timeout if still not finished...
handleLogItem: ['- System/', handleLogItem: ['- System/',
function(logger, path, status, ...rest){ function(logger, path, status, ...rest){
var msg = path.join(': ') var msg = path.join(': ')

View File

@ -368,6 +368,50 @@
"restore-cursor": "^2.0.0" "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": { "cli-spinners": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz",
@ -446,12 +490,12 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
}, },
"color": { "color": {
"version": "3.1.2", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
"integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
"requires": { "requires": {
"color-convert": "^1.9.1", "color-convert": "^1.9.1",
"color-string": "^1.5.2" "color-string": "^1.5.4"
} }
}, },
"color-convert": { "color-convert": {
@ -468,9 +512,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
}, },
"color-string": { "color-string": {
"version": "1.5.3", "version": "1.5.4",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==",
"requires": { "requires": {
"color-name": "^1.0.0", "color-name": "^1.0.0",
"simple-swizzle": "^0.2.2" "simple-swizzle": "^0.2.2"
@ -479,8 +523,7 @@
"colors": { "colors": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
"dev": true
}, },
"combined-stream": { "combined-stream": {
"version": "1.0.8", "version": "1.0.8",
@ -1144,6 +1187,11 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" "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": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "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=", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"requires": { "requires": {
"is-arrayish": "^0.3.1" "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": { "source-map": {

View File

@ -20,6 +20,8 @@
"dependencies": { "dependencies": {
"app-module-path": "^1.0.6", "app-module-path": "^1.0.6",
"async-json": "0.0.2", "async-json": "0.0.2",
"cli-progress": "^3.8.2",
"colors": "^1.4.0",
"electron": "^9.3.5", "electron": "^9.3.5",
"exif-reader": "^1.0.3", "exif-reader": "^1.0.3",
"exiftool": "^0.0.3", "exiftool": "^0.0.3",