Finer useRefTooltip to not include children

--- client/message.coffee
+++ client/message.coffee
@@ -239,57 +239,59 @@
       linkToAuthor message.group, user.username, title, icon
     ).join ', '
   , [message._id, message.group]
-  ref = useRefTooltip()
-
-

+  eomRef = useRefTooltip()
+
+

       <MaybeRootHeader message={message}/>
       <Submessage message={message}/>
-

-        {if authors
-          <>
-

-              Authors of visible messages in this thread:
-

-

-          </>
+

+

+          {if authors
+            <>
+

+                Authors of visible messages in this thread:
+

+

+            </>
+          }
+          {if authors and mentions
+

+          }
+          {if mentions
+            <>
+

+                Users @mentioned in visible messages in this thread:
+

+

+            </>
+          }
+

+

+

+            {if emailless()
+              Users who can read this message:
+            else
+              Users who can read this message, and whether they are subscribed to notifications:
+            }
+

+

+

+        {if orphans.length
+          orphans =
+            for orphan in orphans
+              <Submessage key={orphan._id} message={orphan}/>
+          orphans = (orphan for orphan in orphans when orphan?)
+          if orphans.length
+

+
+                {pluralize orphans.length, 'orphaned subthread'}
+
+              {orphans}
+

         }
-        {if authors and mentions
-

-        }
-        {if mentions
-          <>
-

-              Users @mentioned in visible messages in this thread:
-

-

-          </>
-        }
+        <Credits/>

-

-

-          {if emailless()
-            Users who can read this message:
-          else
-            Users who can read this message, and whether they are subscribed to notifications:
-          }
-

-

-

-      {if orphans.length
-        orphans =
-          for orphan in orphans
-            <Submessage key={orphan._id} message={orphan}/>
-        orphans = (orphan for orphan in orphans when orphan?)
-        if orphans.length
-

-
-              {pluralize orphans.length, 'orphaned subthread'}
-
-            {orphans}
-

-      }
-      <Credits/>

       <TableOfContentsID messageID={message._id}/>
@@ -1657,7 +1659,8 @@
     reply: canReply message
     super: canSuper message.group
   , [message._id]
-  ref = useRefTooltip()
+  ref = useRef()
+  headingRef = useRefTooltip()
   messageBodyRef = useRef()

   ## Support dragging rendered attachment like dragging message itself
@@ -1921,7 +1924,7 @@
     false  ## prevent form from submitting

-

+

       {if editing and not history?
         <input className="push-down form-control title" type="text" placeholder="Title" value={editTitle} onChange={onChangeTitle} tabIndex={tabindex0+18}/>
       else


Bug fix with Replace File never finishing

--- client/message.coffee
+++ client/message.coffee
@@ -1122,9 +1122,10 @@
     console.error "Attempt to replace #{message} with #{files.length} files -- expected 1"
   else
     file = files[0]
-    file.callback = (file2) ->
+    file.callback = (file2, done) ->
       Meteor.call 'messageUpdate', message,
         file: file2.uniqueIdentifier
+      , done
     file.group = group
     Files.resumable.addFile file, e


@mention completion improvements

@mention completion improvements

* Sort by lowercase username
* Still complete when pressing Backspace
* last(At)Word bug fix when no match, and cleanup

--- client/message.coffee
+++ client/message.coffee
@@ -743,32 +743,36 @@
               change.text = paste
               paste = null

-          lastWord = (cm) ->
+          lastAtWord = (cm) ->
             cursor = cm.getCursor()
-            return '' unless cursor.ch
+            return null unless cursor.ch
             text = cm.getRange
               line: cursor.line
               ch: 0
             , cursor
-            /@[^\s@]*$/.exec(text)[0]
+            (/@[^\s@]*$/.exec text)?[0]
           users = null
           editor.on 'keyup', (cm, e) ->
-            if e.key.length == 1 and  ## regular typing
-               (word = lastWord cm).startsWith '@'
+            if (e.key.length == 1 or e.key == 'Backspace') and ## regular typing
+               (word = lastAtWord cm)?  ## completable @mention
               word = word[1..]
               cm.showHint
                 completeSingle: false
                 hint: (cm) -> new Promise (callback) ->
-                  users ?= (Meteor.users.find {}, fields:
-                    username: 1
-                    "profile.fullname": 1
-                  ).map (user) ->
-                    display = user.username
-                    if user.profile.fullname
-                      display += " (#{user.profile.fullname})"
-                    text: user.username + ' '
-                    displayText: display
-                    search: display.toLowerCase().replace /\s/g, ''
+                  users ?= _.sortBy (
+                    (Meteor.users.find {}, fields:
+                      username: 1
+                      "profile.fullname": 1
+                    ).map (user) ->
+                      display = user.username
+                      if user.profile.fullname
+                        display += " (#{user.profile.fullname})"
+                      lower = display.toLowerCase()
+                      text: user.username + ' '
+                      displayText: display
+                      sort: lower
+                      search: lower.replace /\s/g, ''
+                  ), 'sort'
                   matches = (user for user in users \
                     when user.search.includes word.toLowerCase())
                   cursor = cm.getCursor()


let interpreter show its own prompt in del editor

--- client/session.coffee
+++ client/session.coffee
@@ -93,7 +93,7 @@

   prompt: (why) ->
     promptType = why; opts.setPromptType promptType; cm.setOption 'readOnly', false; cm.setOption 'cursorHeight', 1; l = cm.lineCount() - 1
-    if (why == 1 && !dirty[l]?) || why !in [1, 4]
+    if (why == 1 && !dirty[l]?) || why !in [1, 3, 4]
       cm.replaceRange '      ', {line: l, ch: 0}, {line: l, ch: cm.getLine(l).length}, 'D'
     cm.setCursor l, cm.getLine(l).length; return


deleted wrong line

deleted wrong line

--- coffee/_player.coffee
+++ coffee/_player.coffee
@@ -194,5 +194,4 @@
     PlayPrevious(__currentTrack.artist, __currentTrack.title)

 $('#player-container #track-info #next').on 'click', (e) ->
-    PlayNext(__currentTrack.artist, __currentTrack.title)
-    $('#tracklist-container').animate({ scrollTop: (+$(".track-container.playing").position().top)})+    PlayNext(__currentTrack.artist, __currentTrack.title)


sending all events to particles

sending all events to particles

--- test/timed_events.coffee
+++ test/timed_events.coffee
@@ -7,6 +7,8 @@
     ok true

   4.times ->
+    gameObject.trigger "update", 1
+

 # Clear out the module
 module()


adding view lifecycle events to BaseView

--- shared/base/view.coffee
+++ shared/base/view.coffee
@@ -164,11 +164,13 @@
   # @hydrate() is called, but before @getTemplateData() is called.
   _preRender: ->
     @preRender()
+    @trigger 'preRender'

   # Anything to do after rendering on the client.
   _postRender: ->
     @attachChildViews()
     @postRender()
+    @trigger 'postRender'

   # To be overridden by subclasses.
   preRender: noop
@@ -197,6 +199,7 @@

   setLoading: (loading) ->
     @$el.toggleClass('loading', loading)
+    @trigger 'loading', loading

   # When HTML is already present (rendered by server),
   # this is what gets called to bind to the element.
@@ -224,6 +227,8 @@
     # have a model or collection, then do so.
     if @options.lazy is true && !@options.collection? && !@options.model?
       @fetchLazy()
+
+    @trigger 'attach'

   # Happens client-side.
   # Find all of sub view DOM elements
@@ -240,6 +245,7 @@
     if (obj = @model || @collection)
       obj.off null, null, @
     super
+    @trigger 'remove'

   # Class methods
   # -------------


Also clipping the main element

Also clipping the main element

--- framer/Layer.coffee
+++ framer/Layer.coffee
@@ -244,7 +244,7 @@
 	@define "visible", layerProperty(@, "visible", "display", true, _.isBoolean)
 	@define "opacity", layerProperty(@, "opacity", "opacity", 1, _.isNumber)
 	@define "index", layerProperty(@, "index", "zIndex", 0, _.isNumber, null, {importable: false, exportable: false})
-	@define "clip", layerProperty(@, "clip", "overflow", false, _.isBoolean, null, {}, null, "_elementHTML")
+	@define "clip", layerProperty(@, "clip", "overflow", false, _.isBoolean, null, {}, null, "_elementHTML", true)

 	@define "scrollHorizontal", layerProperty @, "scrollHorizontal", "overflowX", false, _.isBoolean, null, {}, (layer, value) ->
 		layer.ignoreEvents = false if value is true


Use special placeholder for IPs

Use special placeholder for IPs

--- components/Log.coffee
+++ components/Log.coffee
@@ -31,11 +31,11 @@
   log = []

 display = (log) ->
-  for packet, i in log
+  for packet, i in log.__CONTENT__ or []
     packet = util.inspect packet, options
     packet = packet.replace /\n/g, "\n#{padding}"
     print.pf displayFormat, "DATA", packet
-    delete log[i]
+    delete log.__CONTENT__

   for group, l of log
     print.pf displayFormat, "BEGINGROUP", group
@@ -66,11 +66,11 @@

     @inPorts.in.on "connect", =>
       count++
-      @cache = []
+      @cache = {}
       @groups = []

       if @tag?
-        @cache[@tag] ?= []
+        @cache[@tag] ?= {}
         @groups.push @tag

     @inPorts.in.on "begingroup", (group) =>
@@ -81,7 +81,8 @@

     @inPorts.in.on "data", (data) =>
       here = @locate()
-      here.push deepCopy data
+      here.__CONTENT__ ?= []
+      here.__CONTENT__.push deepCopy data
       @outPorts.out.send data if @outPorts.out.isAttached()

     @inPorts.in.on "endgroup", (group) =>


Add macro checking to `foreach` and `syntax`

--- grammars/stata.cson
+++ grammars/stata.cson
@@ -106,18 +106,46 @@
       '1':
         'name': 'keyword.control.flow.stata'
       '2':
-        'name': 'entity.name.type.class.stata'
+        'patterns': [
+          {
+            'include': '#reserved_names'
+          }
+          {
+            'match': '[A-Za-z_][A-Za-z0-9_]{0,31}'
+            'name': 'entity.name.type.class.stata'
+          }
+          {
+            'include': '#macro-local'
+          }
+          {
+            'include': '#macro-global'
+          }
+        ]
       '3':
         'name': 'keyword.control.flow.stata'
-    'match': '\\b(foreach)\\s+([a-zA-Z0-9_]{1,31})\\s+(in|of var(list|lis|li|l)?|of new(list|lis|li|l)?|of num(list|lis|li|l)?)\\b'
-  }
-  {
-    'begin': '\\b(foreach)\\s+([a-zA-Z0-9_]{1,31})\\s+(of loc(al|a)?|of glo(bal|ba|b)?)\\b\\s*'
+    'match': '\\b(foreach)\\s+((?!in|of).+)\\s+(in|of var(list|lis|li|l)?|of new(list|lis|li|l)?|of num(list|lis|li|l)?)\\b'
+  }
+  {
+    'begin': '\\b(foreach)\\s+((?!in|of).+)\\s+(of loc(al|a)?|of glo(bal|ba|b)?)\\b\\s*'
     'beginCaptures':
       '1':
         'name': 'keyword.control.flow.stata'
       '2':
-        'name': 'entity.name.type.class.stata'
+        'patterns': [
+          {
+            'include': '#reserved_names'
+          }
+          {
+            'match': '[A-Za-z_][A-Za-z0-9_]{0,31}'
+            'name': 'entity.name.type.class.stata'
+          }
+          {
+            'include': '#macro-local'
+          }
+          {
+            'include': '#macro-global'
+          }
+        ]
       '3':
         'name': 'keyword.control.flow.stata'
     'end': '(?=\\s*\\{)'
@@ -338,23 +366,37 @@
           }
           {
             'comment': 'color options with parentheses'
-            'begin': '([a-zA-Z_0-9]+)(\\()'
+            'begin': '([\\S]+)(\\()'
             'beginCaptures':
               '1':
+                'patterns': [
+                  {
+                    'include': '#reserved_names'
+                  }
+                  {
+                    'match': '[A-Za-z_][A-Za-z0-9_]{0,31}'
+                    'name': 'entity.name.type.class.stata'
+                  }
+                  {
+                    'include': '#macro-local'
+                  }
+                  {
+                    'include': '#macro-global'
+                  }
+                ]
                 'comment': 'these are the names that become macros'
-                'name': 'entity.name.type.class.stata'
               '2':
                 'name': 'keyword.operator.parentheses.stata'
-            'end': '(\\))'
+            'end': '\\)'
             'endCaptures':
-              '1':
+              '0':
                 'name': 'keyword.operator.parentheses.stata'
             'patterns': [
               {
                 'comment': 'the first word is often a type'
-                'match': '(integer|intege|integ|inte|int|real|string|strin|stri|str)'
+                'match': 'integer|intege|integ|inte|int|real|string|strin|stri|str'
                 'captures':
-                  '1':
+                  '0':
                     'name': 'support.type.stata'
               }
               {


fix gulp build error

fix gulp build error

--- source/js/config.coffee
+++ source/js/config.coffee
@@ -1,11 +1,11 @@
 try
   local_config = require './local_config'
-catch error
+catch
   local_config = null

 Config = ->
-  @debug = local_config?.debug? or true
-  @host = local_config?.host? or "http://192.168.9.191:12345"
-  @debug_host = local_config?.debug_host? or "http://192.168.9.191:12345"
+  @debug = local_config?.debug or true
+  @host = local_config?.host or "http://192.168.9.191:12345"
+  @debug_host = local_config?.debug_host or "http://192.168.9.191:12345"

 module.exports = new Config()


workaround for ie11

workaround for ie11

when other browsers window.location.hash is ‘’ ie11 is ‘#’ :trollface:

--- spec/DeleteGraph.coffee
+++ spec/DeleteGraph.coffee
@@ -37,12 +37,17 @@

   describe 'graph delete', ->
     it 'should remove the graph and project and redirect home', (done) ->
+      @timeout 7000
       deleteButton = modal.shadowRoot.querySelector '.delete'
       chai.expect(deleteButton).to.be.an 'object'
       setTimeout ->
         Syn.click deleteButton
         setTimeout ->
-          chai.expect( win.location.hash ).to.equal ''
+          hash = win.location.hash
+          # workaround for ie
+          if hash is '#'
+            hash = ''
+          chai.expect(hash).to.equal ''
           done()
         , 1500
       , 1500


Load component with ComponentLoader

Load component with ComponentLoader

--- spec/DoSomething.coffee
+++ spec/DoSomething.coffee
@@ -1,20 +1,29 @@
 noflo = require 'noflo'
 unless noflo.isBrowser()
-  chai = require 'chai' unless chai
-  DoSomething = require '../components/DoSomething.coffee'
+  chai = require 'chai'
+  path = require 'path'
+  baseDir = path.resolve __dirname, '../'
 else
-  DoSomething = require 'noflo-browser-app/components/DoSomething.js'
+  baseDir = 'noflo-browser-app'

 describe 'DoSomething component', ->
   c = null
   ins = null
   out = null
+  before (done) ->
+    @timeout 4000
+    loader = new noflo.ComponentLoader baseDir
+    loader.load 'DoSomething', (err, instance) ->
+      return done err if err
+      c = instance
+      ins = noflo.internalSocket.createSocket()
+      c.inPorts.in.attach ins
+      done()
   beforeEach ->
-    c = DoSomething.getComponent()
-    ins = noflo.internalSocket.createSocket()
     out = noflo.internalSocket.createSocket()
-    c.inPorts.in.attach ins
     c.outPorts.out.attach out
+  afterEach ->
+    c.outPorts.out.detach out

   describe 'when instantiated', ->
     it 'should have an input port', ->


Fixed reference error in ClientSocket.coffee

--- src/ClientSocket.coffee
+++ src/ClientSocket.coffee
@@ -9,7 +9,7 @@
 SEND_WINDOW_SIZE_FACTOR = 10

 DroppedError = (message) ->
-    Error.captureStackTrace this, TooShortError
+    Error.captureStackTrace this, lumberjack.TooShortError
     @name = 'DroppedError'
     @message = message
 DroppedError.prototype = Object.create(Error.prototype)
@@ -131,4 +131,4 @@
         @_closed = true
         @_disconnect()

-module.exports = ClientSocket+module.exports = ClientSocket


Call parent to get events going for journal activities

--- src/JournalStore.coffee
+++ src/JournalStore.coffee
@@ -8,7 +8,8 @@
   genKey: (revId) -> "#{@graph.properties.id}_#{revId}"

   putTransaction: (revId, entries) ->
-    @lastRevision = revId if revId > @lastRevision
+    super revId, entries
+
     trans = @db.transaction ['journals'], 'readwrite'
     store = trans.objectStore 'journals'

@@ -19,6 +20,8 @@
       graph: @graph.properties.id
       revId: revId
       entries: entries
+
+    @transactions[revId] = entries

   fetchTransaction: (revId) ->
     return @transactions[revId]


make canKeppInitalSize as getViewerSize's argument.

--- js/3panorama.coffee
+++ js/3panorama.coffee
@@ -64,7 +64,7 @@

     #  size of render
     records = {} # the camera size records
-    getViewerSize = ->
+    getViewerSize = (canKeepInitalSize = settings.canKeepInitalSize)->
         if not settings.canUseWindowSize
             rect = container.getBoundingClientRect()
             width = rect.width
@@ -85,7 +85,7 @@
         else if not width # height is not zero
             width = height * settings.alternateRatio

-        if settings.canKeepInitalSize is true
+        if canKeepInitalSize is true
             if width not of records
                 # record width height, may use later
                 records[width] = height


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/clamp_bounds.coffee
+++ src/clamp_bounds.coffee
@@ -1,6 +1,5 @@
 ###*
-The ClampBounds module provides a declarative way to manage cooldowns on
-GameObject's properties.
+The ClampBounds module

 # Health regeneration


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/clamp_bounds.coffee
+++ src/clamp_bounds.coffee
@@ -1,46 +0,0 @@
-###*
-The ClampBounds module adds a check to make sure
-that the including GameObject doesn't move outside
-the viewport.
-
-

-  # create a player and include ClampBounds
-  player = GameObject
-    includedModules: ["ClampBounds"]
-    width: 5
-    height: 17
-
-  # put the player outside the viewport
-  player.I.x = -400
-  player.I.y = 1000
-
-  # update the player so ClampBounds can set
-  # his position back inside the viewport.
-  player.update()
-
-  # x, y position is based on the center point so
-  # the position the player is set to is based on
-  # half their width and height
-  player.I.x
-  # => 2.5 # half the player's width
-
-  player.I.y
-  # => 311.5 # The default App.height (320) - half the player's height
-

-
-@name Cooldown
-@module
-@constructor
-@param {Object} I Instance variables
-@param {Core} self Reference to including object
-###
-ClampBounds = (I={}, self) ->
-  Object.reverseMerge I,
-    x: 0
-    y: 0
-    width: 32
-    height: 32
-
-  self.bind "update", ->
-    I.x = I.x.clamp(I.width / 2, App.width - I.width / 2)
-    I.y = I.y.clamp(I.height / 2, App.height - I.height / 2)


fix interrupt keybinding

fix interrupt keybinding

--- keymaps/julia-client.cson
+++ keymaps/julia-client.cson
@@ -30,7 +30,9 @@
   'ctrl-j ctrl-d': 'julia-client:toggle-documentation'

 '.platform-win32 .ink-console,
- .platform-linux .ink-console':
+ .platform-win32 .ink-console atom-text-editor,
+ .platform-linux .ink-console,
+ .platform-linux .ink-console atom-text-editor':
   'ctrl-shift-c': 'julia-client:interrupt-julia'
   'ctrl-`': 'julia-client:toggle-console'


Updated html5-writer (Removed writeNodePretty and other prettification related code)

--- src/html5-writer.coffee
+++ src/html5-writer.coffee
@@ -3,12 +3,7 @@

 class Html5Writer

-  constructor: (options = {}) ->
-    {
-      indentCharacter
-    } = options
-
-    @indentCharacter = indentCharacter or '  '
+  constructor: ->

   writeScope: (scope)->
     returnScope = ''
@@ -70,74 +65,6 @@

       throw new Error 'Unsupported Node'

-
-  writeNodePretty: (node, indentLevel = 0)->
-
-    console.log '"cohtml".Html5Writer.writeNodePretty is deprecated. Please use third party html prettifiers.'
-
-    padding = (@indentCharacter for _ in [0...indentLevel]).join ''
-
-    if node instanceof Html5Node
-
-      signature = tag = '' + node.tag
-
-      for attribute, value of node.attributeMap
-        signature += ' ' + attribute
-        if value
-          signature += '="' + value + '"'
-
-      if node.isNonClosing
-        html = '<' + signature + '>'
-        if node.childrenList.length > 0
-          for child in node.childrenList
-            html += @writeNode child, (indentLevel + 0)
-        return html
-
-      if node.isSelfClosing
-        html = '<' + signature + ' />'
-      else
-        html = '<' + signature + '>'
-
-        if node.childrenList.length > 0
-          for child in node.childrenList
-            html += @writeNode child, (indentLevel + 1)
-        else
-          if node.innerText
-            html += node.innerText
-
-        ## padding insertion at the closing tag
-        if node.childrenList.length is 0
-
-          if node.innerText and (node.innerText.indexOf '\n') > -1
-            if (node.innerText.lastIndexOf '\n') is node.innerText.length - 1
-              html += padding + '</' + tag + '>'
-            else
-              html += '\n' + padding + '</' + tag + '>'
-          else
-            html += '</' + tag + '>'
-
-        else
-
-          if node.childrenList.length is 1 and node.childrenList[0] instanceof Html5TextNode
-            html += '</' + tag + '>'
-          else
-            html += '\n' + padding + '</' + tag + '>'
-
-      html = '\n' + padding + html
-      return html
-
-    else if node instanceof Html5TextNode
-
-      return node.innerText
-
-    else if node instanceof Html5CommentNode
-
-      return '<!-- ' + node.innerText + ' -->'
-
-    else
-
-      throw new Error 'Unsupported Node'
-
 @Html5Writer = Html5Writer


Remove: console.log

Remove: console.log

--- lib/Refactor.coffee
+++ lib/Refactor.coffee
@@ -11,7 +11,6 @@
 exports.Refactor = class Refactor

   constructor: (code) ->
-    console.log inspect coffee.nodes(code), false, null
     @node = new Node coffee.nodes code

   find: (range) ->
@@ -48,8 +47,8 @@

     if @hasScope
       @depth++
-      # if Refactor.verbose
-      #   console.log "#{pad '', 15}|#{pad 'SCOPE', 10}|#{@getIndent()}"
+      if Refactor.verbose
+        console.log "#{pad '', 15}|#{pad 'SCOPE', 10}|#{@getIndent()}-"

     if params?
       nodes = (new Node param, @, @depth, 'param' for param in params)


move after function down the chain, add remove utility fn

--- lib/api/init.coffee
+++ lib/api/init.coffee
@@ -19,11 +19,16 @@
       .then(get_user_config.bind(@))
       .then(user_before_fn.bind(@))
       .then(prompt_for_info.bind(@))
-      .then(user_after_fn.bind(@))
       .then(update_template.bind(@))
       .then(copy_template.bind(@))
       .then(replace_ejs.bind(@))
+      .then(user_after_fn.bind(@))
       .yield("project #{@template} created!")
+
+  # intended for use in the after function, quick way to remove
+  # files/folders that users wanted to nix after the prompts.
+  remove: (f) ->
+    fs.unlinkSync(path.resolve(@target, f))

   #
   # @api private


Tab well placed. The idea in workingDirectory is executing "go test" in the file directory

--- lib/grammars.coffee
+++ lib/grammars.coffee
@@ -137,10 +137,9 @@
   Go:
     "File Based":
       command: "go"
-        args: (context) ->
-          if context.filepath.match(/_test.go/)
-            ['test', '']
-          else ['run', context.filepath]
+      args: (context) ->
+        if context.filepath.match(/_test.go/) then ['test', '' ]
+        else ['run', context.filepath]
       workingDirectory: atom.workspace.getActivePaneItem()?.buffer?.file?.getParent?().getPath?()

   Groovy:


fixed tests

fixed tests

--- src/model/statsd.coffee
+++ src/model/statsd.coffee
@@ -37,7 +37,7 @@
       results = {};
   var allowedIds = allowedIds.length > 0 ? allowedIds : yield metrics.getAllowedChannelIDs(userRequesting)
   var data = []
-  var status_array = ['Processing', 'Failed', 'Completed', 'Successful', 'Completed with error(s)']
+  var status_array = ['Successful', 'Failed', 'Completed', 'Processing', 'Completed with error(s)']

   for (var j = 0; j < allowedIds.length; j++) {
       var render_url = "/render?target=transformNull(summarize(stats.counters." + domain + ".Channels." + allowedIds[j]


whitespace

whitespace

--- src/models/claim.coffee
+++ src/models/claim.coffee
@@ -18,7 +18,6 @@
       throw error if error
       callback results

-
   @putn: (props, callback) ->
     { source, target, rating } = props
     ratingParams = params plain: { rating, timestamp: 'timestamp()' }


remove coffeescript version

remove coffeescript version

--- src/oscilloscope.coffee
+++ src/oscilloscope.coffee
@@ -1,54 +0,0 @@
-class Oscilloscope
-
-  constructor: (source, options = { }) ->
-    return new Oscilloscope source, options unless this instanceof Oscilloscope
-
-    unless source instanceof AudioNode
-      throw new Error "Signal must be an AudioNode"
-
-    if source instanceof AnalyserNode
-      @analyser = source
-    else
-      @analyser = source.context.createAnalyser()
-      source.connect @analyser
-
-    @analyser.fftSize = options.fftSize if options.fftSize
-    @timeDomain = new Uint8Array(@analyser.frequencyBinCount)
-    @drawRequest = 0
-
-  # begin default signal animation
-  animate: (@ctx, x0, y0, width, height) =>
-    return if @drawRequest
-    do drawLoop = =>
-      @ctx.clearRect 0, 0, @ctx.canvas.width, @ctx.canvas.height
-      @draw @ctx, x0, y0, width, height
-      @drawRequest = window.requestAnimationFrame drawLoop
-
-  # stop default signal animation
-  stop: =>
-    cancelAnimationFrame @drawRequest
-    @drawRequest = 0
-    @ctx.clearRect 0, 0, @ctx.canvas.width, @ctx.canvas.height
-
-  # draw signal
-  draw: (ctx, x0, y0, width, height) =>
-    # TODO: maybe cache values
-    x0 = x0 || 0
-    y0 = y0 || 0
-    width = width || (ctx.canvas.width - x0)
-    height = height || (ctx.canvas.height - y0)
-
-    @analyser.getByteTimeDomainData @timeDomain
-    step = width / @timeDomain.length
-
-    ctx.beginPath()
-    # drawing loop (skipping every second record)
-    for value, i in @timeDomain by 2
-      percent = value / 256
-      x = x0 + i * step
-      y = y0 + height * percent
-      ctx.lineTo x, y
-
-    ctx.stroke()
-
-module.exports = Oscilloscope


LongInt: incorporated the cleanup step into the sub() helper function.

--- lib/long_int.coffee
+++ lib/long_int.coffee
@@ -64,14 +64,16 @@
   else
     s or r

-sub = (r, s, b = 0) ->
-  if b or (r and s)
-    [r_, s_] = [r or ZERO, s or ZERO]
-    x = r_.first() - s_.first() - b
-    [digit, borrow] = if x < 0 then [x + BASE, 1] else [x, 0]
-    new Stream(digit, -> sub(r_.rest(), s_.rest(), borrow))
-  else
-    s or r
+sub = (r, s) ->
+  step = (r, s, b = 0) ->
+    if b or (r and s)
+      [r_, s_] = [r or ZERO, s or ZERO]
+      x = r_.first() - s_.first() - b
+      [digit, borrow] = if x < 0 then [x + BASE, 1] else [x, 0]
+      new Stream(digit, -> step(r_.rest(), s_.rest(), borrow))
+    else
+      s or r
+  cleanup step(r, s)

 split = (n) -> [n % HALFBASE, Math.floor n / HALFBASE]

@@ -106,7 +108,7 @@
     d = s.last() + 1
     f = (Math.floor n / d) or (if cmp(h, s) >= 0 then 1 else 0)
     log "divmod step(#{dump(q)}, #{dump(h)}, #{dump(t)}, #{shift}) -- f = #{f}"
-    [q_, h_] = [add(q, new Stream(f)), cleanup(sub(h, streamTimesDigit(s, f)))]
+    [q_, h_] = [add(q, new Stream(f)), sub(h, streamTimesDigit(s, f))]

     if f and not shift
       recur -> step(q_, h_, t, shift)
@@ -164,9 +166,9 @@
     if this.sign != other.sign
       this.plus other.neg()
     else if this.abs().cmp(other.abs()) < 0
-      create(cleanup(sub(other.digits, this.digits)), -this.sign)
-    else
-      create(cleanup(sub(this.digits, other.digits)), this.sign)
+      create(sub(other.digits, this.digits), -this.sign)
+    else
+      create(sub(this.digits, other.digits), this.sign)

   times: (other) ->
     create mul(null, this.digits, other.digits), this.sign * other.sign


Fix reparenting: actually remove child!

Fix reparenting: actually remove child!

--- lib/messages.coffee
+++ lib/messages.coffee
@@ -220,7 +220,7 @@
     if oldParent
       oldParent = findMessageParent child
       if oldParent?
-        Messages.update oldParent,
+        Messages.update oldParent._id,
           $pop: children: child
     if parent?
       if position?


cleanup and now occurrence mutation flashed correctly

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -205,20 +205,7 @@
       @editor.transact =>
         @mutateSelection(selection) for selection in @editor.getSelections()

-    # Cursor position placement [same as before OR start of original selection]
-
-    if @needStay()
-      # same as before
-      for selection in @editor.getSelections()
-        if @isRestorableCursorPositionForSelection(selection)
-          @restoreCursorPositionForSelection(selection)
-        else
-          selection.destroy()
-    else
-      # start of original selection
-      @restoreCursorPositions()
-
-    @pointBySelection = null
+    @restoreCursorPositions()
     @onDidRestoreCursorPositions?() # FIXME
     @activateMode(@finalMode, @finalSubmode)

@@ -249,11 +236,10 @@
     @emitWillSelectTarget()
     @target.select()
     saveCursorsToRestoreAfterSelect?()
-
+    @emitDidSelectTarget()
     @flashIfNecessary(@editor.getSelectedBufferRanges())
     @trackChangeIfNecessary()

-    @emitDidSelectTarget()
     haveSomeSelection(@editor)

   updatePreviousSelection: ->


Refactor

Refactor

--- lib/provider.coffee
+++ lib/provider.coffee
@@ -12,7 +12,6 @@
     file = editor.getText()
     regex = /(Given|And|When|Then)(.*)/g
     match = regex.exec(file)
-    console.log match

     line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
     @getCompletions(line, file)
@@ -41,7 +40,6 @@
       return if error?
       @completions = {}
       classes = JSON.parse(content)
-      @loadProperty('atom', 'Atom', classes)
       return

   getCompletions: (line, file) ->
@@ -55,22 +53,6 @@
       results.push({"text":myRegexArray[2].replace /^\s+|\s+$/g, ""})
     return results

-  getPropertyClass: (name) ->
-    atom[name]?.constructor?.name
-
-  loadProperty: (propertyName, className, classes, parent) ->
-    classCompletions = classes[className]
-    return unless classCompletions?
-
-    @completions[propertyName] = completions: []
-
-    for completion in classCompletions
-      @completions[propertyName].completions.push(completion)
-      if completion.type is 'property'
-        propertyClass = @getPropertyClass(completion.name)
-        @loadProperty(completion.name, propertyClass, classes)
-    return
-
 clone = (obj) ->
   newObj = {}
   newObj[k] = v for k, v of obj


Remove old provider.

Remove old provider.

--- lib/provider.coffee
+++ lib/provider.coffee
@@ -1,42 +0,0 @@
-path = require 'path'
-child_process = require 'child_process'
-
-module.exports = class LinterProvider
-  regex = /(.+) in (.+):(\d+): (.+)/
-
-  getCommand = ->
-    executable = atom.config.get 'linter-crystal.compilerExecPath'
-    command = atom.config.get 'linter-crystal.command'
-    final = "#{executable} #{command}"
-    unless atom.config.get 'linter-crystal.buildArtifacts'
-      final = "#{final} --no-build"
-    unless atom.config.get 'linter-crystal.colorOutput'
-      final = "#{final} --no-color"
-    return final
-
-  getCommandWithFile = (file) -> "#{getCommand()} #{file}"
-
-  # This is based on code taken right from the linter-plus rewrite
-  #   of `linter-crystal`.
-  lint: (TextEditor) ->
-    new Promise (Resolve) ->
-      file = path.basename TextEditor.getPath()
-      cwd = path.dirname TextEditor.getPath()
-      data = []
-      command = getCommandWithFile file
-      console.log "Crystal Linter Command: #{command}" if atom.inDevMode()
-      process = child_process.exec command, {cwd: cwd}
-      process.stdout.on 'data', (d) -> data.push d.toString()
-      process.on 'close', ->
-        toReturn = []
-        for line in data
-          console.log "Crystal Linter Provider: #{line}" if atom.inDevMode()
-          if line.match regex
-            [type, file, line, message] = line.match(regex)[1..4]
-            toReturn.push(
-              type: type,
-              text: message,
-              filePath: path.join(cwd, file).normalize()
-              range: [[line - 1, 0], [line - 1, 0]]
-            )
-        Resolve toReturn


Uses autocomplete-plus v2.0

Uses autocomplete-plus v2.0

--- lib/provider.coffee
+++ lib/provider.coffee
@@ -8,28 +8,11 @@

 module.exports =
 class ReferenceProvider
-  ###
-  For a while, I intended to continue using XRegExp with this `wordRegex`:
-
-  ```
-  wordRegex: XRegExp('(?:^|\\p{WhiteSpace})@[\\p{Letter}\\p{Number}\._-]*')
-  ```
-
-  But I found that the regular expression given here seems to work well. If
-  there are problems with Unicode characters, I can switch back to the other.
-
-  This regular expression is also more lenient about what punctuation it will
-  accept. Whereas the alternate only allows the punctuation which might be
-  expected in a BibTeX key, this will accept all sorts. It does not accept a
-  second `@`, as this would become confusing.
-  ###
-  wordRegex: XRegExp('(?:^|[\\p{WhiteSpace}\\p{Punctuation}])@[\\p{Letter}\\p{Number}\._-]*')

   atom.deserializers.add(this)
   @deserialize: ({data}) -> new ReferenceProvider(data)

   constructor: (state) ->
-    console.log state
     if state and Object.keys(state).length != 0
       @references = state.references
       @possibleWords = state.possibleWords
@@ -49,27 +32,35 @@
     @provider =
       selector: atom.config.get "autocomplete-bibtex.scope"
       disableForSelector: ".comment"
+      inclusionPriority: 1
+      excludeLowerPriority: true

       getSuggestions: ({editor, bufferPosition}) ->
         prefix = @getPrefix(editor, bufferPosition)
         new Promise (resolve) ->
-          suggestions = []
-          for word in fuzzaldrin.filter state.possibleWords, prefix.normalize().replace(/^@/, ''), { key: 'author' }
-            suggestion = {
-              text: word.key
-              displayText: word.label
-              leftLabel: word.key
-              type: "constant"
-              iconHTML: ''
-            }
-            suggestions = suggestions.concat suggestion
-          resolve(suggestions)
+          if prefix[0] == "@"
+            p = prefix.normalize().replace(/^@/, '')
+            suggestions = []
+            for word in fuzzaldrin.filter state.possibleWords, p, { key: 'author' }
+              suggestion = {
+                text: word.key
+                displayText: word.label
+                leftLabel: word.key
+                type: "constant"
+                iconHTML: ''
+              }
+              suggestions = suggestions.concat suggestion
+            resolve(suggestions)

       getPrefix: (editor, bufferPosition) ->
         # Whatever your prefix regex might be
-        regex = XRegExp('(?:^|[\\p{WhiteSpace}\\p{Punctuation}])@[\\p{Letter}\\p{Number}\._-]*')
+        regex = /@[\w-]+/
+        wordregex = XRegExp('(?:^|[\\p{WhiteSpace}\\p{Punctuation}])@[\\p{Letter}\\p{Number}\._-]*')
+        cursor = editor.getCursors()[0]
+        start = cursor.getBeginningOfCurrentWordBufferPosition({ wordRegex: wordregex, allowPrevious: false })
+        end = bufferPosition
         # Get the text for the line up to the triggered buffer position
-        line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
+        line = editor.getTextInRange([start, bufferPosition])
         # Match the regex to the line, and return the match
         line.match(regex)?[0] or ''


fix config description

fix config description

--- lib/settings.coffee
+++ lib/settings.coffee
@@ -106,7 +106,7 @@
     default: false
     description: """
     Can: `_ i (` to replace inner-parenthesis with register's value

-    Can: `_ i ;` to replace inner-any-pair if you enabled `keymapSemicolonToInnerAnyPairInOperatorPendingMode`

+    Can: `_ ;` to replace inner-any-pair if you enabled `keymapSemicolonToInnerAnyPairInOperatorPendingMode`

     Conflicts: `_`( `move-to-first-character-of-line-and-down` ) motion. Who use this??
     """
   keymapPToPutWithAutoIndent:


Call .dispose() instead of .off()

Call .dispose() instead of .off()

--- lib/tab-view.coffee
+++ lib/tab-view.coffee
@@ -100,7 +100,7 @@
     @modifiedSubscription?.dispose()
     @iconSubscription?.dispose()
     @mouseEnterSubscription?.dispose()
-    @configSubscription?.off() # Not a Disposable yet
+    @configSubscription?.dispose()
     @destroyTooltip()
     @remove()


Switch order of call to _listenTouches and declaration of _listenTouches

When importing this through RequireJS, the document.ready event fires immediately (as Quo is loaded after the document has already become ready) and at this point, _listenTouches is undefined.  Simply switching the order of the declaration prevents this issue.

--- src/quo.gestures.coffee
+++ src/quo.gestures.coffee
@@ -21,14 +21,14 @@
             $$(document.body).delegate @selector, event_name, callback
         @

-    $$(document).ready -> _listenTouches()
-
     _listenTouches = ->
         environment = $$ document.body
         environment.bind "touchstart", _onTouchStart
         environment.bind "touchmove", _onTouchMove
         environment.bind "touchend", _onTouchEnd
         environment.bind "touchcancel", _cleanGesture
+
+    $$(document).ready -> _listenTouches()

     _onTouchStart = (event) ->
         EVENT = event


Changed if statements within _onTouchEnd - previously they were strictly checking for GESTURE.angle_difference !== 0 and GESTURE.distance_difference !== 0 but because capture rotation and capture pinch return undefined if they are below the predetermined threshold it meant that any double touch that wasn't a pinch or a zoom (like a double tap) was still firing these events: 'pinch', 'pinchIn' 'rotate', 'rotateLeft' So just changed them to check for if angle_difference and distance_difference are truthy so a negative or positive number will pass through but undefined will not. Also added in a 'twoTap' event for when you do a double finger tap as I couldn't find any support for this anywhere. I think the coffee script is correct but not sure as I usually just do pure JS. Also couldn't find any instructions for if a build was required before committing (assume that's what Grunt is for?) but you can at least see the changes here and decide if they're worthwhile. :)

--- src/quo.gestures.coffee
+++ src/quo.gestures.coffee
@@ -8,7 +8,7 @@
     TOUCH_TIMEOUT = undefined
     HOLD_DELAY = 650
     GESTURES = ["touch",
-                "tap", "singleTap", "doubleTap", "hold",
+                "tap", "singleTap", "twoTap" "doubleTap", "hold",
                 "swipe", "swiping", "swipeLeft", "swipeRight", "swipeUp", "swipeDown",
                 "rotate", "rotating", "rotateLeft", "rotateRight",
                 "pinch", "pinching", "pinchIn", "pinchOut",
@@ -105,12 +105,12 @@
                     ), 100)
         else
             anyevent = false
-            if GESTURE.angle_difference isnt 0
+            if GESTURE.angle_difference
                 _trigger "rotate", angle: GESTURE.angle_difference
                 rotation_direction = if GESTURE.angle_difference > 0 then "rotateRight" else "rotateLeft"
                 _trigger rotation_direction, angle: GESTURE.angle_difference
                 anyevent = true
-            if GESTURE.distance_difference isnt 0
+            if GESTURE.distance_difference
                 _trigger "pinch", angle: GESTURE.distance_difference
                 pinch_direction = if GESTURE.distance_difference > 0 then "pinchOut" else "pinchIn"
                 _trigger pinch_direction, distance: GESTURE.distance_difference
@@ -120,6 +120,9 @@
                     _trigger "drag"
                     drag_direction = _swipeDirection(FIRST_TOUCH[0].x, CURRENT_TOUCH[0].x, FIRST_TOUCH[0].y, CURRENT_TOUCH[0].y)
                     _trigger "drag" + drag_direction
+                    anyevent = true
+            if not anyevent
+                _trigger "twoTap"
             _cleanGesture()
         EVENT = undefined


add tinyint to dbTypeToJsType

add tinyint to dbTypeToJsType

--- src/schema/index.coffee
+++ src/schema/index.coffee
@@ -87,6 +87,7 @@
     varchar: 'string'
     datetime: 'date'
     int: 'number'
+    tinyint: 'number'
 }

 class Column extends DbObject


allow locking the orientation

allow locking the orientation

--- src/shared/Utils.coffee
+++ src/shared/Utils.coffee
@@ -140,4 +140,58 @@
   @isMobile = ->
     /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)

+  # Allow only one screen orientation
+  #
+  # Valid orientation types:
+  #
+  # * all
+  # * landscape
+  # * portrait
+  #
+  # @example Utils.orientation('landscape')
+  #
+  @orientation = (orientation = 'all')->
+    existingElement = document.querySelector('.ce-turn-screen')
+    document.body.removeChild(existingElement) if existingElement?
+    existingStyle = document.querySelector('.ce-turn-screen-style')
+    document.head.removeChild(existingStyle) if existingStyle?
+    return if orientation == 'all'
+
+    throw new Error("invalid orientation type '#{orientation}'") unless ['all', 'landscape', 'portrait'].includes(orientation)
+
+    div = document.createElement('div')
+    div.setAttribute 'class', 'ce-turn-screen'
+    div.style = 'position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; background-color: #f0f0f0;'
+
+    img = document.createElement('img')
+    img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AYNDy012n9FrgAABkxJREFUeNrt3T1sG+cBgGGTRx3FH5GipADhjyGAg5EgaBa1BWog7dIgY5DFXQLEBRJ4yFI0S7aqyOAtS1B3bBEgWYIMLYJ0MZKxk7yoSzoYgmFRaAtRKgmSIU++6xKgi4eTJYo0+TzzR+l0pxffd+Tx7to1AAAAAAAAAOD/MnbB07Xb7d2HDx/uTvN37OzsJPb0bOzt7aX638/aVU9Xq9V+1263d+2J5SYQkSAQkSAQkSAQkSAQkSAQkSAQkSAQkbCocsv2BzcajReDIHg1CIJXgiBo53K57SAI6kEQbGaz2Vo2m13NZDLhOSK5Nu1P3NN+6svlX52w8IE0m80bKysrb4Rh+Nrq6urNlZWV5hRmkqlHghnk0rRarZ/m8/lbxWLxrTAM21e03BKJQOZ66fRCPp+/XSqV3s3n8zdmdE4iEoHM3RLq5UKh8MHa2trb2Ww2Pwcn7iIRyFyE8VKpVNotl8u3MpmMk1gE8sNSaqtYLH5UqVTey2QywTxt28nJye/NHgKZiXq9ngnD8M76+vrdXC63Pm/bJw6BzHI51a5UKn8qFos/n8ftE4dAZmZ7e/udWq32SRAEa1f1O5MkeZJ2+SYOgcxqSbVaKpXuVavVX1/2zz47OzudTCb7URTtR1G0H8fxQRzHnSRJ/pUkSffo6ChK84msOAQyqyVVo1qt/qVQKPz4Mn5eHMfj4XD4zXg8vh9F0f04jvePjo4udEmCOAQyqzh+tLGx8XUYhq0LLpOS4XD47Wg0+iyKoi87nc5/nXPwXAfSarVubm1tfR0EQfUCs8X3/X7/09Fo9PHh4eF3TshZiECuX7/+i83Nza+CICg/YxiTXq93bzQa3e10Ov+exjaKQyCzmjl+dpE4+v3+F4PB4MPDw8OH09pGcQhkZuccW1tbf3uWOKIo6pyent559OjRV9PcRnEIZFZxNDY2Np7pnKPX630+GAze73Q6p+Jg4QKp1+ur1Wr1r+d9typJkqjb7f7m4ODg3rS3URzMLJByufzHQqGwc57XnJ2d/ef4+PjNx48f/10cLGwg29vb71Qqldvnec1kMnnU7XZfPzw8/OdVbKM4mEkgzWazXavVPjnPa8bj8XfdbveXnU7nsUPGVbrS2/7U6/VMpVL583kuPPxh5hAHix9IGIZ3isXia+c55+h2u6+Lg4UPpNFobK2vr99NOz6O48nx8fGbV3XOATMNpFgsfnSebwKenJz89irerYKZB9JsNl+qVCrvpR3f6/U+Pzg4+IPDw1IEUiqVdtN+Qy+Kos5gMHjfoWEpAmk2my+Xy+Vbacefnp7emfblIzA3gRQKhQ/S3req3+9/Me0LD2FuAmk0Gi+sra29nWZsHMeTwWDwoUPC0gSSz+dvp70daK/XuzfN73PA3AVSKpXeTTl7fD8aje46HCxNIK1W6ydp77Le7/c/ndbXZGEuA8nn879KMy5JkmQ0Gn3sULBUgRSLxbfSjBsOh99O4+4jMLeBNJvNG2mf7DQajT5zGFiqQFZWVt5IeXI+jqLoS4eBpQokDMNUl7QPh8NvLvOOh/BcBLK6unozzbjxeHzfIWCpAmk0Gi+mfdRyFEUCYbkCCYLg1TTjzs7OTuM43ncIWLZAXkkzbjKZXPgRBPA8BpLq7d0oisweLF8guVxuO+US6x92P8s4g9TTjHvy5MmB3c8yBrKZZlySJB27n6ULJJvN1tKMi+PY1bssZSCrKWcQ3ztn+QLJZDJhmnFHR0cju595d+k3r37w4EFgt2IGAYGAQACBgEBAICAQEAgIBAQCAgGBAAIBgYBAQCAgEBAICAQEAgIBgQACAYHA5Ul947idnR0Pu5mR53Hf7+3tZcwgYIkFAgEEAgIBgYBAQCAgEHguXfoj2BblE1SebtmuqDCDgEBAICAQEAgIBAQCAgGBgEAAgYBAQCAgEBAICAQEAgIBgYBAAIGAQEAgIBAQCAgEBAICAYEAAgGBgEBAICAQmDc5u4BpWJRHtZlBQCAgEBAICAQEAgIBgYBAYAn5JJ2p2Nvby5hBwBILBAIIBAQCAgGBgEBAICAQEAgIBBAICAQEAgIBgYBAQCAgEBAICAQQCAgEBAICAYGAQEAgsFAu/e7ui/J8bDCDgEBAICAQEAgIBAQCAgGBAAAAAAAAAADAtf8BFNg15uCjV1oAAAAASUVORK5CYII='
+    baseStyle = 'position: absolute; margin: auto; top: 0; left: 0; right: 0; bottom: 0;'
+    if orientation == 'landscape'
+      img.style = "#{baseStyle}transform: rotate(90deg);"
+      a1 = 'canvas#coffee-engine-dom'
+      a2 = '.ce-turn-screen'
+    else
+      img.style = baseStyle
+      a1 = '.ce-turn-screen'
+      a2 = 'canvas#coffee-engine-dom'
+
+    style = document.createElement('style')
+    style.setAttribute 'class', 'ce-turn-screen-style'
+    style.setAttribute 'type', 'text/css'
+    style.setAttribute 'media', 'all'
+    style.innerHTML = "
+@media all and (orientation:portrait) {
+    #{a1} {
+      display: none;
+    }
+}
+@media all and (orientation:landscape) {
+    #{a2} {
+      display: none;
+    }
+}"
+    document.head.appendChild style
+    div.appendChild img
+    document.body.appendChild div
+
 exports.Utils = Utils


