Revert "removing yytext mentions from the grammar"

This reverts commit 5957b9f1552c6a03085b5d074169e6ba7e7a86c6.

--- src/grammar.coffee
+++ src/grammar.coffee
@@ -65,19 +65,19 @@
     o "Body TERMINATOR Line",                   -> $1.push $3
     o "Body TERMINATOR"
   ]
-
+
   # Expressions and statements, which make up a line in a body.
   Line: [
     o "Expression"
     o "Statement"
   ]
-
+
   # Pure statements which cannot be expressions.
   Statement: [
     o "Return"
     o "Throw"
-    o "BREAK",                                  -> new LiteralNode $1
-    o "CONTINUE",                               -> new LiteralNode $1
+    o "BREAK",                                  -> new LiteralNode yytext
+    o "CONTINUE",                               -> new LiteralNode yytext
   ]

   # All the different types of expressions in our language. The basic unit of
@@ -100,8 +100,8 @@
     o "Class"
     o "Splat"
     o "Existence"
-    o "COMMENT"
-    o "EXTENSION"
+    o "Comment"
+    o "Extension"
   ]

   # A an indented block of expressions. Note that the [Rewriter](rewriter.html)
@@ -110,22 +110,27 @@
   Block: [
     o "INDENT Body OUTDENT",                    -> $2
     o "INDENT OUTDENT",                         -> new Expressions()
-    o "TERMINATOR COMMENT",                     -> Expressions.wrap [$2]
+    o "TERMINATOR Comment",                     -> Expressions.wrap [$2]
+  ]
+
+  # A literal identifier, a variable name or property.
+  Identifier: [
+    o "IDENTIFIER",                             -> new LiteralNode yytext
   ]

   # Alphanumerics are separated from the other **Literal** matchers because
   # they can also serve as keys in object literals.
   AlphaNumeric: [
-    o "NUMBER",                                 -> new LiteralNode $1
-    o "STRING",                                 -> new LiteralNode $1
+    o "NUMBER",                                 -> new LiteralNode yytext
+    o "STRING",                                 -> new LiteralNode yytext
   ]

   # All of our immediate values. These can (in general), be passed straight
   # through and printed to JavaScript.
   Literal: [
     o "AlphaNumeric"
-    o "JS",                                     -> new LiteralNode $1
-    o "REGEX",                                  -> new LiteralNode $1
+    o "JS",                                     -> new LiteralNode yytext
+    o "REGEX",                                  -> new LiteralNode yytext
     o "TRUE",                                   -> new LiteralNode true
     o "FALSE",                                  -> new LiteralNode false
     o "YES",                                    -> new LiteralNode true
@@ -142,15 +147,22 @@
   # Assignment when it happens within an object literal. The difference from
   # the ordinary **Assign** is that these allow numbers and strings as keys.
   AssignObj: [
-    o "IDENTIFIER ASSIGN Expression",           -> new AssignNode new ValueNode($1), $3, 'object'
+    o "Identifier ASSIGN Expression",           -> new AssignNode new ValueNode($1), $3, 'object'
     o "AlphaNumeric ASSIGN Expression",         -> new AssignNode new ValueNode($1), $3, 'object'
-    o "COMMENT"
+    o "Comment"
   ]

   # A return statement from a function body.
   Return: [
     o "RETURN Expression",                      -> new ReturnNode $2
     o "RETURN",                                 -> new ReturnNode new ValueNode new LiteralNode 'null'
+  ]
+
+  # A comment. Because CoffeeScript passes comments through to JavaScript, we
+  # have to parse comments like any other construct, and identify all of the
+  # positions in which they can occur in the grammar.
+  Comment: [
+    o "COMMENT",                                -> new CommentNode yytext
   ]

   # [The existential operator](http://jashkenas.github.com/coffee-script/#existence).
@@ -183,8 +195,8 @@
   # A single parameter in a function definition can be ordinary, or a splat
   # that hoovers up the remaining arguments.
   Param: [
-    o "PARAM",                                  -> new LiteralNode $1
-    o "PARAM . . .",                            -> new SplatNode $1
+    o "PARAM",                                  -> new LiteralNode yytext
+    o "Param . . .",                            -> new SplatNode $1
   ]

   # A splat that occurs outside of a parameter list.
@@ -194,7 +206,7 @@

   # Variables and properties that can be assigned to.
   SimpleAssignable: [
-    o "IDENTIFIER",                             -> new ValueNode $1
+    o "Identifier",                             -> new ValueNode $1
     o "Value Accessor",                         -> $1.push $2
     o "Invocation Accessor",                    -> new ValueNode $1, [$2]
     o "ThisProperty"
@@ -221,10 +233,10 @@
   # The general group of accessors into an object, by property, by prototype
   # or by array index or slice.
   Accessor: [
-    o "PROPERTY_ACCESS IDENTIFIER",             -> new AccessorNode $2
-    o "PROTOTYPE_ACCESS IDENTIFIER",            -> new AccessorNode $2, 'prototype'
+    o "PROPERTY_ACCESS Identifier",             -> new AccessorNode $2
+    o "PROTOTYPE_ACCESS Identifier",            -> new AccessorNode $2, 'prototype'
     o "::",                                     -> new AccessorNode(new LiteralNode('prototype'))
-    o "SOAK_ACCESS IDENTIFIER",                 -> new AccessorNode $2, 'soak'
+    o "SOAK_ACCESS Identifier",                 -> new AccessorNode $2, 'soak'
     o "Index"
     o "Slice",                                  -> new SliceNode $1
   ]
@@ -326,7 +338,7 @@

   # A reference to a property on *this*.
   ThisProperty: [
-    o "@ IDENTIFIER",                           -> new ValueNode new LiteralNode('this'), [new AccessorNode($2)]
+    o "@ Identifier",                           -> new ValueNode new LiteralNode('this'), [new AccessorNode($2)]
   ]

   # The CoffeeScript range literal.
@@ -380,7 +392,7 @@

   # A catch clause names its error and runs a block of code.
   Catch: [
-    o "CATCH IDENTIFIER Block",                 -> [$2, $3]
+    o "CATCH Identifier Block",                 -> [$2, $3]
   ]

   # Throw an exception object.
@@ -394,6 +406,12 @@
   # the trick.
   Parenthetical: [
     o "( Line )",                               -> new ParentheticalNode $2
+  ]
+
+  # A language extension to CoffeeScript from the outside. We simply pass
+  # it through unaltered.
+  Extension: [
+    o "EXTENSION",                              -> yytext
   ]

   # The condition portion of a while loop.
@@ -423,8 +441,8 @@
   # (optional) reference to the current index. Or, *key, value*, in the case
   # of object comprehensions.
   ForVariables: [
-    o "IDENTIFIER",                             -> [$1]
-    o "IDENTIFIER , IDENTIFIER",                -> [$1, $3]
+    o "Identifier",                             -> [$1]
+    o "Identifier , Identifier",                -> [$1, $3]
   ]

   # The source of a comprehension is an array or object with an optional filter
@@ -458,7 +476,7 @@
   When: [
     o "LEADING_WHEN SimpleArgs Block",            -> new IfNode $2, $3, null, {statement: true}
     o "LEADING_WHEN SimpleArgs Block TERMINATOR", -> new IfNode $2, $3, null, {statement: true}
-    o "COMMENT TERMINATOR When",                  -> $3.comment: $1; $3
+    o "Comment TERMINATOR When",                  -> $3.comment: $1; $3
   ]

   # The most basic form of *if* is a condition and an action. The following


argument list

argument list

--- src/grammar.coffee
+++ src/grammar.coffee
@@ -309,12 +309,14 @@

   AggregateArgumentList: [
     o 'ArgumentList',                                    -> new ArgumentListValue($1)
-    o 'DISTINCT ArgumentList',                           -> new ArgumentListValue($2, true)
+    o 'DISTINCT ArgumentList',                           -> new ArgumentListValue($2, 'DISTINCT')
+    o 'ALL ArgumentList',                                -> new ArgumentListValue($2, 'ALL')
   ]

   ArgumentList: [
+    o 'STAR',                                            -> [$1]
     o 'Expression',                                       -> [$1]
-    o 'ArgumentList SEPARATOR Value',                     -> $1.concat($3)
+    o 'ArgumentList SEPARATOR Expression',                     -> $1.concat($3)
   ]

   Fields: [


Minor code simplification.

Minor code simplification.

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -280,44 +280,13 @@
 #---------------------------------------------------------------------

 $sum = (options) ->
-  init = options.init ?= 0
-
-  add = (a, b) ->
-    if $_.isArray a
-      n = a.length
-      throw new Error 'invalid sum' unless $_.isArray b and b.length is n
-      i = 0
-      while i < n
-        a[i] = add a[i], b[i]
-        ++i
-    else if $_.isObject a
-      throw new Error 'invalid sum' unless $_.isObject b
-      for key of a
-        a[key] = add a[key], b[key]
-    else
-      a += b
-    a
-  sub = (a, b) ->
-    if $_.isArray a
-      n = a.length
-      throw new Error 'invalid sum' unless $_.isArray b and b.length is n
-      i = 0
-      while i < n
-        a[i] = sub a[i], b[i]
-        ++i
-    else if $_.isObject a
-      throw new Error 'invalid sum' unless $_.isObject b
-      for key of a
-        a[key] = sub a[key], b[key]
-    else
-      a -= b
-    a
+  options.init ?= 0

   $watch this, options, (entered, exited) ->
     prev = @value

-    $each entered, (value) => @value = add @value, value
-    $each exited, (value) => @value = sub @value, value
+    $each entered, (value) => @value += value
+    $each exited, (value) => @value -= value

     @value isnt prev


Add preliminary DialogView

Add preliminary DialogView

--- coffee/conda.coffee
+++ coffee/conda.coffee
@@ -181,6 +181,19 @@

     on_shown: (event) =>
     on_hidden: (event) => @remove()
+
+class DialogView extends ModalView
+    initialize: (options) ->
+        @type = options.type
+        @message = options.message
+        super(options)
+
+    title_text: () -> @type.charAt(0).toUpperCase() + @type.slice(1)
+
+    render_body: () -> $('<span>').text(@message)
+
+    submit_text: () -> null
+    cancel_text: () -> "Close"

 class SettingsView extends ModalView

@@ -439,7 +452,7 @@
         if data.ok
             new PlanModalView({pkg: @pkg, envs: @envs, pkgs: @pkgs, actions: data.actions}).show()
         else
-            new Dialog({message: data.error}).show()
+            new DialogView({message: data.error}).show()

 class PlanModalView extends ModalView

@@ -532,9 +545,9 @@

     on_install: (data) =>
         if data.ok
-            new Dialog({type: "info", message: "#{@pkg.get('name')} was successfully installed"})
+            new DialogView({type: "info", message: "#{@pkg.get('name')} was successfully installed"}).show()
         else
-            new Dialog({type: "error", message: data.error}).show()
+            new DialogView({type: "error", message: data.error}).show()

 class InstalledView extends Backbone.View


fixes #1240

fixes #1240

--- drivers/javascript/net.coffee
+++ drivers/javascript/net.coffee
@@ -252,8 +252,10 @@

         timeout = setTimeout( (()=>
             @rawSocket.destroy()
-            @emit 'error', new RqlDriverError "Handshake timedout"
+            @emit 'error', new err.RqlDriverError "Handshake timedout"
         ), @timeout*1000)
+
+        @rawSocket.once 'error', => clearTimeout(timeout)

         @rawSocket.once 'connect', =>
             # Initialize connection with magic number to validate version


Use --global-style for installing global modules

--- src/install.coffee
+++ src/install.coffee
@@ -91,10 +91,13 @@
         callback("#{stdout}\n#{stderr}")

   installModule: (options, pack, modulePath, callback) ->
+    installGlobally = options.installGlobally ? true
+
     installArgs = ['--globalconfig', config.getGlobalConfigPath(), '--userconfig', config.getUserConfigPath(), 'install']
     installArgs.push(modulePath)
     installArgs.push("--target=#{@electronVersion}")
     installArgs.push("--arch=#{config.getElectronArch()}")
+    installArgs.push("--global-style") if installGlobally
     installArgs.push('--silent') if options.argv.silent
     installArgs.push('--quiet') if options.argv.quiet
     installArgs.push('--production') if options.argv.production
@@ -106,8 +109,6 @@
     @addBuildEnvVars(env)
     installOptions = {env}
     installOptions.streaming = true if @verbose
-
-    installGlobally = options.installGlobally ? true

     if installGlobally
       installDirectory = temp.mkdirSync('apm-install-dir-')


Log arguments of GM detection

Log arguments of GM detection

--- packages/rocketchat-file/file.server.coffee
+++ packages/rocketchat-file/file.server.coffee
@@ -22,6 +22,7 @@

 console.log 'GM: Getting GraphicsMagick version'
 exec 'gm version', Meteor.bindEnvironment (error, stdout, stderr) ->
+	console.log 'GM: GraphicsMagick', arguments
 	if not error? and stdout.indexOf('GraphicsMagick') > -1
 		console.log 'GM: GraphicsMagick installed'
 		RocketChatFile.enable()
@@ -36,6 +37,7 @@

 	console.log 'GM: Getting ImageMagick version'
 	exec 'convert -version', Meteor.bindEnvironment (error, stdout, stderr) ->
+		console.log 'GM: ImageMagick', arguments
 		if not error? and stdout.indexOf('ImageMagick') > -1
 			console.log 'GM: ImageMagick installed'
 			if RocketChatFile.enabled isnt true


Revert fb85bd4..30b89db

Revert fb85bd4..30b89db

This rolls back to commit fb85bd4a06f4373582a8f87ad898da24e462c230.

--- src/aotw.coffee
+++ src/aotw.coffee
@@ -25,7 +25,6 @@
             @storage = @robot.brain.data.aotw ||= {
                 nominations: []
                 history: []
-                nominationsByUser: {}
             }

             @robot.logger.debug "AOTW data loaded: " + JSON.stringify(@storage)
@@ -91,19 +90,14 @@
             soundCloud = /^https?:\/\/(soundcloud.com)\/(.*)\/(sets)\/(.*)$/
             if url.match(spotify) or url.match(googlePlay) or url.match(youtube) or url.match(soundCloud)
                 user = msg.message.user.name.toLowerCase()
-                if(@storage.nominationsByUser[user] <= 3)
-                    try
-                        @storage.nominations.push(user: user, url: msg.match[2])
-                        #increment stored nominations of user by 1
-                        @storage.nominationsByUser[user] = @storage.nominationsByUser[user] + 1;
-                    catch
-                        @storage.nominations = []
-                        @storage.nominations.push(user: user, url: msg.match[2])
-                    finally
-                        @save
-                        msg.send "Nomination saved"
-                else
-                    msg.send "Invalid nomination: nominations exceeded. Limit: 3"
+                try
+                    @storage.nominations.push(user: user, url: msg.match[2])
+                catch
+                    @storage.nominations = []
+                    @storage.nominations.push(user: user, url: msg.match[2])
+                finally
+                    @save
+                    msg.send "Nomination saved"
             else
                 msg.send "Invalid nomination: invalid url"
         else
@@ -141,7 +135,6 @@
     reset: (msg) ->
         @storage.nominations = []
         @storage.history = []
-        @storage.nominationsByUser = {}
         @save
         msg.send "All AOTW data has been reset"

@@ -157,7 +150,6 @@
                     @storage.history.push selected
                 finally
                     @storage.nominations = []
-                    @storage.nominationsByUser = {}
                     @save
                     msg.send "Selected #{selected["url"]}, nominated by #{selected["user"]}"
             else
@@ -171,7 +163,6 @@
                 @storage.history.push selected
             finally
                 @storage.nominations = []
-                @storage.nominationsByUser = {}
                 @save
                 msg.send "Randomly selected #{selected["url"]}, nominated by #{selected["user"]}"


Removed unneeded logging, fixed URL parameter for integrations (requires room name rather than room ID due to how query is structured)

--- packages/rocketchat-api/server/routes.extended.coffee
+++ packages/rocketchat-api/server/routes.extended.coffee
@@ -32,9 +32,9 @@
 Room name needs to be URL encoded, as the identifiers begin with characters
 that are not URL safe (e.g., '#' for channels and groups and '@' for direct messages). Example:

-'http://domain.com:3000/api/v1/room/%23testRoom/integrations'
-###
-RocketChat.API.v1.addRoute 'room/:rname/integrations', authRequired: true,
+'http://domain.com:3000/api/v1/room/name/%23testRoom/integrations'
+###
+RocketChat.API.v1.addRoute 'room/name/:rname/integrations', authRequired: true,
 	get: ->

 		if RocketChat.authz.hasPermission(@userId, 'manage-integrations') is false
@@ -96,7 +96,6 @@
 			this.response.setTimeout (1000 * @userId.length)
 			Meteor.runAsUser this.userId, () =>
 				(Meteor.call 'addUserToRoom', rid:@bodyParams.room, username:@bodyParams.username)
-			console.log status: 'success', rid:@bodyParams.room, username:@bodyParams.username
 		catch e
 			return RocketChat.API.v1.failure e.name + ': ' + e.message


namespaced Movable

namespaced Movable

--- src/ageable.coffee
+++ src/ageable.coffee
@@ -1,6 +1,5 @@
 ###*
-The Ageable module rotates the object
-based on its rotational velocity.
+The Ageable module handles keeping track of an

 player = GameObject()


fix server url

fix server url

--- src/app/app.coffee
+++ src/app/app.coffee
@@ -11,7 +11,7 @@

 events = new EventEmitter()

-serverUrl = '81.240.88.61:3030'
+serverUrl = 'http://81.240.88.61:3030'

 # if !fs.existsSync __dirname+'/bd.json'
 #   fs.writeFileSync __dirname+'/bd.json', "{}"


Show status icon for staged changes

Show status icon for staged changes

--- src/app/git.coffee
+++ src/app/git.coffee
@@ -35,11 +35,16 @@
   isPathModified: (path) ->
     modifiedFlags = @statusFlags.working_dir_modified |
                     @statusFlags.working_dir_delete |
-                    @statusFlags.working_dir_typechange
+                    @statusFlags.working_dir_typechange |
+                    @statusFlags.index_modified |
+                    @statusFlags.index_deleted |
+                    @statusFlags.index_typechange
     (@getPathStatus(path) & modifiedFlags) > 0

   isPathNew: (path) ->
-    (@getPathStatus(path) & @statusFlags.working_dir_new) > 0
+    newFlags = @statusFlags.working_dir_new |
+               @statusFlags.index_new
+    (@getPathStatus(path) & newFlags) > 0

   relativize: (path) ->
     workingDirectory = @getWorkingDirectory()


Use status helpers from git-utils module

--- src/app/git.coffee
+++ src/app/git.coffee
@@ -13,18 +13,6 @@
       new Git(path, options)
     catch e
       null
-
-  statusFlags:
-    index_new: 1 << 0
-    index_modified: 1 << 1
-    index_deleted: 1 << 2
-    index_renamed: 1 << 3
-    index_typechange: 1 << 4
-    working_dir_new: 1 << 7
-    working_dir_modified: 1 << 8
-    working_dir_delete: 1 << 9
-    working_dir_typechange: 1 << 10
-    ignore: 1 << 14

   statuses: null
   upstream: null
@@ -91,22 +79,14 @@
   isPathIgnored: (path) ->
     @getRepo().isIgnored(@relativize(path))

-  isStatusModified: (status=0) ->
-    modifiedFlags = @statusFlags.working_dir_modified |
-                    @statusFlags.working_dir_delete |
-                    @statusFlags.working_dir_typechange |
-                    @statusFlags.index_modified |
-                    @statusFlags.index_deleted |
-                    @statusFlags.index_typechange
-    (status & modifiedFlags) > 0
+  isStatusModified: (status) ->
+    @getRepo().isStatusModified(status)

   isPathModified: (path) ->
     @isStatusModified(@getPathStatus(path))

-  isStatusNew: (status=0) ->
-    newFlags = @statusFlags.working_dir_new |
-               @statusFlags.index_new
-    (status & newFlags) > 0
+  isStatusNew: (status) ->
+    @getRepo().isStatusNew(status)

   isPathNew: (path) ->
     @isStatusNew(@getPathStatus(path))


Add numbered circles canvas markers.

Add numbered circles canvas markers.

--- src/draw.coffee
+++ src/draw.coffee
@@ -131,8 +131,52 @@
         draw: (c) =>
             drawSimpleBerry c, 10, 10, @radius, "#f00"

+    FONT_SIZE = 48
+    PADDING = 15
+
+    class NumberCircleMaker
+        constructor: (@diameter) ->
+
+        stroke: (c, callback) ->
+            c.beginPath()
+            callback c
+            c.fill()
+            c.closePath()
+
+        drawNumber: (ctx, num, width) ->
+            position = width / 2 + PADDING
+            ctx.fillText num, position, position
+
+        drawCircle: (ctx, diameter) ->
+            @stroke ctx, (ctx) ->
+                radius = diameter / 2 + PADDING
+                ctx.arc radius, radius, radius, 0, 2 * Math.PI
+
+        initContext: (ctx) ->
+            ctx.font = "bold #{FONT_SIZE}px sans-serif"
+            ctx.textBaseline = 'middle'
+            ctx.textAlign = 'center'
+
+        drawNumberedCircle: (ctx, num) ->
+            @initContext ctx
+            num = num.toString()
+            ctx.fillStyle = '#ffffff'
+            numberDimensions = ctx.measureText num
+            width = numberDimensions.width
+            scalingFactor = @diameter / (width + 2 * PADDING)
+            ctx.save()
+            ctx.scale scalingFactor, scalingFactor
+            @drawNumber ctx, num, numberDimensions.width
+            ctx.globalCompositeOperation = 'destination-over'
+            ctx.fillStyle = '#000000'
+            @drawCircle ctx, numberDimensions.width
+            ctx.restore()
+
     exports =
         Plant: Plant
         PointCluster: PointCluster
         PointPlant: PointPlant
+        NumberCircleMaker: NumberCircleMaker
+
     return exports
+


change attribute process to jquery attr function

--- src/egen.coffee
+++ src/egen.coffee
@@ -34,12 +34,7 @@
           throw "The query token provided ('#{tokenStr}') is not a valid token type."

     # set attributes
-    if attrs
-      for name, value of attrs
-        if value or value == 0
-          element.setAttribute name, value
-        else
-          element.removeAttribute name
+    $element.attr attrs if attrs

     # set inner contents
     if innerContents


bounded

bounded

--- src/bounded.coffee
+++ src/bounded.coffee
@@ -114,7 +114,6 @@

   @name collisionBounds
   @methodOf Bounded#
-
   @param {Number} xOffset the amount to shift the x position
   @param {Number} yOffset the amount to shift the y position
   @returns {Object} The collision bounds


No longer reconnect, only emit the error, v2.2.0

--- src/meshblu.coffee
+++ src/meshblu.coffee
@@ -40,6 +40,7 @@
   reconnect: =>
     debug 'reconnect'
     @ws.close()
+    @ws.removeAllListeners('ready')
     @connect()

   startPollPinging: =>
@@ -52,11 +53,11 @@
     try
       @ws?.ping()
     catch error
-      return @reconnect()
+      return @emit 'error', error

     elapsedTime = Date.now() - @_lastPong
     if elapsedTime > @options.pingTimeout
-      @reconnect()
+      @emit 'error', new Error('Ping Timeout')

   send: (type, data) =>
     throw new Error 'No Active Connection' unless @ws?


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -1,7 +1,5 @@
 ###*
-The Metered module is used to provide basic data about the
-location and dimensions of the including object. This module is included
-by default in GameObject.
+The Metered module prov

 player = Core


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -133,6 +133,7 @@
     nameColor - Color of the property name displayed above the meter
     font - Size and style of the meter's font
     height - Height of the meter
+
   ###
   meter: (options={}) ->
     Object.reverseMerge options,


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -153,8 +153,7 @@
       text: null
       width: 100

-    if not I[name]
-      I[name] ?= 100
+    I[name] ?= 100

     if not I["max#{name.capitalize()}"]
       if I[name]


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -117,7 +117,7 @@
       y: 5
     radius: 3
     showName: true
-    text:
+    text: ""

   # =>
   </pre></code>


Avoid overwriting 'path'.

Avoid overwriting 'path'.

--- src/methods.coffee
+++ src/methods.coffee
@@ -518,8 +518,8 @@
             js_str = rs.jvm2js_str jvm_path_str
             rs.init_string path.resolve path.normalize js_str
         o 'list(Ljava/io/File;)[Ljava/lang/String;', (rs, _this, file) ->
-            path = rs.jvm2js_str rs.get_obj file.fields.path
-            files = fs.readdirSync(path)
+            pth = rs.jvm2js_str rs.get_obj file.fields.path
+            files = fs.readdirSync(pth)
             rs.init_object('[Ljava/lang/String;',(rs.init_string(f) for f in files))
       ]
     util:


Implement read().

Implement read().

stdin version is untested.

We can now run a simple diff program.

--- src/methods.coffee
+++ src/methods.coffee
@@ -427,6 +427,19 @@
       ]
       FileInputStream: [
         o 'available()I', (rs) -> 0 # we never buffer anything, so this is always zero
+        o 'read()I', (rs, _this) ->
+            if _this.fields.$file?
+              # this is a real file that we've already opened
+              data = rs.fs.readSync(_this.fields.$file, 1)[0]
+              return if data.length == 0 then -1 else data.charCodeAt(0)
+            # reading from System.in, do it async
+            console.log '>>> reading from Stdin now!'
+            data = null # will be filled in after the yield
+            rs.curr_frame().resume = ->
+              if data.length == 0 then -1 else data.charCodeAt(0)
+            throw new util.YieldException (cb) ->
+              rs.async_input 1, (byte) ->
+                data = byte
         o 'readBytes([BII)I', (rs, _this, byte_arr, offset, n_bytes) ->
             if _this.fields.$file?
               # this is a real file that we've already opened


fix average computation

fix average computation

--- src/sprint/states/edit/controller.coffee
+++ src/sprint/states/edit/controller.coffee
@@ -47,7 +47,7 @@
         speedInfo.speed != '?'
       .map (speedInfo) ->
         "Sprint #{speedInfo.number}: #{speedInfo.speed}"
-      .values()
+      .value()

     $scope.speedInfo =
       previousSpeeds: formatedSpeedInfo.join ', '


substitute '.' in mounts to process.cwd()

--- src/decking.coffee
+++ src/decking.coffee
@@ -434,7 +434,10 @@
       arg = [].concat arg, ["-p #{v}"] for v in val

     when "mount"
-      arg = [].concat arg, ["-v #{v}"] for v in val
+      for v in val
+        [host, remote] = v.split ":"
+        host = process.cwd() if host is "."
+        arg = [].concat arg, ["-v #{host}:#{remote}"]

   return done null, arg


:lipstick: spelling

:lipstick: spelling

--- src/row-map.coffee
+++ src/row-map.coffee
@@ -23,7 +23,7 @@
   getRegions: ->
     @regions.slice()

-  # Public: Returns and end-row-exclusive range of screen rows corresponding to
+  # Public: Returns an end-row-exclusive range of screen rows corresponding to
   # the given buffer row. If the buffer row is soft-wrapped, the range may span
   # multiple screen rows. Otherwise it will span a single screen row.
   screenRowRangeForBufferRow: (targetBufferRow) ->
@@ -35,7 +35,7 @@
       screenRows += targetBufferRow - bufferRows
       [screenRows, screenRows + 1]

-  # Public: Returns and end-row-exclusive range of buffer rows corresponding to
+  # Public: Returns an end-row-exclusive range of buffer rows corresponding to
   # the given screen row. If the screen row is the first line of a folded range
   # of buffer rows, the range may span multiple buffer rows. Otherwise it will
   # span a single buffer row.


making the thread chooser more flexible

making the thread chooser more flexible

--- src/runtime.coffee
+++ src/runtime.coffee
@@ -120,8 +120,10 @@
       continue if blacklist? and t in blacklist
       debug "TE(choose_next_thread): choosing thread #{thread_name(@, t)}"
       return t
-    java_throw @, 'java/lang/Error', "tried to switch threads when no other thread was available"
-
+    # we couldn't find a thread! We can't error out, so keep trying
+    return @choose_next_thread() if blacklist?  # forget the blacklist
+    debug "TE(choose_next_thread): no thread found, sticking with curr_thread"
+    return @curr_thread

   wait: (monitor, yieldee) ->
     # add current thread to wait queue


Sure :art:

Sure :art:

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -210,7 +210,7 @@
     if doesMatch is false
       return false
     else if doesMatch is null
-      # Make userKeystrokes with only keyup events doesn't match everything
+      # Make sure userKeystrokes with only keyup events doesn't match everything
       if userKeystrokesHasKeydownEvent
         return PartialMatch
       else


fix marktab.coffee allowing 0s to exist

fix marktab.coffee allowing 0s to exist

--- src/marktab.coffee
+++ src/marktab.coffee
@@ -247,7 +247,10 @@
 			notes = tabMap[stringNum]
 			line = @stringNames[stringNum] + "|-"
 			for note in notes
-				line += (note || '-')
+				if note != undefined
+					line += note
+				else
+					line += '-'
 				if note < 10 || !note || _.isString(note)
 					line += "-"
 			line += "|"


fixed error in sumarizing

fixed error in sumarizing

--- src/service.coffee
+++ src/service.coffee
@@ -165,8 +165,7 @@
                 (
                   if key isnt 'lang'
                     if doc.convention[key]?
-                      conv.column.forEach (elem) ->
-                        conf[elem.key] += doc.convention[key][elem.key]
+                      conv[k] += doc.convention[key][k] for k of conv when k isnt 'commits'
                       conv.commits = _.uniq(conv.commits.concat doc.convention[key].commits)
                 )for key, conv of baseConv.convention
               else


atom.open and atom.close

atom.open and atom.close

--- src/startup.coffee
+++ src/startup.coffee
@@ -22,5 +22,9 @@
 atom.extensions = new ExtensionManager
 atom.app = new App

+# atom.open, atom.close, etc.
+for name, method of atom.app
+  atom[name] = atom.app[name]
+
 require 'window'
 window.startup()


Implement whitelabeled tabs.

Implement whitelabeled tabs.

--- src/main/webapp/coffeescripts-hidden/load.coffee
+++ src/main/webapp/coffeescripts-hidden/load.coffee
@@ -161,17 +161,21 @@

   $("head").append atStyleSheet

+  anchorTabStamp = []
+
+  if ! tabJson.whitelabel
+    anchorTabStamp =
+      $("<a />")
+        .addClass("anchortab-stamp")
+        .attr('href', "http://anchortab.com")
+        .attr('target', '_blank')
+
   # Create the tab and append to the end of the body.
   anchorTab =
     $("<div />")
       .attr("id", "anchor-tab")
       .addClass(colorScheme)
-      .append(
-        $("<a />")
-          .addClass("anchortab-stamp")
-          .attr('href', "http://anchortab.com")
-          .attr('target', '_blank')
-      )
+      .append(anchorTabStamp)
       .append(
         $("<p />")
           .addClass("custom-message")


Refresh bearer tokens when they expire

Refresh bearer tokens when they expire

--- app/api/auth.coffee
+++ app/api/auth.coffee
@@ -2,6 +2,7 @@
 config = require './config'
 client = require './client'

+# Use this to override the default API-specific headers.
 JSON_HEADERS =
   'Content-Type': 'application/json'
   'Accept': 'application/json'
@@ -17,9 +18,13 @@
   CONTENT_ATTR = '''content=['"](.+)['"]'''
   ///#{NAME_ATTR}\s*#{CONTENT_ATTR}|#{CONTENT_ATTR}\s*#{NAME_ATTR}///

+# We don't want to wait until the token is already expired before refreshing it.
+TOKEN_EXPIRATION_ALLOWANCE = 10 * 1000
+
 module.exports = new Model
   _currentUserPromise: null
   _bearerToken: ''
+  _bearerRefreshTimeout: NaN

   _getAuthToken: ->
     console?.log 'Getting auth token'
@@ -46,20 +51,45 @@

       makeHTTPRequest 'POST', config.host + '/oauth/token', data, JSON_HEADERS
         .then (request) =>
-          response = JSON.parse request.responseText
-          @_bearerToken = response.access_token
-          client.headers['Authorization'] = "Bearer #{@_bearerToken}"
-          console?.info 'Got bearer token', @_bearerToken
-          @_bearerToken
+          token = @_handleNewBearerToken request
+          console?.info 'Got bearer token', token[...6]

         .catch (request) ->
           # You're probably not signed in.
           console?.error 'Failed to get bearer token'
           client.handleError request

+  _handleNewBearerToken: (request) ->
+    response = JSON.parse request.responseText
+
+    @_bearerToken = response.access_token
+    client.headers['Authorization'] = "Bearer #{@_bearerToken}"
+
+    refresh = @_refreshBearerToken.bind this, response.refresh_token
+    timeToRefresh = (response.expires_in * 1000) - TOKEN_EXPIRATION_ALLOWANCE
+    @_bearerRefreshTimeout = setTimeout refresh, timeToRefresh
+
+    @_bearerToken
+
+  _refreshBearerToken: (refreshToken) ->
+    data =
+      grant_type: 'refresh_token'
+      refresh_token: refreshToken
+      client_id: config.clientAppID
+
+    makeHTTPRequest 'POST', config.host + '/oauth/token', data, JSON_HEADERS
+      .then (request) =>
+        token = @_handleNewBearerToken request
+        console?.info 'Refreshed bearer token', token[...6]
+
+      .catch (request) ->
+        console?.error 'Failed to refresh bearer token'
+        client.handleError request
+
   _deleteBearerToken: ->
     @_bearerToken = ''
     delete client.headers['Authorization']
+    clearTimeout @_bearerRefreshTimeout
     console?.log 'Deleted bearer token'

   _getSession: ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -19,7 +19,7 @@
       } = meterData

       if not I[name]
-        I[n]
+        I[name] = 100

       ratio = I[name] / I["max#{name.capitalize()}"]


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -108,6 +108,7 @@

   player.meter
     borderColor: 'brown'
+
     showName: true
     name: 'health'
     position:


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -11,6 +11,7 @@

 enemy = GameObject
   health: 500
+

 player.meter 'health'
 # =>


Include relatedTarget when dispatching blur events from TextEditorElement

--- src/text-editor-element.coffee
+++ src/text-editor-element.coffee
@@ -141,7 +141,7 @@

   inputNodeBlurred: (event) ->
     if event.relatedTarget isnt this
-      @dispatchEvent(new FocusEvent('blur', bubbles: false))
+      @dispatchEvent(new FocusEvent('blur', relatedTarget: event.relatedTarget, bubbles: false))

   addGrammarScopeAttribute: ->
     @dataset.grammar = @model.getGrammar()?.scopeName?.replace(/\./g, ' ')


fix removal method for internet explorer, closes #61

--- app/controllers/classifier.coffee
+++ app/controllers/classifier.coffee
@@ -467,7 +467,7 @@
     @el.find("#frame-id-#{frame_idx}").closest("div").show()

   destroyFrames: ->
-    image.remove() for image in @el.find('.frame-image')
+    image.remove?() for image in @el.find('.frame-image')

   onClickInvert: ->
     @invert = !@invert
@@ -483,7 +483,6 @@

   showSummary: ->
     @resetMarkingSurfaces() # remove previous marks
-    @removeElementsOfClass(".known-asteroid")

     if @Subject.current.metadata.known_asteroids.length isnt 0
       @knownAsteroidMessage.show()
@@ -541,7 +540,7 @@
     @el.removeClass 'loading'

   removeElementsOfClass: (class_name) ->
-    element?.remove() for element in [@el.find(class_name)...]
+    element.parentNode.removeChild(element) for element in [@el.find(class_name)...]

   evaluateAnnotations: (P_ref) ->
     xs = []


Progress message updates

Progress message updates

--- app/controllers/classifier.coffee
+++ app/controllers/classifier.coffee
@@ -68,6 +68,7 @@
     'button[name="feature"]': 'featureButtons'
     'button[name="blue"]': 'blueButtons'

+    '.footer .progress .message': 'progressMessage'
     '.footer .progress .series .fill': 'seriesProgressFill'

     '.reveal .storm': 'revealStorm'
@@ -145,6 +146,7 @@
     index = config.setSize - availableSubjects
     remaining = availableSubjects - 1

+    @progressMessage.html "#{CycloneSubject.count()} more to go..."
     @seriesProgressFill.css width: "#{index / (remaining + index + 1) * 100}%"

     @revealStorm.html "#{meta.type} #{meta.name} (#{meta.year})"


Show user/repo and commit-ish in apm list

Signed-off-by: Michelle Tilley <19f7a7eb6786def4c39d6d86c40af5dbc6589663@github.com>

--- src/list.coffee
+++ src/list.coffee
@@ -3,11 +3,13 @@
 _ = require 'underscore-plus'
 CSON = require 'season'
 yargs = require 'yargs'
+Git = require 'git-utils'

 Command = require './command'
 fs = require './fs'
 config = require './apm'
 tree = require './tree'
+{getRepository} = require "./packages"

 module.exports =
 class List extends Command
@@ -57,6 +59,11 @@
       tree packages, (pack) =>
         packageLine = pack.name
         packageLine += "@#{pack.version}" if pack.version?
+        if pack.sha?
+          repo = getRepository(pack)
+          shaLine = "##{pack.sha}"
+          shaLine = repo + shaLine if repo?
+          packageLine += " (#{shaLine})"
         packageLine += ' (disabled)' if @isPackageDisabled(pack.name)
         packageLine
     console.log()
@@ -74,6 +81,10 @@
         try
           manifest = CSON.readFileSync(manifestPath)
       manifest ?= {}
+      try
+        if directoryPath is @gitPackagesDirectory
+          repo = Git.open(path.join(directoryPath, child))
+          manifest.sha = repo.getReferenceTarget(repo.getHead()).substr(0, 7)
       manifest.name = child
       if options.argv.themes
         packages.push(manifest) if manifest.theme


Fix callback for 'apm list --json'

Fix callback for 'apm list --json'

Signed-off-by: Michelle Tilley <19f7a7eb6786def4c39d6d86c40af5dbc6589663@github.com>

--- src/list.coffee
+++ src/list.coffee
@@ -147,7 +147,7 @@
         @listGitPackages options, (error, packages) =>
           @logPackages(packages, options)

-  listPackagesAsJson: (options) ->
+  listPackagesAsJson: (options, callback = ->) ->
     output =
       core: []
       dev: []
@@ -155,21 +155,26 @@
       user: []

     @listBundledPackages options, (error, packages) =>
+      return callback(error) if error
       output.core = packages
       @listDevPackages options, (error, packages) =>
+        return callback(error) if error
         output.dev = packages
         @listUserPackages options, (error, packages) =>
+          return callback(error) if error
           output.user = packages
           @listGitPackages options, (error, packages) ->
+            return callback(error) if error
             output.git = packages
             console.log JSON.stringify(output)
+            callback()

   run: (options) ->
     {callback} = options
     options = @parseOptions(options.commandArgs)

     if options.argv.json
-      @listPackagesAsJson(options)
+      @listPackagesAsJson(options, callback)
     else if options.argv.installed
       @listInstalledPackages(options)
       callback()


some cleanup on controller

some cleanup on controller

--- src/ui/views/controller.coffee
+++ src/ui/views/controller.coffee
@@ -1,14 +1,25 @@
 remote = require('electron').remote

-{applayout, convlist, listhead, messages, convhead, input, conninfo, convadd, controls,
-notifications, typinginfo, menu, trayicon, dockicon, startup, about} = require './index'
-
-models      = require '../models'
-{viewstate, connection} = models
-
-{later} = require '../util'
-
-
+{
+  applayout, convlist, listhead, messages, convhead, input, conninfo,
+  convadd, controls, notifications, typinginfo, menu, trayicon, dockicon,
+  startup, about
+} = require './index'
+
+models = require '../models'
+
+{ viewstate, connection } = models
+
+{ later } = require '../util'
+
+#                                    _   _
+#                                   | | (_)
+#     ___ ___  _ __  _ __   ___  ___| |_ _  ___  _ __
+#    / __/ _ \| '_ \| '_ \ / _ \/ __| __| |/ _ \| '_ \
+#   | (_| (_) | | | | | | |  __/ (__| |_| | (_) | | | |
+#    \___\___/|_| |_|_| |_|\___|\___|\__|_|\___/|_| |_|
+#
+#
 handle 'update:connection', do ->
     el = null
     ->
@@ -26,21 +37,37 @@
             # update startup with connection information
             redraw()

-setLeftSize = (left) ->
-    document.querySelector('.left').style.width = left + 'px'
-    document.querySelector('.leftresize').style.left = (left - 2) + 'px'
-
-setConvMin = (convmin) ->
-    if convmin
-        document.querySelector('.left').classList.add("minimal")
-        document.querySelector('.leftresize').classList.add("minimal")
-    else
-        document.querySelector('.left').classList.remove("minimal")
-        document.querySelector('.leftresize').classList.remove("minimal")
-
+#          _                   _        _
+#         (_)                 | |      | |
+#   __   ___  _____      _____| |_ __ _| |_ ___
+#   \ \ / / |/ _ \ \ /\ / / __| __/ _` | __/ _ \
+#    \ V /| |  __/\ V  V /\__ \ || (_| | ||  __/
+#     \_/ |_|\___| \_/\_/ |___/\__\__,_|\__\___|
+#
+#
 handle 'update:viewstate', ->
+
+    setLeftSize = (left) ->
+        document.querySelector('.left').style.width = left + 'px'
+        document.querySelector('.leftresize').style.left = (left - 2) + 'px'
+
+    setConvMin = (convmin) ->
+        if convmin
+            document.querySelector('.left').classList.add("minimal")
+            document.querySelector('.leftresize').classList.add("minimal")
+        else
+            document.querySelector('.left').classList.remove("minimal")
+            document.querySelector('.leftresize').classList.remove("minimal")
+
     setLeftSize viewstate.leftSize
     setConvMin viewstate.showConvMin
+
+    # check what in what state is the app
+    #
+    # STATE_STARTUP : still connecting
+    # STATE_NORMAL  : conversation list on left with selected chat showing in main window
+    # STATE_ABOUT   : conversation list on the left with about showing in main window
+    # STATE_ADD_CONVERSATION : conversation list on the left and new / modify conversation on the main window
     if viewstate.state == viewstate.STATE_STARTUP
         if Array.isArray viewstate.size
             later -> remote.getCurrentWindow().setSize viewstate.size...
@@ -152,24 +179,14 @@
     else
         console.log 'unknown viewstate.state', viewstate.state

-handle 'update:entity', ->
-    redraw()
-
-handle 'update:conv', ->
-    redraw()
-
-handle 'update:conv_count', ->
-    dockicon viewstate
-    trayicon models
-
-handle 'update:searchedentities', ->
-  redraw()
-
-handle 'update:selectedEntities', ->
-  redraw()
-
-handle 'update:convsettings', -> redraw()
-
+#                 _
+#                | |
+#    _ __ ___  __| |_ __ __ ___      __
+#   | '__/ _ \/ _` | '__/ _` \ \ /\ / /
+#   | | |  __/ (_| | | | (_| |\ V  V /
+#   |_|  \___|\__,_|_|  \__,_| \_/\_/
+#
+# simple redrawing all of yakyak UI
 redraw = ->
     notifications models
     convhead models
@@ -182,11 +199,6 @@
     convadd models
     startup models

-
-handle 'update:language', ->
-    menu viewstate
-    redraw()
-
 throttle = (fn, time=10) ->
     timeout = false
     # return a throttled version of fn
@@ -201,26 +213,142 @@

 redraw = throttle(redraw, 20)

+#               _   _ _
+#              | | (_) |
+#     ___ _ __ | |_ _| |_ _   _
+#    / _ \ '_ \| __| | __| | | |
+#   |  __/ | | | |_| | |_| |_| |
+#    \___|_| |_|\__|_|\__|\__, |
+#                          __/ |
+#                         |___/
+handle 'update:entity', -> redraw()
+
+#
+#
+#     ___ ___  _ ____   __
+#    / __/ _ \| '_ \ \ / /
+#   | (_| (_) | | | \ V /
+#    \___\___/|_| |_|\_/
+#
+#
+handle 'update:conv', -> redraw()
+
+#                                                 _
+#                                                | |
+#     ___ ___  _ ____   __   ___ ___  _   _ _ __ | |_
+#    / __/ _ \| '_ \ \ / /  / __/ _ \| | | | '_ \| __|
+#   | (_| (_) | | | \ V /  | (_| (_) | |_| | | | | |_
+#    \___\___/|_| |_|\_/    \___\___/ \__,_|_| |_|\__|
+#
+#
+handle 'update:conv_count', ->
+    dockicon viewstate
+    trayicon models
+
+#                            _              _              _   _ _   _
+#                           | |            | |            | | (_) | (_)
+#    ___  ___  __ _ _ __ ___| |__   ___  __| |   ___ _ __ | |_ _| |_ _  ___  ___
+#   / __|/ _ \/ _` | '__/ __| '_ \ / _ \/ _` |  / _ \ '_ \| __| | __| |/ _ \/ __|
+#   \__ \  __/ (_| | | | (__| | | |  __/ (_| | |  __/ | | | |_| | |_| |  __/\__ \
+#   |___/\___|\__,_|_|  \___|_| |_|\___|\__,_|  \___|_| |_|\__|_|\__|_|\___||___/
+#
+#
+handle 'update:searchedentities', -> redraw()
+
+#             _           _           _              _   _ _   _
+#            | |         | |         | |            | | (_) | (_)
+#    ___  ___| | ___  ___| |_ ___  __| |   ___ _ __ | |_ _| |_ _  ___  ___
+#   / __|/ _ \ |/ _ \/ __| __/ _ \/ _` |  / _ \ '_ \| __| | __| |/ _ \/ __|
+#   \__ \  __/ |  __/ (__| ||  __/ (_| | |  __/ | | | |_| | |_| |  __/\__ \
+#   |___/\___|_|\___|\___|\__\___|\__,_|  \___|_| |_|\__|_|\__|_|\___||___/
+#
+#
+handle 'update:selectedEntities', -> redraw()
+
+#                                    _   _   _
+#                                   | | | | (_)
+#     ___ ___  _ ____   __  ___  ___| |_| |_ _ _ __   __ _ ___
+#    / __/ _ \| '_ \ \ / / / __|/ _ \ __| __| | '_ \ / _` / __|
+#   | (_| (_) | | | \ V /  \__ \  __/ |_| |_| | | | | (_| \__ \
+#    \___\___/|_| |_|\_/   |___/\___|\__|\__|_|_| |_|\__, |___/
+#                                                     __/ |
+#                                                    |___/
+handle 'update:convsettings', -> redraw()
+
+#    _
+#   | |
+#   | | __ _ _ __   __ _ _   _  __ _  __ _  ___
+#   | |/ _` | '_ \ / _` | | | |/ _` |/ _` |/ _ \
+#   | | (_| | | | | (_| | |_| | (_| | (_| |  __/
+#   |_|\__,_|_| |_|\__, |\__,_|\__,_|\__, |\___|
+#                   __/ |             __/ |
+#                  |___/             |___/
 handle 'update:language', ->
     menu viewstate
     redraw()

-handle 'update:switchConv', ->
-    messages.scrollToBottom()
-
-handle 'update:beforeHistory', ->
-    applayout.recordMainPos()
-handle 'update:afterHistory', ->
-    applayout.adjustMainPos()
-
-handle 'update:beforeImg', ->
-    applayout.recordMainPos()
+#                 _ _       _
+#                (_) |     | |
+#    _____      ___| |_ ___| |__     ___ ___  _ ____   __
+#   / __\ \ /\ / / | __/ __| '_ \   / __/ _ \| '_ \ \ / /
+#   \__ \\ V  V /| | || (__| | | | | (_| (_) | | | \ V /
+#   |___/ \_/\_/ |_|\__\___|_| |_|  \___\___/|_| |_|\_/
+#
+#
+handle 'update:switchConv', -> messages.scrollToBottom()
+
+#    _           __                 _     _     _
+#   | |         / _|               | |   (_)   | |
+#   | |__   ___| |_ ___  _ __ ___  | |__  _ ___| |_ ___  _ __ _   _
+#   | '_ \ / _ \  _/ _ \| '__/ _ \ | '_ \| / __| __/ _ \| '__| | | |
+#   | |_) |  __/ || (_) | | |  __/ | | | | \__ \ || (_) | |  | |_| |
+#   |_.__/ \___|_| \___/|_|  \___| |_| |_|_|___/\__\___/|_|   \__, |
+#                                                              __/ |
+#                                                             |___/
+handle 'update:beforeHistory', -> applayout.recordMainPos()
+
+#           __ _              _     _     _
+#          / _| |            | |   (_)   | |
+#     __ _| |_| |_ ___ _ __  | |__  _ ___| |_ ___  _ __ _   _
+#    / _` |  _| __/ _ \ '__| | '_ \| / __| __/ _ \| '__| | | |
+#   | (_| | | | ||  __/ |    | | | | \__ \ || (_) | |  | |_| |
+#    \__,_|_|  \__\___|_|    |_| |_|_|___/\__\___/|_|   \__, |
+#                                                        __/ |
+#                                                       |___/
+handle 'update:afterHistory', -> applayout.adjustMainPos()
+
+#    _           __                 _
+#   | |         / _|               (_)
+#   | |__   ___| |_ ___  _ __ ___   _ _ __ ___   __ _
+#   | '_ \ / _ \  _/ _ \| '__/ _ \ | | '_ ` _ \ / _` |
+#   | |_) |  __/ || (_) | | |  __/ | | | | | | | (_| |
+#   |_.__/ \___|_| \___/|_|  \___| |_|_| |_| |_|\__, |
+#                                                __/ |
+#                                               |___/
+handle 'update:beforeImg', -> applayout.recordMainPos()
+
+#           __ _              _
+#          / _| |            (_)
+#     __ _| |_| |_ ___ _ __   _ _ __ ___   __ _
+#    / _` |  _| __/ _ \ '__| | | '_ ` _ \ / _` |
+#   | (_| | | | ||  __/ |    | | | | | | | (_| |
+#    \__,_|_|  \__\___|_|    |_|_| |_| |_|\__, |
+#                                          __/ |
+#                                         |___/
 handle 'update:afterImg', ->
     if viewstate.atbottom
         messages.scrollToBottom()
     else
         applayout.adjustMainPos()

+#        _             _     _               _
+#       | |           | |   | |             (_)
+#    ___| |_ __ _ _ __| |_  | |_ _   _ _ __  _ _ __   __ _
+#   / __| __/ _` | '__| __| | __| | | | '_ \| | '_ \ / _` |
+#   \__ \ || (_| | |  | |_  | |_| |_| | |_) | | | | | (_| |
+#   |___/\__\__,_|_|   \__|  \__|\__, | .__/|_|_| |_|\__, |
+#                                 __/ | |             __/ |
+#                                |___/|_|            |___/
 handle 'update:startTyping', ->
     if viewstate.atbottom
         messages.scrollToBottom()


BUGFIX: CoffeeScript syntax error (constructor referencing @parameter without @) can cause invalid references, depending on compilation environment (discovered with webpack).

--- src/tracker.coffee
+++ src/tracker.coffee
@@ -18,15 +18,15 @@
             'resume', 'pause', 'rewind', 'skip', 'closeLinear', 'close'
         ]
         # Duplicate the creative's trackingEvents property so we can alter it
-        for eventName, events of creative.trackingEvents
+        for eventName, events of @creative.trackingEvents
             @trackingEvents[eventName] = events.slice(0)
-        if creative instanceof VASTCreativeLinear
-            @setDuration creative.duration
+        if @creative instanceof VASTCreativeLinear
+            @setDuration @creative.duration

-            @skipDelay = creative.skipDelay
+            @skipDelay = @creative.skipDelay
             @linear = yes
-            @clickThroughURLTemplate = creative.videoClickThroughURLTemplate
-            @clickTrackingURLTemplates = creative.videoClickTrackingURLTemplates
+            @clickThroughURLTemplate = @creative.videoClickThroughURLTemplate
+            @clickTrackingURLTemplates = @creative.videoClickTrackingURLTemplates
         else
             @skipDelay = -1
             @linear = no


fixes for IE8

fixes for IE8

--- src/utils/script-loader.coffee
+++ src/utils/script-loader.coffee
@@ -17,10 +17,16 @@

     sc.id = opts.id if opts.id

-    sc.onload = ()->
-      clearTimeout errorTimeout
-      resolve(sc)
+    sc.src =  opts.src
+    done = false

-    sc.src =  opts.src
+    # http://stackoverflow.com/questions/4845762/onload-handler-for-script-tag-in-internet-explorer
+    sc.onload = sc.onreadystatechange = () ->
+      if !done && (!@readyState || @readyState == "loaded" || @readyState == "complete")
+        # clearTimeout(errorTimeout)
+        done = true;
+        resolve(sc)
+        # Handle memory leak in IE
+        sc.onload = sc.onreadystatechange = null;

     doc.getElementsByTagName('head')[0]?.appendChild(sc)


Export Site from telepath

Export Site from telepath

--- exports/atom.coffee
+++ exports/atom.coffee
@@ -1,5 +1,5 @@
 {View, $$, $$$} = require '../src/space-pen-extensions'
-{Document, Point, Range} = require 'telepath'
+{Document, Point, Range, Site} = require 'telepath'

 module.exports =
   _: require '../src/underscore-extensions'
@@ -17,6 +17,7 @@
   Point: Point
   Range: Range
   ScrollView: require '../src/scroll-view'
+  Site: Site
   stringscore: require '../vendor/stringscore'
   Subscriber: require '../src/subscriber'
   View: View


fixed QueueHandler calls in the createAlgorithm method

--- app/routes/algorithmRouter.coffee
+++ app/routes/algorithmRouter.coffee
@@ -191,7 +191,6 @@
       else
         AlgorithmManagement.updateStatus(identifier, 'testing')
         executableHelper = new ExecutableHelper()
-        tempQueue = new ProcessingQueue()
         inputs = {}
         highlighter = {}
         for input in req.body.input
@@ -227,13 +226,15 @@
             highlighter: highlighter
             inputs: inputs

-        executableHelper.preprocess req, tempQueue, 'test',
+        executableHelper.preprocess req, QueueHandler.dockerProcessingQueue, 'test',
           (err, response) ->
             #logger.log 'info', response
         ,
           () ->
+            job = QueueHandler.dockerProcessingQueue.getNext()
+            QueueHandler.runningDockerJobs.push(job)
             #execute the algorithm once
-            executableHelper.executeDockerRequest(tempQueue.getNext(), (error, data) ->
+            executableHelper.executeDockerRequest(job, (error, data) ->
               if(error)
                 AlgorithmManagement.updateStatus(identifier, 'error', null, error.statusMessage)
             )


privatize method

privatize method

--- src/main.coffee
+++ src/main.coffee
@@ -94,23 +94,6 @@
 class Calculate

     constructor: (@grid) ->
-
-    # TODO: make private
-    getCellRange: (cell) ->
-
-        point = cell.get Point
-        range = cell.get Range
-
-        list =
-            top:    @grid.getCell point.x, point.y - range.top - 1
-            bottom: @grid.getCell point.x, point.y + range.bottom + 1
-            left:   @grid.getCell point.x - range.left - 1, point.y
-            right:  @grid.getCell point.x + range.right + 1, point.y
-
-        for key, value of list
-            list[key] = value?.get Range
-
-        list

     hasMatch: (foo, bar) ->

@@ -168,13 +151,29 @@

         range = cell.get Range

-        cellRange = @getCellRange cell
+        cellRange = @_getCellRange cell

         cellRange.bottom?.top = range.unitY()
         cellRange.top?.bottom = range.unitY()

         cellRange.right?.left = range.unitX()
         cellRange.left?.right = range.unitX()
+
+    _getCellRange: (cell) ->
+
+        point = cell.get Point
+        range = cell.get Range
+
+        list =
+            top:    @grid.getCell point.x, point.y - range.top - 1
+            bottom: @grid.getCell point.x, point.y + range.bottom + 1
+            left:   @grid.getCell point.x - range.left - 1, point.y
+            right:  @grid.getCell point.x + range.right + 1, point.y
+
+        for key, value of list
+            list[key] = value?.get Range
+
+        list

     getMarkBits = (item) ->
         x: item.range.markX item.point


Disable Followed feed feature for now.

Disable Followed feed feature for now.

--- client/landing/app/Applications/Activity.kdapplication/views/activityinnernavigation.coffee
+++ client/landing/app/Applications/Activity.kdapplication/views/activityinnernavigation.coffee
@@ -29,7 +29,7 @@
     title : "FEED"
     items : [
         { title : "Public"  , type : "public" }
-        { title : "Followed", type : "private" }
+        # { title : "Followed", type : "private" }
       ]

   showMenuData :


mqtt: Fix falsy messages not being sent

mqtt: Fix falsy messages not being sent

--- src/mqtt.coffee
+++ src/mqtt.coffee
@@ -105,7 +105,7 @@
     handlers = @subscribers[topic]

     debug 'message', handlers.length, msg != null
-    return if not msg or not handlers
+    return if not handlers
     out =
       data: msg
       mqtt: message


Add a test for a SQL Batch request that results in more than one set of results.

--- test/integration/connection2-test.coffee
+++ test/integration/connection2-test.coffee
@@ -159,3 +159,47 @@
   connection.on('debug', (text) ->
     #console.log(text)
   )
+
+exports.sqlWithMultipleResultSets = (test) ->
+  test.expect(8)
+
+  config = getConfig()
+  row = 0
+
+  request = new Request('select 1; select 2;', (err) ->
+      test.ok(!err)
+
+      connection.close()
+  )
+
+  request.on('done', (rowCount) ->
+      test.strictEqual(rowCount, 1)
+  )
+
+  request.on('columnMetadata', (columnsMetadata) ->
+      test.strictEqual(columnsMetadata.length, 1)
+  )
+
+  request.on('row', (columns) ->
+      test.strictEqual(columns[0].value, ++row)
+  )
+
+  connection = new Connection(config)
+
+  connection.on('connection', (err) ->
+      test.ok(!err)
+
+      connection.execSql(request)
+  )
+
+  connection.on('end', (info) ->
+      test.done()
+  )
+
+  connection.on('infoMessage', (info) ->
+    #console.log("#{info.number} : #{info.message}")
+  )
+
+  connection.on('debug', (text) ->
+    #console.log(text)
+  )


BUG-FIX child Scope should set own property, not just set it becouse
it sometimes can be set on parent

NEW-FUNC innerTemplate property set if controller gets inner html for
template. It also prevent parser to go inside of that controller

--- src/neck.coffee
+++ src/neck.coffee
@@ -65,6 +65,13 @@
     Object.defineProperty @, key,
       value: value
       enumerable: false
+      configurable: false
+      writable: true
+
+  addOwnProperty: (key, value)->
+    Object.defineProperty @, key,
+      value: value
+      enumerable: true
       configurable: false
       writable: true

@@ -141,7 +148,7 @@
           for resolver in @_resolvers[property]
             @listenTo resolver.scope, "refresh:#{resolver.property}", callback
         else if @hasOwnProperty(property) or !@parent
-          @bind "refresh:#{property}", callback
+          @on "refresh:#{property}", callback
         else
           scope = @
           while scope = scope.parent
@@ -197,6 +204,10 @@
   scope: true
   inheritScope: true

+  # When true controller will take innerHTML
+  # of element and set it as template
+  innerTemplate: false
+
   constructor: ->
     super

@@ -214,9 +225,12 @@
             switch @scope[key]
               when '@' then childScope.addProperty key, "'#{string}'", @parentScope
               when '=' then childScope.addProperty key, string, @parentScope
-              else childScope[key] = @scope[key]
+              else childScope.addOwnProperty key, @scope[key]
           else
-            childScope[key] = if @scope[key] isnt '=' and @scope[key] isnt '@' then @scope[key] else undefined
+            if @scope[key] isnt '=' and @scope[key] isnt '@'
+              childScope.addOwnProperty key, @scope[key]
+            else
+              childScope.addOwnProperty key, undefined
       else if @scope is '@'
         for key, value of @el[0].dataset
           childScope.addProperty key, "'#{value}'", @parentScope
@@ -228,6 +242,11 @@
     else
       @scope = undefined

+    if @innerTemplate
+      if(template = @el.html()) isnt ''
+        @template = template
+        @el.empty()
+
   append: (controller)->
     @yield or= @el.find('[ui-yield]')[0] or @el[0]
     $(@yield).append controller.el or controller
@@ -242,9 +261,9 @@
         if Neck.Controller.runners[name]
           el or= $(node)
           runner = new Neck.Controller.runners[name](el: el, parentScope: @scope, runAttr: attribute.value)
-
-    @parse child for child in node.childNodes
+          breakParse = true if runner.innerTemplate

+    @parse child for child in node.childNodes unless breakParse
     undefined

   render: ->


Do not load hookfiles (thus no glob.sync search) in transaction-runner-test for executeAllTransactions

--- test/unit/transaction-runner-test.coffee
+++ test/unit/transaction-runner-test.coffee
@@ -540,7 +540,8 @@
         header: []
         reporter:  []
         only: []
-        hookfiles: './**/*_hooks.*'
+        # do not actually search & load hookfiles from disk
+        # hookfiles: './**/*_hooks.*'

     transaction = {}
     transactions = {}


Library: Store @options

Library: Store @options

--- src/library.coffee
+++ src/library.coffee
@@ -29,6 +29,7 @@
     options.config = JSON.parse(fs.readFileSync options.configfile, 'utf-8') if options.configfile
     options.config = {} if not options.config
     options.config = options.config.msgflo if options.config.msgflo
+    @options = options

     @components = componentsFromConfig options.config


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -125,6 +125,8 @@

   @name meter
   @methodOf Metered#
+  @param {Number} xOffset the amount to shift the x position
+  @param {Number} yOffset the amount to shift the y position
   ###
   meter: (options={}) ->
     Object.reverseMerge options,


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -146,7 +146,7 @@
       text: null
       width: 100

-    if not I[options.name
+    if not I[options.name]
       I[I.name] = 100

     if not I["max#{I.name.capitalize()}"]


Remove more obsolete rs.push-es.

Remove more obsolete rs.push-es.

--- src/methods.coffee
+++ src/methods.coffee
@@ -38,7 +38,7 @@
   classname = util.int_classname rs.jvm2js_str(rs.get_obj(args[0]))
   rs.push (b_ref = rs.init_object classname)
   rs.method_lookup({class: classname, sig: {name:'<init>',type:'()V'}}).run(rs)
-  rs.push b_ref
+  b_ref

 # convenience function. idea taken from coffeescript's grammar
 o = (fn_name, fn) -> fn_name: fn_name, fn: fn
@@ -207,7 +207,7 @@
             cls = rs.class_lookup type.toClassString()
             if cls.access_flags.interface
               return null
-            rs.push rs.init_class_object(cls.super_class)
+            rs.init_class_object(cls.super_class)
       ],
       Float: [
         o 'floatToRawIntBits(F)I', (rs, f_val) ->  #note: not tested for weird values


- [grunt] relaxed engine type to general `gm` (GraphicsMagick or ImageMagick) for grunt-spritesmith

--- tasks/grunt-spritesmith.coffee
+++ tasks/grunt-spritesmith.coffee
@@ -11,8 +11,6 @@
       destCSS: '<%= path.source.styles %>/generic/_sprites.map.scss'
       padding: 2
       engine: 'gm'
-      engineOpts:
-        imagemagick: true
       algorithm: 'binary-tree'
       cssTemplate: '<%= path.source.styles %>/generic/_sprites.map.mustache'
       cssVarMap: (sprite) ->


add font

add font

--- src/options.coffee
+++ src/options.coffee
@@ -263,6 +263,7 @@
       { texname: 'mktsFontfileSourcehansansregular',           filename: 'SourceHanSans-Regular.ttc',           }
       { texname: 'mktsFontfileSunexta',                        filename: 'sun-exta.ttf',                        }
       { texname: 'mktsFontfileSunextb',                        filename: 'Sun-ExtB.ttf',                        }
+      { texname: 'mktsFontfileːsunːextbːttf',                        filename: 'Sun-ExtB.ttf',                        }
       { texname: 'mktsFontfileSunflowerucjkxb',                filename: 'sunflower-u-cjk-xb.ttf',              }
       { texname: 'mktsFontfileTakaopgothic',                   filename: 'TakaoPGothic.ttf',                    }
       { texname: 'mktsFontfileUbuntub',                        filename: 'Ubuntu-B.ttf',                        }


fix #174: use coffeescript cell for lead markdown examples

--- app/markdown.coffee
+++ app/markdown.coffee
@@ -4,7 +4,7 @@
 Context = require './context'
 URI = require 'URIjs'
 _ = require 'underscore'
-CoffeeScript = require 'coffee-script'
+CoffeeScriptCell = require './coffeescript_cell'
 Documentation = require './documentation'

 fix_marked_renderer_href = (fn, base_href) ->
@@ -36,10 +36,10 @@

     nested_context = Context.create_nested_context @state.ctx
     value = @props.value
+    fn = CoffeeScriptCell.create_fn value
     Context.apply_to nested_context, ->
       Context.run_in_context @, (ctx) ->
-        # FIXME use CoffeeScriptCell
-        Context.scoped_eval ctx, CoffeeScript.compile value, {bare: true}
+        fn ctx
     React.DOM.div {className: 'inline-example'},
       React.DOM.div {className: 'example'}, example_component
       React.DOM.div {className: 'output'}, nested_context.component


resolved issue where multiple audio instances would be created

--- app/assets/coffee/apps/episodes/player/player_controller.coffee
+++ app/assets/coffee/apps/episodes/player/player_controller.coffee
@@ -186,13 +186,15 @@
               "player:playnow": (uuid) ->
                 require ["entities/feed"], ->
                   getEpisode = Swabcast.request("entity:episode", uuid)
-                  player = AudioPlayer.getInstance()
                   $.when(getEpisode).done (episodeModel) ->
+                    player = AudioPlayer.getInstance()
+                    player.clearAudio()
                     # audio options
                     options = {}
                     options.preload = true

                     # player commands
+
                     self.playerControls.model.destroy()
                     self.playerControls.model = self.newPlayerData(episodeModel)
                     # self.newPlayerData episodeModel
@@ -209,8 +211,9 @@
                   player = AudioPlayer.getInstance()
                   fetchEpisode = Swabcast.request("playlist:episode", episodeId)
                   $.when(fetchEpisode).done (episodeModel) ->
-                    console.log(episodeModel)
-                    self.playerControls.model.destroy()
+                    # console.log(episodeModel)
+                    if self.playerControls.model is not "undefined"
+                      self.playerControls.model.destroy()
                     self.playerControls.model = self.newPlayerData(episodeModel)
                     self.updateAudio episodeModel.get("mediaUrl"), options
                     self.playerControls.render()


Follow up #1814 and #1822: LDAP sync BaseDN detection is broken because of ambiguously Coffescript syntax statement evaluation.

--- app/assets/javascripts/app/controllers/_integration/ldap.coffee
+++ app/assets/javascripts/app/controllers/_integration/ldap.coffee
@@ -294,7 +294,7 @@

         option = ''
         options = {}
-        if !_.isEmpty data.attributes && !_.isEmpty data.attributes.namingcontexts
+        if !_.isEmpty(data.attributes) && !_.isEmpty(data.attributes.namingcontexts)
           for dn in data.attributes.namingcontexts
             options[dn] = dn
             if option is ''


include qj dependency via source path

include qj dependency via source path

--- src/payment.coffee
+++ src/payment.coffee
@@ -1,4 +1,4 @@
-QJ = require 'qj'
+QJ = require 'qj/src/qj'

 defaultFormat = /(\d{1,4})/g


Fix bug leaving off </url> tag

Fix bug leaving off </url> tag

--- src/sitemap.coffee
+++ src/sitemap.coffee
@@ -17,7 +17,7 @@
   if url.links?
     for link in url.links
       xml = xml + "<xhtml:link rel=\"#{link.rel}\" href=\"#{link.href}\"/>"
-  xml + "</url>"
+  xml = xml + "</url>"
   xml

 module.exports = class Sitemap


Fix inconsistent indentation

Fix inconsistent indentation

--- src/project.coffee
+++ src/project.coffee
@@ -141,7 +141,7 @@
     @findBufferForPath(@resolve(filePath))?.isModified()

   findBufferForPath: (filePath) ->
-   _.find @buffers, (buffer) -> buffer.getPath() == filePath
+    _.find @buffers, (buffer) -> buffer.getPath() == filePath

   # Only to be used in specs
   bufferForPathSync: (filePath) ->


Project::openAsync always resolves the filePath

--- src/project.coffee
+++ src/project.coffee
@@ -192,6 +192,7 @@
   #
   # Returns a promise that resolves to an {EditSession}.
   openAsync: (filePath, options={}) ->
+    filePath = @resolve(filePath)
     resource = null
     _.find @openers, (opener) -> resource = opener(filePath, options)


Remove Project deserialize deprecation

Remove Project deserialize deprecation

--- src/project.coffee
+++ src/project.coffee
@@ -64,7 +64,7 @@
   ###

   serializeParams: ->
-    path: @path
+    paths: @getPaths()
     buffers: _.compact(@buffers.map (buffer) -> buffer.serialize() if buffer.isRetained())

   deserializeParams: (params) ->


refixing stupid bug

refixing stupid bug

--- src/runtime.coffee
+++ src/runtime.coffee
@@ -72,7 +72,7 @@
     obj = @string_pool[oref] unless obj #megahack
     throw "undefined heap reference: #{oref}" unless obj
     name = field_spec.sig.name
-    obj[name] = @init_field(@field_lookup(field_spec)) unless name[obj] is undefined
+    obj[name] = @init_field(@field_lookup(field_spec)) if name[obj] is undefined
     @push obj[name]
     @push null if field_spec.sig.type in ['J','D']


udefine.env.amd should return a boolean, not the define function

--- src/udefine.coffee
+++ src/udefine.coffee
@@ -150,7 +150,7 @@

   # Default settings for udefine environment
   udefine.env or=
-    amd: do -> define? and (define.amd or define.umd)
+    amd: do -> !!(define? and (define.amd or define.umd))
     commonjs: hasModule
     browser: not hasModule
     globals: not hasModule and not udefine.amd
@@ -187,4 +187,4 @@
     configFunc.apply context, [root, udefine]

   # Export udefine function on CommonJS environments
-  if hasModule then module.exports = udefine else root.udefine = udefine+  if hasModule then module.exports = udefine else root.udefine = udefine


bug fix

bug fix

--- src/pjax.coffee
+++ src/pjax.coffee
@@ -53,11 +53,11 @@
     if @opts.history
       @on 'pushstate.pjax', (e, state) =>
         history.pushState state, state.name, state.url
-        document.title = page.name
+        document.title = state.name

       @on 'replacestate.pjax', (e, state) =>
         history.replaceState state, state.name, state.url
-        document.title = page.name
+        document.title = state.name

       $(window).off('popstate.pjax').on 'popstate.pjax', (e) =>
         state = e.originalEvent.state


more debug

more debug

--- src/poll.coffee
+++ src/poll.coffee
@@ -50,8 +50,8 @@
 		@robot.logger.info "Topic: #{topic}"
 		options = msg.match[2]
 		@robot.logger.info "options: #{options}"
-		@robot.logger.info @
-		response = @createPoll topic, options
+		@robot.logger.info createPoll
+		response = createPoll topic, options
 		msg.send "@channel: #{response}"

 	robot.respond /poll ping/i, (msg) ->


Added remote/client-side rendering

Added remote/client-side rendering

Views are now publicly available. If the querystring has a remote=true
parameter, the timbit will render a block of javascript which will allow
for remote rendering.

--- src/timbits.coffee
+++ src/timbits.coffee
@@ -29,6 +29,7 @@
 	@server.configure =>
 		@server.use connectESI.setupESI()
 		@server.use express.static("#{config.home}/public")
+		@server.use express.static("#{config.home}/views")
 		@server.use express.bodyParser()
 		@server.use express.cookieParser()

@@ -191,7 +192,20 @@

 	# default render implementation
 	render: (req, res, context) ->
-		res.render "#{context.name}/#{context.view}", context: context
+		if context.remote is 'true'
+			output = """
+					$().ready(function() {
+						return $.get("/#{context.name}/#{context.view}.coffee", function(data) {
+							context = #{JSON.stringify(context)};
+							return $('##{context.timbit_id}').html(CoffeeKup.render(data, context));
+						});
+					});
+			"""
+			res.setHeader "Content-Type", "text/plain"
+			res.write output
+			res.end()
+		else
+			res.render "#{context.name}/#{context.view}", context: context

 	# helper method to retrieve data via REST
 	fetch: (req, res, context, key, options, callback = @render) ->


yet another bugfix

yet another bugfix

--- src/runr.coffee
+++ src/runr.coffee
@@ -24,3 +24,5 @@
     return setNow(-> callback(err)) if err?
     return setNow(callback) if isRunning
     f = exports[name].run(args, callback)
+
+  result


improve colorModel check

improve colorModel check

--- framer/Color.coffee
+++ framer/Color.coffee
@@ -221,10 +221,12 @@
 	HSLA: "hsla"

 ColorModel.isRGB = (colorModel) ->
-	return colorModel.toLowerCase() in [ColorModel.RGB, ColorModel.RGBA]
+	return colorModel.toLowerCase() in [ColorModel.RGB, ColorModel.RGBA] if _.isString(colorModel)
+	return false

 ColorModel.isHSL = (colorModel) ->
-	return colorModel.toLowerCase() in [ColorModel.HSL, ColorModel.HSLA]
+	return colorModel.toLowerCase() in [ColorModel.HSL, ColorModel.HSLA] if _.isString(colorModel)
+	return false

 # Functions
 inputToRGB = (color, g, b, alpha) ->


remove print statement from lighten function

--- framer/Color.coffee
+++ framer/Color.coffee
@@ -100,7 +100,6 @@

 	lighten: (amount) ->
 		hsl = @toHsl()
-		print hsl
 		hsl.l += amount / 100
 		hsl.l = Math.min(1, Math.max(0, hsl.l))
 		return new Color(hsl)


Error for invalid eventName in Layer.off too

--- framer/Layer.coffee
+++ framer/Layer.coffee
@@ -962,7 +962,7 @@
 		@_addListener(eventName, listener)

 	removeListener: (eventName, listener) ->
-		throw Error("Layer.off needs an event name") unless eventName
+		throw Error("Layer.off needs a valid event name") unless eventName
 		super(eventName, listener)
 		@_removeListener(eventName, listener)


Print: add monospace font fallback

Print: add monospace font fallback

--- framer/Print.coffee
+++ framer/Print.coffee
@@ -23,7 +23,7 @@
 			@_printLayer.ignoreEvents = false
 			@_printLayer.html = ""
 			@_printLayer.style =
-				"font": "12px/1.35em Menlo"
+				"font": "12px/1.35em Menlo, Consolas, monospace"
 				"color": "rgba(0, 0, 0, .7)"
 				"padding": "8px"
 				"padding-bottom": "30px"


Update victory.coffee

Update victory.coffee

--- src/victory.coffee
+++ src/victory.coffee
@@ -38,7 +38,9 @@
   "http://rack.3.mshcdn.com/media/ZgkyMDEzLzA4LzA1L2U1L2NvbGJlcnRyZXBvLjVjNmYxLmdpZgpwCXRodW1iCTg1MHg1OTA-CmUJanBn/710824a0/764/colbert-report.jpg",
   "http://rack.1.mshcdn.com/media/ZgkyMDEzLzA4LzA1LzYyL2FuY2hvcm1hbi42NjJkYS5naWYKcAl0aHVtYgk4NTB4NTkwPgplCWpwZw/009ee80f/1c0/anchorman.jpg",
   "http://rack.3.mshcdn.com/media/ZgkyMDEzLzA4LzA1LzFmL2hhcnJ5cG90dGVyLjYxNjYzLmdpZgpwCXRodW1iCTg1MHg1OTA-CmUJanBn/db79fc85/147/harry-potter.jpg",
-  "http://www.velocityindiana.org/wp-content/uploads/2014/08/bff.gif"
+  "http://www.velocityindiana.org/wp-content/uploads/2014/08/bff.gif",
+  "http://i.kinja-img.com/gawker-media/image/upload/s--_dYUH9jW--/18vvnw5taib2ogif.gif",
+  "https://31.media.tumblr.com/e844e0925dbd8699ddb68fb2408d61b6/tumblr_mqrjr2oH0G1r3kc9vo1_250.gif"
 ]

 module.exports = (robot) ->


coffeescriptism issue

coffeescriptism issue

So apparently... coffee script doesnt get the '/ success/' and requires the \s for the white space. (rageguy) (fail)

--- src/victory.coffee
+++ src/victory.coffee
@@ -54,5 +54,5 @@
   robot.hear /victory\b/i, (msg) ->
     msg.send msg.random victory

-  robot.hear / success\b/i, (msg) ->
+  robot.hear /\ssuccess\b/i, (msg) ->
     msg.send msg.random victory


i think this is right but i am not sure

i think this is right but i am not sure

--- src/wordarray.iced
+++ src/wordarray.iced
@@ -106,6 +106,7 @@
         ch = b.readUInt8 p
         last |= (ch << (24 - (p%4) * 8))
         p++
+      last = util.fixup_uint32 last
       words.push last
     new WordArray words, b.length

@@ -123,6 +124,7 @@
         ch = b.readUInt8 p
         last |= (ch << ((p%4) * 8))
         p++
+      last = util.fixup_uint32 last
       words.push last
     new WordArray words, b.length

@@ -158,7 +160,8 @@
       throw new Error "source range exceeded"

     for i in [0...n_words]
-      @words[dst_offset+i] ^= wa2.words[src_offset+i]
+      tmp = @words[dst_offset + i] ^ wa2.words[src_offset + i]
+      @words[dst_offset+i] = util.fixup_uint32 tmp

   #--------------


ns: add BUDDYCLOUD_V1 xmlns

ns: add BUDDYCLOUD_V1 xmlns

--- src/xmpp/ns.coffee
+++ src/xmpp/ns.coffee
@@ -1,13 +1,14 @@
 module.exports =
-	PUBSUB: "http://jabber.org/protocol/pubsub"
-	PUBSUB_EVENT: "http://jabber.org/protocol/pubsub#event"
-	PUBSUB_OWNER: "http://jabber.org/protocol/pubsub#owner"
-	PUBSUB_NODE_CONFIG: "http://jabber.org/protocol/pubsub#node_config"
-	PUBSUB_META_DATA: "http://jabber.org/protocol/pubsub#meta-data"
-	DISCO_INFO: "http://jabber.org/protocol/disco#info"
-	DISCO_ITEMS: "http://jabber.org/protocol/disco#items"
-	DATA: "jabber:x:data"
-	REGISTER: "jabber:iq:register"
-	COMMANDS: "http://jabber.org/protocol/commands"
-	ARCHIVE_MANAGEMENT: "urn:xmpp:archive#management"
-	RSM: "http://jabber.org/protocol/rsm"
+    PUBSUB: "http://jabber.org/protocol/pubsub"
+    PUBSUB_EVENT: "http://jabber.org/protocol/pubsub#event"
+    PUBSUB_OWNER: "http://jabber.org/protocol/pubsub#owner"
+    PUBSUB_NODE_CONFIG: "http://jabber.org/protocol/pubsub#node_config"
+    PUBSUB_META_DATA: "http://jabber.org/protocol/pubsub#meta-data"
+    DISCO_INFO: "http://jabber.org/protocol/disco#info"
+    DISCO_ITEMS: "http://jabber.org/protocol/disco#items"
+    DATA: "jabber:x:data"
+    REGISTER: "jabber:iq:register"
+    COMMANDS: "http://jabber.org/protocol/commands"
+    ARCHIVE_MANAGEMENT: "urn:xmpp:archive#management"
+    RSM: "http://jabber.org/protocol/rsm"
+    BUDDYCLOUD_V1: "http://buddycloud.org/v1"


Fix toBuffer for the Buffer case.

Fix toBuffer for the Buffer case.

--- src/coffee/leveldb/iterator.coffee
+++ src/coffee/leveldb/iterator.coffee
@@ -29,7 +29,7 @@
 exports.Iterator = class Iterator

   toBuffer = (val) ->
-    new Buffer val unless Buffer.isBuffer val
+    if Buffer.isBuffer val then val else new Buffer val

   toValue = (val, options) ->
     unless val
@@ -108,7 +108,7 @@
   forRange: ->

     args = Array.prototype.slice.call arguments
-
+
     #Optional finished callback
     if typeof(args[args.length - 1]) is 'function' and typeof(args[args.length - 2]) is 'function'
         finishedCallback = args.pop()


Matrix copy constructor

Matrix copy constructor

--- test/matrix.coffee
+++ test/matrix.coffee
@@ -17,8 +17,8 @@

   test "copy constructor", ->
    matrix = Matrix(1, 0, 0, 1, 10, 12)
-
-
+
+   matrix2 =

   test "Matrix() (Identity)", ->
     matrix = Matrix()


Removed unneeded debug code

Removed unneeded debug code

--- test/mylist.coffee
+++ test/mylist.coffee
@@ -9,8 +9,6 @@
 fs = require 'fs'

 NicoQuery = require '../production/nicoquery.js'
-console.log "!!!"
-console.log NicoQuery

 describe "about Mylist class", ->
   describe "when create an instance with mylist id", ->


Added missing word in error message

Added missing word in error message

--- src/component/ComponentView.coffee
+++ src/component/ComponentView.coffee
@@ -73,6 +73,6 @@
   _checkIfImplemented: (methodNames) ->
     for methodName in methodNames
       unless @constructor.prototype.hasOwnProperty(methodName)
-        throw new Error("#{@constructor.name} - #{methodName}() must be implemented in .")
+        throw new Error("#{@constructor.name} - #{methodName}() must be implemented in View.")

 Vigor.ComponentView = ComponentView


fix(details): Make Homepage field clickable/a hyperlink

--- src/components/EntryDetails.coffee
+++ src/components/EntryDetails.coffee
@@ -5,7 +5,7 @@

 { NAMES, CSS_CLASSES } = require "../constants/Categories"

-{ div, p, h3, button, span, i } = React.DOM
+{ div, p, h3, button, span, i, a } = React.DOM

 module.exports = React.createClass

@@ -22,7 +22,7 @@
       div null,
         h3 null, entry.title
         p null, entry.description
-        p null, entry.homepage
+        p null, a href: entry.homepage, entry.homepage
         p null, entry.phone
         div null,
           button


updating stimulus and stem order

updating stimulus and stem order

--- src/components/question/index.cjsx
+++ src/components/question/index.cjsx
@@ -52,8 +52,8 @@
     exerciseUid =
{exercise_uid}
 if exercise_uid?

+      <QuestionHtml type='stimulus' html={stimulus_html} />
       <QuestionHtml type='stem' html={stem_html} />
-      <QuestionHtml type='stimulus' html={stimulus_html} />
       {@props.children}
       <AnswersTable {...@props}/>
       {details}


Fixed the relative date format

Fixed the relative date format

--- main/static/src/script/common/util.coffee
+++ main/static/src/script/common/util.coffee
@@ -19,7 +19,7 @@
         date = moment.utc ($ this).attr 'datetime'
         diff = moment().diff date , 'days'
         if diff > 25
-          ($ this).text date.local().format 'YYYY-DD-MM'
+          ($ this).text date.local().format 'YYYY-MM-DD'
         else
           ($ this).text date.fromNow()
         ($ this).attr 'title', date.local().format 'dddd, MMMM Do YYYY, HH:mm:ss Z'


Fix spacing

Fix spacing

--- src/spot.coffee
+++ src/spot.coffee
@@ -114,6 +114,6 @@
     spotRequest message, '/spot', 'put', {}, (err, res, body) ->
       message.send(body)

- robot.respond /respot/i, (message) ->
+  robot.respond /respot/i, (message) ->
     spotRequest message, '/respot', 'put', {}, (err, res, body) ->
       message.send(body)


@ is important, as always

@ is important, as always

--- src/teak.coffee
+++ src/teak.coffee
@@ -242,7 +242,7 @@

   sendRequestOfOpporunity: (callback) ->
     if @requestOfOpportunity
-      internal_directRequest(@requestOfOpportunity, callback)
+      @internal_directRequest(@requestOfOpportunity, callback)
     @requestOfOpportunity = undefined

   internal_directRequest: (carrotResponse, callback, postMethod) ->


Single quotes

Single quotes

--- repl.coffee
+++ repl.coffee
@@ -4,7 +4,7 @@
 {merge} = require './helpers'

 replDefaults =
-  prompt: "coffee> ",
+  prompt: 'coffee> ',
   eval: (code, context, file, cb) ->
     try
       code = '' if /^\(\s+\)$/.test code # Empty command won't parse


Follow mixin

Follow mixin

--- test/follow.coffee
+++ test/follow.coffee
@@ -8,6 +8,6 @@
     height: 10

   enemy = GameObject
-
+    x:

 module()


Remove unnecessary helper

Remove unnecessary helper

--- test/helper.coffee
+++ test/helper.coffee
@@ -1,3 +0,0 @@
-chai = require 'chai'
-chai.should()
-chai.use require 'chai-as-promised'


Prefixed all views with LRS

Prefixed all views with LRS

--- src/view.coffee
+++ src/view.coffee
@@ -41,6 +41,7 @@
 	initialize: () ->
 		@hidden = @el.hasClass('hidden')
 		@enabled = !@el.hasClass('disabled')
+
 		for name, view of @views
 			view.initialize()
 		super
@@ -254,7 +255,7 @@

 	hideAction: -> @hide()

-class lrs.LRSView.views.ListView extends lrs.LRSView
+class lrs.LRSView.views.LRSListView extends lrs.LRSView

 	initialize: (content = null) ->
 		@permanentContent = @el.children()
@@ -301,7 +302,7 @@
 			if (@options.itemClass)
 				view = new @options.itemClass(null, null, @).initialize(object)
 			else
-				view = new lrs.LRSView.views.GeneratedListItemView(@options.subTemplate, null, @).initialize(object)
+				view = new lrs.LRSView.views.LRSGeneratedListItemView(@options.subTemplate, null, @).initialize(object)
 		else
 			view = object

@@ -312,9 +313,9 @@
 		@listViews.splice(i, 0, view)
 		@views[_.uniqueId('lvi_')] = view

-class lrs.LRSView.views.ListItemView extends lrs.LRSView
-
-class lrs.LRSView.views.GeneratedListItemView extends lrs.LRSView.views.ListItemView
+class lrs.LRSView.views.LRSListItemView extends lrs.LRSView
+
+class lrs.LRSView.views.LRSGeneratedListItemView extends lrs.LRSView.views.LRSListItemView

 	constructor: (template, @options, @owner) ->
 		@template = template if template


The translate-crash-log-addresses script is abandonded.

--- script/translate-crash-log-addresses.coffee
+++ script/translate-crash-log-addresses.coffee
@@ -1,54 +0,0 @@
-#!/usr/bin/env coffee
-# Usage:
-# Copy the crash log into pasteboard and then run
-# pbpaste | ./script/translate-crash-log-addresses.coffee
-
-atos = (addresses, callback) ->
-  path = require 'path'
-  exec = require('child_process').exec
-
-  exec 'atos -o vendor/brightray/vendor/download/libchromiumcontent/Release/libchromiumcontent.dylib -arch i386 '.concat(addresses...), (error, stdout, stderr) ->
-    throw error if error?
-    callback stdout.split('\n')
-
-parse_stack_trace = (raw) ->
-  lines = {}
-  addresses = []
-  for line in raw
-    columns = line.split /\ +/
-    if columns[1] == 'libchromiumcontent.dylib' and /0x[a-f0-9]+/.test columns[3]
-      lines[columns[0]] = addresses.length
-      addresses.push '0x' + parseInt(columns[5]).toString(16) + ' '
-
-  atos addresses, (parsed) ->
-    for line in raw
-      columns = line.split /\ +/
-      frame = columns[0]
-      if lines[frame]?
-        console.log frame, parsed[lines[frame]]
-      else
-        console.log line
-
-parse_log_file = (content) ->
-  state = 'start'
-  stack_trace = []
-  lines = content.split /\r?\n/
-
-  for line in lines
-    if state == 'start'
-      if /Thread \d+ Crashed::/.test line
-        console.log line
-        state = 'parse'
-    else if state == 'parse'
-      break if line == ''
-      stack_trace.push line
-
-  parse_stack_trace stack_trace
-
-input = ''
-process.stdin.resume()
-process.stdin.setEncoding 'utf8'
-process.stdin.on 'data', (chunk) ->
-  input += chunk
-process.stdin.on 'end', ->
-  parse_log_file input


Consolidated comments into 1 per rule

Consolidated comments into 1 per rule

--- grammars/latex.cson
+++ grammars/latex.cson
@@ -121,8 +121,7 @@
     match: '~'
   }
   ampersandMeta: {
-    comment: 'The ampersand normally represents alignment (catcode 4).'
-    comment: 'Probably not useful (or legal) outside of align or table environment. However, it must be left this way to let users implement custom environments.'
+    comment: 'The ampersand normally represents alignment (catcode 4). Probably not useful (or legal) outside of align or table environment. However, it must be left this way to let users implement custom environments.'
     name: 'punctuation.alignment.latex'
     match: '&'
   }
@@ -155,8 +154,7 @@
     match: '}'
   }
   underscoreMeta: {
-    comment: 'Underscore means subscript. It will take an argument in brackets if possible. If not, just the single next character.'
-    comment: 'Only valid when within mathmode. Will address this later.'
+    comment: 'Underscore means subscript. It will take an argument in brackets if possible. If not, just the single next character. Only valid when within mathmode. Will address this later.'
     patterns: [
       {
         include: '#underscoreWithArgument'
@@ -178,8 +176,7 @@
     ]
   }
   underscoreNoArgument: {
-    comment: 'Matches an underscore and next character or macro'
-    comment: 'Considering making this give a warning, as brackets is best practice'
+    comment: 'Matches an underscore and next character or macro. Considering making this give a warning, as brackets is best practice'
     name: 'punctuation.subscript.latex'
     match: '_\\s*(\\\\[a-zA-Z]+|\\\\[.]|.)?'
   }
@@ -206,8 +203,7 @@
     ]
   }
   caretNoArgument: {
-    comment: 'Matches a caret and next character or macro'
-    comment: 'Considering making this give a warning, as brackets is best practice'
+    comment: 'Matches a caret and next character or macro. Considering making this give a warning, as brackets is best practice'
     name: 'punctuation.superscript.latex'
     match: '\\^\\s*(\\\\[a-zA-Z]+|\\\\[.]|.)?'
   }


