stacks: copy changes

stacks: copy changes

--- client/app/lib/providers/computecontroller.ui.coffee
+++ client/app/lib/providers/computecontroller.ui.coffee
@@ -213,25 +213,24 @@
           title   : "Resize VM?"
           message : "
             If you choose to proceed, this VM will be resized #{resizeDetails}.
-            During the resize process, you will not be able to use the VM but
-            all your files, workspaces and data will be safe.
+            During the resize process, you will not be able to use your VM.
+            No need to worry, your files, workspaces and your data therein will be safe.
           "
           button  : "Proceed"
         reinit    :
           title   : "Reinitialize VM?"
           message : "
-            If you choose to proceed, this VM will be reset to default state.
-            You will lose all your files, workspaces, collaboration sessions and data but your VM
-            settings (VM aliases, sub-domains etc.) will not be lost.
+            If you choose to proceed, this VM will be reset to its default state.
+            That means you will lose all of its data i.e. your files, workspaces, collaboration
+            sessions. Your VM settings however, (VM aliases, sub-domains etc.) will not be lost.
           "
           button  : "Proceed"
         reinitStack :
           title   : "Reinitialize Stack?"
           message : "
-            If you choose to proceed, this stack and all the VMs will be
+            If you choose to proceed, this stack and all of its VMs will be
             re-initialized from the latest revision of this stack.
-            You will lose all of your existing files, workspaces, VMs and all
-            of your data.
+            You will lose all of your existing VMs, workspaces and your data therein.
           "
           button  : "Proceed"
         deleteStack :
@@ -247,17 +246,17 @@
         forceDeleteStack :
           title   : "Delete Stack data?"
           message : "
-
If you choose to proceed, all the meta data and related
-            informations for this stack will be removed from Koding.

+
If you choose to proceed, all of the meta data and related
+            information for this stack will be removed from Koding.

-              WARNING! This action won't destroy created resources in your
-              stack provider, you need to cleanup those resources
+              WARNING! This action won't destroy created resources on your
+              stack provider, you need to perform a cleanup for those resources
               (such as VMs, domains, security groups etc.) manually.

-
With this action you'll remove all the connection between
-            this stack on Koding and related resources on stack provider.

+
With this action you'll remove the connection between
+            this stack on Koding and related resources on your stack provider.

Do you want to continue?

           "


ComputeController.UI: copy updates for github/oauth flow

--- client/app/lib/providers/computecontroller.ui.coffee
+++ client/app/lib/providers/computecontroller.ui.coffee
@@ -386,29 +386,29 @@
           message : '
By clicking Yes, You will not recieve anymore update for this stack.
'
           button  : 'Yes'
         enableTeamOAuth :
-          title   : 'Do you want to setup organization token?'
+          title   : 'Do you want to setup as organization token?'
           message : applyMarkdown "
             In order to use and share GitHub organization tokens with admins
-            you can set a team token for your team. You need to be organization
-            admin on GitHub and a team admin on Koding. \n\n
-
-            This will require you to allow `#{options.scope}` scopes with your
+            you can set a team token for your team. For this, you need to be
+            organization admin on GitHub and a team admin on Koding. \n\n
+
+            You will need to allow `#{options.scope}` scopes with your
             integration. \n\n

             Do you want to enable your GitHub integration with these scopes or
             do you want to setup this integration as a regular user?
           "
-          button  : 'Yes, Setup as Organization'
-          cancel  : 'No, Setup as User'
+          button  : 'Setup as Organization'
+          cancel  : 'Setup as User'
         disableTeamOAuth :
           title   : 'Do you want to disable organization token?'
-          message : applyMarkdown "
+          message : applyMarkdown '
             Currently your GitHub token is also set as default for team
-            integration, if you continue this integration will be removed
+            integration, if you continue, this integration will be removed
             as well.\n\n

             Do you want to continue?
-          "
+          '
           button  : 'Yes, Disable Integration'
       managed     :
         destroy   :


Integrates score manager

Integrates score manager

--- coffee/presenters/home_presenter.coffee
+++ coffee/presenters/home_presenter.coffee
@@ -6,7 +6,7 @@
     @car = new Car('.js-car', @grid, CONFIG.carSpeed)

   _initRideEngine: () ->
-    @rideEngine = new RideEngine(@grid, @car, 5 * 1000, 10 * 1000)
+    @rideEngine = new RideEngine(@grid, @car)
     @rideEngine.setPickupFrequency CONFIG.pickupFrequency
     @rideEngine.setPickupDuration CONFIG.pickupDuration
     @rideEngine.setPickupAnimationDelay CONFIG.pickupAnimationDelay
@@ -26,6 +26,8 @@
     @scoreManager.setBonusTip CONFIG.bonusTip
     @scoreManager.setTipSpeedRatio CONFIG.tipSpeedRatio

+    EventBus.get('ScoreManager').register(GameOverEvent.NAME, (z) => @onGameOver(z))
+
   onStart: () ->
     @grid = new Grid('.js-map', 200, 10)
     @grid.render()
@@ -34,6 +36,7 @@

     @_initCar()
     @_initRideEngine()
+    @_initScoreManager()

     @userEngine = new UserEngine('.js-user-list', '.js-user-card')

@@ -50,4 +53,8 @@
     id = e.getZone().getId()
     o = @currentRides[e.getZone().getId()]
     @userEngine.hide(o.user)
-    delete @currentRides[id]+    delete @currentRides[id]
+
+  onGameOver: (e) ->
+    alert('game over')
+    @rideEngine.stop()


fix private link weirdness

fix private link weirdness

--- components/block_collection/client/block_view.coffee
+++ components/block_collection/client/block_view.coffee
@@ -69,10 +69,7 @@
     e.stopImmediatePropagation()

     if @model.get('visibility') is 'private'
-      site = window.open "#{Math.random() * 100}", "hide_referrer"
-      site.document.open()
-      site.document.writeln '<script type="text/javascript">window.location = "' + "#{sd.APP_URL}/go?redirect-to=#{url}" + '";</script>'
-      site.document.close()
+      site = window.open "#{sd.APP_URL}/go?redirect-to=#{url}", "_blank"
     else
       window.open url,'_blank'
       return false


fixed bug: build not handling latexmk emergency stops

(just spelling)

--- lib/parsers/parse-tex-log.coffee
+++ lib/parsers/parse-tex-log.coffee
@@ -304,7 +304,7 @@
       debug("Reporting error in line: " + line)
       # We check for emergency stops here, too, because it may occur before the l.nn text
       if line.length>0 && line.indexOf("! Emergency stop.") >= 0
-        emergency_stop = True
+        emergency_stop = true
         debug("Emergency stop found")
         continue
       err_match = line_rx.exec(line)


Fixed invalid json in API query results. Added total count in response header.

--- api.coffee
+++ api.coffee
@@ -323,17 +323,19 @@

         cur.skip(parseInt(urlParts.query.skip)) if urlParts.query.skip?
         cur.limit(parseInt(urlParts.query.limit)) if urlParts.query.limit?