mp4: Add more tags

mp4: Add more tags

--- mp4.coffee
+++ mp4.coffee
@@ -1,5 +1,7 @@
 Bits = require './bits'
 fs = require 'fs'
+
+TAG_CTOO = new Buffer([0xa9, 0x74, 0x6f, 0x6f]).toString 'utf8'

 class MP4File
   constructor: (filename) ->
@@ -16,7 +18,7 @@
     startTime = process.hrtime()
     while @bits.has_more_data()
       box = Box.parse @bits, null  # null == root box
-      process.stdout.write box.getTree()
+      process.stdout.write box.getTree 0, 1
     diffTime = process.hrtime startTime
     console.log "took #{(diffTime[0] * 1e9 + diffTime[1]) / 1000000} ms to parse"
     console.log "EOF"
@@ -27,15 +29,23 @@
   @mp4TimeToDate: (time) ->
     return new Date(new Date('1904-01-01 00:00:00+0000').getTime() + time * 1000)

-  getTree: (depth=0) ->
+  getTree: (depth=0, detailLevel=0) ->
     str = ''
     for i in [0...depth]
       str += '  '
-    str += "#{@typeStr}\n"
+    str += "#{@typeStr}"
+    if detailLevel > 0
+      detailString = @getDetails detailLevel
+      if detailString?
+        str += " (#{detailString})"
+    str += "\n"
     if @children?
       for child in @children
