Scrollable base impl unused code removed

--- impl/base/level2/scrollable.coffee
+++ impl/base/level2/scrollable.coffee
@@ -11,75 +11,11 @@

 	impl._scrollableUsePointer ?= true
 	impl._scrollableUseWheel ?= true
-
-	outQuint = (t, b, c, d) ->
-		# c*((t=t/d-1)*t*t*t*t + 1) + b
-		c * (t/d) + b

 	###
 	Scroll container by given x and y deltas
 	###
 	scroll = do ->
-		# list = []
-		# pending = false
-		# vsyncRun = false
-
-		# getSwingY = (item, y) ->
-		# 	maxSwing = item.height * 0.4
-
-		# 	if y < 0
-		# 		max = 0
-		# 		if y < -maxSwing
-		# 			y = -maxSwing
-		# 	else
-		# 		max = item._impl.contentItem._height - item._height
-		# 		if y < max
-		# 			return y
-		# 		if y > max + maxSwing
-		# 			y = max + maxSwing
-		# 	delta = Math.max(Math.pow(Math.abs(max - y), 1.3) / 42, 2)
-		# 	if y < 0
-		# 		y += delta
-		# 		if y > 0
-		# 			y = 0
-		# 	else
-		# 		y -= delta
-		# 		if y < max
-		# 			y = max
-		# 	y
-
-		# vsync = ->
-		# 	i = 0; n = list.length
-		# 	while i < n
-		# 		item = list[i]
-
-		# 		if item._impl.swingDisabled
-		# 			i++
-		# 			continue
-
-		# 		# y
-		# 		y = getSwingY item, item.contentY
-		# 		max = getLimitedY item, y
-
-		# 		if y is max
-		# 			item._impl.swingPending = false
-		# 			item._impl.swingFramesY = 0
-		# 			item._impl.lastSwingTime = Date.now()
-		# 			list[i] = list[n-1]
-		# 			list.pop()
-		# 			i--; n--;
-
-		# 		item.contentY = Math.round y
-		# 		item._impl.swingFramesY++
-
-		# 		i++
-
-		# 	if list.length
-		# 		requestAnimationFrame vsync
-		# 	else
-		# 		pending = false
-		# 	return
-
 		(item, x=0, y=0) ->
 			deltaX = getDeltaX item, x
 			deltaY = getDeltaY item, y
@@ -88,17 +24,6 @@

 			x = limitedX = getLimitedX item, x
 			y = limitedY = getLimitedY item, y
-
-			# if item._impl.swingPending and not item._impl.swingDisabled
-			# 	y = getSwingY item, y
-
-			# unless item._impl.swingPending
-			# 	if y isnt limitedY
-			# 		item._impl.swingPending = true
-			# 		list.push item
-			# 		unless pending
-			# 			pending = true
-			# 			requestAnimationFrame vsync

 			if item._contentX isnt x or item._contentY isnt y
 				item.contentX = x
@@ -245,12 +170,6 @@
 			if snap
 				snapTarget = getSnapTarget target
 				shouldSnap = data[lastSnapTargetProp] isnt snapTarget
-				# top
-				# shouldSnap ||= item[contentProp] < snapTarget
-				# # bottom
-				# if not shouldSnap and snapTarget + snapTarget[sizeProp] < item[contentProp] + item[sizeProp]
-				# 	shouldSnap = true
-				# 	snapTarget += snapTarget[sizeProp] - item[sizeProp]
 				if shouldSnap
 					target = snapTarget
 					data[lastSnapTargetProp] = snapTarget
@@ -420,9 +339,6 @@
 			x = e.deltaX / WHEEL_DIVISOR
 			y = e.deltaY / WHEEL_DIVISOR

-			# if Math.abs(y) > Math.abs(x)
-			# 	x = y
-
 			if x > 0 and x > maxX
 				maxX = (maxX * (i-1) + x) / i
 			else if x < minX


another aggressivelyAgnostic test

another aggressivelyAgnostic test

--- test/common/kozu/promises_test.coffee
+++ test/common/kozu/promises_test.coffee
@@ -103,3 +103,14 @@
         Promise.resolve({b: Promise.resolve(obj.a)}))
     )
     expect(fn(a: 1)).to.eventually.equal(2)
+  it "returns functions which are agnostic about `this`", ->
+    arrayPromise = Promise.resolve(
+      [
+        Promise.resolve({name: "Jim"}),
+        Promise.resolve({name: "Sally"})
+      ]
+    )
+    arrayPromise.map = promises.aggressivelyAgnostic(Array.prototype.map || core.methodize(core.map))
+    names = arrayPromise.map(core.getter('name'))
+    expect(names).to.eventually.deep.equal(["Jim", "Sally"])
+


Removed whitespace

Removed whitespace

--- test/tests/LayerStatesBackwardsTest.coffee
+++ test/tests/LayerStatesBackwardsTest.coffee
@@ -95,7 +95,7 @@
 	it "should still support layer.states.animationOptions and fall back", ->
 		# This used to crash: https://www.facebook.com/groups/framerjs/permalink/987570871369984/
 		shoes = new Layer
-		shoes.states.stateA = scale: 1
+		shoes.states.stateA = scale: 1
 		shoes.states.stateB = scale: 0.8
 		shoes.states.animationOptions =
 			curve: "spring (300,20,0)"


Ignore select-all events for disabled check-boxes

--- services/web/public/coffee/directives/selectAll.coffee
+++ services/web/public/coffee/directives/selectAll.coffee
@@ -49,18 +49,21 @@
 						selectAllListController.clearSelectAllState()

 				scope.$on "select-all:select", () ->
+					return if element.prop('disabled')
 					ignoreChanges = true
 					scope.$apply () ->
 						scope.ngModel = true
 					ignoreChanges = false

 				scope.$on "select-all:deselect", () ->
+					return if element.prop('disabled')
 					ignoreChanges = true
 					scope.$apply () ->
 						scope.ngModel = false
 					ignoreChanges = false

 				scope.$on "select-all:row-clicked", () ->
+					return if element.prop('disabled')
 					ignoreChanges = true
 					scope.$apply () ->
 						scope.ngModel = !scope.ngModel
@@ -75,4 +78,4 @@
 			link: (scope, element, attrs) ->
 				element.on "click", (e) ->
 					scope.$broadcast "select-all:row-clicked"
-		}+		}


Allow results to be dismissed

Allow results to be dismissed

--- public/coffee/controllers.coffee
+++ public/coffee/controllers.coffee
@@ -178,6 +178,11 @@
       hist.push toStore
       Storage.put key, JSON.stringify(hist)

+  $scope.dismiss = (res) ->
+    results = $scope.m.results or []
+    i = results.indexOf res
+    results.splice(i, 1) if i >= 0
+
   $scope.run = ->
     m = $scope.m


add id to a preload+postmessage test to make it work better

--- testApp/app/controllers/postmessage.coffee
+++ testApp/app/controllers/postmessage.coffee
@@ -31,7 +31,10 @@
         onFailure: ->
           navigator.notification.alert "FAILURE in testPushLayerAndSendMessage failed to push layer"

