<commit_before>/**
 * PopupToolGroup is an abstract base class used by both {@link OO.ui.MenuToolGroup MenuToolGroup}
 * and {@link OO.ui.ListToolGroup ListToolGroup} to provide a popup--an overlaid menu or list of tools with an
 * optional icon and label. This class can be used for other base classes that also use this functionality.
 *
 * @abstract
 * @class
 * @extends OO.ui.ToolGroup
 * @mixins OO.ui.mixin.IconElement
 * @mixins OO.ui.mixin.IndicatorElement
 * @mixins OO.ui.mixin.LabelElement
 * @mixins OO.ui.mixin.TitledElement
 * @mixins OO.ui.mixin.FlaggedElement
 * @mixins OO.ui.mixin.ClippableElement
 * @mixins OO.ui.mixin.TabIndexedElement
 *
 * @constructor
 * @param {OO.ui.Toolbar} toolbar
 * @param {Object} [config] Configuration options
 * @cfg {string} [header] Text to display at the top of the popup
 */
OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
	// Allow passing positional parameters inside the config object
	if ( OO.isPlainObject( toolbar ) && config === undefined ) {
		config = toolbar;
		toolbar = config.toolbar;
	}

	// Configuration initialization
	config = $.extend( {
		indicator: config.indicator === undefined ? ( toolbar.position === 'bottom' ? 'up' : 'down' ) : config.indicator
	}, config );

	// Parent constructor
	OO.ui.PopupToolGroup.parent.call( this, toolbar, config );

	// Properties
	this.active = false;
	this.dragging = false;
	this.onBlurHandler = this.onBlur.bind( this );
	this.$handle = $( '<span>' );

	// Mixin constructors
	OO.ui.mixin.IconElement.call( this, config );
	OO.ui.mixin.IndicatorElement.call( this, config );
	OO.ui.mixin.LabelElement.call( this, config );
	OO.ui.mixin.TitledElement.call( this, config );
	OO.ui.mixin.FlaggedElement.call( this, config );
	OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );
	OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) );

	// Events
	this.$handle.on( {
		keydown: this.onHandleMouseKeyDown.bind( this ),
		keyup: this.onHandleMouseKeyUp.bind( this ),
		mousedown: this.onHandleMouseKeyDown.bind( this ),
		mouseup: this.onHandleMouseKeyUp.bind( this )
	} );

	// Initialization
	this.$handle
		.addClass( 'oo-ui-popupToolGroup-handle' )
		.attr( 'role', 'button' )
		.append( this.$icon, this.$label, this.$indicator );
	// If the pop-up should have a header, add it to the top of the toolGroup.
	// Note: If this feature is useful for other widgets, we could abstract it into an
	// OO.ui.HeaderedElement mixin constructor.
	if ( config.header !== undefined ) {
		this.$group
			.prepend( $( '<span>' )
				.addClass( 'oo-ui-popupToolGroup-header' )
				.text( config.header )
			);
	}
	this.$element
		.addClass( 'oo-ui-popupToolGroup' )
		.prepend( this.$handle );
};

/* Setup */

OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IconElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IndicatorElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.LabelElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TitledElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.FlaggedElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.ClippableElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TabIndexedElement );

/* Methods */

/**
 * @inheritdoc OO.ui.mixin.ClippableElement
 */
OO.ui.PopupToolGroup.prototype.getHorizontalAnchorEdge = function () {
	var out;
	if ( this.$element.hasClass( 'oo-ui-popupToolGroup-right' ) ) {
		out = 'right';
	} else {
		out = 'left';
	}
	// Flip for RTL
	if ( this.$element.css( 'direction' ) === 'rtl' ) {
		out = ( out === 'left' ) ? 'right' : 'left';
	}
	return out;
};

/**
 * @inheritdoc OO.ui.mixin.ClippableElement
 */
OO.ui.PopupToolGroup.prototype.getVerticalAnchorEdge = function () {
	if ( this.toolbar.position === 'bottom' ) {
		return 'bottom';
	}
	return 'top';
};

/**
 * @inheritdoc
 */
OO.ui.PopupToolGroup.prototype.setDisabled = function () {
	// Parent method
	OO.ui.PopupToolGroup.parent.prototype.setDisabled.apply( this, arguments );

	if ( this.isDisabled() && this.isElementAttached() ) {
		this.setActive( false );
	}
};

/**
 * Handle focus being lost.
 *
 * The event is actually generated from a mouseup/keyup, so it is not a normal blur event object.
 *
 * @protected
 * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event
 */
OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
	// Only deactivate when clicking outside the dropdown element
	if ( $( e.target ).closest( '.oo-ui-popupToolGroup' )[ 0 ] !== this.$element[ 0 ] ) {
		this.setActive( false );
	}
};

/**
 * @inheritdoc
 */
OO.ui.PopupToolGroup.prototype.onMouseKeyUp = function ( e ) {
	// Only close toolgroup when a tool was actually selected
	if (
		!this.isDisabled() && this.pressed && this.pressed === this.findTargetTool( e ) &&
		( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
	) {
		this.setActive( false );
	}
	return OO.ui.PopupToolGroup.parent.prototype.onMouseKeyUp.call( this, e );
};

/**
 * Handle mouse up and key up events.
 *
 * @protected
 * @param {jQuery.Event} e Mouse up or key up event
 */
OO.ui.PopupToolGroup.prototype.onHandleMouseKeyUp = function ( e ) {
	if (
		!this.isDisabled() &&
		( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
	) {
		return false;
	}
};

/**
 * Handle mouse down and key down events.
 *
 * @protected
 * @param {jQuery.Event} e Mouse down or key down event
 */
OO.ui.PopupToolGroup.prototype.onHandleMouseKeyDown = function ( e ) {
	if (
		!this.isDisabled() &&
		( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
	) {
		this.setActive( !this.active );
		return false;
	}
};

/**
 * Switch into 'active' mode.
 *
 * When active, the popup is visible. A mouseup event anywhere in the document will trigger
 * deactivation.
 *
 * @param {boolean} value The active state to set
 */
OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
	var containerWidth, containerLeft;
	value = !!value;
	if ( this.active !== value ) {
		this.active = value;
		if ( value ) {
			this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
			this.getElementDocument().addEventListener( 'keyup', this.onBlurHandler, true );

			this.$clippable.css( 'left', '' );
			// Try anchoring the popup to the left first
			this.$element.addClass( 'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left' );
			this.setFlags( { progressive: true } );
			this.toggleClipping( true );
			if ( this.isClippedHorizontally() || this.isFloatableOutOfView() ) {
				// Anchoring to the left caused the popup to clip, so anchor it to the right instead
				this.toggleClipping( false );
				this.$element
					.removeClass( 'oo-ui-popupToolGroup-left' )
					.addClass( 'oo-ui-popupToolGroup-right' );
				this.toggleClipping( true );
			}
			if ( this.isClippedHorizontally() || this.isFloatableOutOfView() ) {
				// Anchoring to the right also caused the popup to clip, so just make it fill the container
				containerWidth = this.$clippableScrollableContainer.width();
				containerLeft = this.$clippableScrollableContainer[ 0 ] === document.documentElement ?
					0 :
					this.$clippableScrollableContainer.offset().left;

				this.toggleClipping( false );
				this.$element.removeClass( 'oo-ui-popupToolGroup-right' );

				this.$clippable.css( {
					left: -( this.$element.offset().left - containerLeft ),
					width: containerWidth
				} );
			}
		} else {
			this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
			this.getElementDocument().removeEventListener( 'keyup', this.onBlurHandler, true );
			this.$element.removeClass(
				'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left  oo-ui-popupToolGroup-right'
			);
			this.setFlags( { progressive: false } );
			this.toggleClipping( false );
		}
	}
};
<commit_msg>PopupToolGroup: Revert "Fix popup direction changing..."<commit_after>/**
 * PopupToolGroup is an abstract base class used by both {@link OO.ui.MenuToolGroup MenuToolGroup}
 * and {@link OO.ui.ListToolGroup ListToolGroup} to provide a popup--an overlaid menu or list of tools with an
 * optional icon and label. This class can be used for other base classes that also use this functionality.
 *
 * @abstract
 * @class
 * @extends OO.ui.ToolGroup
 * @mixins OO.ui.mixin.IconElement
 * @mixins OO.ui.mixin.IndicatorElement
 * @mixins OO.ui.mixin.LabelElement
 * @mixins OO.ui.mixin.TitledElement
 * @mixins OO.ui.mixin.FlaggedElement
 * @mixins OO.ui.mixin.ClippableElement
 * @mixins OO.ui.mixin.TabIndexedElement
 *
 * @constructor
 * @param {OO.ui.Toolbar} toolbar
 * @param {Object} [config] Configuration options
 * @cfg {string} [header] Text to display at the top of the popup
 */
OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
	// Allow passing positional parameters inside the config object
	if ( OO.isPlainObject( toolbar ) && config === undefined ) {
		config = toolbar;
		toolbar = config.toolbar;
	}

	// Configuration initialization
	config = $.extend( {
		indicator: config.indicator === undefined ? ( toolbar.position === 'bottom' ? 'up' : 'down' ) : config.indicator
	}, config );

	// Parent constructor
	OO.ui.PopupToolGroup.parent.call( this, toolbar, config );

	// Properties
	this.active = false;
	this.dragging = false;
	this.onBlurHandler = this.onBlur.bind( this );
	this.$handle = $( '<span>' );

	// Mixin constructors
	OO.ui.mixin.IconElement.call( this, config );
	OO.ui.mixin.IndicatorElement.call( this, config );
	OO.ui.mixin.LabelElement.call( this, config );
	OO.ui.mixin.TitledElement.call( this, config );
	OO.ui.mixin.FlaggedElement.call( this, config );
	OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );
	OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) );

	// Events
	this.$handle.on( {
		keydown: this.onHandleMouseKeyDown.bind( this ),
		keyup: this.onHandleMouseKeyUp.bind( this ),
		mousedown: this.onHandleMouseKeyDown.bind( this ),
		mouseup: this.onHandleMouseKeyUp.bind( this )
	} );

	// Initialization
	this.$handle
		.addClass( 'oo-ui-popupToolGroup-handle' )
		.attr( 'role', 'button' )
		.append( this.$icon, this.$label, this.$indicator );
	// If the pop-up should have a header, add it to the top of the toolGroup.
	// Note: If this feature is useful for other widgets, we could abstract it into an
	// OO.ui.HeaderedElement mixin constructor.
	if ( config.header !== undefined ) {
		this.$group
			.prepend( $( '<span>' )
				.addClass( 'oo-ui-popupToolGroup-header' )
				.text( config.header )
			);
	}
	this.$element
		.addClass( 'oo-ui-popupToolGroup' )
		.prepend( this.$handle );
};

/* Setup */

OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IconElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IndicatorElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.LabelElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TitledElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.FlaggedElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.ClippableElement );
OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TabIndexedElement );

/* Methods */

/**
 * @inheritdoc OO.ui.mixin.ClippableElement
 */
OO.ui.PopupToolGroup.prototype.getHorizontalAnchorEdge = function () {
	var out;
	if ( this.$element.hasClass( 'oo-ui-popupToolGroup-right' ) ) {
		out = 'right';
	} else {
		out = 'left';
	}
	// Flip for RTL
	if ( this.$element.css( 'direction' ) === 'rtl' ) {
		out = ( out === 'left' ) ? 'right' : 'left';
	}
	return out;
};

