Minor additions and changes

Minor additions and changes

--- library/nucleus/kernel.coffee
+++ library/nucleus/kernel.coffee
@@ -140,7 +140,7 @@
     shutdownKernel: (reason) ->
         util.puts require("os").EOL
         logger.warn reason.toString().red
-        try @router.shutdownRouter?()
+        try @router.shutdownRouter?() catch
         snapshot = _.clone(@router.registry or [])
         @router.unregister srv for srv in snapshot
         try @server.close(); try @secure.close()


fail when parse error

fail when parse error

--- lib/watcher.coffee
+++ lib/watcher.coffee
@@ -131,6 +131,7 @@

   createReferences: ->
     ranges = @ripper.find @editor.getSelectedBufferRange().start
+    return unless ranges? and ranges.length > 0
     @referenceMarkers = for range in ranges
       marker = @editor.markBufferRange range
       @editor.decorateMarker marker, type: 'highlight', class: 'refactor-reference'
@@ -152,7 +153,7 @@
     # When no reference exists, do nothing.
     cursor = @editor.getLastCursor()
     ranges = @ripper.find cursor.getBufferPosition()
-    return false if ranges.length is 0
+    return false unless ranges? and ranges.length > 0

     # Pause highlighting life cycle.
     @destroyReferences()


reenable the downloading of messages

reenable the downloading of messages

--- lib/controllers/vehicles_controller.coffee
+++ lib/controllers/vehicles_controller.coffee
@@ -35,7 +35,7 @@
       console.log "#{data.units.length} vehicles downloaded"
       @loadVehicles(data.units)
       @set('loadedVehicles',true)
-      # @getMessages()
+      @getMessages()
   loadVehicles: (vehicles) ->
     vehicles.forEach (vehicleData) =>
       vehicle = Sensor.Vehicle.create(vehicleData)


forces phantomjs viewport size to 800x800 (average)

--- lib/teabag/drivers/phantomjs/runner.coffee
+++ lib/teabag/drivers/phantomjs/runner.coffee
@@ -15,6 +15,7 @@

   initPage: ->
     @page = webpage.create()
+    @page.viewportSize = {width: 800, height: 800}

   loadPage: ->


redirect login for select plan page

redirect login for select plan page

--- js/inner/org.coffee
+++ js/inner/org.coffee
@@ -66,11 +66,13 @@

     # This is a computed observable that only exists for its side-effects
     @redirect_to_plan = ko.computed
-      read: () =>
-        if @billing().loaded() && _.contains(@billing_subpages, @subpage())
-          if !@billing().can_edit_plan()
-            @subpage('plan')
-      deferEvaluation: false # insurance in case we make true the default
+      read: () =>
+        if @billing().loaded() && _.contains(@billing_subpages, @subpage())
+          if !@billing().can_edit_plan()
+            @subpage('plan')
+          else if @subpage() is 'plan'
+            @subpage('containers')
+      deferEvaluation: false # insurance in case we make true the default

   loadSettings: () =>
     $.ajax


Disable Pic highlighting for binary files

