Don't use random values in a unit test case.

--- test/unit/modelingSpec.coffee
+++ test/unit/modelingSpec.coffee
@@ -8,11 +8,11 @@
         sessions: [
           acquisition_date: new Date
           modeling:
-            v_e: Math.random()
-            tau_i: Math.random()
-            fxl_k_trans: Math.random()
-            fxr_k_trans: Math.random()
-            delta_k_trans: Math.random()
+            v_e: 2.4
+            tau_i: 0.1
+            fxl_k_trans: 2.3
+            fxr_k_trans: 2.1
+            delta_k_trans: 0.2
           number: 1
         ]


atom config update

atom config update

--- atom/config.cson
+++ atom/config.cson
@@ -41,6 +41,9 @@
     userId: "ceb72210-3bbf-ef71-d8fd-ac9521b8fc8b"
   "file-icons":
     coloured: false
+  "git-plus":
+    general:
+      _analyticsUserId: "885f78b0-1cd7-45f0-a6f6-895aca468599"
   "highlight-selected":
     showInStatusBar: false
   "julia-client":


Don't auto-indent JSX; it doesn't work right

--- atom/config.cson
+++ atom/config.cson
@@ -34,8 +34,7 @@
   "git-plus": {}
   "incremental-search":
     instantSearch: true
-  "language-babel":
-    autoIndentJSX: true
+  "language-babel": {}
   linter:
     showErrorTabLine: true
   "linter-eslint":


Update atom config

Update atom config

--- atom/config.cson
+++ atom/config.cson
@@ -14,6 +14,7 @@
     fontSize: 18
     showIndentGuide: true
     showInvisibles: true
+    softWrap: true
   "exception-reporting":
     userId: "abe57ba3-7bca-4173-bea9-84fc720fd106"
   "linter-php":


don't clobber colors

don't clobber colors

--- src/graph.coffee
+++ src/graph.coffee
@@ -16,8 +16,7 @@
     x_axis = d3.svg.axis().scale(x).orient('bottom')
     y_axis = d3.svg.axis().scale(y).orient('left')

-    colors = params.d3_colors ? colors.d3.category10
-    color = d3.scale.ordinal().range colors
+    color = d3.scale.ordinal().range params.d3_colors ? colors.d3.category10

     area_opacity = params.areaAlpha ? 1.0
     line_opacity = 1.0


Implement basic deforestation

Implement basic deforestation

--- src/hello.coffee
+++ src/hello.coffee
@@ -72,10 +72,11 @@
   cameraTopLeft.sampledBy(clicks, (cam, click) ->
     [cam[0] + click[0], cam[1] + click[1]])
                .onValue (pos) ->
-                  GameState.mutate "terraforming", (state) ->
+                  GameState.mutate "deforestation", (state) ->
                     return unless pos[0] >= 0
                     return unless pos[1] >= 0
                     return unless pos[1] < state.world.length
                     return unless pos[0] < state.world[pos[1]].length
+                    return unless state.world[pos[1]][pos[0]] is 2
                     state.world[pos[1]][pos[0]] = 1


When saving data always return new object

--- src/index.coffee
+++ src/index.coffee
@@ -134,7 +134,7 @@
           return after false

         @close() if @_closeAfterRequest is true
-        after if params._id? then params else results[0]
+        after results

   closeAfterRequest: (value) ->
     @_closeAfterRequest = value


TODO  정리

TODO  정리

--- src/index.coffee
+++ src/index.coffee
@@ -321,6 +321,12 @@

+###
+같은 명령 + 같은 데이터 = 단일 명령 - 없어도 되
+같은 명령 + 다른 데이터 = SIMD
+다른 명령 + 같은 데이터 = MISD - 그닥 쓸모가...
+다른 명령 + 다른 데이터 = MIMD
+###

 ficent = (args...)->
   ficent.flow args...


fix media preview

fix media preview

--- MediaAdminBundle/Resources/public/coffee/GalleryView.coffee
+++ MediaAdminBundle/Resources/public/coffee/GalleryView.coffee
@@ -68,6 +68,6 @@
     modalContainer = @$el.closest(".mediaModalContainer")
     intputName = modalContainer.data('input')
     $('#' + intputName).val @options.media.id
-    $('#previewImage_' + intputName).attr 'src', @$el.find('.superbox-img').attr('src')
+    $('#previewImage_' + intputName).attr 'src', @$el.find('.superbox-img img').attr('src')
     modalContainer.find('.mediaModalClose').click()
 )


Made shotguns actually damage enemies

Made shotguns actually damage enemies

--- src/items.coffee
+++ src/items.coffee
@@ -98,6 +98,7 @@
 					for target in targets
 						emit 'game.creature.fire.hit.creature',
 							creature, @, dir, target
+						target.damage 10, creature

 				else
 					emit 'game.creature.fire.hit.none', creature, @, dir


delete duplicate tests introduced by previous commit

--- tests/batman/view_test.coffee
+++ tests/batman/view_test.coffee
@@ -354,14 +354,6 @@
       names = names.toArray()
       deepEqual names, ['foo', 'bar', 'baz']

-asyncTest 'it should continue to render nodes after the loop', 1, ->
-  source = '

'
-  objects = new Batman.Set('foo', 'bar', 'baz')
-
-  render source, false, {bar: objects, foo: "qux"}, (node) ->
-    delay => equal 'qux', $('span', node).html(), "Node after the loop is also rendered"
-
-
 asyncTest 'it should render new items as they are added', ->
   source = '

'
   objects = new Batman.Set('foo', 'bar')
@@ -412,22 +404,6 @@
       names = $('p', view.get('node')).map -> @innerHTML
       names = names.toArray()
       deepEqual names, ['zero', 'foo', 'bar']
-
-asyncTest 'it should allow simple loops', ->
-  source = '

'
-  objects = new Batman.Set('foo', 'bar', 'baz')
-
-  render source, {objects}, (node, view) ->
-    delay => # new renderer's are used for each loop node, must wait longer
-      tracking = {foo: false, bar: false, baz: false}
-      node = $(view.get('node')).children()
-      for i in [0...node.length]
-        # We must track these in a temp object because they are a set => undefined order, can't assume
-        tracking[node[i].innerHTML] = true
-        equal node[i].className,  'present'
-
-      for k in ['foo', 'bar', 'baz']
-        ok tracking[k], "Object #{k} was found in the source"

 asyncTest 'the ready event should wait for all children to be rendered', ->
   source = '

'


#730 - A user is able to add the 'username' meta question

--- jsapp/xlform_model_view/model.configs.coffee
+++ jsapp/xlform_model_view/model.configs.coffee
@@ -38,6 +38,14 @@
       asJson:
         type: "today"
         name: "today"
+    username:
+      name: "username"
+      label: "username"
+      description: "includes interviewer's username"
+      default: false
+      asJson:
+        type: "username"
+        name: "username"
     simserial:
       name: "simserial"
       label: "sim serial"


fixes #52, config.path works mostly

fixes #52, config.path works mostly

--- src/jscpd.coffee
+++ src/jscpd.coffee
@@ -10,6 +10,7 @@
 {Detector} = require './detector'
 {Strategy} = require './strategy'
 {Report} = require './report'
+

 class jscpd

@@ -38,19 +39,35 @@
     for key, value of options
       if value is not null then optionsNew[key] = value

+    # TODO:
+    # the best thing to do would be to change from using `path`
+    # so that we can differentiate between the cwd and a passed path
+
+    # --------------------------------------------------------------
+    # heuristic - use config.path if options.path is absolute (not passed)
+    # this means that you can't override the configuration file path
+    # with an absolute --path on the command line
+    # Conf    Options
+    #   X         X     - use options.path if not abs, else use config.path
+    #   O         X     - use options.path, passed (or cwd)
+    #   X         O     - use config.path, assume abs path means not passed
+    #   O         O     - use options.path which will be cwd as fallback
+    # console.log(Object.keys(path));
+    # if config.path and not path.isAbsolute(options.path)
+    #   optionsNew.path = config.path
+    # ---------------------------------------------------------------
+    # Scratch the above comment, if we have config.path, we use it.
+
+    if config.path
+      optionsNew.path = config.path
+
     if typeof optionsNew.languages is 'string' then optionsNew.languages = optionsNew.languages.split ','

-    if config.path
-      optionsNew.path = path.normalize "#{options.path}/#{config.path}"
-      cwd = options.path
-
     optionsNew.extensions = TokenizerFactory::getExtensionsByLanguages(optionsNew.languages)
-
     return optionsNew

-  run: (options)->
-    cwd = options.path
-    config = @readConfig("#{cwd}/.cpd.yaml") || @readConfig("#{cwd}/.cpd.yml") || {}
+  run: (options) ->
+    config = @readConfig(".cpd.yaml") || @readConfig(".cpd.yml") || {}
     options = @prepareOptions options, config

     logger.profile 'Files search time:'
@@ -79,14 +96,15 @@
     excluded_files = []

     _.forEach patterns, (pattern) ->
-      files = _.union files, glob.sync(pattern, cwd: cwd)
+      files = _.union files, glob.sync(pattern, cwd: options.path)

+    # console.log(files);
     if excludes.length > 0
       _.forEach excludes, (pattern) ->
-        excluded_files = _.union excluded_files, glob.sync(pattern, cwd: cwd)
+        excluded_files = _.union excluded_files, glob.sync(pattern, cwd: options.path)

     files = _.difference files, excluded_files
-    files = _.map files, (file) -> path.normalize "#{cwd}/#{file}"
+    files = _.map files, (file) -> path.normalize "#{options.path}/#{file}"

     logger.profile 'Files search time:'
     if options.debug


Remove --harmony_collections from test command

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -32,7 +32,7 @@

     shell:
       test:
-        command: 'node --harmony_collections node_modules/.bin/jasmine-focused --coffee --captureExceptions spec'
+        command: 'node node_modules/.bin/jasmine-focused --coffee --captureExceptions spec'
         options:
           stdout: true
           stderr: true


Added test:ci:faster grunt task

Added test:ci:faster grunt task

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -51,6 +51,7 @@
   grunt.registerTask 'test:firefox:faster', 'Sets up and runs the tests in Firefox', ['sanity', 'test:conf', 'express:inline', 'curl-dir:downloadfiles', 'parallel_spec_runner:appsp:firefox']
   grunt.registerTask 'test:server', "Starts a Jasmine server at localhost:#{serverPort}, specify a different port with --port=<port>", ['express:server', 'express-keepalive']
   grunt.registerTask 'test:ci', 'Runs the tests in both firefox and chrome', ['sanity', 'test:conf', 'express:inline', 'curl-dir:downloadfiles', 'webdriver_jasmine_runner:chrome', 'webdriver_jasmine_runner:firefox']
+  grunt.registerTask 'test:ci:faster', 'Runs the tests in both firefox and chrome', ['sanity', 'test:conf', 'express:inline', 'curl-dir:downloadfiles', 'parallel_spec_runner:appsp:chrome', 'parallel_spec_runner:appsp:firefox']

   _ = grunt.util._
   spec = (grunt.option('spec') || grunt.option('jsspec') || '*').replace(/(Spec|Test)$/, '')


docs are now in their own repo

docs are now in their own repo

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -74,8 +74,6 @@
     shell:
       commitBuild:
         command: "git add -A && git commit -am 'commit dist files for #{pkg.version}'"
-      docs:
-        command: 'grunt --gruntfile site/Gruntfile.coffee'

     # Watches files for changes and runs tasks based on the changed files
     watch:
@@ -499,10 +497,6 @@
         cwd: "<%= yeoman.dist %>"
         src: "**"

-      litcoffee:
-        files:
-          'site/app/docs/_documentation/Annotated-Source.md':'.tmp/scripts/alchemysrc.coffee.md'
-
     concurrent:
       # Run some tasks in parallel to speed up build process
       server: ["compass:server", "coffee:dev",  "copy:styles"]
@@ -560,7 +554,7 @@
   pullRequest = grunt.option('pr')
   travis = grunt.option('travis')
   grunt.registerTask "default",
