experimenting...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2021-06-23 15:43:46 +03:00
parent 78136895a0
commit 04b703309e
2 changed files with 175 additions and 13 deletions

186
diff2.js
View File

@ -7,6 +7,7 @@
(function(require){ var module={} // make module AMD/node compatible... (function(require){ var module={} // make module AMD/node compatible...
/*********************************************************************/ /*********************************************************************/
var object = require('ig-object')
var types = require('ig-types') var types = require('ig-types')
@ -275,6 +276,19 @@ module.HANDLERS = {
//false: { match: false }, //false: { match: false },
} }
var HANDLE_DEFAULTS =
module.HANDLE_DEFAULTS = {
flat: true,
flatPaths: true,
// handlers: <object>,
// seen: <map>
// no<handler-name>: true | false,
}
// //
// handle(obj[,options]) // handle(obj[,options])
// handle(obj, path[,options]) // handle(obj, path[,options])
@ -302,9 +316,17 @@ var handle =
module.handle = module.handle =
function*(obj, path=[], options={}){ function*(obj, path=[], options={}){
// parse args... // parse args...
options = typeof(path) == 'object' && !(path instanceof Array) ? options =
path typeof(path) == 'object' && !(path instanceof Array) ?
: options path
: options
options =
// inherit options from HANDLE_DEFAULTS of we don't already...
!object.parentOf(module.HANDLE_DEFAULTS, options) ?
Object.assign(
{ __proto__: module.HANDLE_DEFAULTS },
options)
: options
path = path instanceof Array ? path = path instanceof Array ?
path path
: typeof(path) == 'string' ? : typeof(path) == 'string' ?
@ -330,35 +352,149 @@ function*(obj, path=[], options={}){
: [p, v]) } : [p, v]) }
// handle the object... // handle the object...
var res = [path, ]
var handlers = options.handlers || module.HANDLERS var handlers = options.handlers || module.HANDLERS
var res = [path]
yield* Object.entries(handlers) yield* Object.entries(handlers)
.iter() .iter()
.filter(function([_, handler]){ .filter(function([name, handler]){
return !!handler.handle }) return handler.handle
// skip options.no<handler-name>...
&& !options['no'+ name.capitalize()] })
.map(function*([name, handler]){ .map(function*([name, handler]){
// skip...
if(!!options['no'+ name.capitalize()]){
return }
// expand aliases... // expand aliases...
var h = handler var h = handler
while(h && typeof(h.handle) == 'string'){ while(h && typeof(h.handle) == 'string'){
h = handlers[h.handle] } h = handlers[h.handle] }
// XXX should .handle(..) be called in the context of h or handler??? // XXX should .handle(..) be called in the context of h or handler???
res = h.handle.call(handler, obj, res, next, stop, options) res = h.handle.call(handler, obj, res, next, stop, options)
// non-flat mode...
!options.flat
&& _next.length > 0
// XXX need to get the parent result to add .children to...
&& console.log('!!!!!!!!!!!!!!')
//&& parent.children.concat([...doNext()])
yield res yield res
&& [path, res] }) && [path, res] })
// clean out remains of handlers that rejected the obj... // clean out remains of handlers that rejected the obj...
.filter(function(e){ .filter(function(e){
return !!e }) return !!e })
// handle the next stuff... // handle the next stuff...
yield* _next yield* _next
.iter() .iter()
.map(function*([k, v]){ .map(function*([k, v]){
yield* handle(v, path.concat(k), options) }) } yield* handle(v, path.concat(k), options) }) }
var WALK_HANDLERS = {
map: {
walk: function(obj){
return obj instanceof Map
&& obj.entries() } },
set: {
walk: function(obj){
return obj instanceof Set
&& obj.values() } },
attrs: {
walk: function(obj){
return typeof(obj) == 'object'
&& Object.entries(obj) } },
text: {
walk: function(obj){
return typeof(obj) == 'string'
&& obj.includes('\n')
&& obj.split(/\n/g) } },
}
//
// walk(<handler>[, <options>])
// walk(<handler>, <path>[, <options>])
// -> <walker>
//
// <handler>(<obj>, <path>, <next>, <type>)
// -> <value>
// !> STOP(<value>)
//
// <walker>(<obj>)
// <walker>(<obj>, <path>)
// -> <generator>
// -> <value>
//
//
// XXX the idea here is to try to decouple the walk from the format and
// move the formatters and other stuff out...
// ...not sure if this is simpler yet...
var walk =
module.walk =
function(handler, path=[], options={}){
// parse args...
options =
typeof(path) == 'object' && !(path instanceof Array) ?
path
: options
options =
// inherit options from HANDLE_DEFAULTS of we don't already...
!object.parentOf(module.HANDLE_DEFAULTS, options) ?
Object.assign(
{ __proto__: module.HANDLE_DEFAULTS },
options)
: options
var _walk = function*(obj, path=path, type=undefined){
path = path instanceof Array ?
path
: typeof(path) == 'string' ?
str2path(path)
: []
type = type || 'root'
var handlers = options.handlers || module.HANDLERS
// format:
// [
// [<handler-name>, [ [<key>, <value>], .. ]],
// ..
// ]
var next = Object.entries(handlers)
.filter(function([n, h]){
return h.walk
&& !options['no' + n.capitalize()] })
.map(function([n, h]){
// XXX should we call the handler(..) once per set of
// next values (i.e. attrs, items, ...)???
var res = h.walk.call(obj)
return res
&& [n, res] })
.filter(function(e){
return !!e })
try {
// main object...
if(handler instanceof types.Generator){
yield* handler(obj, path, next, type)
} else {
yield handler(obj, path, next, type) }
// next/children...
yield* next
.iter()
.map(function*([type, items]){
yield* items
.iter()
.map(function([key, value]){
yield* _walk(value, path.concat(key), type) }) })
// handle STOP...
} catch(err){
if(err === module.STOP){
return
} else if(err instanceof module.STOP){
yield err.value
return }
throw err } }
return _walk }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
@ -389,6 +525,8 @@ var path2str =
module.path2str = module.path2str =
function(p){ function(p){
return '/'+ p return '/'+ p
// flatten lispPaths...
.flat(Infinity)
.map(serializePathElem) .map(serializePathElem)
.reduce(function(res, e){ .reduce(function(res, e){
e = e === module.CONTENT ? e = e === module.CONTENT ?
@ -420,6 +558,7 @@ var deserializePathElem = function(p){
// XXX PROBLEM: need to be able to reference '' in {'': 123}, i.e, how do // XXX PROBLEM: need to be able to reference '' in {'': 123}, i.e, how do
// we stringify ['']??? // we stringify ['']???
// [''] => ??? // [''] => ???
// XXX add support for options.lispPaths
var str2path = var str2path =
module.str2path = module.str2path =
function(str){ function(str){
@ -754,7 +893,7 @@ function(A, B, cmp){
// 2) selectively match keys... // 2) selectively match keys...
// ...need to test how complex this will be... // ...need to test how complex this will be...
// //
var diff = var keyValueDiff =
function(A, B){ function(A, B){
return diffSections( return diffSections(
[...handle(A) [...handle(A)
@ -770,6 +909,26 @@ function(A, B){
&& av.type && av.type
&& av.type == bv.type )) }) } && av.type == bv.type )) }) }
// XXX this completely ignores the path/key...
// XXX this works great for arrays but is questionable on other stuff...
var valueDiff =
function(A, B){
return diffSections(
[...handle(A)
.chain(serializePaths)],
[...handle(B)
.chain(serializePaths)],
// XXX add link support...
function([ap, av], [bp, bv]){
return av == bv
|| (typeof(av) == 'object'
&& typeof(bv) == 'object'
&& av.type
&& av.type == bv.type ) }) }
var diff = valueDiff
//--------------------------------------------------------------------- //---------------------------------------------------------------------
@ -857,7 +1016,7 @@ console.log([
)]) )])
// use spec to create a new object... /*/ use spec to create a new object...
console.log('\n\n---\n', console.log('\n\n---\n',
[...handle(write(null, handle(o))) [...handle(write(null, handle(o)))
.chain( .chain(
@ -865,6 +1024,7 @@ console.log('\n\n---\n',
// make the output a bit more compact... // make the output a bit more compact...
stripAttr('source'), stripAttr('source'),
)]) )])
//*/
/* XXX /* XXX
@ -886,10 +1046,12 @@ console.log([...handle(B).chain(serializePaths)])
console.log(diff(B, A)) console.log(diff(B, A))
//*/ //*/
/*
console.log(JSON.stringify(diff( console.log(JSON.stringify(diff(
[1,4,2,3], [1,4,2,3],
[1,2,3], [1,2,3],
), null, ' ')) ), null, ' '))
//*/

View File

@ -25,7 +25,7 @@
"homepage": "https://github.com/flynx/object-diff.js#readme", "homepage": "https://github.com/flynx/object-diff.js#readme",
"dependencies": { "dependencies": {
"generic-walk": "^1.4.0", "generic-walk": "^1.4.0",
"ig-object": "^2.2.0", "ig-object": "*",
"ig-types": "*" "ig-types": "*"
}, },
"devDependencies": { "devDependencies": {