3d: make point plotting work, at least for webgl (doesn't work for canvas yet)

--- salvus/page/3d.coffee
+++ salvus/page/3d.coffee
@@ -99,7 +99,7 @@

 _scene_using_renderer  = undefined
 _renderer = undefined
-renderer_type = undefined
+dynamic_renderer_type = undefined

 get_renderer = (scene) ->
     # if there is a scene currently using this renderer, tell it to switch to
@@ -112,13 +112,13 @@
     if not _renderer?
         # get the best-possible THREE.js renderer (once and for all)
         if Detector.webgl
-            render_type = 'webgl'
+            dynamic_renderer_type = 'webgl'
             _renderer = new THREE.WebGLRenderer
                 antialias             : true
                 alpha                 : true
                 preserveDrawingBuffer : true
         else
-            render_type = 'canvas'
+            dynamic_renderer_type = 'canvas'
             _renderer = new THREE.CanvasRenderer
                 antialias : true
                 alpha     : true
@@ -410,20 +410,18 @@
             size : 1
             color: "#000000"
             sizeAttenuation : false
-        #console.log("rendering a point", o)
         @show_canvas()

-        material = new THREE.ParticleBasicMaterial
+        material = new THREE.PointCloudMaterial
             color           : o.color
             size            : o.size
             sizeAttenuation : o.sizeAttenuation
-
-        switch renderer_type
+        switch dynamic_renderer_type
             when 'webgl'
                 geometry = new THREE.Geometry()
                 geometry.vertices.push(@vector(o.loc))
-                particle = new THREE.ParticleSystem(geometry, material)
-            when 'canvas2d'
+                particle = new THREE.PointCloud(geometry, material)
+            when 'canvas'
                 particle = new THREE.Particle(material)
                 particle.position.set(@aspect_ratio_scale(o.loc))
                 if @_frame_params?
@@ -432,6 +430,8 @@
                 else
                     w = 5 # little to go on
                 particle.scale.x = particle.scale.y = Math.max(50/@opts.width, o.size * 5 * w / @opts.width)
+            else
+                throw "bug -- uknown dynamic_renderer_type = #{dynamic_renderer_type}"

         @scene.add(particle)

@@ -722,7 +722,7 @@
     render_scene: (force=false) =>
         # console.log('render', @opts.element.length)

-        if @render_type == 'static'
+        if @renderer_type == 'static'
             console.log 'render static -- todo'
             return


initial config file loading working

initial config file loading working

--- src/commands/cacheit.coffee
+++ src/commands/cacheit.coffee
@@ -56,4 +56,5 @@
 ###

 module.exports = cacheit = (options, callback = (->)) ->
-  console.log options
+  config = helpers.loadConfig options.configPath
+  console.log config, options


Update bundle tests

Update bundle tests

--- test/bundle.coffee
+++ test/bundle.coffee
@@ -7,7 +7,24 @@
 describe 'bundle', ->
   # Declare bundlers in outer scope so tests have access to them.
   bundler = null
-  bundleContent = null
+  content = null
+  reqFiles = [
+    'require.define(["/a","70f886d883"]'
+    'require.define(["/b","8908bb92f8"]'
+    'require.define(["/c","318af1af20"]'
+    'require.define(["/entry","21568343a3"]'
+  ]
+  reqDirectories = [
+    'require.define(["/test/assets/foo","58c67562d2"]'
+  ]
+  reqModules = [
+    'require.define(["/node_modules/mod","e63313c6a9"]'
+  ]
+  reqTemplates = [
+    'require.define(["/test/assets/template","04e021b689"]'
+  ]
+  prelude = 'return this.require.define = function(aliases, fn) {'
+  jadeRuntime = 'jade=function(exports){Array.isArray||(Array.isArray=function(arr)'

   before (done) ->
     # Create bundlers
@@ -20,27 +37,42 @@
       fs.mkdirSync mod
       fs.writeFileSync join(mod, 'index.js'), "module.exports = {x: 42};"

-    bundler.bundle (err, content) ->
+    # Save output of bundle() for tests, call twice to ensure there are no issues with caching
+    bundler.bundle (err, _content) ->
       throw err if err
-      bundleContent = content
+      content = _content
       done()

   describe 'bundle#bundle()', ->
-    it 'should find and define all absolute/relatively required modules properly', ->
-      required = '''
-        require.define(["/a","70f886d883"]
-        require.define(["/b","8908bb92f8"]
-        require.define(["/c","318af1af20"]
-        require.define(["/test/assets/foo","58c67562d2"]
-        require.define(["/test/assets/template","04e021b689"]
-        require.define(["/entry","21568343a3"]
-        '''.split('\n')
+    it 'should include the appropriate prelude', ->
+      content.should.have.string prelude

-      for define in required
-        bundleContent.should.have.string define
+    it 'should find and define all absolute/relatively required files properly', ->
+      for str in reqFiles
+        content.should.have.string str
+
+    it 'should find and define all absolute/relatively required directories properly', ->
+      for str in reqDirectories
+        content.should.have.string str

     it 'should find and define all modules required from node_modules', ->
-      bundleContent.should.have.string 'require.define(["/node_modules/mod","e63313c6a9"]'
+      for str in reqModules
+        content.should.have.string str
+
+    it 'should find and define all jade templates', ->
+      for str in reqTemplates
+        content.should.have.string str

     it 'should include the jade runtime', ->
-      bundleContent.should.have.string 'jade=function(exports){Array.isArray||(Array.isArray=function(arr){'
+      content.should.have.string jadeRuntime
+
+  describe 'bundle#bundle() pt. ii: return of the bundle', ->
+    it 'should still pass previous tests after being bundled up again', (done) ->
+      bundler.bundle (err, content) ->
+        throw err if err
+
+        content.should.have.string prelude
+        content.should.have.string jadeRuntime
+        for str in reqFiles.concat reqDirectories, reqModules, reqTemplates
+          content.should.have.string str
+        done()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/color2.coffee
+++ test/color2.coffee
@@ -269,7 +269,7 @@
   color1 = Color2(50, 50, 50)
   color2 = Color2(10, 10, 10)

-  color3 = Color.mix(color1, color2)
+  color3 = Color2.mix(color1, color2)

   equals color3.r, 30
   equals color3.g, 30


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/color2.coffee
+++ test/color2.coffee
@@ -159,7 +159,7 @@
   color1 = Color2(255, 255, 255, 1)
   color2 = Color2([255, 255, 255])

-  log color1
+  log color1.equal(color2)

 module()


Record having called `initialize` instead of nuking it

Safari doesn't seem to like the nuclear option

--- src/trix/core/helpers/custom_elements.coffee
+++ src/trix/core/helpers/custom_elements.coffee
@@ -24,7 +24,7 @@
 rewriteFunctionsAsValues = (definition) ->
   object = {}
   for key, value of definition
-    object[key] = if typeof value is "function" then {value, writable: true} else value
+    object[key] = if typeof value is "function" then {value} else value
   object

 rewriteLifecycleCallbacks = do ->
@@ -40,14 +40,14 @@
       {initialize, connect, disconnect} = extract(definition)

       # Call `initialize` once in `connectedCallback` if defined
-      if initialize or connect
+      if initialize
         original = connect
         connect = ->
-          @initialize?()
-          @initialize = null
+          unless @initialized
+            @initialized = true
+            initialize.call(this)
           original?.call(this)

-      definition.initialize = initialize if initialize
       definition.connectedCallback = connect if connect
       definition.disconnectedCallback = disconnect if disconnect
       definition


Forward <trix-editor> name property to inputElement

--- src/trix/elements/trix_editor_element.coffee
+++ src/trix/elements/trix_editor_element.coffee
@@ -75,6 +75,10 @@
         element = makeElement("input", type: "hidden", id: inputId)
         @parentElement.insertBefore(element, @nextElementSibling)
         element
+
+  name:
+    get: ->
+      @inputElement.name

   value:
     get: ->


when newtag is a builder and empty, add spaceholder tag

--- src/dt-jquery.coffee
+++ src/dt-jquery.coffee
@@ -106,13 +106,27 @@
             $fyBuilder(parent) if parent is parent.builder

         replace: (oldtag, newtag) =>
-            return if removed newag
-            _jquery = newtag._jquery ? newtag
-            oldtag._jquery.replaceWith(_jquery)
+            return if removed newtag
+            parent = newtag.parent
+            $new = newtag._jquery ? newtag
+            $old = oldtag._jquery ? oldtag
+
+            if $new.length is 0
+                newtag._jquery = $new = @$('<spaceholder>', parent._jquery)
+                newtag._jquery_wrapped = yes
+                if newtag is newtag.builder
+                    $fyBuilder(newtag) # includes defineJQueryAPI
+                else
+                    defineJQueryAPI(newtag)
+
+            if parent is parent.builder
+                $par.splice($par.index($old), $old.length, $new...)
+                $fyBuilder(parent)
+            if $old.parent().length > 0
+                $old.replaceWith($new)
             # replaceWith isnt inplace
-            newtag._jquery = _jquery
-            if newtag is newtag.builder
-                newtag.jquery = _jquery
+            newtag._jquery = $new
+            $fyBuilder(newtag) if newtag is newtag.builder

         text: (el, text) =>
             el._jquery.text(text)


Add ArrayBuffer.transfer (experimental)

Add ArrayBuffer.transfer (experimental)

--- src/es7compat.coffee
+++ src/es7compat.coffee
@@ -25,3 +25,18 @@
 Float32Array::includes      ||= Array::includes
 Float64Array::includes      ||= Array::includes

+# https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer/transfer
+# FIXME: Currently this method does *not* detach oldBuffer
+unless ArrayBuffer.transfer
+  ArrayBuffer.transfer = (oldBuffer, newByteLength) ->
+    unless oldBuffer instanceof ArrayBuffer
+      throw new TypeError("oldBuffer must be an ArrayBuffer")
+    oldByteLength = oldBuffer.byteLength
+    newByteLength = oldbyteLength unless newByteLength?
+    unless typeof(newByteLength) == "number"
+      throw new TypeError("newByteLength must be a number")
+    newBuffer = new ArrayBuffer(newByteLength)
+    copyByteLength = Math.min(oldByteLength, newByteLength)
+    new Uint8Array(newBuffer).set(new Uint8Array(oldBuffer, 0, copyByteLength))
+    return newBuffer
+


Added tests for smartcase

Added tests for smartcase

--- spec/motions-spec.coffee
+++ spec/motions-spec.coffee
@@ -977,6 +977,22 @@
           keydown('n')
           expect(editor.getCursorBufferPosition()).toEqual [2, 0]

+        it "uses Smartcase insensitive search if useSmartcaseForSearch is true and searching lowercase", ->
+          atom.config.set 'vim-mode.useSmartcaseForSearch', true
+          editor.commandModeInputView.editor.setText 'abc'
+          editor.commandModeInputView.editor.trigger 'core:confirm'
+          expect(editor.getCursorBufferPosition()).toEqual [1, 0]
+          keydown('n')
+          expect(editor.getCursorBufferPosition()).toEqual [2, 0]
+
+        it "uses Smartcase sensitive search if useSmartcaseForSearch is true and searching uppercase", ->
+          atom.config.set 'vim-mode.useSmartcaseForSearch', true
+          editor.commandModeInputView.editor.setText 'ABC'
+          editor.commandModeInputView.editor.trigger 'core:confirm'
+          expect(editor.getCursorBufferPosition()).toEqual [2, 0]
+          keydown('n')
+          expect(editor.getCursorBufferPosition()).toEqual [2, 0]
+
       describe "repeating", ->
         it "does nothing with no search history", ->
           # This tests that no exception is raised


rename normalEditor->inputEditor: more descriptive

--- spec/motions-spec.coffee
+++ spec/motions-spec.coffee
@@ -22,9 +22,9 @@
     editor.normalModeInputView.editorElement.getModel().setText(key)

   submitNormalModeInputText = (text) ->
-    normalEditor = editor.normalModeInputView.editorElement
-    normalEditor.getModel().setText(text)
-    atom.commands.dispatch(normalEditor, "core:confirm")
+    inputEditor = editor.normalModeInputView.editorElement
+    inputEditor.getModel().setText(text)
+    atom.commands.dispatch(inputEditor, "core:confirm")

   describe "simple motions", ->
     beforeEach ->
@@ -1189,7 +1189,7 @@
             expect(editor.getCursorBufferPosition()).toEqual [1, 0]

     describe "using search history", ->
-      normalEditor = null
+      inputEditor = null

       beforeEach ->
         keydown('/')
@@ -1200,27 +1200,27 @@
         submitNormalModeInputText('abc')
         expect(editor.getCursorBufferPosition()).toEqual [2, 0]

-        normalEditor = editor.normalModeInputView.editorElement
+        inputEditor = editor.normalModeInputView.editorElement

       it "allows searching history in the search field", ->
         keydown('/')
-        atom.commands.dispatch(normalEditor, 'core:move-up')
-        expect(normalEditor.getModel().getText()).toEqual('abc')
-        atom.commands.dispatch(normalEditor, 'core:move-up')
-        expect(normalEditor.getModel().getText()).toEqual('def')
-        atom.commands.dispatch(normalEditor, 'core:move-up')
-        expect(normalEditor.getModel().getText()).toEqual('def')
+        atom.commands.dispatch(inputEditor, 'core:move-up')
+        expect(inputEditor.getModel().getText()).toEqual('abc')
+        atom.commands.dispatch(inputEditor, 'core:move-up')
+        expect(inputEditor.getModel().getText()).toEqual('def')
+        atom.commands.dispatch(inputEditor, 'core:move-up')
+        expect(inputEditor.getModel().getText()).toEqual('def')

       it "resets the search field to empty when scrolling back", ->
         keydown('/')
-        atom.commands.dispatch(normalEditor, 'core:move-up')
-        expect(normalEditor.getModel().getText()).toEqual('abc')
-        atom.commands.dispatch(normalEditor, 'core:move-up')
-        expect(normalEditor.getModel().getText()).toEqual('def')
-        atom.commands.dispatch(normalEditor, 'core:move-down')
-        expect(normalEditor.getModel().getText()).toEqual('abc')
-        atom.commands.dispatch(normalEditor, 'core:move-down')
-        expect(normalEditor.getModel().getText()).toEqual ''
+        atom.commands.dispatch(inputEditor, 'core:move-up')
+        expect(inputEditor.getModel().getText()).toEqual('abc')
+        atom.commands.dispatch(inputEditor, 'core:move-up')
+        expect(inputEditor.getModel().getText()).toEqual('def')
+        atom.commands.dispatch(inputEditor, 'core:move-down')
+        expect(inputEditor.getModel().getText()).toEqual('abc')
+        atom.commands.dispatch(inputEditor, 'core:move-down')
+        expect(inputEditor.getModel().getText()).toEqual ''

   describe "the * keybinding", ->
     beforeEach ->


:space_invader: removed xy change in topo flag

--- app/assets/javascripts/inspector_toponym.coffee
+++ app/assets/javascripts/inspector_toponym.coffee
@@ -226,10 +226,7 @@

     flag.on 'add', ()->
       # move point a few pixels down
-      xy = m.latLngToContainerPoint(latlng)
-      xy.y -= window.innerHeight * .2 # to account for keyboard in mobile device
-      latlng_offset = m.containerPointToLatLng(xy)
-      m.panTo(latlng_offset, m.getZoom())
+      m.panTo(latlng, m.getZoom())

     flag.addTo @map


Assign $ to jQuery rather than jQuery.noConflict(). noConflict has side-effect of reassigning window.$, extending its affect outside the scope of this anonymous function. The purpose of this pattern appears only to be to use $ in place of jQuery inside the function scope.

--- app/assets/javascripts/rails_admin/ui.js.coffee
+++ app/assets/javascripts/rails_admin/ui.js.coffee
@@ -1,4 +1,4 @@
-$ = jQuery.noConflict()
+$ = jQuery

 $("#list input.checkbox.toggle").live "click", ->
   checked_status = $(this).is(":checked")


when we're initializing a new choice, it shouldn't be immediately marked as InProgress or else we'll never be allowed to complete the task

--- app/classifier/tasks/flexible-survey/index.cjsx
+++ app/classifier/tasks/flexible-survey/index.cjsx
@@ -80,7 +80,7 @@

   handleChoice: (choiceID) ->
     @setState selectedChoiceID: choiceID
-    newAnnotation = Object.assign {}, @props.annotation, _choiceInProgress: true
+    newAnnotation = Object.assign {}, @props.annotation, _choiceInProgress: false
     @props.onChange newAnnotation

   clearFilters: ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine.coffee
+++ test/engine.coffee
@@ -180,7 +180,7 @@

   engine.collides(Rectangle(0, 0, 10, 10), null)

-test ""
+test "integration", ->

 test "#setState", 3, ->
   engine = Engine()


bump atom config

bump atom config

--- atom.symlink/config.cson
+++ atom.symlink/config.cson
@@ -1,34 +1,35 @@
-'editor':
-  'showIndentGuide': true
-  'fontFamily': 'Menlo'
-  'fontSize': 15
-  'invisibles': {}
-'core':
-  'ignoredNames': [
-    '.bundle'
-    '.git'
-    'log'
-    'repositories'
-    'tmp'
-    'vendor'
-  ]
-  'themes': [
-    'unity-ui'
-    'glacier-syntax'
-  ]
-  'hideGitIgnoredFiles': true
-  'disabledPackages': [
-    'background-tips'
-    'exception-reporting'
-    'metrics'
-  ]
-'spell-check':
-  'grammars': [
-    'text.plain'
-    'source.gfm'
-    'text.git-commit'
-  ]
-'welcome':
-  'showOnStartup': false
-'release-notes':
-  'viewedVersion': '0.89.0'
+'global':
+  'editor':
+    'showIndentGuide': true
+    'fontFamily': 'Menlo'
+    'fontSize': 15
+  'core':
+    'ignoredNames': [
+      '.bundle'
+      '.git'
+      'log'
+      'repositories'
+      'tmp'
+      'vendor'
+    ]
+    'themes': [
+      'unity-ui'
+      'glacier-syntax'
+    ]
+    'hideGitIgnoredFiles': true
+    'disabledPackages': [
+      'background-tips'
+      'exception-reporting'
+      'metrics'
+    ]
+  'spell-check':
+    'grammars': [
+      'text.plain'
+      'source.gfm'
+      'text.git-commit'
+    ]
+  'welcome':
+    'showOnStartup': false
+  'release-notes':
+    'viewedVersion': '0.89.0'
+  'go-plus': {}


save session plugin settings

save session plugin settings

--- atom.symlink/config.cson
+++ atom.symlink/config.cson
@@ -33,3 +33,5 @@
     'showOnStartup': false
   'release-notes':
     'viewedVersion': '0.89.0'
+  'save-session':
+    'dataSaveFolder': '/Users/ingo/.dotfiles/atom.symlink/packages/save-session/projects'


Updates atom packages

Updates atom packages

--- atom.symlink/config.cson
+++ atom.symlink/config.cson
@@ -53,7 +53,6 @@
     ignoredLinterErrors: [
       "jshint"
     ]
-    showErrorPanel: false
   "autocomplete-plus": {}
   "linter-jshint": {}
   "git-plus": {}
@@ -70,10 +69,10 @@
   "linter-eslint":
     globalNodePath: "/Users/benoit/.node"
     disableWhenNoEslintrcFileInPath: true
-".js.jsx.source":
+".coffee.jsx.source":
   editor:
     preferredLineLength: 100
-".coffee.jsx.source":
+".js.jsx.source":
   editor:
     preferredLineLength: 100
 ".diff.source":


dont replace underscores in PSN id's

dont replace underscores in PSN id's

--- scripts/bungie.coffee
+++ scripts/bungie.coffee
@@ -97,12 +97,12 @@

 tryPlayerId = (res, membershipType, displayName, robot) ->
   deferred = new Deferred()
-  # replaces underscores with spaces (for xbox)
-  # safe to call on PSN IDs because underscores are not allowed
-  displayName = displayName.split('_').join(' ')

   if membershipType
     networkName = if membershipType is '1' then 'xbox' else 'playstation'
+    # replaces underscores with spaces (for xbox)
+    displayName = displayName.split('_').join(' ') if networkName is 'xbox'
+
     return getPlayerId(res, membershipType, displayName, robot)
     .then (results) ->
       if !results
@@ -113,7 +113,7 @@
       deferred.promise
   else
     return Q.all([
-      getPlayerId(res, '1', displayName, robot),
+      getPlayerId(res, '1', displayName.split('_').join(' '), robot),
       getPlayerId(res, '2', displayName, robot)
     ]).then (results) ->
       if results[0] && results[1]


Chaged path sep chars

Chaged path sep chars

--- tests/unit.coffee
+++ tests/unit.coffee
@@ -29,9 +29,9 @@
       "isBuffer": sinon.stub().returns true
       "isStream": sinon.stub().returns false
       "pipe": sinon.spy()
-      "path": "/tests/data/source.scss"
-      "cwd": "/"
-      "base": "/tests/data"
+      "path": path.join path.sep, "tests", "data", "source.scss"
+      "cwd": path.sep
+      "base": path.join path.sep, "tests", "data"
       "contents": new Buffer("Hello World")
       "relative": "source.scss"


senpai change realname

senpai change realname

--- scripts/senpai.coffee
+++ scripts/senpai.coffee
@@ -13,6 +13,8 @@
 #   {アダ名 or nickname}--  - ヨクナイネ！
 #   hubot {アダ名 or nickname} 何点ですか?  - hubot に後輩の点数を教えてもらおう!

+_ = require('underscore')
+
 # {{{ AISATSU
 AISATSU_YOROSHIKU = [
   'よろしくな'
@@ -326,7 +328,7 @@

     gNicknames[nickname] = null
     setSenpaiStorage robot, msg, 'NICKNAMES', gNicknames
-    newNicknames = (item for item in nicknames when item isnt nickname)
+    newNicknames = (item for item in nicknames when item.toLowerCase() isnt nickname)
     setUserInfo robot, msg, realname, 'NICKNAMES', newNicknames
     checkKeigo robot, msg
 # }}}
@@ -335,8 +337,8 @@
   robot.hear /([^ ]+)(\+\+[ ]*(.*))/i, (msg) ->
     fromname = msg.message.user.name
     fromuser = whoIsThis robot, msg, fromname
-    unless whoIsThis robot, msg, fromuser
-      msg.send "#{fromuser} こいつ誰？ > all"
+    unless fromuser
+      msg.send "#{fromname} こいつ誰？ > all"
       checkKeigo robot, msg
       return

@@ -376,8 +378,8 @@
   robot.hear /([^ ]+)(--[ ]*(.*))/i, (msg) ->
     fromname = msg.message.user.name
     fromuser = whoIsThis robot, msg, fromname
-    unless whoIsThis robot, msg, fromuser
-      msg.send "#{fromuser} こいつ誰？ > all"
+    unless fromuser
+      msg.send "#{fromname} こいつ誰？ > all"
       checkKeigo robot, msg
       return

@@ -429,7 +431,35 @@
     checkKeigo robot, msg
 # }}}

+  # cace sensitive
+  robot.respond /([^ ]+)[ ]*→[ ]*([^ ]+)/i, (msg) ->
+    fromname = msg.match[1]
+    toname = msg.match[2]
+
+    return msg.send "それだめ" if fromname.toLowerCase() is robot.name
+    # return msg.send "#{fromname} がいない" unless existsUser robot, msg, fromname
+    return msg.send "#{toname} はすでにいる" if whoIsThis robot, msg, toname
+
+    usersInfo = robot.brain.data.usersInfo ||= {}
+    newUsersInfo = {}
+    console.log usersInfo
+    for k, v of usersInfo
+      if k is fromname
+        k = toname
+      newUsersInfo[k] = _.clone(v)
+    console.log newUsersInfo
+    robot.brain.data.usersInfo = newUsersInfo
+
+    gNicknames = getSenpaiStorage robot, msg, 'NICKNAMES'
+    gNicknames ||= {}
+    newNicknames = {}
+    console.log gNicknames
+    robot.brain.data.usersInfo = newUsersInfo
+    for k, v of gNicknames
+      newNicknames[k] = v?.replace new RegExp('^' + fromname + '$'), toname
+    console.log newNicknames
+    setSenpaiStorage robot, msg, 'NICKNAMES', newNicknames
+
   robot.respond /DIE$/i, (msg) ->
-    msg.send "どうやら俺の人生もここまでだ。みん元気でな"
     process.exit 0


improved the regex to accept could

improved the regex to accept could

--- scripts/trello.coffee
+++ scripts/trello.coffee
@@ -47,7 +47,8 @@
     trelloIt msg

 module.exports = (robot) ->
-  robot.hear /we should (.*)/i, (msg) ->
+  robot.hear /we (sh|c)ould (.*)/i, (msg) ->
+    msg.send msg.match[2]
     unless process.env.TRELLO_API_KEY?
       msg.send "Please specify the Trello API key in TRELLO_API_KEY"
       return


Add info in data when set image as preview state

--- app/assets/javascripts/uploadcare/widget/tabs/preview-tab.coffee
+++ app/assets/javascripts/uploadcare/widget/tabs/preview-tab.coffee
@@ -55,7 +55,7 @@
             # 1162x684 is 1.5 size of conteiner
             src += "-/preview/1162x693/-/setfill/ffffff/-/format/jpeg/-/progressive/yes/"
             imgInfo = info.originalImageInfo
-            @__setState('image', {src, name: info.name})
+            @__setState('image', {src, name: info.name, info})
             @initImage([imgInfo.width, imgInfo.height], info.cdnUrlModifiers)
         else
           # , but update if other


fixed cmyk NaN bug

fixed cmyk NaN bug

--- client/converter.coffee
+++ client/converter.coffee
@@ -230,6 +230,10 @@
       # logic
       k = Math.min(1, cmy.c, cmy.m, cmy.y)

+      c = cmy.c
+      m = cmy.m
+      y = cmy.y
+
       c = 0 if k > 0.997 # ~black
       m = 0 if k > 0.997 # ~black
       y = 0 if k > 0.997 # ~black
@@ -237,6 +241,7 @@
       c = (cmy.c - k) / (1 - k) if k > 0.003
       m = (cmy.m - k) / (1 - k) if k > 0.003
       y = (cmy.y - k) / (1 - k) if k > 0.003
+
       # validate output
       converter.bounds.validate "cmyk", {c: c, m: m, y: y, k: k}


improve readability for spec

improve readability for spec

--- spec/vim-mode-plus-move-selected-text-spec.coffee
+++ spec/vim-mode-plus-move-selected-text-spec.coffee
@@ -43,10 +43,10 @@
         'left': 'vim-mode-plus-user:move-selected-text-left'
         'right': 'vim-mode-plus-user:move-selected-text-right'

-        'cmd-K': 'vim-mode-plus-user:duplicate-selected-text-up'
-        'cmd-J': 'vim-mode-plus-user:duplicate-selected-text-down'
-        'cmd-H': 'vim-mode-plus-user:duplicate-selected-text-left'
-        'cmd-L': 'vim-mode-plus-user:duplicate-selected-text-right'
+        'cmd-up': 'vim-mode-plus-user:duplicate-selected-text-up'
+        'cmd-down': 'vim-mode-plus-user:duplicate-selected-text-down'
+        'cmd-left': 'vim-mode-plus-user:duplicate-selected-text-left'
+        'cmd-right': 'vim-mode-plus-user:duplicate-selected-text-right'
     keymapsPriority = 1
     atom.keymaps.add "test", keymaps, keymapsPriority

@@ -508,26 +508,26 @@
         it "duplicate single line", ->
           ensure 'V',
             selectedBufferRange: rowRange(0, 0)
-          ensure 'cmd-J',
+          ensure 'cmd-down',
             selectedBufferRange: rowRange(1, 1)
             text: 'line0\nline0\nline1\nline2\n'

         it "duplicate 2 selected line", ->
           ensure 'V j',
             selectedBufferRange: rowRange(0, 1)
-          ensure 'cmd-J',
+          ensure 'cmd-down',
             selectedBufferRange: rowRange(2, 3)
             text: "line0\nline1\nline0\nline1\nline2\n"
-          ensure 'cmd-K',
+          ensure 'cmd-up',
             selectedBufferRange: rowRange(2, 3)
             text: "line0\nline1\nline0\nline1\nline0\nline1\nline2\n"
         it "suport count", ->
           ensure 'V',
             selectedBufferRange: rowRange(0, 0)
-          ensure '2 cmd-J',
+          ensure '2 cmd-down',
             selectedBufferRange: rowRange(1, 2)
             text: "line0\nline0\nline0\nline1\nline2\n"
-          ensure '2 cmd-K',
+          ensure '2 cmd-up',
             selectedBufferRange: rowRange(1, 4)
             text: "line0\nline0\nline0\nline0\nline0\nline0\nline0\nline1\nline2\n"
       describe "overwrite: true", ->
@@ -537,19 +537,19 @@
         it "overrite lines down", ->
           ensure 'V',
             selectedBufferRange: rowRange(0, 0)
-          ensure 'cmd-J',
+          ensure 'cmd-down',
             text: "line0\nline0\nline2\n"
-          ensure 'cmd-J',
+          ensure 'cmd-down',
             text: "line0\nline0\nline0\n"
             selectedBufferRange: rowRange(2, 2)
-          ensure '2 cmd-J',
+          ensure '2 cmd-down',
             text: "line0\nline0\nline0\nline0\nline0\n"
             selectedBufferRange: rowRange(3, 4)

         it "overrite lines up", ->
           ensure 'j j V',
             selectedBufferRange: rowRange(2, 2)
-          ensure '2 cmd-K',
+          ensure '2 cmd-up',
             selectedBufferRange: rowRange(0, 1)
             text: "line2\nline2\nline2\n"
         it "adjust count when duplicate up to stop overwrite when no enough height is available", ->
@@ -563,7 +563,7 @@
             """
           ensure 'V j',
             selectedBufferRange: rowRange(3, 4)
-          ensure '1 0 cmd-K',
+          ensure '1 0 cmd-up',
             selectedBufferRange: rowRange(1, 2)
             text: """
             0
@@ -593,7 +593,7 @@
             YYYY
             ZZZZ\n
             """
-          ensure 'cmd-K',
+          ensure 'cmd-up',
             mode: ['visual', 'characterwise']
             selectedTextOrdered: ['oo', 'YY']
             text_: """
@@ -608,7 +608,7 @@
               [[0, 1], [0, 3]]
               [[3, 1], [3, 3]]
             ]
-          ensure '2 cmd-K', # mode shift to vB
+          ensure '2 cmd-up', # mode shift to vB
             mode: ['visual', 'blockwise']
             selectedTextOrdered: ['oo', 'oo', 'YY', 'YY']
             text_: """
@@ -640,7 +640,7 @@
             YYYY
             ZZZZ\n
             """
-          ensure 'cmd-J',
+          ensure 'cmd-down',
             mode: ['visual', 'characterwise']
             selectedTextOrdered: ['oo', 'YY']
             text_: """
@@ -655,7 +655,7 @@
               [[1, 1], [1, 3]]
               [[4, 1], [4, 3]]
             ]
-          ensure '2 cmd-J',
+          ensure '2 cmd-down',
             mode: ['visual', 'blockwise']
             selectedTextOrdered: ['oo', 'oo', 'YY', 'YY']
             text_: """
@@ -698,7 +698,7 @@
             YYYY
             ZZZZ\n
             """
-          ensure 'cmd-J',
+          ensure 'cmd-down',
             mode: ['visual', 'characterwise']
             selectedTextOrdered: ['oo', 'YY']
             text: """
@@ -707,7 +707,7 @@
             YYYY
             ZYYZ\n
             """
-          ensure '2 cmd-J',
+          ensure '2 cmd-down',
             mode: ['visual', 'blockwise']
             selectedTextOrdered: ['oo', 'oo', 'YY', 'YY']
             text: """
@@ -733,7 +733,7 @@
             YYYY
             ZZZZ\n
             """
-          ensure 'cmd-K',
+          ensure 'cmd-up',
             mode: ['visual', 'characterwise']
             selectedTextOrdered: ['YY', 'ZZ']
             text: """
@@ -754,7 +754,7 @@
             YYYY
             ZZZZ\n
             """
-          ensure 'v l cmd-K',
+          ensure 'v l cmd-up',
             mode: ['visual', 'characterwise']

   describe "duplicate right/left", ->
@@ -773,7 +773,7 @@

       describe "overwrite: false", ->
         it "duplicate linewise right", ->
-          ensure 'V j j cmd-L',
+          ensure 'V j j cmd-right',
             selectedBufferRange: rowRange(0, 2)
             text: """
             0 |_0 |_
@@ -782,7 +782,7 @@

             """
         it "count support", ->
-          ensure 'V j j 2 cmd-L',
+          ensure 'V j j 2 cmd-right',
             selectedBufferRange: rowRange(0, 2)
             text: """
             0 |_0 |_0 |_
@@ -792,7 +792,7 @@
             """

         it "duplicate linewise left(identical behavior to right)", ->
-          ensure 'V j j cmd-H',
+          ensure 'V j j cmd-left',
             selectedBufferRange: rowRange(0, 2)
             text: """
             0 |_0 |_
@@ -801,7 +801,7 @@

             """
         it "duplicate linewise left with count(identical behavior to right)", ->
-          ensure 'V j j 2 cmd-H',
+          ensure 'V j j 2 cmd-left',
             selectedBufferRange: rowRange(0, 2)
             text: """
             0 |_0 |_0 |_
@@ -814,7 +814,7 @@
           setOverwriteConfig(true)

         it "duplicate linewise right(no behavior diff with overwrite=false)", ->
-          ensure 'V j j cmd-L',
+          ensure 'V j j cmd-right',
             selectedBufferRange: rowRange(0, 2)
             text: """
             0 |_0 |_
@@ -823,7 +823,7 @@

             """
         it "duplicate linewise right(no behavior diff with overwrite=false)", ->
-          ensure 'V j j 2 cmd-L',
+          ensure 'V j j 2 cmd-right',
             selectedBufferRange: rowRange(0, 2)
             text: """
             0 |_0 |_0 |_
@@ -851,14 +851,14 @@
             YYY
             ZZZ\n
             """
-          ensureDuplicate 'cmd-L',
+          ensureDuplicate 'cmd-right',
             text: """
             ooooo
             xxx
             YYYYY
             ZZZ\n
             """
-          ensureDuplicate '2 cmd-L',
+          ensureDuplicate '2 cmd-right',
             selectedTextOrdered: ['oooo', 'YYYY']
             text: """
             ooooooooo
@@ -874,7 +874,7 @@
             YYYYY____
             ZZZ__YYYY\n
             """
-          ensureDuplicate 'cmd-H',
+          ensureDuplicate 'cmd-left',
             selectedTextOrdered: ['oooo', 'YYYY']
             selectedBufferRange: [
               [[1, 5], [1, 9]]
@@ -886,7 +886,7 @@
             YYYYY____
             ZZZ__YYYYYYYY\n
             """
-          ensureDuplicate '2 cmd-H',
+          ensureDuplicate '2 cmd-left',
             selectedTextOrdered: ['oooooooo', 'YYYYYYYY']
             selectedBufferRange: [
               [[1, 5], [1, 13]]
@@ -919,7 +919,7 @@
             oxYZ@
             oxYZ@\n
             """
-          ensureDuplicate 'cmd-L',
+          ensureDuplicate 'cmd-right',
             text: """
             oxYxY
             oxYZ@
@@ -930,7 +930,7 @@
               [[0, 3], [0, 5]]
               [[2, 3], [2, 5]]
             ]
-          ensureDuplicate '2 cmd-L',
+          ensureDuplicate '2 cmd-right',
             selectedTextOrdered: ['xYxY', 'xYxY']
             text: """
             oxYxYxYxY
@@ -954,7 +954,7 @@
               [[1, 5], [1, 9]]
               [[3, 5], [3, 9]]
             ]
-          ensureDuplicate 'cmd-H',
+          ensureDuplicate 'cmd-left',
             selectedTextOrdered: ['xYxY', 'xYxY']
             text_: """
             oxYxY____


Fix custom command not found when specifying different config dir

Resolves: #123

--- lib/custom-commands.coffee
+++ lib/custom-commands.coffee
@@ -15,8 +15,17 @@
 # along with GenieACS.  If not, see <http://www.gnu.org/licenses/>.
 ###

+path = require 'path'
 config = require './config'
 common = require './common'
+
+
+FILES = {}
+getFile = (filename) ->
+  if filename not of FILES
+    FILES[filename] = require(path.resolve(config.get('CONFIG_DIR'), "custom_commands/#{filename}"))
+
+  return FILES[filename]

 exports.execute = (deviceId, command, callback) ->
@@ -24,13 +33,13 @@
   f = args.shift()
   c = args.shift()

-  file = require "../config/custom_commands/#{f}"
+  file = getFile(f)
   file[c](deviceId, args.join(' '), callback)

 exports.getFileCommands = (filename) ->
   commands = []
-  f = require("../config/custom_commands/#{filename}")
+  f = getFile(filename)
   for k,v of f
     commands.push(k)
   return commands


Fix crash bug

Fix crash bug

--- src/graphview.coffee
+++ src/graphview.coffee
@@ -64,8 +64,9 @@
       from = graph.from
     else
       from = "-#{@config.settings.timeRange} hours"
+    series = graph.series
     if not graph.noAdditional?
-      series = graph.series.concat(@config.settings.graphiteAdditionalSeries)
+      series = series.concat(@config.settings.graphiteAdditionalSeries)
     url = "#{@config.sources.graphite}/render/?width=#{@imageWidth}&height=#{@imageHeight}"
     url += "&target=#{series.join('&target=')}&from=#{from}"
     url += "&graphOnly=false&hideLegend=true&areaMode=first&lineWidth=2"


Fixa few bugs in the reg tests.

Fixa few bugs in the reg tests.

--- test/lib/user.iced
+++ test/lib/user.iced
@@ -252,7 +252,7 @@
   prove_twitter : (cb) ->
     opts =
       which : "twitter"
-      search_regex : /Please tweet the following:\s+(\S.*?)\n/
+      search_regex : /Please.*tweet.*the following:\s+(\S.*?)\n/
       http_action : tweet_api
     await @prove opts, defer err
     cb err
@@ -283,8 +283,8 @@
     await @init esc('init', defer())
     await @signup esc('signup', defer())
     await @push_key esc('push_key', defer())
-    await @prove_github esc('prove_github', defer()) if twitter
-    await @prove_twitter esc('prove_twitter', defer()) if github
+    await @prove_github esc('prove_github', defer()) if github
+    await @prove_twitter esc('prove_twitter', defer()) if twitter
     await @write_pw esc('write_pw', defer()) if save_pw
     gcb null


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/random.coffee
+++ test/random.coffee
@@ -16,6 +16,7 @@
   ok Random.angleBetween

   a = Random.angleBetween(0.25.turns, 0.5.turns)
-  ok a < 0.5
+  ok a < 0.5.turns
+  o

 module()


re-enable notebook tests

re-enable notebook tests

--- test/runner.coffee
+++ test/runner.coffee
@@ -13,9 +13,9 @@
   'github'
   'html'
 ]
-# TODO
-#if window?
-#  tests.push 'notebook'
+
+if window?
+  tests.push 'notebook'

 collect_suites = (suites) ->
   _.map suites, (suite) ->


send a currentProfile when starting a recording

--- client/room/room.coffee
+++ client/room/room.coffee
@@ -75,7 +75,6 @@

 userCallback = (err, res) ->
-  console.log res
   Session.setTemp 'recUserName', res.user_name
   Session.setTemp 'recUserPic', res.pic_url
   mods = []
@@ -98,7 +97,7 @@

     userId = $('#user-id').val()
     $('#user-id').val('')
-
+
     userName = $('#user-name').text().trim()

     isPartOf = $('#module-id').val()
@@ -108,7 +107,7 @@
     Session.setTemp 'recUserPic', ''
     Session.setTemp 'recModules', []
     Session.setTemp 'recWaiting', false
-
+
     currentMediaPackage =
       title: title
       rightsHolder: userId
@@ -120,10 +119,11 @@

     update =
       recording: true
+      currentProfile: 'cam'
       currentMediaPackage: currentMediaPackage
-
+
     Rooms.update room._id, $set: update
-
+
   'keyup #user-id': (e, template) ->
     if @userTimeout then Meteor.clearTimeout @userTimeout
     $('.peakaboo-userdetails').hide()
@@ -132,7 +132,7 @@
       Meteor.call 'user_ws', e.currentTarget.value, userCallback
     if e.currentTarget.value
       @userTimeout = Meteor.setTimeout timeoutFunc, 1000
-
+
 Template.recordModal.helpers
   userPic: ->
     Session.get 'recUserPic'
@@ -141,4 +141,4 @@
   modules: ->
     Session.get 'recModules'
   waiting: ->
-    Session.get 'recWaiting'+    Session.get 'recWaiting'


Fix another issue with $.i18n.t and this

--- app/views/play/level/LevelPlaybackView.coffee
+++ app/views/play/level/LevelPlaybackView.coffee
@@ -61,14 +61,13 @@
     if /safari/.test(ua) and not /chrome/.test(ua)
       @$el.find('.toggle-fullscreen').hide()
     @timePopup ?= new HoverPopup
-    t = $.i18n.t
-    @second = t 'units.second'
-    @seconds = t 'units.seconds'
-    @minute = t 'units.minute'
-    @minutes = t 'units.minutes'
-    @goto = t 'play_level.time_goto'
-    @current = t 'play_level.time_current'
-    @total = t 'play_level.time_total'
+    @second = $.i18n.t 'units.second'
+    @seconds = $.i18n.t 'units.seconds'
+    @minute = $.i18n.t 'units.minute'
+    @minutes = $.i18n.t 'units.minutes'
+    @goto = $.i18n.t 'play_level.time_goto'
+    @current = $.i18n.t 'play_level.time_current'
+    @total = $.i18n.t 'play_level.time_total'
     @$el.find('#play-button').css('visibility', 'hidden') if @options.level.get 'hidesPlayButton'  # Don't show for first few levels, confuses new players.

   updatePopupContent: ->


added options for different output formats

--- src/git-timetracking.coffee
+++ src/git-timetracking.coffee
@@ -4,8 +4,20 @@
 spawn = childProcess.spawn
 cliTable = require "cli-table"

+outputPossibilities = ["csv", "ascii"]
+
+defaultOutputFormat = outputPossibilities[0]
 defaultPauseTime = 20
 defaultInitTime = 10
+
+
+parseOutputFormat = (val) ->
+	if val?
+		val = val.toLowerCase()
+		for option in outputPossibilities
+			if option is val
+				return val
+	outputPossibilities[0]

 parsePauseTime = (val) ->
 	if val?
@@ -27,6 +39,7 @@
 	#.option("-t, --time [time]", "git log since compatible time")
 	.option("-p, --pause [pause]", "max pause time in minutes (default: #{defaultPauseTime})", parsePauseTime)
 	.option("-i, --init [init]", "init time in minutes (default: #{defaultInitTime})", parseInitTime)
+	.option("-o, --output [format]", "output formats (default: #{defaultOutputFormat}) (options: " + outputPossibilities.join(", ") + ")" , parseOutputFormat)

 zeroPadding = (str) ->
 	str = str.toString()
@@ -151,6 +164,8 @@
 			program.pause = defaultPauseTime
 		if not program.init?
 			program.init = defaultInitTime
+		if not program.output?
+			program.output = defaultOutputFormat
 		if not program.user?
 			console.log "Need user email address"
 			process.exit()


Replace 'not ... ==' with 'isnt', remove double negative.


Added start log to download

Added start log to download

--- source/Downloader.coffee
+++ source/Downloader.coffee
@@ -13,3 +13,4 @@
 # Download function for downloading
 # a file from url to destination path.
 download = (uri, file, callback) ->
+  winston.info('Download started.')


Rename rootView.openAsync to rootView.open

--- spec/root-view-spec.coffee
+++ spec/root-view-spec.coffee
@@ -294,7 +294,7 @@
           editSession = null

           waitsForPromise ->
-            rootView.openAsync().then (o) -> editSession = o
+            rootView.open().then (o) -> editSession = o

           runs ->
             expect(rootView.getActivePane().activeItem).toBe editSession
@@ -306,10 +306,10 @@
           editSession2 = null

           waitsForPromise ->
-            rootView.openAsync()
+            rootView.open()
               .then (o) ->
                 editSession1 = o
-                rootView.openAsync()
+                rootView.open()
               .then (o) ->
                 editSession2 = o

@@ -321,7 +321,7 @@
         it "creates an edit session for the given path as an item on a new pane, and focuses the pane", ->
           editSession = null
           waitsForPromise ->
-            rootView.openAsync('b').then (o) -> editSession = o
+            rootView.open('b').then (o) -> editSession = o

           runs ->
             expect(rootView.getActivePane().activeItem).toBe editSession
@@ -339,7 +339,7 @@
           editSession = null

           waitsForPromise ->
-            rootView.openAsync().then (o) -> editSession = o
+            rootView.open().then (o) -> editSession = o

           runs ->
             expect(activePane.getItems().length).toBe 2
@@ -354,14 +354,14 @@

             editSession = null
             waitsForPromise ->
-              rootView.openAsync('b').then (o) -> editSession = o
+              rootView.open('b').then (o) -> editSession = o

             runs ->
               expect(activePane.activeItem).toBe editSession
               expect(editSession).not.toBe previousEditSession

             waitsForPromise ->
-              rootView.openAsync(previousEditSession.getPath()).then (o) -> editSession = o
+              rootView.open(previousEditSession.getPath()).then (o) -> editSession = o

             runs ->
               expect(editSession).toBe previousEditSession
@@ -373,7 +373,7 @@
             editSession = null

             waitsForPromise ->
-              rootView.openAsync('b').then (o) -> editSession = o
+              rootView.open('b').then (o) -> editSession = o

             runs ->
               expect(activePane.activeItem).toBe editSession


Test that updateWindowSheetOffset can be called

Testing the wiring to themes isn't worth it, but this at least makes sure we don't break if Electron APIs change.

--- spec/title-bar-spec.coffee
+++ spec/title-bar-spec.coffee
@@ -1,7 +1,7 @@
 TitleBar = require '../src/title-bar'

 describe "TitleBar", ->
-  it 'updates the title based on document.title when the active pane item changes', ->
+  it "updates the title based on document.title when the active pane item changes", ->
     titleBar = new TitleBar({
       workspace: atom.workspace,
       themes: atom.themes,
@@ -17,3 +17,13 @@

     expect(document.title).not.toBe(initialTitle)
     expect(titleBar.element.querySelector('.title').textContent).toBe document.title
+
+  it "can update the sheet offset for the current window based on its height", ->
+    titleBar = new TitleBar({
+      workspace: atom.workspace,
+      themes: atom.themes,
+      applicationDelegate: atom.applicationDelegate,
+    })
+    expect(->
+      titleBar.updateWindowSheetOffset()
+    ).not.toThrow()


This never ended up being used

This never ended up being used

--- spec/vim-state-spec.coffee
+++ spec/vim-state-spec.coffee
@@ -17,11 +17,6 @@

   keydown = (key, options={}) ->
     options.element ?= editorView[0]
-    helpers.keydown(key, options)
-
-  type = (key, options={}) ->
-    options.element = editorView[0]
-    options.raw = true
     helpers.keydown(key, options)

   commandModeInputKeydown = (key, opts = {}) ->


Update proposal_model.coffee

Update proposal_model.coffee

change to 0 decimal places.

--- lineman/app/models/proposal_model.coffee
+++ lineman/app/models/proposal_model.coffee
@@ -67,7 +67,7 @@
       numVoted = @numberVoted()
       groupSize = @groupSizeWhenVoting()
       return 0 if numVoted == 0 or groupSize == 0
-      (100 * numVoted / groupSize).toFixed(2)
+      (100 * numVoted / groupSize).toFixed(0)

     groupSizeWhenVoting: ->
       if @isActive()


Rearrange specs for testing constructor options

Conflicts:
	test/ansi_to_html.coffee

--- test/ansi_to_html.coffee
+++ test/ansi_to_html.coffee
@@ -1,131 +1,141 @@
 Filter = require '../lib/ansi_to_html.js'
 expect = require('chai').expect

-test = (text, result, done) ->
-	f = new Filter()
-	expect(f.toHtml(text)).to.equal(result)
-	done()
+test = (text, result, done, opts = {}) ->
+  f = new Filter(opts)
+  expect(f.toHtml(text)).to.equal(result)
+  done()

 describe 'ansi to html', () ->

-	it "doesn't modify the input string", (done) ->
-		text = 'some text'
-		new Filter().toHtml(text)
-		expect(text).to.equal('some text')
-		done()
+  describe 'constructed with no options', () ->

-	it 'returns plain text when given plain text', (done) ->
-		text = 'test\ntest\n'
-		result = 'test\ntest\n'
-		test(text, result, done)
+    it "doesn't modify the input string", (done) ->
+      text = result = 'some text'
+      test(text, result, done)

-	it 'renders foreground colors', (done) ->
-		text = "colors: \x1b[30mblack\x1b[37mwhite"
-		result = 'colors: blackwhite'
-		test(text, result, done)
+    it 'returns plain text when given plain text', (done) ->
+      text = 'test\ntest\n'
+      result = 'test\ntest\n'
+      test(text, result, done)

-	it 'renders light foreground colors', (done) ->
-		text = 'colors: \x1b[90mblack\x1b[97mwhite'
-		result = 'colors: blackwhite'
-		test(text, result, done)
+    it 'renders foreground colors', (done) ->
+      text = "colors: \x1b[30mblack\x1b[37mwhite"
+      result = 'colors: blackwhite'
+      test(text, result, done)

-	it 'renders background colors', (done) ->
-		text = 'colors: \x1b[40mblack\x1b[47mwhite'
-		result = 'colors: blackwhite'
-		test(text, result, done)
+    it 'renders light foreground colors', (done) ->
+      text = 'colors: \x1b[90mblack\x1b[97mwhite'
+      result = 'colors: blackwhite'
+      test(text, result, done)

-	it 'renders light background colors', (done) ->
-		text = 'colors: \x1b[100mblack\x1b[107mwhite'
-		result = 'colors: blackwhite'
-		test(text, result, done)
+    it 'renders background colors', (done) ->
+      text = 'colors: \x1b[40mblack\x1b[47mwhite'
+      result = 'colors: blackwhite'
+      test(text, result, done)

-	it 'renders strikethrough', (done) ->
-		text = 'strike: \x1b[9mthat'
-		result = 'strike: that'
-		test(text, result, done)
+    it 'renders light background colors', (done) ->
+      text = 'colors: \x1b[100mblack\x1b[107mwhite'
+      result = 'colors: blackwhite'
+      test(text, result, done)

-	it 'renders blink', (done) ->
-		text = 'blink: \x1b[5mwhat'
-		result = 'blink: <blink>what</blink>'
-		test(text, result, done)
+    it 'renders strikethrough', (done) ->
+      text = 'strike: \x1b[9mthat'
+      result = 'strike: that'
+      test(text, result, done)

-	it 'renders underline', (done) ->
-		text = 'underline: \x1b[3mstuff'
-		result = 'underline: stuff'
-		test(text, result, done)
+    it 'renders blink', (done) ->
+      text = 'blink: \x1b[5mwhat'
+      result = 'blink: <blink>what</blink>'
+      test(text, result, done)

-	it 'renders bold', (done) ->
-		text = 'bold: \x1b[1mstuff'
-		result = 'bold: stuff'
-		test(text, result, done)
+    it 'renders underline', (done) ->
+      text = 'underline: \x1b[3mstuff'
+      result = 'underline: stuff'
+      test(text, result, done)

-	it 'handles ressets', (done) ->
-		text = '\x1b[1mthis is bold\x1b[0m, but this isn\'t'
-		result = 'this is bold, but this isn\'t'
-		test(text, result, done)
+    it 'renders bold', (done) ->
+      text = 'bold: \x1b[1mstuff'
+      result = 'bold: stuff'
+      test(text, result, done)

-	it 'handles multiple resets', (done) ->
-		text = 'normal, \x1b[1mbold, \x1b[3munderline, \x1b[31mred\x1b[0m, normal'
-		result = 'normal, bold, underline, red, normal'
-		test(text, result, done)
+    it 'handles ressets', (done) ->
+      text = '\x1b[1mthis is bold\x1b[0m, but this isn\'t'
+      result = 'this is bold, but this isn\'t'
+      test(text, result, done)

-	it 'handles resets with implicit 0', (done) ->
-		text = '\x1b[1mthis is bold\x1b[m, but this isn\'t'
-		result = 'this is bold, but this isn\'t'
-		test(text, result, done)
+    it 'handles multiple resets', (done) ->
+      text = 'normal, \x1b[1mbold, \x1b[3munderline, \x1b[31mred\x1b[0m, normal'
+      result = 'normal, bold, underline, red, normal'
+      test(text, result, done)

-	it 'renders multi-attribute sequences', (done) ->
-		text = 'normal, \x1b[1;3;31mbold, underline, and red\x1b[0m, normal'
-		result = 'normal, bold, underline, and red, normal'
-		test(text, result, done)
+    it 'handles resets with implicit 0', (done) ->
+      text = '\x1b[1mthis is bold\x1b[m, but this isn\'t'
+      result = 'this is bold, but this isn\'t'
+      test(text, result, done)

-	it 'renders multi-attribute sequences with a semi-colon', (done) ->
-		text = 'normal, \x1b[1;3;31;mbold, underline, and red\x1b[0m, normal'
-		result = 'normal, bold, underline, and red, normal'
-		test(text, result, done)
+    it 'renders multi-attribute sequences', (done) ->
+      text = 'normal, \x1b[1;3;31mbold, underline, and red\x1b[0m, normal'
+      result = 'normal, bold, underline,' +
+               ' and red, normal'
+      test(text, result, done)

-	it 'eats malformed sequences', (done) ->
-		text = '\x1b[25oops forgot the \'m\''
-		result = 'oops forgot the \'m\''
-		test(text, result, done)
+    it 'renders multi-attribute sequences with a semi-colon', (done) ->
+      text = 'normal, \x1b[1;3;31;mbold, underline, and red\x1b[0m, normal'
+      result = 'normal, bold, underline, ' +
+               'and red, normal'
+      test(text, result, done)

-	it 'renders xterm 256 sequences', (done) ->
-		text = '\x1b[38;5;196mhello'
-		result = 'hello'
-		test(text, result, done)
+    it 'eats malformed sequences', (done) ->
+      text = '\x1b[25oops forgot the \'m\''
+      result = 'oops forgot the \'m\''
+      test(text, result, done)

-	it 'handles resetting to default foreground color', (done) ->
-		text = '\x1b[30mblack\x1b[39mdefault'
-		result = 'blackdefault'
-		test(text, result, done)
+    it 'renders xterm 256 sequences', (done) ->
+      text = '\x1b[38;5;196mhello'
+      result = 'hello'
+      test(text, result, done)

-	it 'handles resetting to default background color', (done) ->
-		text = '\x1b[100mblack\x1b[49mdefault'
-		result = 'blackdefault'
-		test(text, result, done)
+    it 'handles resetting to default foreground color', (done) ->
+      text = '\x1b[30mblack\x1b[39mdefault'
+      result = 'black' +
+               'default'
+      test(text, result, done)

-	it 'is able to disable underline', (done) ->
-		text = 'underline: \x1b[4mstuff\x1b[24mthings'
-		result = 'underline: stuffthings'
-		test(text, result, done)
+    it 'handles resetting to default background color', (done) ->
+      text = '\x1b[100mblack\x1b[49mdefault'
+      result = 'blackdefault'
+      test(text, result, done)

-	it 'renders newlines when the newline option is true', (done) ->
-		text = 'test\ntest\n'
-		result = 'test
test
'
-		f = new Filter(newline: true)
-		expect(f.toHtml(text)).to.equal(result)
-		done()
+    it 'is able to disable underline', (done) ->
+      text = 'underline: \x1b[4mstuff\x1b[24mthings'
+      result = 'underline: stuffthings'
+      test(text, result, done)

-	it 'renders two escape sequences in sequence', (done) ->
-		text = 'months remaining\x1b[1;31mtimes\x1b[m\x1b[1;32mmultiplied by\x1b[m $10'
-		result = 'months remainingtimesmultiplied by $10'
-		f = new Filter()
-		expect(f.toHtml(text)).to.equal(result)
-		done()
+    it 'renders two escape sequences in sequence', (done) ->
+      text = 'months remaining\x1b[1;31mtimes\x1b[m\x1b[1;32mmultiplied' +
+             ' by\x1b[m $10'
+      result = 'months remainingtimes' +
+               'multiplied by $10'
+      test(text, result, done)

-	it 'escapes XML entities when the escapeXML option is true', (done) ->
-		text = 'normal, \x1b[1;3;31;mbold, <underline>, and red\x1b[0m, normal'
-		result = 'normal, bold, <underline>, and red, normal'
-		f = new Filter(escapeXML: true)
-		expect(f.toHtml(text)).to.equal(result)
-		done()
+  describe 'with escapeXML option enabled', () ->
+
+    it 'escapes XML entities', (done) ->
+      text = 'normal, \x1b[1;3;31;mbold, <underline>, and red\x1b[0m, normal'
+      result = 'normal, bold, <underline' +
+               '>, and red, normal'
+      test(text, result, done, escapeXML: true)
+
+  describe 'with newline option enabled', () ->
+
+    it 'renders line breaks', (done) ->
+      text = 'test\ntest\n'
+      result = 'test
test
'
+      test(text, result, done, newline: true)


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/timed_events.coffee
+++ src/timed_events.coffee
@@ -23,7 +23,7 @@

   @name every
   @methodOf TimedEvents#
-
+  @param
   @returns {Number} Distance between the two objects
   ###
   every: (n, fn) ->


Using elapsed time in delayed events

Using elapsed time in delayed events

--- src/timed_events.coffee
+++ src/timed_events.coffee
@@ -65,7 +65,7 @@
   ###
   delay: (seconds, callback) ->
     delayedEvents.push
-      delay: steps
+      delay: seconds
       callback: callback

     return self


Boyscout.

Boyscout.

--- js-library/Gruntfile.coffee
+++ js-library/Gruntfile.coffee
@@ -161,7 +161,7 @@
     grunt.log.writeln "Renaming file \"#{source_file_path}\" to \"#{new_source_file_path}\""
     fs.renameSync(source_file_path, new_source_file_path );

-    grunt.log.writeln "Replacing placeholder with hash value in file \"#{destination_file_path}."
+    grunt.log.writeln "Replacing placeholder with hash value in file \"#{destination_file_path}\"."
     content = grunt.file.read destination_file_path
     content_with_hash = content.replace /&\*HASH_PLACE_HOLDER\*&/, source_file_hash
     grunt.file.write destination_file_path, content_with_hash


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/controllable.coffee
+++ test/controllable.coffee
@@ -2,6 +2,7 @@

 test "should move player left while key is pressed", ->
   player = GameObject
+    x: 0

 module()


sadly it can't pass the test of Node.js

sadly it can't pass the test of Node.js

--- test/plist-reader.coffee
+++ test/plist-reader.coffee
@@ -4,7 +4,10 @@

 describe 'Plist reader test', ->
     it 'should parse xml correctly', (done)->
-        r = new plistReader 'Docsets/PHP.docset/Contents/Info.plist'
+        r = new plistReader 'Docsets/NodeJS_(v0.10.32).docset/Contents/Info.plist'
         r.parse().then (data)->
-            console.log data
+            data.should.have.property 'CFBundleIdentifier'
+            data.should.have.property 'CFBundleName'
+            data.should.have.property 'DocSetPlatformFamily'
+            data.should.have.property 'dashIndexFilePath'
             done()


Add missing test to natureBoost.

Add missing test to natureBoost.

--- test/pokemon_spec.coffee
+++ test/pokemon_spec.coffee
@@ -57,5 +57,8 @@
     it "returns 1.1 for natures that boost a certain stat", ->
       new Pokemon(nature: 'Adamant').natureBoost('attack').should.equal 1.1

+    it "returns 1.0 for natures do not affect a certain stat", ->
+      new Pokemon(nature: 'Adamant').natureBoost('speed').should.equal 1
+
     it "returns 0.9 for natures that decrease a certain stat", ->
       new Pokemon(nature: 'Timid').natureBoost('attack').should.equal 0.9


comment out livereload for now

comment out livereload for now

--- src/web/gulpfile.coffee
+++ src/web/gulpfile.coffee
@@ -58,7 +58,7 @@
   gulp.src(config.files.html.app)
     .pipe(plumber())
     .pipe(gulp.dest('./generated'))
-    .pipe(livereload())
+    #.pipe(livereload())
     .pipe(htmlmin(config.htmlmin))
     .pipe(gulp.dest('./dist'))

@@ -79,7 +79,7 @@
     ).pipe(plumber())
     .pipe(concat(config.output.jsApp))
     .pipe(gulp.dest('./generated'))
-    .pipe(livereload())
+    #.pipe(livereload())
     .pipe(ngmin())
     .pipe(uglify())
     .pipe(gulp.dest('./dist'))
@@ -89,7 +89,7 @@
     .pipe(plumber())
     .pipe(concat(config.output.jsVendor))
     .pipe gulp.dest('./generated')
-    .pipe(livereload())
+    #.pipe(livereload())
     .pipe(gulp.dest('./dist'))

 gulp.task 'css', ['install'], () ->
@@ -98,7 +98,7 @@
     .pipe(less())
     .pipe(concat(config.output.css))
     .pipe(gulp.dest('./generated'))
-    .pipe(livereload())
+    #.pipe(livereload())
     .pipe(cssmin())
     .pipe(gulp.dest('./dist'))


:green_heart: Fix broken tests

:green_heart: Fix broken tests

--- spec/minimap-spec.coffee
+++ spec/minimap-spec.coffee
@@ -6,6 +6,7 @@

     runs ->
       atom.workspaceView = new WorkspaceView
+      atom.config.set 'minimap.autoToggle', false

     waitsForPromise ->
       atom.workspaceView.open('sample.js')
@@ -16,18 +17,14 @@

   describe "when the minimap:toggle event is triggered", ->
     beforeEach ->
-      waitsForPromise ->
-        promise = atom.packages.activatePackage('minimap')
-        expect(atom.workspaceView.find('.minimap')).not.toExist()
-        atom.workspaceView.trigger 'minimap:toggle'
-        promise
+      waitsForPromise -> atom.packages.activatePackage('minimap')

     it "attaches and then detaches the view", ->
+      expect(atom.workspaceView.find('.minimap')).not.toExist()
+      atom.workspaceView.trigger 'minimap:toggle'
       expect(atom.workspaceView.find('.minimap')).toExist()
-      atom.workspaceView.trigger 'minimap:toggle'
-      expect(atom.workspaceView.find('.minimap')).not.toExist()

     it 'decorates the pane view with a with-minimap class', ->
+      expect(atom.workspaceView.find('.pane.with-minimap').length).toEqual(0)
+      atom.workspaceView.trigger 'minimap:toggle'
       expect(atom.workspaceView.find('.pane.with-minimap').length).toEqual(1)
-      atom.workspaceView.trigger 'minimap:toggle'
-      expect(atom.workspaceView.find('.pane.with-minimap').length).toEqual(0)


die when the subprocess dies

die when the subprocess dies

--- index.coffee
+++ index.coffee
@@ -11,6 +11,9 @@
   restart: =>
     @process?.kill 'SIGKILL'
     @process = spawn 'node', ['command.js'], stdio: 'inherit'
+    @process.on 'exit', (code, signal) =>
+      console.log 'process exited', code, signal
+      process.exit code unless signal == 'SIGKILL'

   onMessage: =>
     debug 'onMessage'


added usage message when query not set

added usage message when query not set

--- index.coffee
+++ index.coffee
@@ -7,7 +7,17 @@
 client_id1 = 'b45b1aa10f1ac2941910a7f0d10f8e28'
 client_id2 = 'a3e059563d7fd3372b49b37f00a00bcf'
 app = express()
+server = null
 app.get '/', (req, res) ->
+
+  unless req.query.s?
+    prefix = "http://#{server.address().address}:#{server.address().port}?s=username/"
+    res.send "usage:

+      #{prefix}tracks

+      or

+      #{prefix}favorites"
+    return
+
   res.set 'Content-Type', 'text/xml'
   console.log 'processing: ', "https://api.soundcloud.com/users/#{req.query.s}?client_id=#{client_id1}"

@@ -55,5 +65,5 @@
 port = process.env.OPENSHIFT_NODEJS_PORT or process.env.PORT or 8080
 ip = process.env.OPENSHIFT_NODEJS_IP or '127.0.0.1'

-http.createServer(app).listen port, ip, ->
-  console.log 'Example app listening at http://%s:%s', ip, port
+server = http.createServer(app).listen port, ip, ->
+  console.log "http://#{server.address().address}:#{server.address().port}?s=username/favorites"


O noes, test fail. Stub out the MTurk API properly

--- tests/admin_tests.coffee
+++ tests/admin_tests.coffee
@@ -29,7 +29,11 @@
 Tinytest.add "admin - create HIT for active batch", withCleanup (test) ->

   newHitId = Random.id()
-  TestUtils.mturkAPI.handler = (op, params) -> newHitId
+  TestUtils.mturkAPI.handler = (op, params) ->
+    switch op
+      when "CreateHIT" then newHitId
+      when "GetHIT" then { CreationTime: new Date } # Stub out the GetHIT call with some arbitrary data
+
   Batches.upsert batchId, $set: { active: true }

   # test


Added tests for withAguments and TerminalAccessible

--- tests/batman/view/filter_parsing_test.coffee
+++ tests/batman/view/filter_parsing_test.coffee
@@ -428,3 +428,31 @@
     helpers.render '

', {}, (node) ->
       equal node.html(), "bar"
       QUnit.start()
+
+asyncTest 'withArguments passes arguments to specified function and returns result', 2, ->
+  context =
+    foo: spy = createSpy()
+
+  helpers.render '', context, (node) ->
+    node[0].click()
+
+    ok spy.called
+    equal spy.lastCallArguments[0], 2
+    QUnit.start()
+
+asyncTest 'Pass arguments to accessor with Batman.TerminalAccessible', ->
+  class TestClass extends Batman.Object
+
+    @::col = ["a", "b", "c"]
+
+    @accessor 'accessible', ->
+      new Batman.TerminalAccessible (id) =>
+        debugger
+        return @col[id]
+
+  context = Batman
+    test: new TestClass
+
+  helpers.render '

', context, (node) ->
+    equal node[0].innerHTML, "b"
+    QUnit.start()


Add regression test

Add regression test

--- tests/batman/view/loop_rendering_test.coffee
+++ tests/batman/view/loop_rendering_test.coffee
@@ -468,15 +468,19 @@
     delay ->
       deepEqual dieVals, [['item.id', '4'], ['item.id', '5'], ['item.id', '6']]

-asyncTest 'it shouldn\'t break state if bound to undefined', 3, ->
+asyncTest 'it shouldn\'t break state if bound to undefined', ->
   source = '

'
   objects = new Batman.Set('a')

   helpers.render source, {objects}, (node, view) ->
     deepEqual getPs(view), ['a']
+    equal objects.event('itemsWereAdded').handlers.length, 1
+
     view.set('objects', undefined)
     delay ->
+      equal objects.event('itemsWereAdded').handlers.length, 0
       deepEqual getPs(view), []
+
       view.set('objects', objects)
       delay ->
         deepEqual getPs(view), ['a']


fix inline format not trigger event bug.

--- app/assets/javascripts/editor/formator.js.coffee
+++ app/assets/javascripts/editor/formator.js.coffee
@@ -18,7 +18,7 @@
   bold: ->
     if @canBold()
       @exec "bold"
-      @afterFormat()  unless @isCollapsed
+      @afterFormat() unless @isCollapsed()

   isItalic: ->
     @canItalic() and (document.queryCommandValue("italic") is "true" or document.queryCommandState("italic"))
@@ -29,7 +29,7 @@
   italic: ->
     if @canItalic()
       @exec "italic"
-      @afterFormat()  unless @isCollapsed
+      @afterFormat() unless @isCollapsed()

   isStrikeThrough: ->
     @canStrikeThrough() and (document.queryCommandValue("strikeThrough") is "true" or document.queryCommandState("strikeThrough"))
@@ -40,7 +40,7 @@
   strikeThrough: ->
     if @canStrikeThrough()
       @exec "strikeThrough"
-      @afterFormat()  unless @isCollapsed
+      @afterFormat() unless @isCollapsed()

   isUnderline: ->
     @canUnorderedList() and (document.queryCommandValue("underline") is "true" or document.queryCommandState("underline"))
@@ -51,7 +51,7 @@
   underline: ->
     if @canUnderline()
       @exec "underline"
-      @afterFormat()  unless @isCollapsed
+      @afterFormat() unless @isCollapsed()

   isOrderedList: ->
     @canOrderedList() and document.queryCommandValue("insertOrderedList") is "true"


tab link to external form

tab link to external form

--- app/assets/javascripts/partials/main-header.cjsx
+++ app/assets/javascripts/partials/main-header.cjsx
@@ -38,7 +38,11 @@
         }
         { # Page tabs:
           @props.pages?.map (page, key) =>
-            <Link key={key} to="/#{page.name.toLowerCase()}" activeClassName="selected" className="main-header-item">{page.name}</Link>
+            console.log 'page:', page
+            if page.key is 'feedback'
+              {page.name}
+            else
+              <Link key={key} to="/#{page.name.toLowerCase()}" activeClassName="selected" className="main-header-item">{page.name}</Link>
         }

         <Login />


Use a string to specify adapter

Use a string to specify adapter

--- app/assets/javascripts/rglossa/data/store.coffee
+++ app/assets/javascripts/rglossa/data/store.coffee
@@ -1,3 +1,3 @@
 App.Store = DS.Store.extend
   revision: 11
-  adapter: App.Adapter.create()
+  adapter: 'App.Adapter'


fix issue with hidden regrade tour overlay blocking quiz edit links

fixes CNVS-16719

test plan:
  - as a teacher
    - create a quiz

  - as a student
    - take the quiz

  - as a teacher
    - edit the quiz
    - the left side navigation links should all be clickable
    - edit the question to change the answer and regrade
    - the regrade tour should appear
    - close the regrade tour
    - the hidden overlay should still not be blocking the navigation links

Change-Id: I656de5f08c7c5696ff9f8e202e3e869e529cf1b0
Reviewed-on: https://gerrit.instructure.com/44411
Reviewed-by: Jason Madsen <bcb5fff571a20f07c35d17ba9c364855c776dce7@instructure.com>
Tested-by: Jenkins <d95b56ce41a2e1ac4cecdd398defd7414407cc08@instructure.com>
QA-Review: Trevor deHaan <85df72112e8a9484fec7b3db2e31789c2c2d4e07@instructure.com>
Product-Review: Derek DeVries <ff87a0776152510efd53bb1f4ea089dbbc90e730@instructure.com>

--- app/coffeescripts/views/tours/QuizRegrade.coffee
+++ app/coffeescripts/views/tours/QuizRegrade.coffee
@@ -9,7 +9,7 @@

     template: template

-    attach: ->
+    attachTour: ->
       $(document).one 'click', '.select_answer_link', =>
         setTimeout =>
           @tour.start()


Size of the iframe based on first child, otherwise IE makes it 500px wide.

--- app/js/jail_iframe/classes/control_iframe.coffee
+++ app/js/jail_iframe/classes/control_iframe.coffee
@@ -28,12 +28,12 @@
     @_sizeFrameToFitContent()

   _sizeFrameToFitContent: ->
-    @el.style.width = @frameBody.clientWidth  + 'px'
-    @el.style.height = @frameBody.clientHeight + 'px'
+    @el.style.width = @frameBody.firstChild.clientWidth  + 'px'
+    @el.style.height = @frameBody.firstChild.clientHeight + 'px'

     # Also resize the frame <html> itself for iOS Safari,
     # which resizes iframes themselves based on their inner size
-    @frameBody.parentElement.style.width = @frameBody.clientWidth  + 'px'
+    @frameBody.parentElement.style.width = @frameBody.firstChild.clientWidth  + 'px'

   fadeIn: ->
     @$el.addClass 'factlink-control-visible'


updates exponentiation to wrap base and power in expressions

--- math/expression_manipulation_spec.coffee
+++ math/expression_manipulation_spec.coffee
@@ -56,13 +56,14 @@
         expect(@new_exp.first()).toBeInstanceOf @components.exponentiation

       it "provides the exponentiation its base", ->
-        expect(@new_exp.first().base()).toBeAnEqualExpressionTo @exp_builder(10).first()
+        expect(@new_exp.first().base()).toBeAnEqualExpressionTo @exp_builder([10]).first()

     describe "on an expression that currently ends with an operator ", ->
       it "replaces the trailing operator", ->
         exp = @exp_builder(10, '+')
         new_exp = @manip.exponentiate_last.build().invoke(exp)
-        expect(new_exp).toBeAnEqualExpressionTo @exp_builder('^': [10, null])
+        expected = @exp_builder('^': [10, {open_expression: null}])
+        expect(new_exp).toBeAnEqualExpressionTo expected

     describe "on an expression that has a trailing exponent", ->
       it "manipulates expression correctly", ->
@@ -90,15 +91,26 @@
         expected = @exp_builder(open_expression: {open_expression: [8]})
         expect(exp).toBeAnEqualExpressionTo expected

-    describe "when the manipulation to be manipulated has an exponentiation ", ->
+    describe "when the manipulation to be manipulated has an exponentiation as its last element", ->
       describe "with no power", ->
         beforeEach ->
           @exp = @exp_builder('^': [10, null])

         it "inserts the number into the exponentiation", ->
           new_exp = @manip.append_number.build(value: 11).invoke(@exp)
-          expected = @exp_builder({'^': [10,11]})
+
+          expected = @exp_builder('^': [10, {open_expression: 11}])
           expect(new_exp).toBeAnEqualExpressionTo expected
+
+      describe "with a power", ->
+        beforeEach ->
+          @exp = @exp_builder('^': [10, 11])
+
+        it "inserts a multiplication and then the number", ->
+          new_exp = @manip.append_number.build(value: 12).invoke(@exp)
+          expected = @exp_builder({'^': [10,11]}, '*', 12)
+          expect(new_exp).toBeAnEqualExpressionTo expected
+

   describe "opening a new sub expression", ->
     it "adds a sub-expression to the expression", ->


Regression: window.screen return wrong value some time.

--- src/Browser/Browser.coffee
+++ src/Browser/Browser.coffee
@@ -7,27 +7,15 @@
     @element:  window.document.documentElement
     @body:     window.document.getElementsByTagName('body')[0]

-    @_height: ->
+    @height: ->
       @window.innerHeight   or
       @element.clientHeight or
       @body.clientHeight

-    @height: ->
-      if window.screen? and window.screen.availHeight?
-        return window.screen.availHeight
-      else
-        return @_height()
-
-    @_width: ->
+    @width: ->
       @window.innerWidth   or
       @element.clientWidth or
       @body.clientWidth
-
-    @width: ->
-      if window.screen? and window.screen.availWidth?
-        return window.screen.availWidth
-      else
-        return @_width()

     @haveTransform: ->
       return @testCSSProp('transform')


Remove delete period button

Remove delete period button

A teacher deleting a period is not supported.

--- src/components/course-settings/period-roster.cjsx
+++ src/components/course-settings/period-roster.cjsx
@@ -31,12 +31,6 @@
         <BS.Col sm=2>
           <AddStudentButton {...@props} />
         </BS.Col>
-        <BS.Col smOffset=8 sm=2>
-          <BS.Button block bsStyle='danger' className='btn-flat'>
-            <i className='fa fa-trash' />
-            Delete Period
-            </BS.Button>
-        </BS.Col>
       </BS.Row>
       <BS.Table striped bordered condensed hover className="roster">
         <thead>


ScrollView: passing lazyloadthreshold to customscrollview the right way

--- src/components/scrollview/customscrollview.coffee
+++ src/components/scrollview/customscrollview.coffee
@@ -9,9 +9,12 @@

   constructor:(options = {}, data)->

-    options.naturalScroll   ?= yes
-    options.cssClass         = KD.utils.curry 'kdcustomscrollview', options.cssClass
-    options.mouseWheelSpeed ?= 3
+    options.cssClass          = KD.utils.curry 'kdcustomscrollview', options.cssClass
+    options.mouseWheelSpeed  ?= 3
+
+    # we don't need it here but on the actual scrollview
+    {lazyLoadThreshold}       = options
+    options.lazyLoadThreshold = null

     super options, data

@@ -19,11 +22,13 @@

     @wrapper = new KDCustomScrollViewWrapper {
       tagName  : 'main'
+      lazyLoadThreshold
       mouseWheelSpeed
     }

     @verticalTrack   = new KDScrollTrack delegate : @wrapper
     @horizontalTrack = new KDScrollTrack delegate : @wrapper, type : 'horizontal'
+
     @wrapper.verticalThumb   = @verticalTrack.thumb
     @wrapper.horizontalThumb = @horizontalTrack.thumb


Unindent only if the tab is at the start of the line

--- src/selection.coffee
+++ src/selection.coffee
@@ -495,7 +495,7 @@
   outdentSelectedRows: ->
     [start, end] = @getBufferRowRange()
     buffer = @editor.buffer
-    leadingTabRegex = new RegExp("^ {1,#{@editor.getTabLength()}}|\t")
+    leadingTabRegex = new RegExp("^( {1,#{@editor.getTabLength()}}|\t)")
     for row in [start..end]
       if matchLength = buffer.lineForRow(row).match(leadingTabRegex)?[0].length
         buffer.delete [[row, 0], [row, matchLength]]


:art:

:art:

--- lib/package-manager.coffee
+++ lib/package-manager.coffee
@@ -171,7 +171,6 @@
       args.push '--themes'
     else if options.packages
       args.push '--packages'
-
     errorMessage = "Searching for \u201C#{query}\u201D failed."

     apmProcess = @runCommand args, (code, stdout, stderr) ->


Update panel markup

Update panel markup

`top` seems deprecated

--- lib/styleguide-view.coffee
+++ lib/styleguide-view.coffee
@@ -630,7 +630,7 @@
         @exampleSection 'panel', 'Panels', ->
           @p 'A container attached to some side of the Atom UI.'
           @exampleHtml '''
-            <atom-panel class='top'>
+            <atom-panel>
               Some content
             </atom-panel>
           '''
@@ -638,21 +638,17 @@
           @h2 'Inset Panel'
           @p 'Use inside a panel'
           @exampleHtml '''
-            <atom-panel class='top'>
-

-
Some inset content

-

+            <atom-panel class='padded'>
+
Some inset content

             </atom-panel>
           '''

           @h2 'With a heading'
           @exampleHtml '''
-            <atom-panel class='top'>
-

-

-
An inset-panel heading

-
Some Content

-

+            <atom-panel class='padded'>
+

+
An inset-panel heading

+
Some Content

             </atom-panel>
           '''


Reverse the config entries for editor.completions

They are returned in most specific -> least specific order, and we want the most
specific to win.

--- lib/symbol-provider.coffee
+++ lib/symbol-provider.coffee
@@ -119,6 +119,10 @@
     @config = {}
     allConfigEntries = @settingsForScopeDescriptor(scopeDescriptor, 'editor.completions')

+    # Config entries are reverse sorted in order of specificity. We want most
+    # specific to win; this simplifies the loop.
+    allConfigEntries.reverse()
+
     addedConfigEntry = false
     for {value} in allConfigEntries
       if Array.isArray(value)


Mute host guide link

Mute host guide link

--- client/ide/lib/views/chat/idechatsettingspane.coffee
+++ client/ide/lib/views/chat/idechatsettingspane.coffee
@@ -186,6 +186,8 @@
     kd.singletons.appManager.tell 'IDE', 'setInitialSessionSetting', 'readOnly', state

+  MUTE_HOST_GUIDE_LINK = 'http://learn.koding.com/guides/collaboration/#mute_host'
+
   createMuteHostSettingElements: ->

     @muteHostWrapper = new KDCustomHTMLView cssClass: 'wrapper mute-host'
@@ -198,6 +200,13 @@
     @muteHostWrapper.addSubView new KDLabelView
       title     : 'Participants can mute host'
       mousedown : toggle.bound 'mouseDown'
+
+    @muteHostWrapper.addSubView new KDCustomHTMLView
+      tagName    : 'a'
+      attributes :
+        href     : MUTE_HOST_GUIDE_LINK
+        target   : '_blank'
+      partial  : '(?)'

     @settings.addSubView @muteHostWrapper


teams: login remove logo if nothing uploaded

--- client/landing/site.landing/coffee/core/utils.coffee
+++ client/landing/site.landing/coffee/core/utils.coffee
@@ -328,6 +328,7 @@
       pattern    = geoPattern.generate(group.slug, generator: 'plusSigns').toDataUrl()
       logo.setCss 'background-image', pattern
       logo.setCss 'background-size', 'inherit'
+      logo.setClass 'hidden'

     return logo


Fix Model.find

Fix Model.find

--- src/marbles/model.js.coffee
+++ src/marbles/model.js.coffee
@@ -24,7 +24,7 @@
         options?.success?(instance)
         return instance

-    if !params.cid && (!options.hasOwnProperty('fetch') || options.fetch) && (!params.hasOwnProperty('fetch') || params.fetch)
+    if !params.hasOwnProperty('cid') && (!options.hasOwnProperty('fetch') || options.fetch) && (!params.hasOwnProperty('fetch') || params.fetch)
       @fetch(params, options)

     null


Fix backspace-at-index-0 behavior by ignoring negative start indices

--- src/modules/keyboard.coffee
+++ src/modules/keyboard.coffee
@@ -50,7 +50,7 @@
           @quill.deleteText(range.start, range.end, Quill.sources.USER)
         else
           start = if (hotkey.key == dom.KEYS.BACKSPACE) then range.start - 1 else range.start
-          @quill.deleteText(start, start + 1, Quill.sources.USER)
+          @quill.deleteText(start, start + 1, Quill.sources.USER) if start >= 0
       return false
     )


:lipstick:

:lipstick:

--- space-pen-spec.coffee
+++ space-pen-spec.coffee
@@ -3,7 +3,7 @@

   describe "View objects", ->
     beforeEach ->
-      Subview = class extends View
+      class Subview extends View
         @content: (params, otherArg) ->
           @div =>
             @h2 { outlet: "header" }, params.title + " " + otherArg
@@ -12,7 +12,7 @@
         initialize: (args...) ->
           @initializeCalledWith = args

-      TestView = class extends View
+      class TestView extends View
         @content: (params, otherArg) ->
           @div keydown: 'viewClicked', class: 'rootDiv', =>
             @h1 { outlet: 'header' }, params.title + " " + otherArg
@@ -98,7 +98,7 @@
         contentCalledWith = null
         initializeCalledWith = null

-        TestView = class extends View
+        class TestView extends View
           @content: (params) ->
             contentCalledWith = params
             @div()
@@ -112,7 +112,7 @@
         expect(initializeCalledWith).toEqual {}

       it "throws an exception if the view has more than one root element", ->
-        BadView = class extends View
+        class BadView extends View
           @content: ->
             @div id: 'one'
             @div id: 'two'


Give the UI more time to load the preview runtime

--- spec/EditGraph.coffee
+++ spec/EditGraph.coffee
@@ -20,8 +20,11 @@
         chai.expect(search.classList.contains('overlay')).to.equal false
         done()
       , 500
-    it 'should initially show results', ->
-      chai.expect(search.results.length).to.be.above 10
+    it 'should initially show results', (done) ->
+      setTimeout ->
+        chai.expect(search.results.length).to.be.above 10
+        done()
+      , 1800
     it 'should narrow them down when something is written', (done) ->
       input = search.shadowRoot.querySelector '#search'
       Syn.click(input)


spec: asar: fs.readdirSync

spec: asar: fs.readdirSync

--- spec/asar-spec.coffee
+++ spec/asar-spec.coffee
@@ -147,3 +147,19 @@
         stats = fs.lstat p, (err, stats) ->
           assert.equal err.code, 'ENOENT'
           done()
+
+    describe 'fs.readdirSync', ->
+      it 'reads dirs from root', ->
+        p = path.join fixtures, 'asar', 'a.asar'
+        dirs = fs.readdirSync p
+        assert.deepEqual dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2']
+
+      it 'reads dirs from a normal dir', ->
+        p = path.join fixtures, 'asar', 'a.asar', 'dir1'
+        dirs = fs.readdirSync p
+        assert.deepEqual dirs, ['file1', 'file2', 'file3', 'link1', 'link2']
+
+      it 'reads dirs from a linked dir', ->
+        p = path.join fixtures, 'asar', 'a.asar', 'link2', 'link2'
+        dirs = fs.readdirSync p
+        assert.deepEqual dirs, ['file1', 'file2', 'file3', 'link1', 'link2']


added test for hy

added test for hy

--- spec/languages.coffee
+++ spec/languages.coffee
@@ -613,4 +613,21 @@
       mixed: 0
       empty: 0
     }
+    {
+      names: ["hy"]
+      code:
+        """
+        (print "Hy!");comment
+        ; on line comment
+        (.strip " foo   ")
+        ;;; comment
+        """
+      comment: 3
+      source: 2
+      block: 0
+      single: 3
+      total: 4
+      mixed: 1
+      empty: 0
+    }
   ]


Suppress the isTTY spec, not reliable on some machines

--- spec/node-spec.coffee
+++ spec/node-spec.coffee
@@ -138,5 +138,6 @@
     it 'should not throw exception', ->
       process.stdout

-    it 'should have isTTY defined', ->
+    # Not reliable on some machines
+    xit 'should have isTTY defined', ->
       assert.equal typeof(process.stdout.isTTY), 'boolean'


Updated documentation for spec helper function.

--- spec/preparser.coffee
+++ spec/preparser.coffee
@@ -38,7 +38,7 @@

 # Helper function for expecting errors to be thrown when parsing.
 #
-# @param source [String] A GSS expression.
+# @param source [String] GSS statements.
 # @param message [String] This should be provided when a rule exists to catch
 # invalid syntax, and omitted when an error is expected to be thrown by the PEG
 # parser.


Fix autocomplete to work for game|db|ui snippet owners

--- app/views/play/level/tome/editor/snippets.coffee
+++ app/views/play/level/tome/editor/snippets.coffee
@@ -136,7 +136,7 @@

     beginningOfLine = session.getLine(pos.row).substring(0,pos.column - prefix.length)

-    unless (fullPrefixParts.length < 3 and /^(hero|self|this|@)$/.test(fullPrefixParts[0]) ) or /^\s*$/.test(beginningOfLine)
+    unless (fullPrefixParts.length < 3 and /^(hero|self|this|@|db|game|ui)$/.test(fullPrefixParts[0]) ) or /^\s*$/.test(beginningOfLine)
       # console.log "DEBUG: autocomplete bailing", fullPrefixParts, '|', prefix, '|', beginningOfLine, '|', pos.column - prefix.length
       @completions = completions
       return callback null, completions


cmd.coffeeのhipchat対応部分は、hipchatでの検証ができてないので一旦OFFに

--- cmd.coffee
+++ cmd.coffee
@@ -105,6 +105,11 @@
     switch type
       when "slack"
         @sm.send target, '', @sm.slack_attachments(title, message, color)
+      # when "hipchat"
+      #   console.log "hipchat"
+      #   console.log title
+      #   @sm.send target, title,   color
+      #   @sm.send target, message, color
       else
         # @sm.send target, title,   color
         # @sm.send target, message, color


Removed usage of bindMeteor.

Removed usage of bindMeteor.

--- src/TaskScheduler.coffee
+++ src/TaskScheduler.coffee
@@ -1,5 +1,3 @@
-bindMeteor = Meteor.bindEnvironment.bind(Meteor)
-
 class TaskScheduler

   constructor: (options) ->
@@ -26,10 +24,10 @@
       @pauseDf = null
     runDuration = @options.runDuration
     Logger.debug('Task scheduler running for ' + runDuration + 'ms...')
-    @waitHandle = setTimeout (bindMeteor => @_wait()), @options.runDuration
+    @waitHandle = setTimeout (Meteor.bindEnvironment => @_wait()), @options.runDuration

     @status = 'running'
-    runNext = bindMeteor =>
+    runNext = Meteor.bindEnvironment =>
       if @bufferQueue.length == 0
         @runDf.resolve()
         @reset()


FIX: Update quality rating after modal assessment

--- src/app/tasks/task-viewer/task-viewer.coffee
+++ src/app/tasks/task-viewer/task-viewer.coffee
@@ -98,14 +98,20 @@
         max: newTask.definition.max_quality_pts
         assigned: newTask.quality_pts
       }
-      # Only show the quality stars when the student has them
-      $scope.qualityStars.show = $scope.qualityStars.assigned > 0

     #
-    # Watch grade for changes
+    # Watch grade for changes after modal asssmeent
     #
     $scope.$watch 'project.selectedTask.grade', ->
       $scope.taskIsGraded = taskService.taskIsGraded $scope.project.selectedTask
+
+    #
+    # Watch quality rating for changes after modal assessment
+    #
+    $scope.$watch 'project.selectedTask.quality_pts', (newPts) ->
+      $scope.qualityStars.assigned = newPts
+      # Only show the quality stars when the student has them
+      $scope.qualityStars.show = $scope.qualityStars.assigned > 0

     #
     # Loading the active task


When you delete everything about a chapter, delete the chapter.

--- src/bootstrap-elm.coffee
+++ src/bootstrap-elm.coffee
@@ -51,31 +51,48 @@
   headingEditorElemId = "edit-chapter-heading-#{chapterId}"
   bodyEditorElemId    = "edit-chapter-body-#{chapterId}"

+  # If you delete the chapter's body and heading, assume you want it gone.
+  # (If you didn't, you can just re-add it; there couldn't have been data loss.)
+  wasChapterRemoved = (words, mutations) ->
+    # Returns true iff there's no text content in either the body or the heading
+    words == 0 &&
+      # Don't do this unless nodes were removed; otherwise we can get false
+      # positives while the chapter is being added, causing it to be deleted. :(
+      (mutations.some ({removedNodes}) -> removedNodes.length > 0) &&
+      !document.getElementById(headingEditorElemId).textContent.match(/\S/) &&
+      !document.getElementById(bodyEditorElemId).textContent.match(/\S/)
+
   editorHeadingPromise = setUpEditor headingEditorElemId, chapter.heading, false, (mutations, node) ->
     sync.getCurrentDoc().done (doc) ->
       heading = node.textContent
+
       chapter.heading = heading
       chapter.words   = countWords heading

-      sync.saveDoc(doc).done -> app.ports.updateChapter.send chapter
+      if wasChapterRemoved chapter.words, mutations
+        deleteChapter chapter
+      else
+        sync.saveDoc(doc).done -> app.ports.updateChapter.send chapter

   editorBodyPromise = new Promise (resolve, reject) ->
     sync.getSnapshot(chapter.snapshotId).done (snapshot) ->
       setUpEditor bodyEditorElemId, snapshot.html, true, (mutations, node) ->
-        snapshotId = chapter.snapshotId
-        html       = node.innerHTML
-        text       = node.textContent
-
-        sync.getCurrentDoc().done (doc) ->
-          sync.saveSnapshot({id: snapshotId, html})
-            .then (->
-                app.ports.putSnapshot.send {id: snapshotId, html, text}
-                chapter.words = countWords html
-
-                app.ports.updateChapter.send chapter
-
-                resolve()
-              ), reject
+        snapshotId    = chapter.snapshotId
+        html          = node.innerHTML
+        text          = node.textContent
+        chapter.words = countWords text
+
+        if wasChapterRemoved chapter.words, mutations
+          deleteChapter chapter
+        else
+          sync.getCurrentDoc().done (doc) ->
+            sync.saveSnapshot({id: snapshotId, html})
+              .then (->
+                  app.ports.putSnapshot.send {id: snapshotId, html, text}
+                  app.ports.updateChapter.send chapter
+
+                  resolve()
+                ), reject

   Promise.all [editorHeadingPromise, editorBodyPromise]

@@ -164,6 +181,10 @@
   chapterHeading = document.getElementById("edit-chapter-heading-#{chapterId}")

   editorFrame.scrollTop = chapterHeading.offsetTop - editorHeader.offsetHeight
+
+deleteChapter = (chapter) ->
+  sync.deleteChapter(chapter).done (newChapters) ->
+    app.ports.setChapters.send newChapters

 app.ports.setCurrentDocId.subscribe (newDocId) ->
   if newDocId?


Fix file version

Fix file version

--- lms/static/coffee/src/discussion/utils.coffee
+++ lms/static/coffee/src/discussion/utils.coffee
@@ -249,7 +249,10 @@
           $3
       else if RE_DISPLAYMATH.test(text)
         text = text.replace RE_DISPLAYMATH, ($0, $1, $2, $3) ->
-          processedText += $1 + processor("$$" + $2 + "$$", 'display')
+          #processedText += $1 + processor("$$" + $2 + "$$", 'display')
+          #bug fix, ordering is off
+          processedText =  processor("$$" + $2 + "$$", 'display') + processedText
+          processedText = $1 + processedText
           $3
       else
         processedText += text


Fixed reply modal test

Fixed reply modal test

--- karma/test-modals.coffee
+++ karma/test-modals.coffee
@@ -174,7 +174,7 @@
   )

   it('ReplyModalController', () ->
-    $controller('ReplyModalController', {$scope: $scope, $uibModalInstance: modalInstance, maxLength: 10})
+    $controller('ReplyModalController', {$scope: $scope, $uibModalInstance: modalInstance, selection: null, maxLength: 10})

     expect($scope.fields.text).toEqual({val: "", maxLength: 10})


fixed cloning error

fixed cloning error

--- platform/src/gamEvolve.coffee
+++ platform/src/gamEvolve.coffee
@@ -177,9 +177,14 @@

     compiledParams[paramName] = GE.compileParameter(paramValue, constants, bindings)
     value = compiledParams[paramName].get()
-    # Let undefined values go through. Otherwise there is no way for missing parameters to be passed.
+
+    # Let undefined or non-serializable values go through.
+    # Otherwise there is no way for missing parameters, or native components to be passed.
     # TODO: Could be source of silent errors
-    evaluatedParams[paramName] = if typeof(value) isnt 'undefined' then GE.cloneData(value) else value
+    try
+      evaluatedParams[paramName] = GE.cloneData(value)
+    catch e
+      evaluatedParams[paramName] = value

   locals =
     params: evaluatedParams


quick fixes

quick fixes

--- console/coverage.coffee
+++ console/coverage.coffee
@@ -39,9 +39,10 @@
   native_stats

 print_usage = (stats) ->
-  names = (name for name,count of stats)
+  names = (name for name of stats)
   names.sort (a, b) -> stats[b] - stats[a]
   console.log stats[name], name for name in names
+  return

 print_unused = (stats, stats_name) ->
   unused_count = 0


fixed Gruntfile to point to docs/

fixed Gruntfile to point to docs/

--- bokehjs/Gruntfile.coffee
+++ bokehjs/Gruntfile.coffee
@@ -1,3 +1,4 @@
+
 module.exports = (grunt) ->
   fs = require("fs")

@@ -199,7 +200,7 @@
       server:
         options:
           port: 8000,
-          base: 'build/'
+          base: 'docs/'

     qunit:
       all:


adding eco

adding eco

--- bokehjs/Gruntfile.coffee
+++ bokehjs/Gruntfile.coffee
@@ -153,8 +153,8 @@
   grunt.loadNpmTasks("grunt-contrib-qunit")
   grunt.loadNpmTasks("grunt-eco")

-  grunt.registerTask("default",    ["coffee", "less", "copy", "qunit"])
-  grunt.registerTask("build",      ["coffee", "less", "copy"])
+  grunt.registerTask("default",    ["build", "qunit"])
+  grunt.registerTask("build",      ["coffee", "less", "copy", "eco"])
   grunt.registerTask("deploy",     ["build",  "requirejs:dist", "clean"])
   grunt.registerTask("devdeploy",  ["build",  "requirejs:dev",  "clean"])


Fix docsFor and printDef when file fails to load

Now the drawback is possible extra time spent spawning another idris
process, but at least the old process gets cleaned up.

--- lib/idris-controller.coffee
+++ lib/idris-controller.coffee
@@ -132,6 +132,7 @@
       .load uri
       .filter ({ responseType }) -> responseType == 'return'
       .flatMap => @model.docsFor word
+      .catch (e) => @model.docsFor word
       .subscribe successHandler, @displayErrors

   getTypeForWord: ({ target }) =>
@@ -369,6 +370,7 @@
       .load uri
       .filter ({ responseType }) -> responseType == 'return'
       .flatMap => @model.printDefinition word
+      .catch (e) => @model.printDefinition word
       .subscribe successHandler, @displayErrors

   openREPL: ({ target }) =>


handle no project folder case

handle no project folder case

--- lib/connection/process.coffee
+++ lib/connection/process.coffee
@@ -38,13 +38,17 @@

   script: (s...) -> @packageDir 'script', s...

-  # spawn Julia in the first open project folder (or its parent folder for files)
   workingDir: ->
     paths = atom.workspace.project.getDirectories()
-    if fs.statSync(paths[0].path).isFile()
-      path.dirname paths[0].path
+    if paths.length > 0
+      # spawn Julia in the first open project folder (or its parent folder for files)
+      if fs.statSync(paths[0].path).isFile()
+        path.dirname paths[0].path
+      else
+        paths[0].path
     else
-      paths[0].path
+      # or in HOME if there are no open project folders
+      process.env.HOME || process.env.USERPROFILE

   jlpath: ->
     p = atom.config.get("julia-client.juliaPath")


remove debug statement

remove debug statement

Signed-off-by: Tim Perry <5ee0edb9e2229c0838f1959779f1949031de0123@resin.io>

--- lib/models/application.coffee
+++ lib/models/application.coffee
@@ -143,8 +143,6 @@
 	###
 	exports.get = (nameOrId, options = {}, callback) ->
 		callback = findCallback(arguments)
-
-		console.log('OPTIONS', options)

 		Promise.try ->
 			if not nameOrId?


Allow for the ability to set cmd line arguments

--- lib/simple-flake8-view.coffee
+++ lib/simple-flake8-view.coffee
@@ -14,12 +14,16 @@
   ignoreErrors = atom.config.get "simple-flake8.ignoreErrors"
   mcCabeComplexityThreshold = atom.config.get "simple-flake8.mcCabeComplexityThreshold"
   flake8cmd = atom.config.get "simple-flake8.flake8Command"
+  flake8params = atom.config.get "simple-flake8.cmdLineArguments"
   console.log(flake8cmd)
   if ignoreErrors
     params.push("--ignore=#{ ignoreErrors }")

   if mcCabeComplexityThreshold
     params.push("--max-complexity=#{ mcCabeComplexityThreshold }")
+
+  if flake8params
+    params.push(flake8params)

   proc = process.spawn flake8cmd, params

@@ -65,6 +69,9 @@
       type: "boolean"
       default: false
     mcCabeComplexityThreshold:
+      type: "string"
+      default: ""
+    cmdLineArguments:
       type: "string"
       default: ""
     validateOnSave:


removed redundant wrapping of mesh in object

--- app/vis.coffee
+++ app/vis.coffee
@@ -76,7 +76,11 @@
             transparent: false,
             color: 'rgb(10, 10, 10)'
         }))
-        new THREE.Mesh(geometry, material)
+        # material.transparent = true
+        # material.opacity = 0.1
+        material.uniforms.opacity.value = 1.0
+        mesh = new THREE.Mesh(geometry, material)
+        mesh

     processChain = (chain) ->
         chain.map (obj, i, array) ->
@@ -91,12 +95,13 @@
                 obj.prev_connector_index = prev_idx
             obj

-    getTextObject: (geometry) ->
-        mesh = @getTextMesh(geometry)
-        textAnchor = new THREE.Object3D()
-        textAnchor.add(mesh)
-        textAnchor.scale.multiplyScalar(-1)
-        textAnchor
+    # DEPRECATED
+    # getTextObject: (mesh) ->
+    #     # mesh = @getTextMesh(geometry)
+    #     textAnchor = new THREE.Object3D()
+    #     textAnchor.add(mesh)
+    #     textAnchor.scale.multiplyScalar(-1)
+    #     textAnchor

     getLineObject: (_line, index) =>
         line_geometry = @getTextGeometry(_line.line)
@@ -105,9 +110,10 @@

         letterObjects = _line.line.split("").map (letter, index) =>
             letter_geom = @getTextGeometry(letter)
-            letter_object = @getTextObject(letter_geom)
-            letter_object.position.x = - glyph_positions[index][0]
-            letter_object
+            letter_mesh = @getTextMesh(letter_geom)
+            letter_mesh.scale.multiplyScalar(-1)
+            letter_mesh.position.x = - glyph_positions[index][0]
+            letter_mesh

         # TODO: Pack up words...


...and forgot the basicAI also

...and forgot the basicAI also

--- basicAI.coffee
+++ basicAI.coffee
@@ -271,6 +271,7 @@
     "Explorer"
     "Woodcutter"
     "Chancellor"
+    "Counting House"
     "Coppersmith" if my.countInHand("Copper") >= 2
     # Play an Ambassador if our hand has something we'd want to discard.
     #


propagate scope name to the kernel instance

--- library/nucleus/kernel.coffee
+++ library/nucleus/kernel.coffee
@@ -464,6 +464,7 @@
         bare = "Running without Forever supervision"
         supd = "Running using %s mode within Forever"
         assert not _.isEmpty(tag), missing.toString()
+        assert @tag = @env = @environment = tag or null
         assert @scope = try scoping.Scope.lookup tag
         assert this.scope.incorporate this, undefined
         logger.warn bare.toString().red unless mode


a couple of loader minors

a couple of loader minors

--- library/nucleus/loader.coffee
+++ library/nucleus/loader.coffee
@@ -46,9 +46,9 @@
     assert scanSync = fs.readdirSync if shallow
     scanned = scanSync directory.toString()
     supported = _.filter scanned, isSupported
-    modules = _.map supported, ingest
-    symbols = _.map supported, sym
-    _.object symbols, modules
+    modules = try _.map supported, ingest
+    symbols = try _.map supported, sym
+    return _.object symbols, modules

 # This method is the base method for very important functionality.
 # It scans the supplied directory, find all the packages there and


change level to debug

change level to debug

--- library/nucleus/scaled.coffee
+++ library/nucleus/scaled.coffee
@@ -160,7 +160,7 @@
         assert proxy = queue.shift(); queue.push proxy
         a = "#{proxy.target.host}:#{proxy.target.port}"
         assert a = "#{a.toLowerCase().underline.yellow}"
-        logger.info "Proxy %s request %s to %s", x, u, a
+        logger.debug "Proxy %s request %s to %s", x, u, a
         return proxy.proxyRequest request, response

     # Create and launch a Seaport server in the current kernel. It


Activity: right boxes cleanup

Activity: right boxes cleanup

--- client/Social/Activity/ContentDisplays/ActivityRightBlock.coffee
+++ client/Social/Activity/ContentDisplays/ActivityRightBlock.coffee
@@ -1,5 +1,7 @@
 class ActivityRightBase extends JView
+
   constructor:(options={}, data)->
+
     super options, data

     @tickerController = new KDListViewController
@@ -11,9 +13,12 @@

     @tickerListView = @tickerController.getView()

+
   renderItems: (err, items=[])->
+
     @tickerController.hideLazyLoader()
     @tickerController.addItem item for item in items  unless err
+

   pistachio:->
     """
@@ -24,8 +29,15 @@
     """

 class ActiveUsers extends ActivityRightBase
+
+
   constructor:(options={}, data)->
-    @itemClass = ActiveUserItemView
+
+    @itemClass       = ActiveUserItemView
+    options.title    = "Active Koders"
+    options.cssClass = "active-users"
+
+    super options, data

     @showAllLink = new KDCustomHTMLView
       tagName : "a"
@@ -34,15 +46,17 @@
       click   : (event) -> KD.singletons.router.handleRoute "/Members"
     , data

-    options.title    = "Active Koders"
-    options.cssClass = "active-users"
-    super options, data
-
     KD.remote.api.ActiveItems.fetchUsers {}, @bound 'renderItems'

 class ActiveTopics extends ActivityRightBase
+
   constructor:(options={}, data)->
-    @itemClass = ActiveTopicItemView
+
+    @itemClass       = ActiveTopicItemView
+    options.title    = "Popular Topics"
+    options.cssClass = "active-topics"
+
+    super options, data

     @showAllLink = new KDCustomHTMLView
       tagName : "a"
@@ -51,9 +65,4 @@
       click   : (event) -> KD.singletons.router.handleRoute "/Topics"
     , data

-    options.title    = "Popular Topics"
-    options.cssClass = "active-topics"
-
-    super options, data
-
     KD.remote.api.ActiveItems.fetchTopics {}, @bound 'renderItems'