Added all the good math stuff to Elyssa.Vector

Like cross product, dot product, normalize, etc.

--- src/types/vector.coffee
+++ src/types/vector.coffee
@@ -1,11 +1,48 @@
 do (window = @, Elyssa = @Elyssa or= {}) ->

   class Elyssa.Vector
-    constructor: ({@x, @y, @z} = {x: 0, y: 0, z: 0}) ->
-      @x = 0 unless @x?
-      @y = 0 unless @y?
-      @z = 0 unless @z?
+    defaultValue =
+      x: 0
+      y: 0
+      z: 0
+
+    constructor: ({@x, @y, @z} = defaultValue) ->
+      @x = defaultValue.x unless @x?
+      @y = defaultValue.y unless @y?
+      @z = defaultValue.z unless @z?

     toRect: -> new Elyssa.Rect {@x, @y, w: 0, h: 0}

-    toString: -> JSON.stringify {@x, @y, @z}+    toString: -> JSON.stringify {@x, @y, @z}
+
+    normalize: ->
+      new Elyssa.Vector
+        x: @x / @length
+        y: @y / @length
+        z: @z / @length
+
+    @property 'length',
+      get: -> window.Math.sqrt(@x * @x + @y * @y + @z * @z)
+
+    @crossProduct: (a, b) ->
+      new Elyssa.Vector
+        x: a.y * b.z - b.y * a.z
+        y: a.z * b.x - b.z * a.x
+        z: a.x * b.y - b.x * a.y
+
+    @dotProduct: (a, b) -> a.x * b.x + a.y * b.y + a.z * b.z
+
+    @normalize: (vec) ->
+      new Elyssa.Vector
+        x: vec.x / vec.length
+        y: vec.y / vec.length
+        z: vec.z / vec.length
+
+    @up: -> new Elyssa.Vector {x: 0, y: 1, z: 0}
+    @zero: -> new Elyssa.Vector {x: 0, y: 0, Z: 0}
+    @one: -> new Elyssa.Vector {x: 1, y: 1, z: 1}
+    @right: -> new Elyssa.Vector {x: 1, y: 0, z: 0}
+
+    toString: -> Elyssa.serialize {@x, @y, @z}, defaultValue
+
+    @fromString: (string) -> Elyssa.deserialize string, 'Vector'


Client: Sidebar: Added setCoordinates method to calculate invitationWidget coordinates by related machineListItem

--- client/app/lib/components/sidebarmachineslistitem/sharingmachineinvitationwidget.coffee
+++ client/app/lib/components/sidebarmachineslistitem/sharingmachineinvitationwidget.coffee
@@ -16,6 +16,18 @@
   onAcceptClicked: ->

     actions.acceptInvitation @props.machine
+
+
+  setCoordinates: ->
+
+    listItemNode = ReactDOM.findDOMNode @props.listItem
+
+    if listItemNode
+      clientRect    = listItemNode.getBoundingClientRect()
+      { top, left, width } = clientRect
+      left = left + width
+      top  = top - 15
+      @coordinates = { top, left }

   render: ->


Turn off the actual spinning of icon-spin jquery plugin, since it uses a LOT of CPU.

--- salvus/page/misc_page.coffee
+++ salvus/page/misc_page.coffee
@@ -174,8 +174,8 @@
         elt = $(this)
         if start
             f = () ->
-                if elt.find("i.icon-spinner").length == 0
-                    elt.append("<i class='icon-spin icon-spinner' style='margin-left:1em'> </i>")
+                if elt.find("i.icon-spinner").length == 0  # icon-spin
+                    elt.append("<i class=' icon-spinner' style='margin-left:1em'> </i>")
             if delay
                 elt.data('icon-spin', setTimeout(f, delay))
             else


minor refactoring

minor refactoring

--- tail.coffee
+++ tail.coffee
@@ -29,11 +29,7 @@
     stats =  fs.statSync(@filename)
     @internalDispatcher.on 'next',=>
       @readBlock()
-    if @frombeginning
-      @pos = 0
-      @watchEvent('change')
-    else
-      @pos = stats.size
+    @pos = if @frombeginning then 0 else stats.size
     @watch()


Center editor grid on resize

Center editor grid on resize

--- src/views/editor.coffee
+++ src/views/editor.coffee
@@ -33,8 +33,6 @@
   gridSize: 10

   initialize: ->
-    # Ensure 'this' has correct context
-    #_.bindAll @, 'onPointStart', 'onPointMove', 'onPointEnd', 'fillBlock', 'checkCompleted', 'win', 'pause', 'changePoint', 'updateTimer', 'showTutorial', 'resize', 'hide', 'show'
     _.bindAll(@, 'onPointStart', 'onPointMove', 'onPointEnd')

     # View is initialized hidden
@@ -103,7 +101,7 @@
     col = Math.floor((position.x - @grid.offset().left) / @blockSize)

     # Only recognize movement if within grid bounds
-    if 0 <= row <= 9 and 0 <= col <= 9
+    if 0 <= row < @MAX_GRID_SIZE and 0 <= col < @MAX_GRID_SIZE
       @fillBlock(row, col) if row != @previousRow or col != @previousCol

       @previousRow = row
@@ -119,8 +117,7 @@
     @previousRow = @previousCol = null

   fillBlock: (row, col) ->
-    index = row * 10 + col
-
+    index = row * @gridSize + col
     block = @grid.find('div').eq(index)

     if block.hasClass('filled') is true
@@ -131,26 +128,34 @@
       block.addClass 'filled'

   resize: (width, height, orientation) ->
+    # TODO: lots of duplication here, refactor!
+    # TODO: rename @gridSize; it's the # of cells in the grid, whereas
+    # @blockSize is an actual pixel size
     if orientation is 'landscape'
-      gridWidth = Math.round(height * 0.97 / 10) * 10   # Make sure grid background size is 97% of viewport
-      @grid.width gridWidth
-      @grid.height gridWidth
+      maxGridSize = Math.round(height * 0.97 / 10) * 10   # Make sure grid background size is 97% of viewport
+      @blockSize = maxGridSize / 10
+      @grid.width(@gridSize * @blockSize)
+      @grid.height(@gridSize * @blockSize)

       # Add some margin to the grid, so it appears centered
-      margin = (height - gridWidth - 10) / 2
-      @grid.css
-        'margin': "#{margin}px 0"
+      horizontalMargin = (height - @grid.width() - 10) / 2
+      verticalMargin = (maxGridSize - @grid.height()) / 2

     else if orientation is 'portrait'
-      gridWidth = Math.round(width * 0.97 / 10) * 10  # grid size is 97% of viewport
-      @grid.width gridWidth
-      @grid.height gridWidth
+      maxGridSize = Math.round(width * 0.97 / 10) * 10  # grid size is 97% of viewport
+      @blockSize = maxGridSize / 10
+      @grid.width(@gridSize * @blockSize)
+      @grid.height(@gridSize * @blockSize)

       # Add some margin to the grid, so it appears centered
-      margin = (width - gridWidth - 10) / 2
-      @grid.css
-        'margin': "0 #{margin}px"
+      verticalMargin = (width - @grid.height() - 10) / 2
+      horizontalMargin = (maxGridSize - @grid.width()) / 2
+
+    @grid.css
+      margin: "#{horizontalMargin}px #{verticalMargin}px"

-    @blockSize = gridWidth / 10
+    @grid.children('div').css
+      width: @blockSize
+      height: @blockSize

 module.exports = EditorScene


Fix weight a little

Fix weight a little

--- baby-connect.coffee
+++ baby-connect.coffee
@@ -293,7 +293,7 @@
   db = new sqlite3.Database(DB_FILE)
   p = q.defer()
   db.run('INSERT INTO data (startTime, endTime, activity, quantity, label, notes) VALUES (?, ?, ?, ?, ?, ?)',
-    [params.time.toDate(), params.endTime.toDate(), 'Weight', params.weight, params.text || params.body, params.body], () =>
+    [params.time.toDate(), params.time.toDate(), 'Weight', params.weight, params.text || params.body, params.body], () =>
       db.close()
       p.resolve(logStatus(formData))
   )


Snippets are not auto-indented when they are inserted.

--- src/extensions/snippets/snippet-expansion.coffee
+++ src/extensions/snippets/snippet-expansion.coffee
@@ -6,7 +6,7 @@
     @editSession.selectToBeginningOfWord()
     startPosition = @editSession.getCursorBufferPosition()
     @editSession.transact =>
-      @editSession.insertText(snippet.body)
+      @editSession.insertText(snippet.body, autoIndent: false)
       if snippet.tabStops.length
         @placeTabStopAnchorRanges(startPosition, snippet.tabStops)
       if snippet.lineCount > 1


fixed normalError

fixed normalError

--- lib/errors.coffee
+++ lib/errors.coffee
@@ -20,6 +20,7 @@
   this.name = 'NormalError'

 util.inherits ArgumentError, restify.RestError
+util.inherits NormalError, restify.RestError

 module.exports = errors =
   # 资源不存在错误，有以下几种情况需要返回此错误


More explicit window context in src/browser.coffee.

--- browser.coffee
+++ browser.coffee
@@ -35,7 +35,7 @@
   xhr = if window.ActiveXObject
     new window.ActiveXObject('Microsoft.XMLHTTP')
   else
-    new XMLHttpRequest()
+    new window.XMLHttpRequest()
   xhr.open 'GET', url, true
   xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
   xhr.onreadystatechange = ->
@@ -51,7 +51,7 @@
 # all script tags with a content-type of `text/coffeescript`.
 # This happens on page load.
 runScripts = ->
-  scripts = document.getElementsByTagName 'script'
+  scripts = window.document.getElementsByTagName 'script'
   coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']
   coffees = (s for s in scripts when s.type in coffeetypes)
   index = 0
@@ -71,6 +71,6 @@

 # Listen for window load, both in decent browsers and in IE.
 if window.addEventListener
-  addEventListener 'DOMContentLoaded', runScripts, no
+  window.addEventListener 'DOMContentLoaded', runScripts, no
 else
-  attachEvent 'onload', runScripts
+  window.attachEvent 'onload', runScripts


Grammar : allow incomplete data definition

Idris type checker accepts incomplete data definitions (`data X`) as a hole.

--- grammars/language-idris.cson
+++ grammars/language-idris.cson
@@ -151,7 +151,7 @@
           name: 'entity.name.type.idris'
         3:
           name: 'keyword.operator.colon.idris'
-      end: '\\b(where)\\b|(=)'
+      end: '\\b(where)\\b|(=)|$'
       endCaptures:
         1:
           name: 'keyword.other.idris'


update includes on save

update includes on save

--- src/cs-resource/cs-resource.js.coffee
+++ src/cs-resource/cs-resource.js.coffee
@@ -178,8 +178,13 @@
         (data) =>  # successCallback
           object = @.$assign(data.data)
           included = _.map data.included, (i) =>
-            resource = ResourceService.get(i.type)
-            return new resource(i, datastore: object.$datastore)
+            assoc = object.$datastore.get(i.type, i.id)
+            if assoc
+              assoc.$assign(i)
+              return assoc
+            else
+              resource = ResourceService.get(i.type)
+              return new resource(i, datastore: object.$datastore)
           return object
         (reason) => # errorCallback
           return $q.reject(reason);


export default async funcion

export default async funcion

