mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-11-04 04:50:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			147 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
/**********************************************************************
 | 
						|
* 
 | 
						|
*
 | 
						|
*
 | 
						|
**********************************************/  /* c8 ignore next 2 */
 | 
						|
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
 | 
						|
(function(require){ var module={} // make module AMD/node compatible...
 | 
						|
/*********************************************************************/
 | 
						|
 | 
						|
var object = require('ig-object')
 | 
						|
var stoppable = require('ig-stoppable')
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************/
 | 
						|
 | 
						|
// Wrap .map(..) / .filter(..) / .reduce(..) / .. to support STOP...
 | 
						|
// 
 | 
						|
// NOTE: internally these are implemented as for-of loops (./generator.js)
 | 
						|
var stoppableSet = function(iter){
 | 
						|
	return function(func){
 | 
						|
		return new Set([...this][iter](...arguments)) } }
 | 
						|
var stoppableValue = function(iter, no_return=false){
 | 
						|
	return function(func){
 | 
						|
		var res = [...this][iter](...arguments) 
 | 
						|
		return no_return ?
 | 
						|
			undefined
 | 
						|
			: res } }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//---------------------------------------------------------------------
 | 
						|
 | 
						|
var SetProtoMixin =
 | 
						|
module.SetProtoMixin =
 | 
						|
object.Mixin('SetMixin', 'soft', {
 | 
						|
	iter: function*(){
 | 
						|
		for(var e of this){
 | 
						|
			yield e } },
 | 
						|
 | 
						|
	// Set set operation shorthands...
 | 
						|
	unite: function(other=[]){ 
 | 
						|
		return new Set([...this, ...other]) },
 | 
						|
	intersect: function(other){
 | 
						|
		var test = other.has ?  
 | 
						|
			'has' 
 | 
						|
			: 'includes'
 | 
						|
		return new Set([...this]
 | 
						|
			.filter(function(e){ 
 | 
						|
				return other[test](e) })) },
 | 
						|
	subtract: function(other=[]){
 | 
						|
		other = new Set(other)
 | 
						|
		return new Set([...this]
 | 
						|
			.filter(function(e){ 
 | 
						|
				return !other.has(e) })) },
 | 
						|
 | 
						|
	sort: function(values=[]){
 | 
						|
		values = (typeof(values) == 'function' 
 | 
						|
				|| values === undefined) ?
 | 
						|
			[...this].sort(values)
 | 
						|
			: values
 | 
						|
		var del = this.delete.bind(this)
 | 
						|
		var add = this.add.bind(this)
 | 
						|
		new Set([...values, ...this])
 | 
						|
			.forEach(function(e){
 | 
						|
				if(this.has(e)){
 | 
						|
					del(e)
 | 
						|
					add(e) } }.bind(this))
 | 
						|
		return this },
 | 
						|
 | 
						|
	replace: function(old, value, ordered=true){
 | 
						|
		// nothing to do...
 | 
						|
		if(!this.has(old) || old === value){
 | 
						|
			return this }
 | 
						|
		if(ordered){
 | 
						|
			var order = [...this]
 | 
						|
			// XXX is this fast enough???
 | 
						|
			order[order.lastIndexOf(old)] = value }
 | 
						|
		// replace...
 | 
						|
		this.delete(old)
 | 
						|
		this.add(value)
 | 
						|
		ordered
 | 
						|
			&& this.sort(order)
 | 
						|
		return this },
 | 
						|
	// NOTE: if index is <0 then the value is prepended to the set, if 
 | 
						|
	// 		it's >=this.size then the value will be appended.
 | 
						|
	// 		if ordered is set to false in both cases the value is appended.
 | 
						|
	// XXX should this be implemented via .splice(..) ???
 | 
						|
	replaceAt: function(index, value, ordered=true){
 | 
						|
		// append...
 | 
						|
		if(index >= this.size){
 | 
						|
			this.add(value)
 | 
						|
			return this }
 | 
						|
		// prepend...
 | 
						|
		if(index < 0){
 | 
						|
			index = 0
 | 
						|
			var order = [, ...this]
 | 
						|
		// replace...
 | 
						|
		} else {
 | 
						|
			var order = [...this]
 | 
						|
			var old = order[index] 
 | 
						|
			// nothing to do...
 | 
						|
			if(old === value){
 | 
						|
				return this } }
 | 
						|
		ordered
 | 
						|
			&& (order[index] = value)
 | 
						|
 | 
						|
		// replace...
 | 
						|
		this.has(old)
 | 
						|
			&& this.delete(old)
 | 
						|
		this.add(value)
 | 
						|
 | 
						|
		ordered
 | 
						|
			&& this.sort(order)
 | 
						|
		return this },
 | 
						|
 | 
						|
	// XXX do we need this???
 | 
						|
	// 		...should this be enough???
 | 
						|
	// 			new Set([...set].splice(..))
 | 
						|
	splice: function(from, count, ...items){
 | 
						|
		var that = this
 | 
						|
		var order = [...this]
 | 
						|
		var removed = order.splice(...arguments)
 | 
						|
 | 
						|
		// update the set...
 | 
						|
		removed.forEach(this.delete.bind(this))
 | 
						|
		items.forEach(this.add.bind(this))
 | 
						|
		this.sort(order) 
 | 
						|
 | 
						|
		return removed },
 | 
						|
 | 
						|
	filter: stoppableSet('filter'),
 | 
						|
	map: stoppableSet('map'),
 | 
						|
	reduce: stoppableValue('reduce'),
 | 
						|
	reduceRight: stoppableValue('reduceRight'),
 | 
						|
	forEach: stoppableValue('map', true),
 | 
						|
})
 | 
						|
 | 
						|
 | 
						|
SetProtoMixin(Set.prototype)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
* vim:set ts=4 sw=4 :                               */ return module })
 |