-    webView = new steroids.views.WebView "views/postmessage/listener.html"
+    webView = new steroids.views.WebView {
+      location: "views/postmessage/listener.html",
+      id: "uliuli"
+    }

     webView.preload {}, {
       onSuccess: ->


add test for sidebar in intro to cypress

--- cypress/integration/main_spec.coffee
+++ cypress/integration/main_spec.coffee
@@ -97,3 +97,15 @@
       cy.get("#search-input").type("g")
       cy.wait("@postAlgolia")
       cy.get(".ds-dropdown-menu").should("be.visible")
+
+  describe "Intro to Cypress", ->
+    beforeEach ->
+      cy.visit("/guides/core-concepts/introduction-to-cypress.html")
+
+    # check if rendering messed up and removed the sidebar
+    it "has navigation sidebar", ->
+      cy.get("aside#sidebar")
+        .should("be.visible")
+
+    it "displays algolia dropdown on search", ->
+      testSearchDropDown()


update

update

--- examples/config.cson
+++ examples/config.cson
@@ -64,7 +64,7 @@
             useJSTemplateString: true

             # Important: path here would be compiled as a JavaScript template string
-            path: 'bash -c "echo current file is ${CURRENT_FILE} which is placed inside ${CURRENT_DIR}"'
+            path: 'cmd /c cmd /k start "echo current file is ${CURRENT_FILE} which is placed inside ${CURRENT_DIR}"'

             console: true # To see the result


asegurando el funcionamiento de la rama develop funcione y este listo para la presentacion

--- proyecto/public/js/controllers/tablero-controller.coffee
+++ proyecto/public/js/controllers/tablero-controller.coffee
@@ -127,10 +127,10 @@
       return true

     # Funcion que devuelve falso
-    # si no existe colision    # con el nuevo barco
-    long = nuevaLongitud
-    dir = nuevaDireccion
-    checkearColisionBarco = (nuevoX, nuevoY, long, dir, duenio)->
+    # si no existe colision con el nuevo barco
+    # longitud es del nuevo barco
+    # dir = direccion del barco horizontal o vertical
+    checkearColisionBarco = (nuevoX, nuevoY, longitud, dir, duenio)->
       colision = false

       if duenio == 's'
@@ -140,7 +140,7 @@

       if barcos.length > 0
         for i in [0..barcos.length-1]
-          for j in [1..nuevaLongitud]
+          for j in [1..longitud]
             if dir == 'h' and barcos[i].estaOcupadoSector(nuevoX+j-1, nuevoY)
               return true
             if dir == 'v' and barcos[i].estaOcupadoSector(nuevoX, nuevoY+j-1)


Fixed rendering of fact wheel in other places.

--- core/app/backbone/views/base_fact_wheel_view.coffee
+++ core/app/backbone/views/base_fact_wheel_view.coffee
@@ -43,6 +43,7 @@
     else
       super()
       @already_rendered = true
+    @

   renderRaphael: ->
     @$canvasEl = $('

')


Add a description for each package

Add a description for each package

--- package.cson
+++ package.cson
@@ -1 +1,2 @@
-'main': 'lib/git-diff'
+'main': './lib/git-diff'
+'description': 'Add decorations to the editor gutter for lines added, edited, and deleted since the last commit.'


Support for sorting in query API

Support for sorting in query API

--- api.coffee
+++ api.coffee
@@ -361,6 +361,15 @@
                   projection[a] = 1 for a in v

         cur = collection.find(q, projection, {batchSize : 50})
+        if urlParts.query.sort?
+          s = JSON.parse(querystring.unescape(urlParts.query.sort))
+          sort = {}
+          for k,v of s
+            if config.ALIASES[k]?
+              sort[a] = v for a in config.ALIASES[k]
+            else
+              sort[k] = v
+          cur.sort(sort)

         cur.skip(parseInt(urlParts.query.skip)) if urlParts.query.skip?
         cur.limit(parseInt(urlParts.query.limit)) if urlParts.query.limit?


app.loadCoreTemplates fix #89

app.loadCoreTemplates fix #89

--- app.coffee
+++ app.coffee
@@ -35,8 +35,16 @@
   unless fs.existsSync session_key_path
     fs.writeFileSync session_key_path, crypto.randomBytes(48).toString('hex')

+exports.loadCoreTemplates = ->
+  app.template_data = {}
+
+  for filename in fs.readdirSync "#{__dirname}/core/template"
+    template_name = path.basename filename, path.extname(filename)
+    app.template_data[template_name] = fs.readFileSync "#{__dirname}/core/template/#{filename}"
+
 exports.run = ->
   exports.checkEnvironment()
+  exports.loadCoreTemplates()

   {user, password, host, name} = config.mongodb

@@ -72,10 +80,6 @@
     app.middleware = require './core/middleware'
     app.notification = require './core/notification'
     app.authenticator = require './core/authenticator'
-
-    app.template_data =
-      ticket_create_email: fs.readFileSync('./core/template/ticket_create_email.html').toString()
-      ticket_reply_email: fs.readFileSync('./core/template/ticket_reply_email.html').toString()

     app.use connect.json()
     app.use connect.urlencoded()


Support Ctrl-. to compile for v1 compabitility

--- services/web/public/coffee/ide/editor/directives/aceEditor.coffee
+++ services/web/public/coffee/ide/editor/directives/aceEditor.coffee
@@ -112,13 +112,21 @@
 				# Prevert Ctrl|Cmd-S from triggering save dialog
 				scope.$watch "onSave", (callback) ->
 					if callback?
+						Vim.defineEx 'write', 'w', callback
 						editor.commands.addCommand
 							name: "save",
 							bindKey: win: "Ctrl-S", mac: "Command-S"
 							exec: () ->
 								callback()
 							readOnly: true
-						Vim.defineEx 'write', 'w', callback
+						# Not technically 'save', but Ctrl-. recompiles in OL v1
+						# so maintain compatibility
+						editor.commands.addCommand
+							name: "recompile_v1",
+							bindKey: win: "Ctrl-.", mac: "Ctrl-."
+							exec: () ->
+								callback()
+							readOnly: true
 				editor.commands.removeCommand "transposeletters"
 				editor.commands.removeCommand "showSettingsMenu"
 				editor.commands.removeCommand "foldall"


Fixing EOF whitespace bug

Fixing EOF whitespace bug

--- app.coffee
+++ app.coffee
@@ -581,7 +581,7 @@
                 lastModified: new Date()
                 context: yaml
                 # The first and last lines are markdown formatting.
-                script: content.split('\n').slice(1,-1).join('\n')
+                script: content.trim().split('\n').slice(1,-1).join('\n')
             .then(resolve)
             .catch(reject)
     )


bugfix in error reporting

bugfix in error reporting

--- modules/gui/lib/widgets/List.coffee
+++ modules/gui/lib/widgets/List.coffee
@@ -68,7 +68,7 @@

         _reload: (done)->
             @_loadData @data.offset, @data.limit, (err, items, data)=>
-                return @logger.error(err) if err
+                return done(err) if err
                 @_display.call @, items, data, done


Fix interpolation

Fix interpolation

--- app.coffee
+++ app.coffee
@@ -49,8 +49,8 @@
             return
         else if result.result
             messages = [
-                'im like #{result.confidence}% turned on'
-                'arousal circuits at #{result.confidence}%'
+                "im like #{result.confidence}% turned on"
+                "arousal circuits at #{result.confidence}%"
             ]
             index = Math.floor(Math.random() * messages.length)
             msg = messages[index]


Temporary disable sentry

Temporary disable sentry

--- app.coffee
+++ app.coffee
@@ -22,9 +22,9 @@
 app = bootable(express())
 server = http.createServer(app)

-if process.env.APP_ENV is 'production'
-	raven = require 'raven'
-	server.error(raven.middleware.express(config.sentryURL));
+#if process.env.APP_ENV is 'production'
+#	raven = require 'raven'
+#	server.error(raven.middleware.express(config.sentryURL));

 app.use(favicon(__dirname + '/client/img/favicon.png'))
 app.set('views', __dirname + '/views')


Bump to v1.0.0-beta4

Bump to v1.0.0-beta4

--- app.coffee
+++ app.coffee
@@ -1,4 +1,4 @@
-global.POI_VERSION = '1.0.0-beta3'
+global.POI_VERSION = '1.0.0-beta4'

 app = require 'app'
 BrowserWindow = require 'browser-window'


Move metrics init to start of app.coffee

--- app.coffee
+++ app.coffee
@@ -1,3 +1,5 @@
+Metrics = require "metrics-sharelatex"
+Metrics.initialize("filestore")
 express = require('express')
 bodyParser = require "body-parser"
 logger = require('logger-sharelatex')
@@ -15,8 +17,6 @@
 if settings.sentry?.dsn?
 	logger.initializeErrorReporting(settings.sentry.dsn)

-Metrics = require "metrics-sharelatex"
-Metrics.initialize("filestore")
 Metrics.open_sockets.monitor(logger)
 Metrics.event_loop?.monitor(logger)
 Metrics.memory.monitor(logger)


Add function to leave chat

Add function to leave chat

--- app.coffee
+++ app.coffee
@@ -90,6 +90,14 @@

 		callback roomList.returnValues if callback?

+leaveChat = (callback) ->
+	request.post config.host + '/index.php/AJAXProxy/',
+	form:
+		actionName: 'leave'
+		className: 'chat\\data\\room\\RoomAction'
+		t: securityToken
+	, -> do callback if callback?
+
 fetchMessages = (callback) ->
 	request.get config.host + 'index.php/NewMessages/', (err, res, body) ->
 		data = JSON.parse body
@@ -103,12 +111,14 @@
 		setTimeout ->
 			recursiveFetchMessages callback
 		, 5e2
-
-fetchSecurityToken ->
-	sendLoginRequest ->
-		# new session after login, refetch token
-		fetchSecurityToken ->
-			getRoomList (roomList) ->
-				fatal 'No available rooms' if roomList.length is 0
-				joinRoom roomList[0].roomID, ->
-					do recursiveFetchMessages
+
+process.on 'SIGTERM', -> leaveChat -> process.exit 0
+process.on 'SIGINT', -> leaveChat -> process.exit 0
+
+
+fetchSecurityToken -> sendLoginRequest ->
+	# new session after login, refetch token
+	fetchSecurityToken -> getRoomList (roomList) ->
+		fatal 'No available rooms' if roomList.length is 0
+		joinRoom roomList[0].roomID, ->
+			do recursiveFetchMessages


feat(paginator): Update user facing text to new API

--- modules/paginator/main/index.coffee
+++ modules/paginator/main/index.coffee
@@ -71,10 +71,10 @@
       visibleCount: 10,
       updatePageOnSelect: true,
       paginatorAria: hx.userFacingText('paginator', 'paginatorAria'),
-      currentPageAria: hx.userFacingText('paginator', 'currentPageAria'),
-      gotoPageAria: hx.userFacingText('paginator', 'gotoPageAria'),
-      prevPageAria: hx.userFacingText('paginator', 'prevPageAria'),
-      nextPageAria: hx.userFacingText('paginator', 'nextPageAria'),
+      currentPageAria: hx.userFacingText('paginator', 'currentPageAria', true),
+      gotoPageAria: hx.userFacingText('paginator', 'gotoPageAria', true),
+      prevPageAria: hx.userFacingText('paginator', 'prevPageAria', true),
+      nextPageAria: hx.userFacingText('paginator', 'nextPageAria', true),
       prevText: hx.userFacingText('paginator', 'prev'),
       nextText: hx.userFacingText('paginator', 'next'),
       v2Features: {
@@ -230,14 +230,14 @@
           return {
             isPrevNextButton: true,
             text: @prevText(),
-            aria: @prevPageAria().replace('$page', currentPage - 1),
+            aria: hx.userfacingText.format(@prevPageAria(), { page: currentPage - 1 }),
             onClick: () => selectPage.call(this, 'user', currentPage - 1),
           }
         if item is 'next'
           return {
             isPrevNextButton: true,
             text: @nextText(),
-            aria: @nextPageAria().replace('$page', currentPage + 1),
+            aria: hx.userfacingText.format(@nextPageAria(), { page: currentPage + 1 }),
             onClick: () => selectPage.call(this, 'user', currentPage + 1),
           }
         if item is '...'
@@ -250,7 +250,7 @@
         aria = if selected then @currentPageAria() else @gotoPageAria()
         return {
           text: numericItem,
-          aria: aria.replace('$page', numericItem),
+          aria: hx.userfacingText.format(aria, { page: numericItem }),
           selected: selected,
           onClick: () => selectPage.call(this, 'user', numericItem)
         }


Add parent(), next(), prev()

Add parent(), next(), prev()

--- js/u.coffee
+++ js/u.coffee
@@ -97,7 +97,19 @@
       toggleClass: (cls) -> @each (i, el) -> u.dom.toggleClass el, cls
       click: (cb) -> @bind "click", cb
       on: (n,cb) -> @bind(n,cb)
-      bind: (n, cb) -> @each (i, el) -> el.addEventListener n, cb
+      bind: (n, cb) -> @each (i, el, capture) -> el.addEventListener n, cb, capture
+
+      parent: ->
+        e = @get(0)
+        return new uSet(e.parentNode) if e
+
+      next: ->
+        e = @get(0)
+        return new uSet(e.nextSibling) if e
+
+      prev: ->
+        e = @get(0)
+        return new uSet(e.prevSibling) if e

       ###
       # Returns style or computed style


remove .shadowRoot from editor view

remove .shadowRoot from editor view

The contents of atom-text-editor elements are no longer encapsulated within a shadow DOM boundary. Please, stop using shadowRoot and access the editor contents directly instead.

--- lib/line-diff-worker.coffee
+++ lib/line-diff-worker.coffee
@@ -9,7 +9,7 @@
         @clearMarkers()
         markers = @editor.findMarkers({name: "line-diff"})
         marker.destroy() for marker in markers
-        editorView = atom.views.getView(@editor).shadowRoot
+        editorView = atom.views.getView(@editor)
         gutter = $(editorView).find ".gutter"
         statusChangeSelector = ".git-line-modified, .git-line-removed, .git-line-added"
         gutter.off("click mouseenter mouseleave")


nvim arguments starts from 3rd

nvim arguments starts from 3rd

--- src/nvim/nvim.coffee
+++ src/nvim/nvim.coffee
@@ -14,7 +14,7 @@

     # Atom Shell apps are run as 'Atom <path> <args>'
     # might need a better way to locate the arguments
-    nvim_args = ['--embed'].concat remote.process.argv[2..]
+    nvim_args = ['--embed'].concat remote.process.argv[3..]

     @nvim_process = child_process.spawn 'nvim', nvim_args, stdio: ['pipe', 'pipe', process.stderr]
     console.log 'child process spawned: ' + @nvim_process.pid


Disabled release

Disabled release

--- lib/model_extensions.coffee
+++ lib/model_extensions.coffee
@@ -191,9 +191,10 @@
     return _original_initialize.apply(@, arguments)

   model_type::release = ->
-    if model_type.schema and (schema = model_type.schema())
-      relation.releaseModel(@) for key, relation of schema.relations
-    return
+    throw "release: experimental and incomplete"
+    # if model_type.schema and (schema = model_type.schema())
+    #   relation.releaseModel(@) for key, relation of schema.relations
+    # return

   ###################################
   # Backbone ORM - Model Overrides


Revert 723253f to fix weird keybinding regressions

For reasons unknown, this commit has caused copy/paste functions to stop
working on non-editor elements with input focus. Which makes zero sense,
but hey, that's Atom for you.

--- keymap.cson
+++ keymap.cson
@@ -73,9 +73,6 @@
 	"alt-7":          "unset!"
 	"alt-8":          "unset!"
 	"alt-9":          "unset!"
-	"ctrl-c":         "unset!"
-	"ctrl-x":         "unset!"
-	"ctrl-v":         "unset!"
 	"ctrl-1":         "pane:show-item-1"
 	"ctrl-2":         "pane:show-item-2"
 	"ctrl-3":         "pane:show-item-3"
@@ -183,9 +180,6 @@
 	"shift-cmd-c":    "find-and-replace:toggle-case-option"

 "body.platform-darwin .tree-view":
-	"cmd-c":          "unset!"
-	"cmd-x":          "unset!"
-	"cmd-v":          "unset!"
 	"cmd-1":          "pane:show-item-1"
 	"cmd-2":          "pane:show-item-2"
 	"cmd-3":          "pane:show-item-3"


Agent pie: start/end angle pie transition work

--- widgets/fullpie_agent/fullpie_agent.coffee
+++ widgets/fullpie_agent/fullpie_agent.coffee
@@ -403,8 +403,8 @@

         #console.log('window.oldPieData BOTTOM',window.oldPieData)
         #window.oldPieData[@instanceDataId] = piedata
-        window.oldPieData = window.oldPieData or {}
-        window.oldPieData[@instanceDataId] = window.oldPieData[@instanceDataId] or []
+        #window.oldPieData = window.oldPieData or {}
+        #window.oldPieData[@instanceDataId] = window.oldPieData[@instanceDataId] or []
         window.oldPieData[@instanceDataId] = piedata
         #console.log('piedata',piedata)
         return


HTTP between servers

HTTP between servers

--- lib/services/appnima.coffee
+++ lib/services/appnima.coffee
@@ -7,15 +7,15 @@
 ###
 "use strict"

-https   = require "https"
+http    = require "http"
 qs      = require "querystring"
 Hope    = require "hope"

 Appnima =
   key     : ""
-  protocol: "https"
+  protocol: "http"
   host    : "api.appnima.com"
-  port    : 443
+  port    : 80

   open: (connection) ->
     promise = new Hope.Promise()
@@ -68,7 +68,7 @@
       options.headers["Content-Type"] = "application/x-www-form-urlencoded"
       options.headers["Content-Length"] = body.length

-    client = https.request options, (response) =>
+    client = http.request options, (response) =>
       body = ""
       response.setEncoding "utf8"
       response.on "data", (chunk) -> body += chunk


resize holes

resize holes

--- lib/text-buffer/pure.coffee
+++ lib/text-buffer/pure.coffee
@@ -101,6 +101,37 @@

     return text

+# resizeHoles : Text -> Text
+# resize all holes to make room for goal indices {! asdsd __!}
+resizeHoles = (indices) ->
+
+    tokens = new Lexer text
+        .lex commentRegex, 'raw', 'comment'
+        .lex goalBracketRegex, 'raw', 'goal bracket'
+        .result
+
+    i = 0
+
+    text = tokens.map (obj) =>
+        if obj.type is 'goal bracket'
+            # in case the goalIndex wasn't given, make it '*'
+            # this happens when splitting case, agda2-goals-action is one index short
+            goalIndex = indices[i] || '*'
+
+            paddingSpaces = ' '.repeat(goalIndex.toString().length)
+
+            # strip whitespaces in between {!<--space-->some data<---space-->!}
+            content = /\{!(.*)!\}/.exec(obj.content)[1].replace(/^\s\s*/, '').replace(/\s\s*$/, '')
+
+            obj.content = "{! #{content + paddingSpaces} !}"
+            i += 1
+            return obj
+        .map (obj) => obj.content
+        .join('')
+
+    return text
+
+

 module.exports =


queue: function to check docs in queue

queue: function to check docs in queue

--- lib/transforms/queue.coffee
+++ lib/transforms/queue.coffee
@@ -23,10 +23,11 @@
         @push out
         cb()
     , @options.concurrency
+  _docs_in_queue: => @q.length() + @q.running()
   _transform: (chunk, encoding, cb) =>
     # If the queue is full, we hold on to the callback to preserve backpressure
     async.whilst(
-      => @q.length() + @q.running() >= @options.concurrency
+      => @_docs_in_queue() >= @options.concurrency
       (cb_w) => nextTick cb_w
       =>
         debug "pushing", chunk
@@ -34,7 +35,7 @@
         cb()
     )
   _flush: (cb) =>
-    if @q.length() + @q.running() > 0
+    if @_docs_in_queue() > 0
       @q.drain = => cb @_err
     else
       nextTick => cb @_err


Fix: name of controller

Fix: name of controller

--- app/assets/javascripts/app/main.js.coffee
+++ app/assets/javascripts/app/main.js.coffee
@@ -3,6 +3,6 @@
 @simpleWebApp.config(['$routeProvider', ($routeProvider) ->
   $routeProvider.otherwise({
     templateUrl: '/assets/home.html',
-    controller: 'HomeCtrl'
+    controller: 'MessagesCtrl'
   })
 ])


BF-124 adjusted branching, now compatible with brainflight DB

--- app/assets/javascripts/model/route.coffee
+++ app/assets/javascripts/model/route.coffee
@@ -84,7 +84,8 @@
     @initialize().done =>

       @addToBuffer(position)
-      @branchStack.push(position)
+      # push TransformationMatrix for compatibility reasons
+      @branchStack.push([0,0,0,0,0,0,0,0,0,0,0,0,position[0],position[1],position[2],0])

     return


updated api

updated api

--- app/assets/javascripts/monster/api.coffee
+++ app/assets/javascripts/monster/api.coffee
@@ -3,6 +3,34 @@
 # (c) 2013 http://monsterboxpro.com
 # License: MIT
 #
+
+parameter_name = (root)->
+  name = root[0]
+  name += '['  + root.slice(1).join('][') + ']' if root.length > 1
+  name
+has_attached_file = (value)->
+  result = false
+  if typeof value == 'object' && !(value instanceof File)
+    for own k,v of value
+      result |= has_attached_file v
+  else if typeof value == 'array'
+    for vv in v
+      result |= has_attached_file vv
+  else
+    result |= value instanceof File
+  return result
+form_object_to_form_data = (value,fd=null,root=[]) ->
+  fd = new FormData() unless fd
+  if typeof value == 'object' && !(value instanceof File)
+    for own k,v of value
+      form_object_to_form_data v, fd, root.concat [k]
+  else if typeof value == 'array'
+    for i,vv in value
+      form_object_to_form_data vv, fd, root.concat [i]
+  else
+    return if _.last(root)[0] == '$' # Skip angular attributes like $$hashKey
+    fd.append parameter_name(root), value
+  fd

 class window.ApiBase
   _get:(table_name,action,name,params={},opts={})=>
@@ -14,11 +42,31 @@
     @_callback table_name, req, action, opts
   _post:(table_name,action,name,params={},opts={})=>
     params.socket_id = window.socket_id if window.socket_id
-    req  = @$http.post name, params
+    if has_attached_file(params)
+      form_data = form_object_to_form_data(params)
+      req = @$http
+        method: 'POST'
+        url: name
+        data: form_data
+        transformRequest: angular.identity
+        headers:
+          'Content-Type': undefined
+    else
+      req  = @$http.post name, params
     @_callback table_name, req, action, opts
   _put:(table_name,action,name,params,opts={})=>
     params.socket_id = window.socket_id if window.socket_id
-    req  = @$http.put name, params
+    if has_attached_file(params)
+      form_data = form_object_to_form_data(params)
+      req = @$http
+        method: 'PUT'
+        url: name
+        data: form_data
+        transformRequest: angular.identity
+        headers:
+          'Content-Type': undefined
+    else
+      req  = @$http.put name, params
     @_callback table_name, req, action, opts
   _delete:(table_name,action,name,params={},opts={})=>
     params.socket_id = window.socket_id if window.socket_id
@@ -48,13 +96,13 @@
   constructor:(@$rootScope,@$http)->
     _.each @resources, (options, table_name) =>
       @[table_name] =
-        index   : (params,opts)=>       @_get    table_name, 'index'  , @path(table_name) , params, opts
-        new     : (params,opts)=>       @_get    table_name, 'new'    , @path(table_name) , params, opts
-        create  : (params,opts)=>       @_post   table_name, 'create' , @path(table_name) , params, opts
-        show    : (model,params,opts)=> @_get    table_name, 'show'   , @path(table_name,@_extract_id(model)) , params, opts
-        edit    : (model,params,opts)=> @_get    table_name, 'edit'   , @path(table_name,@_extract_id(model)) , params, opts
-        update  : (model,params,opts)=> @_put    table_name, 'update' , @path(table_name,@_extract_id(model)) , params, opts
-        destroy : (model,params,opts)=> @_delete table_name, 'destroy', @path(table_name,@_extract_id(model)) , params, opts
+        index   : (params,opts)=>       @_get    table_name, 'index'  , @path(table_name)       , params, opts
+        new     : (params,opts)=>       @_get    table_name, 'new'    , @path(table_name,'new') , params, opts
+        create  : (params,opts)=>       @_post   table_name, 'create' , @path(table_name)       , params, opts
+        show    : (model,params,opts)=> @_get    table_name, 'show'   , @path(table_name,@_extract_id(model))        , params, opts
+        edit    : (model,params,opts)=> @_get    table_name, 'edit'   , @path(table_name,@_extract_id(model),'edit') , params, opts
+        update  : (model,params,opts)=> @_put    table_name, 'update' , @path(table_name,@_extract_id(model))        , params, opts
+        destroy : (model,params,opts)=> @_delete table_name, 'destroy', @path(table_name,@_extract_id(model))        , params, opts
       _.each options.collection, (method, action) =>
         name = @path table_name, action
         fun = switch method


enable unrolls on edit

enable unrolls on edit

--- app/assets/javascripts/selector.js.coffee
+++ app/assets/javascripts/selector.js.coffee
@@ -364,8 +364,14 @@
       false

   $(document).behave "load", "input[data-selector]", (event) ->
-    $("input[data-selector]").each ->
-      $(this).selector()
+    enableSelectors = ($collection) =>
+      $collection.each ->
+        $(this).selector()
+
+    document.addEventListener 'DOMContentLoaded', ->
+      enableSelectors($("input[data-selector]"))
+
+    E.onDOMElementAdded("input[data-selector]", enableSelectors)

   $(document).on "selector:change", (changeEvent, value) ->
     $("*[data-selector-update]").each ->


Potential fix for the problem in 'relay'

--- scripts/exp.coffee
+++ scripts/exp.coffee
@@ -8,4 +8,5 @@
   robot.respond /relay(?: to)? (#[^ ]+) +(.*)/i, (msg) ->
     channel = msg.match[1]
     text = msg.match[2]
-    msg.send "/msg #{channel} #{text}"+    msg.envelope.room = channel
+    msg.send text


NewAnalyzer tests commented

NewAnalyzer tests commented

--- test/NewAnalyzerSpec.coffee
+++ test/NewAnalyzerSpec.coffee
@@ -1,595 +1,595 @@
-define ['NewAnalyzer', 'Utils'], (Analyzer, u)->
-
-  fdescribe 'Analyzer', ->
-    subject = undefined
-
-    beforeEach ->
-      subject = Analyzer()
-
-    describe 'resolve', ->
-      subject  =
-      resolved = undefined
-
-      beforeEach ->
-        subject = Analyzer('resolve')
-        resolved = Analyzer('resolved')
-        Analyzer('resolved', undefined)
-
-      it 'should set resolve to true', ->
-        expect(resolved()).toBeUndefined()
-        subject()
-        expect(resolved()).toBeTruthy()
-        subject()
-        expect(resolved()).toBeTruthy()
-
-    describe 'unresolve', ->
-      subject  =
-      resolved = undefined
-
-      beforeEach ->
-        subject = Analyzer('unresolve')
-        resolved = Analyzer('resolved')
-        Analyzer('resolved', undefined)
-
-      it 'should set unresolve to true', ->
-        expect(resolved()).toBeUndefined()
-        subject()
-        expect(resolved()).toBeUndefined()
-        Analyzer('resolved', true)
-        expect(resolved()).toBeTruthy()
-        subject()
-        expect(resolved()).toBeUndefined()
-
-    describe 'dump', ->
-      beforeEach ->
-        Analyzer('crntChar', undefined)
-        Analyzer('dumped', 'edcb')
-        Analyzer('dump')('a')
-
-      it 'should set crntChar', ->
-        expect(Analyzer('crntChar')()).toBe 'a'
-
-      it 'should leave only four last chars', ->
-        expect(Analyzer('dumped')()).toBe 'dcba'
-
-    describe 'charFilter', ->
-      spy      =
-      resolve  =
-      resolved = undefined
-      processibleChars = u(Analyzer('SPECIAL_CHARS')).values()
-
-      beforeEach ->
-        spy = jasmine.createSpy('resolve')
-        subject  = Analyzer('charFilter')
-        resolved = Analyzer('resolved')
-        resolve  = Analyzer('resolve')
-        Analyzer('resolved', undefined)
-        spy.calls.reset()
-
-      afterEach -> Analyzer('resolve', resolve)
-
-      it 'should resolve if crntChar not in processibleChars', ->
-        Analyzer('resolve', spy)
-        Analyzer('crntChar', 'a')
-        subject()
-        expect(spy).toHaveBeenCalledWith()
-
-      it 'should not resolve if crntChar in processibleChars', ->
-        Analyzer('resolve', spy)
-        for char in processibleChars
-          Analyzer('crntChar', char)
-          subject()
-          expect(spy).not.toHaveBeenCalled()
-
-      describe 'inner state', ->
-        cases = [
-          { value: "\n"
-          state:
-            endOfLine:        true
-            escape:           undefined
-            quote:            undefined
-            doubleQuote:      undefined
-            openParenthesis:  undefined
-            closeParenthesis: undefined }
-          { value: '\\'
-          state:
-            endOfLine:        undefined
-            escape:           true
-            quote:            undefined
-            doubleQuote:      undefined
-            openParenthesis:  undefined
-            closeParenthesis: undefined }
-          { value: "'"
-          state:
-            endOfLine:        undefined
-            escape:           undefined
-            quote:            true
-            doubleQuote:      undefined
-            openParenthesis:  undefined
-            closeParenthesis: undefined }
-          { value: '"'
-          state:
-            endOfLine:        undefined
-            escape:           undefined
-            quote:            undefined
-            doubleQuote:      true
-            openParenthesis:  undefined
-            closeParenthesis: undefined }
-          { value: '('
-          state:
-            endOfLine:        undefined
-            escape:           undefined
-            quote:            undefined
-            doubleQuote:      undefined
-            openParenthesis:  true
-            closeParenthesis: undefined }
-          { value: ')'
-          state:
-            endOfLine:        undefined
-            escape:           undefined
-            quote:            undefined
-            doubleQuote:      undefined
-            openParenthesis:  undefined
-            closeParenthesis: true      }
-        ]
-
-        for exam in cases
-          do (exam = exam)->
-            describe "in case of #{JSON.stringify(exam.value)}", ->
-
-              beforeEach ->
-                Analyzer('crntChar', exam.value)
-                Analyzer('charFilter')()
-
-              for param, value of exam.state
-                do (param = param, value = value) ->
-                  it "#{param} should equal #{value}", ->
-                    expect(Analyzer(param)()).toBe value
-
-    describe 'escapeTracker', ->
-      cases = [
-        { escape: undefined
-        escaped:
-            before: undefined
-            after: undefined }
-        { escape: true
-        escaped:
-            before: undefined
-            after: true }
-        { escape: undefined
-        escaped:
-            before: true
-            after: undefined }
-        { escape: true
-        escaped:
-            before: true
-            after: undefined }
-      ]
-
-      for exam in cases
-        do (exam = exam)->
-          describe "in case when escape = #{JSON.stringify(exam.escape)} and escaped = #{JSON.stringify(exam.escaped.before)}", ->
-            escape  =
-            escaped = undefined
-
-            beforeEach ->
-              escape  = Analyzer('escape')
-              escaped = Analyzer('escaped')
-              Analyzer('escape', exam.escape)
-              Analyzer('escaped', exam.escaped.before)
-              Analyzer('escapeTracker')()
-
-            it 'should not update escape', ->
-              expect(escape()).toBe exam.escape
-
-            it "should change escaped to #{JSON.stringify(exam.escaped.after)}", ->
-              expect(escaped()).toBe exam.escaped.after
-
-    describe 'callInChain', ->
-      func1 = jasmine.createSpy 'func1'
-      func2 = jasmine.createSpy('func2').and.callFake -> Analyzer('resolved', true)
-      func3 = jasmine.createSpy('func3')
-      unresolve = jasmine.createSpy 'unresolve'
-
-      beforeEach ->
-        Analyzer('resolved', undefined)
-        subject   = Analyzer('callInChain')
-        Analyzer('unresolve', unresolve)
-
-      it 'should call given methods in chain', ->
-        subject func1, func2
-        expect(func1).toHaveBeenCalledWith()
-        expect(func2).toHaveBeenCalledWith()
-
-      it 'should return if resolved', ->
-        subject func1, func2, func3
-        expect(func1).toHaveBeenCalledWith()
-        expect(func2).toHaveBeenCalledWith()
-        expect(func3).not.toHaveBeenCalled()
-
-      it 'should unresolve on start', ->
-        subject()
-        expect(unresolve).toHaveBeenCalledWith()
-
-    describe 'stringTracker', ->
-      cases = [
-        { escaped: undefined
-        chars: [
-          { value: '"'
-          inString: [
-            { before: undefined, after: '"'      , resolved: true }
-            { before: '"',       after: undefined, resolved: true }
-            { before: "'",       after: "'"      , resolved: true }
-          ] }
-          { value: "'"
-          inString: [
-            { before: undefined, after: "'"      , resolved: true }
-            { before: "'",       after: undefined, resolved: true }
-            { before: '"',       after: '"'      , resolved: true }
-          ] }
-          { value: "a"
-          inString: [
-            { before: undefined, after: undefined, resolved: undefined }
-            { before: "'",       after: "'"      , resolved: true }
-            { before: '"',       after: '"'      , resolved: true }
-          ] }
-        ] }
-        { escaped: true
-        chars: [
-          { value: '"'
-          inString: [
-            { before: undefined, after: undefined, resolved: true }
-            { before: '"',       after: '"'      , resolved: true }
-            { before: "'",       after: "'"      , resolved: true }
-          ] }
-          { value: "'"
-          inString: [
-            { before: undefined, after: undefined, resolved: true }
-            { before: "'",       after: "'"      , resolved: true }
-            { before: '"',       after: '"'      , resolved: true }
-          ] }
-          { value: "a"
-          inString: [
-            { before: undefined, after: undefined, resolved: undefined }
-            { before: "'",       after: "'"      , resolved: true }
-            { before: '"',       after: '"'      , resolved: true }
-          ] }
-        ] }
-      ]
-
-      for exam in cases
-        do (exam = exam)->
-          describe "when escaped = #{JSON.stringify(exam.escaped)}", ->
-            beforeEach -> Analyzer('escaped', exam.escaped)
-
-            for char in exam.chars
-              do (char = char)->
-                describe "and currentChar = #{JSON.stringify(char.value)}", ->
-                  beforeEach ->
-                    Analyzer('crntChar', char.value)
-                    Analyzer('charFilter')()
-
-                  for subject in char.inString
-                    do (subject = subject)->
-                      describe "and inString = #{JSON.stringify(subject.before)}", ->
-                        beforeEach ->
-                          Analyzer('inString', subject.before)
-                          Analyzer('resolved', undefined)
-
-                        it "inString should became #{JSON.stringify(subject.after)}", ->
-                          Analyzer('stringTracker')()
-                          expect(Analyzer('inString')()).toBe subject.after
-
-                        it "resolved should be #{JSON.stringify(subject.resolved)}", ->
-                          Analyzer('stringTracker')()
-                          expect(Analyzer('resolved')()).toBe subject.resolved
-
-    describe 'parenthesesTracker', ->
-      cases = [
-        { crntChar: '('
-        escaped: undefined
-        cases: [
-          { before: [], after: ['('] }
-          { before: ['('], after: ['(', '('] }
-          { before: ['(', '('], after: ['(', '(', '('] }
-        ] }
-        { crntChar: ')'
-        escaped: undefined
-        cases: [
-          { before: [], after: [] }
-          { before: ['('], after: [] }
-          { before: ['(', '('], after: ['('] }
-        ] }
-        { crntChar: 'a'
-        escaped: undefined
-        cases: [
-          { before: [], after: [] }
-          { before: ['('], after: ['('] }
-          { before: ['(', '('], after: ['(', '('] }
-        ] }
-        { crntChar: '('
-        escaped: true
-        cases: [
-          { before: [], after: [] }
-          { before: ['('], after: ['('] }
-          { before: ['(', '('], after: ['(', '('] }
-        ] }
-        { crntChar: ')'
-        escaped: true
-        cases: [
-          { before: [], after: [] }
-          { before: ['('], after: ['('] }
-          { before: ['(', '('], after: ['(', '('] }
-        ] }
-        { crntChar: 'a'
-        escaped: true
-        cases: [
-          { before: [], after: [] }
-          { before: ['('], after: ['('] }
-          { before: ['(', '('], after: ['(', '('] }
-        ] }
-      ]
-
-      for exam in cases
-        do (exam = exam)->
-          describe "when currentChar = #{JSON.stringify(exam.crntChar)}", ->
-            beforeEach ->
-              Analyzer('resolved', undefined)
-              Analyzer('crntChar', exam.crntChar)
-              Analyzer('escaped', exam.escaped)
-              Analyzer('charFilter')()
-
-            for ex in exam.cases
-              do (ex = ex)->
-                it "should change parentheses from #{JSON.stringify(ex.before)} to #{JSON.stringify(ex.after)}", ->
-                  Analyzer('parentheses', ex.before)
-                  Analyzer('parenthesesTracker')()
-                  expect(Analyzer('parentheses')()).toBeEqual ex.after
-
-    describe 'dslTracker', ->
-      cases = [
-        { dump: '.is('
-        crntChar: '('
-        cases: [
-          { escaped: undefined
-          inString: undefined
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: 1 }
-            { parentheses: []
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: 2 }
-          ] }
-          { escaped: true
-          inString: undefined
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-          ] }
-          { escaped: undefined
-          inString: true
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-          ] }
-        ] }
-        { dump: 'is(('
-        crntChar: '('
-        cases: [
-          { escaped: undefined
-          inString: undefined
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: []
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-          ] }
-          { escaped: true
-          inString: undefined
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-          ] }
-          { escaped: undefined
-          inString: true
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-          ] }
-        ] }
-        { dump: ''
-        crntChar: ')'
-        cases: [
-          { escaped: undefined
-          inString: undefined
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: []
-            inDslParams:
-              before: 1
-              after: undefined }
-            { parentheses: []
-            inDslParams:
-              before: 2
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 1
-              after: undefined }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: 2
-              after: undefined }
-          ] }
-          { escaped: true
-          inString: undefined
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-          ] }
-          { escaped: undefined
-          inString: true
-          cases: [
-            { parentheses: ['(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-            { parentheses: ['(']
-            inDslParams:
-              before: 2
-              after: 2 }
-            { parentheses: ['(', '(']
-            inDslParams:
-              before: undefined
-              after: undefined }
-          ] }
-        ] }
-      ]
-
-      for exam in cases
-        do (exam = exam)->
-          describe "when dump = #{JSON.stringify(exam.dump)}
-                    and crntChar = #{JSON.stringify(exam.crntChar)}", ->
-            beforeEach ->
-              Analyzer('dumped', exam.dump)
-              Analyzer('crntChar', exam.crntChar)
-              Analyzer('charFilter')()
-
-            for ex in exam.cases
-              do (ex = ex)->
-                for e in ex.cases
-                  do (e = e)->
-                    describe "and escaped = #{JSON.stringify(ex.escaped)}
-                              and inString = #{JSON.stringify(ex.inString)}
-                              and parentheses =  #{JSON.stringify(e.parentheses)}", ->
-                      beforeEach ->
-                        Analyzer('escaped', ex.escaped)
-                        Analyzer('inString', ex.inString)
-                        Analyzer('parentheses', e.parentheses)
-                        Analyzer('inDslParams', e.inDslParams.before)
-                        Analyzer('dslTracker')()
-
-                      it "inDslParams should became #{e.inDslParams.after}", ->
-                        expect(Analyzer('inDslParams')()).toBe e.inDslParams.after
-
-    describe 'main function', ->
-      dumpSpy            =
-      crntChar           =
-      charFilter         =
-      dslTracker         =
-      callInChain        =
-      escapeTracker      =
-      stringTracker      =
-      callInChainSpy     =
-      parenthesesTracker = undefined
-
-      beforeEach ->
-        crntChar           = Analyzer('crntChar')
-        charFilter         = Analyzer('charFilter')
-        dslTracker         = Analyzer('dslTracker')
-        callInChain        = Analyzer('callInChain')
-        escapeTracker      = Analyzer('escapeTracker')
-        stringTracker      = Analyzer('stringTracker')
-        parenthesesTracker = Analyzer('parenthesesTracker')
-
-        dumpSpy        = jasmine.createSpy('dump')
-        callInChainSpy = jasmine.createSpy('callInChain')
-        Analyzer('crntChar',    undefined)
-        Analyzer('dump',        dumpSpy)
-        Analyzer('callInChain', callInChainSpy)
-        dumpSpy.calls.reset()
-        callInChainSpy.calls.reset()
-
-      afterEach -> Analyzer('callInChain', callInChain)
-
-      it 'should dump currentChar', ->
-        subject('a')
-        expect(dumpSpy).toHaveBeenCalledWith 'a'
-
-      it 'should call filters in chain', ->
-        subject('a')
-        expect(callInChainSpy).toHaveBeenCalledWith(
-          escapeTracker
-          charFilter
-          stringTracker
-          parenthesesTracker
-          dslTracker
-        )
-
-
+# define ['NewAnalyzer', 'Utils'], (Analyzer, u)->
+
+  # describe 'Analyzer', ->
+  #   subject = undefined
+
+  #   beforeEach ->
+  #     subject = Analyzer()
+
+  #   describe 'resolve', ->
+  #     subject  =
+  #     resolved = undefined
+
+  #     beforeEach ->
+  #       subject = Analyzer('resolve')
+  #       resolved = Analyzer('resolved')
+  #       Analyzer('resolved', undefined)
+
+  #     it 'should set resolve to true', ->
+  #       expect(resolved()).toBeUndefined()
+  #       subject()
+  #       expect(resolved()).toBeTruthy()
+  #       subject()
+  #       expect(resolved()).toBeTruthy()
+
+  #   describe 'unresolve', ->
+  #     subject  =
+  #     resolved = undefined
+
+  #     beforeEach ->
+  #       subject = Analyzer('unresolve')
+  #       resolved = Analyzer('resolved')
+  #       Analyzer('resolved', undefined)
+
+  #     it 'should set unresolve to true', ->
+  #       expect(resolved()).toBeUndefined()
+  #       subject()
+  #       expect(resolved()).toBeUndefined()
+  #       Analyzer('resolved', true)
+  #       expect(resolved()).toBeTruthy()
+  #       subject()
+  #       expect(resolved()).toBeUndefined()
+
+  #   describe 'dump', ->
+  #     beforeEach ->
+  #       Analyzer('crntChar', undefined)
+  #       Analyzer('dumped', 'edcb')
+  #       Analyzer('dump')('a')
+
+  #     it 'should set crntChar', ->
+  #       expect(Analyzer('crntChar')()).toBe 'a'
+
+  #     it 'should leave only four last chars', ->
+  #       expect(Analyzer('dumped')()).toBe 'dcba'
+
+  #   describe 'charFilter', ->
+  #     spy      =
+  #     resolve  =
+  #     resolved = undefined
+  #     processibleChars = u(Analyzer('SPECIAL_CHARS')).values()
+
+  #     beforeEach ->
+  #       spy = jasmine.createSpy('resolve')
+  #       subject  = Analyzer('charFilter')
+  #       resolved = Analyzer('resolved')
+  #       resolve  = Analyzer('resolve')
+  #       Analyzer('resolved', undefined)
+  #       spy.calls.reset()
+
+  #     afterEach -> Analyzer('resolve', resolve)
+
+  #     it 'should resolve if crntChar not in processibleChars', ->
+  #       Analyzer('resolve', spy)
+  #       Analyzer('crntChar', 'a')
+  #       subject()
+  #       expect(spy).toHaveBeenCalledWith()
+
+  #     it 'should not resolve if crntChar in processibleChars', ->
+  #       Analyzer('resolve', spy)
+  #       for char in processibleChars
+  #         Analyzer('crntChar', char)
+  #         subject()
+  #         expect(spy).not.toHaveBeenCalled()
+
+  #     describe 'inner state', ->
+  #       cases = [
+  #         { value: "\n"
+  #         state:
+  #           endOfLine:        true
+  #           escape:           undefined
+  #           quote:            undefined
+  #           doubleQuote:      undefined
+  #           openParenthesis:  undefined
+  #           closeParenthesis: undefined }
+  #         { value: '\\'
+  #         state:
+  #           endOfLine:        undefined
+  #           escape:           true
+  #           quote:            undefined
+  #           doubleQuote:      undefined
+  #           openParenthesis:  undefined
+  #           closeParenthesis: undefined }
+  #         { value: "'"
+  #         state:
+  #           endOfLine:        undefined
+  #           escape:           undefined
+  #           quote:            true
+  #           doubleQuote:      undefined
+  #           openParenthesis:  undefined
+  #           closeParenthesis: undefined }
+  #         { value: '"'
+  #         state:
+  #           endOfLine:        undefined
+  #           escape:           undefined
+  #           quote:            undefined
+  #           doubleQuote:      true
+  #           openParenthesis:  undefined
+  #           closeParenthesis: undefined }
+  #         { value: '('
+  #         state:
+  #           endOfLine:        undefined
+  #           escape:           undefined
+  #           quote:            undefined
+  #           doubleQuote:      undefined
+  #           openParenthesis:  true
+  #           closeParenthesis: undefined }
+  #         { value: ')'
+  #         state:
+  #           endOfLine:        undefined
+  #           escape:           undefined
+  #           quote:            undefined
+  #           doubleQuote:      undefined
+  #           openParenthesis:  undefined
+  #           closeParenthesis: true      }
+  #       ]
+
+  #       for exam in cases
+  #         do (exam = exam)->
+  #           describe "in case of #{JSON.stringify(exam.value)}", ->
+
+  #             beforeEach ->
+  #               Analyzer('crntChar', exam.value)
+  #               Analyzer('charFilter')()
+
+  #             for param, value of exam.state
+  #               do (param = param, value = value) ->
+  #                 it "#{param} should equal #{value}", ->
+  #                   expect(Analyzer(param)()).toBe value
+
+  #   describe 'escapeTracker', ->
+  #     cases = [
+  #       { escape: undefined
+  #       escaped:
+  #           before: undefined
+  #           after: undefined }
+  #       { escape: true
+  #       escaped:
+  #           before: undefined
+  #           after: true }
+  #       { escape: undefined
+  #       escaped:
+  #           before: true
+  #           after: undefined }
+  #       { escape: true
+  #       escaped:
+  #           before: true
+  #           after: undefined }
+  #     ]
+
+  #     for exam in cases
+  #       do (exam = exam)->
+  #         describe "in case when escape = #{JSON.stringify(exam.escape)} and escaped = #{JSON.stringify(exam.escaped.before)}", ->
+  #           escape  =
+  #           escaped = undefined
+
+  #           beforeEach ->
+  #             escape  = Analyzer('escape')
+  #             escaped = Analyzer('escaped')
+  #             Analyzer('escape', exam.escape)
+  #             Analyzer('escaped', exam.escaped.before)
+  #             Analyzer('escapeTracker')()
+
+  #           it 'should not update escape', ->
+  #             expect(escape()).toBe exam.escape
+
+  #           it "should change escaped to #{JSON.stringify(exam.escaped.after)}", ->
+  #             expect(escaped()).toBe exam.escaped.after
+
+  #   describe 'callInChain', ->
+  #     func1 = jasmine.createSpy 'func1'
+  #     func2 = jasmine.createSpy('func2').and.callFake -> Analyzer('resolved', true)
+  #     func3 = jasmine.createSpy('func3')
+  #     unresolve = jasmine.createSpy 'unresolve'
+
+  #     beforeEach ->
+  #       Analyzer('resolved', undefined)
+  #       subject   = Analyzer('callInChain')
+  #       Analyzer('unresolve', unresolve)
+
+  #     it 'should call given methods in chain', ->
+  #       subject func1, func2
+  #       expect(func1).toHaveBeenCalledWith()
+  #       expect(func2).toHaveBeenCalledWith()
+
+  #     it 'should return if resolved', ->
+  #       subject func1, func2, func3
+  #       expect(func1).toHaveBeenCalledWith()
+  #       expect(func2).toHaveBeenCalledWith()
+  #       expect(func3).not.toHaveBeenCalled()
+
+  #     it 'should unresolve on start', ->
+  #       subject()
+  #       expect(unresolve).toHaveBeenCalledWith()
+
+  #   describe 'stringTracker', ->
+  #     cases = [
+  #       { escaped: undefined
+  #       chars: [
+  #         { value: '"'
+  #         inString: [
+  #           { before: undefined, after: '"'      , resolved: true }
+  #           { before: '"',       after: undefined, resolved: true }
+  #           { before: "'",       after: "'"      , resolved: true }
+  #         ] }
+  #         { value: "'"
+  #         inString: [
+  #           { before: undefined, after: "'"      , resolved: true }
+  #           { before: "'",       after: undefined, resolved: true }
+  #           { before: '"',       after: '"'      , resolved: true }
+  #         ] }
+  #         { value: "a"
+  #         inString: [
+  #           { before: undefined, after: undefined, resolved: undefined }
+  #           { before: "'",       after: "'"      , resolved: true }
+  #           { before: '"',       after: '"'      , resolved: true }
+  #         ] }
+  #       ] }
+  #       { escaped: true
+  #       chars: [
+  #         { value: '"'
+  #         inString: [
+  #           { before: undefined, after: undefined, resolved: true }
+  #           { before: '"',       after: '"'      , resolved: true }
+  #           { before: "'",       after: "'"      , resolved: true }
+  #         ] }
+  #         { value: "'"
+  #         inString: [
+  #           { before: undefined, after: undefined, resolved: true }
+  #           { before: "'",       after: "'"      , resolved: true }
+  #           { before: '"',       after: '"'      , resolved: true }
+  #         ] }
+  #         { value: "a"
+  #         inString: [
+  #           { before: undefined, after: undefined, resolved: undefined }
+  #           { before: "'",       after: "'"      , resolved: true }
+  #           { before: '"',       after: '"'      , resolved: true }
+  #         ] }
+  #       ] }
+  #     ]
+
+  #     for exam in cases
+  #       do (exam = exam)->
+  #         describe "when escaped = #{JSON.stringify(exam.escaped)}", ->
+  #           beforeEach -> Analyzer('escaped', exam.escaped)
+
+  #           for char in exam.chars
+  #             do (char = char)->
+  #               describe "and currentChar = #{JSON.stringify(char.value)}", ->
+  #                 beforeEach ->
+  #                   Analyzer('crntChar', char.value)
+  #                   Analyzer('charFilter')()
+
+  #                 for subject in char.inString
+  #                   do (subject = subject)->
+  #                     describe "and inString = #{JSON.stringify(subject.before)}", ->
+  #                       beforeEach ->
+  #                         Analyzer('inString', subject.before)
+  #                         Analyzer('resolved', undefined)
+
+  #                       it "inString should became #{JSON.stringify(subject.after)}", ->
+  #                         Analyzer('stringTracker')()
+  #                         expect(Analyzer('inString')()).toBe subject.after
+
+  #                       it "resolved should be #{JSON.stringify(subject.resolved)}", ->
+  #                         Analyzer('stringTracker')()
+  #                         expect(Analyzer('resolved')()).toBe subject.resolved
+
+  #   describe 'parenthesesTracker', ->
+  #     cases = [
+  #       { crntChar: '('
+  #       escaped: undefined
+  #       cases: [
+  #         { before: [], after: ['('] }
+  #         { before: ['('], after: ['(', '('] }
+  #         { before: ['(', '('], after: ['(', '(', '('] }
+  #       ] }
+  #       { crntChar: ')'
+  #       escaped: undefined
+  #       cases: [
+  #         { before: [], after: [] }
+  #         { before: ['('], after: [] }
+  #         { before: ['(', '('], after: ['('] }
+  #       ] }
+  #       { crntChar: 'a'
+  #       escaped: undefined
+  #       cases: [
+  #         { before: [], after: [] }
+  #         { before: ['('], after: ['('] }
+  #         { before: ['(', '('], after: ['(', '('] }
+  #       ] }
+  #       { crntChar: '('
+  #       escaped: true
+  #       cases: [
+  #         { before: [], after: [] }
+  #         { before: ['('], after: ['('] }
+  #         { before: ['(', '('], after: ['(', '('] }
+  #       ] }
+  #       { crntChar: ')'
+  #       escaped: true
+  #       cases: [
+  #         { before: [], after: [] }
+  #         { before: ['('], after: ['('] }
+  #         { before: ['(', '('], after: ['(', '('] }
+  #       ] }
+  #       { crntChar: 'a'
+  #       escaped: true
+  #       cases: [
+  #         { before: [], after: [] }
+  #         { before: ['('], after: ['('] }
+  #         { before: ['(', '('], after: ['(', '('] }
+  #       ] }
+  #     ]
+
+  #     for exam in cases
+  #       do (exam = exam)->
+  #         describe "when currentChar = #{JSON.stringify(exam.crntChar)}", ->
+  #           beforeEach ->
+  #             Analyzer('resolved', undefined)
+  #             Analyzer('crntChar', exam.crntChar)
+  #             Analyzer('escaped', exam.escaped)
+  #             Analyzer('charFilter')()
+
+  #           for ex in exam.cases
+  #             do (ex = ex)->
+  #               it "should change parentheses from #{JSON.stringify(ex.before)} to #{JSON.stringify(ex.after)}", ->
+  #                 Analyzer('parentheses', ex.before)
+  #                 Analyzer('parenthesesTracker')()
+  #                 expect(Analyzer('parentheses')()).toBeEqual ex.after
+
+  #   describe 'dslTracker', ->
+  #     cases = [
+  #       { dump: '.is('
+  #       crntChar: '('
+  #       cases: [
+  #         { escaped: undefined
+  #         inString: undefined
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: 1 }
+  #           { parentheses: []
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: 2 }
+  #         ] }
+  #         { escaped: true
+  #         inString: undefined
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #         ] }
+  #         { escaped: undefined
+  #         inString: true
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #         ] }
+  #       ] }
+  #       { dump: 'is(('
+  #       crntChar: '('
+  #       cases: [
+  #         { escaped: undefined
+  #         inString: undefined
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: []
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #         ] }
+  #         { escaped: true
+  #         inString: undefined
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #         ] }
+  #         { escaped: undefined
+  #         inString: true
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #         ] }
+  #       ] }
+  #       { dump: ''
+  #       crntChar: ')'
+  #       cases: [
+  #         { escaped: undefined
+  #         inString: undefined
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: []
+  #           inDslParams:
+  #             before: 1
+  #             after: undefined }
+  #           { parentheses: []
+  #           inDslParams:
+  #             before: 2
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 1
+  #             after: undefined }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: 2
+  #             after: undefined }
+  #         ] }
+  #         { escaped: true
+  #         inString: undefined
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #         ] }
+  #         { escaped: undefined
+  #         inString: true
+  #         cases: [
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #           { parentheses: ['(']
+  #           inDslParams:
+  #             before: 2
+  #             after: 2 }
+  #           { parentheses: ['(', '(']
+  #           inDslParams:
+  #             before: undefined
+  #             after: undefined }
+  #         ] }
+  #       ] }
+  #     ]
+
+  #     for exam in cases
+  #       do (exam = exam)->
+  #         describe "when dump = #{JSON.stringify(exam.dump)}
+  #                   and crntChar = #{JSON.stringify(exam.crntChar)}", ->
+  #           beforeEach ->
+  #             Analyzer('dumped', exam.dump)
+  #             Analyzer('crntChar', exam.crntChar)
+  #             Analyzer('charFilter')()
+
+  #           for ex in exam.cases
+  #             do (ex = ex)->
+  #               for e in ex.cases
+  #                 do (e = e)->
+  #                   describe "and escaped = #{JSON.stringify(ex.escaped)}
+  #                             and inString = #{JSON.stringify(ex.inString)}
+  #                             and parentheses =  #{JSON.stringify(e.parentheses)}", ->
+  #                     beforeEach ->
+  #                       Analyzer('escaped', ex.escaped)
+  #                       Analyzer('inString', ex.inString)
+  #                       Analyzer('parentheses', e.parentheses)
+  #                       Analyzer('inDslParams', e.inDslParams.before)
+  #                       Analyzer('dslTracker')()
+
+  #                     it "inDslParams should became #{e.inDslParams.after}", ->
+  #                       expect(Analyzer('inDslParams')()).toBe e.inDslParams.after
+
+  #   describe 'main function', ->
+  #     dumpSpy            =
+  #     crntChar           =
+  #     charFilter         =
+  #     dslTracker         =
+  #     callInChain        =
+  #     escapeTracker      =
+  #     stringTracker      =
+  #     callInChainSpy     =
+  #     parenthesesTracker = undefined
+
+  #     beforeEach ->
+  #       crntChar           = Analyzer('crntChar')
+  #       charFilter         = Analyzer('charFilter')
+  #       dslTracker         = Analyzer('dslTracker')
+  #       callInChain        = Analyzer('callInChain')
+  #       escapeTracker      = Analyzer('escapeTracker')
+  #       stringTracker      = Analyzer('stringTracker')
+  #       parenthesesTracker = Analyzer('parenthesesTracker')
+
+  #       dumpSpy        = jasmine.createSpy('dump')
+  #       callInChainSpy = jasmine.createSpy('callInChain')
+  #       Analyzer('crntChar',    undefined)
+  #       Analyzer('dump',        dumpSpy)
+  #       Analyzer('callInChain', callInChainSpy)
+  #       dumpSpy.calls.reset()
+  #       callInChainSpy.calls.reset()
+
+  #     afterEach -> Analyzer('callInChain', callInChain)
+
+  #     it 'should dump currentChar', ->
+  #       subject('a')
+  #       expect(dumpSpy).toHaveBeenCalledWith 'a'
+
+  #     it 'should call filters in chain', ->
+  #       subject('a')
+  #       expect(callInChainSpy).toHaveBeenCalledWith(
+  #         escapeTracker
+  #         charFilter
+  #         stringTracker
+  #         parenthesesTracker
+  #         dslTracker
+  #       )
+
+