/**
 * @inheritdoc OO.ui.mixin.ClippableElement
 */
OO.ui.PopupToolGroup.prototype.getVerticalAnchorEdge = function () {
	if ( this.toolbar.position === 'bottom' ) {
		return 'bottom';
	}
	return 'top';
};

/**
 * @inheritdoc
 */
OO.ui.PopupToolGroup.prototype.setDisabled = function () {
	// Parent method
	OO.ui.PopupToolGroup.parent.prototype.setDisabled.apply( this, arguments );

	if ( this.isDisabled() && this.isElementAttached() ) {
		this.setActive( false );
	}
};

/**
 * Handle focus being lost.
 *
 * The event is actually generated from a mouseup/keyup, so it is not a normal blur event object.
 *
 * @protected
 * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event
 */
OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
	// Only deactivate when clicking outside the dropdown element
	if ( $( e.target ).closest( '.oo-ui-popupToolGroup' )[ 0 ] !== this.$element[ 0 ] ) {
		this.setActive( false );
	}
};

/**
 * @inheritdoc
 */
OO.ui.PopupToolGroup.prototype.onMouseKeyUp = function ( e ) {
	// Only close toolgroup when a tool was actually selected
	if (
		!this.isDisabled() && this.pressed && this.pressed === this.findTargetTool( e ) &&
		( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
	) {
		this.setActive( false );
	}
	return OO.ui.PopupToolGroup.parent.prototype.onMouseKeyUp.call( this, e );
};

/**
 * Handle mouse up and key up events.
 *
 * @protected
 * @param {jQuery.Event} e Mouse up or key up event
 */
OO.ui.PopupToolGroup.prototype.onHandleMouseKeyUp = function ( e ) {
	if (
		!this.isDisabled() &&
		( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
	) {
		return false;
	}
};

/**
 * Handle mouse down and key down events.
 *
 * @protected
 * @param {jQuery.Event} e Mouse down or key down event
 */
OO.ui.PopupToolGroup.prototype.onHandleMouseKeyDown = function ( e ) {
	if (
		!this.isDisabled() &&
		( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
	) {
		this.setActive( !this.active );
		return false;
	}
};

/**
 * Switch into 'active' mode.
 *
 * When active, the popup is visible. A mouseup event anywhere in the document will trigger
 * deactivation.
 *
 * @param {boolean} value The active state to set
 */
OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
	var containerWidth, containerLeft;
	value = !!value;
	if ( this.active !== value ) {
		this.active = value;
		if ( value ) {
			this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
			this.getElementDocument().addEventListener( 'keyup', this.onBlurHandler, true );

			this.$clippable.css( 'left', '' );
			// Try anchoring the popup to the left first
			this.$element.addClass( 'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left' );
			this.setFlags( { progressive: true } );
			this.toggleClipping( true );
			if ( this.isClippedHorizontally() ) {
				// Anchoring to the left caused the popup to clip, so anchor it to the right instead
				this.toggleClipping( false );
				this.$element
					.removeClass( 'oo-ui-popupToolGroup-left' )
					.addClass( 'oo-ui-popupToolGroup-right' );
				this.toggleClipping( true );
			}
			if ( this.isClippedHorizontally() ) {
				// Anchoring to the right also caused the popup to clip, so just make it fill the container
				containerWidth = this.$clippableScrollableContainer.width();
				containerLeft = this.$clippableScrollableContainer[ 0 ] === document.documentElement ?
					0 :
					this.$clippableScrollableContainer.offset().left;

				this.toggleClipping( false );
				this.$element.removeClass( 'oo-ui-popupToolGroup-right' );

				this.$clippable.css( {
					left: -( this.$element.offset().left - containerLeft ),
					width: containerWidth
				} );
			}
		} else {
			this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
			this.getElementDocument().removeEventListener( 'keyup', this.onBlurHandler, true );
			this.$element.removeClass(
				'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left  oo-ui-popupToolGroup-right'
			);
			this.setFlags( { progressive: false } );
			this.toggleClipping( false );
		}
	}
};
<|endoftext|>


<commit_before>const {Document} = require('tree-sitter')
const {Point, Range, Emitter} = require('atom')
const ScopeDescriptor = require('./scope-descriptor')
const TokenizedLine = require('./tokenized-line')

let nextId = 0

module.exports =
class TreeSitterLanguageMode {
  constructor ({buffer, grammar, config}) {
    this.id = nextId++
    this.buffer = buffer
    this.grammar = grammar
    this.config = config
    this.document = new Document()
    this.document.setInput(new TreeSitterTextBufferInput(buffer))
    this.document.setLanguage(grammar.languageModule)
    this.document.parse()
    this.rootScopeDescriptor = new ScopeDescriptor({scopes: [this.grammar.id]})
    this.emitter = new Emitter()
    this.isFoldableCache = []
  }

  getLanguageId () {
    return this.grammar.id
  }

  bufferDidChange ({oldRange, newRange, oldText, newText}) {
    const startRow = oldRange.start.row
    const oldEndRow = oldRange.end.row
    const newEndRow = newRange.end.row
    this.isFoldableCache.splice(startRow, oldEndRow - startRow, ...new Array(newEndRow - startRow))
    this.document.edit({
      startIndex: this.buffer.characterIndexForPosition(oldRange.start),
      lengthRemoved: oldText.length,
      lengthAdded: newText.length,
      startPosition: oldRange.start,
      extentRemoved: oldRange.getExtent(),
      extentAdded: newRange.getExtent()
    })
  }

  /*
   * Section - Highlighting
   */

  buildHighlightIterator () {
    const invalidatedRanges = this.document.parse()
    for (let i = 0, n = invalidatedRanges.length; i < n; i++) {
      const range = invalidatedRanges[i]
      const startRow = range.start.row
      const endRow = range.end.row
      for (let row = startRow; row < endRow; row++) {
        this.isFoldableCache[row] = undefined
      }
      this.emitter.emit('did-change-highlighting', range)
    }
    return new TreeSitterHighlightIterator(this)
  }

  onDidChangeHighlighting (callback) {
    return this.emitter.on('did-change-hightlighting', callback)
  }

  classNameForScopeId (scopeId) {
    return this.grammar.classNameForScopeId(scopeId)
  }

  /*
   * Section - Commenting
   */

  commentStringsForPosition () {
    return this.grammar.commentStrings
  }

  isRowCommented () {
    return false
  }

  /*
   * Section - Indentation
   */

  suggestedIndentForLineAtBufferRow (row, line, tabLength) {
    return this.suggestedIndentForBufferRow(row, tabLength)
  }

  suggestedIndentForBufferRow (row, tabLength, options) {
    let precedingRow
    if (!options || options.skipBlankLines !== false) {
      precedingRow = this.buffer.previousNonBlankRow(row)
      if (precedingRow == null) return 0
    } else {
      precedingRow = row - 1
      if (precedingRow < 0) return 0
    }

    return this.indentLevelForLine(this.buffer.lineForRow(precedingRow), tabLength)
  }

  suggestedIndentForEditedBufferRow (row) {
    return null
  }

  indentLevelForLine (line, tabLength = tabLength) {
    let indentLength = 0
    for (let i = 0, {length} = line; i < length; i++) {
      const char = line[i]
      if (char === '\t') {
        indentLength += tabLength - (indentLength % tabLength)
      } else if (char === ' ') {
        indentLength++
      } else {
        break
      }
    }
    return indentLength / tabLength
  }

  /*
   * Section - Folding
   */

  isFoldableAtRow (row) {
    if (this.isFoldableCache[row] != null) return this.isFoldableCache[row]
    const result = this.getFoldableRangeContainingPoint(Point(row, Infinity), 0, true) != null
    this.isFoldableCache[row] = result
    return result
  }

  getFoldableRanges () {
    return this.getFoldableRangesAtIndentLevel(null)
  }

  getFoldableRangesAtIndentLevel (goalLevel) {
    let result = []
    let stack = [{node: this.document.rootNode, level: 0}]
    while (stack.length > 0) {
      const {node, level} = stack.pop()

      const range = this.getFoldableRangeForNode(node)
      if (range) {
        if (goalLevel == null || level === goalLevel) {
          let updatedExistingRange = false
          for (let i = 0, {length} = result; i < length; i++) {
            if (result[i].start.row === range.start.row &&
                result[i].end.row === range.end.row) {
              result[i] = range
              updatedExistingRange = true
              break
            }
          }
          if (!updatedExistingRange) result.push(range)
        }
      }

      const parentStartRow = node.startPosition.row
      const parentEndRow = node.endPosition.row
      for (let children = node.namedChildren, i = 0, {length} = children; i < length; i++) {
        const child = children[i]
        const {startPosition: childStart, endPosition: childEnd} = child
        if (childEnd.row > childStart.row) {
          if (childStart.row === parentStartRow && childEnd.row === parentEndRow) {
            stack.push({node: child, level: level})
          } else {
            const childLevel = range && range.containsPoint(childStart) && range.containsPoint(childEnd)
              ? level + 1
              : level
            if (childLevel <= goalLevel || goalLevel == null) {
              stack.push({node: child, level: childLevel})
            }
          }
        }
      }
    }

    return result.sort((a, b) => a.start.row - b.start.row)
  }

  getFoldableRangeContainingPoint (point, tabLength, existenceOnly = false) {
    let node = this.document.rootNode.descendantForPosition(this.buffer.clipPosition(point))
    while (node) {
      if (existenceOnly && node.startPosition.row < point.row) break
      if (node.endPosition.row > point.row) {
        const range = this.getFoldableRangeForNode(node, existenceOnly)
        if (range) return range
      }
      node = node.parent
    }
  }

  getFoldableRangeForNode (node, existenceOnly) {
    const {children, type: nodeType} = node
    const childCount = children.length
    let childTypes

    for (var i = 0, {length} = this.grammar.folds; i < length; i++) {
      const foldEntry = this.grammar.folds[i]

      if (foldEntry.type) {
        if (typeof foldEntry.type === 'string') {
          if (foldEntry.type !== nodeType) continue
        } else {
          if (!foldEntry.type.includes(nodeType)) continue
        }
      }

      let foldStart
      const startEntry = foldEntry.start
      if (startEntry) {
        if (startEntry.index != null) {
          const child = children[startEntry.index]
          if (!child || (startEntry.type && startEntry.type !== child.type)) continue
          foldStart = child.endPosition
        } else {
          if (!childTypes) childTypes = children.map(child => child.type)
          const index = typeof startEntry.type === 'string'
            ? childTypes.indexOf(startEntry.type)
            : childTypes.findIndex(type => startEntry.type.includes(type))
          if (index === -1) continue
          foldStart = children[index].endPosition
        }
      }

      let foldEnd
      const endEntry = foldEntry.end
      if (endEntry) {
        let foldEndNode
        if (endEntry.index != null) {
          const index = endEntry.index < 0 ? childCount + endEntry.index : endEntry.index
          foldEndNode = children[index]
          if (!foldEndNode || (endEntry.type && endEntry.type !== foldEndNode.type)) continue
        } else {
          if (!childTypes) childTypes = children.map(foldEndNode => foldEndNode.type)
          const index = typeof endEntry.type === 'string'
            ? childTypes.indexOf(endEntry.type)
            : childTypes.findIndex(type => endEntry.type.includes(type))
          if (index === -1) continue
          foldEndNode = children[index]
        }

        if (foldEndNode.endIndex - foldEndNode.startIndex > 1 && foldEndNode.startPosition.row > foldStart.row) {
          foldEnd = new Point(foldEndNode.startPosition.row - 1, Infinity)
        } else {
          foldEnd = foldEndNode.startPosition
        }
      }

      if (existenceOnly) return true

      if (!foldStart) {
        foldStart = new Point(node.startPosition.row, Infinity)
      }

      if (!foldEnd) {
        const {endPosition} = node
        if (endPosition.column === 0) {
          foldEnd = Point(endPosition.row - 1, Infinity)
        } else if (childCount > 0) {
          foldEnd = endPosition
        } else {
          foldEnd = Point(endPosition.row, 0)
        }
      }

      return new Range(foldStart, foldEnd)
    }
  }

  /*
   * Syntax Tree APIs
   */

  getRangeForSyntaxNodeContainingRange (range) {
    const startIndex = this.buffer.characterIndexForPosition(range.start)
    const endIndex = this.buffer.characterIndexForPosition(range.end)
    let node = this.document.rootNode.descendantForIndex(startIndex, endIndex - 1)
    while (node && node.startIndex === startIndex && node.endIndex === endIndex) {
      node = node.parent
    }
    if (node) return new Range(node.startPosition, node.endPosition)
  }

  /*
   * Section - Backward compatibility shims
   */

  tokenizedLineForRow (row) {
    return new TokenizedLine({
      openScopes: [],
      text: this.buffer.lineForRow(row),
      tags: [],
      ruleStack: [],
      lineEnding: this.buffer.lineEndingForRow(row),
      tokenIterator: null,
      grammar: this.grammar
    })
  }

  scopeDescriptorForPosition (point) {
    return this.rootScopeDescriptor
  }

  hasTokenForSelector (scopeSelector) {
    return false
  }

  getGrammar () {
    return this.grammar
  }
}

class TreeSitterHighlightIterator {
  constructor (layer, document) {
    this.layer = layer

    // Conceptually, the iterator represents a single position in the text. It stores this
    // position both as a character index and as a `Point`. This position corresponds to a
    // leaf node of the syntax tree, which either contains or follows the iterator's
    // textual position. The `currentNode` property represents that leaf node, and
    // `currentChildIndex` represents the child index of that leaf node within its parent.
    this.currentIndex = null
    this.currentPosition = null
    this.currentNode = null
    this.currentChildIndex = null

    // In order to determine which selectors match its current node, the iterator maintains
    // a list of the current node's ancestors. Because the selectors can use the `:nth-child`
    // pseudo-class, each node's child index is also stored.
    this.containingNodeTypes = []
    this.containingNodeChildIndices = []

    // At any given position, the iterator exposes the list of class names that should be
    // *ended* at its current position and the list of class names that should be *started*
    // at its current position.
    this.closeTags = []
    this.openTags = []
  }

  seek (targetPosition) {
    const containingTags = []

    this.closeTags.length = 0
    this.openTags.length = 0
    this.containingNodeTypes.length = 0
    this.containingNodeChildIndices.length = 0
    this.currentPosition = targetPosition
    this.currentIndex = this.layer.buffer.characterIndexForPosition(targetPosition)

    var node = this.layer.document.rootNode
    var childIndex = -1
    var done = false
    var nodeContainsTarget = true
    do {
      this.currentNode = node
      this.currentChildIndex = childIndex
      this.containingNodeTypes.push(node.type)
      this.containingNodeChildIndices.push(childIndex)
      if (!nodeContainsTarget) break

      const scopeName = this.currentScopeName()
      if (scopeName) {
        const id = this.layer.grammar.idForScope(scopeName)
        if (this.currentIndex === node.startIndex) {
          this.openTags.push(id)
        } else {
          containingTags.push(id)
        }
      }

      done = true
      for (var i = 0, {children} = node, childCount = children.length; i < childCount; i++) {
        const child = children[i]
        if (child.endIndex > this.currentIndex) {
          node = child
          childIndex = i
          done = false
          if (child.startIndex > this.currentIndex) nodeContainsTarget = false
          break
        }
      }
    } while (!done)

    return containingTags
  }

  moveToSuccessor () {
    this.closeTags.length = 0
    this.openTags.length = 0

    if (!this.currentNode) {
      this.currentPosition = {row: Infinity, column: Infinity}
      return false
    }

    do {
      if (this.currentIndex < this.currentNode.startIndex) {
        this.currentIndex = this.currentNode.startIndex
        this.currentPosition = this.currentNode.startPosition
        this.pushOpenTag()
        this.descendLeft()
      } else if (this.currentIndex < this.currentNode.endIndex) {
        while (true) {
          this.currentIndex = this.currentNode.endIndex
          this.currentPosition = this.currentNode.endPosition
          this.pushCloseTag()

          const {nextSibling} = this.currentNode
          if (nextSibling) {
            this.currentNode = nextSibling
            this.currentChildIndex++
            if (this.currentIndex === nextSibling.startIndex) {
              this.pushOpenTag()
              this.descendLeft()
            }
            break
          } else {
            this.currentNode = this.currentNode.parent
            this.currentChildIndex = last(this.containingNodeChildIndices)
            if (!this.currentNode) break
          }
        }
      } else {
        this.currentNode = this.currentNode.nextSibling
        if (this.currentNode) {
          this.currentChildIndex++
          this.currentPosition = this.currentNode.startPosition
          this.currentIndex = this.currentNode.startIndex
          this.pushOpenTag()
          this.descendLeft()
        }
      }
    } while (this.closeTags.length === 0 && this.openTags.length === 0 && this.currentNode)

    return true
  }

  getPosition () {
    return this.currentPosition
  }

  getCloseScopeIds () {
    return this.closeTags.slice()
  }

  getOpenScopeIds () {
    return this.openTags.slice()
  }

  // Private methods

  descendLeft () {
    let child
    while ((child = this.currentNode.firstChild) && this.currentIndex === child.startIndex) {
      this.currentNode = child
      this.currentChildIndex = 0
      this.pushOpenTag()
    }
  }

  currentScopeName () {
    return this.layer.grammar.scopeMap.get(
      this.containingNodeTypes,
      this.containingNodeChildIndices,
      this.currentNode.isNamed
    )
  }

  pushCloseTag () {
    const scopeName = this.currentScopeName()
    if (scopeName) this.closeTags.push(this.layer.grammar.idForScope(scopeName))
    this.containingNodeTypes.pop()
    this.containingNodeChildIndices.pop()
  }

  pushOpenTag () {
    this.containingNodeTypes.push(this.currentNode.type)
    this.containingNodeChildIndices.push(this.currentChildIndex)
    const scopeName = this.currentScopeName()
    if (scopeName) this.openTags.push(this.layer.grammar.idForScope(scopeName))
  }
}

class TreeSitterTextBufferInput {
  constructor (buffer) {
    this.buffer = buffer
    this.seek(0)
  }

  seek (characterIndex) {
    this.position = this.buffer.positionForCharacterIndex(characterIndex)
  }

  read () {
    const endPosition = this.buffer.clipPosition(this.position.traverse({row: 1000, column: 0}))
    const text = this.buffer.getTextInRange([this.position, endPosition])
    this.position = endPosition
    return text
  }
}

function last (array) {
  return array[array.length - 1]
}
<commit_msg>Fix exception in getFoldableRangeForNode<commit_after>const {Document} = require('tree-sitter')
const {Point, Range, Emitter} = require('atom')
const ScopeDescriptor = require('./scope-descriptor')
const TokenizedLine = require('./tokenized-line')

let nextId = 0

module.exports =
class TreeSitterLanguageMode {
  constructor ({buffer, grammar, config}) {
    this.id = nextId++
    this.buffer = buffer
    this.grammar = grammar
    this.config = config
    this.document = new Document()
    this.document.setInput(new TreeSitterTextBufferInput(buffer))
    this.document.setLanguage(grammar.languageModule)
    this.document.parse()
    this.rootScopeDescriptor = new ScopeDescriptor({scopes: [this.grammar.id]})
    this.emitter = new Emitter()
    this.isFoldableCache = []
  }

  getLanguageId () {
    return this.grammar.id
  }

  bufferDidChange ({oldRange, newRange, oldText, newText}) {
    const startRow = oldRange.start.row
    const oldEndRow = oldRange.end.row
    const newEndRow = newRange.end.row
    this.isFoldableCache.splice(startRow, oldEndRow - startRow, ...new Array(newEndRow - startRow))
    this.document.edit({
      startIndex: this.buffer.characterIndexForPosition(oldRange.start),
      lengthRemoved: oldText.length,
      lengthAdded: newText.length,
      startPosition: oldRange.start,
      extentRemoved: oldRange.getExtent(),
      extentAdded: newRange.getExtent()
    })
  }

  /*
   * Section - Highlighting
   */

  buildHighlightIterator () {
    const invalidatedRanges = this.document.parse()
    for (let i = 0, n = invalidatedRanges.length; i < n; i++) {
      const range = invalidatedRanges[i]
      const startRow = range.start.row
      const endRow = range.end.row
      for (let row = startRow; row < endRow; row++) {
        this.isFoldableCache[row] = undefined
      }
      this.emitter.emit('did-change-highlighting', range)
    }
    return new TreeSitterHighlightIterator(this)
  }

  onDidChangeHighlighting (callback) {
    return this.emitter.on('did-change-hightlighting', callback)
  }

  classNameForScopeId (scopeId) {
    return this.grammar.classNameForScopeId(scopeId)
  }

  /*
   * Section - Commenting
   */

  commentStringsForPosition () {
    return this.grammar.commentStrings
  }

  isRowCommented () {
    return false
  }

  /*
   * Section - Indentation
   */

  suggestedIndentForLineAtBufferRow (row, line, tabLength) {
    return this.suggestedIndentForBufferRow(row, tabLength)
  }

  suggestedIndentForBufferRow (row, tabLength, options) {
    let precedingRow
    if (!options || options.skipBlankLines !== false) {
      precedingRow = this.buffer.previousNonBlankRow(row)
      if (precedingRow == null) return 0
    } else {
      precedingRow = row - 1
      if (precedingRow < 0) return 0
    }

    return this.indentLevelForLine(this.buffer.lineForRow(precedingRow), tabLength)
  }

  suggestedIndentForEditedBufferRow (row) {
    return null
  }

  indentLevelForLine (line, tabLength = tabLength) {
    let indentLength = 0
    for (let i = 0, {length} = line; i < length; i++) {
      const char = line[i]
      if (char === '\t') {
        indentLength += tabLength - (indentLength % tabLength)
      } else if (char === ' ') {
        indentLength++
      } else {
        break
      }
    }
    return indentLength / tabLength
  }

  /*
   * Section - Folding
   */

  isFoldableAtRow (row) {
    if (this.isFoldableCache[row] != null) return this.isFoldableCache[row]
    const result = this.getFoldableRangeContainingPoint(Point(row, Infinity), 0, true) != null
    this.isFoldableCache[row] = result
    return result
  }

  getFoldableRanges () {
    return this.getFoldableRangesAtIndentLevel(null)
  }

  getFoldableRangesAtIndentLevel (goalLevel) {
    let result = []
    let stack = [{node: this.document.rootNode, level: 0}]
    while (stack.length > 0) {
      const {node, level} = stack.pop()

      const range = this.getFoldableRangeForNode(node)
      if (range) {
        if (goalLevel == null || level === goalLevel) {
          let updatedExistingRange = false
          for (let i = 0, {length} = result; i < length; i++) {
            if (result[i].start.row === range.start.row &&
                result[i].end.row === range.end.row) {
              result[i] = range
              updatedExistingRange = true
              break
            }
          }
          if (!updatedExistingRange) result.push(range)
        }
      }

      const parentStartRow = node.startPosition.row
      const parentEndRow = node.endPosition.row
      for (let children = node.namedChildren, i = 0, {length} = children; i < length; i++) {
        const child = children[i]
        const {startPosition: childStart, endPosition: childEnd} = child
        if (childEnd.row > childStart.row) {
          if (childStart.row === parentStartRow && childEnd.row === parentEndRow) {
            stack.push({node: child, level: level})
          } else {
            const childLevel = range && range.containsPoint(childStart) && range.containsPoint(childEnd)
              ? level + 1
              : level
            if (childLevel <= goalLevel || goalLevel == null) {
              stack.push({node: child, level: childLevel})
            }
          }
        }
      }
    }

    return result.sort((a, b) => a.start.row - b.start.row)
  }

  getFoldableRangeContainingPoint (point, tabLength, existenceOnly = false) {
    let node = this.document.rootNode.descendantForPosition(this.buffer.clipPosition(point))
    while (node) {
      if (existenceOnly && node.startPosition.row < point.row) break
      if (node.endPosition.row > point.row) {
        const range = this.getFoldableRangeForNode(node, existenceOnly)
        if (range) return range
      }
      node = node.parent
    }
  }

  getFoldableRangeForNode (node, existenceOnly) {
    const {children, type: nodeType} = node
    const childCount = children.length
    let childTypes

    for (var i = 0, {length} = this.grammar.folds; i < length; i++) {
      const foldEntry = this.grammar.folds[i]

      if (foldEntry.type) {
        if (typeof foldEntry.type === 'string') {
          if (foldEntry.type !== nodeType) continue
        } else {
          if (!foldEntry.type.includes(nodeType)) continue
        }
      }

      let foldStart
      const startEntry = foldEntry.start
      if (startEntry) {
        if (startEntry.index != null) {
          const child = children[startEntry.index]
          if (!child || (startEntry.type && startEntry.type !== child.type)) continue
          foldStart = child.endPosition
        } else {
          if (!childTypes) childTypes = children.map(child => child.type)
          const index = typeof startEntry.type === 'string'
            ? childTypes.indexOf(startEntry.type)
            : childTypes.findIndex(type => startEntry.type.includes(type))
          if (index === -1) continue
          foldStart = children[index].endPosition
        }
      } else {
        foldStart = new Point(node.startPosition.row, Infinity)
      }

      let foldEnd
      const endEntry = foldEntry.end
      if (endEntry) {
        let foldEndNode
        if (endEntry.index != null) {
          const index = endEntry.index < 0 ? childCount + endEntry.index : endEntry.index
          foldEndNode = children[index]
          if (!foldEndNode || (endEntry.type && endEntry.type !== foldEndNode.type)) continue
        } else {
          if (!childTypes) childTypes = children.map(foldEndNode => foldEndNode.type)
          const index = typeof endEntry.type === 'string'
            ? childTypes.indexOf(endEntry.type)
            : childTypes.findIndex(type => endEntry.type.includes(type))
          if (index === -1) continue
          foldEndNode = children[index]
        }

        if (foldEndNode.endIndex - foldEndNode.startIndex > 1 && foldEndNode.startPosition.row > foldStart.row) {
          foldEnd = new Point(foldEndNode.startPosition.row - 1, Infinity)
        } else {
          foldEnd = foldEndNode.startPosition
        }
      } else {
        const {endPosition} = node
        if (endPosition.column === 0) {
          foldEnd = Point(endPosition.row - 1, Infinity)
        } else if (childCount > 0) {
          foldEnd = endPosition
        } else {
          foldEnd = Point(endPosition.row, 0)
        }
      }

      return existenceOnly ? true : new Range(foldStart, foldEnd)
    }
  }

  /*
   * Syntax Tree APIs
   */

  getRangeForSyntaxNodeContainingRange (range) {
    const startIndex = this.buffer.characterIndexForPosition(range.start)
    const endIndex = this.buffer.characterIndexForPosition(range.end)
    let node = this.document.rootNode.descendantForIndex(startIndex, endIndex - 1)
    while (node && node.startIndex === startIndex && node.endIndex === endIndex) {
      node = node.parent
    }
    if (node) return new Range(node.startPosition, node.endPosition)
  }

  /*
   * Section - Backward compatibility shims
   */

  tokenizedLineForRow (row) {
    return new TokenizedLine({
      openScopes: [],
      text: this.buffer.lineForRow(row),
      tags: [],
      ruleStack: [],
      lineEnding: this.buffer.lineEndingForRow(row),
      tokenIterator: null,
      grammar: this.grammar
    })
  }

  scopeDescriptorForPosition (point) {
    return this.rootScopeDescriptor
  }

  hasTokenForSelector (scopeSelector) {
    return false
  }

  getGrammar () {
    return this.grammar
  }
}

class TreeSitterHighlightIterator {
  constructor (layer, document) {
    this.layer = layer

    // Conceptually, the iterator represents a single position in the text. It stores this
    // position both as a character index and as a `Point`. This position corresponds to a
    // leaf node of the syntax tree, which either contains or follows the iterator's
    // textual position. The `currentNode` property represents that leaf node, and
    // `currentChildIndex` represents the child index of that leaf node within its parent.
    this.currentIndex = null
    this.currentPosition = null
    this.currentNode = null
    this.currentChildIndex = null

    // In order to determine which selectors match its current node, the iterator maintains
    // a list of the current node's ancestors. Because the selectors can use the `:nth-child`
    // pseudo-class, each node's child index is also stored.
    this.containingNodeTypes = []
    this.containingNodeChildIndices = []

    // At any given position, the iterator exposes the list of class names that should be
    // *ended* at its current position and the list of class names that should be *started*
    // at its current position.
    this.closeTags = []
    this.openTags = []
  }

  seek (targetPosition) {
    const containingTags = []

    this.closeTags.length = 0
    this.openTags.length = 0
    this.containingNodeTypes.length = 0
    this.containingNodeChildIndices.length = 0
    this.currentPosition = targetPosition
    this.currentIndex = this.layer.buffer.characterIndexForPosition(targetPosition)

    var node = this.layer.document.rootNode
    var childIndex = -1
    var done = false
    var nodeContainsTarget = true
    do {
      this.currentNode = node
      this.currentChildIndex = childIndex
      this.containingNodeTypes.push(node.type)
      this.containingNodeChildIndices.push(childIndex)
      if (!nodeContainsTarget) break

      const scopeName = this.currentScopeName()
      if (scopeName) {
        const id = this.layer.grammar.idForScope(scopeName)
        if (this.currentIndex === node.startIndex) {
          this.openTags.push(id)
        } else {
          containingTags.push(id)
        }
      }

      done = true
      for (var i = 0, {children} = node, childCount = children.length; i < childCount; i++) {
        const child = children[i]
        if (child.endIndex > this.currentIndex) {
          node = child
          childIndex = i
          done = false
          if (child.startIndex > this.currentIndex) nodeContainsTarget = false
          break
        }
      }
    } while (!done)

    return containingTags
  }

  moveToSuccessor () {
    this.closeTags.length = 0
    this.openTags.length = 0

    if (!this.currentNode) {
      this.currentPosition = {row: Infinity, column: Infinity}
      return false
    }

    do {
      if (this.currentIndex < this.currentNode.startIndex) {
        this.currentIndex = this.currentNode.startIndex
        this.currentPosition = this.currentNode.startPosition
        this.pushOpenTag()
        this.descendLeft()
      } else if (this.currentIndex < this.currentNode.endIndex) {
        while (true) {
          this.currentIndex = this.currentNode.endIndex
          this.currentPosition = this.currentNode.endPosition
          this.pushCloseTag()

          const {nextSibling} = this.currentNode
          if (nextSibling) {
            this.currentNode = nextSibling
            this.currentChildIndex++
            if (this.currentIndex === nextSibling.startIndex) {
              this.pushOpenTag()
              this.descendLeft()
            }
            break
          } else {
            this.currentNode = this.currentNode.parent
            this.currentChildIndex = last(this.containingNodeChildIndices)
            if (!this.currentNode) break
          }
        }
      } else {
        this.currentNode = this.currentNode.nextSibling
        if (this.currentNode) {
          this.currentChildIndex++
          this.currentPosition = this.currentNode.startPosition
          this.currentIndex = this.currentNode.startIndex
          this.pushOpenTag()
          this.descendLeft()
        }
      }
    } while (this.closeTags.length === 0 && this.openTags.length === 0 && this.currentNode)

    return true
  }

  getPosition () {
    return this.currentPosition
  }

  getCloseScopeIds () {
    return this.closeTags.slice()
  }

  getOpenScopeIds () {
    return this.openTags.slice()
  }

  // Private methods

  descendLeft () {
    let child
    while ((child = this.currentNode.firstChild) && this.currentIndex === child.startIndex) {
      this.currentNode = child
      this.currentChildIndex = 0
      this.pushOpenTag()
    }
  }

  currentScopeName () {
    return this.layer.grammar.scopeMap.get(
      this.containingNodeTypes,
      this.containingNodeChildIndices,
      this.currentNode.isNamed
    )
  }

  pushCloseTag () {
    const scopeName = this.currentScopeName()
    if (scopeName) this.closeTags.push(this.layer.grammar.idForScope(scopeName))
    this.containingNodeTypes.pop()
    this.containingNodeChildIndices.pop()
  }

  pushOpenTag () {
    this.containingNodeTypes.push(this.currentNode.type)
    this.containingNodeChildIndices.push(this.currentChildIndex)
    const scopeName = this.currentScopeName()
    if (scopeName) this.openTags.push(this.layer.grammar.idForScope(scopeName))
  }
}

class TreeSitterTextBufferInput {
  constructor (buffer) {
    this.buffer = buffer
    this.seek(0)
  }

  seek (characterIndex) {
    this.position = this.buffer.positionForCharacterIndex(characterIndex)
  }

  read () {
    const endPosition = this.buffer.clipPosition(this.position.traverse({row: 1000, column: 0}))
    const text = this.buffer.getTextInRange([this.position, endPosition])
    this.position = endPosition
    return text
  }
}

function last (array) {
  return array[array.length - 1]
}
<|endoftext|>


<commit_before>macro setupContracts {
    case ($loc) => {
	var C = $loc;
    }
}

macro check {
    case (function ($arg:ident) { $check ... }, $name:lit) => {
	C.check(function ($arg) { $check ... }, $name)
    }

    case ($handle:ident, function ($arg:ident) { $check ... }, $name:lit) => {
	var $handle = C.check(function ($arg) { $check ... }, $name)
    }
}

// TODO: add invariant sytax
//       even though it doesn't work (on account of contracts.js)
// TODO: figure out "shift/reduce" like error with operators mixed with functions
macro vbl {
    case ($[?] $comb1, $rest ...) => {
	vbl (? $comb1), vbl ($rest ...)
    }
    case ($p_type -> $ret_type $[|] $rest ...) => {
	C.fun(vbl ($p_type), vbl ($ret_type), {
	    vbl ($rest ...)
	})
    }
    case ($key:ident $[:] ! ($arg) -> { $check ... }, $rest ...) => {
	$key: function($arg) { $check ... }, vbl ($rest ...)
    }
    case ($key:ident $[:] ! ($arg) -> { $check ... }) => {
	$key: function($arg) { $check ... }
    }
    case ($p_type -> $ret_type, $rest ...) => {
    	vbl ($p_type -> $ret_type), vbl ($rest ...)
    }
    case {$key $[:] $rest ...} $[|] invariant $[:] !($arg:ident) -> {$check ...} => {
    	C.object({ $key: vbl ($rest ...) },
    		 { invariant: function($arg) { $check ... } })
    }
    case {$key $[:] $rest ...} => {
	C.object({$key: vbl ($rest ...)})
    }
    case ($key $[:] $rest ...) => {
	$key: vbl ($rest ...)
    }
    case ([$comb, $arr ...], $rest ...) => {
    	C.arr([vbl ($comb), vbl ($arr ...)]), vbl ($rest ...)
    }
    // also, note that the '@' symbol is 'not allowed'
    // the 'this' parameter now comes "after" the function contract
    case ($[#] $this) => {
	vbl ($this)
    }
    case ($comb1 or $comb2, $rest ...) => {
    	C.or(vbl ($comb1), vbl ($comb2)), vbl ($rest ...)
    }
    case ($comb1 and $comb2, $rest ...) => {
    	C.and(vbl ($comb1), vbl ($comb2)), vbl ($rest ...)
    }
    case ($comb1 or $comb2 $rest ...) => {
	vbl (($comb1 or $comb2) $rest ...)
    }
    case ($comb1 and $com2 $rest ...) => {
	vbl (($comb2 and $comb2) $rest ...)
    }
    case ($comb:ident, $rest ...) => {
	C.$comb, vbl ($rest ...)
    }
    case ($comb, $rest ...) => {
	vbl $comb, vbl ($rest ...)
    }
    // base cases
    case $p_type -> $ret_type $[|] $opts => {
    	C.fun ([vbl $p_type], vbl $ret_type, {
    	    opts $opts
    	})
    }
    case ($p_type -> $ret_type) => {
	C.fun ([vbl $p_type], vbl $ret_type)
    }
    case (! ($args:ident, $result:ident) -> { $check ... }) => {
	function ($args) {
	    return C.check(
		function ($result) { $check ... }, 'dependent')
	}
    }
    case [$arr ...] => {
    	C.arr([vbl ($arr ...)])
    }
    case ($comb1 and $comb2) => {
	C.and(vbl ($comb1), vbl ($comb2))
    }
    case ($comb1 or $comb2) => {
	C.or(vbl ($comb1), vbl ($comb2))
    }
    case ($key: ! ($arg) -> { $check ...} ) => {
	function ($arg) {
	    $check ...
	}
    }
    case ($comb $[...]) => {
    	C.___(vbl ($comb))
    }
    case ($[?] $comb) => {
	C.opt(vbl ($comb))
    }
    case ($comb) => {
    	vbl $comb
    }
    case $comb:ident => {
	C.$comb
    }
}

// so many cases...makes the syntax pretty, though
macro fun {
    case $params -> $ret function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret),
    	    function $args $body);
    }

    // an experiment. does this make sense for 'this' contract syntax
    case $params -> $ret $[#] $this function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {this: vbl $this}),
    	    function $args $body);
    }
    case $params -> ! ($argl:ident, $result:ident) -> {$check ...} function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...})),
    	    function $args $body);
    }
    case $params -> $ret $[#] $this var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret),
    	    $def);
    }
    case $params -> ! ($argl:ident, $result:ident) -> {$check ...} var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...})),
    	    $def);
    }

    // TODO: decide whether it makes sense to have a 'this' contract on callOnly/newOnly

    // no new
    case $params --> $ret function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {callOnly: true}),
    	    function $args $body);
    }
    case $params --> ! ($argl:ident, $result:ident) -> {$check ...} function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {callOnly: true}),
    	    function $args $body);
    }
    case $params --> $ret var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {callOnly: true}),
    	    $def);
    }
    case $params --> ! ($argl:ident, $result:ident) -> {$check ...} var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {callOnly: true}),
    	    $def);
    }

    // only new
    case $params ==> $ret function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {newOnly: true}),
    	    function $args $body);
    }
    case $params ==> ! ($argl:ident, $result:ident) -> {$check ...} function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {newOnly: true}),
    	    function $args $body);
    }
    case $params ==> $ret var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {newOnly: true}),
    	    $def);
    }
    case $params ==> ! ($argl:ident, $result:ident) -> {$check ...} var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {newOnly: true}),
    	    $def);
    }
}