--- snippets/basic.cson
+++ snippets/basic.cson
@@ -6,6 +6,14 @@
     'prefix': 'func'
     'body': """
       export default function ($1) {
+        $2
+      }
+
+    """
+  'Export async default function':
+    'prefix': 'afunc'
+    'body': """
+      export default async function ($1) {
         $2
       }


Add offset parameter to :visible

Add offset parameter to :visible

--- src/commands/Selector.coffee
+++ src/commands/Selector.coffee
@@ -443,7 +443,13 @@

   getIndexPrefix: (operation, parent)->
     return parent && ' ' || ''
-
+
+Selector.Pseudo = Selector.Combinator.extend
+  signature: [[
+    context: ['Selector']
+    query: ['String', 'Number']
+  ]]
+
 Selector.Virtual = Selector.extend
   signature: [
     [context: ['Selector']]
@@ -791,20 +797,20 @@
   ':visible':
     singular: true
     deferred: true
-    Combinator: (node = scope, engine, operation, continuation, scope) ->
-      return Selector[':visible-y']::Combinator.apply(@, arguments) &&
-             Selector[':visible-x']::Combinator.apply(@, arguments)
+    Pseudo: (node, offset, engine, operation, continuation, scope) ->
+      return Selector[':visible-y']::Pseudo.apply(@, arguments) &&
+             Selector[':visible-x']::Pseudo.apply(@, arguments)

   ':visible-y':
     singular: true
     deferred: true
-    Combinator: (node = scope, engine, operation, continuation, scope) ->
+    Pseudo: (node = scope, offset, engine, operation, continuation, scope) ->
+      property = engine.scope.nodeType == 1 && 'computed-height' || 'height'
       ey = engine.data.watch(node,         'computed-y',      operation, continuation, scope)
       eh = engine.data.watch(node,         'computed-height', operation, continuation, scope)
-      sy = engine.data.watch(engine.scope, 'scroll-top',      operation, continuation, scope)
-
-      sh = engine.data.watch(engine.scope, "#{engine.scope.nodeType == 1 && 'computed-' || ''}height", operation, continuation, scope)
-
+      sy = engine.data.watch(engine.scope, 'scroll-top',      operation, continuation, scope) - (offset || 0)
+      sh = engine.data.watch(engine.scope, property,          operation, continuation, scope) + (offset || 0) * 2
+
       if (ey <= sy && ey + eh > sy + sh)  || # mid
          (ey > sy && ey < sy + sh)        || # top
          (ey + eh > sy && ey + eh < sy + sh) # bottom
@@ -813,15 +819,16 @@
   ':visible-x':
     singular: true
     deferred: true
-    Combinator: (node = scope, engine, operation, continuation, scope) ->
+    Pseudo: (node = scope, offset, engine, operation, continuation, scope) ->
+      property = engine.scope.nodeType == 1 && 'computed-width' || 'width'
       ex = engine.data.watch(node,         'computed-x',     operation, continuation, scope)
       ew = engine.data.watch(node,         'computed-width', operation, continuation, scope)
-      sx = engine.data.watch(engine.scope, 'scroll-left',    operation, continuation, scope)
-      sw = engine.data.watch(engine.scope, "#{engine.scope.nodeType == 1 && 'computed-' || ''}height", operation, continuation, scope)
+      sx = engine.data.watch(engine.scope, 'scroll-left',    operation, continuation, scope) - (offset || 0)
+      sw = engine.data.watch(engine.scope, property,         operation, continuation, scope) + (offset || 0)

       if (ex <= sx && ex + ew > sx + sw)  || # mid
          (ex > sx && ex < sx + sw)        || # left
-         (ex + ew > sx && ex < sx + sw)      # right
+         (ex + ew > sx && ex + ew < sx + sw) # right
         return node


Don't pluralize controller / collection by default.

--- src/commands/scaffold.coffee
+++ src/commands/scaffold.coffee
@@ -218,7 +218,10 @@

 module.exports = scaffold = (rollback, options, callback = (->)) ->
   {type, name, pluralName, parentDir, configPath} = options
-  pluralName = inflection.pluralize name, pluralName
+  pluralName = if type in ['controller', 'collection']
+    name
+  else
+    inflection.pluralize name, pluralName
   if name is pluralName
     if type in ['controller', 'collection', 'scaffold']
       name = inflection.singularize pluralName


Damn debugger call snuck in.

Damn debugger call snuck in.

--- client/entry.coffee
+++ client/entry.coffee
@@ -21,7 +21,6 @@
     unless Meteor.user() and extraCondition
       Router.go('/sign-in')
       Session.set('entryError', i18n('error.signInRequired'))
-      debugger
       router.stop()

 @AccountsEntry = AccountsEntry


Bug in test

Bug in test

--- test/unit/model/plan.coffee
+++ test/unit/model/plan.coffee
@@ -33,4 +33,5 @@
         form:
           path: 'fskjh33i'
           size: 8
+      correctArgs.should.be.true


Update name-expander.coffee

Update name-expander.coffee

--- scripts/name-expander.coffee
+++ scripts/name-expander.coffee
@@ -72,6 +72,8 @@
   "nmathrani"
 ]

+sysadmin = ["ehays", "fnenz2", "fnenz", "lbernat", "Stephen Couratier", "kying", "hvellanki", "bnessler"]
+
 module.exports = (robot) ->
   robot.hear /^(merlern|dert)( team| dudes| guys)*:(.+)/i, (msg) ->
     msg.send dert_mermbers.join(", ") + ": ^^"
@@ -102,3 +104,9 @@

   robot.hear /^(di|devinf)( team| dudes| guys)*:(.+)/i, (msg) ->
     msg.send devinf_members.join(", ") + ": ^^"
+
+  robot.hear /^@?(sysadmin)( team| dudes| guys)*(:| )(.+)/i, (msg) ->
+    msg.send sysadmin.join(", ") + ": ^^"
+
+  robot.hear /^@?(ops)( team| dudes| guys)*(:| )(.+)/i, (msg) ->
+    msg.send sysadmin.join(", ") + ": ^^"


Bug fix: $pop -> $pull

Bug fix: $pop -> $pull

--- client/group.coffee
+++ client/group.coffee
@@ -243,8 +243,8 @@
     if subscribedToMessage @_id
       Meteor.users.update Meteor.userId(),
         $push: 'profile.notifications.unsubscribed': @_id
-        $pop: 'profile.notifications.subscribed': @_id
+        $pull: 'profile.notifications.subscribed': @_id
     else
       Meteor.users.update Meteor.userId(),
         $push: 'profile.notifications.subscribed': @_id
-        $pop: 'profile.notifications.unsubscribed': @_id
+        $pull: 'profile.notifications.unsubscribed': @_id


bug: calling sync in render causes (slow) infinite loop

Was wondering why chrome was sucking 100% of cpu and traced it to this.
Unsure if it was needed or not, but removing it doesn't seem to affect
functionality


fix image width and height on inserted image, using correct values now

--- plugins/image.coffee
+++ plugins/image.coffee
@@ -239,14 +239,13 @@
                 # create image to be inserted
                 createInsertElement: (ui, tmp) ->
                     image = ui.draggable[0]
-                    src = image.src
-                    width = image.width
-                    height = image.height
+                    tmpImg = new Image()
+                    tmpImg.src = image.src
                     altText = image.alt
                     imageInsert = $("<img>").attr(
-                        src: src
-                        width: width
-                        height: height
+                        src: tmpImg.src
+                        width: tmpImg.width
+                        height: tmpImg.height
                         alt: altText
                         class: (if tmp then "tmp" else "")
                     ).css("display", "none")


Fixed #389 decorating a line when an inline form has no a delete checkbox

--- wzk/ui/inlineform/RowBuilder.coffee
+++ wzk/ui/inlineform/RowBuilder.coffee
@@ -70,8 +70,8 @@
   ###
   decorateRow: (row) ->
     removeIcon = @rowDecorator.addRemoveIcon(row)
-    return unless removeIcon?
-    removeIcon.listen goog.ui.Component.EventType.ACTION, @handleIconAction
+    if removeIcon?
+      removeIcon.listen(goog.ui.Component.EventType.ACTION, @handleIconAction)
     @reg.process row

   ###*


OHM-68: Fixed broken test

OHM-68: Fixed broken test

--- test/integration/auditAPITests.coffee
+++ test/integration/auditAPITests.coffee
@@ -16,64 +16,64 @@

     auditData =
       rawMessage:  'This will be the raw ATNA message that gets received to be used as a backup reference'
-      EventIdentification:
-        EventDateTime: '2015-02-20T15:38:25.282Z'
-        EventOutcomeIndicator: '0'
-        EventActionCode: 'E'
-        EventID:
+      eventIdentification:
+        eventDateTime: '2015-02-20T15:38:25.282Z'
+        eventOutcomeIndicator: '0'
+        eventActionCode: 'E'
+        eventID:
           code: '110112'
           displayName: 'Query'
           codeSystemName: 'DCM'
-        EventTypeCode:
+        eventTypeCode:
           code: 'ITI-9'
           displayName: 'PIX Query'
           codeSystemName: 'IHE Transactions'
-      ActiveParticipant:
+      activeParticipant:
         [
           {
-            UserID: 'pix|pix'
-            AlternativeUserID: '2100'
-            UserIsRequestor: 'false'
-            NetworkAccessPointID: 'localhost'
-            NetworkAccessPointTypeCode: '1'
-            RoleIDCode:
+            userID: 'pix|pix'
+            alternativeUserID: '2100'
+            userIsRequestor: 'false'
+            networkAccessPointID: 'localhost'
+            networkAccessPointTypeCode: '1'
+            roleIDCode:
               code: '110152'
               displayName: 'Destination'
               codeSystemName: 'DCM'
           }, {
-            UserID: 'pix|pix'
-            AlternativeUserID: '2100'
-            UserIsRequestor: 'false'
-            NetworkAccessPointID: 'localhost'
-            NetworkAccessPointTypeCode: '1'
-            RoleIDCode:
+            userID: 'pix|pix'
+            alternativeUserID: '2100'
+            userIsRequestor: 'false'
+            networkAccessPointID: 'localhost'
+            networkAccessPointTypeCode: '1'
+            roleIDCode:
               code: '110152'
               displayName: 'Destination'
               codeSystemName: 'DCM'
           }
         ]
-      AuditSourceIdentification:
-        AuditSourceID: 'openhim'
-      ParticipantObjectIdentification:
+      auditSourceIdentification:
+        auditSourceID: 'openhim'
+      participantObjectIdentification:
         [
           {
-            ParticipantObjectID: '975cac30-68e5-11e4-bf2a-04012ce65b02^^^ECID&ECID&ISO'
-            ParticipantObjectTypeCode: '1'
-            ParticipantObjectTypeCodeRole: '1'
-            ParticipantObjectIDTypeCode:
+            participantObjectID: '975cac30-68e5-11e4-bf2a-04012ce65b02^^^ECID&ECID&ISO'
+            participantObjectTypeCode: '1'
+            participantObjectTypeCodeRole: '1'
+            participantObjectIDTypeCode:
               code: '2'
               displayName: 'PatientNumber'
               codeSystemName: 'RFC-3881'
           }, {
-            ParticipantObjectID: 'dca6c09e-cc92-4bc5-8741-47bd938fa405'
-            ParticipantObjectTypeCode: '2'
-            ParticipantObjectTypeCodeRole: '24'
-            ParticipantObjectIDTypeCode:
+            participantObjectID: 'dca6c09e-cc92-4bc5-8741-47bd938fa405'
+            participantObjectTypeCode: '2'
+            participantObjectTypeCodeRole: '24'
+            participantObjectIDTypeCode:
               code: 'ITI-9'
               displayName: 'PIX Query'
               codeSystemName: 'IHE Transactions'
-            ParticipantObjectQuery: 'TVNIfF5+XCZ8b3BlbmhpbXxvcGVuaGltLW1lZGlhdG9yLW9oaWUteGRzfHBpeHxwaXh8MjAxNTAyMjAxNTM4MjUrMDIwMHx8UUJQXlEyM15RQlBfUTIxfDEwMDQxYWQ5LTkyNDAtNDEyNS04ZDMwLWZiYzczNGEwOTMwMXxQfDIuNQ1RUER8SUhFIFBJWCBRdWVyeXw1OTRhNDVkYS0zOTY5LTQzOTAtODE2Ni01MjhkZDFmNWU0ZTF8NzZjYzc2NWE0NDJmNDEwXl5eJjEuMy42LjEuNC4xLjIxMzY3LjIwMDUuMy43JklTT15QSXxeXl5FQ0lEJkVDSUQmSVNPXlBJDVJDUHxJDQ=='
-            ParticipantObjectDetail:
+            participantObjectQuery: 'TVNIfF5+XCZ8b3BlbmhpbXxvcGVuaGltLW1lZGlhdG9yLW9oaWUteGRzfHBpeHxwaXh8MjAxNTAyMjAxNTM4MjUrMDIwMHx8UUJQXlEyM15RQlBfUTIxfDEwMDQxYWQ5LTkyNDAtNDEyNS04ZDMwLWZiYzczNGEwOTMwMXxQfDIuNQ1RUER8SUhFIFBJWCBRdWVyeXw1OTRhNDVkYS0zOTY5LTQzOTAtODE2Ni01MjhkZDFmNWU0ZTF8NzZjYzc2NWE0NDJmNDEwXl5eJjEuMy42LjEuNC4xLjIxMzY3LjIwMDUuMy43JklTT15QSXxeXl5FQ0lEJkVDSUQmSVNPXlBJDVJDUHxJDQ=='
+            participantObjectDetail:
               type: 'MSH-10'
               value: 'MTAwNDFhZDktOTI0MC00MTI1LThkMzAtZmJjNzM0YTA5MzAx'
           }
@@ -116,22 +116,22 @@
             if err
               done err
             else
-              Audit.findOne { "EventIdentification.EventDateTime": "2015-02-20T15:38:25.282Z" }, (error, newAudit) ->
+              Audit.findOne { "eventIdentification.eventDateTime": "2015-02-20T15:38:25.282Z" }, (error, newAudit) ->
                 should.not.exist (error)
                 (newAudit != null).should.be.true
-                newAudit.EventIdentification.EventActionCode.should.equal "E"
-                newAudit.EventIdentification.EventID.code.should.equal "110112"
-                newAudit.EventIdentification.EventID.displayName.should.equal "Query"
-                newAudit.EventIdentification.EventID.codeSystemName.should.equal "DCM"
-                newAudit.ActiveParticipant.length.should.equal 2
-                newAudit.ActiveParticipant[0].UserID.should.equal "pix|pix"
-                newAudit.ActiveParticipant[0].NetworkAccessPointID.should.equal "localhost"
-                newAudit.AuditSourceIdentification.AuditSourceID.should.equal "openhim"
-                newAudit.ParticipantObjectIdentification.length.should.equal 2
-                newAudit.ParticipantObjectIdentification[0].ParticipantObjectID.should.equal "975cac30-68e5-11e4-bf2a-04012ce65b02^^^ECID&ECID&ISO"
-                newAudit.ParticipantObjectIdentification[0].ParticipantObjectIDTypeCode.codeSystemName.should.equal "RFC-3881"
-                newAudit.ParticipantObjectIdentification[1].ParticipantObjectID.should.equal "dca6c09e-cc92-4bc5-8741-47bd938fa405"
-                newAudit.ParticipantObjectIdentification[1].ParticipantObjectIDTypeCode.codeSystemName.should.equal "IHE Transactions"
+                newAudit.eventIdentification.eventActionCode.should.equal "E"
+                newAudit.eventIdentification.eventID.code.should.equal "110112"
+                newAudit.eventIdentification.eventID.displayName.should.equal "Query"
+                newAudit.eventIdentification.eventID.codeSystemName.should.equal "DCM"
+                newAudit.activeParticipant.length.should.equal 2
+                newAudit.activeParticipant[0].userID.should.equal "pix|pix"
+                newAudit.activeParticipant[0].networkAccessPointID.should.equal "localhost"
+                newAudit.auditSourceIdentification.auditSourceID.should.equal "openhim"
+                newAudit.participantObjectIdentification.length.should.equal 2
+                newAudit.participantObjectIdentification[0].participantObjectID.should.equal "975cac30-68e5-11e4-bf2a-04012ce65b02^^^ECID&ECID&ISO"
+                newAudit.participantObjectIdentification[0].participantObjectIDTypeCode.codeSystemName.should.equal "RFC-3881"
+                newAudit.participantObjectIdentification[1].participantObjectID.should.equal "dca6c09e-cc92-4bc5-8741-47bd938fa405"
+                newAudit.participantObjectIdentification[1].participantObjectIDTypeCode.codeSystemName.should.equal "IHE Transactions"
                 done()

       it  "should only allow admin users to add audits", (done) ->
@@ -212,20 +212,20 @@
                 done err
               else
                 (res != null).should.be.true
-                res.body.EventIdentification.EventDateTime.should.equal "2015-02-20T15:38:25.282Z"
-                res.body.EventIdentification.EventActionCode.should.equal "E"
-                res.body.EventIdentification.EventID.code.should.equal "110112"
-                res.body.EventIdentification.EventID.displayName.should.equal "Query"
-                res.body.EventIdentification.EventID.codeSystemName.should.equal "DCM"
-                res.body.ActiveParticipant.length.should.equal 2
-                res.body.ActiveParticipant[0].UserID.should.equal "pix|pix"
-                res.body.ActiveParticipant[0].NetworkAccessPointID.should.equal "localhost"
-                res.body.AuditSourceIdentification.AuditSourceID.should.equal "openhim"
-                res.body.ParticipantObjectIdentification.length.should.equal 2
-                res.body.ParticipantObjectIdentification[0].ParticipantObjectID.should.equal "975cac30-68e5-11e4-bf2a-04012ce65b02^^^ECID&ECID&ISO"
-                res.body.ParticipantObjectIdentification[0].ParticipantObjectIDTypeCode.codeSystemName.should.equal "RFC-3881"
-                res.body.ParticipantObjectIdentification[1].ParticipantObjectID.should.equal "dca6c09e-cc92-4bc5-8741-47bd938fa405"
-                res.body.ParticipantObjectIdentification[1].ParticipantObjectIDTypeCode.codeSystemName.should.equal "IHE Transactions"
+                res.body.eventIdentification.eventDateTime.should.equal "2015-02-20T15:38:25.282Z"
+                res.body.eventIdentification.eventActionCode.should.equal "E"
+                res.body.eventIdentification.eventID.code.should.equal "110112"
+                res.body.eventIdentification.eventID.displayName.should.equal "Query"
+                res.body.eventIdentification.eventID.codeSystemName.should.equal "DCM"
+                res.body.activeParticipant.length.should.equal 2
+                res.body.activeParticipant[0].userID.should.equal "pix|pix"
+                res.body.activeParticipant[0].networkAccessPointID.should.equal "localhost"
+                res.body.auditSourceIdentification.auditSourceID.should.equal "openhim"
+                res.body.participantObjectIdentification.length.should.equal 2
+                res.body.participantObjectIdentification[0].participantObjectID.should.equal "975cac30-68e5-11e4-bf2a-04012ce65b02^^^ECID&ECID&ISO"
+                res.body.participantObjectIdentification[0].participantObjectIDTypeCode.codeSystemName.should.equal "RFC-3881"
+                res.body.participantObjectIdentification[1].participantObjectID.should.equal "dca6c09e-cc92-4bc5-8741-47bd938fa405"
+                res.body.participantObjectIdentification[1].participantObjectIDTypeCode.codeSystemName.should.equal "IHE Transactions"
                 done()

       it "should NOT return a audit that a user is not allowed to view", (done) ->


get 10 photos from flickr instead of 15

get 10 photos from flickr instead of 15

--- src/controllers/index.coffee
+++ src/controllers/index.coffee
@@ -71,7 +71,7 @@
   #fetch the next photo in the array of recent photos from Flickr
   req_url = 'https://api.flickr.com/services/rest?\
   format=json&method=flickr.photos.search&tags=landmark\
-  &sort=relevance&content_type=1&has_geo=1&per_page=15&page='+req.query.page+'&extras=geo,url_z&api_key='+flickr_api_key
+  &sort=relevance&content_type=1&has_geo=1&per_page=10&page='+req.query.page+'&extras=geo,url_z&api_key='+flickr_api_key
   console.log req_url

   #prepare the request to flickr.api


feat(ctrl): pass original filename to onBeforeUpload function

--- cgFileUploadCtrl.coffee
+++ cgFileUploadCtrl.coffee
@@ -124,6 +124,7 @@
             return unless file
             @_size = (file.size / Math.pow(1024, 2)).toFixed(2)
             @_mimetype = file.type
+            _originalFilename = file.name
             _filename = @_normalizeName(file.name)
             @onUploadStart?(
                 size: @_size
@@ -133,6 +134,7 @@

             _ctrl =
                 filename: _filename
+                originalFilename: _originalFilename
                 setDestFolder: (destFolder) -> _ctrl.destFolder = destFolder
                 setFileName: (filename) -> _ctrl.filename = filename
             @onBeforeUpload?(_ctrl)


Fix maximize button style in FF.

Fix maximize button style in FF.

--- src/main/webapp/coffeescripts-hidden/load.coffee
+++ src/main/webapp/coffeescripts-hidden/load.coffee
@@ -324,7 +324,11 @@

   stylesheet = document.createElement("style")
   document.head.appendChild(stylesheet)
-  stylesheet.sheet.addRule?(maximizeColorSelector, maximizeColorStyle)
+
+  if stylesheet.sheet.addRule?
+    stylesheet.sheet.addRule?(maximizeColorSelector, maximizeColorStyle)
+  else
+    stylesheet.sheet.insertRule(maximizeColorSelector + " {" + maximizeColorStyle + "}", 0)

   $("body").append anchorTab


:fire: unused

:fire: unused

--- lib/motion.coffee
+++ lib/motion.coffee
@@ -33,10 +33,6 @@
   debug
 } = require './utils'

-getLengthForRange = (range) ->
-  Range.fromObject(range).getExtent().toString()
-
-swrap = require './selection-wrapper'
 {MatchList} = require './match'
 settings = require './settings'
 Base = require './base'


Added number methods gcd and pow.

Added number methods gcd and pow.

--- lib/number.coffee
+++ lib/number.coffee
@@ -113,13 +113,30 @@
     NumberBase[name]   = (args...) -> f.call NumberBase, args...
     NumberBase::[name] = (args...) -> NumberBase[name] this, args...

-  for name in ['cmp', 'plus', 'minus', 'times', 'div', 'mod', 'gcd']
+  for name in ['cmp', 'plus', 'minus', 'times', 'div', 'mod']
     do (name) ->
       namex = "#{name}__"
       operator name, (a, b) ->
         [x, y] = upcast a, b
         @downcast x[namex] y

+  gcd: (other) ->
+    step = (a, b) -> if b.sgn() > 0 then -> step b, a.mod(b) else a
+
+    [a, b] = [@abs(), makeNum(other).abs()]
+    if a > b then trampoline step a, b else trampoline step b, a
+
+  pow: (other) ->
+    step = (p, r, s) ->
+      if s.sgn() > 0
+        if s.mod(2).sgn() > 0
+          -> step p.times(r), r, s.minus 1
+        else
+          -> step p, r.times(r), s.div 2
+      else
+        p
+
+    trampoline step makeNum(1), this, makeNum other

 # ----

@@ -166,12 +183,6 @@
   div__: (x) -> new CheckedInt Math.floor @val / x.val

   mod__: (x) -> new CheckedInt @val % x.val
-
-  gcd: (other) ->
-    step = (a, b) -> if b > 0 then -> step b, a % b else a
-
-    [a, b] = [Math.abs(@val), Math.abs(getval other)]
-    new CheckedInt if a > b then trampoline step a, b else trampoline step b, a

   toString: -> "" + @val

@@ -440,6 +451,7 @@

   log ''
   show -> number(98).gcd 21
+  show -> number(77777).gcd 21

   log ''
   show -> a = number Math.pow 2, 13
@@ -480,3 +492,7 @@
   show -> number(9801).sqrt()
   show -> number(998001).sqrt()
   show -> number(99980001).sqrt()
+
+  log ''
+  show -> number(10).pow 6
+  show -> number(2).pow 16


Increase undo delay

Increase undo delay

Travis/sauce keeps getting false positive fails

--- test/unit/modules/undo-manager.coffee
+++ test/unit/modules/undo-manager.coffee
@@ -7,7 +7,7 @@
       </div>'
     @quill = new Quill(@container.firstChild, {
       modules: {
-        'undo-manager': { delay: 100 }
+        'undo-manager': { delay: 400 }
       }
     })
     @undoManager = @quill.getModule('undo-manager')


Refactor Reader class methods

Refactor Reader class methods

--- lib/reader.coffee
+++ lib/reader.coffee
@@ -37,27 +37,29 @@
     return

   getUrlStream: (source, callback = ->) ->
-    tr = through (data) ->
-      @emit 'data', data
-
-    phantom.create (ph) ->
-      ph.createPage (page) ->
-        page.set 'onResourceReceived', (res) ->
-          if res.stage is 'end' and res.status isnt 200
-            err = new Error "#{messages.httpStatusError} #{res.status}:
-              #{http.STATUS_CODES[res.status]}"
-            callback err
-
-        page.open source, (status) ->
-          return if status isnt 'success'
-          callback null, tr
-
-          page.evaluate (-> document.body.innerHTML), (result) ->
-            tr.end result
-            ph.exit()
-    ,
+    phantom.create
       parameters:
         'ignore-ssl-errors': 'yes'
+    , (ph) =>
+      ph.createPage (page) =>
+        page.set 'onResourceReceived', @_onPageResourceReceived.bind(this, callback)
+        page.open source, @_onPageOpen.bind(this, callback, ph, page)
+
+  _onPageResourceReceived: (callback, res) ->
+    if res.stage is 'end' and res.status isnt 200
+      err = new Error "#{messages.httpStatusError} #{res.status}:
+        #{http.STATUS_CODES[res.status]}"
+      callback err
+
+  _onPageOpen: (callback, ph, page, status) ->
+    return if status isnt 'success'
+
+    tr = through (data) -> @emit 'data', data
+    callback null, tr
+
+    page.evaluate (-> document.body.innerHTML), (content) ->
+      tr.end content
+      ph.exit()

   _httpOptions: (options) ->
     options = url.parse options if typeof options is 'string'


tests/client: no cookie jar, please

tests/client: no cookie jar, please

--- tests/support/client.coffee
+++ tests/support/client.coffee
@@ -32,6 +32,7 @@

     opts ?= {}
     opts.followRedirect ?= no
+    opts.jar = false
     opts.method ?= method
     opts.url = "http://#{@host}:#{@port}#{path}"
     opts.encoding ?= 'utf8'


fix pkg dir

fix pkg dir

--- lib/server.coffee
+++ lib/server.coffee
@@ -10,7 +10,7 @@

 # helpers
 package_dir = (id, version) ->
-  path.resolve "#{__dirname}/../../pkg/#{id}/#{version}"
+  path.resolve "#{__dirname}/../../../pkg/#{id}/#{version}"

 read_package = (id, version) ->
   root = package_dir id, version
@@ -36,7 +36,7 @@

   # watch for file changes
   if not prod
-    pkg_path = path.resolve "#{__dirname}/../../pkg"
+    pkg_path = path.resolve "#{__dirname}/../../../pkg"
     console.log pkg_path
     watcher = chokidar.watch pkg_path, {
       ignored: /(^\.|\.swp$|\.tmp$|~$)/


Have degree type.

Have degree type.

--- client/types.coffee
+++ client/types.coffee
@@ -5,6 +5,14 @@
     step:    0.1
     measure: "%"
     desc:    "Prozent"
+
+  degree:
+    type:    "range"
+    min:     0
+    max:     359
+    step:    0.1
+    measure: "°"
+    desc:    "Winkelgrad"

   pixel:
     type:    "range"


Change Order (#2)

Change Order (#2)

--- lib/sorter.coffee
+++ lib/sorter.coffee
@@ -56,14 +56,14 @@
 				# map
 				separations = [
 					{
+						find: '="'
+						join: ' '
+						split: ' '
+					}
+					{
 						find: ';'
 						join: '; '
 						split: ';'
-					}
-					{
-						find: '="'
-						join: ' '
-						split: ' '
 					}
 					{
 						find: '='


list should return empty [] when undefined/uninitialized so it always produces a proxy object

--- src/list.coffee
+++ src/list.coffee
@@ -80,11 +80,10 @@

   @Item = ListItem

-  # XXX: not a fan of below value override... :-(
   @property 'value',
     get: -> switch
       when @state.value? then @props.map((item) -> item.data).filter(Boolean)
-      else undefined
+      else []

   @property 'props',
     get: -> switch


Make market Isk Out positive

Make market Isk Out positive

--- src/javascript/character_stats.coffee
+++ src/javascript/character_stats.coffee
@@ -32,6 +32,7 @@
   calcDerived: ->
     # fix a few stats
     @iskOut = -(@iskOut)
+    @marketIskOut = -(@marketIskOut)
     # derive some stats
     @averageSessionLength = @characterMinutes / @characterSessionsStarted


feat(templateUrl): Support theme template by url

Closes #24

--- src/main.coffee
+++ src/main.coffee
@@ -33,7 +33,7 @@
 	require: 'ngModel'
 	templateUrl: (tElement, tAttrs) ->
 		if not tAttrs.theme? or tAttrs.theme is '' then tAttrs.theme = scDateTimeConfig.defaultTheme
-		return "scDateTime-#{tAttrs.theme}.tpl"
+		return if tAttrs.theme.indexOf('/') <= 0 then "scDateTime-#{tAttrs.theme}.tpl" else tAttrs.theme
 	link: (scope, element, attrs, ngModel) ->
 		attrs.$observe 'defaultMode', (val) ->
 			if val isnt 'time' and val isnt 'date' then val = scDateTimeConfig.defaultMode


a couple documentation touches

a couple documentation touches

--- src/builtins.coffee
+++ src/builtins.coffee
@@ -34,7 +34,7 @@
 #       - A zero-rank APL array is a JavaScript array of size one with a
 #       `shape` property of `[]`, e.g. created by:
 #
-#               var a = []; a.shape = [];
+#               var a = [123]; a.shape = [];
 #
 #   * An APL vector is a JavaScript array.
 #
@@ -56,7 +56,7 @@
 #               return cube;
 #           }
 #
-#       A vector's representation, as opposed to that of higher-dimension
+#       A vector's representation, as opposed to that of higher-dimensional
 #       arrays, is not required to have a `shape` property.  The shape of a
 #       vector `v` is assumed to be `[v.length]`, by convention.  Similarly, we
 #       could say that a scalar's shape is `[]` by convention.


Fixed compilation of require call

Fixed compilation of require call

--- src/compiler.coffee
+++ src/compiler.coffee
@@ -3646,7 +3646,7 @@
   moduleHandle =
     switch baseType
       when 'commonJs'
-        jsCall 'require', (toJsString (pathNames[0...numModules].join '/'))
+        jsCall 'require', [(toJsString (pathNames[0...numModules].join '/'))]
       when 'browser'
         acc = 'Shem'
         for i in [0...numModules]


fix for transactions timezone

fix for transactions timezone

--- app/js/services/wallet.coffee
+++ app/js/services/wallet.coffee
@@ -240,8 +240,8 @@
         t.error = val.error
         t.trx_num = val.trx_num
         t.time = time
-        t.expiration_pretty_time = @utils.toDate(val.expiration_timestamp).toLocaleString(undefined, {timeZone:"UTC"})
-        t.pretty_time = time.toLocaleString(undefined, {timeZone:"UTC"})
+        t.expiration_pretty_time = @utils.toDate(val.expiration_timestamp).toLocaleString()
+        t.pretty_time = time.toLocaleString()
         t.fee = @utils.asset(val.fee.amount, @blockchain.asset_records[val.fee.asset_id])
         t.vote = "N/A"
         if t.status != "rebroadcasted"


add host stats fix

add host stats fix

--- app/modules/host/index.coffee
+++ app/modules/host/index.coffee
@@ -32,50 +32,46 @@
     $scope.currentPCIPage = 1
     $scope.currentGPUPage = 1

-    # Provides a fibonacci behaviour for stats refresh on failure
     $scope.refreshStatControl = refreshStatControl = {
       baseStatInterval: 5000
-      timeout: null
+      baseTimeOut: 10000
+      period: null
       running: false
+      attempt: 0

       start: () ->
         return if this.running
+        this.stop()
         this.running = true
         this._reset()
         $scope.$on('$destroy', () => this.stop())
         return this._trig(Date.now())
       _trig: (t1) ->
         if this.running
-          t2 = Date.now()
-          timeLeft = Math.max(this.baseStatInterval * this._factor() - Math.max(t2 - t1 - (this.baseStatInterval * this._factor(true)), 0), 0)
-          return this.timeout = $timeout(
-            () => $scope.refreshStats($scope.host.UUID),
-            timeLeft
+          timeoutSecurity = $timeout(
+            () => this.stop(),
+            this.baseTimeOut
           )
-
-          .then () =>
-            this._reset()
-            return this._trig(t2)
-
+          return $scope.refreshStats($scope.host.UUID)
+          .then () => this._reset()
           .catch (err) =>
-            if !this.running || $scope.host.power_state isnt 'Running'
+            if !this.running || this.attempt >= 2 || $scope.host.power_state isnt 'Running' || $scope.isVMWorking($scope.host)
               return this.stop()
             else
-              if this.attempt >= 1
-                return this.stop()
               this.attempt++
-              this._next()
-              return this._trig(t2)
+          .finally () =>
+            $timeout.cancel(timeoutSecurity)
+            if this.running
+              t2 = Date.now()
+              return this.period = $timeout(
+                () => this._trig(t2),
+                Math.max(this.baseStatInterval - (t2 - t1), 0)
+              )
       _reset: () ->
-        this.terms = [1,1]
         this.attempt = 0
-      _next: () ->
-        this.terms = [this.terms[1], this.terms[0] + this.terms[1]]
-      _factor: (previous) ->
-        return this.terms[if previous then 0 else 1]
       stop: () ->
-        if this.timeout
-          $timeout.cancel(this.timeout)
+        if this.period
+          $timeout.cancel(this.period)
         this.running = false
         return
     }


test.expect in integration test

test.expect in integration test

--- test/integration.coffee
+++ test/integration.coffee
@@ -8,7 +8,7 @@
 module.exports =

   'systems are started and stopped in the most efficient order': (test) ->
-    # test.expect (12 * 4) + (2 * 4)
+    test.expect (12 * 4) + (2 * 4)

     starting = new Set
     running = new Set


fix typo (fraySquirrel -> graySquirrel)

fix typo (fraySquirrel -> graySquirrel)

--- app/translations/en_us.coffee
+++ app/translations/en_us.coffee
@@ -383,7 +383,7 @@
       '''

     chipmunk:
-      fraySquirrel: '''
+      graySquirrel: '''
       to do description
       '''


Fix user slides JSON format

Fix user slides JSON format

--- user.coffee
+++ user.coffee
@@ -33,7 +33,8 @@
       url = storage.getItemSync('url') + "/register/" + data.registerLink
       data.link = url
     _.omit data, 'password'
-    data
+    data.slides = data.slides.map (s) -> s.data
+    return data

   deleteSlide: (id, cb) ->
     if id > 0 and id < @data.slides.length


Remove debug line

Remove debug line

--- test/test_client.coffee
+++ test/test_client.coffee
@@ -113,7 +113,6 @@
         receivedRequests++

         if receivedRequests is 3
-          console.log "quit"
           process.quit()

     request1 = client.request 'GET', '/foo', {}


match version in tests

match version in tests

--- test/unit-module.coffee
+++ test/unit-module.coffee
@@ -7,4 +7,5 @@
   describe 'module', ->

     it 'version', ->
-      expect( domaintree.VERSION ).to.equal '0.1.1'
+      expect( domaintree.VERSION ).to.equal '0.2.0'
+


fix tests due to interface change in format

--- test/unit/format.coffee
+++ test/unit/format.coffee
@@ -5,35 +5,35 @@

   tests =
     tag:
-      format: new Quill.Format(Quill.Format.FORMATS.bold)
+      format: new Quill.Format(document, Quill.Format.FORMATS.bold)
       existing: 'Text'
       missing: 'Text'
       added: 'Text'
       value: true
     style:
-      format: new Quill.Format(Quill.Format.FORMATS.color)
+      format: new Quill.Format(document, Quill.Format.FORMATS.color)
       existing: 'Text'
       missing: 'Text'
       value: 'blue'
     image:
-      format: new Quill.Format(Quill.Format.FORMATS.image)
+      format: new Quill.Format(document, Quill.Format.FORMATS.image)
       existing: ''
       missing: 'Text'
       removed: "#{Quill.Format.EMBED_TEXT}"
       value: 'http://quilljs.com/images/icon.png'
     link:
-      format: new Quill.Format(Quill.Format.FORMATS.link)
+      format: new Quill.Format(document, Quill.Format.FORMATS.link)
       existing: 'Text'
       missing: 'Text'
       added: 'Text'
       value: 'http://quilljs.com'
     line:
-      format: new Quill.Format(Quill.Format.FORMATS.align)
+      format: new Quill.Format(document, Quill.Format.FORMATS.align)
       existing: '
Text
'
       missing: '
Text
'
       value: 'right'
     complex:
-      format: new Quill.Format(Quill.Format.FORMATS.bold)
+      format: new Quill.Format(document, Quill.Format.FORMATS.bold)
       existing: 'Text<s>Strike</s>Under'
       missing: 'Text<s>Strike</s>Under'
       removed: 'Text<s>Strike</s>Under'
@@ -55,7 +55,7 @@

     it('default', ->
       @container.innerHTML = 'Text'
-      format = new Quill.Format(Quill.Format.FORMATS.color)
+      format = new Quill.Format(document, Quill.Format.FORMATS.color)
       expect(format.match(@container.firstChild)).toBe(false)
     )
   )
@@ -75,7 +75,7 @@

     it('default', ->
       @container.innerHTML = 'Text'
-      format = new Quill.Format(Quill.Format.FORMATS.color)
+      format = new Quill.Format(document, Quill.Format.FORMATS.color)
       expect(format.value(@container.firstChild)).toBe(undefined)
     )
   )
@@ -109,14 +109,14 @@

     it('change value', ->
       @container.innerHTML = 'Text'
-      format = new Quill.Format(Quill.Format.FORMATS.color)
+      format = new Quill.Format(document, Quill.Format.FORMATS.color)
       format.add(@container.firstChild, 'red')
       expect(@container).toEqualHTML('Text')
     )

     it('default value', ->
       @container.innerHTML = 'Text'
-      format = new Quill.Format(Quill.Format.FORMATS.size)
+      format = new Quill.Format(document, Quill.Format.FORMATS.size)
       format.add(@container.firstChild, Quill.Format.FORMATS.size.default)
       expect(@container).toEqualHTML('Text')
     )


fix crash when api.port not exist 2

fix crash when api.port not exist 2

--- coffee/index.coffee
+++ coffee/index.coffee
@@ -27,8 +27,8 @@
         # the api.port may not exist
         false
     .then (oldPort)->
-        resolve() unless oldPort
         new Promise (resolve, reject)->
+            resolve() unless oldPort
             options =
                 hostname: 'localhost'
                 port: oldPort


Fixed hash links to headers from TOC

Fixed hash links to headers from TOC

--- coffee/utils.coffee
+++ coffee/utils.coffee
@@ -1,3 +1,5 @@
+slug = (str) -> str.trim().replace(/\s+/g,'-').toLowerCase()
+
 module.exports =
   getCursorPosition: (el) ->
     pos = 0
@@ -51,8 +53,11 @@
                    """ + e.innerHTML
     el