-
-        response.writeHead(200, {'Content-Type' : 'application/json'})
-        response.write("[\n")
-        cur.each((err, item) ->
-          if item is null
-            response.end(']')
-          else
-            addAliases(item) if collectionName is 'devices'
-            response.write(JSON.stringify(item) + ",\n")
+        cur.count((err, total) ->
+          response.writeHead(200, {'Content-Type' : 'application/json', 'total' : total})
+          response.write("[\n")
+          i = 0
+          cur.each((err, item) ->
+            if item is null
+              response.end("\n]")
+            else
+              response.write(",\n") if i++
+              addAliases(item) if collectionName is 'devices'
+              response.write(JSON.stringify(item))
+          )
         )
-        return
       else
         response.writeHead 404
         response.end('404 Not Found')


Added documentation to gameManager

Added documentation to gameManager

--- web/scripts/gameManager.coffee
+++ web/scripts/gameManager.coffee
@@ -3,14 +3,25 @@
     log = (mesg) -> console.log(mesg)
 else
     log = (mesg) -> null
-
+
 log("GameManager log")
+
+# Some browsers have a deepcopy function, others do not.
+# For those who do not, we use the JQuery deepcopy function.
 if not deepcopy?
-    deepcopy = (src) -> $.extend(true, {},src)
+    deepcopy = (src) -> $.extend(true, {}, src)

 class window.GameManager
-    #environment is defined in codeland.startGame
     constructor: (@environment) ->
+        ###
+            External Function (used by something outside of this file)
+
+            Takes in the game environment and sets up the code editor and
+            the game visual and the game logic.
+
+            @param environment
+                The environment and configuration required for this game.
+        ###
         @config = deepcopy @environment.description
         @gameStateBase = @environment.gameState

@@ -20,11 +31,20 @@
         return

     storeStats: ->
-        @environment.codeland.storeGameStats @environment.key, @environment.stats
+        ###
+            Internal Function (used only by the code in this file)
+
+            Saves the game statistics to codeland.
+        ###
+        @environment.codeland.storeGameStats @environment.key, @environment.stats
+        return

     setUpGame: ->
         ###
+            Internal Function (used only by the code in this file)
+
             Sets up everything for the game to run.
+            That is, the code editor, the game visual and the event listeners.
         ###
         @gameDiv = jQuery @environment.gamediv
         @gameDiv.empty()
@@ -66,11 +86,22 @@
         return

     gameName: () =>
+        ###
+            Internal Function (used only by the code in this file)
+
+            Returns the key of the current game.
+        ###
         return @environment.key

-#Note this does not mean run the student's code. Rather it's the entry point to show animations and start the desired game map as a live experience.
     startGame: (waitForCode) =>
-        #TODO Explain purpose of waitForCode
+        ###
+            Internal Function (used only by the code in this file)
+
+            This starts the game's visual and initializes the logic for the game.
+
+            @param waitForCode
+                Whether the game logic should wait for the code to begin running.
+        ###
         waitForCode ?= false

         @visual.startGame @config.visual
@@ -79,6 +110,12 @@
         return

     interpretGameConfigMap: ->
+        ###
+            Internal Function (used only by the code in this file)
+
+            Parses the map found in the game's config file and creates
+            the necessary characters in the visual and in the gameManager.
+        ###
         x = @config.game.offset.x ?=0
         y = @config.game.offset.y ?=0
         map = @config.game.map ?= ""
@@ -98,6 +135,26 @@
         return

     generateCharacter: (name, x, y, staysOnReset, dir) ->
+        ###
+            External Function (used by something outside of this file)
+
+            Creates a character using the defaults found in the config file,
+            overwriting them as necessary and generating an appropriate name.
+            Places this character in the visual config and in the game's config
+            and makes sure the victory flag is the first item in the visual
+            config's array.
+
+            @param name
+                The name of the type of character to create
+            @param x
+                The x location of the character
+            @param y
+                The y location of the character
+            @param staysOnReset
+                Whether this character is a permanent part of the game
+            @param dir
+                The direction the character is facing
+        ###
         base = deepcopy @config.game.characterBase[name]
         visualBase = deepcopy @config.visual.visualBase[base.sprite]
         base.x = x
@@ -136,18 +193,33 @@
             @config.game.characters[name] = base
         return {'game': base, 'visual': visualBase}

-    #Callback for games
     gameLost: ->
+        ###
+            External Function (used by something outside of this file)
+
+            Updates the game statistics on the loss, plays the losing sound,
+            and summons the game lost cloud.
+        ###
         @updateGameLostStats()
         playAudio 'defeat.ogg'
-
+
         messages = ["Try Again!"]
         window.objCloud(400,messages,"body","30%","30%",3,"none",@gameManager)
         @gameRunFinished()
-
-    #Callback for games
-    gameWon: ->
-        @updateGameWonStats()
+
+    gameWon: (score, stars) ->
+        ###
+            External Function (used by something outside of this file)
+
+            Updates the game statistics on the win, plays the winning sound,
+            and summons the game won cloud.
+
+            @param score
+                The score the player achieved during this play of the game.
+            @param stars
+                How many stars the player earned during this play of the game.
+        ###
+        @updateGameWonStats score, stars
         playAudio 'victory.ogg'

         gameName = @gameName()
@@ -161,16 +233,35 @@
         messages = ['Congratulations!']
         window.objCloud 400, messages, "body",  "30%", "30%", 1.5, gameName, @
         @gameRunFinished()
-
+
     updateGameLostStats: ->
+        ###
+            Internal Function (used only by the code in this file)
+
+            Creats the losing statistics and saves them to codeland.
+        ###
         s = @environment.stats
-        s.lostCount+= 1
+        s.lostCount += 1
         s.lastLoss = Date.now()
         s.firstLoss = s.lastLoss unless s.firstLoss
         @storeStats()
-
-    #Callback for games
+
     updateGameWonStats: (score, stars) ->
+        ###
+            Internal Function (used only by the code in this file)
+
+            Creates the statistics of the won game and saves them
+            to codeland.
+
+            @param score
+                The score the player achieved during this play of the game.
+            @param stars
+                How many stars the player earned during this play of the game.
+
+            @return
+                Whether or not this achieved score is a new high score for the
+                player.
+        ###
         log "Game Won: #{@environment.key}"
         s = @environment.stats
         s.winCount += 1
@@ -178,15 +269,20 @@
         s.lastWin = Date.now()
         s.firstWin = s.lastWin unless s.firstWin
         s.stars = Math.max(stars, s.stars)
-
+
         isNewHiscore = s.hiscore < score
-        s.hiscore = score if(isNewHiscore)
-
+        s.hiscore = score if(isNewHiscore)
+
         @storeStats()
         #Other celebrations after storeStats
         return isNewHiscore

     finishGame: ->
+        ###
+            External Function (used by something outside of this file)
+
+            Stops the current game and uninitializes used classes.
+        ###
         @gameState?.stopGame()
         @codeEditor = null
         @interpreter = null
@@ -196,6 +292,11 @@
         return

     addEventListeners: ->
+        ###
+            Internal Function (used only by the code in this file)
+
+            Sets up the event listeners the game manager responds to.
+        ###
         jQuery('#compileAndRun').click @runStudentCode
         jQuery('#stopRun').click @stopStudentCode
         jQuery('#resetState').click @reset
@@ -205,6 +306,16 @@
         return

     commandsValid: (valid) =>
+        ###
+            External Function (used by something outside of this file)
+            Event Function (passed in as a callback or bound to a button press)
+
+            Disables the run button should the commands in the editor be
+            invalid, enables the run button should they be valid.
+
+            @param valid
+                Whether or not the code in the code editor is valid.
+        ###
         if valid
             jQuery('#compileAndRun').attr 'disabled', false
             @canRun = true
@@ -214,24 +325,35 @@
         return

     reset: =>
+        ###
+            Event Function (passed in as a callback or bound to a button press)
+
+            Resets the code editor and the visual.
+        ###
         @environment.stats.resetCount += 1
-        @storeStats()
-
+        @storeStats()
+
         @codeEditor.resetEditor()
         @startGame false
         return

     runStudentCode: =>
+        ###
+            Event Function (passed in as a callback or bound to a button press)
+
+            Scans the code from the code editor and begins running the student's
+            code.
+        ###
         if @running
             return
         @running = true
         code = @codeEditor.getStudentCode()
         jQuery('#compileAndRun').hide()
         jQuery('#stopRun').show()
-
+
         @environment.stats.runCount += 1
-        @storeStats()
-
+        @storeStats()
+
         if @environment.backEnd == 'interpreter'
             @codeEditor.scan()
             if not @canRun
@@ -258,10 +380,15 @@
         return false

     stopStudentCode: =>
+        ###
+            Event Function (passed in as a callback or bound to a button press)
+
+            Stops running the student's code and resets the visual.
+        ###
         if not @running
             return
         @environment.stats.abortCount +=1
-        @storeStats()
+        @storeStats()
         if @environment.backEnd == 'doppio'
             @environment.codeland.doppioAPI.abort @showRun
         else
@@ -270,18 +397,35 @@
         return false

     showRun: =>
+        ###
+            Internal Function (used only by the code in this file)
+
+            Shows the run button.
+        ###
         jQuery('#stopRun').hide()
         jQuery('#compileAndRun').show()
         @running = false
         return

     gameRunFinished: ->
+        ###
+            Internal Function (used only by the code in this file)
+
+            Called when a run has finished, currently only re-displays
+            the run button.
+        ###
         @showRun()
         return

     helpTips:=>
+        ###
+            Event Function (passed in as a callback or bound to a button press)
+
+            Summons the help tips cloud to display the tips associated with
+            this game.
+        ###
         @environment.stats.tipsCount +=1
-        @storeStats()
+        @storeStats()
         ma = @config?.code?.comments
         if ma
             if ma.length > 1


Fixes #17

Fixes #17

--- web/scripts/referenceUI.coffee
+++ web/scripts/referenceUI.coffee
@@ -69,10 +69,7 @@

     $(dictionary).css({width:'35%',height:'90%',position:'absolute',left:'5%',top:'5%',bottom:'80%','border':'1px solid black'})
     $(input).css({width:'50%',height:'40%',position:'absolute',right:'5%',top:'5%','border':'1px solid black'})
-    $(output).css(
-        {width:'50%',height:'40%',position:'absolute',
-        right:'5%',top:'50%','border':'1px solid black',
-        "overflow":"auto"})
+    $(output).css({width:'50%',height:'45%',position:'absolute',right:'5%',top:'50%','border':'1px solid black',"overflow":"auto"})

     $(refContainer).prepend(dictionary)
     $(refContainer).prepend(input)
@@ -124,7 +121,7 @@

         $(dictionary).animate({width:'35%',height:'90%',opacity:'1'})
         $(input).animate({width:'50%',height:'40%',opacity:'1'})
-        $(output).animate({width:'50%',height:'45%',opacity:'1',top:'50%'})
+        $(output).animate({width:'50%',height:'40%',opacity:'1',top:'50%'})

         $(".en").hover(enHover,lvHover)
         $(".en").click(enClick)


Refactor - set port variable before configuration

fetching the port from the config involves a get method call, which can be confused with a GET route to the untrained eye.

--- app.coffee
+++ app.coffee
@@ -14,9 +14,10 @@
 socketIoApp = io.listen 3005
 socketIoRoutes = routes socketIoApp

+port = process.env.PORT || 3004
 webApp = express()
 webApp.configure ->
-  webApp.set 'port', process.env.PORT || 3004
+  webApp.set 'port', port
   webApp.use express.logger 'dev'
   webApp.use express.bodyParser()
   webApp.use express.errorHandler()
@@ -24,6 +25,5 @@

 webApp.post '/', socketIoRoutes.index

-port = webApp.get 'port'
 webApp.listen port, ->
   logger.info "Flumen server listening on port #{port}"


process.env.REDISCLOUD_URL >> process.env.REDIS_URL, set cookie maxAge and name

--- app.coffee
+++ app.coffee
@@ -16,11 +16,15 @@
 sessionOptions = {
     secret: process.env.EXPRESS_SESSION_SECRET or 'keyboard cat',
     resave: false,
-    saveUninitialized: false
+    saveUninitialized: false,
+    cookie: {
+        maxAge: 2592000000          # 30 days
+        name: 'protected-s3.sid',
+    }
 }

 if process.env.USE_REDIS_SESSION is '1'
-    redisURL = require('redis-url').connect(process.env.REDISCLOUD_URL)
+    redisURL = require('redis-url').connect(process.env.REDIS_URL)
     options =
         host: redisURL.hostname
         port: redisURL.port


silly people with bad email verification

--- app.coffee
+++ app.coffee
@@ -111,7 +111,7 @@
 <!DOCTYPE html>

 <meta charset="utf-8">
-<title>Password Reset Sent</title>
+<title>Authentication Successful!</title>
 <link href='http://fonts.googleapis.com/css?family=Lato:300' rel='stylesheet' type='text/css'>
 <h1 style="
 max-width: 500px;
@@ -123,7 +123,21 @@

           """)
       .fail (err) ->
-        res.send(err)
+        res.send """
+<!DOCTYPE html>
+
+<meta charset="utf-8">
+<title>Error!</title>
+<link href='http://fonts.googleapis.com/css?family=Lato:300' rel='stylesheet' type='text/css'>
+
Sorry, an error occured.
Please try again later.

+
+            """

   # -----
@@ -266,7 +280,7 @@
 <!DOCTYPE html>

 <meta charset="utf-8">
-<title>Password Reset Sent</title>
+<title>Error!</title>
 <link href='http://fonts.googleapis.com/css?family=Lato:300' rel='stylesheet' type='text/css'>
 <h1 style="
 max-width: 500px;
@@ -287,7 +301,7 @@
         return res.status(401).send """<!DOCTYPE html>

 <meta charset="utf-8">
-<title>Password Reset Sent</title>
+<title>Passwords do not match!</title>
 <link href='http://fonts.googleapis.com/css?family=Lato:300' rel='stylesheet' type='text/css'>
 <h1 style="
 max-width: 500px;
@@ -310,7 +324,7 @@
             res.send """<!DOCTYPE html>

 <meta charset="utf-8">
-<title>Password Reset Sent</title>
+<title>Password Changed</title>
 <link href='http://fonts.googleapis.com/css?family=Lato:300' rel='stylesheet' type='text/css'>
 <h1 style="
 max-width: 500px;


Do bulk rejects in reverse order.

Do bulk rejects in reverse order.

--- services/web/public/coffee/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.coffee
+++ services/web/public/coffee/ide/editor/directives/aceEditor/track-changes/TrackChangesManager.coffee
@@ -214,6 +214,8 @@
 		rejectChangeIds: (change_ids) ->
 			changes = @rangesTracker.getChanges(change_ids)
 			return if changes.length == 0
+			changes.sort((a, b) -> b.op.p - a.op.p)
+
 			session = @editor.getSession()
 			for change in changes
 				if change.op.d?


Upgrade tag-create-view

Upgrade tag-create-view

--- lib/views/tag-create-view.coffee
+++ lib/views/tag-create-view.coffee
@@ -2,7 +2,8 @@
 Path = require 'path'
 fs = require 'fs-plus'

-{$, BufferedProcess, EditorView, View} = require 'atom'
+{BufferedProcess} = require 'atom'
+{$, TextEditorView, View} = require 'atom-space-pen-views'
 StatusView = require './status-view'
 git = require '../git'

@@ -12,9 +13,9 @@
   @content: ->
     @div class: 'overlay from-top', =>
       @div class: 'block', =>
-        @subview 'tagName', new EditorView(mini: true, placeholderText: 'Tag')
+        @subview 'tagName', new TextEditorView(mini: true, placeholderText: 'Tag')
       @div class: 'block', =>
-        @subview 'tagMessage', new EditorView(mini: true, placeholderText: 'Annotation message')
+        @subview 'tagMessage', new TextEditorView(mini: true, placeholderText: 'Annotation message')
       @div class: 'block', =>
         @span class: 'pull-left', =>
           @button class: 'btn btn-success inline-block-tight gp-confirm-button', click: 'createTag', 'Create Tag'
@@ -22,12 +23,13 @@
           @button class: 'btn btn-error inline-block-tight gp-cancel-button', click: 'abort', 'Cancel'

   initialize: ->
-    atom.workspaceView.append this
+    @panel ?= atom.workspace.addModalPanel(item: this)
+    @panel.show()
     @tagName.focus()
-    @on 'core:cancel', => @abort()
+    @on 'core:cancel', => @destroy()

   createTag: ->
-    tag = name: @tagName.text().slice(2), message: @tagMessage.text().slice(2)
+    tag = name: @tagName.getModel().getText(), message: @tagMessage.getModel().getText()
     new BufferedProcess
       command: 'git'
       args: ['tag', '-a', tag.name, '-m', tag.message]
@@ -37,7 +39,7 @@
         new StatusView(type: 'alert', message: data.toString())
       exit: (code) ->
         new StatusView(type: 'success', message: "Tag '#{tag.name}' has been created successfully!") if code is 0
-    @detach()
+    @destroy()

-  abort: ->
-    @detach()
+  destroy: ->
+    @panel.destroy()


only parameterize form title if exists

only parameterize form title if exists

--- _source/client/templates/components/forms/form.coffee
+++ _source/client/templates/components/forms/form.coffee
@@ -17,8 +17,9 @@

   paramaterize: (string) ->
-    string = string.trim()
-    string = string.replace /[^a-zA-Z0-9-\s]/g, ''
-    string = string.replace /[^a-zA-Z0-9-]/g, '-'
-    string = string.toLowerCase()
-    return string
+    if not string is undefined
+      string = string.trim()
+      string = string.replace /[^a-zA-Z0-9-\s]/g, ''
+      string = string.replace /[^a-zA-Z0-9-]/g, '-'
+      string = string.toLowerCase()
+      return string


unmount recusive calls

unmount recusive calls

--- app/assets/javascripts/components/yale-home-page.cjsx
+++ app/assets/javascripts/components/yale-home-page.cjsx
@@ -31,6 +31,10 @@
   componentWillMount: ->
     @requestImageUpdate()

+  componentWillUnmount: ->
+    this.requestImageUpdate = null
+    this.updateImage = null
+
   componentWillReceiveProps: (new_props) ->
     @setState project: new_props.project

@@ -43,48 +47,52 @@
   requestImageUpdate: ->
     self = this
     setTimeout ( ->
-      self.updateImage()
+      try
+        self.updateImage()
+      catch e
     ), 6000

   updateImage: ->
     # first make the foreground and the background the same
-    self = this
-    currentBackgroundIndex = @state.backgroundImageIndex
-    currentBackgroundPosition = @state.backgroundImagePosition
-    nextIndexPosition = (currentBackgroundIndex+1) % 5
-    nextBackgroundPosition = @state.backgroundPositions[nextIndexPosition]
+    try
+      self = this
+      currentBackgroundIndex = @state.backgroundImageIndex
+      currentBackgroundPosition = @state.backgroundImagePosition
+      nextIndexPosition = (currentBackgroundIndex+1) % 5
+      nextBackgroundPosition = @state.backgroundPositions[nextIndexPosition]

-    @setState({
-      foregroundImageIndex: currentBackgroundIndex,
-      backgroundImageIndex: currentBackgroundIndex,
-      foregroundImagePosition: currentBackgroundPosition,
-      backgroundImagePosition: currentBackgroundPosition
-    })
+      @setState({
+        foregroundImageIndex: currentBackgroundIndex,
+        backgroundImageIndex: currentBackgroundIndex,
+        foregroundImagePosition: currentBackgroundPosition,
+        backgroundImagePosition: currentBackgroundPosition
+      })

-    # then remove opacity from the background image
-    setTimeout ( ->
-      self.setState({
-        backgroundImageOpacity: 0
-      })
-    ), 500
+      # then remove opacity from the background image
+      setTimeout ( ->
+        self.setState({
+          backgroundImageOpacity: 0
+        })
+      ), 500

-    # next set the background image to the next image to display
-    setTimeout ( ->
-      self.setState({
-        backgroundImageIndex: nextIndexPosition,
-        backgroundImagePosition: nextBackgroundPosition
-      })
-    ), 2000
+      # next set the background image to the next image to display
+      setTimeout ( ->
+        self.setState({
+          backgroundImageIndex: nextIndexPosition,
+          backgroundImagePosition: nextBackgroundPosition
+        })
+      ), 2000

-    # then fade the new background into view
-    setTimeout ( ->
-      self.setState({
-        backgroundImageOpacity: 1
-      })
-    ), 4000
+      # then fade the new background into view
+      setTimeout ( ->
+        self.setState({
+          backgroundImageOpacity: 1
+        })
+      ), 4000

-    # then place the next update cycle on the call stack
-    self.requestImageUpdate()
+      # then place the next update cycle on the call stack
+      self.requestImageUpdate()
+    catch e

   render:->


Improved setting of player width (fixes hud size)

--- app/assets/javascripts/player/renderers/pre.js.coffee
+++ app/assets/javascripts/player/renderers/pre.js.coffee
@@ -25,8 +25,8 @@
     width = @cols * @cellWidth
     height = @lines * @cellHeight

-    @$el.parent('.player').css(width: width + 'px')
     @$el.css(width: width + 'px', height: height + 'px')
+    @$el.parent('.player').css(width: @$el.outerWidth() + 'px')

   render: (changes, cursorX, cursorY) ->
     @$el.find('.cursor').removeClass('cursor')


Removed large comment chunk

Removed large comment chunk

--- app/assets/javascripts/refinery/menu_editor.js.coffee
+++ app/assets/javascripts/refinery/menu_editor.js.coffee
@@ -1,5 +1,9 @@
 #= require ./helpers
 #= require ./menu_link_views
+
+###########
+# EDITORS #
+###########

 class NewCustomLinkEditor

@@ -18,6 +22,10 @@
     return false

+##############
+# INDEX VIEW #
+##############
+
 class MenuLinkIndex

   constructor: ->
@@ -28,35 +36,6 @@
     @$container.append(link_view.el)

-#class CustomMenuLink
-#
-#  constructor: (url, label, title_attribute) ->
-#    @url = url
-#    @label = label
-#    @title_attribute = title_attribute || ""
-#    console.log @title_attribute
-#    @el = $(@render())
-#    @el.find('.header').click =>
-#      @el.find('.body').slideToggle()
-#
-#  type_name: =>
-#    "Custom Link"
-#
-#  render: =>
-#    "
" +
-#      "
" +
-#        "
#{@label}
" +
-#        "
#{@type_name()}
" +
-#        " " +
-#      "
" +
-#      "
" +
-#        ViewHelpers.input_tag('url', @url) +
-#        ViewHelpers.input_tag('label', @label) +
-#        ViewHelpers.input_tag('title_attribute', @title_attribute) +
-#      "
" +
-#    "
"
-
-
 $('document').ready ->
   new NewCustomLinkEditor
   window.menuLinkIndex = new MenuLinkIndex


Add a few languages for the language drop-down

--- app/assets/javascripts/rglossa/translations/en.coffee
+++ app/assets/javascripts/rglossa/translations/en.coffee
@@ -8,4 +8,7 @@
     "no": [null, "Norwegian"]
     "nb": [null, "Norwegian bokmål"]
     "nn": [null, "Norwegian nynorsk"]
-    "ru": [null, "Russian"]+    "ru": [null, "Russian"]
+    "fr": [null, "French"]
+    "it": [null, "Italian"]
+    "se": [null, "Swedish"]


Object bindings support for binding a lambda function

--- lib/ST/Object.coffee
+++ lib/ST/Object.coffee
@@ -179,10 +179,13 @@
   @hybridMethod 'bind', (trigger, receiver, selector) ->
     @_bindings ||= {}
     @_bindings[trigger] ||= []
-    @_bindings[trigger].push {
-      receiver: receiver,
-      selector: selector || trigger
-    }
+    if typeof receiver == 'function' && receiver[selector || trigger] is undefined
+      @_bindings[trigger].push { fn: receiver }
+    else
+      @_bindings[trigger].push {
+        receiver: receiver,
+        selector: selector || trigger
+      }

   @hybridMethod 'unbindOne', (trigger, receiver) ->
     if @_bindings && @_bindings[trigger]
@@ -213,7 +216,9 @@
   @hybridMethod 'trigger', (trigger, passArgs...) ->
     if @_bindings && @_bindings[trigger]
       for target in @_bindings[trigger]
-        if target.receiver[target.selector]
+        if target.fn
+          target.fn this, passArgs...
+        else if target.receiver[target.selector]
           target.receiver[target.selector] this, passArgs...
         else
           ST.error "Error triggering binding from #{this}: #{trigger} to #{target.receiver}.#{target.selector}"


:art: LinterHack -> AtomHack

:art: LinterHack -> AtomHack

--- lib/atom-hack.coffee
+++ lib/atom-hack.coffee
@@ -1,5 +1,5 @@

-module.exports = LinterHack =
+module.exports = AtomHack =
   Hack: null
   activate: ->
     @Hack = new (require './hack')
@@ -17,10 +17,10 @@
       scope: 'project'
       lintOnFly: false
       normalizePath: (FilePath)->
-        if LinterHack.Hack.config.type is 'local'
+        if AtomHack.Hack.config.type is 'local'
           return FilePath
         else
-          Path.join(atom.project.getPaths()[0], Path.relative(LinterHack.Hack.config.remoteDir, FilePath).replace('/', Path.sep))
+          Path.join(atom.project.getPaths()[0], Path.relative(AtomHack.Hack.config.remoteDir, FilePath).replace('/', Path.sep))
       formatErrors: (Content)->
         ToReturn = []
         Content.errors.forEach (ErrorEntry)->
@@ -45,12 +45,12 @@
       lint: (ActiveEditor)->
         return new Promise (Resolve)->
           FilePath = ActiveEditor.getPath()
-          return Resolve([]) unless FilePath or LinterHack.Hack.config.status # Files that have not be saved
-          if LinterHack.Hack.config.type is 'local' or not LinterHack.Hack.config.autoPush
-            LePromise = LinterHack.Hack.exec('hh_client --json', Path.dirname(FilePath))
+          return Resolve([]) unless FilePath or AtomHack.Hack.config.status # Files that have not be saved
+          if AtomHack.Hack.config.type is 'local' or not AtomHack.Hack.config.autoPush
+            LePromise = AtomHack.Hack.exec('hh_client --json', Path.dirname(FilePath))
           else
-            LePromise = LinterHack.Hack.transfer(FilePath).then ->
-              LinterHack.Hack.exec('hh_client --json', Path.dirname(FilePath))
+            LePromise = AtomHack.Hack.transfer(FilePath).then ->
+              AtomHack.Hack.exec('hh_client --json', Path.dirname(FilePath))
           LePromise.then (Data)->
             try
               Content = JSON.parse(Data.stderr)


reorder for a nicer follow in and out

reorder for a nicer follow in and out

--- library/membrane/document.coffee
+++ library/membrane/document.coffee
@@ -93,17 +93,6 @@
             reasoning: reasoning
             code: code

-    # Either get or set the relevant information of the method that
-    # is being described by this document. If you do no supply any
-    # arguments this method will return already described failures.
-    # The relevant should be a string that contains a valid URL.
-    relevant: (relevant) ->
-        return @$relevant if arguments.length is 0
-        noRelevant = "the relevant should be a string"
-        assert _.isString(relevant), noRelevant
-        @emit.call this, "relevant", arguments...
-        return (@$relevant ?= []).push relevant
-
     # Either get or set the produces information of the method that
     # is being described by this document. If you do no supply any
     # arguments this method will return already described failures.
@@ -128,6 +117,18 @@
         @emit.call @, "consumes", @$consumes, arguments
         assert _.isArray @$consumes; return @$consumes

+    # Either get or set the relevant information of the method that
+    # is being described by this document. If you do no supply any
+    # arguments this method will return already described failures.
+    # The relevant should be a string that contains a valid URL.
+    relevant: (relevant) ->
+        return @$relevant if arguments.length is 0
+        notString = "a relevant should be a string"
+        assert _.all(relevant, _.isString), notString
+        @$relevant = (@$relevant or []).concat relevant
+        @emit.call @, "relevant", @$relevant, arguments
+        assert _.isArray @$relevant; return @$relevant
+
     # Either get or set the markings information of the method that
     # is being described by this document. If you do no supply any
     # arguments this method will return already described failures.
@@ -136,7 +137,7 @@
         return @$markings if arguments.length is 0
         noMarkings = "the markings should be a object"
         assert _.isObject(markings), noMarkings
-        assert _.extend (@$markings ?= {}), markings
+        assert _.extend @$markings ?= {}, markings
         @emit.call @, "markings", arguments...
         assert @$markings; return @$markings

@@ -148,7 +149,7 @@
         return @$schemas if arguments.length is 0
         noSchemas = "the schemas should be a object"
         assert _.isObject(schemas), noSchemas
-        assert _.extend (@$schemas ?= {}), schemas
+        assert _.extend @$schemas ?= {}, schemas
         @emit.call this, "schemas", arguments...
         assert @$schemas; return @$schemas


additions to the docs in the document module

--- library/membrane/document.coffee
+++ library/membrane/document.coffee
@@ -40,12 +40,14 @@
 # and expected way, so that it can later be used to programmatically
 # process such documentation and do with it whatever is necessary.
 # This approach gives unique ability to build self documented APIs.
+# So this class is basically a typed, programmatic data storage.
 module.exports.Document = class Document extends Archetype

     # Either get or set the argument information of the method that
     # is being described by this document. If you do no supply any
     # arguments this method will return already described arguments.
     # Argument consists of name, approximate type and description.
+    # The information is being stored as a structured data object.
     argument: (identify, typeable, description) ->
         return @$argument if arguments.length is 0
         noIdentify = "the identify param is not a string"
@@ -62,8 +64,9 @@

     # Either get or set the Github information of the method that
     # is being described by this document. If you do no supply any
-    # arguments this method will return already described failures.
+    # arguments this method will return already described Github.
     # Each consists of a username, the repository name and the path.
+    # The information is being stored as a structured data object.
     github: (username, repository, path) ->
         return @$github if arguments.length is 0
         noUsername = "the username must be a string"
@@ -82,6 +85,7 @@
     # is being described by this document. If you do no supply any
     # arguments this method will return already described failures.
     # Each failure consists of the expected code and reason for fail
+    # The information is being stored as a structured data object.
     failure: (code, reasoning) ->
         return @$failure if arguments.length is 0
         noCode = "the supplied code is not a number"


Some minor reordering

Some minor reordering

--- library/membrane/validate.coffee
+++ library/membrane/validate.coffee
@@ -126,6 +126,22 @@
         assert params = request.params, notParams
         return @value params, name, message

+    # Given the request with possible validation contexts appended
+    # run all the validator contexts in parallel and wait for the
+    # completion. If no validation mistakes found, run continuation.
+    # If some mistakes are found, however, `@renderParamValidation`.
+    validateParameters: (request, response, continuation) ->
+        notRequest = "a #{request} is not a request"
+        notResponse = "a #{response} is not a response"
+        notContinuation = "a #{continuation} is not function"
+        assert _.isFunction(continuation), notContinuation
+        assert _.isObject(response), notResponse
+        assert _.isObject(request), notRequest
+        @validateValues request.params, (failure, results) ->
+            signature = [results, request, response, continuation]
+            return @renderParamValidation signature... if failure
+            return continuation.bind(this) failure, results
+
     # This method is a default implementation of the renderer that
     # will be called when the validation has failed. You can easily
     # override it in either your service or in an external compound.
@@ -139,22 +155,6 @@
         strings = _.map results, (e) -> e.message
         map = _.object _.keys(results), strings
         return @reject response, params: map
-
-    # Given the request with possible validation contexts appended
-    # run all the validator contexts in parallel and wait for the
-    # completion. If no validation mistakes found, run continuation.
-    # If some mistakes are found, however, `@renderParamValidation`.
-    validateParameters: (request, response, continuation) ->
-        notRequest = "a #{request} is not a request"
-        notResponse = "a #{response} is not a response"
-        notContinuation = "a #{continuation} is not function"
-        assert _.isFunction(continuation), notContinuation
-        assert _.isObject(response), notResponse
-        assert _.isObject(request), notRequest
-        @validateValues request.params, (failure, results) ->
-            signature = [results, request, response, continuation]
-            return @renderParamValidation signature... if failure
-            return continuation.bind(this) failure, results

 # This is an ABC service intended to be used only as a compund. It
 # provides a complete validation solution for request headers. The
@@ -180,6 +180,22 @@
         assert headers = request.headers, notParams
         return @value headers, name, message

+    # Given the request with possible validation contexts appended
+    # run all the validator contexts in parallel and wait for the
+    # completion. If no validation mistakes found, run continuation.
+    # If some mistakes are found, however, `@renderHeaderValidation`.
+    validateHeaders: (request, response, continuation) ->
+        notRequest = "a #{request} is not a request"
+        notResponse = "a #{response} is not a response"
+        notContinuation = "a #{continuation} is not function"
+        assert _.isFunction(continuation), notContinuation
+        assert _.isObject(response), notResponse
+        assert _.isObject(request), notRequest
+        @validateValues request.headers, (failure, results) ->
+            signature = [results, request, response, continuation]
+            return @renderHeaderValidation signature... if failure
+            return continuation.bind(this) failure, results
+
     # This method is a default implementation of the renderer that
     # will be called when the validation has failed. You can easily
     # override it in either your service or in an external compound.
@@ -193,19 +209,3 @@
         strings = _.map results, (e) -> e.message
         map = _.object _.keys(results), strings
         return @reject response, headers: map
-
-    # Given the request with possible validation contexts appended
-    # run all the validator contexts in parallel and wait for the
-    # completion. If no validation mistakes found, run continuation.
-    # If some mistakes are found, however, `@renderHeaderValidation`.
-    validateHeaders: (request, response, continuation) ->
-        notRequest = "a #{request} is not a request"
-        notResponse = "a #{response} is not a response"
-        notContinuation = "a #{continuation} is not function"
-        assert _.isFunction(continuation), notContinuation
-        assert _.isObject(response), notResponse
-        assert _.isObject(request), notRequest
-        @validateValues request.headers, (failure, results) ->
-            signature = [results, request, response, continuation]
-            return @renderHeaderValidation signature... if failure
-            return continuation.bind(this) failure, results


Indentation consistency fix

Indentation consistency fix

--- lib/directory.coffee
+++ lib/directory.coffee
@@ -93,14 +93,14 @@
     else
       status = 0
       if @isRoot
-          # repo.getDirectoryStatus will always fail for the
-          # root because the path is relativized + concatenated with '/'
-          # making the matching string be '/'.  Then path.indexOf('/')
-          # is run and will never match beginning of string with a leading '/'
-          for statusPath, statusId of repo.statuses
-            status |= parseInt(statusId, 10)
+        # repo.getDirectoryStatus will always fail for the
+        # root because the path is relativized + concatenated with '/'
+        # making the matching string be '/'.  Then path.indexOf('/')
+        # is run and will never match beginning of string with a leading '/'
+        for statusPath, statusId of repo.statuses
+          status |= parseInt(statusId, 10)
       else
-          status = repo.getDirectoryStatus(@path)
+        status = repo.getDirectoryStatus(@path)

       if repo.isStatusModified(status)
         newStatus = 'modified'


Extend from `Ember.Service` instead of `Ember.Object` in service blueprint

--- blueprints/service/files/app/services/__name__.coffee
+++ blueprints/service/files/app/services/__name__.coffee
@@ -1,5 +1,5 @@
 `import Ember from 'ember'`

-<%= classifiedModuleName %>Service = Ember.Object.extend()
+<%= classifiedModuleName %>Service = Ember.Service.extend()

 `export default <%= classifiedModuleName %>Service`


fix bug with extract hook

fix bug with extract hook

--- lib/fs_parser.coffee
+++ lib/fs_parser.coffee
@@ -66,7 +66,7 @@
       cat = ext.fs.category || ext.category
       @ast[cat] ||= []
       @ast[cat].push(file)
-      if ext.extract then W.resolve(true) else W.resolve(false)
+      if ext.fs.extract then W.resolve(true) else W.resolve(false)

   format_dirs = ->
     @ast.dirs = _.uniq(@ast.dirs).map((d) => @roots.config.out(d))


Claiming core

Claiming core

--- lib/spark-ide.coffee
+++ lib/spark-ide.coffee
@@ -8,6 +8,7 @@
 ClaimCoreManuallyView = null
 ListeningModeView = null
 SelectPortView = null
+ApiClient = null

 module.exports =
   statusView: null
@@ -98,7 +99,7 @@

     buttons['Remove ' + SettingsHelper.get('current_core_name')] = =>
       workspace = atom.workspaceView
-      ApiClient = require './vendor/ApiClient'
+      ApiClient ?= require './vendor/ApiClient'
       client = new ApiClient SettingsHelper.get('apiUrl'), SettingsHelper.get('access_token')
       @removePromise = client.removeCore SettingsHelper.get('current_core')
       @removePromise.done (e) =>
@@ -139,18 +140,40 @@

     promise = SerialHelper.listPorts()
     promise.done (ports) =>
-      console.log ports
       if ports.length == 0
         @listeningModeView = new ListeningModeView()
         @listeningModeView.show()
       else if (ports.length == 1) || (!!port)
-        # TODO: Only one core or it was selected
         if !port
           port = ports[0].comName

-        console.log 'Will claim core on port ' + port
+        @statusView.setStatus 'Claiming core on port ' + port + '...'
+        promise = SerialHelper.askForCoreID port
+        promise.done (coreID) =>
+          ApiClient ?= require './vendor/ApiClient'
+          client = new ApiClient SettingsHelper.get('apiUrl'), SettingsHelper.get('access_token')
+          workspace = atom.workspaceView
+          @claimPromise = client.claimCore coreID
+          @claimPromise.done (e) =>
+            if !@claimPromise
+              return
+
+            SettingsHelper.setCurrentCore e.id, e.id
+
+            atom.workspaceView.trigger 'spark-ide:update-core-status'
+            atom.workspaceView.trigger 'spark-ide:update-menu'
+
+            @claimPromise = null
+
+            @statusView.setStatus 'Core claimed!'
+            @statusView.clearAfter 5000
+          , (e) =>
+            @statusView.setStatus e.errors, 'error'
+            @statusView.clearAfter 5000
+        , (e) =>
+          @statusView.setStatus e, 'error'
+          @statusView.clearAfter 5000
       else
-        # TODO: Show list with cores
         SelectPortView ?= require './views/select-port-view'
         @selectPortView ?= new SelectPortView()


:tada: keep last cursor when clear selection

--- lib/vim-state.coffee
+++ lib/vim-state.coffee
@@ -267,7 +267,15 @@
   resetNormalMode: ({userInvocation}={}) ->
     if userInvocation ? false
       if @editor.hasMultipleCursors()
-        @editor.clearSelections()
+        # Don't @editor.clearSelections() doesn't respect lastCursor
+        # So here I destroy() except lastSelection
+        # Important when clearing multi-cursor after bulk-edit using occurrence
+        for selection in @editor.getSelections()
+          if selection.isLastSelection()
+            selection.clear()
+          else
+            selection.destroy()
+
       else if @hasPersistentSelections() and settings.get('clearPersistentSelectionOnResetNormalMode')
         @clearPersistentSelections()
       else if @occurrenceManager.hasPatterns()


Make JSON handling more robust

Make JSON handling more robust

--- lib/webserver.coffee
+++ lib/webserver.coffee
@@ -13,7 +13,15 @@
   req.on "data", (buf) ->
     optStr += buf.toString()
   req.on "end", ->
-    cb JSON.parse optStr
+    try
+      parsed = JSON.parse optStr
+    catch e
+      cb e, null
+    cb null, parsed
+
+respondJSONerr = (err, res) ->
+  res.writeHead 400
+  res.end err

 server.on 'request', (req, res) ->
   res.setHeader "Access-Control-Allow-Origin", "*"
@@ -44,6 +52,7 @@
     when "/stop"
       #Should there should be logic here (or elsewhere) to send the right PIDs to the right slaves?
       getJSON req, (opts) ->
+        return respondJSONerr err, res if err?
         cavalry.stop opts.slave, opts.ids, (err, body) ->
           res.end()
     else


Preliminary implementation of Figure._glyph()

--- bokehjs/src/coffee/api/plotting.coffee
+++ bokehjs/src/coffee/api/plotting.coffee
@@ -107,18 +107,6 @@

     @add_tools(@_process_tools(tools)...)

-  _glyph: (cls, params, args) ->
-    params = params.split(",")
-
-    if args.length == 1
-      [attrs] = args
-    else
-      [args..., opts] = args
-
-    return new models.GlyphRenderer()
-
-  _marker: (cls, args) -> @_glyph(cls, "x,y", args)
-
   annular_wedge:     (args...) -> @_glyph(models.AnnularWedge, "x,y,inner_radius,outer_radius,start_angle,end_angle", args)
   annulus:           (args...) -> @_glyph(models.Annulus,      "x,y,inner_radius,outer_radius",                       args)
   arc:               (args...) -> @_glyph(models.Arc,          "x,y,radius,start_angle,end_angle",                    args)
@@ -154,6 +142,47 @@
   triangle:          (args...) -> @_marker(models.Triangle,         args)
   x:                 (args...) -> @_marker(models.X,                args)

+  _glyph: (cls, params, args) ->
+    params = params.split(",")
+
+    if args.length == 1
+      [attrs] = args
+      attrs = _.clone(attrs)
+    else
+      [args..., opts] = args
+      attrs = _.clone(opts)
+      for param, i in params
+        attrs[param] = args[i]
+
+    source = attrs.source ? new models.ColumnDataSource()
+    delete attrs.source
+
+    # TODO: process and pop other *_color and *_alpha attrs
+    glyph_ca   = {}
+    nsglyph_ca = {}
+    sglyph_ca  = {}
+    hglyph_ca  = {}
+    delete attrs.color
+
+    _make_glyph = (cls, attrs, ca) => new cls(attrs)
+
+    glyph   = _make_glyph(cls, attrs, glyph_ca)
+    nsglyph = _make_glyph(cls, attrs, nsglyph_ca)
+    sglyph  = _make_glyph(cls, attrs, sglyph_ca)
+    hglyph  = _make_glyph(cls, attrs, hglyph_ca)
+
+    glyph_renderer = new models.GlyphRenderer({
+      data_source:        source
+      glyph:              glyph
+      nonselection_glyph: nsglyph
+      selection_glyph:    sglyph
+      hover_glyph:        hglyph
+    })
+
+    @add_renderers(glyph_renderer)
+
+  _marker: (cls, args) -> @_glyph(cls, "x,y", args)
+
   _get_range: (range) ->
     if not range?
       return new models.DataRange1d()


Client: Activity: Moved messagestore handlers to chatinput actions

--- client/activity/lib/flux/test/messagesstore.coffee
+++ client/activity/lib/flux/test/messagesstore.coffee
@@ -5,6 +5,7 @@

 MessagesStore = require '../stores/messagesstore'
 actionTypes = require '../actions/actiontypes'
+chatInputActionTypes = require '../chatinput/actions/actiontypes'

 MessageCollectionHelpers = require '../helpers/messagecollection'

@@ -283,9 +284,8 @@

     it 'sets message __isEditing value to yes', ->

-      reactor.dispatch actionTypes.CREATE_MESSAGE_SUCCESS, { clientRequestId, message: message_1 }
-      reactor.dispatch actionTypes.CREATE_MESSAGE_SUCCESS, { clientRequestId, message: message_2 }
-      reactor.dispatch actionTypes.SET_LAST_MESSAGE_EDIT_MODE, { accountId }
+      reactor.dispatch chatInputActionTypes.CREATE_MESSAGE_SUCCESS, { clientRequestId, message: message_1 }
+      reactor.dispatch chatInputActionTypes.CREATE_MESSAGE_SUCCESS, { clientRequestId, message: message_2 }
       reactor.dispatch chatInputActionTypes.SET_LAST_MESSAGE_EDIT_MODE, { accountId }

       storeState = reactor.evaluate ['messages']


ComputeResizeModal: disable resize button for only first resize [#89795902]

--- client/app/lib/providers/computeresizemodal.coffee
+++ client/app/lib/providers/computeresizemodal.coffee
@@ -94,7 +94,10 @@
       @resizeVMButton.enable()  unless usage.storage >= maxStorage

     if newUsage is @machineCurrentStorage
-      @resizeVMButton.disable()
+      # If not resized before disable to resize for minimum storage
+      # but for higher values allow user to call resize for the same
+      # storage size since we need that if somehow resize fails once ~GG
+      @resizeVMButton.disable()  if @machineCurrentStorage is 3
       @usageTextView.updatePartial "
         Currently #{@machine.label}
         has #{@machineCurrentStorage}GB storage


Wocaial: fix mapper function with the new structure

--- client/Main/socialapicontroller.coffee
+++ client/Main/socialapicontroller.coffee
@@ -87,12 +87,16 @@
     revivedChannels = []
     {SocialChannel} = KD.remote.api
     for channel in channels
-      c = new SocialChannel channel
+      data = channel.channel
+      data.isParticipated = channel.isParticipated
+      data.participantCount = channel.participantCount
+
+      c = new SocialChannel data
       # until we create message id's
       # programmatically
       # inorder to make realtime updates work
       # we need `channel-` here
-      c._id = "channel-#{channel.id}"
+      c._id = "channel-#{c.id}"

       revivedChannels.push c


Terminal: session item title is changed as "Terminal Screen Session"

--- client/Terminal/sessionitemview.coffee
+++ client/Terminal/sessionitemview.coffee
@@ -16,4 +16,4 @@

   pistachio: ->
     {index} = @getOptions()
-    "Session #{index}"
+    "Terminal Screen Session #{index}"


Providers: re-enable Frankfurt since we are now supporting new API with go-amz update

--- client/app/lib/providers/config.coffee
+++ client/app/lib/providers/config.coffee
@@ -48,7 +48,7 @@
           { title: 'US West (Oregon) (us-west-2)',              value: 'us-west-2' }
           { title: 'US West (N. California) (us-west-1)',       value: 'us-west-1' }
           { title: 'EU (Ireland) (eu-west-1)',                  value: 'eu-west-1' }
-        # { title: 'EU (Frankfurt) (eu-central-1)',             value: 'eu-central-1' }
+          { title: 'EU (Frankfurt) (eu-central-1)',             value: 'eu-central-1' }
           { title: 'Asia Pacific (Singapore) (ap-southeast-1)', value: 'ap-southeast-1' }
           { title: 'Asia Pacific (Sydney) (ap-southeast-2)',    value: 'ap-southeast-2' }
           { title: 'Asia Pacific (Tokyo) (ap-northeast-1)',     value: 'ap-northeast-1' }


Add model name to comparison table PP-8

Add model name to comparison table
PP-8

--- client/src/scripts/scoring-view.coffee
+++ client/src/scripts/scoring-view.coffee
@@ -169,6 +169,7 @@
     createComparisonGrid = (scores) ->
       header = [
         'Method'
+        'Name'
         'Category'
         'Response Column'
         'Input Parameters'
@@ -197,6 +198,7 @@
         errorBadge = if scores.length > 1 and score is scoreWithLowestError then ' (Lowest)' else ''
         [
           model.model_algorithm
+          model.key
           model.model_category
           model.response_column_name
           model.parameters


youtubeShell: stylefix: realign commented out option

--- coffee/src/shells/youtube.shell.coffee
+++ coffee/src/shells/youtube.shell.coffee
@@ -59,7 +59,7 @@
     # see https://developers.google.com/youtube/player_parameters for options
     "http://www.youtube.com/embed/#{@youtubeId()}?" +
          '&fs=1' +
-         # '&modestbranding=1' +
+       # '&modestbranding=1' +
          '&iv_load_policy=3' +
          '&rel=0' +
          '&showsearch=0' +


Removes unnecessary parentheses and makes precedence of || and && explicit

--- content_scripts/vimium_frontend.coffee
+++ content_scripts/vimium_frontend.coffee
@@ -563,8 +563,8 @@

     linkMatches = false
     for linkString in linkStrings
-      if (link.innerText.toLowerCase().indexOf(linkString) != -1 || link.value &&
-          link.value.indexOf(linkString) != -1)
+      if link.innerText.toLowerCase().indexOf(linkString) != -1 ||
+          link.value?.indexOf(linkString) != -1
         linkMatches = true
         break
     continue unless linkMatches
@@ -596,8 +596,8 @@
       else
         new RegExp linkString, "i"
     for candidateLink in candidateLinks
-      if (exactWordRegex.test(candidateLink.innerText) ||
-          candidateLink.value && exactWordRegex.test(candidateLink.value))
+      if exactWordRegex.test(candidateLink.innerText) ||
+          (candidateLink.value && exactWordRegex.test(candidateLink.value))
         followLink(candidateLink)
         return true
   false


Update URL

Update URL

--- extension/chrome/js/src/background.coffee
+++ extension/chrome/js/src/background.coffee
@@ -1,5 +1,5 @@
 settings =
-	url: 'https://script.google.com/macros/s/' +'AKfycbwiaMcutoikPEIkO45ETPr6JCv9oz5BGwpatEPwCpEakKgIGdc'+'/exec'
+	url: 'https://script.google.com/macros/s/' +'AKfycbw9V8T6n79IkEUwZJNknuKWxHTvK2f_U66eIIRerEMU6VKmSq0'+'/exec'

 chrome.extension.onMessage.addListener (request, sender, sendResponse) ->
 	#console.log(sender.tab "from a content script:" + sender.tab.url :


Include changes

Include changes

--- etc/atom/config.cson
+++ etc/atom/config.cson
@@ -19,7 +19,6 @@
       'solarized-dark-syntax'
     ]
     'projectHome': '/Users/stillers/workspace'
-  'whitespace': {}
   'bracket-matcher':
     'autocompleteBrackets': false
   'find-and-replace':


Delete loading_js.js.coffee

Delete loading_js.js.coffee

--- loading_js.js.coffee
+++ loading_js.js.coffee
@@ -1,79 +0,0 @@
-initialize = ->
-  _create_loading_html()
-
-showLoading = ->
-  $('#loading_js_wrapper').show()
-
-hideLoading = ->
-  $('#loading_js_wrapper').fadeOut()
-
-_create_loading_html = ->
-  return if $('#loading_js_wrapper').length > 0
-
-  style = {
-    wrapper: { display: 'none' },
-    background: {
-      position: 'fixed',
-      display: 'block',
-      width: '100%',
-      height: '100%',
-      zIndex: '1000',
-      top: '0',
-      backgroundColor: '#fff',
-      opacity: '0.5'
-    },
-    loadingWrapper: {
-      position: 'fixed',
-      display: 'block',
-      width: '100%',
-      height: '100%',
-      zIndex: '1001',
-      top: '0',
-      left: '0'
-    },
-    loading: {
-      backgroundColor: '#333',
-      width: '80px',
-      margin: '20% auto 0',
-      padding: '25px 10px 20px',
-      "-webkit-border-radius": '3px',
-      "-moz-border-radius": '3px',
-      borderRadius: '3px'
-    },
-    loadingImg: {
-      width: '32px',
-      height: '32px',
-      display: 'block',
-      margin: '0 auto'
-    },
-    title: {
-      fontSize: '12px',
-      textAlign: 'center',
-      margin: '10px 0 0',
-      color: '#ddd'
-    }
-  }
-  loadingImgData = "data:image/gif;base64,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"
-
-  wrapper = $('<div/>').attr('id', 'loading_js_wrapper')
-  wrapper.css(style.wrapper)
-  background = $('<div/>').addClass('background')
-  background.css(style.background)
-  loadingWrapper = $('<div/>').addClass('loading-wrapper')
-  loadingWrapper.css(style.loadingWrapper)
-  loading = $('<div/>').addClass('loading')
-  loading.css(style.loading)
-  loadingImg = $('<img/>').attr('src', loadingImgData)
-  loadingImg.css(style.loadingImg)
-  title = $('<p/>').html('Loading...')
-  title.css(style.title)
-
-  $(loading).append(loadingImg)
-  $(loading).append(title)
-  $(loadingWrapper).append(loading)
-  $(wrapper).append(background)
-  $(wrapper).append(loadingWrapper)
-
-  $('body').append(wrapper)
-
-@LoadingJs = {initialize, showLoading, hideLoading}


added tests for $builder.removeFormObject(), .updateFormObjectIndex() and .$get(). #7

--- test/specs/providerSpec.coffee
+++ test/specs/providerSpec.coffee
@@ -330,3 +330,72 @@
             $builder.insertFormObject 'default', 1, component: 'inputText'
             expect(builderProvider.convertFormObject).toHaveBeenCalled()
             expect(builderProvider.reindexFormObject).toHaveBeenCalled()
+
+    describe '$builder.removeFormObject', ->
+        beforeEach -> inject ($builder) ->
+            $builder.registerComponent 'inputText',
+                template: "

"
+                popoverTemplate: "

"
+
+        it 'check $builder.removeFormObject() will call formObject.splice() and reindexFormObject()', inject ($builder) ->
+            spyOn(builderProvider.forms.default, 'splice').andCallFake (index, length, object) ->
+                expect(index).toBe 1
+                expect(length).toBe 1
+                expect(object).toBeUndefined()
+            spyOn(builderProvider, 'reindexFormObject').andCallFake (name) ->
+                expect(name).toEqual 'default'
+            $builder.removeFormObject 'default', 1
+            expect(builderProvider.forms.default.splice).toHaveBeenCalled()
+            expect(builderProvider.reindexFormObject).toHaveBeenCalled()
+
+    describe '$builder.updateFormObjectIndex', ->
+        beforeEach -> inject ($builder) ->
+            $builder.registerComponent 'inputText',
+                template: "

"
+                popoverTemplate: "

"
+
+        it 'check $builder.updateFormObjectIndex() will directive return if the new index and the old index are the same one', inject ($builder) ->
+            spyOn builderProvider.forms.default, 'splice'
+            spyOn builderProvider, 'reindexFormObject'
+            $builder.updateFormObjectIndex 'default', 0, 0
+            expect(builderProvider.forms.default.splice).not.toHaveBeenCalled()
+            expect(builderProvider.reindexFormObject).not.toHaveBeenCalled()
+
+        it 'check $builder.updateFormObjectIndex() will call formObject.splice() and reindexFormObject()', inject ($builder) ->
+            formObject = id: 0
+            spySplice = spyOn(builderProvider.forms.default, 'splice').andCallFake (index, length, object) ->
+                switch spySplice.calls.length
+                    when 1
+                        expect(index).toBe 0
+                        expect(length).toBe 1
+                        expect(object).toBeUndefined()
+                        [formObject]
+                    when 2
+                        expect(index).toBe 1
+                        expect(length).toBe 0
+                        expect(object).toBe formObject
+                    else
+            spyOn builderProvider, 'reindexFormObject'
+            $builder.updateFormObjectIndex 'default', 0, 1
+            expect(spySplice.calls.length).toBe 2
+            expect(builderProvider.reindexFormObject).toHaveBeenCalled()
+
+    describe '$builder.$get', ->
+        it 'check $builder.components is equal $builderProvider.components', inject ($builder) ->
+            expect($builder.components).toBe builderProvider.components
+        it 'check $builder.groups is equal $builderProvider.groups', inject ($builder) ->
+            expect($builder.groups).toBe builderProvider.groups
+        it 'check $builder.forms is equal $builderProvider.forms', inject ($builder) ->
+            expect($builder.forms).toBe builderProvider.forms
+        it 'check $builder.broadcastChannel is equal $builderProvider.broadcastChannel', inject ($builder) ->
+            expect($builder.broadcastChannel).toBe builderProvider.broadcastChannel
+        it 'check $builder.registerComponent is equal $builderProvider.registerComponent', inject ($builder) ->
+            expect($builder.registerComponent).toBe builderProvider.registerComponent
+        it 'check $builder.addFormObject is equal $builderProvider.addFormObject', inject ($builder) ->
+            expect($builder.addFormObject).toBe builderProvider.addFormObject
+        it 'check $builder.insertFormObject is equal $builderProvider.insertFormObject', inject ($builder) ->
+            expect($builder.insertFormObject).toBe builderProvider.insertFormObject
+        it 'check $builder.removeFormObject is equal $builderProvider.removeFormObject', inject ($builder) ->
+            expect($builder.removeFormObject).toBe builderProvider.removeFormObject
+        it 'check $builder.updateFormObjectIndex is equal $builderProvider.updateFormObjectIndex', inject ($builder) ->
+            expect($builder.updateFormObjectIndex).toBe builderProvider.updateFormObjectIndex


Update for Csound 6.13.0

Update for Csound 6.13.0

--- grammars/csound.cson
+++ grammars/csound.cson
@@ -382,12 +382,12 @@
       },{
         # To update this regex, run
         ###
-          curl --remote-name https://bitbucket.org/nwhetsell/pygments-main/raw/tip/pygments/regexopt.py
-          curl --remote-name https://bitbucket.org/nwhetsell/pygments-main/raw/tip/pygments/lexers/_csound_builtins.py
-          python -c "import re; from _csound_builtins import OPCODES, DEPRECATED_OPCODES; from regexopt import regex_opt; print '\"(?:' + (regex_opt(OPCODES, r'\\\\b', r'\\\\b') + '|' + regex_opt(DEPRECATED_OPCODES, r'\\\\b', r'\\\\b')).replace('\\_', '_') + r')(?:(\\\\:)([A-Za-z]))?\"'"
+          curl --remote-name --show-error --silent https://raw.githubusercontent.com/pygments/pygments/master/pygments/regexopt.py
+          curl --remote-name --show-error --silent https://raw.githubusercontent.com/pygments/pygments/master/pygments/lexers/_csound_builtins.py
+          python -c "import re; from _csound_builtins import OPCODES, DEPRECATED_OPCODES; from regexopt import regex_opt; print('\"(?:' + (regex_opt(OPCODES, r'\\\\b', r'\\\\b') + '|' + regex_opt(DEPRECATED_OPCODES, r'\\\\b', r'\\\\b')).replace('\\_', '_') + r')(?:(\\\\:)([A-Za-z]))?\"')"
         ###
         # and then paste the output.
-        match: "(?:\\b(ATS(?:add(?:(?:nz)?)|bufread|cross|in(?:fo|terpread)|partialtap|read(?:(?:nz)?)|sinnoi)|FL(?:b(?:ox|ut(?:Bank|ton))|c(?:loseButton|o(?:lor(?:(?:2)?)|unt))|execButton|g(?:etsnap|roup(?:(?:(?:E|_e)nd)?))|h(?:ide|vsBox(?:(?:SetValue)?))|joy|k(?:eyIn|nob)|l(?:abel|oadsnap)|mouse|p(?:a(?:ck(?:(?:(?:E|_e)nd)?)|nel(?:(?:(?:E|_e)nd)?))|rintk(?:(?:2)?))|r(?:oller|un)|s(?:avesnap|croll(?:(?:(?:E|_e)nd)?)|et(?:Align|Box|Color(?:(?:2)?)|Font|Position|S(?:ize|napGroup)|Text(?:(?:Color|(?:Siz|Typ)e)?)|Val(?:(?:(?:(?:_)?)i)?)|snap)|how|lid(?:Bnk(?:(?:2(?:(?:Set(?:(?:k)?))?)|GetHandle|Set(?:(?:k)?))?)|er))|t(?:abs(?:(?:(?:E|_e)nd)?)|ext)|update|v(?:alue|keybd|slidBnk(?:(?:2)?))|xyin)|Jacko(?:Audio(?:In(?:(?:Connect)?)|Out(?:(?:Connect)?))|Freewheel|In(?:fo|it)|Midi(?:(?:InConnec|Ou(?:(?:tConnec)?))t)|NoteOut|On|Transport)|K35_(?:(?:[hl])pf)|Mixer(?:Clear|GetLevel|Receive|Se(?:nd|tLevel(?:(?:_i)?)))|OSC(?:bundle|count|init(?:(?:M)?)|listen|raw|send(?:(?:_lo)?))|STK(?:B(?:andedWG|eeThree|low(?:Botl|Hole)|owed|rass)|Clarinet|Drummer|F(?:MVoices|lute)|HevyMetl|M(?:andolin|o(?:dalBar|og))|P(?:ercFlut|lucked)|R(?:esonate|hodey)|S(?:axofony|hakers|i(?:mple|tar)|tifKarp)|TubeBell|VoicForm|W(?:histle|urley))|a(?:bs|ctive|ds(?:r|yn(?:(?:t(?:(?:2)?))?))|ftouch|l(?:pass|wayson)|mp(?:db(?:(?:fs)?)|midi(?:(?:d)?))|reson(?:(?:k)?)|tone(?:(?:[kx])?))|b(?:a(?:bo|lance(?:(?:2)?)|mboo|rmodel)|bcut(?:[ms])|e(?:adsynt|osc|(?:tara|xpr)nd)|form(?:(?:de|en)c1)|i(?:nit|quad(?:(?:a)?)|rnd)|pf(?:(?:cos)?)|qrez|u(?:t(?:b(?:[pr])|hp|lp|t(?:er(?:b(?:[pr])|(?:[hl])p)|on))|zz))|c(?:2r|a(?:basa|uchy(?:(?:i)?))|brt|e(?:il|ll|nt(?:(?:roid)?)|ps(?:(?:inv)?))|h(?:an(?:ctrl|ged(?:(?:2)?)|[io])|e(?:byshevpoly|ckbox)|n(?:_(?:[Sak])|clear|export|get(?:(?:ks)?)|mix|params|set(?:(?:ks)?))|uap)|l(?:ear|filt|ip|ocko(?:ff|n))|mp(?:(?:lxprod)?)|o(?:m(?:b(?:(?:inv)?)|p(?:ile(?:csd|orc|str)|ress(?:(?:2)?)))|n(?:nect|trol|v(?:(?:l|olv)e))|py(?:a2ftab|f2array)|s(?:(?:h|inv|seg(?:(?:[br])?))?))|p(?:s(?:2pch|midi(?:(?:b|nn)?)|oct|pch|t(?:mid|un(?:(?:i)?))|xpch)|u(?:meter|prc))|r(?:oss(?:2|fm(?:(?:i|pm(?:(?:i)?))?)|pm(?:(?:i)?))|unch)|t(?:lchn|rl(?:14|21|7|init))|userrnd)|d(?:a(?:m|te(?:(?:s)?))|b(?:(?:(?:(?:fs)?)amp)?)|c(?:block(?:(?:2)?)|onv|t(?:(?:inv)?))|e(?:interleave|l(?:ay(?:(?:[1krw])?)|tap(?:(?:xw|[3inx])?))|norm)|i(?:ff|ode_ladder|rectory|s(?:k(?:grain|in(?:(?:2)?))|p(?:fft|lay)|tort(?:(?:1)?))|vz)|o(?:ppler|t|wnsamp)|ripwater|ssi(?:a(?:ctivate|udio)|ctls|(?:ini|lis)t)|u(?:mpk(?:(?:[234])?)|s(?:errnd|t(?:(?:2)?))))|e(?:nvlpx(?:(?:r)?)|phasor|qfil|v(?:alstr|ent(?:(?:_i)?))|x(?:citer|itnow|p(?:(?:curve|on|rand(?:(?:i)?)|seg(?:(?:ba|[abr])?))?)))|f(?:a(?:reylen(?:(?:i)?)|ust(?:audio|c(?:ompile|tl)|dsp|gen|play))|ft(?:(?:inv)?)|i(?:close|l(?:e(?:bit|len|nchnls|peak|s(?:cal|r)|valid)|larray|ter2)|n(?:(?:[ik])?)|open)|l(?:a(?:nger|shtxt)|oo(?:per(?:(?:2)?)|r))|m(?:a(?:nal|x)|b(?:3|ell)|in|metal|od|percfl|(?:rhod|voic|wurli)e)|o(?:f(?:2|ilter)|l(?:d|low(?:(?:2)?))|scil(?:(?:i)?)|ut(?:(?:ir|[ik])?)|[fg])|print(?:(?:(?:k)?)s)|r(?:a(?:c(?:(?:talnoise)?)|mebuffer)|eeverb)|t(?:audio|c(?:hnls|onv|ps)|free|gen(?:(?:once|tmp)?)|l(?:en|oad(?:(?:k)?)|ptim)|morf|om|print|resize(?:(?:i)?)|s(?:a(?:mplebank|ve(?:(?:k)?))|lice|r)))|g(?:a(?:in(?:(?:slider)?)|uss(?:(?:i|trig)?))|buzz|e(?:n(?:array(?:(?:_i)?)|dy(?:(?:[cx])?))|t(?:c(?:fg|ol)|ftargs|row(?:(?:lin)?)|seed))|ogobel|ra(?:in(?:(?:[23])?)|nule)|uiro)|h(?:armon(?:(?:[234])?)|df5(?:read|write)|ilbert(?:(?:2)?)|rtf(?:early|move(?:(?:2)?)|reverb|stat)|sboscil|vs(?:[123])|ypot)|i(?:hold|mage(?:create|free|getpixel|load|s(?:ave|etpixel|ize))|n(?:(?:32|ch|it(?:(?:c(?:14|21|7))?)|let(?:kid|[afkv])|rg|s(?:global|remot)|te(?:g|r(?:leave|p))|value|[hoqstxz])?))|j(?:acktransport|itter(?:(?:2)?)|oystick|spline)|l(?:a_(?:i_(?:a(?:dd_(?:m(?:[cr])|v(?:[cr]))|ssign_(?:m(?:[cr])|t|v(?:[cr])))|conjugate_(?:m(?:[cr])|v(?:[cr]))|d(?:i(?:stance_v(?:[cr])|vide_(?:m(?:[cr])|v(?:[cr])))|ot_(?:m(?:c_vc|r_vr|[cr])|v(?:[cr])))|get_(?:m(?:[cr])|v(?:[cr]))|invert_m(?:[cr])|l(?:ower_solve_m(?:[cr])|u_(?:det_m(?:[cr])|factor_m(?:[cr])|solve_m(?:[cr])))|m(?:c_(?:create|set)|r_(?:create|set)|ultiply_(?:m(?:[cr])|v(?:[cr])))|norm(?:1_(?:m(?:[cr])|v(?:[cr]))|_(?:euclid_(?:m(?:[cr])|v(?:[cr]))|inf_(?:m(?:[cr])|v(?:[cr]))|max_m(?:[cr])))|print_(?:m(?:[cr])|v(?:[cr]))|qr_(?:eigen_m(?:[cr])|factor_m(?:[cr])|sym_eigen_m(?:[cr]))|random_(?:m(?:[cr])|v(?:[cr]))|s(?:ize_(?:m(?:[cr])|v(?:[cr]))|ubtract_(?:m(?:[cr])|v(?:[cr])))|t(?:_assign|ra(?:ce_m(?:[cr])|nspose_m(?:[cr])))|upper_solve_m(?:[cr])|v(?:c_(?:create|set)|r_(?:create|set)))|k_(?:a(?:_assign|dd_(?:m(?:[cr])|v(?:[cr]))|ssign_(?:m(?:[cr])|v(?:[cr])|[aft]))|c(?:onjugate_(?:m(?:[cr])|v(?:[cr]))|urrent_(?:f|vr))|d(?:i(?:stance_v(?:[cr])|vide_(?:m(?:[cr])|v(?:[cr])))|ot_(?:m(?:c_vc|r_vr|[cr])|v(?:[cr])))|f_assign|get_(?:m(?:[cr])|v(?:[cr]))|invert_m(?:[cr])|l(?:ower_solve_m(?:[cr])|u_(?:det_m(?:[cr])|factor_m(?:[cr])|solve_m(?:[cr])))|m(?:c_set|r_set|ultiply_(?:m(?:[cr])|v(?:[cr])))|norm(?:1_(?:m(?:[cr])|v(?:[cr]))|_(?:euclid_(?:m(?:[cr])|v(?:[cr]))|inf_(?:m(?:[cr])|v(?:[cr]))|max_m(?:[cr])))|qr_(?:eigen_m(?:[cr])|factor_m(?:[cr])|sym_eigen_m(?:[cr]))|random_(?:m(?:[cr])|v(?:[cr]))|subtract_(?:m(?:[cr])|v(?:[cr]))|t(?:_assign|race_m(?:[cr]))|upper_solve_m(?:[cr])|v(?:(?:[cr])_set)))|enarray|fo|i(?:mit(?:(?:1)?)|n(?:cos|e(?:(?:n(?:(?:r)?)|to)?)|k_(?:beat_(?:force|(?:ge|reques)t)|create|enable|is_enabled|metro|peers|tempo_(?:(?:[gs])et))|lin|rand|seg(?:(?:[br])?))|veconv)|o(?:cs(?:end|ig)|g(?:(?:10|2|btwo|curve)?)|op(?:seg(?:(?:p)?)|(?:[tx])seg)|renz|scil(?:(?:(?:(?:3)?)phs|[3x])?)|w(?:pass2|res(?:(?:x)?)))|p(?:f(?:18|orm|reson)|hasor|interp|oscil(?:(?:sa(?:(?:2)?)|[3a])?)|re(?:ad|son)|s(?:hold(?:(?:p)?)|lot))|ua_(?:exec|i(?:aopcall(?:(?:_off)?)|kopcall(?:(?:_off)?)|opcall(?:(?:_off)?))|opdef))|m(?:a(?:ca|dsr|gs|nd(?:(?:[eo])l)|parray(?:(?:_i)?)|rimba|ssign|x(?:_k|a(?:bs(?:(?:accum)?)|ccum|lloc|rray))|[cx])|clock|delay|e(?:dian(?:(?:k)?)|tro)|fb|i(?:d(?:global|i(?:arp|c(?:14|21|7|h(?:annelaftertouch|n)|ontrolchange|trl)|default|filestatus|in|noteo(?:ff|n(?:cps|key|oct|pch))|o(?:n(?:(?:2)?)|ut(?:(?:_i)?))|p(?:gm|itchbend|olyaftertouch|rogramchange)|tempo)|remot)|n(?:(?:a(?:bs(?:(?:accum)?)|ccum|rray)|cer)?)|rror)|o(?:d(?:e|matrix)|nitor|og(?:(?:ladder(?:(?:2)?)|vcf(?:(?:2)?))?)|scil)|p(?:3(?:bitrate|in|len|nchnls|s(?:cal|r))|ulse)|rtmsg|to(?:[fn])|u(?:ltitap|te)|vc(?:hpf|lpf(?:[1234]))|xadsr)|n(?:chnls_hw|estedap|l(?:alp|filt(?:(?:2)?))|o(?:ise|t(?:eo(?:ff|n(?:(?:dur(?:(?:2)?))?))|num))|r(?:everb|pn)|s(?:amp|t(?:ance|rnum))|t(?:om|rpol)|xtpow2)|o(?:ct(?:ave|cps|midi(?:(?:b|nn)?)|pch)|labuffer|sc(?:bnk|il(?:(?:1i|ikt(?:(?:[ps])?)|[13insx])?))|ut(?:(?:32|ch|i(?:at|c(?:(?:14)?)|p(?:at|[bc]))|k(?:at|c(?:(?:14)?)|p(?:at|[bc]))|let(?:kid|[afkv])|q(?:[1234])|rg|s(?:[12])|value|[choqsxz])?))|p(?:5g(?:connect|data)|a(?:n(?:(?:2)?)|r(?:eq|t(?:2txt|i(?:als|kkel(?:(?:get|s(?:et|ync))?))))|ssign|ulstretch)|c(?:auchy|h(?:bend|midi(?:(?:b|nn)?)|oct|tom)|o(?:nvolve|unt))|d(?:clip|half(?:(?:y)?))|eak|gm(?:(?:assig|ch)n)|h(?:as(?:er(?:[12])|or(?:(?:bnk)?))|s)|i(?:n(?:dex|k(?:er|ish))|tch(?:(?:a(?:c|mdf))?))|l(?:a(?:net|terev)|(?:ltra|u)ck)|o(?:isson|l(?:2rect|y(?:aft|nomial))|rt(?:(?:k)?)|scil(?:(?:3)?)|w(?:(?:ershape|oftwo|s)?))|r(?:e(?:alloc|piano)|int(?:(?:_type|array|f_i|k(?:s2|[2s])|[fks])?)|oduct)|set|t(?:able(?:(?:iw|[3iw])?)|rack)|uts|v(?:add|bufread|cross|interp|oc|read|s(?:2(?:array|tab)|a(?:dsyn|nal|rp)|b(?:and(?:[pr])|in|lur|uf(?:fer|read(?:(?:2)?)))|c(?:ale|e(?:nt|ps)|ross)|d(?:emix|is(?:kin|p))|envftw|f(?:ilter|r(?:e(?:ad|eze)|omarray)|t(?:[rw])|write)|gain|hift|i(?:fd|n(?:(?:fo|it)?))|lock|m(?:aska|ix|o(?:(?:ot|rp)h))|o(?:sc|ut)|pitch|t(?:anal|encil|race)|voc|warp|ynth))|wd|y(?:assign(?:(?:[it])?)|call(?:(?:1(?:[it])|2(?:[it])|3(?:[it])|4(?:[it])|5(?:[it])|6(?:[it])|7(?:[it])|8(?:[it])|ni|[12345678int])?)|e(?:val(?:(?:[it])?)|xec(?:(?:[it])?))|init|l(?:assign(?:(?:[it])?)|call(?:(?:1(?:[it])|2(?:[it])|3(?:[it])|4(?:[it])|5(?:[it])|6(?:[it])|7(?:[it])|8(?:[it])|ni|[12345678int])?)|e(?:val(?:(?:[it])?)|xec(?:(?:[it])?))|run(?:(?:[it])?))|run(?:(?:[it])?)))|q(?:inf|nan)|r(?:2c|and(?:(?:om(?:(?:[hi])?)|[hi])?)|bjeq|e(?:ad(?:clock|fi|k(?:[234s])|sc(?:ore|ratch)|[fk])|ct2pol|lease|mo(?:teport|ve)|pluck|s(?:hapearray|on(?:(?:xk|[krxyz])?)|yn)|verb(?:(?:2|sc)?)|windscore|zzy)|fft|ifft|ms|nd(?:(?:31)?)|ound|spline|tclock)|s(?:16b14|32b14|a(?:mphold|ndpaper)|c(?:_(?:lag(?:(?:ud)?)|phasor|trig)|a(?:le(?:(?:array)?)|n(?:hammer|table|[su]))|hed(?:kwhen(?:(?:named)?)|ule|when)|oreline(?:(?:_i)?))|e(?:ed|kere|lect|mitone|nse(?:(?:key)?)|qtime(?:(?:2)?)|rial(?:Begin|End|Flush|Print|Read|Write(?:(?:_i)?))|t(?:c(?:(?:o|tr)l)|ksmps|row|scorepos))|f(?:i(?:list|nstr(?:(?:3m|[3m])?))|lo(?:ad|oper)|p(?:assign|l(?:ay(?:(?:3m|[3m])?)|ist)|reset))|h(?:aker|ift(?:in|out))|i(?:gnum|n(?:(?:h|inv|syn)?))|l(?:eighbells|i(?:cearray(?:(?:_i)?)|der(?:16(?:(?:f|table(?:(?:f)?))?)|32(?:(?:f|table(?:(?:f)?))?)|64(?:(?:f|table(?:(?:f)?))?)|8(?:(?:f|table(?:(?:f)?))?)|Kawai)))|nd(?:loop|warp(?:(?:st)?))|o(?:ck(?:recv(?:(?:s)?)|send(?:(?:s)?))|rt(?:[ad])|undin)|p(?:a(?:ce|t3d(?:(?:[it])?))|dist|litrig|rintf(?:(?:k)?)|send)|q(?:rt|uinewave)|t(?:atevar|ix|r(?:c(?:at(?:(?:k)?)|har(?:(?:k)?)|mp(?:(?:k)?)|py(?:(?:k)?))|e(?:cv|son)|fromurl|get|index(?:(?:k)?)|l(?:en(?:(?:k)?)|ower(?:(?:k)?))|rindex(?:(?:k)?)|s(?:et|ub(?:(?:k)?))|to(?:(?:[dl])k|[dl])|upper(?:(?:k)?))|send)|u(?:binstr(?:(?:init)?)|m(?:(?:array)?))|vfilter|y(?:nc(?:grain|loop|phasor)|stem(?:(?:_i)?)))|t(?:a(?:b(?:2(?:array|pvs)|_i|ifd|le(?:(?:3kt|copy|filter(?:(?:i)?)|gpw|i(?:copy|gpw|kt|mix|w)|kt|mix|ng|ra|s(?:eg|huffle(?:(?:i)?))|w(?:a|kt)|x(?:kt|seg)|[3iw])?)|morph(?:(?:ak|[ai])?)|play|r(?:ec|owlin)|sum|w(?:(?:_i)?))|mbourine|n(?:h|inv(?:(?:2)?))|[bn])|bvcf|emp(?:est|o(?:(?:(?:sc|v)al)?))|i(?:me(?:dseq|inst(?:[ks])|[ks])|val)|lineto|one(?:(?:[kx])?)|r(?:a(?:dsyn|n(?:dom|seg(?:(?:[br])?)))|cross|filter|highest|i(?:g(?:ger|seq)|m(?:(?:_i)?)|rand)|lowest|mix|s(?:cale|(?:hif|pli)t))|urno(?:ff(?:(?:2)?)|n)|vconv)|u(?:n(?:irand|wrap)|psamp|r(?:andom|d))|v(?:a(?:ctrol|dd(?:(?:_i|v(?:(?:_i)?))?)|get|lpass|set)|bap(?:(?:gmove|lsinit|(?:(?:z)?)move|[gz])?)|c(?:ella|o(?:(?:2(?:(?:(?:f|i(?:f|ni))t)?)|mb|py(?:(?:_i)?))?))|d(?:el(?:_k|ay(?:(?:x(?:w(?:[qs])|[qsw])|[3kx])?))|ivv(?:(?:_i)?))|e(?:cdelay|loc|xp(?:(?:_i|seg|v(?:(?:_i)?))?))|i(?:b(?:es|r(?:(?:ato)?))|ncr)|l(?:i(?:mit|nseg)|owres)|m(?:ap|irror|ult(?:(?:_i|v(?:(?:_i)?))?))|o(?:ice|sim)|p(?:haseseg|o(?:rt|w(?:(?:_i|v(?:(?:_i)?))?))|voc)|rand(?:[hi])|subv(?:(?:_i)?)|tab(?:le(?:1k|w(?:[aik])|[aik])|w(?:[aik])|[aik])|wrap)|w(?:aveset|e(?:bsocket|ibull)|g(?:b(?:ow(?:(?:edbar)?)|rass)|clar|flute|pluck(?:(?:2)?)|uide(?:[12]))|i(?:i(?:connect|data|range|send)|ndow)|r(?:ap|itescratch)|terrain)|x(?:adsr|in|out|scan(?:map|smap|[su])|tratim|yscale)|z(?:a(?:cl|kinit|mod|rg|wm|[rw])|df_(?:1pole(?:(?:_mode)?)|2pole(?:(?:_mode)?)|ladder)|filter2|i(?:wm|[rw])|k(?:cl|mod|wm|[rw]))|[Saikp])\\b|\\b(array|bform(?:(?:de|en)c)|copy2(?:(?:[ft])tab)|hrtfer|ktableseg|lentab|m(?:(?:ax|in)tab)|p(?:op(?:(?:_f)?)|ush(?:(?:_f)?))|s(?:calet|ndload|oundout(?:(?:s)?)|pec(?:addm|di(?:ff|sp)|filt|hist|ptrk|s(?:cal|um)|trum)|tack|umtab)|t(?:ab(?:gen|map(?:(?:_i)?)|slice)|b(?:0_init|1(?:(?:(?:[012345])?)_init|[012345])|(?:[23456789])_init|[0123456789]))|vbap(?:16|(?:[48])move|[48])|xyin)\\b)(?:(\\:)([A-Za-z]))?"
+        match: "(?:\\b(ATS(?:add(?:(?:nz)?)|bufread|cross|in(?:fo|terpread)|partialtap|read(?:(?:nz)?)|sinnoi)|FL(?:b(?:ox|ut(?:Bank|ton))|c(?:loseButton|o(?:lor(?:(?:2)?)|unt))|execButton|g(?:etsnap|roup(?:(?:(?:E|_e)nd)?))|h(?:ide|vsBox(?:(?:SetValue)?))|joy|k(?:eyIn|nob)|l(?:abel|oadsnap)|mouse|p(?:a(?:ck(?:(?:(?:E|_e)nd)?)|nel(?:(?:(?:E|_e)nd)?))|rintk(?:(?:2)?))|r(?:oller|un)|s(?:avesnap|croll(?:(?:(?:E|_e)nd)?)|et(?:Align|Box|Color(?:(?:2)?)|Font|Position|S(?:ize|napGroup)|Text(?:(?:Color|(?:Siz|Typ)e)?)|Val(?:(?:(?:(?:_)?)i)?)|snap)|how|lid(?:Bnk(?:(?:2(?:(?:Set(?:(?:k)?))?)|GetHandle|Set(?:(?:k)?))?)|er))|t(?:abs(?:(?:(?:E|_e)nd)?)|ext)|update|v(?:alue|keybd|slidBnk(?:(?:2)?))|xyin)|Jacko(?:Audio(?:In(?:(?:Connect)?)|Out(?:(?:Connect)?))|Freewheel|In(?:fo|it)|Midi(?:(?:InConnec|Ou(?:(?:tConnec)?))t)|NoteOut|On|Transport)|K35_(?:(?:[hl])pf)|Mixer(?:Clear|GetLevel|Receive|Se(?:nd|tLevel(?:(?:_i)?)))|OSC(?:bundle|count|init(?:(?:M)?)|listen|raw|send(?:(?:_lo)?))|STK(?:B(?:andedWG|eeThree|low(?:Botl|Hole)|owed|rass)|Clarinet|Drummer|F(?:MVoices|lute)|HevyMetl|M(?:andolin|o(?:dalBar|og))|P(?:ercFlut|lucked)|R(?:esonate|hodey)|S(?:axofony|hakers|i(?:mple|tar)|tifKarp)|TubeBell|VoicForm|W(?:histle|urley))|a(?:bs|ctive|ds(?:r|yn(?:(?:t(?:(?:2)?))?))|ftouch|l(?:pass|wayson)|mp(?:db(?:(?:fs)?)|midi(?:(?:curve|d)?))|reson(?:(?:k)?)|tone(?:(?:[kx])?))|b(?:a(?:bo|lance(?:(?:2)?)|mboo|rmodel)|bcut(?:[ms])|e(?:adsynt|osc|(?:tara|xpr)nd)|form(?:(?:de|en)c1)|i(?:nit|quad(?:(?:a)?)|rnd)|pf(?:(?:cos)?)|qrez|u(?:t(?:b(?:[pr])|hp|lp|t(?:er(?:b(?:[pr])|(?:[hl])p)|on))|zz))|c(?:2r|a(?:basa|uchy(?:(?:i)?))|brt|e(?:il|ll|nt(?:(?:roid)?)|ps(?:(?:inv)?))|h(?:an(?:ctrl|ged2|[io])|e(?:byshevpoly|ckbox)|n(?:_(?:[Sak])|clear|export|get(?:(?:ks)?)|mix|params|set(?:(?:ks)?))|uap)|l(?:ear|filt|ip|ocko(?:ff|n))|mp(?:(?:lxprod)?)|o(?:m(?:b(?:(?:inv)?)|p(?:ile(?:csd|orc|str)|ress(?:(?:2)?)))|n(?:nect|trol|v(?:(?:l|olv)e))|py(?:a2ftab|f2array)|s(?:(?:h|inv|seg(?:(?:[br])?))?))|p(?:s(?:2pch|midi(?:(?:b|nn)?)|oct|pch|t(?:mid|un(?:(?:i)?))|xpch)|u(?:meter|prc))|r(?:oss(?:2|fm(?:(?:i|pm(?:(?:i)?))?)|pm(?:(?:i)?))|unch)|t(?:lchn|rl(?:14|21|7|init))|userrnd)|d(?:a(?:m|te(?:(?:s)?))|b(?:(?:(?:(?:fs)?)amp)?)|c(?:block(?:(?:2)?)|onv|t(?:(?:inv)?))|e(?:interleave|l(?:ay(?:(?:[1krw])?)|tap(?:(?:xw|[3inx])?))|norm)|i(?:ff|ode_ladder|rectory|s(?:k(?:grain|in(?:(?:2)?))|p(?:fft|lay)|tort(?:(?:1)?))|vz)|o(?:ppler|t|wnsamp)|ripwater|ssi(?:a(?:ctivate|udio)|ctls|(?:ini|lis)t)|u(?:mpk(?:(?:[234])?)|s(?:errnd|t(?:(?:2)?))))|e(?:nvlpx(?:(?:r)?)|phasor|qfil|v(?:alstr|ent(?:(?:_i)?))|x(?:citer|itnow|p(?:(?:curve|on|rand(?:(?:i)?)|seg(?:(?:ba|[abr])?))?)))|f(?:a(?:reylen(?:(?:i)?)|ust(?:audio|c(?:ompile|tl)|dsp|gen|play))|ft(?:(?:inv)?)|i(?:close|l(?:e(?:bit|len|nchnls|peak|s(?:cal|r)|valid)|larray|ter2)|n(?:(?:[ik])?)|open)|l(?:a(?:nger|shtxt)|oo(?:per(?:(?:2)?)|r)|uid(?:AllOut|C(?:C(?:[ik])|ontrol)|Engine|Info|Load|Note|Out|ProgramSelect|SetInterpMethod))|m(?:a(?:nal|x)|b(?:3|ell)|in|metal|od|percfl|(?:rhod|voic|wurli)e)|o(?:f(?:2|ilter)|l(?:d|low(?:(?:2)?))|scil(?:(?:i)?)|ut(?:(?:ir|[ik])?)|[fg])|print(?:(?:(?:k)?)s)|r(?:a(?:c(?:(?:talnoise)?)|mebuffer)|eeverb)|t(?:audio|c(?:hnls|onv|ps)|free|gen(?:(?:once|tmp)?)|l(?:en|oad(?:(?:k)?)|ptim)|morf|om|print|resize(?:(?:i)?)|s(?:a(?:mplebank|ve(?:(?:k)?))|lice|r)))|g(?:a(?:in(?:(?:slider)?)|uss(?:(?:i|trig)?))|buzz|e(?:n(?:array(?:(?:_i)?)|dy(?:(?:[cx])?))|t(?:c(?:fg|ol)|ftargs|row(?:(?:lin)?)|seed))|ogobel|ra(?:in(?:(?:[23])?)|nule)|tf|uiro)|h(?:armon(?:(?:[234])?)|df5(?:read|write)|ilbert(?:(?:2)?)|rtf(?:early|move(?:(?:2)?)|reverb|stat)|sboscil|vs(?:[123])|ypot)|i(?:hold|mage(?:create|free|getpixel|load|s(?:ave|etpixel|ize))|n(?:(?:32|ch|it(?:(?:c(?:14|21|7))?)|let(?:kid|[afkv])|rg|s(?:global|remot)|te(?:g|r(?:leave|p))|value|[hoqstxz])?))|j(?:acktransport|itter(?:(?:2)?)|oystick|spline)|l(?:a_(?:i_(?:a(?:dd_(?:m(?:[cr])|v(?:[cr]))|ssign_(?:m(?:[cr])|t|v(?:[cr])))|conjugate_(?:m(?:[cr])|v(?:[cr]))|d(?:i(?:stance_v(?:[cr])|vide_(?:m(?:[cr])|v(?:[cr])))|ot_(?:m(?:c_vc|r_vr|[cr])|v(?:[cr])))|get_(?:m(?:[cr])|v(?:[cr]))|invert_m(?:[cr])|l(?:ower_solve_m(?:[cr])|u_(?:det_m(?:[cr])|factor_m(?:[cr])|solve_m(?:[cr])))|m(?:c_(?:create|set)|r_(?:create|set)|ultiply_(?:m(?:[cr])|v(?:[cr])))|norm(?:1_(?:m(?:[cr])|v(?:[cr]))|_(?:euclid_(?:m(?:[cr])|v(?:[cr]))|inf_(?:m(?:[cr])|v(?:[cr]))|max_m(?:[cr])))|print_(?:m(?:[cr])|v(?:[cr]))|qr_(?:eigen_m(?:[cr])|factor_m(?:[cr])|sym_eigen_m(?:[cr]))|random_(?:m(?:[cr])|v(?:[cr]))|s(?:ize_(?:m(?:[cr])|v(?:[cr]))|ubtract_(?:m(?:[cr])|v(?:[cr])))|t(?:_assign|ra(?:ce_m(?:[cr])|nspose_m(?:[cr])))|upper_solve_m(?:[cr])|v(?:c_(?:create|set)|r_(?:create|set)))|k_(?:a(?:_assign|dd_(?:m(?:[cr])|v(?:[cr]))|ssign_(?:m(?:[cr])|v(?:[cr])|[aft]))|c(?:onjugate_(?:m(?:[cr])|v(?:[cr]))|urrent_(?:f|vr))|d(?:i(?:stance_v(?:[cr])|vide_(?:m(?:[cr])|v(?:[cr])))|ot_(?:m(?:c_vc|r_vr|[cr])|v(?:[cr])))|f_assign|get_(?:m(?:[cr])|v(?:[cr]))|invert_m(?:[cr])|l(?:ower_solve_m(?:[cr])|u_(?:det_m(?:[cr])|factor_m(?:[cr])|solve_m(?:[cr])))|m(?:c_set|r_set|ultiply_(?:m(?:[cr])|v(?:[cr])))|norm(?:1_(?:m(?:[cr])|v(?:[cr]))|_(?:euclid_(?:m(?:[cr])|v(?:[cr]))|inf_(?:m(?:[cr])|v(?:[cr]))|max_m(?:[cr])))|qr_(?:eigen_m(?:[cr])|factor_m(?:[cr])|sym_eigen_m(?:[cr]))|random_(?:m(?:[cr])|v(?:[cr]))|subtract_(?:m(?:[cr])|v(?:[cr]))|t(?:_assign|race_m(?:[cr]))|upper_solve_m(?:[cr])|v(?:(?:[cr])_set)))|enarray|fo|i(?:mit(?:(?:1)?)|n(?:cos|e(?:(?:n(?:(?:r)?)|to)?)|k_(?:beat_(?:force|(?:ge|reques)t)|create|enable|is_enabled|metro|peers|tempo_(?:(?:[gs])et))|lin|rand|seg(?:(?:[br])?))|veconv)|o(?:cs(?:end|ig)|g(?:(?:10|2|btwo|curve)?)|op(?:seg(?:(?:p)?)|(?:[tx])seg)|renz|scil(?:(?:(?:(?:3)?)phs|[3x])?)|w(?:pass2|res(?:(?:x)?)))|p(?:f(?:18|orm|reson)|hasor|interp|oscil(?:(?:sa(?:(?:2)?)|[3a])?)|re(?:ad|son)|s(?:hold(?:(?:p)?)|lot))|ua_(?:exec|i(?:aopcall(?:(?:_off)?)|kopcall(?:(?:_off)?)|opcall(?:(?:_off)?))|opdef))|m(?:a(?:ca|dsr|gs|nd(?:(?:[eo])l)|parray(?:(?:_i)?)|rimba|ssign|x(?:_k|a(?:bs(?:(?:accum)?)|ccum|lloc|rray))|[cx])|clock|delay|e(?:dian(?:(?:k)?)|tro)|fb|i(?:d(?:global|i(?:arp|c(?:14|21|7|h(?:annelaftertouch|n)|ontrolchange|trl)|default|filestatus|in|noteo(?:ff|n(?:cps|key|oct|pch))|o(?:n(?:(?:2)?)|ut(?:(?:_i)?))|p(?:gm|itchbend|olyaftertouch|rogramchange)|tempo)|remot)|n(?:(?:a(?:bs(?:(?:accum)?)|ccum|rray)|cer)?)|rror)|o(?:d(?:e|matrix)|nitor|og(?:(?:ladder(?:(?:2)?)|vcf(?:(?:2)?))?)|scil)|p(?:3(?:bitrate|in|len|nchnls|s(?:cal|r))|ulse)|rtmsg|to(?:[fn])|u(?:ltitap|te)|vc(?:hpf|lpf(?:[1234]))|xadsr)|n(?:chnls_hw|estedap|l(?:alp|filt(?:(?:2)?))|o(?:ise|t(?:eo(?:ff|n(?:(?:dur(?:(?:2)?))?))|num))|r(?:everb|pn)|s(?:amp|t(?:ance|r(?:num|str)))|t(?:o(?:[fm])|rpol)|xtpow2)|o(?:ct(?:ave|cps|midi(?:(?:b|nn)?)|pch)|labuffer|sc(?:bnk|il(?:(?:1i|ikt(?:(?:[ps])?)|[13insx])?))|ut(?:(?:32|ch|i(?:at|c(?:(?:14)?)|p(?:at|[bc]))|k(?:at|c(?:(?:14)?)|p(?:at|[bc]))|let(?:kid|[afkv])|q(?:[1234])|rg|s(?:[12])|value|[choqsxz])?))|p(?:5g(?:connect|data)|a(?:n(?:(?:2)?)|r(?:eq|t(?:2txt|i(?:als|kkel(?:(?:get|s(?:et|ync))?))))|ssign|ulstretch)|c(?:auchy|h(?:bend|midi(?:(?:b|nn)?)|oct|tom)|o(?:nvolve|unt))|d(?:clip|half(?:(?:y)?))|eak|gm(?:(?:assig|ch)n)|h(?:as(?:er(?:[12])|or(?:(?:bnk)?))|s)|i(?:n(?:dex|k(?:er|ish))|tch(?:(?:a(?:c|mdf))?))|l(?:a(?:net|terev)|(?:ltra|u)ck)|o(?:isson|l(?:2rect|y(?:aft|nomial))|rt(?:(?:k)?)|scil(?:(?:3)?)|w(?:(?:ershape|oftwo|s)?))|r(?:e(?:alloc|piano)|int(?:(?:_type|array|f_i|k(?:s2|[2s])|[fks])?)|oduct)|set|t(?:able(?:(?:[3iw])?)|rack)|uts|v(?:add|bufread|cross|interp|oc|read|s(?:2(?:array|tab)|a(?:dsyn|nal|rp)|b(?:and(?:[pr])|in|lur|uf(?:fer|read(?:(?:2)?)))|c(?:ale|e(?:nt|ps)|ross)|d(?:emix|is(?:kin|p))|envftw|f(?:ilter|r(?:e(?:ad|eze)|omarray)|t(?:[rw])|write)|gain|hift|i(?:fd|n(?:(?:fo|it)?))|lock|m(?:aska|ix|o(?:(?:ot|rp)h))|o(?:sc|ut)|pitch|t(?:anal|encil|race)|voc|warp|ynth))|wd|y(?:assign(?:(?:[it])?)|call(?:(?:1(?:[it])|2(?:[it])|3(?:[it])|4(?:[it])|5(?:[it])|6(?:[it])|7(?:[it])|8(?:[it])|ni|[12345678int])?)|e(?:val(?:(?:[it])?)|xec(?:(?:[it])?))|init|l(?:assign(?:(?:[it])?)|call(?:(?:1(?:[it])|2(?:[it])|3(?:[it])|4(?:[it])|5(?:[it])|6(?:[it])|7(?:[it])|8(?:[it])|ni|[12345678int])?)|e(?:val(?:(?:[it])?)|xec(?:(?:[it])?))|run(?:(?:[it])?))|run(?:(?:[it])?)))|q(?:inf|nan)|r(?:2c|and(?:(?:om(?:(?:[hi])?)|[hi])?)|bjeq|e(?:ad(?:clock|fi|k(?:[234s])|sc(?:ore|ratch)|[fk])|ct2pol|lease|mo(?:teport|ve)|pluck|s(?:hapearray|on(?:(?:xk|[krxyz])?)|yn)|verb(?:(?:2|sc)?)|windscore|zzy)|fft|ifft|ms|nd(?:(?:31)?)|ound|spline|tclock)|s(?:16b14|32b14|a(?:mphold|ndpaper)|c(?:_(?:lag(?:(?:ud)?)|phasor|trig)|a(?:le(?:(?:array)?)|n(?:hammer|table|[su]))|hed(?:kwhen(?:(?:named)?)|ule|when)|oreline(?:(?:_i)?))|e(?:ed|kere|lect|mitone|nse(?:(?:key)?)|qtime(?:(?:2)?)|rial(?:Begin|End|Flush|Print|Read|Write(?:(?:_i)?))|t(?:c(?:(?:o|tr)l)|ksmps|row|scorepos))|f(?:i(?:list|nstr(?:(?:3m|[3m])?))|lo(?:ad|oper)|p(?:assign|l(?:ay(?:(?:3m|[3m])?)|ist)|reset))|h(?:aker|ift(?:in|out))|i(?:gnum|n(?:(?:h|inv|syn)?))|l(?:eighbells|i(?:cearray(?:(?:_i)?)|der(?:16(?:(?:f|table(?:(?:f)?))?)|32(?:(?:f|table(?:(?:f)?))?)|64(?:(?:f|table(?:(?:f)?))?)|8(?:(?:f|table(?:(?:f)?))?)|Kawai)))|nd(?:loop|warp(?:(?:st)?))|o(?:ck(?:recv(?:(?:s)?)|send(?:(?:s)?))|rt(?:[ad])|undin)|p(?:a(?:ce|t3d(?:(?:[it])?))|dist|litrig|rintf(?:(?:k)?)|send)|q(?:rt|uinewave)|t(?:atevar|ix|r(?:c(?:at(?:(?:k)?)|har(?:(?:k)?)|mp(?:(?:k)?)|py(?:(?:k)?))|e(?:cv|son)|fromurl|get|in(?:dex(?:(?:k)?)|g2array)|l(?:en(?:(?:k)?)|ower(?:(?:k)?))|rindex(?:(?:k)?)|s(?:et|ub(?:(?:k)?))|to(?:(?:[dl])k|[dl])|upper(?:(?:k)?))|send)|u(?:binstr(?:(?:init)?)|m(?:(?:array)?))|vfilter|y(?:nc(?:grain|loop|phasor)|stem(?:(?:_i)?)))|t(?:a(?:b(?:2(?:array|pvs)|_i|ifd|le(?:(?:3kt|copy|filter(?:(?:i)?)|gpw|i(?:copy|gpw|kt|mix)|kt|mix|ng|ra|s(?:eg|huffle(?:(?:i)?))|w(?:a|kt)|x(?:kt|seg)|[3iw])?)|morph(?:(?:ak|[ai])?)|play|r(?:ec|owlin)|sum|w(?:(?:_i)?))|mbourine|n(?:h|inv(?:(?:2)?))|[bn])|bvcf|emp(?:est|o(?:(?:(?:sc|v)al)?))|i(?:me(?:dseq|inst(?:[ks])|[ks])|val)|lineto|one(?:(?:[kx])?)|r(?:a(?:dsyn|n(?:dom|seg(?:(?:[br])?)))|cross|filter|highest|i(?:g(?:ger|seq)|m(?:(?:_i)?)|rand)|lowest|mix|s(?:cale|(?:hif|pli)t))|urno(?:ff(?:(?:2)?)|n)|vconv)|u(?:n(?:irand|wrap)|psamp|r(?:andom|d))|v(?:a(?:ctrol|dd(?:(?:_i|v(?:(?:_i)?))?)|get|lpass|set)|bap(?:(?:gmove|lsinit|(?:(?:z)?)move|[gz])?)|c(?:ella|o(?:(?:2(?:(?:(?:f|i(?:f|ni))t)?)|mb|py(?:(?:_i)?))?))|d(?:el(?:_k|ay(?:(?:x(?:w(?:[qs])|[qsw])|[3kx])?))|ivv(?:(?:_i)?))|e(?:cdelay|loc|xp(?:(?:_i|seg|v(?:(?:_i)?))?))|i(?:b(?:es|r(?:(?:ato)?))|ncr)|l(?:i(?:mit|nseg)|owres)|m(?:ap|irror|ult(?:(?:_i|v(?:(?:_i)?))?))|o(?:ice|sim)|p(?:haseseg|o(?:rt|w(?:(?:_i|v(?:(?:_i)?))?))|voc)|rand(?:[hi])|subv(?:(?:_i)?)|tab(?:le(?:1k|w(?:[aik])|[aik])|w(?:[aik])|[aik])|wrap)|w(?:aveset|e(?:bsocket|ibull)|g(?:b(?:ow(?:(?:edbar)?)|rass)|clar|flute|pluck(?:(?:2)?)|uide(?:[12]))|i(?:i(?:connect|data|range|send)|ndow)|r(?:ap|itescratch)|terrain)|x(?:adsr|in|out|scan(?:map|smap|[su])|tratim|yscale)|z(?:a(?:cl|kinit|mod|rg|wm|[rw])|df_(?:1pole(?:(?:_mode)?)|2pole(?:(?:_mode)?)|ladder)|filter2|i(?:wm|[rw])|k(?:cl|mod|wm|[rw]))|[Saikp])\\b|\\b(array|bform(?:(?:de|en)c)|c(?:hanged|opy2(?:(?:[ft])tab))|hrtfer|ktableseg|lentab|m(?:(?:ax|in)tab)|p(?:op(?:(?:_f)?)|tableiw|ush(?:(?:_f)?))|s(?:calet|ndload|oundout(?:(?:s)?)|pec(?:addm|di(?:ff|sp)|filt|hist|ptrk|s(?:cal|um)|trum)|tack|umtab)|t(?:ab(?:gen|leiw|map(?:(?:_i)?)|slice)|b(?:0_init|1(?:(?:(?:[012345])?)_init|[012345])|(?:[23456789])_init|[0123456789]))|vbap(?:16|(?:[48])move|[48])|xyin)\\b)(?:(\\:)([A-Za-z]))?"
         captures:
           1: name: "support.function.csound"
           2: name: "invalid.deprecated.csound"


Text constructor tests

Text constructor tests

--- test/src/trix/text_test.coffee
+++ test/src/trix/text_test.coffee
@@ -8,6 +8,35 @@
       new Trix.Piece("text", { italic: true }),
       new Trix.Piece("!")
     ]
+
+
+test "textForAttachmentWithAttributes", ->
+  attachment = id: 1
+
+  text = Trix.Text.textForAttachmentWithAttributes(attachment)
+  runsEqual text,
+    [{ attachment: attachment, string: undefined, attributes: {} }],
+    "single-run text with attachment and no attributes"
+
+  text = Trix.Text.textForAttachmentWithAttributes(attachment, bold: true)
+  runsEqual text,
+    [{ attachment: attachment, string: undefined, attributes: { bold: true }}],
+    "single-run text with attachment and attributes"
+
+
+test "textForStringWithAttributes", ->
+  string = "Hello, world"
+
+  text = Trix.Text.textForStringWithAttributes(string)
+  runsEqual text,
+    [{ string: string, attachment: undefined, attributes: {} }],
+    "single-run text with string and no attributes"
+
+  text = Trix.Text.textForStringWithAttributes(string, italic: true)
+  runsEqual text,
+    [{ string: string, attachment: undefined, attributes: { italic: true }}],
+    "single-run text with string and attributes"
+

 test "#isEqualTo", ->
   ok @text.isEqualTo(@text), "text is equal to itself"
@@ -21,6 +50,7 @@
   text = @text.getTextAtRange([0, 16])
   ok !@text.isEqualTo(text) and !text.isEqualTo(@text), "text is not equal to subslice of text"

+
 test "#getLength", ->
   text = new Trix.Text
   equal text.getLength(), 0, "empty text length is 0"
@@ -30,3 +60,30 @@

   equal @text.getLength(), 17, "multiple-run text length"

+
+# Test helpers
+
+runsEqual = (text, expectedRuns, message) ->
+  actualRuns = getRunsForText(text)
+
+  if expectedRuns.length isnt actualRuns.length
+    return QUnit.push(false, actualRuns.length, expectedRuns.length, "#{message} (run length mismatch)")
+
+  for actualRun, index in actualRuns
+    expectedRun = expectedRuns[index]
+
+    if expectedRun.attachment? and expectedRun.attachment isnt actualRun.attachment
+      return QUnit.push(false, actualRun.attachment, expectedRun.attachment, "#{message} (attachment mismatch in run #{index + 1})")
+
+    if expectedRun.attributes? and not Trix.Hash.box(expectedRun.attributes).isEqualTo(actualRun.attributes)
+      return QUnit.push(false, actualRun.attributes, expectedRun.attributes, "#{message} (attributes mismatch in run #{index + 1})")
+
+    if expectedRun.string? and expectedRun.string isnt actualRun.string
+      return QUnit.push(false, actualRun.string, expectedRun.string, "#{message} (string mismatch in run #{index + 1})")
+
+  QUnit.push(true, actualRuns, expectedRuns, message)
+
+getRunsForText = (text) ->
+  result = []
+  text.eachRun (run) -> result.push(run)
+  result


hub -- fix a major issue with restarting projects in the hub, which would lead to user hangs, etc.

--- salvus/hub.coffee
+++ salvus/hub.coffee
@@ -3346,7 +3346,7 @@
                 cb?()

     _restart_local_hub_if_not_all_daemons_running: (cb) =>
-        if @_status.local_hub #and @_status.console_server
+        if @_status?.local_hub #and @_status.console_server
             # NOTE! we do *not* check for @_status.sage_server, since it is easy for a user to mess that up.
             # If they mess up console_server and local_hub (which should be very hard), they couldn't fix it
             # anyways -- but messing up the sage server is fixable via the console or file editor.
@@ -3355,9 +3355,9 @@
             # TODO: it would be better just to force start only the daemons that need to be started -- doing this is
             # just a first brutal minimum way to do this!
             bad = ''
-            if not @_status.local_hub
+            if not @_status?.local_hub
                 bad += ' local_hub'
-            if not @_status.console_server
+            if not @_status?.console_server
                 bad += ' console_server'
             winston.debug("Not all daemons are running (not running: #{bad}) -- restart required -- #{@username}@#{@host}")
             @_restart_local_hub_daemons (err) =>
@@ -3365,7 +3365,7 @@
                     cb(err)
                 else
                     # try one more time:
-                    @_get_local_hub_status (err,_status) =>
+                    @_get_local_hub_status (err, _status) =>
                         @_status = _status
                         cb(err)


Resizable window disabled.

Resizable window disabled.

--- electron.coffee
+++ electron.coffee
@@ -51,6 +51,7 @@
             icon: path.join __dirname, 'static_files/images/icon.png'
             title: 'MyouLog'
             skipTaskbar: true
+            resizable: false

         # Create the browser window.
         win = new BrowserWindow options