// double duty objects and arrays
macro obj {
    case $contract var $handle:ident = $obj => {
	var $handle = C.guard(vbl $contract, $obj);
    }
    case $contract $[|] invariant $[:] ! ($var:ident) -> { $check ... } var $handle:ident = $obj => {
        var $handle = C.guard(vbl $contract | invariant: !($var) -> { $check ... }, $obj);
    }
}

macro arr {
    case $contract var $handle:ident = $arr => {
	var $handle = C.guard(vbl $contract, $arr)
    }
}

// var contracts = window['contracts-js'];
// setupContracts(contracts)
<commit_msg>removes some cruft and adds this contract to newOnly functions, fixes one of the cases for regular functions<commit_after>macro setupContracts {
    case ($loc) => {
	var C = $loc;
    }
}

macro check {
    case (function ($arg:ident) { $check ... }, $name:lit) => {
	C.check(function ($arg) { $check ... }, $name)
    }

    case ($handle:ident, function ($arg:ident) { $check ... }, $name:lit) => {
	var $handle = C.check(function ($arg) { $check ... }, $name)
    }
}

macro vbl {
    case ($[?] $comb1, $rest ...) => {
	vbl (? $comb1), vbl ($rest ...)
    }
    case ($p_type -> $ret_type $[|] $rest ...) => {
	C.fun(vbl ($p_type), vbl ($ret_type), {
	    vbl ($rest ...)
	})
    }
    case ($key:ident $[:] ! ($arg) -> { $check ... }, $rest ...) => {
	$key: function($arg) { $check ... }, vbl ($rest ...)
    }
    case ($key:ident $[:] ! ($arg) -> { $check ... }) => {
	$key: function($arg) { $check ... }
    }
    case ($p_type -> $ret_type, $rest ...) => {
    	vbl ($p_type -> $ret_type), vbl ($rest ...)
    }
    case {$key $[:] $rest ...} $[|] invariant $[:] !($arg:ident) -> {$check ...} => {
    	C.object({ $key: vbl ($rest ...) },
    		 { invariant: function($arg) { $check ... } })
    }
    case {$key $[:] $rest ...} => {
	C.object({$key: vbl ($rest ...)})
    }
    case ($key $[:] $rest ...) => {
	$key: vbl ($rest ...)
    }
    case ([$comb, $arr ...], $rest ...) => {
    	C.arr([vbl ($comb), vbl ($arr ...)]), vbl ($rest ...)
    }
    case ($comb1 or $comb2, $rest ...) => {
    	C.or(vbl ($comb1), vbl ($comb2)), vbl ($rest ...)
    }
    case ($comb1 and $comb2, $rest ...) => {
    	C.and(vbl ($comb1), vbl ($comb2)), vbl ($rest ...)
    }
    case ($comb1 or $comb2 $rest ...) => {
	vbl (($comb1 or $comb2) $rest ...)
    }
    case ($comb1 and $com2 $rest ...) => {
	vbl (($comb2 and $comb2) $rest ...)
    }
    case ($comb:ident, $rest ...) => {
	C.$comb, vbl ($rest ...)
    }
    case ($comb, $rest ...) => {
	vbl $comb, vbl ($rest ...)
    }

    // base cases
    case $p_type -> $ret_type $[|] $opts => {
    	C.fun ([vbl $p_type], vbl $ret_type, {
    	    opts $opts
    	})
    }
    case ($p_type -> $ret_type) => {
	C.fun ([vbl $p_type], vbl $ret_type)
    }
    case (! ($args:ident, $result:ident) -> { $check ... }) => {
	function ($args) {
	    return C.check(
		function ($result) { $check ... }, 'dependent')
	}
    }
    case [$arr ...] => {
    	C.arr([vbl ($arr ...)])
    }
    case ($comb1 and $comb2) => {
	C.and(vbl ($comb1), vbl ($comb2))
    }
    case ($comb1 or $comb2) => {
	C.or(vbl ($comb1), vbl ($comb2))
    }
    case ($key: ! ($arg) -> { $check ...} ) => {
	function ($arg) {
	    $check ...
	}
    }
    case ($comb $[...]) => {
    	C.___(vbl ($comb))
    }
    case ($[?] $comb) => {
	C.opt(vbl ($comb))
    }
    case ($comb) => {
    	vbl $comb
    }
    case $comb:ident => {
	C.$comb
    }
}