better handle requests

better handle requests

--- test/pagerv2_commands_test.coffee
+++ test/pagerv2_commands_test.coffee
@@ -325,7 +325,7 @@
             .to.eql 'PT4KHLK (resolved) The server is on fire.'

     # ----------------------------------------------------------------------------------------------
-    describe '".pd sup"', ->
+    describe.only '".pd sup"', ->
       context 'when everything goes right,', ->
         beforeEach ->
           nock('https://api.pagerduty.com')


fixing indent bug in order form handler

fixing indent bug in order form handler

--- app/assets/javascripts/mobile/_mobile.js.coffee
+++ app/assets/javascripts/mobile/_mobile.js.coffee
@@ -154,23 +154,24 @@
             e.preventDefault() if ($ @).find('.unhappy').length)

 if gon.page is 'orders_new' or gon.page is 'orders_edit' or gon.page is 'orders_create'
-    $credit_card_number = $('#credit_card_number')
-    $credit_card_expiration_month = $('#credit_card_expiration_month')
-    $credit_card_expiration_year = $('#credit_card_expiration_year')
-
-    stripeResponseHandler = (status, response) ->
-        if response.error
-            alert response.error.message
-            ($ '#order_form_submit').attr('disabled', false)
-        else
-            $credit_card_number.val('')
-            $credit_card_expiration_month.val('')
-            $credit_card_expiration_year.val('')
-            token = response['id']
-            $(".order-form")
-                .append("<input type='hidden' name='stripeToken' value='#{token}'/>")
-                .get(0)
-                    .submit()
+    $ ->
+        $credit_card_number = $('#credit_card_number')
+        $credit_card_expiration_month = $('#credit_card_expiration_month')
+        $credit_card_expiration_year = $('#credit_card_expiration_year')
+
+        stripeResponseHandler = (status, response) ->
+            if response.error
+                alert response.error.message
+                ($ '#order_form_submit').attr('disabled', false)
+            else
+                $credit_card_number.val('')
+                $credit_card_expiration_month.val('')
+                $credit_card_expiration_year.val('')
+                token = response['id']
+                $(".order-form")
+                    .append("<input type='hidden' name='stripeToken' value='#{token}'/>")
+                    .get(0)
+                        .submit()

         ($ "#order_form")
             .isHappy(order_form_validation_rules)