--- grammars/pic.cson
+++ grammars/pic.cson
@@ -3,6 +3,7 @@
 fileTypes: ["chem", "pic"]
 firstLineMatch: "^#[!/].*\\bpic2plot\\b"
 patterns: [
+	{include: "#binary"}
 	{include: "#tags"}

 	# Unexpected Roff lines caught inside Pic
@@ -53,6 +54,13 @@
 		name: "variable.language.backreference.pic"
 		match: "\\b(last|(?:\\d*1[1-3]th|\\d*0th|(?:(?!11st)\\d)*1st|\\d*2nd|(?:(?!13rd)\\d*)3rd|\\d*[4-9]th)(?:[ \t]+last)?)\\b"
 		captures: 0: name: "entity.name.pic"
+
+
+	# Lookahead to avoid highlighting binary .PIC files
+	binary:
+		name: "raw.binary.data"
+		begin: "^(?=.*[\\x00-\\x06])"
+		end: "(?=A)B"

 	# Booleans, used in DFORMAT and Grap


minor UI update

minor UI update

--- index.cjsx
+++ index.cjsx
@@ -200,7 +200,7 @@

 module.exports =
   name: 'HenseiNikki'
-  displayName: <FontAwesome key={0} name='folder-open' />{__ 'Organization Records'}
+  displayName: <FontAwesome key={0} name='folder-open' /> {__ 'Organization Records'}
   priority: 7
   author: 'Rui'
   link: 'https://github.com/ruiii'


fix(macScrollSpy): Scroll spy doesn't flicker when scrolling to last element.

Closes #132

--- src/directives/scroll_spy.coffee
+++ src/directives/scroll_spy.coffee
@@ -29,7 +29,7 @@
         return true unless scrollSpy.registered.length

         # Select the last anchor when scrollTop is over maxScroll
-        if scrollTop >= maxScroll and scrollSpy.active.id isnt scrollSpy.last().id
+        if scrollTop >= maxScroll
           return scrollSpy.setActive scrollSpy.last()

         for i in [0..scrollSpy.registered.length - 1]


Possible bug fix: Start map spot

Possible bug fix: Start map spot

--- index.cjsx
+++ index.cjsx
@@ -468,7 +468,7 @@
           # Compass
           mapArea = body.api_maparea_id
           mapCell = body.api_mapinfo_no
-          nowSpot = 0
+          nowSpot = body.api_from_no || 0
           nextSpot = body.api_no
           nextSpotKind = getCellInfo body.api_event_id, body.api_event_kind, body.api_bosscell_no, body.api_no
         when '/kcsapi/api_get_member/base_air_corps'


refactored to allow non-image links

refactored to allow non-image links

--- modules/gui/lib/widgets/ListBrowser.coffee
+++ modules/gui/lib/widgets/ListBrowser.coffee
@@ -8,6 +8,12 @@

                 data:
                     color: 'white'
+
+                    text:
+                        first: '|<'
+                        left: '<'
+                        right: '>'
+                        last: '>|'

                 template: ->
                     div class:'browse'
@@ -27,19 +33,33 @@
         ##
         ##
         _wireLinks: (data, done)->
-            _emit = (i)=>
-                @_emit 'browse',
-                    offset: i*data.limit
-                    limit: data.limit
-                return false
-
+
+
             @find('a').each (i, link)=>
                 link = $(link).click ()=>
+                    process.nextTick ()=>
+                        @_emit 'browse',
+                            offset: data.limit * parseInt link.attr('href').match(/([0-9]+)\/$/)[1]
+                            limit: data.limit

-                    _emit parseInt link.attr('href').match(/([0-9]+)\/$/)[1]
-
+                    return false
+
             done?()

+        ##
+        ##
+        ##
+        _createLink: (href, type, text, _class, img)->
+            link = $('').attr('href', href).attr 'class', 'link '+_class
+
+            if !img
+                link.html text
+            else
+                link.append $('').attr('src', '/img/arrow-'+@data.color+'-'+type+'.png')
+
+            return link
+
+
         ##
         ##
         ##
@@ -56,27 +76,22 @@
                 if rest is 0
                     last -= 1

-                linkdepth = @data.linkdepth
+                linkdepth = @data.linkdepth || 1
                 href = location.pathname.split('/')
                 href[linkdepth + 1] = ''

                 href[linkdepth] = 0
-                @__root.append $('').attr('href', href.join '/')
-                    .attr('class', 'link first')
-                    .append($('').attr 'src', '/img/arrow-'+@data.color+'-first.png')
+                @__root.append @_createLink href.join('/'), 'first', @data.text.first, 'first', @data.imageLinks

                 href[linkdepth] = if curr > 0 then curr - 1 else last
-                @__root.append $('').attr('href', href.join '/')
-                    .attr('class', 'link prev')
-                    .append($('').attr 'src', '/img/arrow-'+@data.color+'-left.png')
+                @__root.append @_createLink href.join('/'), 'left', @data.text.left, 'prev', @data.imageLinks

                 @_process [0..last],

                     each: (i, next)=>
                         href[linkdepth] = i
-                        link = $('').attr('href', href.join '/')
-                            .attr('class', 'link page')
-                            .text(i + 1)
+
+                        link = @_createLink href.join('/'), 'page', i + 1, 'page'

                         if i is curr
                             link.addClass 'actual'
@@ -85,19 +100,17 @@

                         next()

-                    done: ()=>
-
+                    done: (err)=>
+                        return done?(err) if err
+
                         href[linkdepth] = if curr < last then curr + 1 else 0
-                        @__root.append $('').attr('href', href.join '/')
-                            .attr('class', 'link next')
-                            .append($('').attr 'src', '/img/arrow-'+@data.color+'-right.png')
-
+                        @__root.append @_createLink href.join('/'), 'right', @data.text.right, 'next', @data.imageLinks
+
                         href[linkdepth] = last
-                        @__root.append $('').attr('href', href.join '/')
-                            .attr('class', 'link last')
-                            .append($('').attr 'src', '/img/arrow-'+@data.color+'-last.png')
+                        @__root.append @_createLink href.join('/'), 'last', @data.text.last, 'last', @data.imageLinks

-                        @_wireLinks data, done
+                        if floyd.system.platform is 'remote'
+                            @_wireLinks data, done


Node modules koding: set bongo.redisClient property

--- node_modules_koding/bongo/lib/bongo.coffee
+++ node_modules_koding/bongo/lib/bongo.coffee
@@ -76,7 +76,7 @@
     process.exit 1

   constructor:(options)->
-    { @mq, @mongo, @resourceName, @root, @metrics
+    { @mq, @mongo, @resourceName, @root, @metrics, @redisClient
       @fetchClient, @verbose, models, @kite, @mqConfig } = options
     @setClient @mongo  if @mongo
     @localStore = new Store


bongo: code style: @ => this

bongo: code style: @ => this

--- node_modules_koding/bongo/lib/bongo.coffee
+++ node_modules_koding/bongo/lib/bongo.coffee
@@ -425,8 +425,8 @@
     if @stack.length
       queue = @stack.map (fn)=>=>
         switch fn.length
-          when 2 then fn.call @, api, -> queue.next()   # async style
-          when 1 then fn.call @, api; queue.next()      # sync style
+          when 2 then fn.call this, api, -> queue.next()   # async style
+          when 1 then fn.call this, api; queue.next()      # sync style
           else        callback new Error "Arity error! (got #{fn.length}; expected 1 or 2)"
       daisy queue, callback
     else


client: don't include collaboration channels for private channels

--- client/activity/lib/flux/getters.coffee
+++ client/activity/lib/flux/getters.coffee
@@ -75,7 +75,10 @@
 followedPrivateChannels = [
   FollowedPrivateChannelIdsStore
   allChannels
-  (ids, channels) -> ids.map (id) -> channels.get id
+  (ids, channels) ->
+    ids
+      .map (id) -> channels.get id
+      .filter (channel) -> channel.get('typeConstant') is 'privatemessage'
 ]

 popularChannels = [


Catch ECT errors

Catch ECT errors

--- gulp-tasks.coffee
+++ gulp-tasks.coffee
@@ -51,6 +51,7 @@

     gulp.src files.html
       .pipe ect {data}
+      .on 'error', util.log
       .pipe compileInlineTags()
       .on 'error', util.log
       .pipe htmlFileToDirectory()


update clean.coffee

update clean.coffee

--- gulp/clean.coffee
+++ gulp/clean.coffee
@@ -1,14 +1,13 @@
 gulp = require 'gulp'
 del  = require 'del'
-yargs = require 'yargs'

 gulp.task 'clean', ->
-    argv = yargs.argv
-    all = argv.all
-    if all
-        del 'dist/'
-    else
-        del 'dist/js/*.js'
-        del 'dist/css/*.css'
-        del 'dist/*.html'
-        del 'dist/js/*.js.map'+	# clean image output
+	del 'dist/images/*.*'
+	# clean css / stylus output
+    del 'dist/css/*.css'
+    # clean jade output
+    del 'dist/*.html'
+    # clean javascript output
+    del 'dist/js/*.js'
+    del 'dist/js/*.js.map'


Update author

Update author

--- index.cjsx
+++ index.cjsx
@@ -79,6 +79,7 @@
   priority: 2
   displayName: [<FontAwesome key={0} name='calculator' />, ' 经验计算']
   description: '经验值计算界面'
+  author: [Yunze]
   version: '1.1.0'
   reactClass: React.createClass
     lastShipId: 0


change the name and version code

change the name and version code

--- index.cjsx
+++ index.cjsx
@@ -17,11 +17,11 @@
 module.exports =
   name: 'Akashic'
   priority: 10
-  displayName: [<FontAwesome key={0} name='book' />, ' 航海日志']
-  description: '日志'
+  displayName: [<FontAwesome key={0} name='book' />, ' 航海日志(测试版)']
+  description: '日志（测试版）'
   author: 'W.G.'
   link: 'http://weibo.com/jenningswu'
-  version: '0.0.1'
+  version: '0.6.1'
   reactClass: React.createClass
     getInitialState: ->
       content: 'Hello, world!'


Add mapred_user config

Add mapred_user config

--- hdp/mapred.coffee
+++ hdp/mapred.coffee
@@ -14,6 +14,7 @@
   require('./mapred_').configure ctx
   jobhistoryserver = ctx.host_with_module 'phyla/hdp/mapred_jhs'
   # Options for mapred-site.xml
+  ctx.config.hdp.mapred_user ?= "mapred"
   ctx.config.hdp.mapred ?= {}
   ctx.config.hdp.mapred['mapreduce.job.counters.max'] ?= 120
   # http://developer.yahoo.com/hadoop/tutorial/module7.html
@@ -21,7 +22,7 @@
   ctx.config.hdp.mapred['mapred.tasktracker.map.tasks.maximum'] ?= ctx.config.hdp.dfs_data_dir.length
   ctx.config.hdp.mapred['mapred.tasktracker.reduce.tasks.maximum'] ?= Math.ceil(ctx.config.hdp.dfs_data_dir.length / 2)
   ctx.config.hdp.mapred['mapreduce.jobtracker.system.dir'] ?= '/mapred/system'
-  ctx.config.hdp.mapred_log_dir ?= '/var/log/hadoop-mapreduce'  # /etc/hadoop/conf/hadoop-env.sh#73
+  # ctx.config.hdp.mapred_log_dir ?= '/var/log/hadoop-mapreduce'  # /etc/hadoop/conf/hadoop-env.sh#73
   ctx.config.hdp.mapred_pid_dir ?= '/var/run/hadoop-mapreduce'  # /etc/hadoop/conf/hadoop-env.sh#94
   # [Configurations for MapReduce Applications](http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/ClusterSetup.html#Configuring_the_Hadoop_Daemons_in_Non-Secure_Mode)
   ctx.config.hdp.mapred['mapreduce.framework.name'] ?= 'yarn' # Execution framework set to Hadoop YARN.


add some scrolling to click on sidebar

add some scrolling to click on sidebar

--- app/views/repos-list.coffee
+++ app/views/repos-list.coffee
@@ -23,7 +23,13 @@
       colorForState(@get('repo.lastBuildState'))
     ).property('repo.lastBuildState')

+    scrollTop: (->
+      if (window.scrollY > 0)
+        $('html, body').animate({scrollTop: 0}, 200)
+    )
+
     click: ->
+      @scrollTop()
       @get('controller').transitionToRoute('/' + @get('repo.slug'))

 `export default View`


:fire: Remove pointless logging

:fire: Remove pointless logging

--- lib/composer.coffee
+++ lib/composer.coffee
@@ -61,10 +61,7 @@
   # NOTE: Does not support `latex.outputDirectory` setting!
   clean: ->
     {filePath} = @getEditorDetails()
-
-    unless filePath?
-      latex.log.warning('File needs to be saved to disk before clean can find the project files.')
-      return
+    return unless filePath?

     rootFilePath = @resolveRootFilePath(filePath)
     rootFile = path.basename(rootFilePath)
@@ -75,14 +72,10 @@
     rootFile = rootFile.join('.')

     cleanExtensions = atom.config.get('latex.cleanExtensions')
-    # NOTE: This needs to be done async, and there's no point in being this noisy.
+    # NOTE: This needs to be done async.
     for extension in cleanExtensions
       fileToRemove = path.join(rootFilePath, rootFile + extension)
-      if fs.existsSync(fileToRemove)
-        fs.removeSync(fileToRemove)
-        console.info 'LaTeX clean removed: ' + fileToRemove
-      else
-        console.info 'LaTeX clean did not find: ' + fileToRemove
+      fs.removeSync(fileToRemove) if fs.existsSync(fileToRemove)

   setStatusBar: (statusBar) ->
     @statusBar = statusBar


Change menu label

Change menu label

--- menus/atom-sys-angular.cson
+++ menus/atom-sys-angular.cson
@@ -5,19 +5,19 @@
       label: 'SysAngular',
       submenu: [
         {
-          label: 'Generate Module',
+          label: 'Create Module',
           command: 'atom-sys-angular:generate-module'
         },
         {
-          label: 'Generate Controller',
+          label: 'Create Controller',
           command: 'atom-sys-angular:generate-controller'
         },
         {
-          label: 'Generate Directive',
+          label: 'Create Directive',
           command: 'atom-sys-angular:generate-directive'
         },
         {
-          label: 'Generate Service',
+          label: 'Create Service',
           command: 'atom-sys-angular:generate-service'
         }
       ]


fixing assets 6

fixing assets 6

--- app/assets/javascripts/pirates/simulation.coffee
+++ app/assets/javascripts/pirates/simulation.coffee
@@ -5,6 +5,7 @@

 class @Simulation
+
   @initialize = () ->
     # load elements
     @canvas = document.getElementById "pirateGrid"


Fix whitespace, split long line and...

Fix whitespace, split long line and...

... keep 'grad.transform' so that the old api continues working as before

--- lib/gradient.coffee
+++ lib/gradient.coffee
@@ -2,7 +2,7 @@
   constructor: (@doc) ->
     @stops = []
     @embedded = no
-    @_transform = [1, 0, 0, 1, 0, 0]
+    @transform = [1, 0, 0, 1, 0, 0]
     @_colorSpace = 'DeviceRGB'

   stop: (pos, color, opacity = 1) ->
@@ -10,8 +10,8 @@
     @stops.push [pos, @doc._normalizeColor(color), opacity]
     return this

-  transform: (m11, m12, m21, m22, dx, dy) ->
-    @_transform = [m11, m12, m21, m22, dx, dy]
+  setTransform: (m11, m12, m21, m22, dx, dy) ->
+    @transform = [m11, m12, m21, m22, dx, dy]
     return this

   embed: (m) ->
@@ -117,9 +117,9 @@
         Resources:
           ProcSet: ['PDF', 'Text', 'ImageB', 'ImageC', 'ImageI']
           Pattern:
-            Sh1 : pattern
+            Sh1: pattern
           ExtGState:
-            Gs1 : gstate
+            Gs1: gstate

       opacityPattern.write "/Gs1 gs /Pattern cs /Sh1 scn"
       opacityPattern.end "#{pageBBox.join(" ")} re f"
@@ -134,8 +134,13 @@
   apply: (op) ->
     # apply gradient transform to existing document ctm
     [m0, m1, m2, m3, m4, m5] = @doc._ctm.slice()
-    [m11, m12, m21, m22, dx, dy] = @_transform
-    m = [m0 * m11 + m2 * m12, m1 * m11 + m3 * m12, m0 * m21 + m2 * m22, m1 * m21 + m3 * m22, m0 * dx + m2 * dy + m4, m1 * dx + m3 * dy + m5]
+    [m11, m12, m21, m22, dx, dy] = @transform
+    m = [m0 * m11 + m2 * m12,
+         m1 * m11 + m3 * m12,
+         m0 * m21 + m2 * m22,
+         m1 * m21 + m3 * m22,
+         m0 * dx + m2 * dy + m4,
+         m1 * dx + m3 * dy + m5]

     @embed(m) unless @embedded and m.join(" ") is @matrix.join(" ")
     @doc.addContent "/#{@id} #{op}"


Refactoring factory before introducing actor/adapter library

--- lib/hfactory.coffee
+++ lib/hfactory.coffee
@@ -23,6 +23,9 @@
 # *    If not, see <http://opensource.org/licenses/mit-license.php>.
 #

+
+# Factory :
+# load all dependencies
 fs = require "fs"
 winston = require "winston"
 logger = new winston.Logger
@@ -30,6 +33,12 @@
     new winston.transports.Console(colorize: true)
   ]

+builtinActorsName = ['hactor','hauth','hchannel','hdispatcher','hgateway',
+                     'hsession','htracker']
+builtinAdaptersName = ['channel_in','channel_out','fork','http_in',
+                       'http_out','inproc','lb_socket_in','lb_socket_out',
+                       'socket_in','socket_out','socketIO','timerAdapter',
+                       'twitter_in']

 actors = {}
 adapters = {}
@@ -55,55 +64,48 @@

 newActor = (type, properties) ->
-  if not type then throw new Error "Actor's type undefined"
-  if not actors[type] then actors[type] = require type
-  else if typeof actors[type] is "string" then actors[type] = require actors[type]
+  # Controls and warning about builtinAdapters override
+  throw new Error "Actor's type undefined" if not type
+  if not actors[type]
+    actors[type] = require type
+  else if typeof actors[type] is "string"
+    actors[type] = require actors[type]
   new actors[type] properties

 newAdapter = (type, properties) ->
-  if not type then throw new Error "Adapter's type undefined"
-  if not adapters[type] then adapters[type] = require type
-  else if typeof adapters[type] is "string" then adapters[type] = require adapters[type]
+  # Controls and warning about builtinAdapters override
+  throw new Error "Adapter's type undefined" if not type
+  if not adapters[type]
+    adapters[type] = require type
+  else if typeof adapters[type] is "string"
+    adapters[type] = require adapters[type]
   new adapters[type] properties

-scan = (path, callback) ->
-  if fs.existsSync path
-    stats =  fs.statSync path
-    if stats.isDirectory()
-      logger.info "Scanning #{path}..."
-      files = fs.readdirSync path
-      files.forEach (file) ->
-        pos = file.indexOf ".coffee"
-        if pos isnt -1
-          stats = fs.statSync "#{path}/#{file}"
-          if stats.isFile()
-            callback file.substr(0, pos), "#{path}/#{file}"
+loadDirectory = (path, callback) ->
+  return unless fs.existsSync path
+  stats =  fs.statSync path
+  return unless stats.isDirectory()
+  logger.info "Scanning #{path}..."
+  files = fs.readdirSync path
+  files.forEach (file) ->
+    # TODO Recursive file loading
+    if (file.indexOf ".coffee" isnt -1) and (fs.statSync("#{path}/#{file}").isFile())
+      callback file.substr(0, pos), "#{path}/#{file}"

-scan "#{process.cwd()}/actors", withActor
-scan "#{process.cwd()}/adapters", withAdapter
+loadActors = () ->
+  builtinActorsName.forEach(name) ->
+    require "./actor/#{name}"
+  loadDirectory "#{process.cwd()}/actors", withActor

-actors['hactor'] = require "./actor/hactor"
-actors['hauth'] = require "./actor/hauth"
-actors['hchannel'] = require "./actor/hchannel"
-actors['hdispatcher'] = require "./actor/hdispatcher"
-actors['hgateway'] = require "./actor/hgateway"
-actors['hsession'] = require "./actor/hsession"
-actors['htracker'] = require "./actor/htracker"
+loadAdapters = () ->
+  builtinAdaptersName.forEach(name) ->
+    require "./adapters/#{name}"
+  loadDirectory "#{process.cwd()}/adapters", withAdapter

-adapters['channel_in'] = require "./adapters/channel_in"
-adapters['channel_out'] = require "./adapters/channel_out"
-adapters['fork'] = require "./adapters/fork"
-adapters['http_in'] = require "./adapters/http_in"
-adapters['http_out'] = require "./adapters/http_out"
-adapters['inproc'] = require "./adapters/inproc"
-adapters['lb_socket_in'] = require "./adapters/lb_socket_in"
-adapters['lb_socket_out'] = require "./adapters/lb_socket_out"
-adapters['socket_in'] = require "./adapters/socket_in"
-adapters['socket_out'] = require "./adapters/socket_out"
-adapters['socketIO'] = require "./adapters/socketIO"
-adapters['timerAdapter'] = require "./adapters/timerAdapter"
-adapters['twitter_in'] = require "./adapters/twitter_in"
+
+loadAdapters
+loadActors

 exports.withActor = withActor


Lint.

Lint.

--- lib/locparse.coffee
+++ lib/locparse.coffee
@@ -169,7 +169,8 @@
 			dbConnection.query.sync(
 				dbConnection
 				'INSERT INTO locations (id, title, description, area, "default", goto, picture) VALUES($1,$2,$3,$4,$5,$6,$7)'
-				[loc.id, loc.name, loc.description, loc.area.id, (if loc is @defaultLocation then 1 else 0), goto.join('|'), loc.picture]
+				[loc.id, loc.name, loc.description, loc.area.id, (if loc is @defaultLocation then 1 else 0),
+					goto.join('|'), loc.picture]
 			)


no message

no message

--- contentful.coffee
+++ contentful.coffee
@@ -6,5 +6,5 @@
      topics:                          # data will be made available through this key on the `contentful` object in your templates
        id: 'topic'                    # ID of your content type
     #   filters: {}                   # passes filters to the call to contentful's API, see contentful's docs for more info
-       template: 'views/codepage.jade'  # if present a single page view will be created for each entry in the content type
+    #   template: 'views/codepage.jade'  # if present a single page view will be created for each entry in the content type
     #   path: (entry) ->              # override function for generating single page file path, passed in the entry object


Make count to return configurable

Make count to return configurable

--- src/hubot-untappd-friends.coffee
+++ src/hubot-untappd-friends.coffee
@@ -9,6 +9,7 @@
 #  UNTAPPD_API_KEY - Your Untappd API Key
 #  UNTAPPD_API_SECRET - Your Untappd API Secret
 #  UNATPPD_API_ACCESS_TOKEN - A valid OAuth 2 token
+#  UNTAPPD_MAX_COUNT - (optional) Number of results to return
 #
 # Commands:
 #  hubot untappd - Recent friend activity
@@ -22,6 +23,8 @@
 # Author:
 #  sethington, stephenyeargin

+count_to_return = process.env.UNTAPPD_MAX_COUNT || 10
+
 module.exports = (robot) ->
   QS = require 'querystring'
   UntappdClient = require 'node-untappd'
@@ -98,7 +101,7 @@
           msg.send "#{checkin.user.user_name}: #{checkin.beer.beer_name} (#{checkin.beer.beer_style} - #{checkin.beer.beer_abv}%) by #{checkin.brewery.brewery_name} at #{checkin.venue.venue_name} - #{time_ago}"
         else
           msg.send "#{checkin.user.user_name}: #{checkin.beer.beer_name} (#{checkin.beer.beer_style} - #{checkin.beer.beer_abv}%) by #{checkin.brewery.brewery_name} - #{time_ago}"
-    , 5
+    , count_to_return

   ##
   # Get User Data
@@ -118,7 +121,7 @@
           msg.send "#{checkin.beer.beer_name} (#{checkin.beer.beer_style} - #{checkin.beer.beer_abv}%) by #{checkin.brewery.brewery_name} at #{checkin.venue.venue_name} - #{time_ago}"
         else
           msg.send "#{checkin.beer.beer_name} (#{checkin.beer.beer_style} - #{checkin.beer.beer_abv}%) by #{checkin.brewery.brewery_name} - #{time_ago}"
-    , username, 1
+    , username, count_to_return

   ##
   # Get Brewery Data
@@ -127,7 +130,7 @@
       msg.send 'Must provide a brewery name to ask about.'
       return

-    count = 5
+    count = count_to_return
     untappd.searchBrewery (err, obj) ->
       return unless checkUntappdErrors err, obj, msg

@@ -150,7 +153,7 @@
       msg.send 'Must provide a beer name to ask about.'
       return

-    count = 5
+    count = count_to_return
     untappd.searchBeer (err, obj) ->
       return unless checkUntappdErrors err, obj, msg


clear non-last-selection when create-persistent-selection #414

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -333,6 +333,14 @@

   mutateSelection: (selection) ->
     @vimState.persistentSelection.markBufferRange(selection.getBufferRange())
+
+  execute: ->
+    @onDidFinishOperation =>
+      lastSelection = @editor.getLastSelection()
+      for selection in @editor.getSelections() when selection isnt lastSelection
+        selection.destroy()
+    super
+

 class TogglePersistentSelection extends CreatePersistentSelection
   @extend()


:beers: Now I I understood there is 3 cases!

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -210,22 +210,17 @@
     @pointBySelection = new Map
     wasVisual = @isMode('visual')

-    if @needStay()
-      if wasVisual
-        console.log 'case-1'
-        @saveCursorPositions('head', fromProperty: true, allowFallback: true) # visual-stay
-      else
-        console.log 'case-2'
-        @saveCursorPositions('head') unless @instanceof('Select') # stay
-    else
-      if wasVisual
-        console.log 'case-3'
-        @saveCursorPositions('start') # visual-notStay
-      else
-        console.log 'case-4'
-        # normal-mode
-        @preemptDidSelectTarget =>
-          @saveCursorPositions('start')
+    if @needStay() and wasVisual
+      console.log 'case-1'
+      @saveCursorPositions('head', fromProperty: true, allowFallback: true) # visual-stay
+
+    else if @needStay() and not wasVisual
+      console.log 'case-2'
+      @saveCursorPositions('head') unless @instanceof('Select') # stay
+
+    else
+      console.log 'case-3'
+      @preemptDidSelectTarget => @saveCursorPositions('start')

     @emitWillSelectTarget()
     @target.select()


disable "sugar" package (slows it down

disable "sugar" package (slows it down

--- lib/provider.coffee
+++ lib/provider.coffee
@@ -1,7 +1,7 @@
 fs = require "fs"
 bibtexParse = require "zotero-bibtex-parse"
 fuzzaldrin = require "fuzzaldrin"
-require "sugar"
+# require "sugar"
 XRegExp = require('xregexp').XRegExp

 module.exports =


Only remove settings from storage.local if it's not our main store

--- lib/settings.coffee
+++ lib/settings.coffee
@@ -75,7 +75,7 @@
         setting = {}; setting[key] = @cache[key]
         @log "   chrome.storage.#{storageArea}.set(#{key})"
         @storage.set setting
-      if Utils.isBackgroundPage()
+      if Utils.isBackgroundPage() and storageArea == "sync"
         # Remove options installed by the "copyNonDefaultsToChromeStorage-20150717" migration; see below.
         @log "   chrome.storage.local.remove(#{key})"
         chrome.storage.local.remove key


correcting strategy.coffee

correcting strategy.coffee

--- lib/strategy.coffee
+++ lib/strategy.coffee
@@ -36,7 +36,6 @@
     query.redirect_uri = options.redirect
     done null, url

-"grant_type":"client_credentials"
 fetchAccessToken: (code, dialog, done) ->
   url = @url 'token'
   query = url.query or= {}


Don't do anything for bootstrap collapse component

--- resources/assets/coffee/turbolinks-overrides.coffee
+++ resources/assets/coffee/turbolinks-overrides.coffee
@@ -19,7 +19,11 @@
 # Anchor navigation with turbolinks. Works around [1].
 # [1] https://github.com/turbolinks/turbolinks/issues/75
 $(document).on 'click', 'a[href^="#"]', (e) ->
-  href = e.currentTarget.href
+  link = e.currentTarget
+
+  return if link.dataset.toggle == 'collapse'
+
+  href = link.href
   targetId = decodeURIComponent href[href.indexOf('#') + 1..]

   return if targetId == ''


Let OSX version find 7za

Let OSX version find 7za

--- metal/extractors/zip.coffee
+++ metal/extractors/zip.coffee
@@ -1,6 +1,11 @@

 path = require "path"
 Zip = require "node-7z"
+
+switch process.platform
+  when "darwin"
+    # ship 7za with the client
+    process.env.PATH += ':.'

 normalize = (p) ->
   path.normalize p.replace /[\s]*$/, ""


simplified 'pack' main build task

simplified 'pack' main build task

--- dist/buildscripts/src/pack.coffee
+++ dist/buildscripts/src/pack.coffee
@@ -7,39 +7,13 @@

 tools = require './tools'
 standalone = require './standalone'
-{PackBuild} = require './standalone'
+{Pack, PackAll} = require './standalone'
 {InstallerBuild} = require './installer'

 module.exports = pack = ( argv ) ->
-    builds = []
-
-    ask_pack = (callback) ->
-        maybe_pack = (err, val) ->
-            if val
-                builds.push new PackBuild('linux', 'x64')
-                builds.push new PackBuild('win32', 'ia32')
-                builds.push new PackBuild('win32', 'x64')
-            callback null, null
-        tools.promptBool("perform packing tasks?", no, maybe_pack)
-
-    ask_intallers = (callback) ->
-        maybe_installers = (err, val) ->
-            if val
-                builds.push new InstallerBuild('linux', 'x64')
-                builds.push new InstallerBuild('win32', 'ia32')
-                builds.push new InstallerBuild('win32', 'x64')
-            callback null, null
-        tools.promptBool("perform installer tasks?", no, maybe_installers)
-
-    async.series [ask_pack, ask_intallers], ->
-        task = (b, f) -> b.execute(f)
-        tasks = (_.partial(task, b) for b in builds)
-
-        async.series tasks, (err, result) ->
-            if err?
-                console.error err
-            else
-                console.log " -- Done -- "
+    packall = new PackAll()
+    packall.execute ->
+        console.log " Nigger Anus "

 do ->
     argv = process.argv[2..]


Put MineralCtrl dependencies on separate rows

--- app/static/script/controller/mineral-ctrl.coffee
+++ app/static/script/controller/mineral-ctrl.coffee
@@ -1,7 +1,16 @@
 'use strict'

-angular.module('app')
-  .controller 'MineralCtrl', ['$http', '$log', '$scope', 'Functional', ($http, $log, $scope, Fx) ->
+angular.module('app').controller 'MineralCtrl', [
+  '$http',
+  '$log',
+  '$scope',
+  'Functional',
+  (
+    $http,
+    $log,
+    $scope,
+    Fx,
+  ) ->
     $scope.chart =
       src: ''
       data: []
@@ -97,4 +106,4 @@
       # $log.info "Watching chart.src:", src, old
       return unless src
       $scope.getStatistics(src)
-  ]
+]


REFACTOR: code cleanup

REFACTOR: code cleanup

--- source/Art/Engine/Core/Element.coffee
+++ source/Art/Engine/Core/Element.coffee
@@ -818,14 +818,6 @@
     stagingBitmap = @_renderStagingBitmap rect(0, 0, @_currentSize.x * s.x, @_currentSize.y * s.y), m = Matrix.scale s
     target.drawBitmap m.inv.mul(elementToTargetMatrix), stagingBitmap, compositeMode:@_compositeMode, opacity: @opacity

-  _fullDraw: (targetSpaceDrawArea, target, elementToTargetMatrix) ->
-    # @log _fullDraw:element:@inspectedName, targetSpaceDrawArea:targetSpaceDrawArea, elementToTargetMatrix:elementToTargetMatrix,
-    #   clip:@_clip
-    #   _useStagingBitmap: @_useStagingBitmap()
-    if @_clip                     then @_clipDraw targetSpaceDrawArea, target, elementToTargetMatrix
-    else if @needsStagingBitmap   then @_drawWithStagingBitmap targetSpaceDrawArea, target, elementToTargetMatrix
-    else                               @_drawChildren target, elementToTargetMatrix
-
   _clipDraw: (clipArea, target, elementToTargetMatrix)->
     if !elementToTargetMatrix.getIsTranslateAndScaleOnly() || @needsStagingBitmap
       @_clippedDrawWithStagingBitmapInElementSpace target, elementToTargetMatrix
@@ -850,7 +842,13 @@
       targetSpaceDrawArea = @drawAreaIn(elementToTargetMatrix).intersection target.getClippingArea()
       return unless targetSpaceDrawArea.area > 0

-      @_cachedFullDraw targetSpaceDrawArea, target, elementToTargetMatrix
+      if @getCacheDrawRequired()
+        @_cachedFullDraw targetSpaceDrawArea, target, elementToTargetMatrix
+      else
+        @_clearDrawCache()
+        if @_clip then  @_clipDraw targetSpaceDrawArea, target, elementToTargetMatrix
+        else            @_drawChildren target, elementToTargetMatrix
+
     finally
       @_currentDrawTarget = @_currentToTargetMatrix = null

@@ -925,24 +923,15 @@
     # override this for elements which are faster w/o caching (RectangleElement, BitmapElement)
     cacheable: -> true

-  _generateDrawCacheIfNeeded: ->
-    if @getCacheDrawRequired()
-      @_generateDrawCache() unless @getCacheIsValid()
-    else
-      @_clearDrawCache()
-
   _cachedFullDraw: (targetSpaceDrawArea, target, elementToTargetMatrix) ->

-    @_generateDrawCacheIfNeeded()
-
-    if @getCacheIsValid()
-      drawCacheManager.useDrawCache @
-      drawCacheToTargetMatrix = @_drawCacheToElementMatrix.mul elementToTargetMatrix
-      target.drawBitmap drawCacheToTargetMatrix, @_drawCacheBitmap,
-        opacity:        @opacity
-        compositeMode:  @compositeMode
-    else
-      @_fullDraw targetSpaceDrawArea, target, elementToTargetMatrix
+    @getCacheIsValid() || @_generateDrawCache()
+
+    drawCacheManager.useDrawCache @
+    drawCacheToTargetMatrix = @_drawCacheToElementMatrix.mul elementToTargetMatrix
+    target.drawBitmap drawCacheToTargetMatrix, @_drawCacheBitmap,
+      opacity:        @opacity
+      compositeMode:  @compositeMode

   _generateDrawCache: ->


debug

debug

--- JSKit/04_JSMenuView.coffee
+++ JSKit/04_JSMenuView.coffee
@@ -46,7 +46,7 @@
                 if (@_userInteractionEnabled == false)
                     return
                 obj = ui.item
-                JSLog($(obj).value())
+                JSLog(event)
                 @selectMenuItem(item)
                 @closeMenu()
             classes:


lazy load package dependencies to speed up Atom startup time

--- lib/wakatime.coffee
+++ lib/wakatime.coffee
@@ -6,20 +6,22 @@
 Website:     https://wakatime.com/
 ###

-AdmZip = require 'adm-zip'
-fs = require 'fs'
-os = require 'os'
-path = require 'path'
-execFile = require('child_process').execFile
-request = require 'request'
-rimraf = require 'rimraf'
-ini = require 'ini'
-
+# package-global attributes
 packageVersion = null
 unloadHandler = null
 lastHeartbeat = 0
 lastFile = ''
 apiKey = null
+
+# lazy-load packages during activation to speed up Atom startup time
+AdmZip = null
+fs = null
+os = null
+path = null
+execFile = null
+request = null
+rimraf = null
+ini = null

 module.exports =
   config:
@@ -41,6 +43,8 @@
   activate: (state) ->
     packageVersion = atom.packages.getLoadedPackage('wakatime').metadata.version

+    loadPackages()
+
     if not isCLIInstalled()
       installCLI(->
         console.log 'Finished installing wakatime cli.'
@@ -64,6 +68,16 @@
     cleanupOnUninstall()
     setupEventHandlers()
     setApiKey()
+
+loadPackages = ->
+  AdmZip = require 'adm-zip'
+  fs = require 'fs'
+  os = require 'os'
+  path = require 'path'
+  execFile = require('child_process').execFile
+  request = require 'request'
+  rimraf = require 'rimraf'
+  ini = require 'ini'

 getUserHome = ->
   process.env[if process.platform == 'win32' then 'USERPROFILE' else 'HOME'] || ''


adjust delta

adjust delta

--- source/javascripts/application.coffee
+++ source/javascripts/application.coffee
@@ -112,9 +112,11 @@
   nav = $ '#sidebar-navigation'
   cls = 'fixed'
   top = win.scrollTop()
-  if lastScrollTop - top > 0 or top < nav.height()
+  navh = nav.height()
+  diff = lastScrollTop - top
+  if diff > 1 or top < navh
     nav.addClass cls
-  else
+  else if diff < -1
     nav.removeClass cls
   lastScrollTop = top
   return


log out which command logger is used

log out which command logger is used

--- app/coffee/CompileManager.coffee
+++ app/coffee/CompileManager.coffee
@@ -7,10 +7,13 @@
 logger = require "logger-sharelatex"
 Metrics = require "./Metrics"
 child_process = require "child_process"
-CommandRunner = require(Settings.clsi?.commandRunner or "./CommandRunner")
 DraftModeManager = require "./DraftModeManager"
 fs = require("fs")
 os = require("os")
+
+commandRunner = Settings.clsi?.commandRunner or "./CommandRunner"
+logger.info commandRunner:commandRunner, "selecting command runner for clsi"
+CommandRunner = require(commandRunner)

 module.exports = CompileManager =
 	doCompile: (request, callback = (error, outputFiles) ->) ->


Correctly count project_ops_length

Correctly count project_ops_length

--- app/coffee/ProjectManager.coffee
+++ app/coffee/ProjectManager.coffee
@@ -106,25 +106,34 @@
 			timer.done()
 			_callback(args...)

+		project_ops_length = 0
+
 		handleDocUpdate = (update, cb) ->
 			doc_id = update.id
 			if update.docLines?
-				RedisManager.addEntity project_id, 'doc', doc_id, user_id, update, cb
+				RedisManager.addEntity project_id, 'doc', doc_id, user_id, update, (error, count) =>
+					project_ops_length = count
+					cb(error)
 			else
-				DocumentManager.renameDocWithLock project_id, doc_id, user_id, update, cb
+				DocumentManager.renameDocWithLock project_id, doc_id, user_id, update, (error, count) =>
+					project_ops_length = count
+					cb(error)

 		handleFileUpdate = (update, cb) ->
 			file_id = update.id
 			if update.url?
-				RedisManager.addEntity project_id, 'file', file_id, user_id, update, cb
+				RedisManager.addEntity project_id, 'file', file_id, user_id, update, (error, count) =>
+					project_ops_length = count
+					cb(error)
 			else
-				RedisManager.renameFile project_id, file_id, user_id, update, cb
+				RedisManager.renameFile project_id, file_id, user_id, update, (error, count) =>
+					project_ops_length = count
+					cb(error)

 		async.each docUpdates, handleDocUpdate, (error) ->
 			return callback(error) if error?
-			async.each fileUpdates, handleFileUpdate, (error, project_ops_length) ->
+			async.each fileUpdates, handleFileUpdate, (error) ->
 				return callback(error) if error?
 				if HistoryManager.shouldFlushHistoryOps(project_ops_length, docUpdates.length + fileUpdates.length, HistoryManager.FLUSH_PROJECT_EVERY_N_OPS)
-					logger.log { project_ops_length, project_id }, "flushing project history api"
 					HistoryManager.flushProjectChangesAsync project_id
 				callback()


Send worker idle waiting times to statsd

--- app/coffee/WorkersManager.coffee
+++ app/coffee/WorkersManager.coffee
@@ -3,6 +3,7 @@
 Keys = require('./RedisKeyBuilder')
 redis = require('redis')
 UpdateManager = require('./UpdateManager')
+Metrics = require('./Metrics')

 module.exports = WorkersManager =
 	createWorker: () ->
@@ -13,7 +14,9 @@
 		worker = {
 			client: client
 			waitForAndProcessUpdate: (callback = (error) ->) ->
+				timer = new Metrics.Timer "worker.waiting"
 				worker.client.blpop "pending-updates-list", 0, (error, result) ->
+					timer.done()
 					return callback(error) if error?
 					return callback() if !result?
 					[list_name, doc_key] = result


fix: silly mistake

fix: silly mistake

--- app/components/vnc-viewer.coffee
+++ app/components/vnc-viewer.coffee
@@ -95,7 +95,7 @@
         isApiScanEnabled: isApiScanEnabled
       @get("ajax").post apiScanOptions, data: data
       .then (data)->
-        @send "closeModal"
+        that.send "closeModal"
         that.send "dynamicScan"
         that.get("notify").success "Starting the scan"
       .catch (error) ->


Add JS style changes.

Add JS style changes.

Thanks @rspeicher

--- app/assets/javascripts/application.js.coffee
+++ app/assets/javascripts/application.js.coffee
@@ -232,7 +232,8 @@
       $this = $(this)
       $thisIcon = $this.find 'i'
       if $thisIcon.hasClass('fa-angle-double-right')
-        $thisIcon.removeClass('fa-angle-double-right')
+        $thisIcon
+          .removeClass('fa-angle-double-right')
           .addClass('fa-angle-double-left')
         $this
           .closest('aside')
@@ -242,7 +243,8 @@
           .removeClass('right-sidebar-expanded')
           .addClass('right-sidebar-collapsed')
       else
-        $thisIcon.removeClass('fa-angle-double-left')
+        $thisIcon
+          .removeClass('fa-angle-double-left')
           .addClass('fa-angle-double-right')
         $this
           .closest('aside')


Removed realtime price checking

Removed realtime price checking

--- app/assets/javascripts/application.js.coffee
+++ app/assets/javascripts/application.js.coffee
@@ -1,5 +1,5 @@
 #= require def
-#= require realtime_price
+## require realtime_price
 #= require raphael
 #= require jquery.dependClass
 #= require jquery.history


MO Chart: fixed bad unit on element tooltip

--- app/assets/javascripts/d3/merit_order.coffee
+++ app/assets/javascripts/d3/merit_order.coffee
@@ -170,7 +170,7 @@
         )
         .attr("x", (d) => @x(d.get 'x_offset'))
         .attr("data-tooltip-text", (d) ->
-          html = "Installed capacity: #{Metric.autoscale_value(d.value_x() * 1000000, 'MW', 2)}
+          html = "Installed capacity: #{Metric.autoscale_value(d.value_x(), 'MW', 2)}
                   <br/>
                   Operating costs: #{Metric.autoscale_value d.original_y_value(), 'euro', 2}"
           if d.get('key') == 'must_run'


improve dead call resistence

improve dead call resistence

--- app/assets/javascripts/models/call.js.coffee
+++ app/assets/javascripts/models/call.js.coffee
@@ -48,20 +48,20 @@

   agent: ( ->
     users = @get('allUsers')
-    return false unless users
+    chan1 = @get('channel1')
+    return false unless users && chan1

-    users.find (user) =>
-      @get('channel1').match user.get('name')
+    users.find (user) -> chan1.match(user.get 'name')
   ).property('allUsers.@each.name', 'channel1')

   origin: ( ->
     calls = @get('allCalls')
-    return false unless calls
+    chan2 = @get('channel2')
+    return false unless calls && chan2

-    calls.find (call) =>
-      call.get('initiator') &&
-      call.get('channel1') == @get('channel2')
+    calls.find (call) ->
+      call.get('initiator') && call.get('channel1') == chan2
   ).property('allCalls.@each.{initiator,channel2}', 'channel1')


Fix typo

Fix typo

--- app/coffee/modules/backlog/lightboxes.coffee
+++ app/coffee/modules/backlog/lightboxes.coffee
@@ -133,7 +133,7 @@

     return {link: link}

-CreateBulkUserstroriesDirective = ($repo, $rs, $rootscope) ->
+CreateBulkUserstoriesDirective = ($repo, $rs, $rootscope) ->
     link = ($scope, $el, attrs) ->
         $scope.form = {data: ""}

@@ -208,6 +208,8 @@

 module = angular.module("taigaBacklog")
-module.directive("tgLbCreateEditUserstory", ["$tgRepo", "$tgModel", "$tgResources", "$rootScope", CreateEditUserstoryDirective])
-module.directive("tgLbCreateBulkUserstories", ["$tgRepo", "$tgResources", "$rootScope", CreateBulkUserstroriesDirective])
+module.directive("tgLbCreateEditUserstory", ["$tgRepo", "$tgModel", "$tgResources", "$rootScope",
+                                             CreateEditUserstoryDirective])
+module.directive("tgLbCreateBulkUserstories", ["$tgRepo", "$tgResources", "$rootScope",
+                                               CreateBulkUserstoriesDirective])
 module.directive("tgLbCreateSprint", ["$tgRepo", "$tgResources", "$rootScope", CreateSprint])


debugging

debugging

--- src/smc-hub/postgres-base.coffee
+++ src/smc-hub/postgres-base.coffee
@@ -25,6 +25,7 @@
 read_password_from_disk = ->
     filename = (process.env.SMC_ROOT ? '.') + '/data/secrets/postgres'
     try
+        winston.debug("Loading password from '#{filename}'")
         return fs.readFileSync(filename).toString().trim()
     catch
         winston.debug("NO PASSWORD FILE!")


Format.

Format.

--- src/spec/integration.spec.coffee
+++ src/spec/integration.spec.coffee
@@ -9,18 +9,18 @@
     @xmlImport = new XmlImport()
     @sync = new Sync Config
     rest = new Rest Config
-    rest.GET "/products", (error, response, body)->
+    rest.GET "/products", (error, response, body) =>
       expect(response.statusCode).toBe 200
       for p in JSON.parse(body).results
-        rest.DELETE "/products/#{p.id}?version=#{p.version}", (error, response, body)->
+        rest.DELETE "/products/#{p.id}?version=#{p.version}", (error, response, body) =>
           expect(response.statusCode.toString()).toMatch /[24]00/

   it 'process', (done)->
-    fs.readFile 'src/spec/oneProduct.xml', 'utf8', (err, content)=>
+    fs.readFile 'src/spec/oneProduct.xml', 'utf8', (err, content) =>
       expect(err).toBeUndefined
       data =
         attachments:
           oneProduct: content
-      @xmlImport.process data, (cb)->
+      @xmlImport.process data, (cb) ->
         console.log("PROCESS %j", cb)
         done()


Wait for beforeEach to be finished. Execute xmlImport twice.

--- src/spec/integration.spec.coffee
+++ src/spec/integration.spec.coffee
@@ -5,7 +5,7 @@
 Rest = require("sphere-node-connect").Rest

 describe "Integration", ->
-  beforeEach ->
+  beforeEach (done) ->
     @xmlImport = new XmlImport()
     @sync = new Sync Config
     rest = new Rest Config
@@ -14,6 +14,7 @@
       for p in JSON.parse(body).results
         rest.DELETE "/products/#{p.id}?version=#{p.version}", (error, response, body) =>
           expect(response.statusCode.toString()).toMatch /[24]00/
+          done()

   it 'process', (done)->
     fs.readFile 'src/spec/oneProduct.xml', 'utf8', (err, content) =>
@@ -21,6 +22,8 @@
       data =
         attachments:
           oneProduct: content
-      @xmlImport.process data, (cb) ->
-        console.log("PROCESS %j", cb)
-        done()+      @xmlImport.process data, (msg) =>
+        expect(msg.message.status).toBe true
+        @xmlImport.process data, (msg) =>
+          expect(msg.status).toBe true
+          done()


:art: Use `pixelPositionForScreenPositionInTile`

--- src/text-editor-presenter.coffee
+++ src/text-editor-presenter.coffee
@@ -1042,7 +1042,14 @@
   hasPixelPositionRequirements: ->
     @lineHeight? and @baseCharacterWidth?

-  pixelPositionForScreenPosition: (screenPosition, clip=true, foo) ->
+  pixelPositionForScreenPositionInTile: (tileStartRow, screenPosition, clip) ->
+    position = @pixelPositionForScreenPosition(screenPosition, clip)
+    position.top -= tileStartRow * @lineHeight
+    position.top += @scrollTop
+    position.left += @scrollLeft
+    position
+
+  pixelPositionForScreenPosition: (screenPosition, clip=true) ->
     screenPosition = Point.fromObject(screenPosition)
     screenPosition = @model.clipScreenPosition(screenPosition) if clip

@@ -1051,7 +1058,6 @@
     baseCharacterWidth = @baseCharacterWidth

     top = targetRow * @lineHeight
-    top -= foo * @lineHeight if foo?
     left = 0
     column = 0

@@ -1076,8 +1082,8 @@
         left += characterWidths[char] ? baseCharacterWidth unless char is '\0'
         column += charLength

-    top -= @scrollTop unless foo?
-    left -= @scrollLeft unless foo?
+    top -= @scrollTop
+    left -= @scrollLeft
     {top, left}

   hasPixelRectRequirements: ->
@@ -1302,8 +1308,8 @@

   buildHighlightRegions: (tileStartRow, screenRange) ->
     lineHeightInPixels = @lineHeight
-    startPixelPosition = @pixelPositionForScreenPosition(screenRange.start, true, tileStartRow)
-    endPixelPosition = @pixelPositionForScreenPosition(screenRange.end, true, tileStartRow)
+    startPixelPosition = @pixelPositionForScreenPositionInTile(tileStartRow, screenRange.start, true)
+    endPixelPosition = @pixelPositionForScreenPositionInTile(tileStartRow, screenRange.end, true)
     spannedRows = screenRange.end.row - screenRange.start.row + 1

     if spannedRows is 1


QUALITY: Remove unused code in progress-burndown

--- src/app/visualisations/progress-burndown-chart.coffee
+++ src/app/visualisations/progress-burndown-chart.coffee
@@ -48,21 +48,7 @@
     # Clips x values to be at the y = 0 intercept if y < 0
     #
     xAxisClipNegBurndown = (d) ->
-      if d[1] < 0.0
-        # find the x intercept at y = 0
-        # know originX is the origin date of the graph (i.e. burnoff is still 100%)
-        originX = $scope.project.burndown_chart_data[0].values[0][0]
-        # work off the 100% point and this point
-        [pt1x, pt1y] = [originX, 1]
-        [pt2x, pt2y] = [d[0], d[1]]
-        # find gradient
-        m    = (pt2y - pt1y) / (pt2x - pt1x)
-        # get actual y intercept
-        c    = pt1y - m * pt1x
-        # solve x intercept via 0 = mx+c
-        -c/m
-      else
-        d[0]
+      d[0]

     #
     # Clips y to 0 if y < 0


Only show output files which are images or pdfs

--- services/web/public/coffee/ide/file-tree/controllers/FileTreeController.coffee
+++ services/web/public/coffee/ide/file-tree/controllers/FileTreeController.coffee
@@ -342,7 +342,9 @@
 				})
 				.then (resp) ->
 					if resp.data.status == 'success'
-						$scope.data.projectOutputFiles = resp.data.outputFiles
+						filteredFiles = resp.data.outputFiles.filter (f) ->
+							f.path.match(/.*\.(pdf|png|jpeg|jpg|gif)/)
+						$scope.data.projectOutputFiles = filteredFiles
 						_reset(err: false)
 					else
 						$scope.data.projectOutputFiles = null


:white_check_mark: Add test for underline background color

--- spec/color-marker-element-spec.coffee
+++ spec/color-marker-element-spec.coffee
@@ -156,6 +156,10 @@
       expect(regions[2].textContent).toEqual('')
       expect(regions[3].textContent).toEqual('')

+    it 'sets the background of the region with the color css value', ->
+      for region in regions
+        expect(region.style.backgroundColor).toEqual('rgb(255, 0, 0)')
+
     describe 'when the marker is modified', ->
       beforeEach ->
         spyOn(colorMarkerElement.renderer, 'render').andCallThrough()


Add interns

Add interns

--- app/controllers/team-page.coffee
+++ app/controllers/team-page.coffee
@@ -53,6 +53,21 @@

Blanka Shaw (Database Manager)

+
+
Interns

+

+
Dara  Arabsheibani (Northeastern Illinois University)

+
Charlie D'Lavoy (Northeastern Illinois University)

+
Alex Vizzone (Northeastern Illinois University)

+
Xenia Alava (Northeastern Illinois University)

+
Ariel Wagner (DePaul University)

+
Veronica Lopez (Northeastern Illinois University)

+
Jonathan Scheffel (Harold Washington, Chicago City College)

+
Pedro Rebollar (DePaul University)

+
Kavita Elliott (Ohio State University)

+
Ramsey Millison (DePaul University)

+
Zak Zillon (Northeastern Illinois University)

+

 '''

 class TeamPage extends Page


Sort all PRs across all repos.

Sort all PRs across all repos.

--- prviewer.coffee
+++ prviewer.coffee
@@ -350,16 +350,14 @@

           cb err, pulls

-      # Sort the pulls based on update time.
-      (pulls, cb) ->
-        pulls.sort (a, b) ->
-          if a.last_update.isBefore b.last_update then 1 else -1
-
-        cb null, pulls
-
     ], (err, pulls) ->
       return userRepoCb err if err
+
+      # Sort the pulls based on update time.
       allPulls = allPulls.concat pulls
+      allPulls.sort (a, b) ->
+        if a.last_update.isBefore b.last_update then 1 else -1
+
       userRepoCb null

   async.each settings.github.repos, userRepoIterator, (err) ->


Warn about bad repo spec.

Warn about bad repo spec.

--- prviewer.coffee
+++ prviewer.coffee
@@ -64,7 +64,9 @@

 for spec in requireEnv('GITHUB_REPOS').split ','
   [user, repo] = spec.split '/'
+  console.assert user and repo, "Bad user/repo: '#{ spec }'"
   settings.github.repos.push { user: user, repo: repo }
+console.log "Repositories:", JSON.stringify(settings.github.repos, null, '  ')

 settings.github.forcedReviewers = do ->
   obj = {}


fix(spec): remove obsolete account store spec

--- spec/stores/account-store-spec.coffee
+++ spec/stores/account-store-spec.coffee
@@ -122,7 +122,6 @@
         "organization_unit": "label"
       @instance = new @constructor
       spyOn(NylasEnv.config, "set")
-      spyOn(Actions, 'focusDefaultMailboxPerspectiveForAccounts')
       spyOn(@instance, "trigger")
       @instance.addAccountFromJSON(@json)

@@ -138,9 +137,6 @@
       expect(NylasEnv.config.set.calls[0].args).toEqual(['nylas.accountTokens', null])
       # Version must be updated last since it will trigger other windows to load nylas.accounts
       expect(NylasEnv.config.set.calls[2].args).toEqual(['nylas.accountsVersion', 1])
-
-    it "selects the account", ->
-      expect(Actions.focusDefaultMailboxPerspectiveForAccounts).toHaveBeenCalledWith(["B"])

     it "triggers", ->
       expect(@instance.trigger).toHaveBeenCalled()


Stack Catalog: Refresh my stacks list when any stack is generated

--- client/app/lib/environment/yourstacksview.coffee
+++ client/app/lib/environment/yourstacksview.coffee
@@ -68,6 +68,8 @@
         for item in controller.getListItems()
           item.emit 'ManagedMachineIsNotAllowed'

+    computeController.on 'RenderStacks', controller.bound 'loadItems'
+

   destroyModal: ->


IDELayoutManager: Emit an event when layout resurrected.

--- client/ide/lib/workspace/idelayoutmanager.coffee
+++ client/ide/lib/workspace/idelayoutmanager.coffee
@@ -190,6 +190,7 @@
     @applyLayoutSize()

     @isRestored = yes
+    @emit 'LayoutResurrected'

   ###*


fixes channel error for non-logged in user

--- models/block.coffee
+++ models/block.coffee
@@ -39,7 +39,7 @@
       @get('visibility')

   getPermissions: (user, channel)->
-    return "" unless @has('user') && channel?
+    return "" unless @has('user') && channel? and user?

     permissions = ['can-read']


simplified popup window handling, it now correctly relocates (interval may be too short for slow machines)

--- client/landing/app/CommonViews/VideoPopup.coffee
+++ client/landing/app/CommonViews/VideoPopup.coffee
@@ -7,22 +7,16 @@
     @setClass "hidden invisible"
     @videoPopup = @getSingleton("windowController").videoPopup
     @embedData = data
+    @options = options

   openVideoPopup:->
     h=@getDelegate().getHeight()
     w=@getDelegate().getWidth()
     t=@getDelegate().$().offset()
-    unless @videoPopup? and @videoPopup?.top isnt null
-
-      @videoPopup = window.open "http://localhost:3000/1.0/video-container.html", "KodingVideo", "menubar=no,resizable=yes,scrollbars=no,status=no,height=#{h},width=#{w},left=#{t.left+window.screenX},top=#{window.screenY+t.top+(window.outerHeight - window.innerHeight)}"
-      @getSingleton("windowController").videoPopup = @videoPopup
-
-    else
-
-      @videoPopup.resizeTo w,(h+@videoPopup.outerHeight-@videoPopup.innerHeight)
-      @videoPopup.moveTo t.left+window.screenX, window.screenY+t.top+(window.outerHeight - window.innerHeight)
-      @videoPopup.focus()
+    @videoPopup?.close()
+    @videoPopup = window.open "http://localhost:3000/1.0/video-container.html", "KodingVideo", "menubar=no,location=no,resizable=yes,titlebar=no,scrollbars=no,status=no,innerHeight=#{h},width=#{w},left=#{t.left+window.screenX},top=#{window.screenY+t.top+(window.outerHeight - window.innerHeight)}"
+    @getSingleton("windowController").videoPopup = @videoPopup

     @utils.wait 1500, =>          # give the popup some time to open

@@ -42,18 +36,18 @@
               content       : "
Your video will automatically end in #{secondsToAutoClose} seconds unless you click the 'Yes'-Button below.
"
               overlay       : yes
               buttons       :
+                "No, close it" :
+                  title     : "No, close it"
+                  cssClass  : "modal-clean-gray"
+                  callback  : =>
+                    @videoPopup?.close()
+                    modal.destroy()
                 "Yes, keep it running" :
                   title     : "Yes, keep it running"
-                  cssClass  : "modal-clean-gray"
+                  cssClass  : "modal-clean-green"
                   callback  : =>
                     modal.destroy()
                     userChoice = yes
-                "No, close it" :
-                  title     : "No, close it"
-                  cssClass  : "modal-clean-red"
-                  callback  : =>
-                    @videoPopup?.close()
-                    modal.destroy()

             currentSeconds = secondsToAutoClose-1
             countdownInterval = window.setInterval =>
@@ -68,7 +62,13 @@
                 @videoPopup?.close()
                 modal.destroy()

-      embed = @embedData
+      embed =
+        embed : @embedData
+        coordinates :
+          left : @options.popup?.left or t.left+window.screenX or 100
+          top : @options.popup?.top or window.screenY+t.top+(window.outerHeight - window.innerHeight) or 100
+          # height : @options.popup?.height or h or 100
+          # width : @options.popup?.width or w or 100

       if embed and @videoPopup
         @videoPopup.postMessage embed, "*"


- bingo ! overlaying an axis helper as in the three.js editor with depthTest=false and transparent= true makes the selection axis overlay work as intended

--- src/app/modules/editors/visualEditor/helpers.coffee
+++ src/app/modules/editors/visualEditor/helpers.coffee
@@ -98,7 +98,7 @@
       @add @line

       @arrowHeadRootPosition = @origin.clone().add(@direction)
-      @arrowHead = new THREE.Mesh(new THREE.CylinderGeometry(0, 1, 5, 10, 10, false),new THREE.MeshBasicMaterial({color:@color,side : THREE.DoubleSide,blending: THREE.AdditiveBlending}))
+      @arrowHead = new THREE.Mesh(new THREE.CylinderGeometry(0, 1, 5, 10, 10, false),new THREE.MeshBasicMaterial({color:@color}))
       @arrowHead.position = @arrowHeadRootPosition
       #@arrowHead.rotation = Math.PI/2
       @add @arrowHead
@@ -350,6 +350,14 @@
         lengthArrow = new THREE.ArrowHelper(new THREE.Vector3(0,1,0),new THREE.Vector3(0,0,0),length/2, 0x77FF00)
         heightArrow = new THREE.ArrowHelper(new THREE.Vector3(0,0,1),new THREE.Vector3(0,0,0),height/2, 0x0077FF)

+
+        selectionAxis = new THREE.AxisHelper( width )
+        selectionAxis.material.depthTest = false
+        selectionAxis.material.transparent = true
+        selectionAxis.position = new THREE.Vector3(width,length,height/2)
+        #selectionAxis.matrixAutoUpdate = false
+
+        mesh.add selectionAxis
         #mesh.material.side= THREE.BackSide
         #widthArrow.material.side = THREE.FrontSide


remov that

remov that

--- modules/eval.coffee
+++ modules/eval.coffee
@@ -36,7 +36,5 @@
           icon_url: msg.mentions[0].avatarURL
           text: args.slice(1).join(' ')
         }
-      .catch (e)=>
-        console.error(e)

 module.exports = EvalModule


defaulting initial tool selection to asteroid

--- app/controllers/marking-tool-controls.coffee
+++ app/controllers/marking-tool-controls.coffee
@@ -40,6 +40,7 @@

     @currentFrame  =  @imageSet.getFrameFromElement('frame-id-0')

+
     # provisional default case of artifact subtype
     artifactSubtype = "other"

@@ -52,8 +53,8 @@

         #   when 'artifact'
         #     #@tool.mark.artifact.set "subtype", @selectedArtifactRadios.value
-
-    console.log("mark changed")
+        #console.log ("noop")
+
     @setState 'whatKind'

   events:
@@ -63,29 +64,22 @@
     'change input[name="classifier-type"]': (e) ->

       if e.currentTarget.value == 'asteroid'
-        asteroid_detection=
-          type: "asteroid"
-          frame: @currentFrame.seqNumber
-
-        @setState 'asteroidTool change'
-        @tool.mark.set 'detection', asteroid_detection
+        @setState 'asteroidTool'

       else if  e.currentTarget.value == 'artifact'
-        art_detection =
-          type: "artifact"
-          frame:   @currentFrame.seqNumber
-          subType: @artifactSubtype
         @setState 'artifactTool'
-        @tool.mark.set 'detection', art_detection

       else
         console.log("Error: unknown classifier-type")

-    'change input[name="selected-artifact"]': =>
+    #'change input[name="selected-artifact"]': =>

       #TODO why do I need to place locate  selectedArtifactRadios in elements.
       # it shoudl be added go  the object scope
       # @artifactSubtype = selectedArtifactRadios.filter(':checked').val()
+
+    'click button[name="done"]': ->
+      @setMark()

     'click button[name="delete"]': ->
       @tool.mark.destroy()
@@ -134,6 +128,15 @@

   destroyImage: (img_id) ->

+  setMark: ->
+    #TODO state machine is getting messy
+    if @state is "asteroidTool" or "whatKind"
+      @tool.mark.set 'detection', @getAsteroidDetection()
+    else if @state is "artifactTool"
+      @tool.mark.set 'detection', @getArtifactDetection()
+    else
+      debugger
+      console.log("Error: marking tool not specified")

   setState: (newState) ->
     if @state
@@ -174,6 +177,21 @@
       exit: ->
         @el.find('.artifact-classifier').hide()

+  getAsteroidDetection: =>
+    asteroid_detection=
+      type: "asteroid"
+      frame: @currentFrame.seqNumber
+    asteroid_detection
+
+  getArtifactDetection: =>
+    art_detection =
+        type: "artifact"
+        frame:   @currentFrame.seqNumber
+        subType: @artifactSubtype
+    art_detection
+
+
+
   #ToDo move to model
 class ImageSet

@@ -199,7 +217,6 @@

 #TODO move to model
 class ImageFrame
-  require ("underscore")
   elementId: ''
   seqNumber: ''
   url: ''


namespaced unbind

namespaced unbind

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

   o.trigger "test"

-  o.unbind "TestNamespace", ->
+  o.unbind "TestNamespace.", ->
   o.trigger "test"

 module()


filtering in fixtures

filtering in fixtures

--- test/fixtures.coffee
+++ test/fixtures.coffee
@@ -87,8 +87,11 @@
 # Create disk from distribution
 exports.create_dist_disk = ->
   nock('https://api.linode.com')
-  .filteringPath(/rootSSHKey=[^&]*/g, 'rootSSHKey=fakesshkey')
-  .get('/?api_key=fakeapikey&api_action=linode.disk.createfromdistribution&LinodeID=206102&DistributionID=98&Label=system&Size=20000&rootPass=r00ter&rootSSHKey=fakesshkey')
+  .filteringPath (path) ->
+    return path
+      .replace(/rootSSHKey=[^&]*/g, 'rootSSHKey=fakesshkey')
+      .replace(/rootPass=[^&]*/g, 'rootPass=fakepass')
+  .get('/?api_key=fakeapikey&api_action=linode.disk.createfromdistribution&LinodeID=206102&DistributionID=98&Label=system&Size=20000&rootPass=fakepass&rootSSHKey=fakesshkey')
   .reply 200,
     """
     { "ERRORARRAY":[],


Fix merge mistake

Fix merge mistake

--- client/Home/includes.coffee
+++ client/Home/includes.coffee
@@ -2,4 +2,6 @@

   "AppController.coffee",
   "AppView.coffee",
+
+  "styl/home.styl"
 ]


client: setup analytics when remote is ready

--- client/app/lib/index.coffee
+++ client/app/lib/index.coffee
@@ -40,6 +40,8 @@
   remote.once 'ready', ->
     globals.currentGroup = remote.revive globals.currentGroup
     globals.userAccount  = remote.revive globals.userAccount
+
+    setupAnalytics()

   MainController = require './maincontroller'
   Status = require './status'
@@ -153,8 +155,6 @@

       item.ping -> destroyCurrentNotif()  if currentNotif

-  setupAnalytics()
-
   return true

 initialize = (defaults, next) ->


modest changes

modest changes

--- client/ide/fs/fsitem.coffee
+++ client/ide/fs/fsitem.coffee
@@ -57,6 +57,7 @@

       osKite.fsEnsureNonexistentPath(path: targetPath)
       .then (actualPath) ->
+
         command = "#{ commandPrefix } #{ escapeFilePath sourceItem.path } #{ escapeFilePath actualPath }"

         osKite.exec(command)
@@ -70,13 +71,10 @@
             osKite
           }

-          window.FILE = file
-
           callback null, file  if callback?

     if callback?
-      ok
-      .catch (err) ->
+      ok.catch (err) ->
         warn err
         callback err

@@ -89,7 +87,6 @@
     @copyOrMove sourceItem, targetItem, 'cp -R', callback

   @move:(sourceItem, targetItem, callback)->
-    window.FOLDER = sourceItem
     @copyOrMove sourceItem, targetItem, 'mv', callback

   @compress:(file, type, callback)->
@@ -133,10 +130,12 @@

     path = FSHelper.plainPath file.path

-    [isTarGz, extractFolder] =
-      if tarPattern.test file.name
+    [isTarGz, extractFolder] = switch
+
+      when tarPattern .test file.name
         [yes, path.replace tarPattern, '']
-      else if zipPattern.test file.name
+
+      when zipPattern .test file.name
         [no, path.replace zipPattern, '']

     osKite.vmStart()


Loop through updated properties of workspace

--- client/ide/lib/index.coffee
+++ client/ide/lib/index.coffee
@@ -169,6 +169,10 @@

   bindWorkspaceDataEvents: ->

+    @workspaceData.on 'update', (fields) =>
+
+      fields.forEach (field) =>
+

   setActiveTabView: (tabView) ->


Fix logout

Fix logout

--- client/redux/actions.coffee
+++ client/redux/actions.coffee
@@ -1,4 +1,4 @@
-import {callApiWithBody} from '../lib/callApi'
+import callApi, {callApiWithBody} from '../lib/callApi'

 import {getRawData} from './getters'


Deal with cyclic dependencies

Deal with cyclic dependencies

--- src/lib/nodejs/ComponentLoader.coffee
+++ src/lib/nodejs/ComponentLoader.coffee
@@ -109,7 +109,10 @@

   getPackagePath: (packageId, callback) ->
     found = null
+    seen = []
     find = (packageData) ->
+      return if seen.indexOf(packageData.name) isnt -1
+      seen.push packageData.name
       if packageData.name is packageId
         found = "#{packageData.realPath}/package.json"
         return


fix ignoreWarning

fix ignoreWarning

--- assets/scripts/app/pusher.coffee
+++ assets/scripts/app/pusher.coffee
@@ -85,5 +85,9 @@
       when 'annotation:created', 'annotation:updated'
         { annotation: data }

-  warn: (type, warning) ->
-    console.warn(warning)
+  warn: (type, object) ->
+    console.warn(type, object.error) unless @ignoreWarning(type, object.error)
+
+  ignoreWarning: (type, error) ->
+    if message = error?.data?.message
+      message.indexOf('Existing subscription') == 0 or message.indexOf('No current subscription') == 0


refactoring

refactoring

--- controller.coffee
+++ controller.coffee
@@ -37,43 +37,6 @@

             CozyAdapter.sendMailFromUser mailOptions, cb

-    # # add one rule
-    # # expect body = {email, contactid, autosend, perm}
-    # out.add = (req, res, next) ->
-    #     {email, contactid, autosend, perm} = req.body
-
-    #     perm ?= 'r'
-
-    #     clearance.add req.doc, perm, {email, contactid}, (err, key) ->
-    #         return next err if err
-    #         if not autosend or autosend is 'false'
-    #             res.send req.doc
-    #         else
-    #             req.body.key = key
-    #             out.send req, res, next
-
-    # # revoke one rule
-    # # expect body = {key}
-    # out.revoke = (req, res, next) ->
-    #     {key} = req.body
-    #     clearance.revoke req.doc, {key}, (err) ->
-    #         return next err if err
-    #         res.send req.doc
-
-    # # send one mail
-    # # expect body = {key}
-    # out.send = (req, res, next) ->
-    #     {key} = req.body
-    #     sendMail req.doc, key, (err) ->
-    #         return next err if err
-    #         newrules = req.doc.clearance.map (rule) ->
-    #             rule.sent = true if rule.key is key
-    #             return rule
-
-    #         req.doc.updateAttributes clearance: newrules, (err) ->
-    #             return next err if err
-    #             res.send req.doc
-
     # change the whole clearance object
     out.change = (req, res, next) ->
         {clearance} = req.body
@@ -99,14 +62,22 @@
                     return next err if err
                     res.send req.doc

+    out.getEmailsFromContactFields =  (contact) ->
+        emails = contact.datapoints?.filter (dp) -> dp.name is 'email'
+        emails = emails.map (dp) -> dp.value
+        emails
+
+    # take directly full name or build it from the name field.
+    out.getContactFullName = (contact) ->
+        contact.fn or contact.n?.split(';')[0..1].join(' ')
+
     # contact list for autocomplete
     out.contactList = (req, res, next) ->
         Contact.request 'all', (err, contacts) ->
             return next err if err
             res.send contacts.map (contact) ->
-                name = contact.fn or contact.n?.split(';')[0..1].join(' ')
-                emails = contact.datapoints?.filter (dp) -> dp.name is 'email'
-                emails = emails.map (dp) -> dp.value
+                name = out.getContactFullName contact
+                emails = out.getEmailsFromContactFields contact
                 return simple =
                     id: contact.id
                     hasPicture: contact._attachments?.picture?


Run server side tests on reload.

Run server side tests on reload.

Fixes #10.

--- lib.coffee
+++ lib.coffee
@@ -211,7 +211,7 @@
         # Execute the test.
         Tinytest.addAsync "#{ testCase.getTestName() } - #{ name.slice(4) }", (test, onComplete) ->
           # Based on testAsyncMulti from Meteor's test-helpers package.
-          remaining = testChain
+          remaining = _.clone testChain
           currentAsyncBlock = 0

           # Initialize the local test instance.


util: bug fix: elementHasTag should always return a boolean

--- core/utils.coffee
+++ core/utils.coffee
@@ -26,7 +26,7 @@
     el?.classList.add "hidden"

   elementHasTag: (el, tagName) ->
-    el.tagName?.toLowerCase() is tagName.toLowerCase()
+    !!el.tagName?.toLowerCase() is tagName.toLowerCase()

   elementIsVisible: (el) ->
     return false  if el.offsetWidth <= 0 or el.offsetHeight <= 0


wip for arvid

wip for arvid

--- core/utils.coffee
+++ core/utils.coffee
@@ -472,7 +472,7 @@

     return if location.hostname isnt "localhost"

-    status = dateFormat(Date.now(), "dddd, mmmm dS, yyyy, h:MM:ss TT");
+    status = KD.utils.generatePassword(10, yes) + ' ' + dateFormat(Date.now(), "dddd, mmmm dS, yyyy, h:MM:ss TT")

     KD.remote.api.JStatusUpdate.create body : status, (err,reply)=>
       unless err


Send root survey always

Send root survey always

--- jsapp/xlform/src/view.row.coffee
+++ jsapp/xlform/src/view.row.coffee
@@ -137,7 +137,7 @@

     add_row_to_question_library: (evt) =>
       evt.stopPropagation()
-      @ngScope?.add_row_to_question_library @model, @model.collection._parent._initialParams
+      @ngScope?.add_row_to_question_library @model, @model.getSurvey()._initialParams

   class GroupView extends BaseRowView
     className: "survey__row survey__row--group  xlf-row-view xlf-row-view--depr"


hide - show normals

hide - show normals

--- public/coffee/view/mesh-draw.coffee
+++ public/coffee/view/mesh-draw.coffee
@@ -54,13 +54,14 @@
       meshCanvas.lid.mesh.draw()

       # normals visor
-      meshCanvas.camera.use( meshCanvas.shaderSimple )
-
-      meshCanvas.shaderSimple.setUniform( 'modelMatrix', 'uniformMatrix4fv', meshCanvas.normalsVisor.modelMatrix, false )
-
-      meshCanvas.normalsVisor.mesh.draw()
-
-      meshCanvas.stats.end()
+      if meshCanvas.normalsVisor.show
+         meshCanvas.camera.use( meshCanvas.shaderSimple )
+
+         meshCanvas.shaderSimple.setUniform( 'modelMatrix', 'uniformMatrix4fv', meshCanvas.normalsVisor.modelMatrix, false )
+
+         meshCanvas.normalsVisor.mesh.draw()
+
+         meshCanvas.stats.end()
       return

    updateTime = ->
@@ -175,6 +176,7 @@
          meshCanvas.normalsVisor.modelMatrix,
          translation)

+      meshCanvas.normalsVisor.show = false

       return


Remove unused variable assignment in StorageFreak#_createAccentIndependentRE

--- coffee/storage_freak.coffee
+++ coffee/storage_freak.coffee
@@ -185,8 +185,6 @@
         re = new RegExp "#{value[0]}|#{value[1]}", 'ig'
         query = query.replace re, "(?:#{value[0]}|#{value[1]})"

-      re = null
-
       return new RegExp "#{query}", 'ig' if type == "infix"
       return new RegExp "^#{query}", 'ig' if type == "prefix"


Import jquery as required in server/serverutils

--- bokehjs/src/coffee/server/serverutils.coffee
+++ bokehjs/src/coffee/server/serverutils.coffee
@@ -1,11 +1,12 @@
 define [
+  "jquery"
   "common/base"
   "common/socket"
   "common/load_models"
   "common/logging"
   "backbone"
   "common/has_properties"
-], (base, socket, load_models, Logging, Backbone, HasProperties) ->
+], ($, base, socket, load_models, Logging, Backbone, HasProperties) ->

   logger = Logging.logger

@@ -19,7 +20,7 @@
   Deferreds._doc_requested = $.Deferred()
   Promises.doc_loaded = Deferreds._doc_loaded.promise()
   Promises.doc_requested = Deferreds._doc_requested.promise()
-  Promises.doc_promises = {};
+  Promises.doc_promises = {}

   # these get set out later
   exports.wswrapper = null
@@ -71,7 +72,7 @@
       return promise

     load_doc: (docid) ->
-      resp = utility.make_websocket();
+      resp = utility.make_websocket()
       resp = resp.then(() ->
         Config = require("common/base").Config
         return $.get(Config.prefix + "bokeh/bokehinfo/#{docid}/", {})


Classroom: Enabled chat for classroom workspace.

--- client/app/Applications/Classroom.kdapplication/Views/classroomworkspace.coffee
+++ client/app/Applications/Classroom.kdapplication/Views/classroomworkspace.coffee
@@ -25,6 +25,7 @@
     config.shareSessionKeyInfo = "
This is your session key, you can share this key with your friends to work together.
"
     config.firebaseInstance    = "teamwork-local"
     config.panels              = [options]
+    config.enableChat          = yes

     return config


Allow group admins to skip user VM allocations.

--- client/landing/app/Applications/Groups.kdapplication/Views/groupcreation.coffee
+++ client/landing/app/Applications/Groups.kdapplication/Views/groupcreation.coffee
@@ -181,6 +181,7 @@
             cssClass      : "allocation"
             change        : @bound "allocationChanged"
             selectOptions : [
+              { title : "None",  value : "0" }
               { title : "$ 10",  value : "10" }
               { title : "$ 20",  value : "20" }
               { title : "$ 30",  value : "30" }
@@ -197,6 +198,7 @@
                 VMs

               Each member of your group can have $10 worth of Koding resources e.g. 2 VMs.
+              You will be charged for each member.

"
           approval       :
             title        : "Admin approval is required on member purchases"
@@ -243,6 +245,15 @@
     desc.$('section span.vm').text price / 5
     desc.$('section span.price').text price

+    if price > 0
+      @allocation.fields["Admin approval is required on member purchases"].show()
+      @allocation.fields["Allow over-usage"].show()
+      desc.show()
+    else
+      @allocation.fields["Admin approval is required on member purchases"].hide()
+      @allocation.fields["Allow over-usage"].hide()
+      desc.hide()
+
   back:->

     {back, next, submit} = @buttons


Teamwork: Handled callback non existence case.

--- client/landing/app/Applications/Teamwork.kdapplication/Views/teamworkapp.coffee
+++ client/landing/app/Applications/Teamwork.kdapplication/Views/teamworkapp.coffee
@@ -137,7 +137,7 @@
       content                 : @teamwork.markdownContent
       targetEl                : @teamwork.getActivePanel().headerHint

-  handleZipImportDone_: (vmController, root, folderName, path, modal, notification, url, callback) ->
+  handleZipImportDone_: (vmController, root, folderName, path, modal, notification, url, callback = noop) ->
     vmController.run "rm -rf #{root}/#{folderName} ; mv #{path}/#{folderName} #{root}", (err, res) =>
       return warn err if err
       modal.destroy()


Support dashes in the github username

Support dashes in the github username

--- src/scripts/github-credentials.coffee
+++ src/scripts/github-credentials.coffee
@@ -17,7 +17,7 @@

     msg.send theReply

-  robot.respond /i am (\w+)/i, (msg) ->
+  robot.respond /i am ([a-z-]+)/i, (msg) ->
     githubLogin = msg.match[1]
     msg.message.user.githubLogin = githubLogin
     msg.send "Ok, you are " + githubLogin + " on GitHub"


don't overload pinkyurl

don't overload pinkyurl

--- models/team.coffee
+++ models/team.coffee
@@ -190,12 +190,13 @@

 TeamSchema.method 'screenshot', ->
   return unless url = @entry.url
-  qs = querystring.stringify url: url, expire: 1, resize: '160x93', 'out-format': 'png'
+  qs = querystring.stringify url: url, resize: '160x93', 'out-format': 'png'
   "http://pinkyurl.com/i?#{qs}"

 TeamSchema.method 'updateScreenshot', (callback) ->
+  return
   return unless @entry.url
-  r = request.get @screenshot(), (error, response, body) ->
+  r = request.get @screenshot() + '&expire=1', (error, response, body) ->
     throw error if error
     # no callback


forcing spaces for implicit calls ... making '@ name' a call instead of an access. Ticket #353

--- rewriter.coffee
+++ rewriter.coffee
@@ -122,7 +122,7 @@
       tag: token[0]
       stack[stack.length - 2]: + stack.pop() if tag is 'OUTDENT'
       open: stack[stack.length - 1] > 0
-      if prev and include(IMPLICIT_FUNC, prev[0]) and include(IMPLICIT_CALL, tag)
+      if prev and prev.spaced and include(IMPLICIT_FUNC, prev[0]) and include(IMPLICIT_CALL, tag)
         @tokens.splice i, 0, ['CALL_START', '(', token[2]]
         stack[stack.length - 1]: + 1
         stack.push 0 if include(EXPRESSION_START, tag)
@@ -274,7 +274,7 @@
 EXPRESSION_CLOSE: ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat EXPRESSION_END

 # Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation.
-IMPLICIT_FUNC:  ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '<-']
+IMPLICIT_FUNC:  ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '<-', '@']

 # If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
 IMPLICIT_CALL:  ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START',


Update process.argv creation from settings to take into account program.json in a meteor bundle

--- CLI.coffee
+++ CLI.coffee
@@ -17,16 +17,18 @@

     if commandLine
       process.argv = Meteor.settings.commandLine.split(" ")
-      # In node, the first arg is node and the second the name of the .js file to execute, which in the case of
-      # meteor is main.js
+      # In a meteor bundle, the first arg is node, the 2nd main.js, and the 3rd program.json
+      process.argv.unshift("program.json")
       process.argv.unshift("main.js")
       process.argv.unshift("node")

+    console.log process.argv.join(' ')
+
       # THe first arg after is always the name of the command to execute.

-    expect(process.argv, "No command specified").to.to.have.length.above(2)
+    expect(process.argv, "No command specified").to.to.have.length.above(3)

-    commandName = process.argv[2]
+    commandName = process.argv[3]

     command = @registeredCommands[commandName]
     expect(command, "#{commandName} is not a registered cli command").to.to.be.an 'object'


show the delete box on load if the hash is #delete

--- public/javascripts/teams.coffee
+++ public/javascripts/teams.coffee
@@ -85,6 +85,17 @@
         $('input, textarea', $form).prop 'disabled', (i, d) -> !d

   $('#page.teams-edit').each ->
+
+    # show the delete box on load if the hash is delete
+    if window.location.hash is '#delete'
+      window.location.hash = ''
+      $form = $('#inner form:first')
+      pos = $form.position()
+      $delete = $('form.delete').show()
+      $delete.css
+        left: pos.left + ($form.width() - $delete.outerWidth()) / 2
+        top: pos.top
+
     $('a.pull', this).click ->
       li = $(this).closest('li')
       i = li.prevAll('li').length + 1


bump default jquery test version

bump default jquery test version

--- karma.conf.coffee
+++ karma.conf.coffee
@@ -1,6 +1,6 @@
 # Karma configuration
 # Generated on Wed Mar 09 2016 17:12:47 GMT-0800 (PST)
-DEFAULT_JQUERY_VERSION = '3.0.0'
+DEFAULT_JQUERY_VERSION = '3.2.1'
 JQUERY_VERSION = process.env.JQUERY_VERSION or DEFAULT_JQUERY_VERSION
 JUNIT_DIR = process.env.CIRCLE_TEST_REPORTS or '.junit'


rewrite status updates to return functions. trap health_status events

--- imports/server/mqtt/docker/events.coffee
+++ imports/server/mqtt/docker/events.coffee
@@ -2,21 +2,25 @@
 reconciler  = require '../../stateReconciler.coffee'
 ignore = false

+updateServiceState = (state) -> (labels) -> reconciler.updateServiceState state, labels
+updateHealthStatus = (status) -> (labels) -> reconciler.updateHealthStatus status, labels
+
 handleContainerEvent = (msg) ->
-  mappedState = switch msg.status
-    when 'create' then 'starting'
-    when 'start'  then 'running'
-    when 'kill'   then 'stopping'
-    when 'die'    then 'stopping'
-    when 'stop'   then 'stopped'
-    when 'dead'   then 'stopped'
-    when 'destroy' then 'removed'
-    when 'top'    then ignore
+  updateFunction = switch msg.status
+    when 'create'       then updateServiceState 'starting'
+    when 'start'        then updateServiceState 'running'
+    when 'kill'         then updateServiceState 'stopping'
+    when 'die'          then updateServiceState 'stopping'
+    when 'stop'         then updateServiceState 'stopped'
+    when 'dead'         then updateServiceState 'stopped'
+    when 'destroy'      then updateServiceState 'removed'
+    when 'health_status: healthy'   then updateHealthStatus 'healthy'
+    when 'health_status: unhealthy' then updateHealthStatus 'unhealthy'
+    when 'top'          then ignore
     else console.log 'events:unknown container status', msg.status

-  if mappedState and (labels = msg.Actor?.Attributes)
-    console.log 'eventmsg', msg
-    reconciler.updateServiceState mappedState, labels
+  if updateFunction and (labels = msg.Actor?.Attributes)
+    updateFunction labels

     if id = msg.id
       reconciler.updateContainerId id, labels


disable tags query

disable tags query

--- workers/social/lib/social/models/activeitems.coffee
+++ workers/social/lib/social/models/activeitems.coffee
@@ -36,39 +36,27 @@
   #   * Active topics in the last day
   #   * Random topics
   @fetchTopics = secure (client, options, callback)->
-    JTag.canReadTags client, (err, hasPermission)=>
-      if err or not hasPermission
-        return callback new Error "Not allowed to read tags of this group"
-      Cache.fetch cacheId, (@fetchItems.bind this), options, callback
-
-    [callback, options] = [options, callback]  unless callback
-    options.name       = "topic"
-    options.group      = client.context.group
-    options.fallbackFn = @fetchRandomTopics
-    cacheId            = "#{options.group}-activeItems.fetchTopics"
-
-    JTag.canReadTags client, (err, hasPermission)=>
-      if err or not hasPermission
-        return callback new Error "Not allowed to read tags of this group"
-      @fetchRandomTopics callback, options
-      # Cache.fetch cacheId, (@fetchItems.bind this), options, callback
+    options.name  = "topic"
+    options.group = client.context.group
+    @fetchRandomTopics callback, options

   # Returns users in following order:
   #   * Client's followers who are online
   #   * Active users in the last day
   #   * Random users
   @fetchUsers = secure (client, options, callback)->
-    # [callback, options] = [options, callback]  unless callback
-    # options.client      = client
-    # options.group       = client.context.group
+    [callback, options] = [options, callback]  unless callback
+    options.client      = client
+    options.group       = client.context.group
+
     # options.fallbackFn  = @fetchRandomUsers

-    JGroup.canListMembers client, (err, hasPermission)=>
-      if err or not hasPermission
-        return callback new Error "Not allowed to list members of this group"
+    # JGroup.canListMembers client, (err, hasPermission)=>
+    #   if err or not hasPermission
+    #     return callback new Error "Not allowed to list members of this group"
         # Cache.fetch "activeItems.fetchUsers", (@_fetchUsers.bind this), options, callback

-      @fetchRandomUsers callback
+    @fetchRandomUsers callback

   @fetchRandomUsers = (callback)->
     JAccount.some {"type":"registered"}, {limit:10}, callback
@@ -95,6 +83,8 @@
         members = onlineMembers.concat activeMembers
         callback null, members

+  # DO NOT USE...THIS WILL BRING DOWN KODING: SA
+  #
   # General method that returns popular items in the last day. If none
   # exists, it returns random items.
   #


logger: use ... for extra params

logger: use ... for extra params

--- workers/social/lib/social/models/frontlogger.coffee
+++ workers/social/lib/social/models/frontlogger.coffee
@@ -51,8 +51,8 @@
   logMethods = ['trace', 'debug', 'info', 'warn', 'error', 'fatal']
   for method in logMethods
     do (method)=>
-      @[method] = (message, params)->
+      @[method] = (message, params...)->
         if params
-          logger[method] message, params
+          logger[method] message, params...
         else
           logger[method] message


PremiumBroker: change isPremium logic

PremiumBroker: change isPremium logic

--- workers/social/lib/social/render/scriptblock.coffee
+++ workers/social/lib/social/render/scriptblock.coffee
@@ -22,7 +22,7 @@
     encodedCustomPartial = JSON.stringify customPartial, replacer
     encodedCampaignData = JSON.stringify campaignData, replacer

-    isPremiumBroker = options.client.context.group is "koding"
+    isPremiumBroker = options.client.context.group isnt "koding"
     landingOptions =
       page         : landing


fix(css watch): fix watch for lazy loaded css files, don't try to inject css changes, just do a page refresh

--- src/tasks/browser/browser-sync.coffee
+++ src/tasks/browser/browser-sync.coffee
@@ -55,7 +55,8 @@
 			files:   config.glob.browserSync.files
 			proxy:   "http://localhost:#{config.ports.server}/"
 			browser: 'google chrome'
-			reloadDebounce: 150 # windows fix for bundle reload
+			injectChanges: false # don't try to inject css changes, just do a page refresh
+			reloadDebounce: 150  # windows fix for bundle reload (milliseconds)
 			watchOptions:
 				ignored: config.glob.browserSync.ignore
 		@


Permissions: remove unused code

Permissions: remove unused code

--- client/Dashboard/views/permissionview.coffee
+++ client/Dashboard/views/permissionview.coffee
@@ -12,51 +12,6 @@
   addPermissionsView: ->
     group = @getData()

-    @loader           = new KDLoaderView
-      cssClass        : 'loader'
-    @loaderText       = new KDView
-      partial         : 'Loading Permissions...'
-      cssClass        : ' loader-text'
-
-    addPermissionsView = (newPermissions)=>
-      group.fetchRoles (err,roles)=>
-        group.fetchPermissions (err, permissionSet)=>
-          @loader.hide()
-          @loaderText.hide()
-          unless err
-            if newPermissions
-              permissionSet.permissions = newPermissions
-
-            @permissions.destroy() if @permissions
-
-            @addSubView @permissions = new PermissionsForm {
-              privacy: group.privacy
-              permissionSet
-              roles
-              delegate : this
-            }, group
-
-            @permissions.emit 'RoleViewRefreshed'
-            @permissions.on 'RoleWasAdded', (newPermissions,role,copy)=>
-              copiedPermissions = []
-              for own permission of newPermissions
-                if newPermissions[permission].role is copy
-                  copiedPermissions.push
-                    module      : newPermissions[permission].module
-                    permissions : newPermissions[permission].permissions
-                    role        : role
-              for item in copiedPermissions
-                newPermissions.push item
-              addPermissionsView(newPermissions)
-              @permissions.emit 'RoleViewRefreshed'
-
-          else
-            @addSubView new KDView
-              partial : 'No access'
-
-    @loader.show()
-    @loaderText.show()
-    addPermissionsView()

   viewAppended:->
     super


AppManager: Forgot to remove avoidRecursion flag.

--- client/app/MainApp/ApplicationManager.coffee
+++ client/app/MainApp/ApplicationManager.coffee
@@ -88,10 +88,10 @@
       # we assume it should be a 3rd party app
       # that's why it should be run via kodingappscontroller

-      if not appOptions? and not options.avoidRecursion?
+      if not appOptions?
         return @fetchManifests name, =>
           @open name, options, callback
-
+
       appParams = options.params or {}

       if appOptions?.multiple


use viewTask name for transitioning

use viewTask name for transitioning

--- tutor/src/components/student-dashboard/event-row.cjsx
+++ tutor/src/components/student-dashboard/event-row.cjsx
@@ -1,6 +1,8 @@
 React  = require 'react'
 BS     = require 'react-bootstrap'
+
 Time   = require '../time'
+Router = require '../../helpers/router'
 {StudentDashboardStore, StudentDashboardActions} = require '../../flux/student-dashboard'
 EventInfoIcon = require './event-info-icon'
 {Instructions} = require '../task/details'
@@ -24,8 +26,7 @@
   onClick: (ev) ->
     {courseId, event} = @props
     ev.preventDefault()
-    # url is 1 based so it matches the breadcrumb button numbers. 1==first step
-    @context.router.transitionTo "/courses/#{courseId}/tasks/#{event.id}/steps/1"
+    @context.router.transitionTo Router.makePathname('viewTask', {courseId, id: event.id})

   hideTask: (event) ->
     StudentDashboardActions.hide(@props.event.id)


Add ' body' to make .native-binding selector more specific

--- keymaps/base.cson
+++ keymaps/base.cson
@@ -34,7 +34,7 @@
   'escape': 'editor:consolidate-selections'

 # allow standard input fields to work correctly
-'input:not(.hidden-input), .native-key-bindings':
+'body .native-key-bindings':
   'tab': 'core:focus-next'
   'shift-tab': 'core:focus-previous'
   'enter': 'native!'


Fix to redirect to correct dashboards url when switching projects

--- app/app_view.coffee
+++ app/app_view.coffee
@@ -55,10 +55,7 @@

   projectChange: =>
     User.current.getDashboards()
-    if @appFocusView is @dashboardView
-      Manager.get('router').navigate("#/dashboards/#{Manager.get('project')}", {trigger: true})
-    else
-      @appFocusView.render()
+    Manager.get('router').navigate("#/dashboards/#{Manager.get('project')}", {trigger: true})

   loadUbretTools: =>
     ToolLoader @dashboardModel, @createDashboardView


Fixed autocompletion for javascript and coffeescript

--- lib/autocomplete-provider.coffee
+++ lib/autocomplete-provider.coffee
@@ -2,8 +2,11 @@

 KernelManager = require './kernel-manager'

-module.exports = AutocompleteProvider = ( ->
-    selectors = _.map KernelManager.getAvailableKernels(), ({language}) -> '.source.' + language
+module.exports = AutocompleteProvider = do ->
+    selectors = _.map KernelManager.getAvailableKernels(), ({language}) ->
+        '.source.' + language
+            .replace 'coffeescript', 'coffee'
+            .replace 'javascript', 'js'
     selector = selectors.join(', ')
     return {
         selector: selector
@@ -20,9 +23,6 @@

             # adapted from http://stackoverflow.com/questions/5474008/regular-expression-to-confirm-whether-a-string-is-a-valid-identifier-in-python
             python: /([^\d\W]|[\u00A0-\uFFFF])[\w.\u00A0-\uFFFF]*$/
-
-            # taken from https://github.com/n-riesco/nel/blob/master/lib/nel.js#L713
-            javascript: /[_$a-zA-Z][_$a-zA-Z0-9]*$/

             # adapted from http://php.net/manual/en/language.variables.basics.php
             php: /[$a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/
@@ -79,4 +79,3 @@
         # from things, kill any processes, etc.
         dispose: ->
     }
-)()


Fix deprecated ac+ blacklist option

Fix deprecated ac+ blacklist option

--- lib/autocomplete-provider.coffee
+++ lib/autocomplete-provider.coffee
@@ -4,7 +4,7 @@
 module.exports =
 class AutocompleteProvider
   selector: '.source.haskell'
-  blacklist: '.source.haskell .comment'
+  disableForSelector: '.source.haskell .comment'
   inclusionPriority: 1
   excludeLowerPriority: false
   info:


Commented invoke() usage.

Commented invoke() usage.

--- chapter3/interpreter.coffee
+++ chapter3/interpreter.coffee
@@ -175,7 +175,13 @@
         when "begin" then eprogn (cdr exp), env
         when "set!" then update (nvalu cadr exp), env, (evaluate (caddr exp), env)
         when "lambda" then make_function (astSymbolsToLispSymbols cadr exp), (cddr exp), env
-        else invoke (evaluate (car exp), env), (evlis (cdr exp), env)
+
+        else
+            # Note that invoke ultimately resolves to a (native)
+            # function generated by make_function, and a (interpreter)
+            # list that the generated (native) function knows how to
+            # unpack into the actual (native) operation.
+            invoke (evaluate (car exp), env), (evlis (cdr exp), env)
     else
       invoke (evaluate (car exp), env), (evlis (cdr exp), env)
   else


scrollTop is a DOM attribute, no need to make a jQuery call to set it.

--- Web/js/classes/chat.coffee
+++ Web/js/classes/chat.coffee
@@ -126,10 +126,9 @@
 		@addHtml templates.message.render( line ), prepend

 	addHtml: (html, prepend) ->
-		$chat = @chat
-		chat = $chat[0]
+		chat = @chat[0]

-		atBottom = $chat.outerHeight() >= ( chat.scrollHeight - $chat.scrollTop() - 32 )
+		atBottom = @chat.outerHeight() >= ( chat.scrollHeight - chat.scrollTop - 32 )

 		if prepend
 			@chat.prepend html
@@ -137,4 +136,8 @@
 			@chat.append html

 		if ! prepend && atBottom
-			$chat.scrollTop chat.scrollHeight
+			@scrollToBottom()
+
+	scrollToBottom: ->
+		chat = @chat[0]
+		chat.scrollTop = chat.scrollHeight


Fix test setup

Fix test setup

--- tests/src/FunctionalTests.coffee
+++ tests/src/FunctionalTests.coffee
@@ -46,9 +46,13 @@
     log.debug "spacejam.afterEach"
     try
       spacejamChild?.kill('SIGPIPE')
+    finally
+      spacejamChild = null
+
+    try
       spacejamChild2?.kill('SIGPIPE')
     finally
-      spacejamChild = null
+      spacejamChild2 = null

   describe "test-packages", ->


Update webgrabplus-siteini.cson

Update webgrabplus-siteini.cson

scope.range change

--- grammars/webgrabplus-siteini.cson
+++ grammars/webgrabplus-siteini.cson
@@ -190,7 +190,7 @@
   }
   {
     # specials scope.range
-    'match': '(scope\\.range)\\s*\{\\s*\\((urlindex|datelogo|splitindex|indexshowdetails|showdetails|showsubdetails|channellist)\\s*\\)\\s*\\|\\s*(end)\\s*\}'
+    'match': '(scope\\.range)\\s*\{\\s*\\((urlindex|datelogo|splitindex|indexshowdetails|showdetails|showsubdetails|channellist)\\s*\\)\\s*\\|\\s*(end|\\d+)\\s*\}'
     'captures':
       '1':
         'name': 'entity.name.tag.siteini'


Use Array::filter

Use Array::filter

--- lib/grammar-selector-view.coffee
+++ lib/grammar-selector-view.coffee
@@ -29,8 +29,9 @@
       @li grammar.name, class: grammarClass

   populate: ->
-    grammars = new Array(atom.syntax.grammars...)
-    grammars = _.reject grammars, (grammar) -> grammar is atom.syntax.nullGrammar
+    grammars = atom.syntax.grammars.filter (grammar) ->
+      grammar isnt atom.syntax.nullGrammar
+
     grammars.sort (grammarA, grammarB) ->
       if grammarA.scopeName is 'text.plain'
         -1


correct urlRoot

correct urlRoot

--- core/app/backbone/models/conversation.coffee
+++ core/app/backbone/models/conversation.coffee
@@ -1,2 +1,2 @@
 class window.Conversation extends Backbone.Model
-  urlRoot: '/m/'+  urlRoot: '/m'


Put parantheses around template

Put parantheses around template

As per @markijbema's comments

--- js-library/app/js/views/templates.coffee
+++ js-library/app/js/views/templates.coffee
@@ -14,7 +14,7 @@
 Factlink.templates.preload = ->
   Factlink.templates.getTemplate 'indicator'
   Factlink.templates.getTemplate 'create', (template) ->
-    Factlink.prepare = new Factlink.Prepare template
+    Factlink.prepare = new Factlink.Prepare(template)

 fetchTemplate = (str, callback) ->
   requesting[str] = true


client: init clean up

client: init clean up

--- client/app/lib/index.coffee
+++ client/app/lib/index.coffee
@@ -4,6 +4,7 @@
 kd                     = require 'kd'
 socketConnected        = require './util/socketConnected'
 enableLogs             = require './util/enableLogs'
+cleanup                = require './util/cleanup'
 ConnectionChecker      = require './connectionchecker'
 lazyrouter             = require './lazyrouter'
 setupAnalytics         = require './setupanalytics'
@@ -128,7 +129,7 @@

   logsEnabled = (kookies.get 'enableLogs') or not globals.config?.suppressLogs
   enableLogs logsEnabled
-
+  cleanup()
   next()

 run()


globals: kd removed from the global scope, _globals/_kd/_remote added

--- client/app/lib/index.coffee
+++ client/app/lib/index.coffee
@@ -3,7 +3,7 @@
 kookies = require 'kookies'
 getscript = require 'getscript'
 Promise = require 'bluebird'
-global.kd = kd = require 'kd'
+kd = require 'kd'
 KDModalView = kd.ModalView
 KDNotificationView = kd.NotificationView
 getFullnameFromAccount = require './util/getFullnameFromAccount'
@@ -31,6 +31,11 @@
   # that depend on `remote`, and here we are. -og
   remote = require('./remote').getInstance()
   # it is very important that you invoke this method before anything else does, so f important.
+
+  if globals.config.environment is 'dev'
+    global._kd      = kd
+    global._remote  = remote
+    global._globals = globals

   remote.once 'ready', ->
     globals.currentGroup = remote.revive globals.currentGroup


Added href to contest items

Added href to contest items

--- client/components/Contest.coffee
+++ client/components/Contest.coffee
@@ -4,8 +4,9 @@
 import { withRouter } from 'react-router'

 goToProblem = (m, history) ->
-    () ->
+    (e) ->
         history.push("/material/" + m)
+        e.preventDefault()

 Contest = (props) ->
     <div>
@@ -15,7 +16,7 @@
             res = []
             a = (el) -> res.push(el)
             for m in props.material.materials
-                a <ListGroupItem key={m._id} onClick={goToProblem(m._id, props.history)}>{m.title}</ListGroupItem>
+                a <ListGroupItem key={m._id} onClick={goToProblem(m._id, props.history)} href={"/material/" + m._id}>{m.title}</ListGroupItem>
             res}
         </ListGroup>
     </div>