// so many cases...makes the syntax pretty, though
macro fun {
    case $params -> $ret function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret),
    	    function $args $body);
    }

    case $params -> $ret $[#] $this function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {this: vbl $this}),
    	    function $args $body);
    }
    case $params -> ! ($argl:ident, $result:ident) -> {$check ...} function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...})),
    	    function $args $body);
    }
    case $params -> $ret $[#] $this var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {this: vbl $this}),
    	    $def);
    }
    case $params -> ! ($argl:ident, $result:ident) -> {$check ...} var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...})),
    	    $def);
    }

    // TODO: decide whether it makes sense to have a 'this' contract on callOnly/newOnly

    // no new
    case $params --> $ret function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {callOnly: true}),
    	    function $args $body);
    }

    case $params --> $ret $[#] $this function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {callOnly: true, this: vbl $this}),
    	    function $args $body);
    }

    case $params --> ! ($argl:ident, $result:ident) -> {$check ...} function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {callOnly: true}),
    	    function $args $body);
    }

    case $params --> $ret var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {callOnly: true}),
    	    $def);
    }

    case $params --> $ret $[#] $this var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {callOnly: true, this: vbl $this}),
    	    $def);
    }

    case $params --> ! ($argl:ident, $result:ident) -> {$check ...} var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {callOnly: true}),
    	    $def);
    }

    // only new - note that newOnly functions don't take a 'this' contract
    case $params ==> $ret function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {newOnly: true}),
    	    function $args $body);
    }
    case $params ==> ! ($argl:ident, $result:ident) -> {$check ...} function $handle $args $body => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {newOnly: true}),
    	    function $args $body);
    }
    case $params ==> $ret var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl $ret, {newOnly: true}),
    	    $def);
    }
    case $params ==> ! ($argl:ident, $result:ident) -> {$check ...} var $handle = $def:expr => {
    	var $handle = C.guard(
    	    C.fun([vbl $params], vbl (! ($argl, $result) -> {$check ...}), {newOnly: true}),
    	    $def);
    }
}