Move logic for creating the random value generator(s) out of the class

Instead, move them into private methods. All instance methods should
be user-facing.

--- src/stochator.coffee
+++ src/stochator.coffee
@@ -4,8 +4,6 @@
 isFunc = isType("Function")

 isObject = isType("Object")
-
-callFunctions = (fns) -> (fn() for fn in fns)

 randomBoundedFloat = (min = 0, max = 1) ->
     spread = max - min
@@ -133,6 +131,33 @@
             -> randomSetMember(set)
     else
         -> randomSetMemberWithoutReplacement(set)
+
+createGenerator = (config) ->
+    config.kind ?= "float"
+    generator = switch config.kind
+        when "float"
+            { min, max, mean, stdev } = config
+            floatGenerator(min, max, mean, stdev)
+        when "integer"
+            integerGenerator(config.min, config.max)
+        when "set"
+            { values, replacement, shuffle, weights } = config
+            setGenerator(values, replacement, shuffle, weights)
+        when "color", "rgb" then randomColor(config.kind)
+        when "a-z", "A-Z" then randomCharacter(config.kind is "a-z")
+    if not generator
+        throw Error("#{ config.kind } not a recognized kind.")
+    else
+        generator
+
+getNextValueGenerator = (configs) ->
+    configs[0] ?= {}
+    generators = (createGenerator(config) for config in configs)
+    if generators.length is 1
+        -> generators[0]()
+    else
+        -> (generator() for generator in generators)
+

 class Stochator