-        str += child.getTree depth+1
+        str += child.getTree depth+1, detailLevel
     return str
+
+  getDetails: (detailLevel) ->
+    return null

   constructor: (info) ->
     for name, value of info
@@ -198,12 +208,18 @@
         return new MP4AudioSampleEntry info
       when 'esds'
         return new ESDBox info
+      when 'free'
+        return new FreeSpaceBox info
+      when 'ctts'
+        return new CompositionOffsetBox info
+      when TAG_CTOO
+        return new CTOOBox info
       else
         if cls?
           return new cls info
         else
-          console.log "warning: mp4: skipping unknown (not implemented) box type: #{info.typeStr}"
-          return new Box
+          console.log "warning: mp4: skipping unknown (not implemented) box type: #{info.typeStr} (0x#{info.type.toString('hex')})"
+          return new Box info

 class Container extends Box
   read: (buf) ->
@@ -214,6 +230,9 @@
       @children.push box
     return

+  getDetails: (detailLevel) ->
+    "#{@children.length} children"
+
 # moov
 class MovieBox extends Container

@@ -243,6 +262,7 @@
   read: (buf) ->
     bits = new Bits buf
     @majorBrand = bits.read_uint32()
+    @majorBrandStr = Bits.uintToString @majorBrand, 4
     @minorVersion = bits.read_uint32()
     @compatibleBrands = []
     while bits.has_more_data()