// double duty objects and arrays
macro obj {
    case $contract var $handle:ident = $obj => {
	var $handle = C.guard(vbl $contract, $obj);
    }
    case $contract $[|] invariant $[:] ! ($var:ident) -> { $check ... } var $handle:ident = $obj => {
        var $handle = C.guard(vbl $contract | invariant: !($var) -> { $check ... }, $obj);
    }
}

macro arr {
    case $contract var $handle:ident = $arr => {
	var $handle = C.guard(vbl $contract, $arr)
    }
}

// var contracts = window['contracts-js'];
// setupContracts(contracts)
<|endoftext|>


<commit_before>// ==UserScript==
// @name        The Escapist - Add video link
// @namespace   localhost
// @description Adds a direct link to the video
// @include     http://www.escapistmagazine.com/videos/view/*
// @version     1
// @grant       none
// ==/UserScript==

function addLink()
{
    var video = document.querySelector("video");
    video.autoplay = false;
    video.muted = true;
    video.pause();

    video.addEventListener("play", function(){
        video.pause();
    }, false);

    var link = document.createElement("a");
    link.appendChild(document.createTextNode("Direct link"));
    link.className = "video_menu_link";
    link.href = video.src;

    var menu = document.querySelector("#video_player_menu");
    menu.insertBefore(link, menu.children[0]);
}