-    # release alchemy and build docs
+    # release alchemy
     if releaseFlag
       ["test:dist",
        "build",
@@ -572,7 +566,6 @@
        "concat:s3", # squash vendor and alchemy files for cdn
        "concat:s3Version", # apply version numbers for cdn
        "s3:production" # publish files to s3 for cdn
-       "shell:docs", # publish docs
       ]
     # Travis-ci on a commit to the main repo branches
     else if travis


Tune browserstack build status message

Tune browserstack build status message

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -57,7 +57,7 @@
           child.stdout.on('data', log)
           child.stderr.on('data', log)

-    setCommitStatus = (sha, state) ->
+    setCommitStatus = (sha, state, message) ->
       GitHub = require('github')
       github = new GitHub
         version: '3.0.0'
@@ -76,8 +76,10 @@
         user: repo[0],
         repo: repo[1],
         sha: sha,
-        state: state
-        context: 'continous-integration/browserstack'
+        state: state,
+        description: message || ''
+        target_url: "https://travis-ci.org/#{repo[0]}/#{repo[1]}/jobs/#{process.env.TRAVIS_JOB_ID}"
+        context: 'continuous-integration/browserstack'

       new Promise (resolve, reject) ->
         github.statuses.create q, (error) ->
@@ -102,8 +104,8 @@
       setCommitStatus(sha, 'pending')
         .then(browserstack(grunt))
         .then(
-          (output) -> setCommitStatus(sha, 'success')
-          (error) -> setCommitStatus(sha, 'failure').then(-> Promise.reject(error))
+          (output) -> setCommitStatus(sha, 'success', 'The BrowserStack build passed')
+          (error) -> setCommitStatus(sha, 'failure', 'The BrowserStack build failed').then(-> Promise.reject(error))
         ).then(done, ->
           grunt.log.error(error.message)
           done(1)


Include 404 page in build

Include 404 page in build

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -132,6 +132,7 @@
           modules: [{
             name: 'main'
             include: [
+              'cs!pages/404/404'
               'cs!pages/home/home'
               'cs!pages/content/content'
               'cs!pages/search/search'


Add server files to beautify.

Add server files to beautify.

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -48,7 +48,8 @@
     # beautify
     jsbeautifier:
       working:
-        src:        [ '<%= CLIENT_DIR + JS_FILES %>' ]
+        src:        [ '<%= CLIENT_DIR + JS_FILES %>'
+                      '<%= SERVER_DIR + JS_FILES %>' ]

     # Wipe the `build` directory
     clean:


Update gruntfile

Update gruntfile

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -4,18 +4,7 @@
     coffee:
       compile:
         files:
-          'tether.js': 'tether.coffee'
-          'constraint.js': 'constraint.coffee'
-          'abutment.js': 'abutment.coffee'
-          'shift.js': 'shift.coffee'
-
-          'drop.js': 'drop.coffee'
-
-          'tooltip.js': 'tooltip.coffee'
           'select.js': 'select.coffee'
-
-          'markAttachment.js': 'markAttachment.coffee'
-          'docs/js/intro.js': 'docs/coffee/intro.coffee'
           'docs/welcome/js/welcome.js': 'docs/welcome/coffee/welcome.coffee'

     watch:
@@ -24,21 +13,17 @@
         tasks: ['coffee', 'uglify', 'compass']

     uglify:
-      tether:
-        src: 'tether.js'
-        dest: 'tether.min.js'
+      select:
+        src: 'select.js'
+        dest: 'select.min.js'
         options:
-          banner: '/*! tether.js <%= pkg.version %> */\n'
+          banner: '/*! select.js <%= pkg.version %> */\n'

     compass:
       dist:
         options:
           sassDir: 'sass'
           cssDir: 'css'
-      introDocs:
-        options:
-          sassDir: 'docs/sass'
-          cssDir: 'docs/css'
       welcomeDocs:
         options:
           sassDir: 'docs/welcome/sass'


Update grunt:bump pushTo remote

Update grunt:bump pushTo remote

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -91,6 +91,7 @@
       options:
         files: ['package.json']
         updateConfigs: ['pkg']
+        pushTo: 'origin'

     bower:
       install:


Added Grunt JSHint

Added Grunt JSHint

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -1,6 +1,7 @@
 module.exports = (grunt) ->
     grunt.initConfig
         pkg: grunt.file.readJSON 'package.json'
+
         uglify:
             options:
                 banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
@@ -9,6 +10,11 @@
                 files:
                     'dist/morphext.min.js': ['dist/morphext.js']

+        jshint:
+            all: ['dist/morphext.js']
+
+    grunt.loadNpmTasks 'grunt-contrib-jshint';
     grunt.loadNpmTasks 'grunt-contrib-uglify';

-    grunt.registerTask('default', ['uglify']);+    grunt.registerTask('default', ['uglify', 'test']);
+    grunt.registerTask('test', ['jshint']);


add grep option to grunt test:unit

add grep option to grunt test:unit

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -31,6 +31,7 @@
 			unit:
 				options:
 					reporter: grunt.option('reporter') or 'spec'
+					grep: grunt.option("grep")
 				src: ["test/unit/js/**/*.js"]

 	grunt.loadNpmTasks 'grunt-contrib-coffee'


Build: add 'test' and 'build' grunt tasks

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -100,3 +100,5 @@
             dest: 'c3.min.css'

     grunt.registerTask 'default', ['concat', 'jshint', 'jasmine', 'cssmin', 'uglify']
+    grunt.registerTask 'test', ['concat', 'jshint', 'jasmine']
+    grunt.registerTask 'build', ['concat', 'jshint', 'cssmin', 'uglify']


S87682: should bump version and commit at same time

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -35,7 +35,7 @@
   grunt.registerTask 'nexus:deploy', 'Deploys to nexus', ['build', 'nexus:__createartifact__']
   grunt.registerTask 'nexus:verify', 'Fetches the last build and verifies its integrity', ['clean:nexus', 'version', 'nexus:push:verify']

-  grunt.registerTask 'npm:publish', 'Publish to our private npm registry', ['bump-commit', 'npm-publish']
+  grunt.registerTask 'npm:publish', 'Publish to our private npm registry', ['bump:patch', 'npm-publish']

   grunt.registerTask 'check', 'Run convention tests on all files', ['regex-check']
   grunt.registerTask 'ci', 'Does a full build, runs tests and deploys to nexus', ['build', 'test:ci', 'nexus:__createartifact__']


Virtualenv should work now

Virtualenv should work now

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -5,8 +5,11 @@

 PYTHON_ENV_FOLDER = 'env'

+pythonExecSync = (args...) ->
+  cp.spawnSync.apply(cp, [path.join(PYTHON_ENV_FOLDER, 'bin/python')].concat(args))
+
 pythonExec = (args...) ->
-  cp.spawnSync.apply(cp, [fs.join(PYTHON_ENV_FOLDER, 'bin/python')] + args)
+  cp.spawn.apply(cp, [path.join(PYTHON_ENV_FOLDER, 'bin/python')].concat(args))

 lazyCopyFile = (source, target, callback) ->
@@ -64,7 +67,7 @@
   grunt.registerTask 'launch', 'Launch application', ->
     done = this.async()

-    proc = cp.spawn 'python3', ['manage.py', 'runserver'], {cwd: process.cwd()}, (err) ->
+    proc = pythonExec ['manage.py', 'runserver'], {cwd: process.cwd()}, (err) ->
       done err == null
     proc.stderr.on 'data', (data) ->
       grunt.log.write data
@@ -139,7 +142,7 @@
   grunt.registerTask 'pip-install', 'Get remaining dependencies', ->
     grunt.log.writeln 'installing python dependencies...'

-    o = pythonExec ['-m', 'pip', 'install', '-r', 'requirements.txt']
+    o = pythonExecSync ['-m', 'pip', 'install', '-r', 'requirements.txt']
     if not o.error == null
       grunt.log.writeln o.stderr
       return false
@@ -191,9 +194,9 @@
     done = this.async()

     grunt.log.writeln 'migrating...'
-    pythonExec ['manage.py', 'migrate']
+    pythonExecSync ['manage.py', 'migrate']
     grunt.log.writeln 'loading sample data...'
-    pythonExec ['manage.py', 'loaddata', 'courses']
+    pythonExecSync ['manage.py', 'loaddata', 'courses']

     done()


Allow grepping for spec to run

Allow grepping for spec to run

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -28,6 +28,7 @@
         options:
           reporter: 'spec'
           require: 'coffee-script/register'
+          grep: process.env.TESTS

     # Coding standards
     coffeelint:


boostwatch api url updated

boostwatch api url updated

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -3,7 +3,7 @@
 module.exports = (grunt) ->

   pkg = grunt.file.readJSON 'package.json'
-
+
   grunt.initConfig
     # Metadata
     pkg: pkg
@@ -33,9 +33,10 @@
     http:
       bootswatch:
         options:
-          url: 'http://api.bootswatch.com/3.json'
+          url: 'https://bootswatch.com/api/3.json'
           callback: (error, response, data) ->
             data = JSON.parse data
+            console.log data
             if error?
               grunt.log.error 'Something went wrong! Can\'t reach Bootswatch API'
             else
@@ -60,13 +61,13 @@
               else
                 grunt.task.run 'checkThemes'
                 grunt.task.run 'releaseNewThemes'
-
+
     clean:
       dist:
         src: ['dist']
       tmp:
         src: ['.tmp']
-
+
     shell:
       setUser:
         options:
@@ -77,7 +78,7 @@
           stdout: false
         command: (directory) ->
           'git clone https://$GH_TOKEN@' + pkg.repository.url.split('://')[1] + ' ' + directory
-
+
       commitMaster:
         options:
           failOnError: false
@@ -153,7 +154,7 @@
     grunt.task.run 'writeJsonChanges'
     grunt.task.run 'shell:commitMaster'

-
+
   grunt.registerTask 'updateBowerJson', 'Updates version of bower.json for themes ', (theme) ->
     # read source json
     content = grunt.file.readJSON 'bower.json'
@@ -165,7 +166,7 @@
     'curl'
   ]

-
+
   grunt.registerTask 'release', () ->
     grunt.task.run 'shell:setUser'
     grunt.task.run 'clean:dist'
@@ -179,7 +180,7 @@
       grunt.task.run 'shell:tagVersion:' + theme.name.toLowerCase() + ':' + grunt.config.get 'update.version'
       grunt.task.run 'shell:pushChanges:' + theme.name.toLowerCase()

-
+
   grunt.registerTask 'releaseNewThemes', () ->
     if grunt.config.get('update.newThemes').length > 0
       grunt.log.writeln 'Themes to release', grunt.config.get('update.newThemes').length
@@ -190,7 +191,7 @@
     else
       grunt.log.write "All is well! Themes are up to date. Version: #{grunt.config.get 'bowerConf.version'}."

-
+
   grunt.registerTask 'checkThemes', () ->
     grunt.config.set 'update.newThemes', []


Copy symlinks properly

Copy symlinks properly

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -13,8 +13,14 @@
     if grunt.file.isDir(source)
       grunt.file.recurse source, (sourcePath, rootDirectory, subDirectory='', filename) ->
         return if filter?.test(sourcePath)
+
         destinationPath = path.join(destination, subDirectory, filename)
-        grunt.file.copy(sourcePath, destinationPath)
+        if grunt.file.isLink(sourcePath)
+          grunt.file.mkdir(path.dirname(destinationPath))
+          fs.symlinkSync(fs.readlinkSync(sourcePath), destinationPath)
+        else
+          grunt.file.copy(sourcePath, destinationPath)
+
         if grunt.file.exists(destinationPath)
           fs.chmodSync(destinationPath, fs.statSync(sourcePath).mode)
     else


Change build process to include offline 1st

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -143,6 +143,10 @@
             'copy'
         ]

+    grunt.registerTask 'appcache',
+        'Build cache.manifest', [
+            'appcache'
+        ]

     grunt.registerTask 'deploy',
         'Deploy to Github Pages', [


Refactor build tasks

Refactor build tasks

* light -> default: Now includes building dependencies (Zepto/jquery-bridge)
* Nix "full" — was re-running build several times...

--- Gruntfile.coffee
+++ Gruntfile.coffee
@@ -203,19 +203,15 @@
         globals:
           $: true
           console: true
-
-  # Tasks
-  grunt.registerTask "nuke", ["clean:build", "clean:dist"]
-
+
   # Git submodule updates
-  grunt.registerTask "css", ["clean:css", "update_submodules", "compass"]
-  grunt.registerTask "zepto", ["update_submodules", "rake", "copy:zepto"]
-  grunt.registerTask "jquery-bridge", ["zepto", "copy:jquery-bridge"]
-
-  # Tests & checks
-  grunt.registerTask "test", ["copy:prepare", "copy:test", "qunit"]
-
-  # Full-build tasks
-  grunt.registerTask "light", ["nuke", "copy:prepare", "compass", "copy:zepto"]
-  grunt.registerTask "dist", ["nuke", "zepto", "jquery-bridge", "light", "test", "copy:dist", "uglify"]
-  grunt.registerTask "full", ['update_submodules', "nuke", "light", "dist"]+  grunt.registerTask 'zepto', ['rake', 'copy:zepto', 'copy:jquery-bridge']
+
+  # Default (Build)
+  grunt.registerTask 'default', ['update_submodules', 'clean', 'zepto', 'copy:prepare', 'compass']
+
+  # Test from scratch
+  grunt.registerTask 'test', ['default', 'copy:test', 'qunit']
+
+  # Builds, then copies to versioned dist dir and minifies all JS
+  grunt.registerTask 'dist', ['clean', 'default', 'copy:dist', 'uglify']


refs #8. Remove test params,change the path to the actual config file path.

--- lib/channel_view/emp-channel-list-view.coffee
+++ lib/channel_view/emp-channel-list-view.coffee
@@ -240,12 +240,13 @@

 parse_conf = (callback)->
   ex_state = fs.existsSync(parser_beam_file)
-  channel_conf = test_conf
+  # channel_conf = test_conf
   cha_conf_dir = atom.config.get(emp.ATOM_CONF_CHANNEL_DIR_KEY)
   # console.log cha_conf_dir
   project_path = atom.project.getPath()
   # console.log project_path
-  channel_conf1 = path.join project_path, cha_conf_dir
+  channel_conf = path.join project_path, cha_conf_dir
+  console.log channel_conf
   atom.project.channel_conf = channel_conf
   atom.project.parse_beam_dir = parser_beam_dir


add help and some comments

add help and some comments

--- code/li.coffee
+++ code/li.coffee
@@ -4,40 +4,60 @@

 Linode = (require 'linode').Linode

+# args[1] is the name of the command, e.g. start
+# args[2..] are the command args
 help = (args) ->
-  process.stdout.write('Very helpful help\n')
+  help =
+  """
+  Usage: li <command> [OPTIONS]
+    Commands:
+      list      List instances
+      create    Create a instance by config
+      destroy   Destroy an instance

+      start     Start an instance
+      stop      Stop an instance
+      restart   Restart an instance
+      sh        Execute a command on an instance
+      deploy    Run deployment hooks on an instance [OBSOLESCENT]
+
+  """
+  process.stdout.write help
+
+# args[2] is the name of the instance to start
 start = (args) ->
-  # args[1] is 'start'
-  # args[2] is 'placebo' (later on it will be 'linode' or 'ec2'
-  # or something else or maybe defaulted).
-  # args[3] is the configuration of the server to start.
-
-  # if args[2] is 'placebo' then throw 'foo'
   Linode.get args[2], (instance) ->
     instance.start ->
       process.stdout.write('started\n')

+# args[2] is the name of the instance to stop
 stop = (args) ->
   Linode.get args[2], (instance) ->
     instance.stop ->
       process.stdout.write('stopped\n')

+# args[2] is the name of the instance to restart
 restart = (args) ->
   Linode.get args[2], (instance) ->
     instance.restart ->
       process.stdout.write('restarted\n')

+# Takes a config name, and creates an instance based
+# on that config
+# args[2] is the name of the config
 create = (args) ->
   process.stdout.write('Creating...\n')
   Linode.create args[2], ->
-    process.stdout.write('Possibly created\n')
+    process.stdout.write('Created!\n')

+# args[2] is the name of the instance to destroy
 destroy = (args) ->
   process.stdout.write "Destroying #{args[2]}...\n"
   Linode.destroy args[2], ->
-    process.stdout.write "Possibly destroyed\n"
+    process.stdout.write "Destroyed\n"

+# Executes a command on the instance
+# args[2] is the command
 sh = (args) ->
   Linode.get args[2], (instance) ->
     callback = (code) ->
@@ -46,6 +66,8 @@

     instance.sh (args[3..].join ' '), callback

+# Deploys an instance by running all its hooks
+# args[2] is the instance
 deploy = (args) ->
   Linode.get args[2], (instance) ->
     callback = (code) ->
@@ -53,6 +75,7 @@
         process.exit code
     instance.run_hooks callback

+# Displays a list of instances
 list = (args) ->
   process.stdout.write "Listing instances...\n"
   Linode.list (err, list) ->


remove loftover console.log

remove loftover console.log

--- lib/base.coffee
+++ lib/base.coffee
@@ -325,8 +325,8 @@

     fileToLoad = @commandTable[name].file
     if fileToLoad not in VMP_LOADED_FILES
-      if atom.inDevMode()
-        console.log "lazy-require: #{fileToLoad} for #{name}"
+      # if atom.inDevMode()
+      #   console.log "lazy-require: #{fileToLoad} for #{name}"
       loadVmpOperationFile(fileToLoad)
       return klass if (klass = classRegistry[name])


improve deactivate()

improve deactivate()

--- lib/main.coffee
+++ lib/main.coffee
@@ -16,7 +16,8 @@
     @subscriptions.add atom.commands.add 'atom-workspace', 'nsl-assembler:save-&-compile': => @buildScript()

   deactivate: ->
-    @subscriptions.dispose()
+    @subscriptions?.dispose()
+    @subscriptions = null

   buildScript: ->
     editor = atom.workspace.getActiveTextEditor()


update dep. text

update dep. text

--- lib/main.coffee
+++ lib/main.coffee
@@ -98,5 +98,5 @@
   # Depreciated method associated with previous Services API
   # versioning that matched package version.
   legacyProvideStatusBar: ->
-     Grim.deprecate("Use at least version 1.0.0 of status-bar Service API.")
+     Grim.deprecate("Use versions ^1.0.0 of status-bar Service API.")
      @provideStatusBar()


Add touch support to interactive diagram

--- lib/main.coffee
+++ lib/main.coffee
@@ -171,6 +171,16 @@
   fromOffset: (offset) =>
     [offset % @width, Math.floor(offset / @width)]

+  normalizedCoords: (coords) =>
+    [x, y] = coords
+    x = Math.floor(x / @size)
+    y = Math.floor(y / @size)
+
+    if x >= 0 and x < @width and y >= 0 and y < @height
+      [x, y]
+    else
+      null
+
   appendSVGElements: =>
     # size is 2px bigger to leave room for outside lines on grid
     svg = @container.append 'svg:svg'
@@ -190,6 +200,8 @@
       .attr('transform', 'scale(1,-1)')
       .attr('class', 'annotations')

+    @mapElement = $(@el).find('.map').get 0
+
 class Map
   constructor: (@grid, @points, start, goal, interactive=false) ->

@@ -199,7 +211,9 @@
     @edit = interactive
     @drag = null # what's being dragged, if anything

-    $('body').mouseup @mouseup
+    $('body').on 'mouseup', @mouseup
+    $('body').on 'touchend', @mouseup
+    $('body').on 'touchcancel', @mouseup

   updatePoint: (point, type) =>
     [x, y] = point
@@ -241,7 +255,9 @@
       .attr('width', @grid.size)
       .attr('height', @grid.size)
       .on('mousedown', @mousedown)
+      .on('touchstart', @mousedown)
       .on('mouseover', @mouseover)
+      .on('touchmove', @mouseover)

     squares.attr('class', (d, i) -> d[2])

@@ -250,6 +266,7 @@
     square = d3.select(d3.event.target)
     @drag = square.attr 'class'
     @mouseover d, i
+    d3.event.preventDefault()

   mouseup: =>
     return unless @edit
@@ -264,7 +281,21 @@

   mouseover: (d, i) =>
     return unless @edit and @drag
-    square = d3.select(d3.event.target)
+
+    touches = d3.event.changedTouches
+    coords = if touches?
+      d3.touches(@grid.mapElement, touches)[0]
+    else
+      d3.mouse(@grid.mapElement)
+
+    return unless coords = @grid.normalizedCoords coords
+
+    # can't do d3.select(d3.event.target) since the target is static with
+    # touchmove.
+    square = @grid.mapSelection.selectAll('rect').filter (d, i) ->
+      [x, y, _] = d
+      x is coords[0] and y is coords[1]
+
     switch @drag
       when 'clear'
         if square.classed('clear')
@@ -287,6 +318,8 @@
             @updateNode before, 'clear'
           square.classed('goal', true)

+    d3.event.preventDefault()
+
   updateNode: (selection, type) =>
     [x, y, _] = selection.datum()
     @updatePoint [x, y], type


remove trailing semicolons

remove trailing semicolons

--- lib/main.coffee
+++ lib/main.coffee
@@ -59,7 +59,7 @@
           customArguments.push(script)

         args = defaultArguments.concat(customArguments)
-        bridleCmd = spawn('java', args);
+        bridleCmd = spawn('java', args)

         bridleCmd.stderr.on 'data', (data) ->
           atom.notifications.addError("Transpiling failed", detail: data, dismissable: true)
@@ -75,9 +75,9 @@

   getPath: (callback) ->
     if os.platform() is 'win32'
-      whichJava = spawn('where', ['java']);
+      whichJava = spawn('where', ['java'])
     else
-      whichJava = spawn('which', ['java']);
+      whichJava = spawn('which', ['java'])

     # Find Java
     whichJava.stderr.on 'data', (data) ->


minor cleanup

minor cleanup

--- lib/main.coffee
+++ lib/main.coffee
@@ -37,9 +37,8 @@
       vimState = new VimState(editor, @statusBarManager, globalState)
       @emitter.emit('did-add-vim-state', vimState)

-    workspaceClassList = atom.views.getView(atom.workspace).classList
     @subscribe atom.workspace.onDidChangeActivePane ->
-      workspaceClassList.remove('vim-mode-plus-pane-maximized', 'hide-tab-bar')
+      atom.views.getView(atom.workspace).classList.remove('vim-mode-plus-pane-maximized', 'hide-tab-bar')

     @subscribe atom.workspace.onDidChangeActivePaneItem ->
       if settings.get('automaticallyEscapeInsertModeOnActivePaneItemChange')


Add a notification explaining deprecations were not loaded

--- lib/main.coffee
+++ lib/main.coffee
@@ -35,6 +35,7 @@
       'settings-view:change-themes': -> atom.workspace.open("#{configUri}/themes")
       'settings-view:install-packages-and-themes': -> atom.workspace.open("#{configUri}/install")
       'settings-view:uninstall-themes': -> atom.workspace.open("#{configUri}/themes")
+      'settings-view:view-packages': -> atom.workspace.open("#{configUri}/packages")
       'settings-view:uninstall-packages': -> atom.workspace.open("#{configUri}/packages")
       'settings-view:check-for-package-updates': -> atom.workspace.open("#{configUri}/updates")

@@ -45,23 +46,32 @@
   consumeStatusBar: (statusBar) ->
     PackageManager = require './package-manager'
     packageManager = new PackageManager()
+    packageManager.getInstalled().then (packages) ->
+      deprecatedPackages = packages.user.filter ({name, version}) ->
+        atom.packages.isDeprecatedPackage(name, version)
+      return unless deprecatedPackages.length
+
+      were = 'were'
+      have = 'have'
+      packageText = 'packages'
+      if packages.length is 1
+        packageText = 'package'
+        were = 'was'
+        have = 'has'
+      notification = atom.notifications.addWarning "#{deprecatedPackages.length} #{packageText} #{have} deprecations and #{were} not loaded.",
+        description: 'This message will show one time. You can view deprecated packages in the settings view.'
+        detail: (pack.name for pack in deprecatedPackages).join(', ')
+        dismissable: true
+        buttons: [{
+          text: 'View Deprecated Packages',
+          onDidClick: ->
+            atom.commands.dispatch(atom.views.getView(atom.workspace), 'settings-view:view-packages')
+            notification.dismiss()
+        }]
+    .catch (error) ->
+      console.log error.message, error.stack
+
     packageManager.getOutdated().then (packages) ->
       if packages.length > 0
         PackageUpdatesStatusView = require './package-updates-status-view'
         packageUpdatesStatusView = new PackageUpdatesStatusView(statusBar, packages)
-
-        itemText = 'them'
-        packageText = 'packages'
-        if packages.length is 1
-          itemText = 'it'
-          packageText = 'package'
-        notification = atom.notifications.addInfo "You have #{packages.length} outdated #{packageText}. Please upgrade #{itemText}.",
-          description: 'Keeping packages up to date helps keep things speedy and breakage to a minimum. Upgrade often!'
-          detail: (pack.name for pack in packages).join(', ')
-          dismissable: true
-          buttons: [{
-            text: 'View and Upgrade Outdated Packages',
-            onDidClick: ->
-              atom.commands.dispatch(atom.views.getView(atom.workspace), 'settings-view:check-for-package-updates')
-              notification.dismiss()
-          }]


Remove unnecessary deactivation handler

Remove unnecessary deactivation handler

References: atom/tree-view#967

--- lib/main.coffee
+++ lib/main.coffee
@@ -1,3 +1,4 @@
+{Disposable} = require 'atom'
 FileIcons = require './file-icons'

 module.exports =
@@ -31,13 +32,12 @@
       @gitStatusView.destroy()
       @gitStatusView = null
     @projectPaths = null
-    @fileIconsDisposable?.dispose()
     @stopLoadPathsTask()
     @active = false

   consumeFileIcons: (service) ->
     FileIcons.setService(service)
-    @fileIconsDisposable = service.onWillDeactivate ->
+    new Disposable ->
       FileIcons.resetService()

   serialize: ->


Change status bar color

Change status bar color

--- halalar/config/application.coffee
+++ halalar/config/application.coffee
@@ -77,7 +77,7 @@

 # ## iOS Status Bar
 steroids.config.statusBar.enabled = true
-steroids.config.statusBar.style = "default"
+steroids.config.statusBar.style = "light"

 # ## File Watcher
 # steroids.config.watch.exclude = ["www/my_excluded_file.js", "www/my_excluded_dir"]


修复knex版本升级带来的bug

修复knex版本升级带来的bug

--- src/entity/issue.coffee
+++ src/entity/issue.coffee
@@ -165,7 +165,7 @@
     queue.push(
       (done)->
         countSql = sql.replace ':fields', 'count(id)'
-        entity = self.entity().knex.raw(countSql, [keyword, keyword])
+        entity = _knex.raw(countSql, [keyword, keyword])
         entity.exec (err, result)->
           return done err if err

@@ -182,7 +182,7 @@
                 				          (SELECT COUNT(*) FROM comment WHERE issue_id = issue.id) comment_count"
         sql += "ORDER BY always_top DESC, timestamp DESC limit #{pagination.limit} offset #{pagination.offset}"
         sql = sql.replace ':fields', fields
-        entity = self.entity().knex.raw(sql, [keyword, keyword])
+        entity = _knex.raw(sql, [keyword, keyword])
         entity.exec (err, result)->
           done err, count, result && result[0]
     )
@@ -208,7 +208,7 @@
     sql += 		               " A.timestamp BETWEEN #{start_time} AND #{end_time}"    if !assigned
     sql +=                " AND A.status <> 'trash' AND A.tag IN ('issue', 'form')"

-    @entity().knex.raw(sql).exec (err, result)->
+    _knex.raw(sql).exec (err, result)->
       return cb err if err
       cb err, result[0]

@@ -221,7 +221,7 @@
     sql +=                   " A.timestamp BETWEEN #{start_time} AND #{end_time}"    if !assigned
     sql +=                " AND A.status <> 'trash' "
     console.log sql
-    @entity().knex.raw(sql).exec (err, result)->
+    _knex.raw(sql).exec (err, result)->
       return cb err if err
       cb err, result[0]


Skip coverage on command.coffee

Skip coverage on command.coffee

--- command.coffee
+++ command.coffee
@@ -1,3 +1,5 @@
+### !pragma coverage-skip-block ###
+
 _             = require 'lodash'
 MeshbluConfig = require 'meshblu-config'
 Server        = require './src/server'


Expire fault when original task expires

Expire fault when original task expires

--- lib/cwmp.coffee
+++ lib/cwmp.coffee
@@ -120,6 +120,10 @@
   for channel of channels
     provs = sessionContext.faults[channel]?.provisions or []
     faults[channel] = Object.assign({provisions: provs}, fault)
+    if channel.startsWith('task_')
+      taskId = channel.slice(5)
+      for t in sessionContext.tasks
+        faults[channel].expiry = t.expiry if t._id == taskId and t.expiry

     if sessionContext.retries[channel]?
       ++ sessionContext.retries[channel]


Fix bug in path parser

Fix bug in path parser

--- lib/path.coffee
+++ lib/path.coffee
@@ -128,6 +128,10 @@
             cy = a[3]

         s: (doc, a) ->
+            if px is null
+                px = cx
+                py = cy
+
             doc.bezierCurveTo cx-(px-cx), cy-(py-cy), cx + a[0], cy + a[1], cx + a[2], cy + a[3]
             px = cx + a[0]
             py = cy + a[1]


Using textContent instead of innerHtml

Using textContent instead of innerHtml

--- framer/TextLayer.coffee
+++ framer/TextLayer.coffee
@@ -97,9 +97,9 @@
 		@explicitHeight = true

 	@define "text",
-		get: -> @html
+		get: -> @_element.textContent
 		set: (value) ->
-			@html = value
+			@_element.textContent = value
 			@emit("change:text", value)

 	@define "padding",


[DOC] Add documentation for core/errors.coffee.

--- src/core/errors.coffee
+++ src/core/errors.coffee
@@ -19,16 +19,21 @@
 {Translator}    = require './trans'

 class Errors
+    # Configure 404
     @NotFound : (msg = "404 Not Found") ->
         @name   = 'NotFound'
         Error.call this, msg
         Error.captureStackTrace this, arguments.callee

+    # Configure Internal Server Error
     @Error : (msg) ->
         @name   = 'InternalServerError'
         Error.call this, msg
         Error.captureStackTrace this, arguments.callee

+    # Render the Error page with a 404.
+    # Also used when a wrong browser is use.
+    # Set the right message and render the error page.
     @RenderNotFound : (req, res) ->
         loc = Translator.getDomain req.host
         res.status 404
@@ -53,6 +58,7 @@
         options.year = do (new Date()).getFullYear
         res.render 'error.jade', options

+    # Set the right message and render the internal error page.
     @RenderError : (req, res) ->
         loc = Translator.getDomain req.host
         res.status 500


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/core_object.coffee
+++ src/core_object.coffee
@@ -149,7 +149,8 @@
         else
           # Attempt to discover module name

-        self.extend Module(I, self) unless I.included_modules.include moduleName
+        unless I.included_modules.include moduleName
+          self.extend Module(I, self)

       return self


Add origin servers

Add origin servers


Added max delay

Added max delay

--- tp6/src/script/websock.coffee
+++ tp6/src/script/websock.coffee
@@ -15,6 +15,7 @@
     connect_timeout: 5000
     reconnection_delay: 500
     max_reconnection_attempts: 10
+    max_delay: 60

   websock_connect: ->
     @ws = new WebSocket(@options.host)
@@ -71,6 +72,8 @@
           reset()
         else
           @reconnection_delay *= 2
+          max = @options.max_delay
+          @reconnection_delay = max if @reconnection_delay > max
           @connect()
           @trigger("reconnecting", [@reconnection_delay, @reconnection_attempts])
           Tp.log("Reconnection delay: %d s", @reconnection_delay/1000)


moved some code from constructor to init for performance reasons

--- Framework/Views/BaseView.coffee
+++ Framework/Views/BaseView.coffee
@@ -1,30 +1,25 @@
 root.BaseView = class BaseView
   constructor: (options = {}) ->
     @uiInitialised = false
-    @settings = root._.extend({
+    @settings = root._.extend({ #TODO: GJ: can we pass in isModal?
       title: ''
       backgroundImage: root.app.settings.viewBackgroundImage
       backgroundRepeat: root.app.settings.viewBackgroundRepeat
       backgroundColor: root.app.settings.viewBackgroundColor
       barColor: root.app.settings.viewTitleBarColor
       fullscreen: false
+      modal: false
     }, options)
-
     @isPortrait = (Ti.UI.orientation == Ti.UI.PORTRAIT || Ti.UI.orientation == Ti.UI.UPSIDE_PORTRAIT)
     @isLandscape = (Ti.UI.orientation == Ti.UI.LANDSCAPE_LEFT || Ti.UI.orientation == Ti.UI.LANDSCAPE_RIGHT)

     @controls = []
+
     @window = Ti.UI.createWindow(@settings)
-    @window.title = @settings.title #NOTE: GJ: do we need this?

-    @spinner = Ti.UI.createActivityIndicator({
-      message: "Loading...", width: Ti.UI.SIZE
-      color: "#000", font: { fontSize: 18 }
-    })
-    @window.add(@spinner)

-
-    @noInternetView = Ti.UI.createView({
+    #TODO: SS: perhaps this should be a modal view on the app itself? we don't want every view to have this overhead
+    ###@noInternetView = Ti.UI.createView({ #TODO: GJ: move to NoInternetView class
       height: 60
       width: "100%"
       backgroundColor: "yellow"
@@ -41,22 +36,11 @@
       height: Ti.UI.SIZE
       bottom: 10
     })
-    @noInternetView.add([ noInternetHeader, noInternetText ])
-
+    @noInternetView.add([ noInternetHeader, noInternetText ])###

     @window.addEventListener('focus', @focus)
     @window.addEventListener('close', @onClose)

-    Ti.App.addEventListener("forceLandscapeWindow", (e) =>
-      @window.orientationModes = [Ti.UI.LANDSCAPE_LEFT, Ti.UI.LANDSCAPE_RIGHT]
-    )
-
-    Ti.Gesture.addEventListener("orientationchange", (e) =>
-      if Ti.UI.orientation == Ti.UI.PORTRAIT || Ti.UI.orientation == Ti.UI.UPSIDE_PORTRAIT
-        @onPortrait()
-      else
-        @onLandscape()
-    )

   focus: (e) =>
     @onInit() if !@uiInitialised
@@ -64,7 +48,21 @@
     @uiInitialised = true

   onInit: ->
-    if Ti.Platform.osname == "ipad"
+    @spinner = Ti.UI.createActivityIndicator({
+      message: "Loading...", width: Ti.UI.SIZE
+      color: "#000", font: { fontSize: 18 }
+    })
+    @window.add(@spinner)
+
+    Ti.App.addEventListener("forceLandscapeWindow", (e) => @window.orientationModes = [Ti.UI.LANDSCAPE_LEFT, Ti.UI.LANDSCAPE_RIGHT])
+    Ti.Gesture.addEventListener("orientationchange", (e) =>
+      if Ti.UI.orientation == Ti.UI.PORTRAIT || Ti.UI.orientation == Ti.UI.UPSIDE_PORTRAIT
+        @onPortrait()
+      else
+        @onLandscape()
+    )
+
+    if Ti.Platform.osname == "ipad" #NOTE: GJ: shouldn't we trigger this regardless of the platform?
       if @isPortrait
         @onPortrait()
       if @isLandscape


move to node on first tree click; select node on second click

--- src/textorum/tinymce/tree.coffee
+++ src/textorum/tinymce/tree.coffee
@@ -54,6 +54,8 @@
       })

   _selectNodeHandlerGenerator = (editor) ->
+    previousNode = null
+
     selectNodeHandler = (event, data) ->
       if ignoreNavigation
         return
@@ -67,11 +69,15 @@
         #node.append('');

         nodeEl = node[0]
-        editor.getWin().scrollTo(0, editor.dom.getPos(nodeEl).y);
-        editor.selection.select(nodeEl)
+        editor.getWin().scrollTo(0, editor.dom.getPos(nodeEl).y - 10);
+        if id is previousNode
+          editor.selection.select(nodeEl)
+        else
+          editor.selection.setCursorLocation(nodeEl, 0)
         editor.nodeChanged()

         editor.focus()
+        previousNode = id

   _depthWalkCallbackGenerator = (holder) ->
     depthWalkCallback = (depth) ->


Fix openEmptyEditorOnStart spec styling

Fix openEmptyEditorOnStart spec styling

--- spec/integration/fixtures/atom-home/config-openEmptyEditorOnStart.cson
+++ spec/integration/fixtures/atom-home/config-openEmptyEditorOnStart.cson
@@ -3,4 +3,4 @@
     showOnStartup: false
   "exception-reporting":
     userId: "7c0a3c52-795c-5e20-5323-64efcf91f212"
-	openEmptyEditorOnStart: false+	openEmptyEditorOnStart: false


Components with top 'Class' now are initialized

--- types/basics/component.coffee
+++ types/basics/component.coffee
@@ -61,6 +61,7 @@
 	initAsEmptyDefinition: ->
 		initSignalArr.call @
 		Object.freeze @
+		@initObjects()
 		return

 	init: ->


(feature) Add SessionUID for data call.

(feature) Add SessionUID for data call.

--- src/rest.coffee
+++ src/rest.coffee
@@ -37,6 +37,10 @@
       (app, config) ->
         app.get rest.path, (req, res) ->
           rest.dataCall(req.params[rest.param], res)
+    getResBySessionUIDAndParam: (rest) ->
+      (app, config) ->
+        app.get rest.path, (req, res) ->
+          rest.dataCall(req.session.uid, req.params[rest.param], res)
     post: (rest) ->
       (app, config) ->
         app.post rest.path, (req, res) ->


KD: warn when global window.event property is accessed

- cleanup Function#bind shim
- cleanup Array#first and Array#last getters

--- core/KD.coffee
+++ core/KD.coffee
@@ -1,11 +1,8 @@
-Function::bind or= do ->
-  {slice} = []
-  (context)->
-    func = @
-    if 1 < arguments.length
-      args = slice.call arguments, 1
-      return -> func.apply context, if arguments.length then args.concat slice.call arguments else args
-    -> if arguments.length then func.apply context, arguments else func.call context
+Function::bind3 or= (context) ->
+  if 1 < arguments.length
+    args = [].slice.call arguments, 1
+    return => @apply context, if arguments.length then args.concat [].slice.call arguments else args
+  => if arguments.length then @apply context, arguments else @call context

 Function::swiss = (parent, names...)->
   for name in names
@@ -25,11 +22,14 @@

 # Dict = Object.create.bind null, null, Object.create null

-unless Array::last
-  Object.defineProperty Array::, "last", get : -> @[@length-1]
-
-unless Array::first
-  Object.defineProperty Array::, "first", get : -> @[0]
+do (arrayProto = Array.prototype, {defineProperty} = Object)->
+  # set up .first and .last getters for Array prototype
+
+  "last" of arrayProto or
+    defineProperty arrayProto, "last", { get: -> @[@length-1] }
+
+  "first" of arrayProto or
+    defineProperty arrayProto, "first", { get: -> @[0] }

 # KD Global
 KD = @KD or {}
@@ -39,6 +39,11 @@
 KD.log   = log   = noop
 KD.warn  = warn  = noop
 KD.error = error = noop
+
+unless window.event?
+  # warn when the global "event" property is accessed.
+  Object.defineProperty window, "event", get:->
+    KD.warn "Global \"event\" property is accessed. Did you forget a parameter in a DOM event handler?"

 @KD = $.extend (KD), do ->
   # private member for tracking z-indexes


When refreshing or creating linked files, exempt from 403-error-catcher

--- services/web/public/coffee/ide/file-tree/FileTreeManager.coffee
+++ services/web/public/coffee/ide/file-tree/FileTreeManager.coffee
@@ -386,6 +386,8 @@
 				provider,
 				data,
 				_csrf: window.csrfToken
+			}, {
+				disableAutoLoginRedirect: true
 			}

 		refreshLinkedFile: (file) ->
@@ -396,6 +398,8 @@
 				return
 			return @ide.$http.post "/project/#{@ide.project_id}/linked_file/#{file.id}/refresh", {
 				_csrf: window.csrfToken
+			}, {
+				disableAutoLoginRedirect: true
 			}

 		renameEntity: (entity, name, callback = (error) ->) ->


CHG: select list component

CHG: select list component

--- frontend/javascripts/shared/fields/select/list/base.coffee
+++ frontend/javascripts/shared/fields/select/list/base.coffee
@@ -31,7 +31,7 @@
       $option = $ e.currentTarget
       $option.addClass 'selected'
       option = $option.data('option')
-      @namespacedTrigger('select', [option]) if option
+      @namespacedTrigger('select', [option, $option]) if option
       null

   _hiddenSizeChanged: ->
@@ -83,12 +83,11 @@
     @namespacedTrigger 'search', ['']

   selectOption: (option) ->
-    return false unless option && !(option in @selectedOption)
+    return if _.find @selectedOption, (opt) -> opt.value == option.value
     @selectedOption.push option
     true

   unselectOption: (option) ->
-    return false unless option && option in @selectedOption
     _.remove @selectedOption, (opt) -> opt.value == option.value
     true


Add play ball feature - update

Add play ball feature - update

--- lib/cubic-bezier-curve.coffee
+++ lib/cubic-bezier-curve.coffee
@@ -229,7 +229,9 @@
 				$("#playBall").css
 					"transition-timing-function": "cubic-bezier(" + @points.join() + ")"
 					"transition-duration": @playDurationInSec + "s"
+					"transition-property": "all"
 					"top" : (if startState then start else end) + "px"
+
 				startState = not startState

 		playMe = play()


Simplify a touch

Simplify a touch

--- ui/tests/routers/index.coffee
+++ ui/tests/routers/index.coffee
@@ -5,14 +5,14 @@
 describe('Index Router', ->
     before(->
         @$test = $('#test')
-        sinon.stub(IndexRouter::, 'viewError')
+        @viewErrorStub = sinon.stub(IndexRouter::, 'viewError')
         @router = new IndexRouter({$region: @$test})
         Backbone.history.start({pushState: true})
     )

     after(->
         Backbone.history.stop()
-        IndexRouter::viewError.restore()
+        @viewErrorStub.restore()
         delete @router
     )

@@ -26,6 +26,6 @@

     it('should 404 if the URL doesn\'t match', ->
         @router.navigate('/rainbow', {trigger: true, replace: true})
-        expect(IndexRouter::viewError).to.have.been.called
+        expect(@router.viewError).to.have.been.called
     )
 )


Prevent tag deletion when tag still in use. Fix #243

--- lib/tags.coffee
+++ lib/tags.coffee
@@ -105,9 +105,10 @@
     unless canPost group, null
       throw new Meteor.Error 'tagDelete.unauthorized',
         "Insufficient permissions to untag message in group '#{group}'"
+    return if @isSimulation  ## can't check for global message existence
     any = Messages.findOne
       group: group
-      tags: "#{escapeTag key}": $exists: true
+      "tags.#{escapeTag key}": $exists: true
     if any
       if maybe
         return


return

return

--- lib/init.coffee
+++ lib/init.coffee
@@ -40,8 +40,8 @@
     console.log('getFileFor ' + name, files)
     console.log('getFileFor found', found)
     if found.length
-        "(" + found[0].path + ")"
-    ''
+        return "(" + found[0].path + ")"
+    return ''

 atom.workspace.addLeftPanel(item: el)


add config option for explicitly setting the editor line height

--- src/editor-view.coffee
+++ src/editor-view.coffee
@@ -44,6 +44,7 @@
   @configDefaults:
     fontFamily: ''
     fontSize: 16
+    editorLineHeight: 1
     showInvisibles: false
     showIndentGuide: false
     showLineNumbers: true
@@ -340,6 +341,8 @@
     @subscribe atom.config.observe 'editor.invisibles', (invisibles) => @setInvisibles(invisibles)
     @subscribe atom.config.observe 'editor.fontSize', (fontSize) => @setFontSize(fontSize)
     @subscribe atom.config.observe 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily)
+    @subscribe atom.config.observe 'editor.editorLineHeight', (editorLineHeight) => @setEditorLineHeight(editorLineHeight)
+

   handleEvents: ->
     @on 'focus', =>
@@ -740,6 +743,10 @@

     @clearCharacterWidthCache()

+    @redraw()
+
+  setEditorLineHeight: (editorLineHeight) ->
+    @css('line-height', editorLineHeight)
     @redraw()

   # Public: Gets the font family for the editor.


better type system

better type system

--- src/nodes.coffee
+++ src/nodes.coffee
@@ -24,15 +24,29 @@
 THIS    = -> this
 NEGATE  = -> @negated = not @negated; this

+class Type
+  constructor: (@basic, @args=[]) ->
+    @string = switch @basic
+      when "func" then "func(#{@args.map((x)->x.string).join(",")})"
+      else @basic
+typeRegistry = {}
+getType = (type) ->
+  # singletons, so that comparisons work
+  return typeRegistry[type.string] ?= type
+intType = getType new Type "int"
+stringType = getType new Type "string"
 class Variable
   constructor: (@name, @type, @namespace) ->
   mangledName: ->
     "_" + @name
+class Func
+  constructor: (@label, @code) ->

 class Namespace
   constructor: ->
     @names = {}
     @variables = []
+    @funcs = []
     labelCount = 0
     @nextLabel = -> "_#{labelCount++}"
   find: (name) ->
@@ -47,6 +61,11 @@
     asm = ":#{label} dat #{value.length}, #{JSON.stringify value}"
     @variables.push {asm}
     label
+  createFunc: (code) ->
+    func = new Func @nextLabel(), code
+    @funcs.push func
+    @variables.push func
+    func

 #### Base

@@ -194,17 +213,22 @@
   compileRoot: ->
     o =
       namespace: new Namespace
-    o.namespace.createVariable("printc", "func(int)").asm = stdlib.printc
-    o.namespace.createVariable("prints", "func(string)").asm = stdlib.prints
-    code = @compile o
+    o.namespace.createVariable("printc", getType new Type "func", [intType]).asm = stdlib.printc
+    o.namespace.createVariable("prints", getType new Type "func", [stringType]).asm = stdlib.prints
+    code = @compileStatement o
     codes = [code, "set [0x8ffe], 0\n"]
+
+    # breadth-first traversal through declared functions
+    for func in o.namespace.funcs
+      func.asm = func.code.compileFunc o
+
     for variable in o.namespace.variables
       codes.push variable.asm
     codes.join "\n"
-  compile: (o) ->
+  compileStatement: (o) ->
     codes = []
     for expression in @expressions
-      codes.push expression.compile o
+      codes.push expression.compileStatement o
     codes.join "\n"

   # Wrap up the given nodes as a **Block**, unless it already happens
@@ -226,14 +250,14 @@
       when "false" then "0"
       else value

-  compile: (o) ->
+  compileExpression: (o) ->
     unless @type?
       variable = o.namespace.find @value
       throw SyntaxError "undefined variable \"#{@value}\"" unless variable?
       return {type: variable.type, access: "[#{variable.mangledName()}]"}
     switch @type
-      when "int" then {type: @type, access: @value}
-      when "string" then {type: @type, access: o.namespace.createLiteralString JSON.parse @value}
+      when "int" then {type: intType, access: @value}
+      when "string" then {type: stringType, access: o.namespace.createLiteralString JSON.parse @value}

   makeReturn: ->
     if @isStatement() then this else super
@@ -337,20 +361,22 @@

   children: ['variable', 'args']

-  compile: (o) ->
+  compileStatement: (o) ->
     funcName = @variable.unwrapAll().value
     funcVariable = o.namespace.find funcName
     throw SyntaxError "undefined variable \"#{funcName}\"" unless funcVariable?
-    if funcVariable.type not in ["func(int)", "func(string)"]
-      throw SyntaxError "can't call variable \"#{funcName}\" of type \"#{funcVariable.type}\""
-    throw SyntaxError "function \"#{funcName}\" takes 1 argument" unless @args.length == 1
-    required_arg_type = funcVariable.type.match(/\((.*)\)/)[1]
-    arg = @args[0].unwrapAll().compile o
-    throw SyntaxError "can't pass argument of type #{arg.type} to function \"#{funcName}\"" unless arg.type is required_arg_type
-    return [
-      "set push, #{arg.access}"
-      "jsr #{funcVariable.mangledName()}"
-    ].join("\n")
+    unless funcVariable.type.basic is "func"
+      throw SyntaxError "can't call variable \"#{funcName}\" of type \"#{funcVariable.type.string}\""
+    unless funcVariable.type.args.length is @args.length
+      throw SyntaxError "function \"#{funcName}\" takes #{funcVariable.type.args.length} argument, not #{@args.length}"
+    codes = []
+    for arg, i in @args
+      arg = arg.unwrapAll().compileExpression o
+      unless funcVariable.type.args[i] is arg.type
+        throw SyntaxError "argument #{i} to function #{funcName} should have type #{funcVariable.type.args[i].string}, rather than #{arg.type.string}"
+      codes.push "set push, #{arg.access}"
+    codes.push "jsr #{funcVariable.mangledName()}"
+    return codes.join("\n")

   # Tag this invocation as creating a new instance.
   newInstance: ->
@@ -507,9 +533,9 @@

   children: ['variable', 'value']

-  compile: (o) ->
+  compileStatement: (o) ->
     name = @variable.unwrapAll().value
-    value = @value.unwrapAll().compile o
+    value = @value.unwrapAll().compileExpression o
     variable = o.namespace.find name
     if @context is ":="
       throw SyntaxError "variable \"#{name}\" is already declared" if variable?
@@ -536,6 +562,15 @@
     @body    = body or new Block
     @bound   = tag is 'boundfunc'
     @context = '_this' if @bound
+
+  compileExpression: (o) ->
+    throw SyntaxError "func declarations cannot have parameters" unless @params.length is 0
+    @func = o.namespace.createFunc this
+    {type: getType(new Type "func"), access: @func.label}
+
+  compileFunc: (o) ->
+    code = "; TODO function body here"
+    ":#{@func.label}\n#{code}"

   children: ['params', 'body']


change where moment locale is set from merge

--- modules/preferences/main/index.coffee
+++ modules/preferences/main/index.coffee
@@ -219,8 +219,6 @@

     defaultLocaleId = navigator.languages?[0] or navigator.language

-    @on('localechange', (value) -> moment?.locale(value))
-
     if not (hx.isString(defaultLocaleId) and lookupLocale(defaultLocaleId))
       defaultLocaleId = 'en'
     @locale defaultLocaleId
@@ -253,6 +251,10 @@
       if hx.isString(locale) and (localeObject = lookupLocale(locale))
         if @_.preferences['locale'] isnt localeObject.value
           @_.preferences['locale'] = localeObject.value
+
+          # moment doesn't look up the 'default' locale so we set it here
+          # Moment issue: https://github.com/moment/moment/issues/2621
+          moment?.locale(localeObject.value)
           @emit('localechange', localeObject.value)
       else
         hx.consoleWarning('preferences.locale',


Remove added space and scheduled a real solution

--- lib/main.coffee
+++ lib/main.coffee
@@ -51,11 +51,12 @@
                     isListItem = true

               if isListItem and isPunctuation
+                # TODO make the 'space' part of an empty list-item
                 # TODO increment ordered list-item
                 # TODO add left padding to ordered list-items (003.)
                 # TODO add incomplete task-list-item
                 # TODO skip definition-lists?
-                editor.insertText token.value + ' '
+                editor.insertText token.value
                 break

             # scopeDescriptor = editor.scopeDescriptorForBufferPosition(previousRowRange.end)


Remove duplicate windows1250 entry

Remove duplicate windows1250 entry

It should have been windows1252 from the beginning.

--- lib/main.coffee
+++ lib/main.coffee
@@ -33,9 +33,9 @@
   utf16be:
     list:   'UTF-16 BE'
     status: 'UTF-16 BE'
-  windows1250:
-    list:   'Western (Windows 1250)'
-    status: 'Windows 1250'
+  windows1252:
+    list:   'Western (Windows 1252)'
+    status: 'Windows 1252'
   iso88591:
     list:   'Western (ISO 8859-1)'
     status: 'ISO 8859-1'


Provide more info when .sass-lint.yml is missing

--- lib/main.coffee
+++ lib/main.coffee
@@ -38,7 +38,14 @@
         config = if @configPath is '' then findFile filePath, configExt else path.join @configPath, configExt
         linter = require(@executablePath)

-        if config is null then throw new Error 'No .sass-lint.yml config file found'
+        if config is null
+          atom.notifications.addError """
+            **No .sass-lint.yml config file found.** You can find an example
+            [here](https://github.com/sasstools/sass-lint/blob/master/lib/config/sass-lint.yml)
+            and documentation on how to configure this and also documentation on
+            each of the rules [here](https://github.com/sasstools/sass-lint/tree/develop/docs).
+          """
+          return []

         results = linter.lintFiles(filePath, {}, config)


Fix "charcter" typo

Fix "charcter" typo

I know this is a very small contribution, but I'm just _really_ trying Atom now (I've got a remote workflow and it's really not very good. So far only sshfs is working _ok_).

--- lib/main.coffee
+++ lib/main.coffee
@@ -24,7 +24,7 @@
     ensureSingleTrailingNewline:
       type: 'boolean'
       default: true
-      description: 'If the buffer doesn\'t end with a newline charcter when it\'s saved, then append one. If it ends with more than one newline, remove all but one. To disable/enable for a certain language, use [syntax-scoped properties](https://github.com/atom/whitespace#readme) in your `config.cson`.'
+      description: 'If the buffer doesn\'t end with a newline character when it\'s saved, then append one. If it ends with more than one newline, remove all but one. To disable/enable for a certain language, use [syntax-scoped properties](https://github.com/atom/whitespace#readme) in your `config.cson`.'

   activate: ->
     @whitespace = new Whitespace()


add templates in spec and also start to implement disk provisionning

--- src/spec.coffee
+++ src/spec.coffee
@@ -169,6 +169,30 @@

               exit: (value) -> remove @field, value.UUID

+          templates: @dynamic [],
+            'VM-template':
+              # FIXME: when a VM is updated, this hook will run for each
+              # pool even though we know which pool to update
+              # (`value.$pool`).
+              # There must be a way to fix this problem while still
+              # keeping a generic implementation.
+              #
+              # Note: I do not want to handle this field from the VM
+              # rule, it would make the maintenance harder.
+              update: (VM) ->
+                # Unless this VM belongs to this pool, there is no need
+                # to continue.
+                return unless VM.$pool is @value.UUID
+
+                remove @field, VM.UUID
+
+                # TODO: Check whether this template belong to a local host.
+                local = false
+                unless local
+                  @field.push VM.UUID
+
+              exit: (value) -> remove @field, value.UUID
+
           $running_hosts: @dynamic [],
             host:
               update: (host) ->
@@ -363,6 +387,19 @@
                 @field.push console if found
             }

+          # TODO: parse XML and convert it to an object
+          #disks: (value) -> value.other_config?.disks
+
+          # REMOVE ASAP: mockup data
+          disks: [
+            {
+                device: "0"
+                name_description: "Created with Xen Orchestra"
+                size: 8589934592
+                sr: null
+            }
+          ]
+
           # TODO: `0` should not be used when the value is unknown.
           memory: @dynamic {
             usage: null
@@ -421,7 +458,9 @@
           # TODO: removes it when hooks have access to the generator.
           $pool: get '$pool'

-          $snapshots: get ('snapshots')
+          snapshots: get 'snapshots'
+
+          snapshot_time: get 'snapshot_time'

           $VBDs: @dynamic [], {
             VBD: {
@@ -464,6 +503,12 @@
         test: (value) ->
           value.$type is 'VM' and value.is_a_snapshot

+      'VM-template':
+        extends: 'VM'
+
+        test: (value) ->
+          value.$type is 'VM' and value.is_a_template and not value.is_a_snapshot
+
       'VM_metrics':

         test: test


:shirt: Fix coffeelint issue

:shirt: Fix coffeelint issue

--- lib/main.coffee
+++ lib/main.coffee
@@ -114,7 +114,8 @@
     executablePath:
       type: 'string'
       default: 'flake8'
-      description: 'Semicolon separated list of paths to a binary (e.g. /usr/local/bin/flake8). Use `$PROJECT` substitutions for project specific paths e.g. `$PROJECT/.venv/bin/flake8;/usr/bin/flake8`'
+      description: 'Semicolon separated list of paths to a binary (e.g. /usr/local/bin/flake8). ' +
+        'Use `$PROJECT` substitutions for project specific paths e.g. `$PROJECT/.venv/bin/flake8;/usr/bin/flake8`'
     projectConfigFile:
       type: 'string'
       default: ''


Remove legacy code

Remove legacy code

--- lib/main.coffee
+++ lib/main.coffee
@@ -13,9 +13,6 @@
     @statusBar = new StatusBarView()
     @statusBar.initialize(state)
     @statusBarPanel = atom.workspace.addBottomPanel(item: @statusBar, priority: 0)
-
-    # Remove when legacy panel classes PR (atom/atom#4305) has been released
-    atom.views.getView(@statusBarPanel).classList.add("tool-panel", "panel-bottom")

     # Wrap status bar element in a jQuery wrapper for backwards compatibility
     wrappedStatusBar = $.extend $(@statusBar),


dismiss notification onDidClick

dismiss notification onDidClick

--- lib/main.coffee
+++ lib/main.coffee
@@ -91,16 +91,19 @@
       bridleJar = atom.config.get('language-bridlensis.pathToJar')

       if not bridleJar
-        return atom.notifications.addError(
-          "**#{meta.name}**: No valid `BridleNSIS.jar` was specified in your settings",
-          dismissable: true,
+        notification = atom.notifications.addError(
+          "**#{meta.name}**: No valid `BridleNSIS.jar` was specified in your settings"
+          dismissable: true
           buttons: [
             {
               text: 'Open Settings'
-              onDidClick: -> atom.workspace.open("atom://config/packages/#{meta.name}")
+              onDidClick: ->
+                atom.workspace.open("atom://config/packages/#{meta.name}")
+                notification.dismiss()
             }
           ]
         )
+        return

       defaultArguments = ["-jar", bridleJar]


Even more compact descriptions. :astonished:

--- lib/main.coffee
+++ lib/main.coffee
@@ -8,7 +8,7 @@
       scopes:
         '.source.jade':
           default: false
-      description: 'Automatically remove whitespace characters at ends of lines when the buffer is saved. To disable/enable for a certain language, use syntax-scoped properties in your `config.cson`. See [the README](https://github.com/atom/whitespace#readme) for more information.'
+      description: 'Automatically remove whitespace characters at ends of lines when the buffer is saved. To disable/enable for a certain language, use [syntax-scoped properties](https://github.com/atom/whitespace#readme) in your `config.cson`.'
     keepMarkdownLineBreakWhitespace:
       type: 'boolean'
       default: true
@@ -16,15 +16,15 @@
     ignoreWhitespaceOnCurrentLine:
       type: 'boolean'
       default: true
-      description: 'Skip removing trailing whitespace on the line which the cursor is positioned on when the buffer is saved. To disable/enable for a certain language, use syntax-scoped properties in your `config.cson`. See [the README](https://github.com/atom/whitespace#readme) for more information.'
+      description: 'Skip removing trailing whitespace on the line which the cursor is positioned on when the buffer is saved. To disable/enable for a certain language, use [syntax-scoped properties](https://github.com/atom/whitespace#readme) in your `config.cson`.'
     ignoreWhitespaceOnlyLines:
       type: 'boolean'
       default: false
-      description: 'Skip removing trailing whitespace on lines which consist only of whitespace characters. To disable/enable for a certain language, use syntax-scoped properties in your `config.cson`. See [the README](https://github.com/atom/whitespace#readme) for more information.'
+      description: 'Skip removing trailing whitespace on lines which consist only of whitespace characters. To disable/enable for a certain language, use [syntax-scoped properties](https://github.com/atom/whitespace#readme) in your `config.cson`.'
     ensureSingleTrailingNewline:
       type: 'boolean'
       default: true
-      description: 'If the buffer doesn\'t end with a newline charcter when it\'s saved, then append one. If the buffer ends with more than one newline character, remove all but one. To disable/enable for a certain language, use syntax-scoped properties in your `config.cson`. See [the README](https://github.com/atom/whitespace#readme) for more information.'
+      description: 'If the buffer doesn\'t end with a newline charcter when it\'s saved, then append one. If it ends with more than one newline, remove all but one. To disable/enable for a certain language, use [syntax-scoped properties](https://github.com/atom/whitespace#readme) in your `config.cson`.'

   activate: ->
     @whitespace = new Whitespace()


:new: Implement Render in LinterView

:new: Implement Render in LinterView

--- lib/view.coffee
+++ lib/view.coffee
@@ -7,10 +7,14 @@
   constructor: (@Linter) ->
     super()
     @Decorations = []
+    @Messages = []
+    @CountFile = 0
+    @CountProject = 0
     @BarCurrent = null
     @BarProject = null
     @BarStatus = null
     @Bubble = null
+    @Type = 'file'
     @Root = document.createElement 'div'
     @Root.id = 'linter-panel'

@@ -29,11 +33,11 @@

   updateBubble: (Point) ->
     @Bubble?.destroy()
-    return unless @Linter.Messages.length
+    return unless @Messages.length
     TextEditor = @Linter.ActiveEditor
     ActiveFile = TextEditor.getPath()
     Found = false
-    @Linter.Messages.forEach (Message) =>
+    @Messages.forEach (Message) =>
       return if Found
       return unless Message.File is ActiveFile
       return unless Message.Position
@@ -43,14 +47,35 @@
       Marker = TextEditor.markBufferRange LeRange, {invalidate: 'never'}
       @Bubble = TextEditor.decorateMarker Marker, type: 'overlay', item: Views.bubble(@, Message)
       Found = true
-
+  render: ->
+    @Messages = []
+    @CountFile = 0
+    @CountProject = 0
+    Values = @Linter.MessagesProject.values()
+    Value = Values.next()
+    while not Value.done
+      @Messages = @Messages.concat Value.value if @Type is 'project'
+      @CountProject += Value.value.length
+      Value = Values.next()
+    Values = @Linter.getActiveEditorLinter().Messages.values()
+    Value = Values.next()
+    while not Value.done
+      @Messages = @Messages.concat Value.value
+      @CountFile += Value.value.length
+      Value = Values.next()
+    if not @Messages.length
+      @Linter.ViewPanel.hide() if @Linter.ViewPanel.isVisible()
+      @remove()
+    else
+      @update()
+      @Linter.ViewPanel.show() unless @Linter.ViewPanel.isVisible()
   update: ->
     @Bubble?.destroy()
     @removeDecorations()
     @removeErrors()
     TextEditor = @Linter.ActiveEditor
     ActiveFile = TextEditor.getPath()
-    @Linter.Messages.forEach (Message) =>
+    @Messages.forEach (Message) =>
       Entry = @messageLine Message
       @Root.appendChild Entry


fix source option binding

fix source option binding

--- lib/markem.iced
+++ lib/markem.iced
@@ -100,6 +100,8 @@

       await utils.rmdirDeep @tmp,defer err
       console.log "Done."
+
+    cb()

   # calling git commands
   # params:


Task has better examples

Task has better examples

--- src/task.coffee
+++ src/task.coffee
@@ -4,12 +4,36 @@

 # Extended: Run a node script in a separate process.
 #
-# Used by the fuzzy-finder.
+# Used by the fuzzy-finder and [find in project](https://github.com/atom/atom/blob/master/src/scan-handler.coffee).
+#
+# For a real-world example, see the [scan-handler](https://github.com/atom/atom/blob/master/src/scan-handler.coffee)
+# and the [instantiation of the task](https://github.com/atom/atom/blob/4a20f13162f65afc816b512ad7201e528c3443d7/src/project.coffee#L245).
 #
 # ## Examples
 #
+# In your package code:
+#
 # ```coffee
 # {Task} = require 'atom'
+#
+# task = Task.once '/path/to/task-file.coffee', parameter1, parameter2, ->
+#   console.log 'task has finished'
+#
+# task.on 'some-event-from-the-task', (data) =>
+#   console.log data.someString # prints 'yep this is it'
+# ```
+#
+# In `'/path/to/task-file.coffee'`:
+#
+# ```coffee
+# module.exports = (parameter1, parameter2) ->
+#   # Indicates that this task will be async.
+#   # Call the `callback` to finish the task
+#   callback = @async()
+#
+#   emit('some-event-from-the-task', {someString: 'yep this is it'})
+#
+#   callback()
 # ```
 #
 # ## Events
@@ -55,7 +79,7 @@
   # receives a completion callback, this is overridden.
   callback: null

-  # Public: Creates a task.
+  # Public: Creates a task. You should probably use {.once}
   #
   # * `taskPath` The {String} path to the CoffeeScript/JavaScript file that
   #   exports a single {Function} to execute.


Adds default refinements to refinement library

--- lib_spec.coffee
+++ lib_spec.coffee
@@ -9,17 +9,16 @@
       class XTypeToRefine
         normal: -> 'x'

-      refinement = ttm.require('lib/object_refinement').build()
-      refinement.forType(ATypeToRefine, {refined: -> 'a'})
-      refinement.forType(BTypeToRefine, {refined: -> 'b'})
+      @refinement = ttm.require('lib/object_refinement').build()
+      @refinement.forType(ATypeToRefine, {refined: -> 'a'})
+      @refinement.forType(BTypeToRefine, {refined: -> 'b'})

       @a = new ATypeToRefine
       @b = new BTypeToRefine
       @x = new XTypeToRefine

-      @ap = refinement.refine(@a)
-      @bp = refinement.refine(@b)
-      @xp = refinement.refine(@x)
+      @ap = @refinement.refine(@a)
+      @bp = @refinement.refine(@b)

@@ -32,5 +31,21 @@
         expect(@ap.refined()).toEqual "a"
         expect(@bp.refined()).toEqual "b"

-    it "does nothing to a class that has no applicable refinement", ->
-      expect(@xp.refined).toEqual undefined
+
+    describe "without a default refinement", ->
+      beforeEach ->
+        @xp = @refinement.refine(@x)
+
+      it "does nothing to a class that has no applicable refinement", ->
+        expect(@xp.refined).toEqual undefined
+
+    describe "with a default refinement", ->
+      beforeEach ->
+        @refinement.forDefault({refined: -> 'default'})
+        @xp = @refinement.refine(@x)
+
+      it "adds the default refinement to objects that have no refinements", ->
+        expect(@xp.refined()).toEqual "default"
+
+
+


fix for the asana task https://app.asana.com/0/3716548652471/7302399157071

--- client/landing/app/Applications/Activity.kdapplication/views/activityactions.coffee
+++ client/landing/app/Applications/Activity.kdapplication/views/activityactions.coffee
@@ -91,7 +91,7 @@
     @shareLink    = new ActivityActionLink
       partial         : "Share"
       click           :(event)=>
-        shareUrl      = "https://koding.com/Activity/#{@getData().slug}"
+        shareUrl      = "#{KD.config.mainUri}/Activity/#{@getData().slug}"
         contextMenu   = new JContextMenu
           cssClass    : "activity-share-popup"
           type        : "activity-share"


buttons are hidden to avoid the confusion.

--- client/landing/app/Applications/Inbox.kdapplication/Views/InboxNewMessageBar.coffee
+++ client/landing/app/Applications/Inbox.kdapplication/Views/InboxNewMessageBar.coffee
@@ -23,7 +23,7 @@
         @emit 'RefreshButtonClicked'

     @addSubView @markMessageAsReadButton = new KDButtonView
-      style       : "clean-gray"
+      style       : "clean-gray hidden"
       icon        : yes
       iconOnly    : yes
       iconClass   : "mark-unread"
@@ -34,7 +34,7 @@
         @emit 'MessageShouldBeMarkedAsUnread'

     @addSubView @deleteMessageButton = new KDButtonView
-      style       : "clean-gray"
+      style       : "clean-gray hidden"
       icon        : yes
       iconOnly    : yes
       iconClass   : "delete"
@@ -76,3 +76,5 @@
   enableMessageActionButtons:->
     @deleteMessageButton.enable()
     @markMessageAsReadButton.enable()
+    @deleteMessageButton.show()
+    @markMessageAsReadButton.show()


Fixed issue with request not being sent as text/javascript

--- lib/ethereal/app/assets/javascripts/ethereal/xhr.js.coffee
+++ lib/ethereal/app/assets/javascripts/ethereal/xhr.js.coffee
@@ -1,4 +1,5 @@
 class XHR
+  script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
   constructor: (el) ->
     @element(el)
     @request = new XMLHttpRequest()
@@ -15,6 +16,7 @@

   send: (src, method = 'GET', data) =>
     @request.open(method, src)
+    @request.setRequestHeader('accept', "*/*;q=0.5, #{@script}")
     @request.setRequestHeader('X-Requested-With', "XMLHttpRequest")

     @request.send(data)


Norm special case of 0, 0

Norm special case of 0, 0

--- src/point.coffee
+++ src/point.coffee
@@ -112,7 +112,10 @@
       this.copy().norm$(length)

     norm$: (length=1.0) ->
-      this.scale$(length/this.length())
+      if m = this.length()
+        this.scale$(length/m)
+      else
+        this

     ###*
     Floor the x and y values, returning a new point.


Clean up default config code a little

Clean up default config code a little

--- lib/pep8.coffee
+++ lib/pep8.coffee
@@ -9,11 +9,29 @@
     errorView: null
     pep8Path: null

-    activate: (state) ->
-        unless atom.config.get('pep8.PEP8Path')
-            atom.config.set('pep8.PEP8Path', "/usr/local/bin/pep8")
+    defaultConfig:
+        'pep8.PEP8Path': '/usr/local/bin/pep8',
+        'pep8.ignoreErrors': []
+    boundObservers: false
+
+    loadConfig: ->
+
+        if not @boundObservers
+            for config_key, default_val of @defaultConfig
+                atom.config.observe(config_key, {}, @loadConfig)
+            @boundObservers = true
+
+        console.log "PEP8 Liner: Loading config"
+
+        for config_key, default_val of @defaultConfig
+            unless atom.config.get(config_key)
+                atom.config.set(config_key, default_val)

         @pep8Path = atom.config.get('pep8.PEP8Path')
+        @ignoreErrors = atom.config.get('pep8.ignoreErrors')
+
+    activate: (state) ->
+        @loadConfig()

         atom.workspaceView.command 'pep8:lint', =>
             @lint()


prevents ReferenceError

prevents ReferenceError

--- jsapp/xlform/src/model.row.coffee
+++ jsapp/xlform/src/model.row.coffee
@@ -365,7 +365,7 @@
         newRowType.set 'list', @getList().clone()
         newRowType.set 'listName', newRowType.get('list').get 'name'

-      @getSurvey().trigger('change', changes)
+      @getSurvey().trigger('change')

       return newRow


Probably want to render not-files too

Probably want to render not-files too

--- src/quest.coffee
+++ src/quest.coffee
@@ -238,7 +238,7 @@
       sqlPath = path.join @sqlPath, queries.file
       console.log ">>".blue.bold, "#{sqlPath}".blue.bold if queries.file
       rawQueries = queries.text or fs.readFileSync(sqlPath, encoding: 'utf-8')
-      queries = render rawQueries, view
+    queries = render rawQueries ? queries, view
     if split
       queries = new Splitter().split queries
     result = null


Fix edit comment (sorta)

Fix edit comment (sorta)

--- lineman/app/modules/discussion_page/thread_card/new_comment_item_controller.coffee
+++ lineman/app/modules/discussion_page/thread_card/new_comment_item_controller.coffee
@@ -42,14 +42,14 @@
       templateUrl: 'generated/modules/discussion_page/comment_form/edit_comment.html'
       controller: 'EditCommentController'
       resolve:
-        comment: -> angular.copy($scope.comment)
+        comment: -> $scope.comment

   $scope.deleteComment = ->
     modalInstance = $modal.open
       templateUrl: 'generated/modules/discussion_page/comment_form/delete_comment.html'
       controller: 'DeleteCommentController'
       resolve:
-        comment: -> angular.copy($scope.comment)
+        comment: -> $scope.comment

   $scope.showContextMenu = ->
     $scope.canEditComment($scope.comment) or $scope.canDeleteComment($scope.comment)


spreadsheet remove-global-record button styling

--- web/volume/spreadsheet.coffee
+++ web/volume/spreadsheet.coffee
@@ -496,11 +496,12 @@
             when 'summary'
               if Editing && info.d.global
                 cell.classList.add('null')
+                $(cell).append('Whole volume')
                 del = cell.appendChild(document.createElement('a'))
                 del.className = 'button mini global-record white icon-text'
                 delicon = del.appendChild(document.createElement('span'))
                 delicon.className = 'icon trash'
-                $(del).append('Remove from whole volume')
+                $(del).append('Remove')
                 $(del).on 'click', $scope.$lift(clickGlobal)
             else
               if info.metric.type == 'void' && info.d


Re-enable pusher. Turn on SSL

Re-enable pusher. Turn on SSL

--- js/inner.coffee
+++ js/inner.coffee
@@ -617,10 +617,10 @@
     @project_map = {}
     observableCount += 8

-    #@setupPusher()
+    @setupPusher()

   setupPusher: () =>
-    @pusher = new Pusher("356b7c379e56e14c261b")
+    @pusher = new Pusher("356b7c379e56e14c261b", { encrypted: true})

     Pusher.channel_auth_endpoint = "/auth/pusher"


When clicking on the invite button, dont propagate the event to the row

--- js/inner.coffee
+++ js/inner.coffee
@@ -346,7 +346,7 @@
         invitee: @user
         vcs_url: @vcs_url()
         build_num: @build_num
-    false
+    event.stopPropagation()

   visit: () =>
     SammyApp.setLocation @url()


Scope.data for old blowsers

Scope.data for old blowsers

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

     if option.data
         scope = option.data
-        Object.setPrototypeOf scope, Scope.prototype
+        if Object.setPrototypeOf
+            Object.setPrototypeOf scope, Scope.prototype
+        else
+            for name of Scope::
+                scope[name] = Scope::[name]
     else
         scope = new Scope


tweak for decimal formatting

tweak for decimal formatting

--- src/util.coffee
+++ src/util.coffee
@@ -92,6 +92,7 @@
     if s.indexOf('e') == -1 and Math.abs(num) > Math.pow(10, 7)
       exp_len = s.length - (if num < 0 then 2 else 1)
       s = num.toExponential(Math.min(exp_len, precision-1))
+      s = s.replace(/\.?0+e/,'e')  # remove trailing zeros before exponent
     else if s.indexOf('.') == -1
       s = num.toFixed(1)
     else


Cache on prototype.

Cache on prototype.

--- src/view.coffee
+++ src/view.coffee
@@ -16,7 +16,7 @@

   cacheTemplate: (el) ->
     # Cache on prototype so it can be reused
-    @_cachedEl = el
+    @::_cachedEl = el

   renderTemplate: (ctx, cache=true) ->
     if @_cachedEl? and cache


add doc

add doc

--- src/view.coffee
+++ src/view.coffee
@@ -18,6 +18,9 @@

   name: () -> 'View' # define name, because not work in IE: constructor.name

+  # @param [String] - selector for element
+  # @param [Function] - transform function for new content
+  #
   constructor: (@element, clb = (txt) -> txt) ->
     @_result_fn = (args...) =>
       clb.apply(null, args...)


rename config option name

rename config option name

--- src/share.coffee
+++ src/share.coffee
@@ -25,7 +25,7 @@
         flyout: 'top center'
         button_text: 'Share'
         button_font: true
-        button_icon: true
+        icon_font: true

       networks:
         google_plus:
@@ -71,7 +71,7 @@
     @normalize_network_configuration()

     ## Inject Icon Fontset
-    @inject_icons() if @config.ui.button_icon
+    @inject_icons() if @config.ui.icon_font

     ## Inject Google's Lato Fontset (if enabled)
     @inject_fonts() if @config.ui.button_font


removing test rooms

removing test rooms

--- server/startup/migrations/v4.coffee
+++ server/startup/migrations/v4.coffee
@@ -21,8 +21,13 @@
 			ChatRoom.update item._id, {$set: {name: name}}
 			ChatSubscription.update {rid: item._id}, {$set: {name: name}}, {multi: true}

-	ChatSubscription.find().forEach (item) ->
-		ChatSubscription.find({'u._id': item.u._id, name: item.name, t: item.t, _id: {$ne: item._id}}).forEach (subItem) ->
-			ChatSubscription.delete subItem._id
+	ChatRoom.find({msgs: {'$lt': 10}}).forEach (room) ->
+		ChatRoom.remove room._id
+		ChatMessage.remove {rid: room._id}
+		ChatSubscription.remove {rid: room._id}
+
+	# ChatSubscription.find().forEach (item) ->
+	# 	ChatSubscription.find({'u._id': item.u._id, name: item.name, t: item.t, _id: {$ne: item._id}}).forEach (subItem) ->
+	# 		ChatSubscription.remove subItem._id

 	console.log 'End'


wallapatta content + images wip

wallapatta content + images wip

--- js/nodes.coffee
+++ js/nodes.coffee
@@ -534,8 +534,8 @@

    type: TYPES.media

-   add: (node) ->
-    throw new Error 'Invalid indentation'
+   #add: (node) ->
+   # throw new Error 'Invalid indentation'

    template: ->
     @$.elem = @div "##{PREFIX}#{@$.id}.image-container", ->
@@ -545,8 +545,8 @@
      if @$.width?
       @$.elems.img.style.maxWidth = "#{@$.width}%"

-   render: (options) ->
-    Weya elem: options.elem, context: this, @template
+   #render: (options) ->
+   # Weya elem: options.elem, context: this, @template

   Mod.set 'Wallapatta.Text', Text


support channel_id in addition to channel_name for send

--- src/slack.coffee
+++ src/slack.coffee
@@ -191,6 +191,7 @@

   send: (envelope, messages...) ->
     channel = @client.getChannelGroupOrDMByName envelope.room
+    channel = @client.getChannelGroupOrDMByID(envelope.room) unless channel

     if not channel and @client.getUserByName(envelope.room)
       user_id = @client.getUserByName(envelope.room).id


Controller::replace should accept jQuery object or DOM Element as an argument

--- src/spine.coffee
+++ src/spine.coffee
@@ -586,7 +586,8 @@
     @el

   replace: (element) ->
-    element = $.trim(element.el or element)
+    element = element.el or element
+    element = $.trim(element) if typeof element is "string"
     [previous, @el] = [@el, $($.parseHTML(element)?[0] or element)]
     previous.replaceWith(@el)
     @delegateEvents(@events)


Fix #143

Fix #143

--- lib/util.coffee
+++ lib/util.coffee
@@ -103,6 +103,7 @@
               timeout: atom.config.get('haskell-ghc-mod.syncTimeout')
           catch error
             Util.warn("Running stack failed with ", error)
+            return null
         if stackpath
           Util.debug("Found stack sandbox ", stackpath)
           apd = stackpath.split(delimiter).concat apd


Journal: Fix typo and missing implementation for changeEdge

--- src/lib/Journal.coffee
+++ src/lib/Journal.coffee
@@ -118,8 +118,8 @@
       @appendCommand 'addEdge', edge
     @graph.on 'removeEdge', (edge) =>
       @appendCommand 'removeEdge', edge
-    @graph.on 'changeEdge', (edge) =>
-      @appendCommand 'removeEdge', edge
+    @graph.on 'changeEdge', (edge, oldMeta) =>
+      @appendCommand 'changeEdge', {from: edge.from, to: edge.to, new: edge.metadata, old: oldMeta}
     @graph.on 'addInitial', (iip) =>
       @appendCommand 'addInitial', iip
     @graph.on 'removeInitial', (iip) =>
@@ -197,6 +197,7 @@
       when 'changeNode' then @graph.setNodeMetadata a.id, calculateMeta(a.old, a.new)
       when 'addEdge' then @graph.addEdge a.from.node, a.from.port, a.to.node, a.to.port
       when 'removeEdge' then @graph.removeEdge a.from.node, a.from.port, a.to.node, a.to.port
+      when 'changeEdge' then @graph.setEdgeMetadata a.from.node, a.from.port, a.to.node, a.to.port, calculateMeta(a.old, a.new)
       when 'addInitial' then @graph.addInitial a.from.data, a.to.node, a.to.port
       when 'removeInitial' then @graph.removeInitial a.to.node, a.to.port
       when 'startTransaction' then null
@@ -224,6 +225,7 @@
       when 'changeNode' then @graph.setNodeMetadata a.id, calculateMeta(a.new, a.old)
       when 'addEdge' then @graph.removeEdge a.from.node, a.from.port, a.to.node, a.to.port
       when 'removeEdge' then @graph.addEdge a.from.node, a.from.port, a.to.node, a.to.port
+      when 'changeEdge' then @graph.setEdgeMetadata a.from.node, a.from.port, a.to.node, a.to.port, calculateMeta(a.new, a.old)
       when 'addInitial' then @graph.removeInitial a.to.node, a.to.port
       when 'removeInitial' then @graph.addInitial a.from.data, a.to.node, a.to.port
       when 'startTransaction' then null


cleaning inline installation script after homepage redesign

--- src/lib/install.coffee
+++ src/lib/install.coffee
@@ -10,10 +10,12 @@
 # Wrap the functionality in a request for Template's details in order to get
 # the ID in use.
 chrome.extension.sendRequest type: 'info', (data) ->
+  # Names of the classes to be added to the targeted elements.
+  newClasses = ['disabled']
   # Names of the classes to be removed from the targeted elements.
-  classes = ['chrome_install_button', 'btn-primary', 'primary']
+  oldClasses = ['chrome_install_button', 'btn-primary']
   # Disable all "Install" links on the homepage for Template.
-  for link in document.querySelectorAll "a.#{classes[0]}[href$=#{data.id}]"
+  for link in document.querySelectorAll "a.#{oldClasses[0]}[href$=#{data.id}]"
     link.innerText = 'Installed'
-    link.classList.add 'disabled'
-    link.classList.remove cls for cls in classes+    link.classList.add    cls for cls in newClasses
+    link.classList.remove cls for cls in oldClasses