@@ -252,6 +272,9 @@
         brand: brand
         brandStr: brandStr
     return
+
+  getDetails: (detailLevel) ->
+    "MajorBrand=#{@majorBrandStr} MinorVersion=#{@minorVersion}"

 # mvhd
 class MovieHeaderBox extends Box
@@ -340,8 +363,8 @@
     if @layer isnt 0
       console.log "layer is not 0: #{@layer}"
     @alternateGroup = bits.read_int 16
-    if @alternateGroup isnt 0
-      console.log "alternate_group is not 0: #{@alternateGroup}"
+#    if @alternateGroup isnt 0
+#      console.log "tkhd: alternate_group is not 0: #{@alternateGroup}"
     @volume = bits.read_int 16
     if @volume is 0x0100
       @isAudioTrack = true
@@ -847,35 +870,57 @@
 # ilst: list of actual metadata values
 class MetadataItemListBox extends Container

+class GenericDataBox extends Box
+  read: (buf) ->
+    bits = new Bits buf
+    @length = bits.read_uint32()
+    @name = bits.read_bytes(4).toString 'utf8'
+    @entryCount = bits.read_uint32()
+    zeroBytes = bits.read_bytes_sum 4
+    if zeroBytes isnt 0
+      console.log "warning: mp4: zeroBytes are not all zeros (got #{zeroBytes})"
+    @value = bits.read_bytes(@length - 16)
+    nullPos = @value.indexOf 0x00
+    if nullPos is 0
+      @valueStr = null
+    else if nullPos isnt -1
+      @valueStr = @value[0...nullPos].toString 'utf8'
+    else
+      @valueStr = @value.toString 'utf8'
+    return
+
+  getDetails: (detailLevel) ->
+    return "#{@name}=#{@valueStr}"
+
 # gsst: unknown