window.setTimeout(addLink, 3000);<commit_msg>Escapist: wait a bit longer before kicking in<commit_after>// ==UserScript==
// @name        The Escapist - Add video link
// @namespace   localhost
// @description Adds a direct link to the video
// @include     http://www.escapistmagazine.com/videos/view/*
// @version     1
// @grant       none
// ==/UserScript==

function addLink()
{
    var video = document.querySelector("video");
    video.autoplay = false;
    video.muted = true;
    video.pause();

    video.addEventListener("play", function(){
        video.pause();
    }, false);

    var link = document.createElement("a");
    link.appendChild(document.createTextNode("Direct link"));
    link.className = "video_menu_link";
    link.href = video.src;

    var menu = document.querySelector("#video_player_menu");
    menu.insertBefore(link, menu.children[0]);
}

window.setTimeout(addLink, 5000);<|endoftext|>


<commit_before>/*jshint esversion: 6 */
'use strict';
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const dynamodb = new AWS.DynamoDB.DocumentClient();

exports.handler = (event, context, callback) => {
  const today = new Date();
  var yyyy = today.getFullYear();
  var mm = today.getMonth();
  var dd = today.getDate();
  const todayEpoch = new Date(yyyy, mm, dd).getTime() / 1000;
  console.log(todayEpoch);

  let startTime = todayEpoch + 21600;
  console.log('startTime = ' + startTime);
  if (event.lastupdated > 1) {
    console.log('Detecting lastupdated variable, ' + event.lastupdated);
    startTime = Number(event.lastupdated);
  }
  console.log('startTime = ' + startTime);
  let startTimeString = startTime.toString([10]);

  console.log('startTimeString = ' + startTimeString);

  var params = {
    TableName: "impact-map",
    ProjectionExpression: "Coordinates, #b",
    FilterExpression: "Added > :start",
    ExpressionAttributeNames: {
      "#b": "Action"
    },
    ExpressionAttributeValues: {
      ":start": startTime
    }
  };

  let combinedData = [];

  console.log("Scanning table.");
  dynamodb.scan(params, onScan);

  function onScan(err, data) {
    if (err) {
      console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
    } else {
      // print all items
      console.log("Scan succeeded.");
      data.Items.forEach(function(item) {
        combinedData = combinedData.concat(item);
      });

      // continue scanning if we have more items, because
      // scan can retrieve a maximum of 1MB of data
      if (typeof data.LastEvaluatedKey != "undefined") {
        console.log("Scanning for more...");
        params.ExclusiveStartKey = data.LastEvaluatedKey;
        dynamodb.scan(params, onScan);
      }
      callback(null, combinedData);
    }
  }
};
<commit_msg>Describe UTC day beginning epoch in console<commit_after>/*jshint esversion: 6 */
'use strict';
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const dynamodb = new AWS.DynamoDB.DocumentClient();

exports.handler = (event, context, callback) => {
  const today = new Date();
  var yyyy = today.getFullYear();
  var mm = today.getMonth();
  var dd = today.getDate();
  const todayEpoch = new Date(yyyy, mm, dd).getTime() / 1000;
  console.log('UTC beginning of the day epoch = ' + todayEpoch);

  let startTime = todayEpoch + 21600;
  console.log('startTime = ' + startTime);
  if (event.lastupdated > 1) {
    console.log('Detecting lastupdated variable, ' + event.lastupdated);
    startTime = Number(event.lastupdated);
  }
  console.log('startTime = ' + startTime);
  let startTimeString = startTime.toString([10]);

  console.log('startTimeString = ' + startTimeString);

  var params = {
    TableName: "impact-map",
    ProjectionExpression: "Coordinates, #b",
    FilterExpression: "Added > :start",
    ExpressionAttributeNames: {
      "#b": "Action"
    },
    ExpressionAttributeValues: {
      ":start": startTime
    }
  };

  let combinedData = [];

  console.log("Scanning table.");
  dynamodb.scan(params, onScan);

  function onScan(err, data) {
    if (err) {
      console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
    } else {
      // print all items
      console.log("Scan succeeded.");
      data.Items.forEach(function(item) {
        combinedData = combinedData.concat(item);
      });

      // continue scanning if we have more items, because
      // scan can retrieve a maximum of 1MB of data
      if (typeof data.LastEvaluatedKey != "undefined") {
        console.log("Scanning for more...");
        params.ExclusiveStartKey = data.LastEvaluatedKey;
        dynamodb.scan(params, onScan);
      }
      callback(null, combinedData);
    }
  }
};
<|endoftext|>


<commit_before>/* eslint-disable no-console */
import { Component } from 'react'
import createBehaviorSubject from './createBehaviorSubject'
import createSymbol from './createSymbol'
import asyncThrow from './asyncThrow'
import createEagerFactory from '../createEagerFactory'
import { getConfig } from '../setConfig'
import { config as obsConfig } from '../setObservableConfig'

const MAPPERS_INFO = createSymbol('mappersInfo')
const observablePropType = () => {}

const createComponentFromMappers = (mappers, childFactory) => {
  const { observablesKey: OBSERVABLES } = getConfig()
  const CONTEXT_TYPES = { [OBSERVABLES]: observablePropType }

  return class extends Component {
    static [MAPPERS_INFO] = { mappers, childFactory }
    static contextTypes = CONTEXT_TYPES
    static childContextTypes = CONTEXT_TYPES

    props$ = createBehaviorSubject(this.props)

    componentWillMount() {
      let childProps$ = this.props$
      let childObservables = this.context[OBSERVABLES]
      for (let i = 0; i < mappers.length; i += 1) {
        ;[childProps$, childObservables] = mappers[i](
          childProps$,
          childObservables,
        )
      }

      this.childPropsSubscription = obsConfig
        .toESObservable(childProps$)
        .subscribe({
          next: childProps => {
            this.setState({ childProps })
          },
          error: error => {
            asyncThrow(error)
            this.setState({
              childProps: this.state ? this.state.childProps : {},
            })
          },
        })

      this.childContext = { [OBSERVABLES]: childObservables }
    }

    componentDidMount() {
      this.mounted = true
    }

    getChildContext() {
      return this.childContext
    }

    componentWillReceiveProps(nextProps) {
      this.props$.next(nextProps)
    }

    componentWillUnmount() {
      this.childPropsSubscription.unsubscribe()
    }

    shouldComponentUpdate(nextProps, nextState) {
      return (
        nextState &&
        (!this.state || this.state.childProps !== nextState.childProps)
      )
    }

    render() {
      if (!this.state) {
        return null
      }

      return this.constructor[MAPPERS_INFO].childFactory(this.state.childProps)
    }
  }
}

export const isMapperComponent = BaseComponent =>
  typeof BaseComponent === 'function' && BaseComponent[MAPPERS_INFO]

export default mapper => BaseComponent => {
  if (isMapperComponent(BaseComponent)) {
    return createComponentFromMappers(
      [mapper, ...BaseComponent[MAPPERS_INFO].mappers],
      BaseComponent[MAPPERS_INFO].childFactory,
    )
  }

  return createComponentFromMappers([mapper], createEagerFactory(BaseComponent))
}
<commit_msg>chore: remove a useless lifecycle hook<commit_after>/* eslint-disable no-console */
import { Component } from 'react'
import createBehaviorSubject from './createBehaviorSubject'
import createSymbol from './createSymbol'
import asyncThrow from './asyncThrow'
import createEagerFactory from '../createEagerFactory'
import { getConfig } from '../setConfig'
import { config as obsConfig } from '../setObservableConfig'

const MAPPERS_INFO = createSymbol('mappersInfo')
const observablePropType = () => {}

const createComponentFromMappers = (mappers, childFactory) => {
  const { observablesKey: OBSERVABLES } = getConfig()
  const CONTEXT_TYPES = { [OBSERVABLES]: observablePropType }

  return class extends Component {
    static [MAPPERS_INFO] = { mappers, childFactory }
    static contextTypes = CONTEXT_TYPES
    static childContextTypes = CONTEXT_TYPES

    props$ = createBehaviorSubject(this.props)

    componentWillMount() {
      let childProps$ = this.props$
      let childObservables = this.context[OBSERVABLES]
      for (let i = 0; i < mappers.length; i += 1) {
        ;[childProps$, childObservables] = mappers[i](
          childProps$,
          childObservables,
        )
      }

      this.childPropsSubscription = obsConfig
        .toESObservable(childProps$)
        .subscribe({
          next: childProps => {
            this.setState({ childProps })
          },
          error: error => {
            asyncThrow(error)
            this.setState({
              childProps: this.state ? this.state.childProps : {},
            })
          },
        })

      this.childContext = { [OBSERVABLES]: childObservables }
    }

    getChildContext() {
      return this.childContext
    }

    componentWillReceiveProps(nextProps) {
      this.props$.next(nextProps)
    }

    componentWillUnmount() {
      this.childPropsSubscription.unsubscribe()
    }

    shouldComponentUpdate(nextProps, nextState) {
      return (
        nextState &&
        (!this.state || this.state.childProps !== nextState.childProps)
      )
    }

    render() {
      if (!this.state) {
        return null
      }

      return this.constructor[MAPPERS_INFO].childFactory(this.state.childProps)
    }
  }
}

export const isMapperComponent = BaseComponent =>
  typeof BaseComponent === 'function' && BaseComponent[MAPPERS_INFO]

export default mapper => BaseComponent => {
  if (isMapperComponent(BaseComponent)) {
    return createComponentFromMappers(
      [mapper, ...BaseComponent[MAPPERS_INFO].mappers],
      BaseComponent[MAPPERS_INFO].childFactory,
    )
  }

  return createComponentFromMappers([mapper], createEagerFactory(BaseComponent))
}
<|endoftext|>


<commit_before>const del = require('del');
const fs = require('fs-extra');
const uppercamelcase = require('uppercamelcase');

const iconsSrcFolder = 'node_modules/feather-icons/icons';
const iconsDestFolder = 'src/lib/feather';
const indexFile = 'src/lib/index.ts';

const componentTemplate = fs.readFileSync('src/templates/component.ts.tpl', 'utf-8');

return Promise.resolve()
  // delete feather folder and index
  .then(() => del([iconsDestFolder, indexFile]))
  // create destination folder
  .then(() => fs.mkdirSync(iconsDestFolder))
  .then(() => {
    fs.readdirSync(iconsSrcFolder).forEach(category => {
      'use strict';

      fs.mkdirSync(`${iconsDestFolder}/${category}`);

      fs.readdirSync(`${iconsSrcFolder}/${category}`).forEach(filename => {
        'use strict';
        const name = stripExtension(filename);
        const componentName = `Icon${uppercamelcase(name)}Component`;
        const moduleName = `Icon${uppercamelcase(name)}`;

        let output = componentTemplate
          .replace(/__NAME__/g, name)
          .replace(/__CATEGORY__/g, category)
          .replace(/__COMPONENT_NAME__/g, componentName)
          .replace(/__MODULE_NAME__/, moduleName);

        fs.writeFileSync(`${iconsDestFolder}/${category}/${name}.ts`, output, 'utf-8');

        fs.appendFileSync(
          indexFile,
          `export { ${moduleName}, ${componentName} } from './feather/${category}/${name}';\n`
        );
      });

      fs.appendFileSync(indexFile, `\n`);
    });
  })
  .catch((err) => console.log(err));