+  slug: slug
+
   toc: (el) ->
     '
' + (for e in el.querySelectorAll('H1,H2,H3,H4,H5,H6')
+      e.id = slug e.textContent
       """

<#{e.tagName}>
       #{e.innerHTML}


a bit of music

a bit of music

--- commands/wit.coffee
+++ commands/wit.coffee
@@ -10,4 +10,14 @@
     /what(\'s| is) the problem\?*/i
     /what are you talking about\?*/i
     /I don'?t know what you('?re| are) talking about/i
+]
+
+brain.addAct 'astley', new brain.Act [
+    "Never gonna let you down"
+    "Never gonna make you cry"
+    "Never gonna tell a lie and hurt you"
+], [
+    /(I'?m )?Never gonna give (you|u) up/i
+    /(I'?m )?Never gonna run around (and|n) desert (you|u)/i
+    /(I'?m )?Never gonna say goodbye/i
 ]


Add keybinds for editor:newline

Add keybinds for editor:newline

--- keymaps/transient-emacs.cson
+++ keymaps/transient-emacs.cson
@@ -28,6 +28,8 @@
   'ctrl-g': 'core:cancel'
   'ctrl-k': 'editor:cut-to-end-of-line'
   'ctrl-y': 'core:paste'
+  'ctrl-j': 'editor:newline'
+  'ctrl-m': 'editor:newline'

 'atom-workspace atom-text-editor:not([mini])':
   'ctrl-g': 'emacs:cancel'
@@ -38,6 +40,8 @@
   'ctrl-w': 'emacs:kill-region-or-backward-word'
   'alt-w': 'emacs:copy-region'
   'escape w': 'emacs:copy-region'
+  'ctrl-j': 'editor:newline'
+  'ctrl-m': 'editor:newline'

   'ctrl-d': 'core:delete'
   'backspace': 'emacs:backspace'


Unifying on `invert`

Unifying on `invert`

--- src/ThreeCSG.coffee
+++ src/ThreeCSG.coffee
@@ -125,9 +125,6 @@
 class ThreeBSP.Polygon
   constructor: (@vertices=[], @normal, @w) ->
     @calculateProperties() if @vertices.length
-    # TODO: Update callsites and remove aliases
-    @splitPolygon = @subdivide
-    @invert = @flip

   calculateProperties: () => returning this, =>
     [a, b, c] = @vertices
@@ -143,7 +140,7 @@
       @w
     )

-  flip: () => returning this, =>
+  invert: () => returning this, =>
     @normal.multiplyScalar -1
     @w *= -1
     @vertices.reverse()


Rename to watch:vue

Rename to watch:vue

--- gulp/tasks/watch.coffee
+++ gulp/tasks/watch.coffee
@@ -4,14 +4,14 @@

 gulp.task "watch", ->
   [
-    "babel"
+    "vue"
     "scss"
   ].forEach((name) ->
     gulp.start("watch:#{name}")
   )

-gulp.task "watch:babel", ->
-  $.watch(config.src.babel, -> gulp.start("compile:babel"))
+gulp.task "watch:vue", ->
+  $.watch(config.src.babel, -> gulp.start("compile:vue"))

 gulp.task "watch:scss", ->
   $.watch(config.src.scss, -> gulp.start("compile:scss"))


Support for aliases that are folders of packages

It is possible to require a file that is path of a package that is installed via npm like
require("jade/lib/filters")
this patch should make that possible.

--- src/aliasify.coffee
+++ src/aliasify.coffee
@@ -1,21 +1,34 @@
 path = require 'path'
 transformTools = require 'browserify-transform-tools'
+
+getReplacement = (file, aliases)->
+    if aliases[file]
+        return aliases[file]
+    else
+        fileParts = /^([^\/]*)(\/.*)$/.exec(file)
+        pkg = aliases[fileParts?[1]]
+        if pkg?
+            return pkg+fileParts[2]
+    return null

 module.exports = transformTools.makeRequireTransform "aliasify", (args, opts, cb) ->
     aliases = opts.config?.aliases
     verbose = opts.config?.verbose
-    if (args.length > 0) and aliases? and aliases[args[0]]?
-        replacement = aliases[args[0]]
+    file = args[0]
+    if file? and aliases?
+        replacement = getReplacement(file, aliases)
+        if replacement?
+            if /^\./.test(replacement)
+                # Resolve the new file relative to the file doing the requiring.
+                replacement = path.resolve opts.configData.configDir, replacement
+                fileDir = path.dirname opts.file
+                replacement = "./#{path.relative fileDir, replacement}"

-        if replacement.length > 0 and replacement[0] is '.'
-            # Resolve the new file relative to the file doing the requiring.
-            replacement = path.resolve opts.configData.configDir, replacement
-            fileDir = path.dirname opts.file
-            replacement = "./#{path.relative fileDir, replacement}"
+            if verbose
+                console.log "aliasify - #{opts.file}: replacing #{args[0]} with #{replacement}"

-        if verbose
-            console.log "aliasify - #{opts.file}: replacing #{args[0]} with #{replacement}"
-
-        cb null, "require('#{replacement}')"
+            cb null, "require('#{replacement}')"
+        else
+            cb()
     else
         cb()


Add form validation

Add form validation

--- graphedit/coffee/graphedit.coffee
+++ graphedit/coffee/graphedit.coffee
@@ -449,38 +449,68 @@
     @DATAVIEW.find('.properties').append(str)
     @DATAVIEW.find('.graphedit-remove-property').on 'click', @clickRemoveProperty

+  validatePropertyForm: (form_elm) =>
+    #existing properties
+    data = {}
+
+    #extract existing properties (with name attrs)
+    form = $(form_elm).serializeArray()
+
+    is_valid = true
+
+    $.each form, (i, d) => data[d.name] = d.value
+
+    #new properties
+    $(form_elm).find('.graphedit-new-property').each (i, elm) =>
+      key = $(elm).find('input').first().val()
+      value = $(elm).find('input').last().val()
+      if key.length == 0 and value.length > 0
+        $(elm).addClass('has-error')
+        $(elm).append('Must provide key name')
+        is_valid = false
+
+      else if key.length > 0 and key of data
+        $(elm).addClass('has-error')
+        $(elm).append('Duplicate property')
+        is_valid = false
+
+    return is_valid
+
+
   submitPropertyForm: (e) =>
     e.preventDefault();

-    data = {}
-
-    #extract existing properties (with name attrs)
-    form = $(e.target).serializeArray()
-
-    $.each form, (i, d) =>
-      data[d.name] = d.value
-
-    #add new properties
-    $(e.target).find('.graphedit-new-property').each (i, elm) =>
-      key = $(elm).find('input').first().val()
-      value = $(elm).find('input').last().val()
-      if key.length > 0
-        data[key] = value
-
-    #what's being edited?
-    target = null
-    if @selected_nodes.length == 1 and @selected_edges.length == 0
-      target = @selected_nodes[0]
-    else if @selected_nodes.length == 0 and @selected_edges.length == 1
-      target = @selected_edges[0]
-
-    if target == null
-      throw "Not sure what you were editing"
-
-    d3.select(target).data()[0].properties = data
-
-    @restart()
-    @displayData()
+    if @validatePropertyForm(e.target)
+
+      data = {}
+
+      #extract existing properties (with name attrs)
+      form = $(e.target).serializeArray()
+
+      $.each form, (i, d) =>
+        data[d.name] = d.value
+
+      #add new properties
+      $(e.target).find('.graphedit-new-property').each (i, elm) =>
+        key = $(elm).find('input').first().val()
+        value = $(elm).find('input').last().val()
+        if key.length > 0
+            data[key] = value
+
+      #what's being edited?
+      target = null
+      if @selected_nodes.length == 1 and @selected_edges.length == 0
+        target = @selected_nodes[0]
+      else if @selected_nodes.length == 0 and @selected_edges.length == 1
+        target = @selected_edges[0]
+
+      if target == null
+        throw "Not sure what you were editing"
+
+      d3.select(target).data()[0].properties = data
+
+      @restart()
+      @displayData()

 # GRAPHEDIT PLUGIN DEFINITION


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/animated.coffee
+++ src/animated.coffee
@@ -76,8 +76,7 @@
   initializeState = ->
     I.activeAnimation = I.data.animations.first()

-    I.data.tileset.each (spriteData, i) ->
-      I.spriteLookup[i] = Sprite.fromURL(spriteData.src)
+    I.spriteLookup = I.data.tileset.map (spriteData) -> Sprite.fromURL(spriteData.src)

   window["#{I.animationName}SpriteLookup"] ||= []


Specify default handler for courses/<id> url

--- src/router.cjsx
+++ src/router.cjsx
@@ -22,6 +22,8 @@
       <Redirect from='/' to='dashboard' />
       <Route path='dashboard/?' name='dashboard' handler={CourseListing} />
       <Route path='courses/:courseId/?'>
+        <Router.DefaultRoute handler={TeacherTaskPlans}/>
+
         <Route path='list/?' name='viewStudentDashboard' handler={StudentDashboardShell} />
         <Route path='tasks/:id/?' name='viewTask' handler={SingleTask}/>
         <Route path='tasks/:id/steps/:stepIndex/?'


adds docco documentation to expression evaluation

--- src/math/expression_evaluation.coffee
+++ src/math/expression_evaluation.coffee
@@ -1,10 +1,27 @@
-#= require ./base
-
+# # Expression Evaluation
+
+# A core feature of the library is the ability to
+# "evaluate" expressions.
+#
+# For example, we might trivially evaluate an expression
+# "1 + 2" to "3".
+
+
+
+# make convenient aliases
 ttm = thinkthroughmath
 logger = ttm.logger
 class_mixer = ttm.class_mixer
 object_refinement = ttm.lib.object_refinement

+
+# ## EvaluationRefinementBuilder
+#
+# Evaluation uses the refinement library from
+# ttm-coffeescript-utils.
+#
+# Evaluation methods are added dynamically to expression components
+# when they are needed.
 class EvaluationRefinementBuilder
   initialize: (comps, class_mixer, object_refinement, MalformedExpressionError, precise)->
     comps = comps
@@ -165,6 +182,8 @@
 ttm.class_mixer EvaluationRefinementBuilder

+# If the library receives an expression that it cannot evaluate, it will
+# throw a MalformedExpressError
 MalformedExpressionError = (message)->
   @name = 'MalformedExpressionError'
   @message = message


draw triggering events

draw triggering events

--- src/drawable.coffee
+++ src/drawable.coffee
@@ -30,7 +30,7 @@

     if I.rotation
       I.transform = Matrix.translation(center.x, center.y)
-        .concat(Matrix.rotation(I.rotation)) if I.rotation
+        .concat(Matrix.rotation(I.rotation))
         .concat(Matrix.translation(-I.width/2, -I.height/2))
     else
       # Assumes I.x and I.y are top-left


change domain to cydoemus

change domain to cydoemus

--- configs.coffee
+++ configs.coffee
@@ -22,9 +22,9 @@
 	when "production"
 		configs.cache = true
 		configs.mongoURL = process.env.MONGOLAB_URI
-		configs.url = "http://www.vault.tk"
+		configs.url = "http://cydoemus.vault.tk"
 		configs.port = process.env.PORT || "80"
-		configs.host = 'www.vault.tk'
+		configs.host = 'cydoemus.vault.tk'
 		configs.clef =
 			app_id: process.env.CLEF_APP_ID
 			app_secret: process.env.CLEF_APP_SECRET


Use Project::openSync in specs

Use Project::openSync in specs

--- spec/github-file-spec.coffee
+++ spec/github-file-spec.coffee
@@ -23,7 +23,7 @@

     setupGithubFile = ->
       project.setPath(workingDirPath)
-      editSession = project.open(filePathRelativeToWorkingDir)
+      editSession = project.openSync(filePathRelativeToWorkingDir)
       githubFile = GitHubFile.fromPath(editSession.getPath())

     teardownWorkingDirAndRestoreFixture = (fixtureName) ->


Adjust spec now that tab length does not affect leading space tokens

--- spec/text-editor-spec.coffee
+++ spec/text-editor-spec.coffee
@@ -4867,15 +4867,13 @@
         expect(editor.getSelectedBufferRange()).toEqual [[0, 0], [0, 2]]

   describe '.setTabLength(tabLength)', ->
-    it 'retokenizes the editor with the given tab length', ->
+    it 'clips atomic soft tabs to the given tab length', ->
       expect(editor.getTabLength()).toBe 2
-      leadingWhitespaceTokens = editor.tokensForScreenRow(5).filter (token) -> 'leading-whitespace' in token.scopes
-      expect(leadingWhitespaceTokens.length).toBe(3)
+      expect(editor.clipScreenPosition([5, 1], clipDirection: 'forward')).toEqual([5, 2])

       editor.setTabLength(6)
       expect(editor.getTabLength()).toBe 6
-      leadingWhitespaceTokens = editor.tokensForScreenRow(5).filter (token) -> 'leading-whitespace' in token.scopes
-      expect(leadingWhitespaceTokens.length).toBe(1)
+      expect(editor.clipScreenPosition([5, 1], clipDirection: 'forward')).toEqual([5, 6])

       changeHandler = jasmine.createSpy('changeHandler')
       editor.onDidChange(changeHandler)


More docs.

More docs.

--- src/fs_utils.coffee
+++ src/fs_utils.coffee
@@ -22,11 +22,7 @@

   constructor: (files) ->
     @watched = {}
-    if Array.isArray files
-      #files.forEach @_handle
-      @_handle file for file in files
-    else
-      @_handle files
+    @_handle file for file in files

   _getWatchedDir: (directory) ->
     @watched[directory] ?= []
@@ -134,20 +130,27 @@
 }).call(this);
 '''

-exports.wrap = wrap = (path, data) ->
+# Defines a requirejs module.
+# This allows brunch users to use `require 'module/name'` in browsers.
+#
+# path - path to file, contents of which will be wrapped.
+# source - file contents.
+#
+# Returns a wrapped string.
+exports.wrap = wrap = (path, source) ->
   moduleName = JSON.stringify(
     path.replace(/^app\//, '').replace(/\.\w*$/, '')
   )
   """
   (this.require.define({
     #{moduleName}: function(exports, require, module) {
-      #{data}
+      #{source}
     }
   }));\n
   """

 # Collects content from a list of files and wraps it with
-# require.js module definition.
+# require.js module definition if needed.
 #
 # files - array of objects with fields {file, data}.
 # wrapResult - wrap result with a definition of require.js or not.


Call handle_input in timer_tick

Call handle_input in timer_tick

--- game.coffee
+++ game.coffee
@@ -114,6 +114,7 @@
       if Game.use_collisions
         @handle_collisions(player) for player in @players

+      @handle_input(elapsed_time)
       @render_game() if @browser

       @old_time = new_time


namespaced unbind

namespaced unbind

--- src/bindable.coffee
+++ src/bindable.coffee
@@ -47,7 +47,7 @@
     [event, namespace] = namespacedEvent.split(".")

     if namespace
-      callback[
+      callback.__PIXIE |= {}

     eventCallbacks[event] ||= []
     eventCallbacks[event].push(callback)


namespaced unbind

namespaced unbind

--- src/bindable.coffee
+++ src/bindable.coffee
@@ -83,6 +83,7 @@
       eventCallbacks[event] ||= []

       if namespace
+        # Select only the
         eventCallbacks[event] = eventCallbacks.select (callback) ->
           !callback.__PIXIE?[namespace]?


namespaced unbind

namespaced unbind

--- src/bindable.coffee
+++ src/bindable.coffee
@@ -46,7 +46,7 @@
   bind: (namespacedEvent, callback) ->
     [event, namespace] = namespacedEvent.split(".")

-    if namespace
+    callback if namespace

     eventCallbacks[event] ||= []
     eventCallbacks[event].push(callback)


Remove the web_hooks from the incident respond file.

--- src/incident.coffee
+++ src/incident.coffee
@@ -172,87 +172,6 @@
           #else
           #  msg.send "Sorry, could not add transcript of room to PagerDuty as note."

-  ##### PagerDuty Webhooks
-  # Pagerduty Webhook Integration (For a payload example, see http://developer.pagerduty.com/documentation/rest/webhooks)
-  parseWebhook = (req, res) ->
-    hook = req.body
-
-    messages = hook.messages
-
-    if /^incident.*$/.test(messages[0].type)
-      parseIncidents(messages)
-    else
-      "No incidents in webhook"
-
-  parseIncidents = (messages) ->
-    returnMessage = []
-    count = 0
-    for message in messages
-      incident = message.data.incident
-      hookType = message.type
-      returnMessage.push(generateIncidentString(incident, hookType))
-      count = count+1
-    returnMessage.unshift("You have " + count + " PagerDuty update(s): \n")
-    returnMessage.join("\n")
-
-  getUserForIncident = (incident) ->
-    if incident.assigned_to_user
-      incident.assigned_to_user.email
-    else if incident.resolved_by_user
-      incident.resolved_by_user.email
-    else
-      '(???)'
-
-  generateIncidentString = (incident, hookType) ->
-    console.log "hookType is " + hookType
-    assigned_user   = getUserForIncident(incident)
-    incident_number = incident.incident_number
-
-    if hookType == "incident.trigger"
-      """
-      Incident # #{incident_number} :
-      #{incident.status} and assigned to #{assigned_user}
-       #{incident.html_url}
-      To acknowledge: @#{robot.name} pager me ack #{incident_number}
-      To resolve: @#{robot.name} pager me resolve #{}
-      """
-      startIncident(incident_number, null)
-    else if hookType == "incident.acknowledge"
-      """
-      Incident # #{incident_number} :
-      #{incident.status} and assigned to #{assigned_user}
-       #{incident.html_url}
-      To resolve: @#{robot.name} pager me resolve #{incident_number}
-      """
-    else if hookType == "incident.resolve"
-      """
-      Incident # #{incident_number} has been resolved by #{assigned_user}
-       #{incident.html_url}
-      """
-      endIncident(incident_number, null)
-    else if hookType == "incident.unacknowledge"
-      """
-      #{incident.status} , unacknowledged and assigned to #{assigned_user}
-       #{incident.html_url}
-      To acknowledge: @#{robot.name} pager me ack #{incident_number}
-       To resolve: @#{robot.name} pager me resolve #{incident_number}
-      """
-    else if hookType == "incident.assign"
-      """
-      Incident # #{incident_number} :
-      #{incident.status} , reassigned to #{assigned_user}
-       #{incident.html_url}
-      To resolve: @#{robot.name} pager me resolve #{incident_number}
-      """
-    else if hookType == "incident.escalate"
-      """
-      Incident # #{incident_number} :
-      #{incident.status} , was escalated and assigned to #{assigned_user}
-       #{incident.html_url}
-      To acknowledge: @#{robot.name} pager me ack #{incident_number}
-      To resolve: @#{robot.name} pager me resolve #{incident_number}
-      """
-
   ##### Moment calculations
   calculateDuration = (start, end) ->
     Math.floor(moment.duration(moment(end,"YYYYMMDDTHHmmss").diff(moment(start,"YYYYMMDDTHHmmss"))).asHours())+moment.utc(moment(end,"YYYYMMDDTHHmmss").diff(moment(start,"YYYYMMDDTHHmmss"))).format(":mm:ss")


:art: Suppress other autocomplete providers

--- lib/autocomplete-hack.coffee
+++ lib/autocomplete-hack.coffee
@@ -9,6 +9,8 @@
     Path = require('path')
     Hack.init()
     Provider =
+      inclusionPriority: 100
+      excludeLowerPriority: true # To suppress the html autocompleter
       selector: '.source.cpp, .source.hack, .source.php'
       disableForSelector: '.comment'
       Map:{


Comment support for maths and makeatsomething

--- grammars/latex.cson
+++ grammars/latex.cson
@@ -63,7 +63,6 @@
                 include: '#argumentScope'
             }
         ]
-
     }
     lineComment: {
         comment: 'Line comment. This will find an available % sign and match it and all that follows as a comment. Be sure to prevent edge cases like \\% or \\\% by only ever implementing in this order: doublebackslash -> escaped % -> %.'
@@ -314,6 +313,11 @@
         endCaptures:
             0:
                 name: 'string.other.math.inline.end.latex'
+        patterns: [
+            {
+                include: '#commentMeta'
+            }
+        ]
     }
     displayMathMode: {
         comment: 'This can be triggered using $$ or \[ \]. Both can be used in the same pair.'
@@ -331,6 +335,9 @@
             1:
                 name: 'invalid.deprecated.latex'
         patterns: [
+            {
+                include: '#commentMeta'
+            }
             {
                 comment: 'When in display math, the exit can only be $$ or \]'
                 name: 'invalid.illegal.latex'
@@ -447,4 +454,9 @@
         name: 'support.function.makeat.latex'
         begin: '(\\\\)makeatletter\\b'
         end: '(\\\\)makeatother\\b'
-    }
+        patterns: [
+            {
+                include: '#commentMeta'
+            }
+        ]
+    }


v.p.(environment->function).latex + removed dynamic environment scopes

--- grammars/latex.cson
+++ grammars/latex.cson
@@ -805,7 +805,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -816,7 +816,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: '$self' }]
   }
@@ -828,14 +828,14 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     end: '((\\\\)end)(\\{)(\\4)(\\})'
     endCaptures:
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
   }
   envDocument: {
@@ -846,18 +846,18 @@
       2: name: 'punctuation.definition.function.latex'
       # 3: This is for the first group scopes
       4: name: 'punctuation.definition.arguments.begin.latex'
-      5: name: 'variable.parameter.environment.document.latex'
+      5: name: 'variable.parameter.function.document.latex'
       6: name: 'punctuation.definition.arguments.end.latex'
   }
   envFigure: {
     comment: 'Matches the common figure environment'
-    contentName: 'meta.environment.float.$5.latex'
+    name: 'meta.environment.float.$5.latex'
     begin: '((\\\\)begin)(\\{)((figure)\\*?)(\\})(?:(\\[)(.*?)(\\]))?'
     beginCaptures:
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -868,7 +868,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: '$self' }]
   }
@@ -883,7 +883,7 @@
           1: name: 'support.function.environment.begin.latex'
           2: name: 'punctuation.definition.function.begin.latex'
           3: name: 'punctuation.definition.arguments.begin.latex'
-          4: name: 'variable.parameter.environment.$5.latex'
+          4: name: 'variable.parameter.function.latex'
           # 5: Used for meta scope name (basically just non starred version)
           6: name: 'punctuation.definition.arguments.end.latex'
           7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -894,7 +894,7 @@
           1: name: 'support.function.environment.end.latex'
           2: name: 'punctuation.definition.function.latex'
           3: name: 'punctuation.definition.arguments.begin.latex'
-          4: name: 'variable.parameter.environment.latex'
+          4: name: 'variable.parameter.function.latex'
           5: name: 'punctuation.definition.arguments.end.latex'
         patterns: [{ include: '$self' }]
       }
@@ -907,12 +907,12 @@
           1: name: 'support.function.environment.begin.latex'
           2: name: 'punctuation.definition.function.begin.latex'
           3: name: 'punctuation.definition.arguments.begin.latex'
-          4: name: 'variable.parameter.environment.$5.latex'
+          4: name: 'variable.parameter.function.latex'
           # 5: Used for meta scope name (basically just non starred version)
           6: name: 'punctuation.definition.arguments.end.latex'
           7: name: 'punctuation.definition.arguments.begin.latex'
           8:
-            name: 'variable.parameter.environment.latex'
+            name: 'variable.parameter.function.latex'
             patterns: [
               { include: '#numericConstants' }
               { include: '$self' }
@@ -923,7 +923,7 @@
           1: name: 'support.function.environment.end.latex'
           2: name: 'punctuation.definition.function.latex'
           3: name: 'punctuation.definition.arguments.begin.latex'
-          4: name: 'variable.parameter.environment.latex'
+          4: name: 'variable.parameter.function.latex'
           5: name: 'punctuation.definition.arguments.end.latex'
         patterns: [{ include: '$self' }]
       }
@@ -937,7 +937,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -948,7 +948,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: '$self' }]
   }
@@ -961,7 +961,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.verbatim.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Here to keep numbering consistent with other environments
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -972,7 +972,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
   }
   envGnuplot: {
@@ -984,7 +984,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Used for $4 and meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -995,7 +995,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.gnuplot' }]
   }
@@ -1007,7 +1007,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
     end: '((\\\\)end)(\\{)(\\4)(\\})'
@@ -1015,7 +1015,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.lua' }] # The l-latex package has complicated stuff here, so this might break
   }
@@ -1028,7 +1028,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1044,7 +1044,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'text.tex.latex.tikz' }] # The l-latex package has complicated stuff here, so this might break
   }
@@ -1193,7 +1193,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.$5.latex'
+      4: name: 'variable.parameter.function.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1207,7 +1207,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
   }
   mintPython: {
@@ -1218,7 +1218,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1232,7 +1232,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.python' }]
   }
@@ -1244,7 +1244,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1258,7 +1258,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.js' }]
   }
@@ -1270,7 +1270,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1284,7 +1284,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.json' }]
   }
@@ -1296,7 +1296,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1310,7 +1310,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.coffee' }]
   }
@@ -1322,7 +1322,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1336,7 +1336,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.css' }]
   }
@@ -1348,7 +1348,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1362,7 +1362,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.less' }]
   }
@@ -1374,7 +1374,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1388,7 +1388,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.xml' }]
   }
@@ -1400,7 +1400,7 @@
       1: name: 'support.function.environment.begin.latex'
       2: name: 'punctuation.definition.function.begin.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.minted.latex'
+      4: name: 'variable.parameter.function.minted.latex'
       # 5: Used for meta scope name (basically just non starred version)
       6: name: 'punctuation.definition.arguments.end.latex'
       7: name: 'punctuation.definition.arguments.optional.begin.latex'
@@ -1414,7 +1414,7 @@
       1: name: 'support.function.environment.end.latex'
       2: name: 'punctuation.definition.function.latex'
       3: name: 'punctuation.definition.arguments.begin.latex'
-      4: name: 'variable.parameter.environment.latex'
+      4: name: 'variable.parameter.function.latex'
       5: name: 'punctuation.definition.arguments.end.latex'
     patterns: [{ include: 'source.ruby' }]
   }


more helpful booting error message

more helpful booting error message

--- lib/connection/client.coffee
+++ lib/connection/client.coffee
@@ -152,7 +152,9 @@
       false

   notConnectedError: (action = 'do that') ->
-    if not @isConnected()
+    if @isBooting()
+      atom.notifications.addError "Can't #{action} until Julia finishes booting."
+    else if not @isConnected()
       atom.notifications.addError "Can't #{action} without a Julia client.",
         detail: "Start Julia using Packages → Julia → Start Julia."
       true


Dont create marker views when using the react editor

They only are necessary on the old editor!

--- lib/find-results-view.coffee
+++ lib/find-results-view.coffee
@@ -32,7 +32,7 @@

   getEditor: ->
     activeView = atom.workspaceView.getActiveView()
-    if activeView?.hasClass('editor') then activeView else null
+    if activeView?.hasClass('editor') and not activeView?.hasClass('react') then activeView else null

   getPane: ->
     atom.workspaceView.getActivePane()


Avoid the .label class because it conflicts with bootstrap

--- lib/fuzzy-finder-view.coffee
+++ lib/fuzzy-finder-view.coffee
@@ -59,7 +59,7 @@
         else
           typeClass = 'text-name'

-        @span fsUtils.base(path), class: "file label #{typeClass}"
+        @span fsUtils.base(path), class: "file #{typeClass}"
         if folder = project.relativize(fsUtils.directory(path))
           @span " - #{folder}/", class: 'directory'


jupyter: work in progress on jupyter notebook code evaluation via sage...

--- src/smc-webapp/jupyter/actions.coffee
+++ src/smc-webapp/jupyter/actions.coffee
@@ -11,6 +11,7 @@

 immutable  = require('immutable')
 underscore = require('underscore')
+#async      = require('async')

 misc       = require('smc-util/misc')

@@ -436,9 +437,10 @@

     run_code_cell: (id) =>
         @_set
-            type  : 'cell'
-            id    : id
-            state : 'start'
+            type   : 'cell'
+            id     : id
+            state  : 'start'
+            output : []

     run_selected_cells: =>
         v = @store.get_selected_cell_ids_list()
@@ -679,7 +681,41 @@
         dbg = @dbg("manager_run_cell")
         dbg()
         cell = @store.get('cells').get(id)
-
+        input = (cell.get('input') ? '').trim()
+        if input.length == 0
+            @_set
+                type   : 'cell'
+                id     : id
+                state  : null
+                output : []
+            return
+
+        @_sage_session ?= @_client.sage_session(path : @_directory)
+        outputs = []
+        state = 'running'
+        @_set
+            type   : 'cell'
+            id     : id
+            state  : 'running'
+            output : outputs
+        @_sage_session.call
+            input : input
+            cb    : (mesg) =>
+                outputs.push(mesg)
+                if mesg.done
+                    state = 'done'
+                @_set
+                    type   : 'cell'
+                    id     : id
+                    state  : state
+                    output : outputs
+        ###
+
+        @_set
+            type  : 'cell'
+            id    : id
+            state : ''
+            output : []
         try
             out = "#{eval(cell.get('input'))}"
         catch e
@@ -689,3 +725,4 @@
             id    : id
             state : 'done'
             output : [out]
+        ###


CallbackWrapper refactoring

CallbackWrapper refactoring

--- src/callback.coffee
+++ src/callback.coffee
@@ -18,13 +18,13 @@
       result

     @run = do (properties = @properties())-> ->
-      console.log this
-      for __object in properties
-        this[__object] = eval("(#{factorySource})('#{__object}')")
-        eval("#{__object} = this.#{__object};")
+      (->
+        for __object in properties
+          this[__object] = eval("(#{factorySource})('#{__object}')")
+          eval("#{__object} = this.#{__object};")

-      Context.set this
-      console.log 'in Callback'
-      fn.call(this)
+        # Context.set this
+        fn.call(this)
+      ).call Context.get()

     this


Remove unused function.

Remove unused function.

--- src/code/app.coffee
+++ src/code/app.coffee
@@ -5,17 +5,11 @@
 PaletteStore = require './stores/palette-store'
 HashParams   = require './utils/hash-parameters'

-getParameterByName = (name) ->
-  name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]')
-  regex = new RegExp "[#&]#{name}=([^&]*)"
-  results = regex.exec(location.hash)
-  if results is null then "" else decodeURIComponent results[1].replace(/\+/g, ' ')
-
 appView = null

 # App API
-window.Ivy =
-  initApp: (wireframes=false) ->
+window.Sage =
+  initApp: ->
     opts =
       # Valid opts are:
       # graphStore: store for the node-link graph


Restore new class names lost in merge

Restore new class names lost in merge

--- src/trix/views/attachment_view.coffee
+++ src/trix/views/attachment_view.coffee
@@ -57,9 +57,9 @@
   getClassName: ->
     names = ["attachment"]
     if @attachment.isPreviewable()
-      names.push("preview")
+      names.push("attachment--preview")
     else
-      names.push("file")
+      names.push("attachment--file")
     if extension = @attachment.getExtension()
       names.push(extension)
     names.join(" ")


omit unnecessary relative-path prefix

omit unnecessary relative-path prefix

--- lib/typescript-import.coffee
+++ lib/typescript-import.coffee
@@ -101,10 +101,13 @@
         if (os.platform() == 'win32')
             relative = relative.split(path.sep).join('/');

+        if(!/^\./.test(relative))
+          relative = './' + relative;
+
         if(defaultImport)
-          importClause = "import #{selection} from './#{relative}';\n"
+          importClause = "import #{selection} from '#{relative}';\n"
         else
-          importClause = "import {#{selection}} from './#{relative}';\n"
+          importClause = "import {#{selection}} from '#{relative}';\n"
         @addImportStatement(importClause)
 #        editor.insertText(selection + "\nimport #{selection} from './#{relative}'")
       else


Fix stdout argument issue

Fix stdout argument issue

--- lib/drive/drive.coffee
+++ lib/drive/drive.coffee
@@ -1,6 +1,6 @@
 os = require('os')
 fs = require('fs')
-_ = require('lodash')
+_ = require('lodash-contrib')
 async = require('async')

 IS_WINDOWS = os.platform() is 'win32'
@@ -29,7 +29,7 @@

 		(callback) ->
 			return callback() if not IS_WINDOWS
-			win32.rescanDrives(callback)
+			win32.rescanDrives(_.unary(callback))

 		(callback) ->
 			if not options.progress
@@ -39,7 +39,7 @@

 		(callback) ->
 			return callback() if not IS_WINDOWS
-			win32.rescanDrives(callback)
+			win32.rescanDrives(_.unary(callback))

 	], (error) ->
 		return callback() if not error?


open external links in separate tabs

open external links in separate tabs

--- client/index.coffee
+++ client/index.coffee
@@ -5,6 +5,11 @@

 $ ->
 	$.fancybox.showLoading()
+
+$ ->
+	$(document).on 'click', 'a', (e) ->
+		if e.target.host isnt document.location.host
+			e.target.target = '_blank'

 	$.getJSON TABLE_URL, (data) ->


fix blip substitution

fix blip substitution

resolves #4

--- src/factoids.coffee
+++ src/factoids.coffee
@@ -28,9 +28,9 @@
   robot.router.get "/#{robot.name}/factoids", (req, res) =>
     res.end JSON.stringify @factoids.data, null, 2

-  blip = '!' unless process.env.HUBOT_FACTOID_PREFIX
+  blip = process.env.HUBOT_FACTOID_PREFIX or '!'

-  robot.hear new RegExp("^#{blip}([\\w\\s-]{2,}\\w)( @.+)?", 'i'), (msg) =>
+  robot.hear new RegExp("^[#{blip}]([\\w\\s-]{2,}\\w)( @.+)?", 'i'), (msg) =>
     fact = @factoids.get msg.match[1]
     to = msg.match[2]
     if not fact? or fact.forgotten


Add red test (individual prestations)

Add red test (individual prestations)

--- test/openfisca/mapping/reverse.coffee
+++ test/openfisca/mapping/reverse.coffee
@@ -29,8 +29,11 @@
     paris_logement_familles: '2014-11': 1
     adpa: '2014-11': 1

+  INDIVIDU =
+    aah: '2014-11': 2
+
   OPENFISCA_RESPONSE =
-    value: [familles: [OPENFISCA_FAMILLE]]
+    value: [familles: [OPENFISCA_FAMILLE], individus: [INDIVIDU]]

   SITUATION =
     dateDeValeur: new Date '2014-11'
@@ -40,6 +43,9 @@

   it 'should remove unused properties', ->
     actual.should.not.have.property 'id'
+
+  it 'should extract individual prestations', ->
+    actual.aah.should.equal 2

   describe 'of an amount', ->
     it 'should round', ->


:bug: Messages is no longer a set It's a message registry

--- lib/linter-plus.coffee
+++ lib/linter-plus.coffee
@@ -107,7 +107,6 @@
     @emitter.on 'observe-editor-linters', callback

   deactivate: ->
-    @messages.clear()
     @subscriptions.dispose()
     @eachEditorLinter (linter) ->
       linter.destroy()


:art: Update bubble on render

:art: Update bubble on render

--- lib/linter-view.coffee
+++ lib/linter-view.coffee
@@ -11,6 +11,7 @@
     else
       @Linter.Panel.render @Messages
       @Linter.PanelModal.show() unless @Linter.PanelModal.isVisible()
+    @Linter.Bubble.update @Linter.ActiveEditor.getCursorBufferPosition()
     @Linter.Bottom.update @Messages

   renderMessages: (Values) ->


Remove skipped and unrelevant test

Remove skipped and unrelevant test

--- test/tests/DeviceComponentTest.coffee
+++ test/tests/DeviceComponentTest.coffee
@@ -178,60 +178,3 @@
 		device = new DeviceComponent()
 		device.deviceType = "fullscreen"
 		device.screenBackground.visible.should.equal false
-
-	describe.skip "when not showing bezel", ->
-		before ->
-			Utils.isFramerStudio = ->
-				return true
-
-		it "the background color should follow the screen color", ->
-			Canvas.backgroundColor = "red"
-			Framer.Device.screen.backgroundColor = "green"
-			Framer.Device.hideBezel = true
-			Canvas.backgroundColor.toName().should.eql "green"
-			Framer.Device.screen.backgroundColor = "blue"
-			Canvas.backgroundColor.toName().should.equal "blue"
-
-		it "should keep track of background changes", ->
-			Canvas.backgroundColor = "red"
-			Framer.Device.screen.backgroundColor = "green"
-			Framer.Device.hideBezel = true
-			Canvas.backgroundColor = "blue"
-			Canvas.backgroundColor.toName().should.equal "green"
-			Framer.Device.hideBezel = false
-			Canvas.backgroundColor.toName().should.equal "blue"
-
-	describe.skip "when showing bezel", ->
-		it "should revert to the background color before disabling the bezel", ->
-			Canvas.backgroundColor = "red"
-			Framer.Device.screen.backgroundColor = "green"
-			Framer.Device.hideBezel = true
-			Canvas.backgroundColor.toName().should.eql "green"
-			Framer.Device.hideBezel = false
-			Canvas.backgroundColor.toName().should.equal "red"
-
-		describe "when the device has a mask", ->
-
-			it "should should keep the backgroundColor black if the canvas background is set", ->
-				device = new DeviceComponent()
-				device.deviceType = "apple-iphone-x-silver"
-				device.context.run ->
-					device.background.backgroundColor = "red"
-					device.screen.backgroundColor = "green"
-					device.hideBezel = true
-					device.background.backgroundColor = "blue"
-					device.background.backgroundColor.toName().should.equal "black"
-					device.hideBezel = false
-					device.background.backgroundColor.toName().should.equal "blue"
-
-			it "should should set the backgroundColor to black", ->
-				device = new DeviceComponent()
-				device.deviceType = "apple-iphone-x-silver"
-				device.context.devicePixelRatio = 2
-				device.context.run ->
-					device.background.backgroundColor = "red"
-					device.screen.backgroundColor = "green"
-					device.hideBezel = true
-					device.background.backgroundColor.toName().should.equal "black"
-					device.hideBezel = false
-					device.background.backgroundColor.toName().should.equal "red"


governor: Emit error before state

governor: Emit error before state

More helpful, as the following state update may be invalid

--- src/governor.coffee
+++ src/governor.coffee
@@ -96,10 +96,10 @@
   runOnce: (callback) ->
     @runOnceInternal (err, state) =>
       debug 'ran iteration', err, state
-      @emit 'state', state
       @emit 'error', err if err
       for name, role of state
         @emit 'error', role.error if role.error
+      @emit 'state', state
       return callback err, state

 exports.Governor = Governor


fix mkdir recursive bug

fix mkdir recursive bug

--- lib/promiseSftp.coffee
+++ lib/promiseSftp.coffee
@@ -352,8 +352,13 @@
       result = Promise.resolve()
       tokens = dirPath.split(/\//g)
       currPath = if dirPath.charAt(0) == '/' then '/' else ''
+      isFirst = true;
       for token in tokens
-        currPath = "#{currPath}/#{token}"
+        if isFirst then
+          currPath = "#{token}"
+          isFirst = false
+        else
+          currPath = "#{currPath}/#{token}"
         if token == '.' || token == '..'
           continue
         addMkdirJob = (newPath) =>


Bug fix in put

Bug fix in put

If using a readableStream for a put operation, it would fail with:
```
Tue, 28 Jun 2016 12:20:13 GMT ringr:enterpriseApiCtrl 	name:         Error
	message:      Cannot pipe. Not readable.
	stack:        Error: Cannot pipe. Not readable.
    at WriteStream.Writable.pipe (_stream_writable.js:161:22)
    at /data/ringr-api/node_modules/promise-sftp/dist/promiseSftp.js:368:20
```

This was due to trying to pipe the writableStream into the readableStream:
```
stream.pipe(input);
```
reversed that and its fine:
```
input.pipe(stream)
```

--- lib/promiseSftp.coffee
+++ lib/promiseSftp.coffee
@@ -308,7 +308,7 @@
       .then (stream) ->
         if input instanceof Buffer
           return stream.end(input)
-        stream.pipe(input)
+        input.pipe(stream)
         undefined

     @append = (input, destPath) ->