-class GoogleGSSTBox extends Box
-  read: (buf) ->
-    @str = buf.toString 'utf8'
+class GoogleGSSTBox extends GenericDataBox
+  read: (buf) ->
+    super buf

 # gstd: unknown
-class GoogleGSTDBox extends Box
-  read: (buf) ->
-    @str = buf.toString 'utf8'
+class GoogleGSTDBox extends GenericDataBox
+  read: (buf) ->
+    super buf

 # gssd: unknown
-class GoogleGSSDBox extends Box
-  read: (buf) ->
-    @str = buf.toString 'utf8'
+class GoogleGSSDBox extends GenericDataBox
+  read: (buf) ->
+    super buf

 # gspu: unknown
-class GoogleGSPUBox extends Box
-  read: (buf) ->
-    @str = buf.toString 'utf8'
+class GoogleGSPUBox extends GenericDataBox
+  read: (buf) ->
+    super buf

 # gspm: unknown
-class GoogleGSPMBox extends Box
-  read: (buf) ->
-    @str = buf.toString 'utf8'
+class GoogleGSPMBox extends GenericDataBox
+  read: (buf) ->
+    super buf

 # gshh: unknown
-class GoogleGSHHBox extends Box
-  read: (buf) ->
-    @str = buf.toString 'utf8'
+class GoogleGSHHBox extends GenericDataBox
+  read: (buf) ->
+    super buf

 # Media Data Box (mdat): audio/video frames
 # Defined in ISO 14496-12
@@ -947,6 +992,13 @@

     return

+  getDetails: (detailLevel) ->
+    'SPS=' + @sequenceParameterSets.map((sps) ->
+      "0x#{sps.toString 'hex'}"
+    ).join(',') + ' PPS=' + @pictureParameterSets.map((pps) ->
+      "0x#{pps.toString 'hex'}"
+    ).join(',')
+
 # esds
 class ESDBox extends Box
   readDecoderConfigDescriptor: (bits) ->
@@ -954,7 +1006,7 @@
     info.tag = bits.read_byte()
     if info.tag isnt 0x04  # 0x04 == DecoderConfigDescrTag
       throw new Error "ESDBox: DecoderConfigDescrTag is not 4 (got #{info.tag})"
-    info.length = bits.read_byte()
+    info.length = @readDescriptorLength bits
     info.objectProfileIndication = bits.read_byte()
     info.streamType = bits.read_bits 6
     info.upStream = bits.read_bit()
@@ -972,7 +1024,7 @@
     info.tag = bits.read_byte()
     if info.tag isnt 0x05  # 0x05 == DecSpecificInfoTag
       throw new Error "ESDBox: DecSpecificInfoTag is not 5 (got #{info.tag})"
-    info.length = bits.read_byte()
+    info.length = @readDescriptorLength bits
     info.specificInfo = bits.read_bytes info.length
     return info

@@ -981,7 +1033,7 @@
     info.tag = bits.read_byte()
     if info.tag isnt 0x06  # 0x06 == SLConfigDescrTag
       throw new Error "ESDBox: SLConfigDescrTag is not 6 (got #{info.tag})"
-    info.length = bits.read_byte()
+    info.length = @readDescriptorLength bits
     info.predefined = bits.read_byte()
     if info.predefined is 0
       info.useAccessUnitStartFlag = bits.read_bit()
@@ -1024,26 +1076,35 @@
         info.startCompositionTimeStamp = bits.read_bits info.timeStamplength
     return info

-  read: (buf) ->
-    bits = new Bits buf
-    @readFullBoxHeader bits
-
-    # ES_Descriptor is defined in ISO 14496-1
+  readDescriptorLength: (bits) ->
+    len = bits.read_byte()
+    if len >= 0x80
+      len = ((len & 0x7f) << 21) |
+        ((bits.read_byte() & 0x7f) << 14) |
+        ((bits.read_byte() & 0x7f) << 7) |
+        bits.read_byte()
+    return len
+
+  read: (buf) ->
+    bits = new Bits buf
+    @readFullBoxHeader bits
+
+    # ES_Descriptor (defined in ISO 14496-1)
     @tag = bits.read_byte()
     if @tag isnt 0x03  # 0x03 == ES_DescrTag
       throw new Error "ESDBox: tag is not #{0x03} (got #{@tag})"
-    @length = bits.read_byte()
+    @length = @readDescriptorLength bits
     @ES_ID = bits.read_bits 16
     @streamDependenceFlag = bits.read_bit()
     @urlFlag = bits.read_bit()
     @ocrStreamFlag = bits.read_bit()
     @streamPriority = bits.read_bits 5
-    if @streamDependenceFlag
+    if @streamDependenceFlag is 1
       @depenedsOnES_ID = bits.read_bits 16
-    if @urlFlag
+    if @urlFlag is 1
       @urlLength = bits.read_byte()
       @urlString = bits.read_bytes(@urlLength)
-    if @ocrStreamFlag
+    if @ocrStreamFlag is 1
       @ocrES_ID = bits.read_bits 16

     @decoderConfigDescriptor = @readDecoderConfigDescriptor bits
@@ -1063,6 +1124,9 @@

     return

+  getDetails: (detailLevel) ->
+    "AudioSpecificConfig=0x#{@decoderConfigDescriptor.decoderSpecificInfo.specificInfo.toString 'hex'} MaxBitrate=#{@decoderConfigDescriptor.maxBitrate} AvgBitrate=#{@decoderConfigDescriptor.avgBitrate}"
+
 # mp4a
 # Defined in ISO 14496-14
 class MP4AudioSampleEntry extends AudioSampleEntry
@@ -1074,5 +1138,29 @@
     ]
     return

+# free: can be ignored
+# Defined in ISO 14496-12
+class FreeSpaceBox extends Box
+
+# ctts: offset between decoding time and composition time
+class CompositionOffsetBox extends Box
+  read: (buf) ->
+    bits = new Bits buf
+    @readFullBoxHeader bits
+
+    @entryCount = bits.read_uint32()
+    @entries = []
+    for i in [0...@entryCount]
+      sampleCount = bits.read_uint32()
+      sampleOffset = bits.read_uint32()
+      @entries.push
+        sampleCount: sampleCount
+        sampleOffset: sampleOffset
+    return
+
+class CTOOBox extends GenericDataBox
+  read: (buf) ->
+    super buf
+
 mp4file = new MP4File 'example.mp4'
 mp4file.parse()


Kernel build command

Kernel build command

--- mos.coffee
+++ mos.coffee
@@ -51,6 +51,8 @@
     executeCommand 'dd if=build/bpb of=build/boot conv=notrunc bs=1 count=59 seek=3'
     console.log 'Writing boot sector to disk image...'
     executeCommand 'dd if=build/boot of=disks/mos.img conv=notrunc'
+    console.log 'Building kernel...'
+    executeCommand 'nasm -f bin source/kernel.asm -o build/kernel'

 program
   .parse process.argv


Only throw dragstart event if there was movement

--- framer/LayerDraggable.coffee
+++ framer/LayerDraggable.coffee
@@ -164,8 +164,6 @@
 		@_point = @_correctedLayerStartPoint
 		@_ignoreUpdateLayerPosition = false

-		@emit(Events.DragStart, event)
-
 	_touchMove: (event) =>

 		return unless @enabled
@@ -225,8 +223,10 @@

 		# Update the dragging status
 		if point.x isnt @_layerStartPoint.x or point.y isnt @_layerStartPoint.y
-			@_isDragging = true
-			@_isMoving = true
+			if not @_isDragging
+				@_isDragging = true
+				@_isMoving = true
+				@emit(Events.DragStart, event)

 		# Move literally means move. If there is no movement, we do not emit.
 		if @isDragging


Remove TODO that has been moved to the SDK

--- lib/actions/device.coffee
+++ lib/actions/device.coffee
@@ -49,9 +49,6 @@
 	resin.models.device.identify params.uuid, (error) ->
 		errors.handle(error) if error?