function stripExtension(str) {
  return str.substr(0, str.lastIndexOf('.'));
}
<commit_msg>chore(scripts): remove generation script<commit_after><|endoftext|>


<commit_before>function log(msg) {
  var msg_str = (typeof(msg) == 'object') ? JSON.stringify(msg) : msg;
  console.log(msg_str);

  var l = document.getElementById('log');
  if (l) {
    l.innerText += msg_str + '\n';
  }
}

function updateHeartRate(value) {
  document.getElementById('graph').contentWindow.postMessage(
      {heartrate: value}, '*');
}

var kUUID = '00001101-0000-1000-8000-00805f9b34fb';
var readIntervalId;
var readInterval = function (socket) {
  return function() {
    chrome.bluetooth.read({socket: {id: socket.id}}, function(data) {
      if (chrome.apps.lastError) {
        log('Read error:');
        log(chrome.runtime.lastError);
        window.clearInterval(readIntervalId);
      } else {
        // Data parsing is based on the code in the openzephyr library:
        // http://code.google.com/p/zephyropen/source/browse/zephyropen/src/zephyropen/device/zephyr/ZephyrUtils.java
        if (data) {
          if ((data.byteLength % 60) != 0) {
            log('Payload is wrong size (' + data.byteLength +
                ').  Discarding.');
            return;
          }

          var offset = 0;
          while (offset + 60 <= data.byteLength) {
            var data_view = new Uint8Array(data, offset);
            offset += 60;

            if (data_view[0] != 2) {
              log('Check failed data[0] = ' + data_view[0]);
              continue;
            }

            if (data_view[1] != 38) {
              log('Check failed data[1] = ' + data_view[1]);
              continue;
            }

            if (data_view[2] != 55) {
              log('Check failed data[2] = ' + data_view[2]);
              continue;
            }

            if (data_view[59] != 3) {
              log('Check failed data[59] = ' + data_view[59]);
              continue;
            }

            var heartrate = data_view[12];
            if (heartrate < 30 || heartrate > 240) {
              log('Heartrate out of range (' + heartrate + ').  Discarding.');
              return;
            }

            updateHeartRate(heartrate);
            log('HR=' + heartrate);
          }
        }
      }
    });
  }
}

function startReads(socket) {
  log('Starting reads');
  readIntervalId = window.setInterval(readInterval(socket), 1000);
}

var socketId_;
var connectCallback = function(socket) {
  if (socket) {
    log('Connected!  Socket ID is: ' + socket.id + ' on service ' +
        socket.serviceUuid);
    startReads(socket);
    socketId_ = socket.id;
  } else {
    log('Failed to connect.');
  }
};

var connectToDevice = function(result) {
  if (chrome.runtime.lastError) {
    log('Error searching for a device to connect to.');
    return;
  }
  if (result.length == 0) {
    log('No devices found to connect to.');
    return;
  }
  for (var i in result) {
    var device = result[i];
    if (device.name == 'HXM014782') {
      log('Connecting to device: ' + device.name + ' @ ' + device.address);
      chrome.bluetooth.connect(
          {device: {address: device.address}, profile: {uuid: kUUID}}, connectCallback);
    }
  }
};

log('Starting Zephyr HXM demo...');

var kSimulate = false;
if (kSimulate) {
  window.setInterval(function() {
    updateHeartRate(60 + Math.floor((Math.random()*10)+1));
  }, 1000);
} else {
  var devicesFound = [];
  chrome.bluetooth.getDevices({
      profile: {uuid: kUUID},
      deviceCallback: function(device) { devicesFound.push(device); }
    }, function() {
      connectToDevice(devicesFound);
    });
  }

document.getElementById('close').addEventListener('click',
    function() {
      if (!kSimulate) {
        chrome.bluetooth.disconnect({socket: {id: socketId_}});
      }
      window.close();
    });
<commit_msg>Fix for hard coded serial number of device<commit_after>function log(msg) {
  var msg_str = (typeof(msg) == 'object') ? JSON.stringify(msg) : msg;
  console.log(msg_str);

  var l = document.getElementById('log');
  if (l) {
    l.innerText += msg_str + '\n';
  }
}

function updateHeartRate(value) {
  document.getElementById('graph').contentWindow.postMessage(
      {heartrate: value}, '*');
}

var kUUID = '00001101-0000-1000-8000-00805f9b34fb';
var readIntervalId;
var readInterval = function (socket) {
  return function() {
    chrome.bluetooth.read({socket: {id: socket.id}}, function(data) {
      if (chrome.apps.lastError) {
        log('Read error:');
        log(chrome.runtime.lastError);
        window.clearInterval(readIntervalId);
      } else {
        // Data parsing is based on the code in the openzephyr library:
        // http://code.google.com/p/zephyropen/source/browse/zephyropen/src/zephyropen/device/zephyr/ZephyrUtils.java
        if (data) {
          if ((data.byteLength % 60) != 0) {
            log('Payload is wrong size (' + data.byteLength +
                ').  Discarding.');
            return;
          }

          var offset = 0;
          while (offset + 60 <= data.byteLength) {
            var data_view = new Uint8Array(data, offset);
            offset += 60;

            if (data_view[0] != 2) {
              log('Check failed data[0] = ' + data_view[0]);
              continue;
            }

            if (data_view[1] != 38) {
              log('Check failed data[1] = ' + data_view[1]);
              continue;
            }

            if (data_view[2] != 55) {
              log('Check failed data[2] = ' + data_view[2]);
              continue;
            }

            if (data_view[59] != 3) {
              log('Check failed data[59] = ' + data_view[59]);
              continue;
            }

            var heartrate = data_view[12];
            if (heartrate < 30 || heartrate > 240) {
              log('Heartrate out of range (' + heartrate + ').  Discarding.');
              return;
            }

            updateHeartRate(heartrate);
            log('HR=' + heartrate);
          }
        }
      }
    });
  }
}

function startReads(socket) {
  log('Starting reads');
  readIntervalId = window.setInterval(readInterval(socket), 1000);
}

var socketId_;
var connectCallback = function(socket) {
  if (socket) {
    log('Connected!  Socket ID is: ' + socket.id + ' on service ' +
        socket.serviceUuid);
    startReads(socket);
    socketId_ = socket.id;
  } else {
    log('Failed to connect.');
  }
};

var connectToDevice = function(result) {
  if (chrome.runtime.lastError) {
    log('Error searching for a device to connect to.');
    return;
  }
  if (result.length == 0) {
    log('No devices found to connect to.');
    return;
  }
  for (var i in result) {
    var device = result[i];
    if (device.name.indexOf("HXM") === 0) {
      log('Connecting to device: ' + device.name + ' @ ' + device.address);
      chrome.bluetooth.connect(
          {device: {address: device.address}, profile: {uuid: kUUID}}, connectCallback);
    }
  }
};

log('Starting Zephyr HXM demo...');

var kSimulate = false;
if (kSimulate) {
  window.setInterval(function() {
    updateHeartRate(60 + Math.floor((Math.random()*10)+1));
  }, 1000);
} else {
  var devicesFound = [];
  chrome.bluetooth.getDevices({
      profile: {uuid: kUUID},
      deviceCallback: function(device) { devicesFound.push(device); }
    }, function() {
      connectToDevice(devicesFound);
    });
  }

document.getElementById('close').addEventListener('click',
    function() {
      if (!kSimulate) {
        chrome.bluetooth.disconnect({socket: {id: socketId_}});
      }
      window.close();
    });
<|endoftext|>


<commit_before>/*
Name:           geoip2ws
Description:    Maxmind GeoIP2 Web Services for Node.js
Source & docs:  https://github.com/fvdm/nodejs-geoip2ws
Feedback:       https://github.com/fvdm/nodejs-geoip2ws/issues
License:        Public Domain / Unlicense

This product includes GeoLite2 data created by MaxMind, available from
<http://www.maxmind.com>.
*/

var https = require('https')

// setup
var app = {
  userId: null,
  licenseKey: null,
  service: 'city',
  requestTimeout: 5000
}

module.exports = function( userId, licenseKey, service, requestTimeout ) {
  if( userId === undefined || licenseKey === undefined ) {
    return new Error('no userId or licenseKey')
  }

  app.userId = userId
  app.licenseKey = licenseKey

  if( typeof service === 'number' ) {
    app.requestTimeout = service
  } else {
    app.service = service || app.service
    app.requestTimeout = requestTimeout || app.requestTimeout
  }

  return function( service, ip, callback ) {

    // service is optional
    if( service && ip && !callback ) {
      var callback = ip
      var ip = service
      var service = app.service
    }

    // prevent multiple callbacks
    var complete = false
    function doCallback( err, res ) {
      if( ! complete ) {
        complete = true
        callback( err, res )
      }
    }

    // build request
    var options = {
      hostname: 'geoip.maxmind.com',
      path: '/geoip/v2.1/'+ service +'/'+ ip,
      agent: false,
      headers: {
        'Accept': 'application/json',
        'User-Agent': 'geoip2ws.js'
      },
      auth: app.userId +':'+ app.licenseKey
    }

    var request = https.request( options )

    // request response
    request.on( 'response', function( response ) {
      var data = []
      var size = 0
      var err = null

      // collect data
      response.on( 'data', function( chunk ) {
        data.push( chunk )
        size += chunk.length
      })

      // process data
      response.on( 'end', function() {
        if( data.length >= 1 ) {
          var buf = new Buffer( size )
          var pos = 0

          for( var i=0; i<data.length; i++ ) {
            data[i].copy( buf, pos )
            pos += data[i].length
          }

          data = data.toString('utf8').trim()

          try {
            data = JSON.parse( data )

            if( data.error !== undefined ) {
              err = new Error('API error')
              err.code = data.code
              err.error = data.error
            }
          } catch(e) {
            err = new Error('not json')
          }
        } else {
          err = new Error('no data')
        }

        doCallback( err, data )
      })

      // connection dropped
      response.on( 'close', function() {
        doCallback( new Error('request dropped') )
      })
    })

    request.on( 'socket', function( socket ) {
      if( app.requestTimeout ) {
        socket.setTimeout( app.requestTimeout )
        socket.on( 'timeout', function() {
          doCallback( new Error('request timeout') )
          request.abort()
        })
      }
    })

    // request error
    request.on( 'error', function( error ) {
      var err = new Error('request failed')
      err.error = error
      doCallback( err )
    })

    // request finished
    request.end()
  }
}
<commit_msg>Replaced Buffer loop with Buffer.concat()<commit_after>/*
Name:           geoip2ws
Description:    Maxmind GeoIP2 Web Services for Node.js
Source & docs:  https://github.com/fvdm/nodejs-geoip2ws
Feedback:       https://github.com/fvdm/nodejs-geoip2ws/issues
License:        Public Domain / Unlicense

This product includes GeoLite2 data created by MaxMind, available from
<http://www.maxmind.com>.
*/

var https = require('https')

// setup
var app = {
  userId: null,
  licenseKey: null,
  service: 'city',
  requestTimeout: 5000
}