Added widget attributes

Added widget attributes

--- grammars/marko.cson
+++ grammars/marko.cson
@@ -470,7 +470,7 @@
     'match': '(?<=[^=])\\b([a-zA-Z0-9:-]+)'
     'name': 'entity.other.attribute-name.html'
   'tag-marko-attribute':
-    'match': '(?<=[^=])\\b(if|for|else|else-if|attrs)'
+    'match': '(?<=[^=])\\b(if|for|else|else-if|attrs|w-bind|w-el-id|w-id)'
     'name': 'support.function.marko_attribute'
   'tag-id-attribute':
     'begin': '\\b(id)\\b\\s*(=)'


remove negative lookahead for "in" or "of"

--- grammars/stata.cson
+++ grammars/stata.cson
@@ -71,7 +71,7 @@
         ]
   }
   {
-    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'
+    match: '\\b(foreach)\\s+(.+)\\s+(in|of var(list|lis|li|l)?|of new(list|lis|li|l)?|of num(list|lis|li|l)?)\\b'
     captures:
       1: name: 'keyword.control.flow.stata'
       2:


Hack classify page constructor to not break the rest of the site in IE8

--- app/index.coffee
+++ app/index.coffee
@@ -1,4 +1,5 @@
 require 'lib/setup'
+
 Api = require 'zooniverse/lib/api'
 Navigation = require 'controllers/navigation'
 Route = require 'spine/lib/route'
@@ -30,7 +31,7 @@

   controllers:
     home: HomePage
-    classify: ClassifyPage
+    classify: class extends ClassifyPage then constructor: -> try super # At least display in IE8.
     about: AboutPage
     profile: ProfilePage


Allow lightboxing to be triggered manually

--- source/javascripts/jquery.windoze.js.coffee
+++ source/javascripts/jquery.windoze.js.coffee
@@ -33,6 +33,7 @@
     relocate_modal: true
     allow_outside_click: true
     allow_esc: true
+    lightbox: false
     open: ->
       $(@).trigger('open.windoze')
     close: ->
@@ -41,7 +42,7 @@
       $(@).trigger('destroy.windoze')
     readDataAttributes: ->
       $el = @$el
-      attrs = ['container', 'delegate', 'init_shown', 'relocate_modal', 'animation']
+      attrs = ['container', 'delegate', 'init_shown', 'lightbox', 'relocate_modal', 'animation']
       detected_attrs = attrs.map((a) -> $el.attr("data-wdz-#{a}"))
       for attr, i in detected_attrs
         if attr
@@ -127,7 +128,7 @@
       return if !href or href == '#'
       @$modal.addClass('wdz-loading')
       @fireCallback('beforeLoad')
-      if href.match(/\.(gif|jpg|jpeg|png)$/)
+      if href.match(/\.(gif|jpg|jpeg|png)$/) || @lightbox
         @loadImage href, e
       else
         @loadRemote href, e


Add EAL to projects list

Add EAL to projects list

--- projects.cson
+++ projects.cson
@@ -38,6 +38,7 @@
 		paths: [
 			"~/Labs/Utils"
 			"~/Labs/JG"
+			"~/Labs/EAL"
 		]
 		icon: "icon-tools"
 		devMode: true


similar crashes for same app

similar crashes for same app

--- client/coffee/crash_report.coffee
+++ client/coffee/crash_report.coffee
@@ -48,6 +48,10 @@

 fetch_all_similar_crashes = (id, cb) ->
     $.getJSON "/similarcrashes/#{id}", (result) ->
+        cb? result
+
+fetch_crashes_by_app = (appname, cb) ->
+    $.getJSON "/crashesforapp/#{appname}", (result) ->
         cb? result

 load_crashreport_data = (id, callback) ->
@@ -195,11 +199,13 @@
     #Analysis
     $('#app_similar_crashes_num').text "-"
     $('#all_similar_crashes_num').text "-"
-    fetch_all_similar_crashes crashreport.id, (result) ->
-        console.log result
-        console.log result.data.length
-        if result?.data
-            $('#all_similar_crashes_num').text result.data.length
+    fetch_all_similar_crashes crashreport.id, (ids_by_similarity) ->
+        if ids_by_similarity?.data
+            $('#all_similar_crashes_num').text ids_by_similarity.data.length
+            fetch_crashes_by_app application, (ids_by_app) ->
+                if ids_by_app?.data
+                    app_similars = _.intersect ids_by_app.data, ids_by_similarity.data
+                    $('#app_similar_crashes_num').text app_similars.length

     # Related Bugs
     $('#related_bugs .tab1').empty()


refactor directive

refactor directive

--- js/directives/autofill.coffee
+++ js/directives/autofill.coffee
@@ -1,46 +1,35 @@
-app.directive('autoFill', ($timeout, Weather) ->
-  {
-    restrict: 'EA'
-    scope:
-      autoFill: '&'
-      ngModel: '='
-      timezone: '='
-    compile: (tEle, tAttrs) ->
-      tplEl = angular.element('
' + '<input type="text" autocomplete="off" />' + '
' + '
{{res.name}}
' + '
' + '
')
-      input = tplEl.find('input')
-      input.attr 'type', tAttrs.type
-      input.attr 'ng-model', tAttrs.ngModel
-      input.attr 'timezone', tAttrs.timezone
-      tEle.replaceWith tplEl
-      (scope, ele, attrs, ctrl) ->
-        minKeyCount = attrs.minKeyCount or 3
-        timer = undefined
-        ele.bind 'keyup', (e) ->
-          val = ele.val()
-          if val.length < minKeyCount
-            if timer
-              $timeout.cancel timer
-            scope.reslist = null
-            return
-          else
-            if timer
-              $timeout.cancel timer
-            timer = $timeout((->
-              scope.autoFill()(val).then (data) ->
-                if data and data.length > 0
-                  scope.reslist = data
-                  scope.ngModel = data[0].name
-                  scope.timezone = data[0].tz
-                return
-              return
-            ), 300)
-          return
-        # Hide the reslist on blur
-        input.bind 'blur', (e) ->
+app.directive 'autoFill', ($timeout, Weather) ->
+  restrict: 'EA'
+  scope:
+    autoFill: '&'
+    ngModel: '='
+    timezone: '='
+  templateUrl: '/templates/autofill.html'
+  compile: (tEle, tAttrs) ->
+    input = tEle.find('input')
+    input.attr 'type', tAttrs.type
+    input.attr 'ng-model', tAttrs.ngModel
+    input.attr 'timezone', tAttrs.timezone
+    (scope, ele, attrs, ctrl) ->
+      minKeyCount = attrs.minKeyCount or 3
+      timer = undefined
+      ele.bind 'keyup', (e) ->
+        val = ele.val()
+        if val.length < minKeyCount
+          if timer
+            $timeout.cancel timer
           scope.reslist = null
-          scope.$digest()
-          return
-        return
-
-  }
-)
+        else
+          if timer
+            $timeout.cancel timer
+          timer = $timeout((->
+            scope.autoFill()(val).then (data) ->
+              if data and data.length > 0
+                scope.reslist = data
+                scope.ngModel = data[0].name
+                scope.timezone = data[0].tz
+          ), 300)
+      # Hide the reslist on blur
+      input.bind 'blur', (e) ->
+        scope.reslist = null
+        scope.$digest()


fix obvious mistake in err checking in misc_node

--- src/smc-util-node/misc_node.coffee
+++ src/smc-util-node/misc_node.coffee
@@ -705,7 +705,7 @@
                 (cb) ->
                     fs.mkdir(dir, 0o700, cb)
             ], (err) ->
-                if err.code == 'EEXIST'
+                if err?.code == 'EEXIST'
                     cb?()
                 else
                     cb?(err)


[fix] decreased return limit for live feed past history request to 10

--- routes/report_route.coffee
+++ routes/report_route.coffee
@@ -55,10 +55,15 @@
       res.send(result)
   )