Test spec handles mock API requests, very general regex used (/.*/).

--- test/spec/controllers/main.coffee
+++ test/spec/controllers/main.coffee
@@ -9,7 +9,9 @@
   scope = {}

   # Initialize the controller and a mock scope
-  beforeEach inject ($controller, $rootScope) ->
+  beforeEach inject ($injector, $controller, $rootScope) ->
+    $httpBackend = $injector.get('$httpBackend')
+    $httpBackend.whenGET(/.*/).respond({fake: 'data'})
     scope = $rootScope.$new()
     MainCtrl = $controller 'MainCtrl', {
       $scope: scope
@@ -17,3 +19,4 @@

   it 'should attach a list of awesomeThings to the scope', () ->
     expect(scope.awesomeThings.length).toBe 3;
+


fixed test for checking {}

fixed test for checking {}

the jasmine test for checking if we have an empty object .toBe({}) doesn't work correctly. the jasmine way of doing this is .toEqual({})

Signed-off-by: Dominik Richter <b7323add517e187efe0283b76511b7ed762bfe13@gmail.com>

--- test/spec/controllers/main.coffee
+++ test/spec/controllers/main.coffee
@@ -312,13 +312,13 @@
     paginateResponse @httpBackend, '/v1/repositories', allRepos1, () -> scope.fetchRepos()
     expect(scope.repos.length).toBe(allRepos1.length)
     # for now...
-    expect(scope.repoSelected).toBe({})
+    expect(scope.repoSelected).toEqual({})
     expect(scope.repoSelectedLabel).toBe(null)

     opts = {'query': [['repolabel',allRepos1[0].label],['outdated','true']]}
     select_by_label = () -> scope.selectRepoLabel(allRepos1[0].label)
     paginateResponse @httpBackend, '/v1/packages', allPackages1, select_by_label, opts
-    expect(scope.repoSelected).toBe({})
+    expect(scope.repoSelected).toEqual({})
     expect(scope.repoSelectedLabel).toBe(allRepos1[0].label)

     opts = {'query': [['repo',allRepos1[0].id],['outdated','true']]}
@@ -330,7 +330,7 @@
     opts = {'query': [['repolabel',allRepos1[0].label],['outdated','true']]}
     select_by_label = () -> scope.selectRepoLabel(allRepos1[0].label)
     paginateResponse @httpBackend, '/v1/packages', allPackages1, select_by_label, opts
-    expect(scope.repoSelected).toBe({})
+    expect(scope.repoSelected).toEqual({})
     expect(scope.repoSelectedLabel).toBe(allRepos1[0].label)

   it 'provides all repository labels (uniq)', () ->


Open tree when there's an anchor

Open tree when there's an anchor

--- app/assets/javascripts/tree_navigator.js.coffee
+++ app/assets/javascripts/tree_navigator.js.coffee
@@ -30,3 +30,9 @@
           elem.removeClass('closed').addClass('open')
           elem.siblings('ul').show()

+    if anchor = $(location).attr('hash')
+      if link = elem.find('a[href="'+anchor+'"]')
+        link.parents('ul').each ->
+          $(this).show()
+          $(this).siblings('span').removeClass('closed').addClass('open')
+


Add test case for updating existing document using POST

--- test/collection-spec.coffee
+++ test/collection-spec.coffee
@@ -202,6 +202,13 @@
       assert.equal res.body.documents[0], doc._id
       done()

+  it 'should update existing document', (done) ->
+    doc = {_id: data[50]._id, navn: 'foo'}
+    req.post('/test?api_key=dnt').send(doc).expect(201).end (err, res) ->
+      throw err if err
+      assert.equal res.body.documents[0], doc._id
+      done()
+
   it 'should return error for missing request body', (done) ->
     req.post('/test?api_key=dnt')
       .expect(400, done)


Ensure children are destroyed on Controller#destroy

--- test/controller_spec.coffee
+++ test/controller_spec.coffee
@@ -324,4 +324,8 @@

   describe "destroy", ->
     it "destroys children", ->
-
+      controller = new Controller
+      sinon.spy(controller, 'destroyChildren')
+      controller.destroy()
+      expect( controller.destroyChildren.called ).to.be.true
+


Edit jackal text

Edit jackal text

Removed parentheses from scientific name.

--- app/lib/field-guide-content/jackal.coffee
+++ app/lib/field-guide-content/jackal.coffee
@@ -4,7 +4,7 @@
     The side-striped jackal is easily distinguishable from its other jackal relatives. It has a slightly drabber light gray to tan coloration with a white tip on their otherwise black tail. The side-striped jackal is medium-sized and tends to have a white stripe that extends from the elbow to hip and black side stripes which are not always conspicuous. They have a relatively blunt muzzle and short, rounded ears. This species is sexually dimorphic in size, with males being larger than females.
   '''

-  scientificName: '(Canis adustus)'
+  scientificName: 'Canis adustus'
   mainImage: 'assets/fieldguide-content/mammals/jackal/jackal-feature.jpg'

   conservationStatus: 'Least Concern' # Options are Least Concern, Near Threatened, Vulnerable, and Endangered; all have their own little icons as well.


Constants now tested

Constants now tested

--- src/test/core.coffee
+++ src/test/core.coffee
@@ -1,7 +1,34 @@
 (->
 	describe 'Trocha Js Routes List engine', ->
+		describe 'Constants', ->
+			it 'should return HTTP request methods types', ->
+				assert trocha.OPTIONS, "OPTIONS"
+				assert trocha.GET, "GET"
+				assert trocha.HEAD, "HEAD"
+				assert trocha.POST, "POST"
+				assert trocha.PUT, "PUT"
+				assert trocha.PATCH, "PATCH"
+				assert trocha.DELETE, "DELETE"
+				assert trocha.TRACE, "TRACE"
+				assert trocha.CONNECT, "CONNECT"
+			it 'should return default resource tree', ->
+				assert trocha.$RESOURCE, {
+					$id: 'id'
+					show:
+						$hide: true
+					edit: {}
+					new:
+						$id: false
+					list:
+						$hide: true
+						$id: false
+				}
+			#it 'should return routes creation methods', ->
+				#assert trocha.$ROUTE, "ROUTE"
+				#assert trocha.$SCOPE, "SCOPE"
 		describe 'Constructor', ->
 			it 'should create a valid trocha object', ->
+				assert trocha, ->
 				r = trocha()
-				console.log r
+				assert r, {}
 )()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -32,6 +32,6 @@
     x: 9
     y: 10

-  equ
+  equals engin

 module()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -21,7 +21,7 @@
   obj4 = engine.add
     class: "Awesome"
     x: 9
-    y:
+    y: 80

   indexSum = 0


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/engine_selector.coffee
+++ test/engine_selector.coffee
@@ -27,4 +27,5 @@

   equals engine.first('.type=testObj'), obj1, "should find obj1"

+
 module()


removed some printing

removed some printing

--- test/integrationTest.coffee
+++ test/integrationTest.coffee
@@ -232,7 +232,6 @@
 						.expect(201)
 						.end (err, res) ->
 							transactionId = JSON.parse(res.text)._id
-							console.log "transactionToBeRemove="+transactionId
 							if err
 								done err
 							else
@@ -274,7 +273,6 @@
 		describe ".getTransactionById (transactionId)", ->

 			it "should call getTransactionById", (done) ->
-				console.log "transactionID=#{transactionId}"
 				server.start null, null, 8080,  ->
 					request("http://localhost:8080")
 						.get("/transactions/#{transactionId}")
@@ -361,7 +359,6 @@
 						.get("/applications/domain/#{domain}")
 						.expect(200)
 						.end (err, res) ->
-							console.log "err="+err
 							if err
 								done err
 							else


fixed tests

fixed tests

--- test/jstemplate-test.coffee
+++ test/jstemplate-test.coffee
@@ -41,7 +41,7 @@

     'it should generate a valid file': (topic) ->
       content = fs.readFileSync(fusion.settings.output, "utf8")
-      assert.equal content, "(function(){ab})();"
+      assert.equal content, "(function(){ab}).call(this);"
     teardown: ->
       cleanUpFusion()
 }).export module
@@ -54,7 +54,7 @@

     'it should generate a valid js file': (topic) ->
       content = fs.readFileSync(fusion.settings.output, "utf8")
-      assert.equal content, "(function(){window.templates = {};window.templates.a = '
a
\\n';window.templates.b = {};window.templates.c = '
c
\\n';window.templates.b.b = {};window.templates.b.b.b = '
b
\\n';})();"
+      assert.equal content, "(function(){window.templates = {};window.templates.a = '
a
\\n';window.templates.b = {};window.templates.c = '
c
\\n';window.templates.b.b = {};window.templates.b.b.b = '
b
\\n';}).call(this);"
     teardown: ->
       cleanUpFusion()
 }).export module


Fix race condition with required items not always being required properly

--- app/views/play/menu/InventoryModal.coffee
+++ app/views/play/menu/InventoryModal.coffee
@@ -184,7 +184,7 @@
     @canvasWidth = @$el.find('canvas').innerWidth()
     @canvasHeight = @$el.find('canvas').innerHeight()
     @inserted = true
-    @requireLevelEquipment()
+    @requireLevelEquipment() if @items.loaded

   #- Draggable logic


put done into options, adapt for corepath isAbsolute style

--- test/lib/test-fspath.coffee
+++ test/lib/test-fspath.coffee
@@ -4,6 +4,14 @@
 strung   = require 'strung'
 slash    = corepath.sep
 buildPath= require '../../lib'
+
+dirName = process.cwd().split(slash).pop()
+backToHere = '../' + dirName
+backToPackage = '../' + dirName + '/package.json'
+
+isWindows = process.platform is 'win32'
+windows = (value) -> if isWindows then value else not value
+

 # lean path ops:
 #  1. avoid as much work as possible
@@ -110,17 +118,17 @@

   # path.isReal
   describe 'isReal', ->
-    for string,result of {
-      '.':true
-      './':true
-      './lib':true
-      './lib/index.coffee':true
-      '../node-fspath':true
-      '../node-fspath/package.json':true
-      './fake':false
-      './fake.file':false
-    }
-      do (string,result) ->
+    for pair in [
+      ['.', true]
+      ['./', true]
+      ['./lib', true]
+      ['./lib/index.coffee', true]
+      [backToHere, true]
+      [backToPackage, true]
+      ['./fake', false]
+      ['./fake.file', false]
+    ]
+      do (string = pair[0], result = pair[1]) ->
         it 'with [' + string + '] should return [' + result + ']', (done) ->
           path = buildPath string
           assert.equal path.isReal(), result
@@ -131,17 +139,17 @@

   # path.isFile
   describe 'isFile', ->
-    for string,result of {
-      '.':false
-      './':false
-      './lib':false
-      './lib/index.coffee':true
-      '../node-fspath':false
-      '../node-fspath/package.json':true
-      './fake':false
-      './fake.file':false
-    }
-      do (string,result) ->
+    for pair in [
+      ['.', false]
+      ['./', false]
+      ['./lib', false]
+      ['./lib/index.coffee', true]
+      [backToHere, false]
+      [backToPackage, true]
+      ['./fake', false]
+      ['./fake.file', false]
+    ]
+      do (string = pair[0], result = pair[1]) ->
         it 'with [' + string + '] should return [' + result + ']', (done) ->
           path = buildPath string
           assert.equal path.isFile(), result
@@ -153,17 +161,17 @@

   # path.isDir
   describe 'isDir', ->
-    for string,result of {
-      '.':true
-      './':true
-      './lib':true
-      './lib/index.coffee':false
-      '../node-fspath':true
-      '../node-fspath/package.json':false
-      './fake':false
-      './fake.file':false
-    }
-      do (string,result) ->
+    for pair in [
+      ['.', true]
+      ['./', true]
+      ['./lib', true]
+      ['./lib/index.coffee', false]
+      [backToHere, true]
+      [backToPackage, false]
+      ['./fake', false]
+      ['./fake.file', false]
+    ]
+      do (string = pair[0], result = pair[1]) ->
         it 'with [' + string + '] should return [' + result + ']', (done) ->
           path = buildPath string
           assert.equal path.isDir(), result
@@ -200,14 +208,15 @@
       '/path/more/':false
       '/./path':false
       '/./path/':false
-      '\\':false
-      'C:':false
-      'C:\\':false
-      'C:\\some\\path':false
+      '\\': windows false
+      'C:': windows false
+      'C:\\': windows false
+      'C:\\some\\path': windows false
     }
       do (path,result) ->
         it 'with |' + path + '| should return |' + result + '|', ->
           assert.equal buildPath(path).isRelative, result
+

   # path.isAbsolute
   describe 'isAbsolute', ->
@@ -236,14 +245,15 @@
       '/path/more/':true
       '/./path':true
       '/./path/':true
-      '\\':true
-      'C:':true
-      'C:\\':true
-      'C:\\some\\path':true
+      '\\': windows true
+      'C:': windows true
+      'C:\\': windows true
+      'C:\\some\\path': windows true
     }
       do (path,result) ->
         it 'with [' + path + '] should return [' + result + ']', ->
           assert.equal buildPath(path).isAbsolute, result
+

   # path.isCanonical
   describe 'isCanonical', ->
@@ -276,6 +286,7 @@
       do (path,result) ->
         it 'with [' + path + '] should return [' + result + ']', ->
           assert.equal buildPath(path).isCanonical(), result
+

   # path.normalize
   describe 'normalize', ->
@@ -462,6 +473,7 @@
           # test a second time because value is cached
           assert.equal buildPath(path).basename(), expected, 'cached value should be the same'

+
   # path.extname # -> alias of path.ext ?
   describe 'extname', ->
     for path in pathArray
@@ -484,6 +496,7 @@
           assert.equal actual, expected
           # test a second time because value is cached
           assert.equal actual, expected, 'cached value should be the same'
+

   # path.up(#)
   describe 'up', ->
@@ -545,6 +558,7 @@
           expected = corepath.join path, joins...
           assert.equal buildPath(path).up(count).path, expected

+
   # path.to
   describe 'to', ->
     for path,to of {
@@ -577,6 +591,7 @@
         it 'with [' + path + '] to ' + to, ->
           assert.equal buildPath(path).to(to), corepath.join path, to

+
   # path.subpath
   describe 'subpath', ->
     for path,test of {
@@ -776,9 +791,10 @@
       assert.equal target.string, 'file.txt\nsome test file\n'
       done()
     path = buildPath 'test/helpers/file.txt'
-    path.reader (error, reader) ->
+    path.reader done: (error, reader) ->
       if error? then return done error
       reader.pipe target
+

   describe 'sync reader', -> it 'should read file \'file.txt\'', (done) ->
     target = strung()
@@ -821,7 +837,7 @@

   describe 'async read', -> it 'should read file \'file.txt\'', (done) ->
     path = buildPath 'test/helpers/file.txt'
-    path.read {}, (error, text) ->
+    path.read done: (error, text) ->
       if error? then return done error
       assert.equal text, 'file.txt\nsome test file\n'
       done()
@@ -838,16 +854,24 @@
     assert.equal text, testContent

   describe 'async write', -> it 'should write file \'path.async.write.txt\'', (done) ->
+
     testFile = 'test/output/path.async.write.txt'
     testContent = 'output by path.write test'
     path = buildPath testFile
-    path.write testContent, {}, (error) ->
+    path.write testContent, done: (error) ->
+
       if error? then return done error
+
       fs.readFile testFile, encoding:'utf8', (error, text) ->
+
         if error? then return done error
+
         fs.unlink testFile, (error) ->
+
           if error? then return done error
+
           assert.equal text, testContent
+
           done()

@@ -869,7 +893,7 @@
     testPreexisting = 'async append\n'
     testResult  = testPreexisting + testContent
     path = buildPath testFile
-    path.append testContent, {}, (error) ->
+    path.append testContent, done: (error) ->
       if error? then return done error
       fs.readFile testFile, encoding:'utf8', (error, text) ->
         if error? then return done error
@@ -895,42 +919,22 @@

     describe 'async', ->

-      describe 'with only done callback', ->
+      describe 'with only `done` option', ->

         it 'should list all the project root paths', (done) ->
           path = buildPath()
-          path.list (error, result) ->
+          path.list done: (error, result) ->
             if error? then return done error
             for path in result.paths
               assert (path.path in rootPaths), 'results shouldnt have |' + path.path + '|'
             done()

-      describe 'with only `done` option', ->
-
-        it 'should list all the project root paths', (done) ->
-          path = buildPath()
-          path.list done:(error, result) ->
-            if error? then return done error
-            for path in result.paths
-              assert (path.path in rootPaths), 'results shouldnt have |' + path.path + '|'
-            done()
-
-      describe 'with only `all` option', ->
-
-        it 'should list all the project root paths', (done) ->
-          path = buildPath()
-          path.list all:(error, result) ->
-            if error? then return done error
-            for path in result.paths
-              assert (path.path in rootPaths), 'results shouldnt have |' + path.path + '|'
-            done()
-
       describe 'with `each` and `done` option', ->

         it 'should list all the project root paths', (done) ->
           path = buildPath()
           path.list
-            each:(result) ->
+            each: (result) ->
               assert (result.path.path in rootPaths), 'each shouldnt receive : |' + result.path.path + '|'
             done: (error, result) ->
               if error? then return done error
@@ -945,7 +949,7 @@
           path = buildPath()
           path.list
             acceptString: -> true
-            done:(error, result) ->
+            done: (error, result) ->
               if error? then return done error
               for path in result.paths
                 assert (path.path in rootPaths), 'results shouldnt have |' + path.path + '|'
@@ -957,7 +961,7 @@
           path = buildPath()
           path.list
             acceptString: (path) -> path is 'lib'
-            done:(error, result) ->
+            done: (error, result) ->
               if error? then return done error
               assert.equal result?.paths?.length, 1,
                 'result should only contain \'lib\' path'
@@ -1004,7 +1008,7 @@
   describe 'async files', ->
     it 'should list all files in project root', (done) ->
       path = buildPath()
-      path.files (error, result) ->
+      path.files done: (error, result) ->
         if error? then return done error
         for path in result.paths
           assert (path.path in rootFiles), 'results shouldnt have |' + path.path + '|'
@@ -1022,7 +1026,7 @@
   describe 'async dirs', ->
     it 'should list all dirs in project root', (done) ->
       path = buildPath()
-      path.dirs (error, result) ->
+      path.dirs done: (error, result) ->
         if error? then return done error
         for path in result.paths
           assert (path.path in rootDirs), 'results shouldnt have |' + path.path + '|'


Make I18n instance frozen

Make I18n instance frozen

--- src/util/i18n.coffee
+++ src/util/i18n.coffee
@@ -22,7 +22,16 @@
   @method constructor
     Constructor of multi-language text
   ###
-  constructor: (@_obj) ->
+  constructor: (obj) ->
+    @_text = obj
+    return if typeof(@_text) == "string"
+    @_text = obj[lang]
+    return if typeof(@_text) == "string"
+    @_text = obj["en"]
+    return if typeof(@_text) == "string"
+    @_text = "<translate error>"
+    console.warn("No translated text for object (#{obj})")
+    Object.freeze(this)
     return

   ###*
@@ -32,16 +41,6 @@
     Translated text
   ###
   toString: ->
-    return @_text if @_text?
-    do =>
-      @_text = @_obj
-      return if typeof(@_text) == "string"
-      @_text = @_obj[lang]
-      return if typeof(@_text) == "string"
-      @_text = @_obj["en"]
-      return if typeof(@_text) == "string"
-      @_text = "<translate error>"
-      console.warn("No translated text for object (#{@_obj})")
     return @_text

   ###*


add test for issue #4

add test for issue #4

--- test/macro-tool_test.coffee
+++ test/macro-tool_test.coffee
@@ -280,6 +280,19 @@
           mask: "url(##{maskId})"
           _: [ { circle: { r: 5 } }, { circle:{ r: 4.5 } } ]
         }
+      it 'should add several clear shapes in a row to the same mask', ->
+        # add a rectangle
+        m = new Macro ['AMNAME']
+        m.primitive [ 21, 1, 10, 5, 0, 0, 0 ]
+        # clear out two smaller circles
+        m.primitive [ 1, 0, 3, 3, 0 ]
+        m.primitive [ 1, 0, 2, -3, 0 ]
+        m.shapes.length.should.equal 1
+        m.masks.length.should.equal 1
+        m.masks[0]._.length.should.equal 3
+        m.masks[0]._.should.containDeep [
+          { rect: { width: 10 } }, { circle: { r: 1.5 } }, { circle: { r: 1} }
+        ]

   describe 'getNumber method', ->
     m = new Macro ['MACRONAME']


Rename audio/video configuration keys

Rename audio/video configuration keys

--- src/packages/collaboration/lib/media-connection.coffee
+++ src/packages/collaboration/lib/media-connection.coffee
@@ -21,8 +21,8 @@

   createOutboundStreamPromise: ->
     deferred = $.Deferred()
-    video = config.get('collaboration.enableVideo') ? mandatory: { maxWidth: 320, maxHeight: 240 }, optional: []
-    audio = config.get('collaboration.enableAudio') ? true
+    video = config.get('collaboration.video') ? mandatory: { maxWidth: 320, maxHeight: 240 }, optional: []
+    audio = config.get('collaboration.audio') ? true
     success = (stream) =>
       @getPeerConnection().addStream(stream)
       deferred.resolve(stream)


close #11 #10

close #11 #10

--- assets/javascripts/ember-couchdb-adapter.coffee
+++ assets/javascripts/ember-couchdb-adapter.coffee
@@ -20,7 +20,13 @@
     hash._id || hash.id

   stringForType: (type) ->
-    type.toString()
+    type = type.toString()
+    if type.search(".") < 0
+      type
+    else
+      pattern = /((?:.*))\.(\w+)/ig
+      reg_array = pattern.exec(type)
+      reg_array[reg_array.length - 1].toString().toLowerCase()

   getRecordRevision: (record) ->
     record.get('_data.attributes._rev')
@@ -39,15 +45,18 @@
       json[typeAttribute] = this.stringForType(record.constructor)

   addHasMany: (data, record, key, relationship) ->
+    @_addHasMany(data, record, key, relationship)
+
+  _addHasMany: (data, record, key, relationship) ->
     value = record.get(key)
-    attr_key = record.get("users_key") || "id"
+    attr_key = record.get("#{relationship.key}_key") || "id"
     if this.get('addEmptyHasMany') || !Ember.isEmpty(value)
       data[key] = value.getEach(attr_key)

   addBelongsTo: (hash, record, key, relationship) ->
-    id = get(record, relationship.key + '.id')
+    id_key = record.get("#{relationship.key}_key") || "id"
+    id = Ember.get(record, "#{relationship.key}.#{id_key}")
     hash[key] = id if this.get('addEmptyBelongsTo') || !Ember.isEmpty(id)
-

 DS.CouchDBAdapter = DS.Adapter.extend
   typeAttribute: 'ember_type'
@@ -56,6 +65,7 @@
   serializer: DS.CouchDBSerializer

   _ajax: (url, type, hash) ->
+    if url.split("/").pop() == "" then url = url.substr(0, url.length - 1)
     hash.url = url
     hash.type = type
     hash.dataType = 'json'
@@ -88,7 +98,7 @@
       include_docs: true
       keys: ids

-    this.ajax('_all_docs', 'POST', {
+    this.ajax('_all_docs?include_docs=true', 'POST', {
       data: data
       context: this
       success: (data) ->


Move export to top for consistency

Move export to top for consistency

--- src/validator.coffee
+++ src/validator.coffee
@@ -4,6 +4,10 @@
 manifest = require './manifest'
 _ = require 'underscore'
 semver = require 'semver'
+
+module.exports =
+  checkProject: (dir, options, callback) ->
+    assertValidVersion dir, options, callback

 versionExists = (manifestInfo, gadgets) ->
   return _.any gadgets, (gadget) ->
@@ -41,7 +45,3 @@

       else
         return callback()
-
-module.exports =
-  checkProject: (dir, options, callback) ->
-    assertValidVersion dir, options, callback


Clean up debug message

Clean up debug message

--- test/test-queue-pass.coffee
+++ test/test-queue-pass.coffee
@@ -94,5 +94,4 @@
           done null

       it 'I should not be able to listen', ->
-        console.error 'err is', error
         assert.ok error instanceof Error


Re-render form after save

Re-render form after save

--- graphedit/coffee/graphedit.coffee
+++ graphedit/coffee/graphedit.coffee
@@ -479,7 +479,8 @@

     $.extend d3.select(target).data()[0].properties, data

-    @restart
+    @restart()
+    @displayData()

 # GRAPHEDIT PLUGIN DEFINITION