module.exports = function( userId, licenseKey, service, requestTimeout ) {
  if( userId === undefined || licenseKey === undefined ) {
    return new Error('no userId or licenseKey')
  }

  app.userId = userId
  app.licenseKey = licenseKey

  if( typeof service === 'number' ) {
    app.requestTimeout = service
  } else {
    app.service = service || app.service
    app.requestTimeout = requestTimeout || app.requestTimeout
  }

  return function( service, ip, callback ) {

    // service is optional
    if( service && ip && !callback ) {
      var callback = ip
      var ip = service
      var service = app.service
    }

    // prevent multiple callbacks
    var complete = false
    function doCallback( err, res ) {
      if( ! complete ) {
        complete = true
        callback( err, res )
      }
    }

    // build request
    var options = {
      hostname: 'geoip.maxmind.com',
      path: '/geoip/v2.1/'+ service +'/'+ ip,
      agent: false,
      headers: {
        'Accept': 'application/json',
        'User-Agent': 'geoip2ws.js'
      },
      auth: app.userId +':'+ app.licenseKey
    }

    var request = https.request( options )

    // request response
    request.on( 'response', function( response ) {
      var data = []
      var size = 0
      var err = null

      // collect data
      response.on( 'data', function( chunk ) {
        data.push( chunk )
        size += chunk.length
      })

      // process data
      response.on( 'end', function() {
        if( data.length >= 1 ) {
          data = new Buffer.concat( data, size )
          data = data.toString('utf8').trim()

          try {
            data = JSON.parse( data )

            if( data.error !== undefined ) {
              err = new Error('API error')
              err.code = data.code
              err.error = data.error
            }
          } catch(e) {
            err = new Error('not json')
          }
        } else {
          err = new Error('no data')
        }

        doCallback( err, data )
      })

      // connection dropped
      response.on( 'close', function() {
        doCallback( new Error('request dropped') )
      })
    })

    request.on( 'socket', function( socket ) {
      if( app.requestTimeout ) {
        socket.setTimeout( app.requestTimeout )
        socket.on( 'timeout', function() {
          doCallback( new Error('request timeout') )
          request.abort()
        })
      }
    })

    // request error
    request.on( 'error', function( error ) {
      var err = new Error('request failed')
      err.error = error
      doCallback( err )
    })

    // request finished
    request.end()
  }
}
<|endoftext|>


<commit_before>
(function(window){

  var EventTypeProto = window.EventTarget.prototype ;
  EventTypeProto.off = function(eventName, callback, useCapture){
    return this.removeEventListener( eventName, callback, useCapture );
  };
  EventTypeProto.on = function(eventName, callback, useCapture){
    this.addEventListener( eventName, callback, useCapture );
    return EventTypeProto.off.bind( this, eventName, callback, useCapture );
  };
  EventTypeProto.one = function(eventName, callback, useCapture, times){
    if( !times ) times = 1;
    else if( times < 1 ) return function(){};
    var _retirar = null;
    var _func = function(){
      callback();
      if( !--times ) _retirar();
    };
    _retirar = EventTypeProto.off.bind( this, eventName, _func, useCapture );
    this.addEventListener( eventName, _func, useCapture );
    return _retirar;
  };

  var ElementProto = window.Element.prototype;
  ElementProto.find = function( str ){
    var nodeList = this.querySelectorAll(str);
    var arr = [];
    for(var i = 0; i < nodeList.length; i++) arr.push( nodeList[i] );
    return $( arr );
  };

  var $ = function( param ){
    if( !(this instanceof $) ) return new $( param );
    if( param instanceof $ ) return param ;
    if( typeof param === 'string' ) return ElementProto.find.call( document, param );
    if( typeof param === 'undefined' ) param = [];
    if( !(param instanceof Array) ) param = [ param ] ;

    //this.array = param;
    for( var g in param ) this.push( param[g] );
    if( !this.length ) this.length = 0;

    _defineProperty( this, 'length', 5 );
    return this;
  };
  var proto = ($.prototype = new Array()) ;
  proto.on = function(eventName, callback, useCapture){
    _forEachApply( this, EventTypeProto.on, [ eventName, callback, useCapture ] );
    return this;
  };
  proto.off = function(eventName, callback, useCapture){
    _forEachApply( this, EventTypeProto.off, [ eventName, callback, useCapture ] );
    return this;
  };
  proto.one = function(eventName, callback, useCapture, times){
    _forEachApply( this, EventTypeProto.one, [ eventName, callback, useCapture, times ] );
    return this;
  };
  proto.find = function( str ){
    var res = _forEachApply( this, ElementProto.find, [str] );
    var obj = $();
    for(var i = 0; i < res.length; i++){
      var resI = res[i];
      for(var j = 0; j < resI.length; j++){
        obj.push( resI[j] );
      }
    }
    return obj;
  };

  _defineProperty( proto, 'on', 5 );
  _defineProperty( proto, 'off', 5 );
  _defineProperty( proto, 'one', 5 );
  _defineProperty( proto, 'find', 5 );

  if( !window.$ ) window.$ = $;
  if( !window.$$ ) window.$$ = $;

  //---------------------------
  function _forEachApply( arr, func, arrApply ){
    var ret = [];
    for(var i = 0; i < arr.length; i++) ret.push( func.apply( arr[i], arrApply ) );
    return ret;
  }
  function _defineProperty( obj, prop, intConf, conf ){
    //if( !conf ) conf = {};
    if( !intConf ) intConf = 0;

    Object.defineProperty( obj, prop, {
      configurable: !!(1&intConf),
      enumerable: !!(2&intConf),
      writable: !!(4&intConf),
      iterable: !!(8&intConf),
      //value: conf.value,
      //get: conf.get,
      //set: conf.set
    });
  }

})(window);
<commit_msg>Add funções do jquery a lista de funções (ainda faltam várias!).<commit_after>
(function (window) {

  var undefined; // "undefined", deixar essa var sem valor !!!

  //===========================================================================
  //          EventTarget prototype

  var EventTypeProto = window.EventTarget.prototype;
  EventTypeProto.off = function (eventName, callback, useCapture) {
    return this.removeEventListener(eventName, callback, useCapture);
  };
  EventTypeProto.on = function (eventName, callback, useCapture) {
    this.addEventListener(eventName, callback, useCapture);
    var that = this;
    return function () {
      EventTypeProto.off.call(that, eventName, callback, useCapture);
    };
  };
  EventTypeProto.one = function (eventName, callback, useCapture, times) {
    if (!times)
      times = 1;
    else if (times < 1)
      return function () {};
    var _retirar = null;
    var _func = function () {
      callback();
      if (!--times)
        _retirar();
    };
    _retirar = EventTypeProto.off.bind(this, eventName, _func, useCapture);
    this.addEventListener(eventName, _func, useCapture);
    return _retirar;
  };

  EventTypeProto.bind = EventTypeProto.on;

  //===========================================================================
  //          Element prototype

  var ElementProto = window.Element.prototype;
  ElementProto.find = function (str) {
    var nodeList = this.querySelectorAll(str), len = nodeList.length;
    var arr = [];
    for (var i = 0; i < len; i++)
      arr.push(nodeList[i]);
    return $(arr);
  };
  if ('classList' in ElementProto) {
    ElementProto.hasClass = function () {
      return this.classList.contains( arguments );
    };
    ElementProto.addClass = function () {
      this.classList.add( arguments );
      return this;
    };
    ElementProto.removeClass = function () {
      this.classList.remove( arguments );
      return this;
    };
  } else {
    ElementProto.hasClass = function (str) {
      return new RegExp('\\b' + str + '\\b').test(this.className);
    };
    ElementProto.addClass = function () {
      var i = arguments.length, str;
      while( i-- ){
        str = arguments[i];
        if( !this.hasClass(str) ) this.className += ' ' + str;
      }
      return this;
    };
    ElementProto.removeClass = function (str) {
      var i = arguments.length, str;
      while( i-- ){
        str = arguments[i];
        this.className = this.className.replace(new RegExp('\\b'+ str+'\\b', 'g'), '');
      }
      return this;
    };
  }
  ElementProto.toggleClass = function (str) {
    if (this.hasClass(str))
      this.removeClass(str);
    else
      this.addClass(str);
    return this;
  };
  ElementProto.text = function (str){
    if( str === undefined ) return this.textContent;
    this.textContent = str;
    return this;
  };
  ElementProto.empty = function(){
    while(this.hasChildNodes()) {
      this.removeChild(this.firstChild);
    }
    return this;
  };
  ElementProto.html = function (str){
    if( str === undefined ) return this.innerHTML;
    this.innerHTML = str;
    return this;
  };
  ElementProto.attr = function( str, val ){
    if( str instanceof Object ){
      for( var g in str ){
        this.setAttribute( g, str[g] );
      }
      return this;
    }
    if( val === undefined ) return this.getAttribute( str );
    this.setAttribute( str, val );
    return this;
  };

  //===========================================================================
  //          $ function

  var $ = function (param) {
    if (!(this instanceof $))
      return new $(param);
    if (param instanceof $)
      return param;
    if (typeof param === 'string')
      return ElementProto.find.call(document, param);
    if (typeof param === 'undefined')
      param = [];
    if (!(param instanceof Array))
      param = [param];

    for (var g in param)
      this.push(param[g]);
    if (!this.length)
      this.length = 0;

    _defineProperty(this, 'length', 5);
    return this;
  };
  var proto = ($.prototype = new Array());

  var funcs = [
      'bind',
      'on',
      'off',
      'one',
      'find',
      'hasClass',
      'addClass',
      'removeClass',
      'toggleClass',
      'text',
      'empty',
      'attr'
    ], funcsI = funcs.length;

    // comportamento padrão;
  while( funcsI-- ){
     _normalElementCall(proto, funcs[funcsI]);
  }

    //  Sobreescrever as funções que precisam de comportamento 'especial':

  proto.find = function (str) {
    var res = _forEachApply(this, ElementProto.find, [str]);
    var obj = $(), len = res.length;
    for (var i = 0; i < len; i++) {
      var resI = res[i], lenI = resI.length;
      for (var j = 0; j < lenI; j++) {
        obj.push(resI[j]);
      }
    }
    return obj;
  };
  proto.hasClass = function(){
    var res = _forEachApply(this, ElementProto.hasClass, arguments), i = res.length;
    while( i-- ) if( !res[i] ) return false;
    return true;
  };
  proto.text = function(){
    var res = _forEachApply(this, ElementProto.text, arguments);
  };

    // bloquear a iteração desses elementos:
  funcsI = funcs.length;
  while( funcsI-- ){
    _defineProperty(proto, 5, funcs[funcsI]);
  }

  //===========================================================================
  //    Funções auxiliares

  function _normalElementCall(proto, funcName){
    proto[funcName] = function(){
      _forEachApply(this, ElementProto[funcName], arguments);
      return this;
    };
  }
  function _forEachApply(arr, func, arrApply) {
    var ret = [], len = arr.length;
    for (var i = 0; i < len; i++)
      ret.push(func.apply(arr[i], arrApply));
    return ret;
  }
  function _defineProperty(obj, intConf, prop ) {
    if (!intConf)
      intConf = 0;

    Object.defineProperty(obj, prop, {
      configurable: !!(1 & intConf),
      enumerable: !!(2 & intConf),
      writable: !!(4 & intConf),
      iterable: !!(8 & intConf)
        //value: conf.value,
        //get: conf.get,
        //set: conf.set
    });
  }

  //===========================================================================
  //    Publicando funções

  if (!window.$)
    window.$ = $;
  if (!window.$$)
    window.$$ = $;

})(window);
<|endoftext|>