-# TODO: This action doesn't return any error
-# if trying to rename a device that does not
-# exists. This is being fixed server side.
 exports.rename = permissions.user (params) ->
 	async.waterfall [


Improved last commit.

Improved last commit.

--- lib/atox-toxWorker.coffee
+++ lib/atox-toxWorker.coffee
@@ -73,8 +73,11 @@
     @nodes      = paresedJSON.bootstrapNodes
     @aToxNodes  = paresedJSON.aToxNodes

-    try
-      @TOX = new toxcore.Tox "old": true, "data": toxSaveData, "path": @DLL, "crypto": {"path": @DLL}
+    @cryptoDLL = @DLL
+    @cryptoDLL = null unless os.platform().indexOf('win') > -1
+
+    try
+      @TOX = new toxcore.Tox "old": true, "data": toxSaveData, "path": @DLL, "crypto": {"path": @cryptoDLL}
     catch e
       @err "Failed to init Tox", e
       console.log e, e.stack


Fix nav.showPrevious(animate: false)

Fix nav.showPrevious(animate: false)

--- framer/Components/NavComponent.coffee
+++ framer/Components/NavComponent.coffee
@@ -173,7 +173,7 @@
 	showPrevious: (options={}) =>
 		return unless @previous
 		return if @isTransitioning
-		options = _.defaults({}, {animate: true})
+		options = _.defaults({}, options, {animate: true})
 		previous = @_stack.pop()
 		@_runTransition(previous?.transition, "back", options.animate, @current, previous.layer)


onsider Elaboration in infix grammar

onsider Elaboration in infix grammar

Infix grammar handles multiline cases like `plus`.
however elaboration scripts know the terms `(x), `{x} and `{{x}}
resulting in unclosed backticks which trip the grammar.
This is an attempt to exclude these special cases in the handling
of infix functions.

--- grammars/language-idris.cson
+++ grammars/language-idris.cson
@@ -106,7 +106,7 @@
     }
     {
       name: 'keyword.operator.function.infix.idris'
-      begin: '`'
+      begin: '`(?![\{|\(])'
       beginCaptures:
         0:
           name: 'punctuation.definition.entity.idris'


Fix integration test mode.

Fix integration test mode.

--- mobile/index.coffee
+++ mobile/index.coffee
@@ -1,3 +1,5 @@
 express = require('express')
 module.exports = app = express()
-app.listen(process.env.PORT, -> process.send? 'listening') if module is require.main
+if module is require.main
+  require('./lib/setup') app
+  app.listen(process.env.PORT, -> process.send? 'listening')


do not run determineState on instances that are in state 'removed' and are desired to be 'stopped'. currently removed is a temporary state that will lead to removal of the instance.

--- imports/server/stateReconciler.coffee
+++ imports/server/stateReconciler.coffee
@@ -51,7 +51,7 @@
 Instances.find({desiredState: 'running'}, fields: {services: 1}).observe
   changed: (doc, oldDoc) -> determineState doc, runningIsDesired

-Instances.find({desiredState: 'stopped'}, fields: {services: 1}).observe
+Instances.find({desiredState: 'stopped', state: $ne: 'removed'}, fields: {services: 1}).observe
   changed: (doc, oldDoc) -> determineState doc, stoppedIsDesired


convert labels to properties

convert labels to properties

--- imports/server/stateReconciler.coffee
+++ imports/server/stateReconciler.coffee
@@ -1,3 +1,5 @@
+_ = require 'lodash'
+
 SERVICE_STATES = ['starting', 'restarting', 'running', 'stopping', 'stopped', 'removed']

 atLeastOneWithState = (services, states...) ->
@@ -58,8 +60,15 @@
 f = true

 setServiceField = (fieldName, fieldValue, labels) ->
-  if (name = labels['bigboat/instance/name']) and (service = labels['bigboat/service/name'])
+  if (name = labels['bigboat.instance.name']) and (service = labels['bigboat.service.name']) and labels['bigboat.service.type'] is 'service'
     Instances.upsert {name: name}, $set: {"services.#{service}.#{fieldName}": fieldValue}
+
+labelsToObject = (labels) ->
+  obj = {}
+  for label, val of labels
+    _.set obj, label, val
+  obj
+

 module.exports =
   updateServiceFQDN: (fqdn, labels) -> setServiceField 'fqdn', fqdn, labels
@@ -68,37 +77,38 @@

   updateContainerName: (name, labels) -> setServiceField 'container.name', name, labels

-
   updateServiceState: (mappedState, labels) ->
     unless mappedState in SERVICE_STATES
       throw "Service state '#{mappedState}' is not supported."
-    if name = labels['bigboat/instance/name']
-      if (type = labels['bigboat/container/type']) is 'service'
-        updateDoc = name: name
+    if name = labels['bigboat.instance.name']
+      if (type = labels['bigboat.service.type']) is 'service'
+        properties = labelsToObject labels
+        updateDoc =
+          name: name
+          app:
+            name: properties.bigboat?.application?.name
+            version: properties.bigboat?.application?.version
+          startedBy: properties.bigboat?.startedBy
+          storageBucket: properties.bigboat?.storage?.bucket
+          agent:
+            url: properties.bigboat?.agent?.url

-        if (appName = labels['bigboat/application/name']) and
-          (appVersion = labels['bigboat/application/version'])
-            updateDoc.app = name: appName, version: appVersion
-
-        updateDoc.startedBy = startedBy if startedBy = labels['bigboat/startedBy']
-        updateDoc.storageBucket = storageBucket if storageBucket = labels['bigboat/storage/bucket']
-
-        updateDoc['agent.url'] = val if val = labels['bigboat/agent/url']
-
-        service = labels['bigboat/service/name']
-        search = {name: name}
+        service = labels['bigboat.service.name']

         updateDoc["services.#{service}.state"] = mappedState
+        updateDoc["services.#{service}.properties"] = properties
         updateDoc.status = "Starting #{service}" if mappedState is 'starting'
         updateDoc.status = "Stopping #{service}" if mappedState is 'stopping'

-        Instances.upsert search, $set: updateDoc
-      else if type is 'net'
+        Instances.upsert {name: name}, $set: updateDoc
+      else
         updateDoc = name: name
-        service = labels['bigboat/service/name']
-        updateDoc["services.#{service}.network"] = mappedState
+        auxUpdateDoc =
+          state: mappedState
+          properties: labelsToObject labels
+        service = labels['bigboat.service.name']
+        updateDoc["services.#{service}.aux.#{type}"] = auxUpdateDoc
         Instances.update {name: name}, $set: updateDoc
-      else console.log 'unknown container type', type

   #
   # Updates the internal state based on image pulls


:black_square_button::put_litter_in_its_place: Updated at https://danielx.net/editor/

--- pixie.cson
+++ pixie.cson
@@ -1,4 +1,4 @@
-title: "Mario Paint Composer - danielx.net"
+title: "Mario Paint Music Composer - danielx.net"
 description: """
 This Mario Paint inspired composer tool is easy and fun. You can create simple and
 beautiful songs right in your browser and share them with the world!


assign the same collection to a newly created ChoiceList

--- jsapp/xlform/src/model.choices.coffee
+++ jsapp/xlform/src/model.choices.coffee
@@ -140,7 +140,10 @@
     clone: () ->
       json = @toJSON()
       delete json.name
-      return new choices.ChoiceList(json)
+      return _.assign(
+          new choices.ChoiceList(json),
+          collection: @collection
+        )

     toJSON: ()->
       @finalize()


cleaned up an empty ignore list in the tests

--- test/draft3_test.coffee
+++ test/draft3_test.coffee
@@ -11,8 +11,6 @@
     refRemote: true
     uniqueItems: true
     "optional/zeroTerminatedFloats": true
-    "optional/format": [
-    ]

 runner.test
   constructor: draft3


platform independen classpath delimeter

platform independen classpath delimeter

--- lib/ensime-startup.coffee
+++ lib/ensime-startup.coffee
@@ -170,7 +170,7 @@
           ), 2000
       else
         # Classpath file for running Ensime server is in place
-        classpath = toolsJar + ':' + fs.readFileSync(cpF, {encoding: 'utf8'})
+        classpath = toolsJar + path.delimiter + fs.readFileSync(cpF, {encoding: 'utf8'})
         javaCmd = "#{javaHome}#{path.sep}bin#{path.sep}java"
         ensimeServerFlags = "#{atom.config.get('Ensime.ensimeServerFlags')}"
         ensimeConfigFile = projectPath() + path.sep + '.ensime'


Remove log messages

Remove log messages

--- lib/fuzzy-provider.coffee
+++ lib/fuzzy-provider.coffee
@@ -161,11 +161,9 @@
   # Returns an {Array} of strings
   getCompletionsForCursorScope: (scopeDescriptor) ->
     completions = @settingsForScopeDescriptor(scopeDescriptor, 'editor.completions')
-    console.log completions
     resultCompletions = []
     for {value} in completions
       resultCompletions = resultCompletions.concat(value) if Array.isArray(value)
-    console.log resultCompletions
     _.uniq(resultCompletions)

   # Public: Clean up, stop listening to events


Add TODO.

Add TODO.

--- lib/keyboard_utils.coffee
+++ lib/keyboard_utils.coffee
@@ -84,6 +84,7 @@
     # NOTE: "?" here for the tests.
     Utils?.monitorChromeStorage "mapKeyRegistry", (value) => mapKeyRegistry = value

+    # TODO(smblott) Change this to use event.key.
     (event) ->
       event.keyCode == @keyCodes.ESC || do =>
         keyChar = @getKeyCharString event, true


fix backspace issue by using TextEditorView from space-pen. This modul is oversized in this case! Maybe later it should change.

--- lib/daemon-item-configure-view.coffee
+++ lib/daemon-item-configure-view.coffee
@@ -21,26 +21,31 @@
         @td =>
           @div "Daemon Name"
         @td =>
-          @input type:"text", id: "daemon-item-name", autofocus: true
+          @subview 'daemon-item-name', new TextEditorView(mini: true), autofocus: true
+#          @input type:"text", id: "daemon-item-name", autofocus: true
       @tr class: "daemon-cmd-run", =>
         @td =>
           @div "run command"
         @td =>
-          @input type:"text", id: "daemon-item-cmd-run"
+          @subview 'daemon-item-cmd-run', new TextEditorView(mini: true)
+          #@input type:"text", id: "daemon-item-cmd-run"
       @tr class: "daemon-cmd-stop", =>
         @td =>
           @div "stop command"
         @td =>
-          @input type:"text", id: "daemon-item-cmd-stop"
+          @subview "daemon-item-cmd-stop", new TextEditorView(mini: true)
+          #@input type:"text", id: "daemon-item-cmd-stop"
       @tr =>
         @td class: "daemon-cmd-check", =>
           @div "check command"
         @td =>
-          @input type:"text", id: "daemon-item-cmd-check"
+          @subview "daemon-item-cmd-check", new TextEditorView(mini: true)
+          #@input type:"text", id: "daemon-item-cmd-check"
       @tr =>
         @td title:"true if isin check cmd result", "check string" , =>
         @td =>
-          @input type:"text", id: "daemon-item-str-check"
+          @subview "daemon-item-str-check", new TextEditorView(mini: true)
+          #@input type:"text", id: "daemon-item-str-check"
       @tr class: "daemon-hide", =>
         @td =>
           @div "hide"
@@ -59,9 +64,14 @@

   showTime : false

+  test: ->
+    console.log "t3st"
+
   initialize: ->
     $('#daemon-item-title').mousedown @test
     @autoHide()
+    #console.log @['daemon-item-name']
+    @unloadItems = []

   attach: (@daemonManagement) ->
     @modalPanel = atom.workspace.addModalPanel(item: @, visible: false)
@@ -92,22 +102,25 @@
       @showTime = false
     , 200

+  bindTextEditorView: (editorKey,daemonItemKey) ->
+    #@[editorKey].model.off 'did-change'
+    @[editorKey].model.setText @daemonItem[daemonItemKey]
+    @[editorKey].model.emitter.on 'did-change', =>
+      @daemonItem[daemonItemKey] = @[editorKey].model.getText()
+      @daemonManagement.refreshDaemonItem(@daemonItem)
+
   load: (@daemonItem) ->
-    $('#daemon-item-name').attr('value', @daemonItem.name).keyup (event) =>
-      @daemonItem.name = event.target.value
-      @daemonManagement.refreshDaemonItem(daemonItem)
-    $('#daemon-item-cmd-run').attr('value',@daemonItem.cmdRun).keyup (event) =>
-      @daemonItem.cmdRun = event.target.value
-      @daemonManagement.refreshDaemonItem(daemonItem)
-    $('#daemon-item-cmd-stop').attr('value',@daemonItem.cmdStop).keyup (event) =>
-      @daemonItem.cmdStop = event.target.value
-      @daemonManagement.refreshDaemonItem(daemonItem)
-    $('#daemon-item-cmd-check').attr('value',@daemonItem.cmdCheck).keyup (event) =>
-      @daemonItem.cmdCheck = event.target.value
-      @daemonManagement.refreshDaemonItem(daemonItem)
-    $('#daemon-item-str-check').attr('value',@daemonItem.strCheck).keyup (event) =>
-      @daemonItem.strCheck = event.target.value
-      @daemonManagement.refreshDaemonItem(daemonItem)
+    @bindTextEditorView 'daemon-item-name', 'name'
+    @bindTextEditorView 'daemon-item-cmd-run', 'cmdRun'
+    @bindTextEditorView 'daemon-item-cmd-stop', 'cmdStop'
+    @bindTextEditorView 'daemon-item-cmd-check', 'cmdCheck'
+    @bindTextEditorView 'daemon-item-str-check', 'strCheck'
+
+
+    # $('#daemon-item-cmd-run').attr('value',@daemonItem.cmdRun).keyup (event) =>
+    #   @daemonItem.cmdRun = event.target.value
+    #   @daemonManagement.refreshDaemonItem(daemonItem)
+
     $('#daemon-item-hide').prop('checked',@daemonItem.hide).change (event) =>
       @daemonItem.hide = $(event.target).prop('checked')
       @daemonManagement.refreshDaemonItem(daemonItem)


Age in seconds

Age in seconds

--- test/flickerable.coffee
+++ test/flickerable.coffee
@@ -60,7 +60,7 @@

   5.times ->
     player.update(1)
-    player.trigger "(1)
+    player.trigger "afterUpdate", 1
     equals player.I.alpha, 0.2

   5.times ->


use run function in integration test

use run function in integration test

--- test/integration.coffee
+++ test/integration.coffee
@@ -1,6 +1,6 @@
 Promise = require 'bluebird'

-{Graph, Set} = require('../src/zuvor')
+{Graph, Set, run} = require('../src/zuvor')

 ###################################################################################
 # test
@@ -8,16 +8,18 @@
 module.exports =

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

     starting = new Set
     running = new Set
     stopping = new Set
+    stopped = new Set

     debug = ->
       console.log 'starting', starting.toString()
       console.log 'stopping', stopping.toString()
       console.log 'running', running.toString()
+      console.log 'stopped', stopped.toString()

     ###################################################################################
     # services
@@ -25,333 +27,331 @@
     services =
       redisOne:
         start: ->
-          test.ok starting.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'mailAPI')
-          )
-          test.ok running.equals(
-            new Set
-          )
+          test.ok starting.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'mailAPI'
+          ])
+          test.ok running.equals([])
           Promise.delay(10)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'mailAPI'
-            )
-          )
-          test.ok running.equals(new Set())
+          test.ok stopping.equals([
+            'redisOne',
+            'redisTwo',
+            'mailAPI'
+          ])
+          test.ok stopped.equals([
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+            'elasticSearch'
+            'cache'
+            'postgres'
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
           Promise.delay(10)
       redisTwo:
         start: ->
-          test.ok starting.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'mailAPI')
-          )
-          test.ok running.equals(
-            new Set
-          )
+          test.ok starting.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'mailAPI'
+          ])
+          test.ok running.equals([])
           Promise.delay(20)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'mailAPI'
-            )
-          )
-          test.ok running.equals(new Set())
+          test.ok stopping.equals([
+            'redisOne',
+            'redisTwo',
+            'mailAPI'
+          ])
+          test.ok stopped.equals([
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+            'elasticSearch'
+            'cache'
+            'postgres'
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
           Promise.delay(20)
       serverOne:
         start: ->
-          test.ok starting.equals(
-            new Set('mailAPI', 'serverOne', 'serverTwo', 'serverThree')
-          )
-          test.ok running.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'cache')
-          )
+          test.ok starting.equals([
+            'mailAPI'
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+          ])
+          test.ok running.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'cache'
+          ])
           Promise.delay(5)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'workerTwo',
-              'serverOne',
-              'serverTwo',
-              'serverThree'
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-              'mailAPI',
-            )
-          )
+          test.ok stopping.equals([
+            'workerTwo',
+            'serverOne',
+            'serverTwo',
+            'serverThree'
+          ])
+          test.ok stopped.equals([
+            'workerOne'
+            'loadBalancer'
+          ])
           Promise.delay(5)
       serverTwo:
         start: ->
-          test.ok starting.equals(
-            new Set(['mailAPI', 'serverOne', 'serverTwo', 'serverThree'])
-          )
-          test.ok running.equals(
-            new Set(['redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'cache'])
-          )
+          test.ok starting.equals([
+            'mailAPI'
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+          ])
+          test.ok running.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'cache'
+          ])
           Promise.delay(30)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'workerTwo',
-              'serverOne',
-              'serverTwo',
-              'serverThree'
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-              'mailAPI',
-            )
-          )
+          test.ok stopping.equals([
+            'workerTwo',
+            'serverOne',
+            'serverTwo',
+            'serverThree'
+          ])
+          test.ok stopped.equals([
+            'workerOne'
+            'loadBalancer'
+          ])
           Promise.delay(30)
       serverThree:
         start: ->
-          test.ok starting.equals(
-            new Set(['mailAPI', 'serverOne', 'serverTwo', 'serverThree'])
-          )
-          test.ok running.equals(
-            new Set(['redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'cache'])
-          )
-          Promise.delay(60)
-        stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'workerTwo',
-              'serverOne',
-              'serverTwo',
-              'serverThree'
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-              'mailAPI',
-            )
-          )
+          test.ok starting.equals([
+            'mailAPI'
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+          ])
+          test.ok running.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'cache'
+          ])
+          Promise.delay(60)
+        stop: ->
+          test.ok stopping.equals([
+            'workerTwo',
+            'serverOne',
+            'serverTwo',
+            'serverThree'
+          ])
+          test.ok stopped.equals([
+            'workerOne'
+            'loadBalancer'
+          ])
           Promise.delay(60)
       elasticSearch:
         start: ->
-          test.ok starting.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'mailAPI')
-          )
-          test.ok running.equals(
-            new Set
-          )
+          test.ok starting.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'mailAPI'
+          ])
+          test.ok running.equals([])
           Promise.delay(25)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'elasticSearch'
-              'postgres'
-              'cache'
-              'mailAPI'
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-            )
-          )
+          test.ok stopping.equals([
+            'elasticSearch'
+            'postgres'
+            'cache'
+            'mailAPI'
+          ])
+          test.ok stopped.equals([
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
           Promise.delay(25)
       mailAPI:
         start: ->
-          test.ok starting.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'mailAPI')
-          )
-          test.ok running.equals(
-            new Set
-          )
-          Promise.delay(60)
-        stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'serverThree'
-              'mailAPI'
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-            )
-          )
+          test.ok starting.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'mailAPI'
+          ])
+          test.ok running.equals([])
+          Promise.delay(60)
+        stop: ->
+          test.ok stopping.equals([
+            'serverThree'
+            'mailAPI'
+          ])
+          test.ok stopped.equals([
+            'serverOne'
+            'serverTwo'
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
           Promise.delay(60)
       cache:
         start: ->
-          test.ok starting.equals(
-            new Set('elasticSearch', 'mailAPI', 'cache')
-          )
-          test.ok running.equals(
-            new Set('redisOne', 'redisTwo', 'postgres')
-          )
+          test.ok starting.equals([
+            'elasticSearch'
+            'mailAPI'
+            'cache'
+          ])
+          test.ok running.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+          ])
           Promise.delay(30)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'elasticSearch'
-              'postgres'
-              'cache'
-              'mailAPI'
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-            )
-          )
+          test.ok stopping.equals([
+            'elasticSearch'
+            'postgres'
+            'cache'
+            'mailAPI'
+          ])
+          test.ok stopped.equals([
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
           Promise.delay(30)
       postgres:
         start: ->
-          test.ok starting.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'mailAPI')
-          )
-          test.ok running.equals(
-            new Set
-          )
+          test.ok starting.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'mailAPI'
+          ])
+          test.ok running.equals([])
           Promise.delay(15)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'elasticSearch'
-              'postgres'
-              'cache'
-              'mailAPI'
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-            )
-          )
+          test.ok stopping.equals([
+            'elasticSearch'
+            'postgres'
+            'cache'
+            'mailAPI'
+          ])
+          test.ok stopped.equals([
+            'serverOne'
+            'serverTwo'
+            'serverThree'
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
           Promise.delay(15)
       loadBalancer:
         start: ->
-          test.ok starting.equals(
-            new Set('workerTwo', 'loadBalancer')
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-              'serverOne',
-              'serverTwo',
-              'serverThree',
-              'mailAPI',
-              'workerOne'
-            )
-          )
+          test.ok starting.equals([
+            'workerTwo'
+            'loadBalancer'
+          ])
+          test.ok running.equals([
+            'redisOne',
+            'redisTwo',
+            'postgres',
+            'elasticSearch',
+            'cache',
+            'serverOne',
+            'serverTwo',
+            'serverThree',
+            'mailAPI',
+            'workerOne'
+          ])
           Promise.delay(20)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'loadBalancer',
-              'workerOne',
-              'workerTwo',
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-              'serverOne',
-              'serverTwo',
-              'serverThree',
-              'mailAPI',
-            )
-          )
+          test.ok stopping.equals([
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
+          test.ok stopped.equals([])
           Promise.delay(20)
       workerOne:
         start: ->
-          test.ok starting.equals(
-            new Set('serverTwo', 'serverThree', 'workerOne', 'workerTwo')
-          )
-          test.ok running.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'cache', 'serverOne', 'mailAPI')
-          )
+          test.ok starting.equals([
+            'serverTwo'
+            'serverThree'
+            'workerOne'
+            'workerTwo'
+          ])
+          test.ok running.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'cache'
+            'serverOne'
+            'mailAPI'
+          ])
           Promise.delay(10)
         stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'loadBalancer',
-              'workerOne',
-              'workerTwo',
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-              'serverOne',
-              'serverTwo',
-              'serverThree',
-              'mailAPI',
-            )
-          )
+          test.ok stopping.equals([
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
+          test.ok stopped.equals([])
           Promise.delay(10)
       workerTwo:
         start: ->
-          test.ok starting.equals(
-            new Set('serverTwo', 'serverThree', 'workerOne', 'workerTwo')
-          )
-          test.ok running.equals(
-            new Set('redisOne', 'redisTwo', 'postgres', 'elasticSearch', 'cache', 'serverOne', 'mailAPI')
-          )
-          Promise.delay(60)
-        stop: ->
-          test.ok stopping.equals(
-            new Set(
-              'loadBalancer',
-              'workerOne',
-              'workerTwo',
-            )
-          )
-          test.ok running.equals(
-            new Set(
-              'redisOne',
-              'redisTwo',
-              'postgres',
-              'elasticSearch',
-              'cache',
-              'serverOne',
-              'serverTwo',
-              'serverThree',
-              'mailAPI',
-            )
-          )
+          test.ok starting.equals([
+            'serverTwo'
+            'serverThree'
+            'workerOne'
+            'workerTwo'
+          ])
+          test.ok running.equals([
+            'redisOne'
+            'redisTwo'
+            'postgres'
+            'elasticSearch'
+            'cache'
+            'serverOne'
+            'mailAPI'
+          ])
+          Promise.delay(60)
+        stop: ->
+          test.ok stopping.equals([
+            'loadBalancer'
+            'workerOne'
+            'workerTwo'
+          ])
+          test.ok stopped.equals([])
           Promise.delay(60)

     all = new Set Object.keys(services)
@@ -391,58 +391,33 @@
     ###################################################################################
     # start & stop

-    start = (names) ->
-      starting.add names
-      Promise.all names.map (name) ->
-        callback = services[name].start
-        promise = Promise.resolve(callback())
-        promise.then ->
-          starting.delete name
-          running.add name
-          # start all we can start now that have not been started
-          toStart = new Set(graph.whereAllParentsIn(running.keys()))
-            .delete(starting)
-            .delete(running)
-            .keys()
-          start toStart
-
-    stop = (names) ->
-      stopping.add names
-      running.delete names
-      return Promise.all names.map (name) ->
-        callback = services[name].stop
-        promise = Promise.resolve callback()
-        promise.then ->
-          stopping.delete name
-          stopped = all
-            .clone()
-            .delete(running)
-            .delete(stopping)
-          # stop all we can stop now that have not been stopped
-          toStop = new Set(graph.whereAllChildrenIn(stopped.keys()))
-            .delete(stopping)
-            .delete(stopped)
-            .keys()
-          stop toStop
-
-#     zuvor.run(
-#       graph: graph
-#       call: (id, upstream) -> services[name].start()
-#       running: starting
-#       finished: running
-#       ids:
-#       blacklist:
-#       strict:
-#     ).then ->
-#
-    start(graph.parentless())
+    run(
+      ids: all
+      callback: (id) -> services[id].start()
+      graph: graph
+      pending: starting
+      done: running
+      debug: console.log.bind(console)
+    )
       .then ->
         test.ok running.equals all
         test.equal starting.size, 0
         test.equal stopping.size, 0
-        stop graph.childless()
+        test.equal stopped.size, 0
+
+        run(
+          ids: all
+          callback: (id) -> services[id].stop()
+          graph: graph
+          reversed: true
+          pending: stopping
+          done: stopped
+          debug: console.log.bind(console)
+        )
       .then ->
         test.equal starting.size, 0
+        test.ok running.equals all
         test.equal stopping.size, 0
-        test.equal running.size, 0
+        test.ok stopped.equals all
+
         test.done()


Unit test for changing person attribute in alias()

--- test/kissmetrics.coffee
+++ test/kissmetrics.coffee
@@ -44,3 +44,8 @@

 		km = new KM 'apiKey', 'evan@example.com'
 		km.record('foo').alias('notevan@example.com').lastQuery.output.pop().match(expectedOutput).should.be.ok
+
+	it 'should change person on alias', ->
+		km = new KM 'apiKey', 'evan@example.com'
+		km.alias 'someone@example.com'
+		km.person.should.be.equal 'someone@example.com'


Testing simple, module level callback with options

--- test/parser.test.coffee
+++ test/parser.test.coffee
@@ -235,6 +235,16 @@
         equ r.sample.chartest[0]._, 'Character data here!'
         test.finish()

+  'test simple callback with options': (test) ->
+    fs.readFile fileName, (err, data) ->
+      xml2js.parseString data,
+        trim: true
+        normalize: true,
+        (err, r) ->
+          console.log r
+          equ r.sample.whitespacetest[0]._, 'Line One Line Two'
+          test.finish()
+
   'test double parse': (test) ->
     x2js = new xml2js.Parser()
     fs.readFile fileName, (err, data) ->


chore(logging): Refactor naming of result object

--- lib/product-import.coffee
+++ lib/product-import.coffee
@@ -175,30 +175,30 @@
         resolve(_.flatten(results))
       .catch (err) -> reject(err)

-  _errorLogger: (r, logger) =>
+  _errorLogger: (res, logger) =>
     if @_summary.failed < @errorLimit or @errorLimit is 0
-      logger.error r, "Skipping product due to an error"
+      logger.error res, "Skipping product due to an error"
     else
       logger.warn "
         Error not logged as error limit of #{@errorLimit} has reached.
       "

-  _handleProcessResponse: (r) =>
-    if r.isFulfilled()
-      @_handleFulfilledResponse(r)
-    else if r.isRejected()
+  _handleProcessResponse: (res) =>
+    if res.isFulfilled()
+      @_handleFulfilledResponse(res)
+    else if res.isRejected()
       @_summary.failed++
       if @errorDir
         errorFile = path.join(@errorDir, "error-#{@_summary.failed}.json")
-        fs.outputJsonSync(errorFile, r.reason(), {spaces: 2})
+        fs.outputJsonSync(errorFile, res.reason(), {spaces: 2})

       if _.isFunction(@errorCallback)
-        @errorCallback(r, @logger)
+        @errorCallback(res, @logger)
       else
         @logger.error "Error callback has to be a function!"

-  _handleFulfilledResponse: (r) =>
-    switch r.value().statusCode
+  _handleFulfilledResponse: (res) =>
+    switch res.value().statusCode
       when 201 then @_summary.created++
       when 200 then @_summary.updated++


Add: method to fetch same value attribute names of product type.

--- lib/product-import.coffee
+++ lib/product-import.coffee
@@ -148,6 +148,18 @@
     debug 'About to send %s requests', _.size(posts)
     Promise.settle(posts)

+  _fetchSameForAllAttributesOfProductType: (productType) =>
+    new Promise (resolve) =>
+      if @_cache.productType["#{productType.id}_sameForAllAttributes"]
+        resolve(@_cache.productType["#{productType.id}_sameForAllAttributes"])
+      else
+        @_resolveReference(@client.productTypes, 'productType', productType, "name=\"#{productType?.id}\"")
+        .then (productTypeId) =>
+          sameValueAttributes = _.where(@_cache.productType[productTypeId].attributes, {attributeConstraint: "SameForAll"})
+          sameValueAttributeNames = _.pluck(sameValueAttributes, 'name')
+          @_cache.productType["#{productType.id}_sameForAllAttributes"] = sameValueAttributeNames
+          resolve(sameValueAttributeNames)
+
   _ensureVariantDefaults: (variant = {}) ->
     variantDefaults =
       attributes: []


Remove unused config in Atom

Remove unused config in Atom

--- atom/config.cson
+++ atom/config.cson
@@ -22,8 +22,6 @@
     onlyHighlightWholeWords: false
   "line-ending-selector":
     defaultLineEnding: "LF"
-  linter:
-    lintOnChange: false
   "markdown-preview":
     useGitHubStyle: true
   "omni-ruler":


:atom:

:atom:

--- atom/config.cson
+++ atom/config.cson
@@ -9,7 +9,7 @@
   core:
     customFileTypes:
       "source.ruby": [
-        "god",
+        "god"
         "pp"
       ]
     destroyEmptyPanes: false


Update Atom version in config.cson

Update Atom version in config.cson

--- atom/config.cson
+++ atom/config.cson
@@ -36,4 +36,4 @@
 'autocomplete':
   'includeCompletionsFromAllBuffers': true
 'release-notes':
-  'viewedVersion': '0.68.0'
+  'viewedVersion': '0.71.0'


Prevent Linter from activating in Markdown files

--- atom/config.cson
+++ atom/config.cson
@@ -79,6 +79,7 @@
     showEolInStatusBar: false
   linter:
     errorPanelHeight: 142
+    ignoreMatchedFiles: "/**/*.{min.js,min.css,md}"
     lintOnFly: false
     showErrorInline: false
     showErrorTabFile: false


more atom config

more atom config

--- atom/config.cson
+++ atom/config.cson
@@ -6,18 +6,17 @@
       "welcome"
       "atom-color-highlight"
       "SFTP-deployment"
-      "git-plus"
       "linter-jsxhint"
       "linter-jshint"
       "linter-js-standard"
       "subword-navigation"
-      "linter-rubocop"
       "minimap"
       "ruby-test"
       "seeing-is-believing"
       "unity-ui"
       "atom-beautify"
       "script"
+      "git-blame"
     ]
     themes: [
       "seti-ui"
@@ -70,3 +69,6 @@
       "--timeout"
       "12"
     ]
+  "git-blame": {}
+  "git-plus":
+    gitPath: "/usr/local/bin/git"


Use Control-D to toggle Markdown tasks in Atom

--- atom/keymap.cson
+++ atom/keymap.cson
@@ -20,6 +20,8 @@
   'ctrl-. z': 'dot-atom:scroll-cursor-to-center'
   'ctrl-. b': 'dot-atom:scroll-cursor-to-bottom'

+  'ctrl-d': 'toggle-markdown-task:toggle'
+
 # The maximize-panes package (https://atom.io/packages/maximize-panes)
 # overwrites Atom's default keybinding for the 'editor:newline-above' command.
 # Let's restore that keybinding.


Fix issue when only one match

Fix issue when only one match

--- lib/test-navigator.coffee
+++ lib/test-navigator.coffee
@@ -50,7 +50,7 @@
     )

     if matchingFiles.length == 1
-      @openFile(matchingFiles[0].relative)
+      @openFile(matchingFiles[0].relativePath)
     else if matchingFiles.length > 1
       matchingFiles = @levenshteinSort(matchingFiles, fileInfoHelper.getPath())
       @displaySelectView(matchingFiles)


fix <type> failed to display metas

fix <type> failed to display metas

--- lib/view/body/type.coffee
+++ lib/view/body/type.coffee
@@ -5,7 +5,7 @@
         <template v-repeat="type">
             {{unmarked}}
             <button v-if="goal" class='no-btn text-info' v-on="click: jumpToGoal(goal)">{{goal}}</button>
-            {{meta}}
+            {{meta}}
             <template v-if="sort">
                 Set
                 {{sort}}


Add comment

Add comment

--- avstreams.coffee
+++ avstreams.coffee
@@ -55,7 +55,7 @@
     @spsNALUnit          = null  # buffer
     @ppsNALUnit          = null  # buffer
     @spropParameterSets  = ''    # string
-    @type                = null  # string
+    @type                = null  # string ('live' or 'recorded')

   reset: ->
     logger.debug "[stream:#{@id}] reset"


add columns def to mostLines query

add columns def to mostLines query

--- queries/individual/summary/most_lines.coffee
+++ queries/individual/summary/most_lines.coffee
@@ -11,5 +11,9 @@
     GROUP  BY GET_PLAYER_NAME(p.playerid,'','')
     ORDER  BY nlines DESC
   "
+  columns: [
+    {title: "Name", property: "name", align: "l"}
+    {title: "Lines", property: "nlines", align: "l"}
+  ]

 module.exports = mostLines


update

update

--- lib/connection/client.coffee
+++ lib/connection/client.coffee
@@ -36,7 +36,7 @@
         @loading.done()

     @handle 'cancelCallback', (id) =>
-      delete @callbacks[id]
+      @callbacks[id].reject()
       @loading.done()

   # Will be replaced by the connection logic


Change `facebook` to `fb`

Change `facebook` to `fb`

--- bots/Bing.coffee
+++ bots/Bing.coffee
@@ -15,7 +15,7 @@
     userAgent: hexBot.userAgent
 )
 DASHBOARD = 'http://www.bing.com/rewards/dashboard'
-offers = []; executed = 0; facebook = false
+offers = []; executed = 0; fb = false

 argData = [{name:'email'}, {name:'password'}, {name:'queryCount',default:0},
            {name:'minTime',default:20}, {name:'maxTime',default:40}]
@@ -35,7 +35,7 @@
   require('./libs/Microsoft.coffee').login(@, ARGS[0], ARGS[1])

 casper.thenOpen DASHBOARD, openDashboard = ->
-  [offers, ARGS[2], facebook] = @evaluate (examineDashboard = (offers, queryCount, facebook) ->
+  [offers, ARGS[2], fb] = @evaluate (examineDashboard = (offers, queryCount, fb) ->
     for e in document.querySelectorAll 'ul.row li a div.check-wrapper div.open-check'
       elem = e.parentNode.parentNode
       title = elem.querySelector('.title').innerText
@@ -47,11 +47,11 @@
         # remainingQueries = queriesPerPoint * remainingPoints / earnedPerQueries
         queryCount = Math.ceil(per * (upTo - soFar) / earn)
       else if title is 'Connect to Facebook'
-        facebook = true # free points by logging in with facebook
+        fb = true # free points by logging in with facebook
       else if title not in ['Refer a Friend', 'Bing Newsletter']
         offers.push elem.href # add the link of the offer
-    [offers, queryCount, facebook] # return
-  ), offers, ARGS[2], facebook
+    [offers, queryCount, fb] # return
+  ), offers, ARGS[2], fb

 casper.then openDailyOffers = ->
   @each offers, (self, offer) -> # iterate over offers
@@ -91,6 +91,6 @@

 casper.run ->
   @echo "Completed #{executed}/#{ARGS[2]} quer#{if executed is 1 then 'y' else 'ies'}."
-  if facebook # if there was an offer to log in with a facebook account
+  if fb # if there was an offer to log in with a facebook account
     @echo 'Earn more points by linking your Facebook account (not done through bot).'
   @exit executed - ARGS[2] # exit with code (-failed)


add comment

add comment

--- lib/editor/highlights.coffee
+++ lib/editor/highlights.coffee
@@ -29,6 +29,7 @@
     v.classList.add('ink-profile-line')
     v.classList.add(cl) for cl in classes

+    # can't use ed.defaultCharWidth here because that sometimes seems to be 0
     v.style.width = 0.1 + count*ed.preferredLineLength + 'em'
     v


Corrected tag from TODOs view (see #4)

Corrected tag from TODOs view (see #4)

--- lib/latex-friend-view.coffee
+++ lib/latex-friend-view.coffee
@@ -77,7 +77,7 @@
     @focusFilterEditor()

   viewForItem: (item) ->
-   "
checklist #{item.name}
"
+   "
#{item.name}
"

   confirmed: (item) ->
     editor = Utils.getActiveTextEditor()