+###
+  used in dynamic loading of reports on scroll down in live feed
+  db.getReportsSkip(limit,skip)
+    gets maximimum of limit, skipping n records
+###
 exports.getLimitSkip = (req, res) ->
   skip = req.body.skip;
   console.log skip
-  db.getReportsSkip(20, skip, (result) ->
+  db.getReportsSkip(10, skip, (result) ->
     if result
       res.send(result)
   )


Fixed client tests with new applyOp API

Fixed client tests with new applyOp API

--- test/client.coffee
+++ test/client.coffee
@@ -186,7 +186,7 @@
 					test.expect 4
 					test.done()

-				@model.applyOp @name, {v:0, op:[{i:'hi', p:0}]}, (error, appliedVersion) ->
+				@model.applyOp @name, {v:0, op:[{i:'hi', p:0}]}, (data, error) ->
 					test.ifError error

 		'get a nonexistent document passes null to the callback': (test) ->
@@ -231,7 +231,7 @@
 					test.deepEqual op, serverTransformed
 					onOpApplied()

-				@model.applyOp @name, {v:0, op:serverOp}, (error, v) ->
+				@model.applyOp @name, {v:0, op:serverOp}, (data, error) ->
 					test.ifError error

 		'doc fires both remoteop and change messages when remote ops are received': (test) ->
@@ -245,7 +245,7 @@
 					test.deepEqual op, sentOp
 					passPart()

-				@model.applyOp @name, {v:0, op:sentOp}, (error, v) ->
+				@model.applyOp @name, {v:0, op:sentOp}, (data, error) ->
 					test.ifError error

 		'doc only fires change ops from locally sent ops': (test) ->
@@ -267,7 +267,7 @@
 					throw new Error 'Should not have received op when the doc was unfollowed'

 				doc.close =>
-					@model.applyOp @name, {v:0, op:[{i:'asdf', p:0}]}, (error, v) =>
+					@model.applyOp @name, {v:0, op:[{i:'asdf', p:0}]}, (data, error) =>
 						test.done()

 		'created locally is set on new docs': (test) ->
@@ -437,6 +437,13 @@
 			test.throws ->
 				@c.open @name, 'does not exist', ->
 			test.done()
+
+		'Submitting an op and closing straight after works': (test) ->
+			# This catches a real bug.
+			client.open @name, 'text', "http://localhost:#{@port}/sjs", (doc, error) =>
+				doc.insert 'hi', 0
+				doc.close ->
+					test.done()

 	# This isn't working yet. I might have to rethink it.
 	#	'opening a document with a null name will open a new document with a random document name': (test) ->


Adding toLowerCase() to username

Adding toLowerCase() to username

--- client/views/signUp/signUp.coffee
+++ client/views/signUp/signUp.coffee
@@ -52,7 +52,7 @@

     username =
       if t.find('input[name="username"]')
-        t.find('input[name="username"]').value
+        t.find('input[name="username"]').value.toLowerCase()
       else
         undefined


Revert "update tests"

Revert "update tests"

This reverts commit 501e891760fd5c5bd0e6ffc75f866fd565561f31.

--- test/unit/coffee/DocumentManager/flushDocTests.coffee
+++ test/unit/coffee/DocumentManager/flushDocTests.coffee
@@ -24,7 +24,7 @@
 	describe "when the doc is in Redis", ->
 		beforeEach ->
 			@RedisManager.getDoc = sinon.stub().callsArgWith(1, null, @lines, @version)
-			@TrackChangesManager.flushDocChangesIfNeeded = sinon.stub().callsArg(2)
+			@TrackChangesManager.flushDocChanges = sinon.stub().callsArg(2)
 			@PersistenceManager.setDoc = sinon.stub().callsArgWith(4)
 			@DocumentManager.flushDocIfLoaded @project_id, @doc_id, @callback