Highlight macro names more consistently

Highlight macro names more consistently

--- grammars/roff.cson
+++ grammars/roff.cson
@@ -520,15 +520,13 @@

 			# No terminator specified
 			name: "meta.macro.definition.$2.roff"
-			begin: "(?:^|\\G)([.'])[ \\t]*((dei?1?)|(ami?1?))\\s+(\\S+?)?\\s*(\\\\E?[\"#].*)?$"
+			begin: "(?:^|\\G)([.'])[ \\t]*((?:de|am)i?1?)\\s+(\\S+?)?\\s*(\\\\E?[\"#].*)?$"
 			end:   "^(?:[ \\t]*\\x5C{2})?\\.[ \\t]*\\."
 			beginCaptures:
 				1: name: "punctuation.definition.request.roff"
-				3: name: "storage.type.function.roff"
-				4: name: "entity.name.function.roff"
-				5: name: "variable.parameter.roff", patterns: [include: "#escapes"]
-				6: patterns: [include: "#escapes"]
-				7: patterns: [include: "#param-group"]
+				2: name: "storage.type.function.roff"
+				3: name: "entity.name.function.roff", patterns: [include: "#escapes"]
+				4: patterns: [include: "#escapes"]
 			endCaptures:
 				0: name: "punctuation.definition.request.roff"
 			patterns: [include: "$self"]
@@ -536,15 +534,14 @@

 			# Terminator included
 			name: "meta.macro.definition.with-terminator.$2.roff"
-			begin: "(?:^|\\G)([.'])[ \\t]*((dei?1?)|(ami?1?))\\s+(\\S+)\\s*(\"[^\"]+\"?|\\S+?(?=\\s|\\\\E?[\"#]))?(.*)$"
-			end:   "^(\\.)[ \\t]*((\\6)(?=$|\\s|\\\\(?:$|\")))"
+			begin: "(?:^|\\G)([.'])[ \\t]*((?:de|am)i?1?)\\s+(\\S+)\\s*(\"[^\"]+\"?|\\S+?(?=\\s|\\\\E?[\"#]))?(.*)$"
+			end:   "^(\\.)[ \\t]*((\\4)(?=$|\\s|\\\\(?:$|\")))"
 			beginCaptures:
 				1: name: "punctuation.definition.request.roff"
-				3: name: "storage.type.function.roff"
-				4: name: "entity.name.function.roff"
-				5: name: "variable.parameter.roff",         patterns: [include: "#escapes"]
-				6: name: "keyword.control.terminator.roff", patterns: [include: "#string"]
-				7: patterns: [include: "#param-group"]
+				2: name: "storage.type.function.roff"
+				3: name: "entity.name.function.roff",       patterns: [include: "#escapes"]
+				4: name: "keyword.control.terminator.roff", patterns: [include: "#string"]
+				5: patterns: [include: "#param-group"]
 			endCaptures:
 				1: name: "punctuation.definition.request.roff"
 				2: name: "keyword.control.terminator.roff"


Improve accuracy and granularity of scope-names

The scope-names and capturing groups for several rules have been revised
to ensure they conform to existing conventions:

* Control-line arguments are now scoped to "function-call.arguments"

* Punctuation scopes are now limited to the "less important parts". This
  has a noticeable improvement on legibility in themes (such as DuoTone)
  where words are shaded differently to adjacent symbols.

* ".begin" scope removed from patterns not part of a ".begin/.end" pair.

* Parameters are now consistently identified in escape sequences.

* "\fR" tokens will no longer be affected by the styling they terminate.

--- grammars/roff.cson
+++ grammars/roff.cson
@@ -45,6 +45,9 @@

 	# Control line parameters
 	params:
+		name: "function-call.arguments.roff"
+		begin: "\\G|^"
+		end:   "\\Z|$"
 		patterns: [
 			{include: "#escapes"}
 			{include: "#string"}
@@ -105,13 +108,13 @@

 			# Underlined passage
 			name: "meta.request.ul.roff"
-			begin: "^([.'][ \t]*ul)(?=[ \t\\\\]|$)(.*?)$"
-			end:   "([^\n ]+\n)"
+			begin: "^([.'])[ \t]*(ul)(?=[ \t\\\\]|$)(.*?)$"
+			end:   "[^\n ]+\n"
 			patterns: [{ include: "$self" }]
 			beginCaptures:
-				1: {name: "entity.function.name.roff"}
-				2: {patterns: [{include: "#escapes"}]}
-				3: {name: "comment.line.roff"}
+				1: {name: "punctuation.definition.request.roff"}
+				2: {name: "entity.function.name.roff"}
+				3: {patterns: [{include: "#params"}]}
 			endCaptures:
 				0: {name: "markup.underline.roff"}
 		}]
@@ -125,15 +128,18 @@

 			# Comments
 			name: "comment.line.roff"
-			begin: "(?:^[.'])?\\s*\\\\\""
+			begin: "(?:^([.'])\\s*)?(\\\\\")"
 			end: "$"
 			beginCaptures:
-				0: {name: "punctuation.definition.begin.comment.roff"}
+				1: {name: "punctuation.definition.comment.roff"}
+				2: {name: "punctuation.definition.comment.roff"}
 		},{

 			# Empty control lines
 			name: "comment.empty.roff"
-			match: "^[.'][ \t]*$"
+			match: "^([.'])[ \t]*$"
+			captures:
+				1: {name: "punctuation.definition.comment.roff"}
 		},

@@ -163,7 +169,7 @@
 		{match: "\\\\\n",    name: "constant.character.escape.newline.roff"}, {

 			# \(aa - Character named "aa"
-			name: "constant.character.escape.named-char.roff"
+			name: "constant.character.escape.function.named-char.roff"
 			match: "(?x)
 				(\\\\ \\()
 				(
@@ -172,24 +178,26 @@
 					bv|lf|rf|lc|rc|[>=<|!]=|->|<-|[+]-|\\*[A-IK-UW-Z*a-ik-uw-z]
 				)"
 			captures:
-				1: {name: "punctuation.definition.begin.roff"}
-				2: {name: "entity.name.roff"}
+				1: {name: "entity.name.roff"}
+				2: {name: "variable.parameter.roff"}

 		},{

 			# \*x, \*(xx - Interpolate string "x" or "xx"
-			name: "constant.character.escape.interpolate-string.roff"
-			match: "(\\\\\\*)(\\(\\S{2}|\\S)"
-			captures:
-				1: {name: "punctuation.definition.begin.roff"}
-				2: {name: "variable.parameter.roff"}
+			name: "constant.character.escape.function.interpolate-string.roff"
+			match: "(\\\\\\*\\()(\\S{2})|(\\\\\\*)(\\S)"
+			captures:
+				1: {name: "entity.name.roff"}
+				3: {name: "entity.name.roff"}
+				2: {name: "variable.parameter.roff"}
+				4: {name: "variable.parameter.roff"}
 		},{

 			# \$N - Interpolate argument number N (valid range: 1-9)
-			name: "constant.character.escape.interpolate-argument.roff"
+			name: "constant.character.escape.function.interpolate-argument.roff"
 			match: "(\\\\\\$)(\\d)"
 			captures:
-				1: {name: "punctuation.definition.begin.roff"}
+				1: {name: "entity.name.roff"}
 				2: {name: "variable.parameter.roff"}
 		},{

@@ -204,96 +212,94 @@
 				5: {name: "punctuation.definition.end.roff"}
 		},{

+			# Font: Roman/regular
+			name: "constant.character.escape.font.roff"
+			match: "\\\\f[RP1]"
+			captures:
+				0: {name: "entity.name.roff"}
+		}, {
+
 			# Font: Italics (typically rendered by nroff as underlined text)
 			name: "markup.italic.roff"
-			begin: "(\\\\)(f[I2])"
-			end: "(?=\\\\f[A-Za-z0-9])((\\\\)(f[RP1]))?"
-			beginCaptures:
-				1: {name: "punctuation.definition.backslash.roff"}
-				2: {name: "entity.name.roff"}
-			endCaptures:
-				1: {name: "meta.terminator.roff"}
-				2: {name: "punctuation.definition.backslash.roff"}
-				3: {name: "entity.name.roff"}
+			begin: "(\\\\f[I2])"
+			end: "(?=\\\\f[A-Za-z0-9])"
+			beginCaptures:
+				1: {name: "entity.name.roff"}
 		},{

 			# Font: Bold
 			name: "markup.bold.roff"
-			begin: "(\\\\)(f[B3])"
-			end: "(?=\\\\f[A-Za-z0-9])((\\\\)(f[RP1]))?"
-			beginCaptures:
-				1: {name: "punctuation.definition.backslash.roff"}
-				2: {name: "entity.name.roff"}
-			endCaptures:
-				1: {name: "meta.terminator.roff"}
-				2: {name: "punctuation.definition.backslash.roff"}
-				3: {name: "entity.name.roff"}
+			begin: "(\\\\f[B3])"
+			end: "(?=\\\\f[A-Za-z0-9])"
+			beginCaptures:
+				1: {name: "entity.name.roff"}
 		},{

 			# Font: Bold and italic
 			name: "markup.bold.italic.roff"
-			begin: "(\\\\)(f4)"
-			end: "(?=\\\\f[A-Za-z0-9])((\\\\)(f[RP1]))?"
-			beginCaptures:
-				1: {name: "punctuation.definition.backslash.roff"}
-				2: {name: "entity.name.roff"}
-			endCaptures:
-				1: {name: "meta.terminator.roff"}
-				2: {name: "punctuation.definition.backslash.roff"}
+			begin: "(\\\\f4)"
+			end: "(?=\\\\f[A-Za-z0-9])"
+			beginCaptures:
+				1: {name: "entity.name.roff"}
+		},{
+
+			# \fX, \f(XX, \fN - Change to font named "X" or "XX", or position N
+			name: "constant.character.escape.function.font.roff"
+			match: "(\\\\f\\()(\\S{2})|(\\\\f)(\\S)"
+			captures:
+				1: {name: "entity.name.roff"}
 				3: {name: "entity.name.roff"}
-		},{
-
-			# \fX, \f(XX, \fN - Change to font named "X" or "XX", or position N
-			name: "constant.character.escape.font.roff"
-			match: "(\\\\f)(\\(\\S{2}|\\S)"
-			captures:
-				1: {name: "punctuation.definition.begin.roff"}
-				2: {name: "variable.parameter.roff"}
+				2: {name: "variable.parameter.roff"}
+				4: {name: "variable.parameter.roff"}
 		},{

 			# \gx, \g(xx - Format of number register "x" or "xx"
-			name: "constant.character.escape.format-register.roff"
-			match: "(\\\\g)(\\(\\S{2}|\\S)"
-			captures:
-				1: {name: "punctuation.definition.begin.roff"}
-				2: {name: "variable.parameter.roff"}
+			name: "constant.character.escape.function.format-register.roff"
+			match: "(\\\\g\\()(\\S{2})|(\\\\g)(\\S)"
+			captures:
+				1: {name: "entity.name.roff"}
+				3: {name: "entity.name.roff"}
+				2: {name: "variable.parameter.roff"}
+				4: {name: "variable.parameter.roff"}
 		},{

 			# \kX - Mark horizontal input place in register "X"
-			name: "constant.character.escape.mark-input.roff"
+			name: "constant.character.escape.function.mark-input.roff"
 			match: "(\\\\k)(\\S)"
 			captures:
-				1: {name: "punctuation.definition.begin.roff"}
+				1: {name: "entity.name.roff"}
 				2: {name: "variable.parameter.roff"}
 		},{

 			# \nX, \n(XX - Contents of number register "X" or "XX"
-			name: "constant.character.escape.expand-register.roff"
-			match: "(\\\\n)(\\(\\S{2}|\\S)"
-			captures:
-				1: {name: "punctuation.definition.begin.roff"}
-				2: {name: "variable.parameter.roff"}
+			name: "constant.character.escape.function.expand-register.roff"
+			match: "(\\\\n\\()(\\S{2})|(\\\\n)(\\S)"
+			captures:
+				1: {name: "entity.name.roff"}
+				3: {name: "entity.name.roff"}
+				2: {name: "variable.parameter.roff"}
+				4: {name: "variable.parameter.roff"}
 		},{

 			# \sN, \s±N - Point-size change function; also \s(NN, \s±(NN
-			name: "constant.character.escape.point-size.roff"
-			match: "(\\\\s)([-+]?\\(?\\d+)"
-			captures:
-				1: {name: "punctuation.definition.begin.roff"}
+			name: "constant.character.escape.function.point-size.roff"
+			match: "(\\\\s[-+]?\\(?)(\\d+)"
+			captures:
+				1: {name: "entity.name.roff"}
 				2: {name: "variable.parameter.roff"}
 		},{

 			# \zC - Print "C" with zero width (without spacing)
-			name: "constant.character.escape.zero-width-print.roff"
+			name: "constant.character.escape.function.zero-width-print.roff"
 			match: "(\\\\z)(\\S)"
 			captures:
-				1: {name: "punctuation.definition.begin.roff"}
+				1: {name: "entity.name.roff"}
 				2: {name: "variable.parameter.roff"}
 		},{

 			# \Z - Any character not listed above
-			match: "\\\\(\\S)",
 			name: "constant.character.escape.misc.roff"
+			match: "\\\\\\S"
 		}]

@@ -306,52 +312,60 @@
 			# .TH: Title (GNU manual macro)
 			name: "markup.heading.title.gnu.man.macro.roff"
 			patterns: [{include: "#params"}]
-			begin: "^([.'][ \t]*TH)(?=[ \t]|$)"
+			begin: "^([.'])[ \t]*(TH)(?=[ \t]|$)"
 			end: "$"
 			beginCaptures:
-				1: {name: "entity.name.function.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.name.function.roff"}
 		},{

 			# .SH: Section heading
 			name: "markup.heading.section.man.macro.roff"
 			patterns: [{include: "#params"}]
-			begin: "^([.'][ \t]*SH)(?=[ \t]|$)"
+			begin: "^([.'])[ \t]*(SH)(?=[ \t]|$)"
 			end: "$"
 			beginCaptures:
-				1: {name: "entity.name.function.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.name.function.roff"}
 		},{

 			# .Ss: Subsection
 			name: "markup.heading.subsection.man.macro.roff"
 			patterns: [{include: "#params"}]
-			begin: "^([.'][ \t]*Ss)(?=[ \t]|$)"
+			begin: "^([.'])[ \t]*(Ss)(?=[ \t]|$)"
 			end: "$"
 			beginCaptures:
-				1: {name: "entity.name.function.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.name.function.roff"}
 		},{

 			# .B: Bold
 			name: "markup.bold.roff"
-			begin: "^[.'][ \t]*B(?:$|[ \t]+|(?=\\\\))"
+			begin: "^([.'])[ \t]*(B)(?:$|[ \t]+|(?=\\\\))"
 			end:   "([^\n ]+ ?\n)"
 			patterns: [{ include: "$self" }]
-
+			beginCaptures:
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.name.function.roff"}
 		},{

 			# .I: Italic
 			name: "markup.italic.roff"
-			begin: "^[.'][ \t]*I(?:$|[ \t]+|(?=\\\\))"
+			begin: "^([.'])[ \t]*(I)(?:$|[ \t]+|(?=\\\\))"
 			end:   "([^\n ]+ ?\n)"
 			patterns: [{ include: "$self" }]
-
+			beginCaptures:
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.name.function.roff"}
 		},{

 			# .BI: Bold and italic
 			name: "markup.bold-italic.roff"
-			begin: "^([.'][ \t]*BI)(?=[ \t\\\\]|$)"
+			begin: "^([.'])[ \t]*(BI)(?=[ \t\\\\]|$)"
 			end:   "(?<!\\\\)(?=\n)"
 			beginCaptures:
-				1: {name: "entity.function.name.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
 			patterns: [{
 				begin: '(?x)(?<=
 					^[.\']        BI|
@@ -379,10 +393,11 @@

 			# .BR: Bold and Roman
 			name: "markup.bold-roman.roff"
-			begin: "^([.'][ \t]*BR)(?=[ \t\\\\]|$)"
+			begin: "^([.'])[ \t]*(BR)(?=[ \t\\\\]|$)"
 			end:   "(?<!\\\\)(?=\n)"
 			beginCaptures:
-				1: {name: "entity.function.name.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
 			patterns: [{
 				begin: '(?x)(?<=
 					^[.\']        BR|
@@ -392,7 +407,7 @@
 					^[.\'][ \t]{4}BR)
 					[ \\t]+(".*?(?<!")"(?!")|[^"\\s]\\S*)[ \t]*(?=")'
 				end: '(?<=")|(?<!\\\\)$'
-				patterns: [{include: "#params"}]
+				patterns: [{include: "#roman-strings"}]
 				beginCaptures:
 					1:
 						name: "markup.bold.roff"
@@ -409,10 +424,11 @@

 			# .IB: Italic and bold
 			name: "markup.italic-bold.roff"
-			begin: "^([.'][ \t]*IB)(?=[ \t\\\\]|$)"
+			begin: "^([.'])[ \t]*(IB)(?=[ \t\\\\]|$)"
 			end:   "(?<!\\\\)(?=\n)"
 			beginCaptures:
-				1: {name: "entity.function.name.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
 			patterns: [{
 				begin: '(?x)(?<=
 					^[.\']        IB|
@@ -440,10 +456,11 @@

 			# .IR: Italic and Roman
 			name: "markup.italic-roman.roff"
-			begin: "^([.'][ \t]*IR)(?=[ \t\\\\]|$)"
+			begin: "^([.'])[ \t]*(IR)(?=[ \t\\\\]|$)"
 			end:   "(?<!\\\\)(?=\n)"
 			beginCaptures:
-				1: {name: "entity.function.name.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
 			patterns: [{
 				begin: '(?x)(?<=
 					^[.\']        IR|
@@ -453,7 +470,7 @@
 					^[.\'][ \t]{4}IR)
 					[ \\t]+(".*?(?<!")"(?!")|[^"\\s]\\S*)[ \t]*(?=")'
 				end: '(?<=")|(?<!\\\\)$'
-				patterns: [{include: "#params"}]
+				patterns: [{include: "#roman-strings"}]
 				beginCaptures:
 					1:
 						name: "markup.italic.roff"
@@ -470,10 +487,11 @@

 			# .RB: Roman and bold
 			name: "markup.roman-bold.roff"
-			begin: "^([.'][ \t]*RB)(?=[ \t\\\\]|$)"
+			begin: "^([.'])[ \t]*(RB)(?=[ \t\\\\]|$)"
 			end:   "(?<!\\\\)(?=\n)"
 			beginCaptures:
-				1: {name: "entity.function.name.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
 			patterns: [{
 				begin: '(?x)(?<=
 					^[.\']        RB|
@@ -499,10 +517,11 @@

 			# .RI: Roman and italic
 			name: "markup.roman-italic.roff"
-			begin: "^([.'][ \t]*RI)(?=[ \t\\\\]|$)"
+			begin: "^([.'])[ \t]*(RI)(?=[ \t\\\\]|$)"
 			end:   "(?<!\\\\)(?=\n)"
 			beginCaptures:
-				1: {name: "entity.function.name.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
 			patterns: [{
 				begin: '(?x)(?<=
 					^[.\']        RI|
@@ -607,3 +626,11 @@
 				patterns: [{include: "#italic-bareword"}]
 			}]
 		}]
+
+
+	# Roman words ("Quoted"/Unquoted)
+	"roman-strings":
+		patterns: [
+			{include: "#escapes"}
+			{include: "#string"}
+		]


encapsulate create proposition message

encapsulate create proposition message

--- app/assets/javascripts/admin/views/election/propositions/propositions_list/sub_sub_tag_view.js.coffee
+++ app/assets/javascripts/admin/views/election/propositions/propositions_list/sub_sub_tag_view.js.coffee
@@ -45,4 +45,5 @@
     params = text: event.target.text.value
     params['tagIds'] = @subSubTag.id
     params['candidacyId'] = @candidacy.id
-    @propositions.create params, url: '/api/v1/propositions', type: 'POST'
+    console.log params
+    @propositions.create {proposition: params }, url: '/api/v1/propositions', type: 'POST'


stretch inspector to fill page

stretch inspector to fill page

--- src/config/inspector.coffee
+++ src/config/inspector.coffee
@@ -26,7 +26,7 @@
   _LABEL: "inspector"
   i: (world) -> world.get('split')
   width: (world) -> world.get('size')
-  height: (world) -> world.get('size')
+  height: (world) -> world.get('size') + my.control.spacing
   fill: my.color.background
   stroke: "black"
   path: (world, args) -> world.get('rect_path')


Snippet to translate in Laravel views

Snippet to translate in Laravel views

Signed-off-by: Caddy Dz <cbc6199cd1cb93e9d3589fb9aa7ecaece7b37833@gmail.com>

--- src/atom/snippets.cson
+++ src/atom/snippets.cson
@@ -9,6 +9,9 @@
   'Vue JS Router':
     'prefix' : 'router'
     'body': '<router-link to="${1:url}" exact>${2:title}</router-link>\n\t$3'
+  'Localization retrieval':
+    'prefix' : 'translate'
+    'body': '{{ __(\'${1}\') }}'
 '.source.js':
   'VueJS component':
     'prefix' : 'component'


adding a close event for listmixin

adding a close event for listmixin

--- src/mixins/list.coffee
+++ src/mixins/list.coffee
@@ -23,6 +23,9 @@
     @listenTo @collection, "remove", @removed

     @listenTo @, "render:post", @addAll
+    @listenTo @, "close", (e) =>
+      for id, view of @views
+        view.trigger("close", e)

   setFilter: (filter) ->
     @filter = filter


resolved gulp server path

resolved gulp server path

--- gulp/server.coffee
+++ gulp/server.coffee
@@ -10,7 +10,7 @@
   connect.server
     livereload: true
     port: 4000
-    root: "./"
+    root: path.resolve("./")

   gulp.watch [test_dir], (file) ->


remove sixpack from default settings

remove sixpack from default settings

--- services/web/config/settings.defaults.coffee
+++ services/web/config/settings.defaults.coffee
@@ -354,7 +354,7 @@
 	]

 	sixpack:
-		domain:"http://45.79.157.156:5000"
+		domain:""
 	# ShareLaTeX Server Pro options (https://www.sharelatex.com/university/onsite.html)
 	# ----------


Remove Recaptcha default config (#2382)

Remove Recaptcha default config (#2382)

GitOrigin-RevId: 07fcddc135596f30614b087411e8116abad29770

--- services/web/config/settings.defaults.coffee
+++ services/web/config/settings.defaults.coffee
@@ -479,11 +479,6 @@
 		# Example:
 		#   header_extras: [{text: "Some Page", url: "http://example.com/some/page", class: "subdued"}]

-	recaptcha:
-		disabled:
-			invite: true
-			register: true
-
 	customisation: {}

 #	templates: [{


Space editing sessions heartbeats with an increasing backoff

We send the first heartbeat as soon as the session start.
The next ones are sent (if there's any activity)
when the editing session is about 30 and 60 seconds.
Then at 2min, 3min, 4min, 5min and later on every 5min.

The backoff is not reset, so if due to inactivity the
session expires in the server the backoff will still be
the same.

--- services/web/public/coffee/main/event.coffee
+++ services/web/public/coffee/main/event.coffee
@@ -1,9 +1,14 @@
 define [
+	"moment"
 	"base"
 	"modules/localStorage"
-], (App) ->
+
+], (moment, App) ->
 	CACHE_KEY = "mbEvents"
 	EDIT_SESSION_HEARTBEAT_INTERVAL = 5 * 60 * 1000 # 5min
+
+	sessionStart  = new Date()
+	nextHeartbeat = new Date()

 	send = (category, action, attributes = {})->
 		ga('send', 'event', category, action)
@@ -35,7 +40,22 @@
 			send: (category, action, label, value)->
 				ga('send', 'event', category, action, label, value)

-			editingSessionHeartbeat: _.throttle( (segmentation = {}) ->
+
+			editingSessionHeartbeat: (segmentation = {}) ->
+				return unless nextHeartbeat <= new Date()
+
+				@_sendEditingSessionHeartbeat(segmentation)
+
+				sessionDuration = (new Date().getTime() - sessionStart.getTime())/1000
+
+				backoffSecs = switch
+					when sessionDuration < 60  then 30
+					when sessionDuration < 300 then 60
+					else 300
+
+				nextHeartbeat = moment().add(backoffSecs, 'seconds').toDate()
+
+			_sendEditingSessionHeartbeat: (segmentation) ->
 				$http({
 					url: "/editingSession/#{window.project_id}",
 					method: "PUT",
@@ -44,8 +64,6 @@
 						"X-CSRF-Token": window.csrfToken
 					}
 				})
-			, EDIT_SESSION_HEARTBEAT_INTERVAL, trailing: false)
-

 			sendMB: (key, segmentation = {}) ->
 				$http {


Changed sets so that they take in JS iterables

--- src/builtin/set.coffee
+++ src/builtin/set.coffee
@@ -3,12 +3,12 @@
   constructor: (iterable) ->
     @value = new Dict() # set just is a wrapped version of our own Dict class
     if iterable?
-      for item in iterable.value # Handles empty constructor call too
+      for item in iterable # Handles empty constructor call too
         @value.__setitem__(item, true)

   __and__: (other) ->
-    intersect = new List()
-    intersect.append(item) for item in @value.value when other.__contains__(item)
+    intersect = []
+    intersect.push(item) for item in @value.value when other.__contains__(item)
     return new Set(intersect)

   __cmp__: (set) ->
@@ -48,11 +48,11 @@

   # Inplace and operation. x.__iand__(y) changes x
   __iand__: (set) ->
-    deletedKeys = new List()
-    for item in @value.keys()
-      if not set.__contains__(item)
-        deletedKeys.append(item)
-    for deletedKey in deletedKeys.value
+    deletedKeys = []
+    for item in @value.keys()
+      if not set.__contains__(item)
+        deletedKeys.push(item)
+    for deletedKey in deletedKeys
       @value.pop(deletedKey)
     return @

@@ -110,9 +110,9 @@

   # Returns a new Set containing items from this or set
   __or__: (set) ->
-    union = List()
-    union.append(item) for item in @value.keys()
-    union.append(item) for item in set.value.keys()
+    union = []
+    union.push(item) for item in @value.keys()
+    union.push(item) for item in set.value.keys()
     return new Set(union)

   # Same as __and__ since intersection is symmetric
@@ -164,7 +164,8 @@

   # Returns a shallow copy of this
   copy: ->
-    return new Set(@)
+    keys = @keys()
+    return new Set(keys)

   # Returns a new set containing items in this but not any set in others
   difference: (others...) ->


add sets, add EXTEND flag

add sets, add EXTEND flag

--- cards/phantom.coffee
+++ cards/phantom.coffee
@@ -1,5 +1,6 @@
 fs = require 'fs'
 webpage = require 'webpage'
+EXTEND = require('system').args[1]

 # XXX split cards (eg Fire // Ice) need massaging

@@ -74,7 +75,7 @@
   'The Dark'
   'Legends'
   'Revised Edition'
-  'Anitiquities'
+  'Antiquities'
   'Arabian Nights'
   'Unlimited Edition'
   'Limited Edition Beta'
@@ -85,6 +86,8 @@
   'Unhinged'
   'Unglued'
   'Magic: The Gathering-Commander'
+  'Planechase 2012 Edition' # baleful strix
+  'Masters Edition II' # mana crypt. also in set 'Promo set for Gatherer'
 ]

 Sets = {}
@@ -93,21 +96,33 @@
 process = ->
   if set = sets.pop()
     scrape set
-  else
+    return
+
+  if od = sets.Odyssey?.Rare
     # WTF
-    od = sets.Odyssey.Rare
     bad = 'XXCall of the Herd (Call of the Herd)'
     good = 'Call of the Herd'
     i = od.indexOf(bad)
-    if ~i
-      od[i] = good
-      Cards[good] = Cards[bad]
-      Cards[good].name = good
-      delete Cards[bad]
-
-    fs.write 'cards/sets.json' , JSON.stringify(Sets) , 'w'
-    fs.write 'cards/cards.json', JSON.stringify(Cards), 'w'
-    phantom.exit()
+    od[i] = good
+    Cards[good] = Cards[bad]
+    Cards[good].name = good
+    delete Cards[bad]
+
+  if EXTEND
+    # phantomjs cannot `require` json
+    # http://code.google.com/p/phantomjs/issues/detail?id=1057&sort=-id
+    sets  = JSON.parse fs.read 'cards/sets.json'
+    cards = JSON.parse fs.read 'cards/cards.json'
+    for key, val of Sets
+      sets[key] = val
+    for key, val of Cards
+      cards[key] = val
+    Sets = sets
+    Cards = cards
+
+  fs.write 'cards/sets.json' , JSON.stringify(Sets) , 'w'
+  fs.write 'cards/cards.json', JSON.stringify(Cards), 'w'
+  phantom.exit()

 scrape = (SET) ->
   url = "http://gatherer.wizards.com/Pages/Search/Default.aspx?output=spoiler&method=text&action=advanced&set=%5b%22#{SET}%22%5d"


added ability to import spec

added ability to import spec

--- src/crystal/generate.coffee
+++ src/crystal/generate.coffee
@@ -120,6 +120,15 @@
 						schema = exported.schema
 					module_config.exports[export_name].schema = schema

+				# handle spec
+				if typeof(exported.spec) == 'string' && exported.spec.match(/\./)
+					export_path = "#{module_path}/.crystal/spec/#{exported.spec}"
+					if fs.existsSync export_path
+						spec = yaml.safeLoad fs.readFileSync(export_path)
+					else
+						spec = exported.spec
+					module_config.exports[export_name].spec = spec
+
 				# handle template
 				if typeof(exported.template) == 'string' && exported.template.match(/\./)
 					export_path = "#{module_path}/.crystal/template/#{exported.template}"
@@ -330,10 +339,13 @@
 			if typeof(output.spec) == 'object'
 				spec = output.spec
 			else if typeof(output.spec) == 'string'
-				spec_filename = ".crystal/spec/#{output.spec}"
-				if !fs.existsSync spec_filename
-					throw new Error "File (#{spec_filename}) does not exist for spec in output for project (#{project.id})"
-				spec = yaml.safeLoad fs.readFileSync(spec_filename, 'utf8')
+				if imports[output.spec]
+					spec = imports[output.spec].spec
+				else
+					spec_filename = ".crystal/spec/#{output.spec}"
+					if !fs.existsSync spec_filename
+						throw new Error "File (#{spec_filename}) does not exist for spec in output for project (#{project.id})"
+					spec = yaml.safeLoad fs.readFileSync(spec_filename, 'utf8')

 			# parse spec variables
 			console.log "Processed spec.".blue


me: implement createRepo

me: implement createRepo

--- src/octonode/me.coffee
+++ src/octonode/me.coffee
@@ -136,5 +136,12 @@
       return cb(err) if err
       if s isnt 204 then cb(new Error('User delKey error')) else cb null, b

+  # Create a repository
+  # '/user/repos' POST
+  createRepo: (repo, cb) ->
+    @client.post "/user/repos", repo, (err, s, b)  ->
+      return cb(err) if err
+      if s isnt 201 then cb(new Error('User createRepo error')) else cb null, b
+
 # Export module
 module.exports = Me


:lipstick:

:lipstick:

--- src/editor-component.coffee
+++ src/editor-component.coffee
@@ -71,7 +71,6 @@
     @refs.hiddenInput.focus()

   componentWillUnmount: ->
-    @props.editor.off 'screen-lines-changed', @onScreenLinesChanged
     @getDOMNode().removeEventListener 'mousewheel', @onMousewheel

   listenForCustomEvents: ->


Oh man. Render only once!

Oh man. Render only once!

--- src/editor-component.coffee
+++ src/editor-component.coffee
@@ -538,6 +538,7 @@
     @cursorsMoved = true

   onDecorationChanged: ->
+    return if @decorationChangedImmediate?
     @decorationChangedImmediate = setImmediate =>
       @requestUpdate()
       @decorationChangedImmediate = null


guts - remove false check - not all placeholder nodes will be direct children of their template

--- guts.coffee
+++ guts.coffee
@@ -102,9 +102,6 @@
             throw 'CompositeModelView : error : existing view elements should not be magical children'
           if isDescendant(document, view.el)
             throw 'CompositeModelView : error : orphans should not have a home'
-          parentNode = view.el.parentNode
-          if parentNode
-            throw 'CompositeModelView : error : how did this happen?'

           placeholder = @find_view_placeholder(@$el, view)


Fixes #200: Change warn to warning for checkstyle output

--- src/commandline.coffee
+++ src/commandline.coffee
@@ -223,12 +223,15 @@
                 @print "<file name=\"#{path}\">"

                 for e in errors
+                    level = e.level
+                    level = 'warning' if level is 'warn'
+
                     # context is optional, this avoids generating the string
                     # "context: undefined"
                     context = e.context ? ""
                     @print """
                     <error line="#{e.lineNumber}"
-                        severity="#{@escape(e.level)}"
+                        severity="#{@escape(level)}"
                         message="#{@escape(e.message+'; context: '+context)}"
                         source="coffeelint"/>
                     """


Tweak welcome message

Tweak welcome message

--- scripts/welcome-to-zihub.coffee
+++ scripts/welcome-to-zihub.coffee
@@ -8,6 +8,9 @@
 #   * Sends welcome as private message
 #   * Based on welcome.coffee by Bob Silverberg <bob.silverberg@gmail.com>
 #
+# Commands:
+#   hubot la bienvenida
+
 # Author:
 #   Francho

@@ -35,13 +38,13 @@
         robot.brain.data.nicks.push nick
         robot.logger.debug "Added nick: #{nick}"

-  robot.brain.on 'loaded', =>
-    robot.brain.data.nicks ||= []
-
   welcomeGif = (user, room) ->
     msg = new hubot.TextMessage(user, robot.name + ' gif me hello')
     msg.room = room
     robot.receive msg
+
+  robot.brain.on 'loaded', =>
+    robot.brain.data.nicks ||= []

   robot.enter (res) ->
     user = res.message.user
@@ -55,5 +58,5 @@
       robot.messageRoom '#presentaciones', "Hola @#{user.name}"
       welcomeGif(user, 'presentaciones')

-  robot.respond /bienvenida/i, (msg) ->
+  robot.respond /la bienvenida/i, (msg) ->
     msg.reply welcomeMsg(msg.user.name)


Sim: Use `hasAbility` to check for Shadow Tag

--- server/bw/data/abilities.coffee
+++ server/bw/data/abilities.coffee
@@ -779,7 +779,7 @@
   this::beginTurn = this::switchIn = ->
     opponents = @battle.getOpponents(@pokemon)
     for opponent in opponents
-      opponent.blockSwitch()  if opponent.ability?.displayName != 'Shadow Tag'
+      opponent.blockSwitch()  unless opponent.hasAbility('Shadow Tag')

 makeAbility 'Shed Skin', ->
   this::endTurn = ->


- remove attrsName * use the new define-properties on properties

--- src/advance.coffee
+++ src/advance.coffee
@@ -6,47 +6,26 @@
 getPrototypeOf  = require 'inherits-ex/lib/getPrototypeOf'
 Properties      = require './properties'
 PropertyManager = require './abstract'
+defineProperties= require './properties/define-properties'
 getkeys         = Object.keys

 module.exports  = class AdvancePropertyManager
-  gAttrsName = '$attributes'
-
-  @::[gAttrsName] = null
+  @::$attributes = null
   @::SMART_ASSIGN = Properties.SMART_ASSIGN

-  defineProperty @, gAttrsName,
-    get: -> AdvancePropertyManager::[gAttrsName]
-
-  defineProperty @, 'attrsName', undefined,
-    get: -> gAttrsName
-    set: (value)-> gAttrsName = value
+  defineProperty @, '$attributes',
+    get: -> AdvancePropertyManager::$attributes

   constructor: -> @initialize.apply @, arguments
   # merge the methods on the PropertyManager.prototype.
   extend @::, PropertyManager::

-  getProperties: -> @[gAttrsName]
+  getProperties: -> @$attributes

-  @defineProperties: defineObjectProperties = (aTarget, aProperties, recreate = true)->
-    if isFunction aTarget
-      vPrototype = aTarget::
-      nonExported1stChar = vPrototype.nonExported1stChar
-    else if isObject aTarget
-      vPrototype = getPrototypeOf aTarget
-      nonExported1stChar = aTarget.nonExported1stChar
-    else
-      throw new TypeError 'the target should be a ctor or object!'
-    vAttrs = vPrototype[gAttrsName]
-    nonExported1stChar?= AdvancePropertyManager::nonExported1stChar
-
-    if recreate or not (vAttrs instanceof Properties)
-      vPrototype[gAttrsName] = vAttrs = Properties()
-    vAttrs.nonExported1stChar = nonExported1stChar
-    vAttrs.merge aProperties if aProperties
-    vAttrs
+  @defineProperties = defineProperties

   defineProperties: (aProperties, recreate = false) ->
-    vAttrs = defineObjectProperties @, aProperties, recreate
+    vAttrs = defineProperties @, aProperties, recreate
     vAttrs.initializeTo @
     @

@@ -54,4 +33,3 @@
     attrs = @getProperties() unless attrs
     attrs.assignPropertyTo dest, src, name, value, skipDefaultValue, isExported
     return
-


processes: no need to show

processes: no need to show

--- node_modules_koding/processes/src/processes.coffee
+++ node_modules_koding/processes/src/processes.coffee
@@ -77,7 +77,6 @@
       console.log "[PROCESSES][#{name}] kontrold enabled"
       @kontroldProcess options
     else
-      console.log "[PROCESSES][#{name}] kontrold disabled"
       @child = @startProcess options
       @populateChildObject options, @child


changed to quintic

changed to quintic

--- src/game/states/game.coffee
+++ src/game/states/game.coffee
@@ -88,10 +88,8 @@
      	       @game.add.tween(star).to({alpha:1},200,Phaser.Easing.Quintic.Out,true)
      	 else
        #if Player not on star
-<<<<<<< HEAD
-     	       @game.add.tween(star).to({alpha:0.1},10000,Phaser.Easing.Quintic.Out,true)
-=======
-     	       @game.add.tween(star).to({alpha:0.1},15000,Phaser.Easing.Cubic.Out,true)
+
+     	       @game.add.tween(star).to({alpha:0.1},15000,Phaser.Easing.Quintic.Out,true)
      	 if won
      	    if star.alpha < 0.35
      	       won = false
@@ -99,7 +97,6 @@
      if won
      	@add.text(10, 10, "Congratulations! Level Complete!", { font: "15px Arial", fill: "#ff0044", align: "center" })
      	@levelcomplete = true
->>>>>>> edcabb75232c6fd6a008c69ae49a3a6f2f367e0f

      if @cursors.left.isDown
         @player.body.moveLeft(200)


fix preload for new dir

fix preload for new dir

--- classify-menu.coffee
+++ classify-menu.coffee
@@ -38,8 +38,8 @@

-
-
+
+

   """


Starting on math environments

Starting on math environments

--- grammars/latex.cson
+++ grammars/latex.cson
@@ -63,6 +63,9 @@
             }
             {
                 include: '#figureEnvironment'
+            }
+            {
+                include: '#mathEnvironmentMeta'
             }
             {
                 include: '#genericEnvironment'
@@ -594,7 +597,7 @@
                 name: 'variable.parameter.optional.latex'
             9:
                 name: 'punctuation.definition.optional.end.latex'
-        end: '(\\\\)(end)(\\{)(figure)(\\})'
+        end: '(\\\\)(end)(\\{)(\\4)(\\})'
         endCaptures:
             1:
                 name: 'punctuation.definition.function.latex'
@@ -612,6 +615,47 @@
         #     }
         # ]
     }
+    mathEnvironmentMeta: {
+        comment: 'Matches math environments'
+        patterns: [
+            {
+                include: '#alignMathEnvironment'
+            }
+        ]
+    }
+    alignMathEnvironment: {
+        comment: 'Matches align environment'
+        contentName: 'support.environment.math.align.latex'
+        begin: '(\\\\)(begin)(\\{)(align(\\*)?)(\\})'
+        beginCaptures:
+            1:
+                name: 'punctuation.definition.function.latex'
+            2:
+                name: 'support.function.environment.begin.latex'
+            3:
+                name: 'punctuation.definition.argument.begin.latex'
+            4:
+                name: 'variable.parameter.argument.latex'
+            6:
+                name: 'punctuation.definition.argument.end.latex'
+        end: '(\\\\)(end)(\\{)(\\4)(\\})'
+        endCaptures:
+            1:
+                name: 'punctuation.definition.function.latex'
+            2:
+                name: 'support.function.environment.end.latex'
+            3:
+                name: 'punctuation.definition.argument.begin.latex'
+            4:
+                name: 'variable.parameter.argument.latex'
+            5:
+                name: 'punctuation.definition.argument.end.latex'
+        patterns: [
+            {
+                include: '$base'
+            }
+        ]
+    }
     makeatsomething: {
         comment: 'Matches the makeat(letter|other) commands so that they get custom highlighting (because @ is now a character)'
         name: 'support.function.makeat.latex'


Added large escape sequence highlight support

--- grammars/perl.cson
+++ grammars/perl.cson
@@ -1528,8 +1528,44 @@
 ]
 'repository':
   'escaped_char':
-    'match': '\\\\.'
-    'name': 'constant.character.escape.perl'
+    'patterns': [
+      {
+        'match': '\\\\\\d+'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\c[^\\s\\\\]'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\g(?:\\{(?:\\w*|-\\d+)\\}|\\d+)'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\k(?:\\{\\w*\\}|<\\w*>|\'\\w*\')'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\N\\{[^\\}]*\\}'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\o\\{\\d*\\}'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\(?:p|P)(?:\\{\\w*\\}|P)'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\x(?:\\w+|\\{\\w*\\})?'
+        'name': 'constant.character.escape.perl'
+      }
+      {
+        'match': '\\\\.'
+        'name': 'constant.character.escape.perl'
+      }
+    ]
   'line_comment':
     'patterns': [
       {


Add firstLineMatch setting for files without extensions

This is a last resort for roff documents that've been saved without file
extensions. If the contents of Plan 9's /sys/man/ directory are anything
to go by, the manual pages of earlier systems more often than not opened
with a .TH request.

We can probably get away with interpreting an opening ".TH ####" pattern
as the start of a roff document. Obviously, this won't cover every case,
but we shouldn't stuff too many "magic" heuristics that might risk other
formats being misclassified.

Sources:
A mountable disc image of the AT&T Plan 9 source files can be downloaded
from http://plan9.bell-labs.com/plan9/download/plan9.iso.bz2. If the URL
is inaccessible, the image is also available via the Wayback Machine.

--- grammars/roff.cson
+++ grammars/roff.cson
@@ -1,5 +1,6 @@
 name: "Roff"
 scopeName: "text.roff"
+firstLineMatch: "^\\.TH +(?:\\S+)"
 fileTypes: [
 	"1", "1b", "1c", "1has", "1in", "1m", "1s", "1x",
 	"2",


Add majority of paper-formatting troff macros

--- grammars/roff.cson
+++ grammars/roff.cson
@@ -429,36 +429,6 @@
 		}]

-	# Underline first argument only
-	"underline-first":
-		patterns: [{
-
-			# Unquoted string
-			contentName: "markup.underline.roff"
-			begin: "\\G[ \t]*(?!\")(?=(?:[^\\s\\\\]|\\\\(?!\").)+)"
-			end:   "(?<![^\\\\]\\\\|^\\\\)(?=\\s|$)|(?=\\\\\")"
-			patterns: [include: "#escapes"]
-		},{
-
-			# Null argument
-			name: "string.quoted.double.empty.roff"
-			match: '(")(")'
-			beginCaptures: {0: {name: "punctuation.definition.string.begin.roff"}}
-			endCaptures:   {0: {name: "punctuation.definition.string.end.roff"}}
-		},{
-			# Quoted string
-			name: "string.quoted.double.roff"
-			contentName: "markup.underline.roff"
-			begin: '\\G[ \t]*(")'
-			end:   '((?:"")*)"(?!")|(?<!\\\\)$|(?=\\\\\")'
-			beginCaptures: 1: name: "punctuation.definition.string.begin.roff"
-			endCaptures:
-				0: name: "punctuation.definition.string.end.roff"
-				1: name: "markup.underline.roff", patterns: [include: "#string-escapes"]
-			patterns: [include: "#string-escapes"]
-		}
-		{include: "#escapes"}
-		{include: "#string"}]

@@ -701,6 +671,7 @@
 			{include: "#man"}
 			{include: "#ms"}
 			{include: "#mm"}
+			{include: "#me"}
 			{include: "#www"}
 		]

@@ -832,6 +803,83 @@
 				1: {name: "punctuation.definition.macro.roff"}
 				2: {name: "entity.function.name.roff"}
 			patterns: [{include: "#params"}]
+		}]
+
+
+	# Paper-formatting macros
+	me:
+		patterns: [{
+
+			# Assorted macros without special highlighting or pattern-matching
+			name: "meta.function.${3:/downcase}.me.macro.roff"
+			begin: "(?x) ^([.'])[ \t]*
+				((?:[()][cdfqxz]|\\+\\+|\\+c)|
+				(1c|2c|EN|EQ|GE|GS|PE|PS|TE|TH|TS|ba|bc|bu|bx|hx
+				|hl|ip|lp|np|pd|pp|r|re|sk|sm|sz|tp|uh|xp)\\b)"
+			end: "(?<!\\\\)$|(?=\\\\\")"
+			beginCaptures:
+				1: {name: "punctuation.definition.macro.roff"}
+				3: {name: "entity.function.name.roff"}
+			patterns: [include: "#params"]
+		},{
+
+			# .(l: List
+			begin: "^([.'])[ \t]*(\\(l)\\b[ \t]*(?=$|\\n|\\\\\")"
+			end:   "^([.'])[ \t]*(\\)l)\\b"
+			contentName: "markup.list.unnumbered.roff"
+			patterns: [include: "$self"]
+			beginCaptures:
+				0: {name: "meta.function.list.begin.me.macro.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
+			endCaptures:
+				0: {name: "meta.function.list.end.me.macro.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
+		},{
+
+			# .b: Bold
+			begin: "^([.'])[ \t]*(b)\\b"
+			end: "(?<![^\\\\]\\\\|^\\\\)(?=$|\\n)|(?=\\\\\")"
+			contentName: "function-call.arguments.roff"
+			beginCaptures:
+				0: {name: "meta.function.bold-text.me.macro.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
+			patterns: [include: "#bold-first"]
+		},{
+
+			# .i: Italic
+			begin: "^([.'])[ \t]*(i)\\b"
+			end: "(?<![^\\\\]\\\\|^\\\\)(?=$|\\n)|(?=\\\\\")"
+			contentName: "function-call.arguments.roff"
+			beginCaptures:
+				0: {name: "meta.function.italic-text.me.macro.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
+			patterns: [include: "#italic-first"]
+		},{
+
+			# .bi: Bold/Italic
+			begin: "^([.'])[ \t]*(bi)\\b"
+			end: "(?<![^\\\\]\\\\|^\\\\)(?=$|\\n)|(?=\\\\\")"
+			contentName: "function-call.arguments.roff"
+			beginCaptures:
+				0: {name: "meta.function.bold-italic-text.me.macro.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
+			patterns: [include: "#bold-italic-first"]
+		},{
+
+			# .u: Underline
+			begin: "^([.'])[ \t]*(u)\\b"
+			end: "(?<![^\\\\]\\\\|^\\\\)(?=$|\\n)|(?=\\\\\")"
+			contentName: "function-call.arguments.roff"
+			beginCaptures:
+				0: {name: "meta.function.underline-text.me.macro.roff"}
+				1: {name: "punctuation.definition.macro.roff"}
+				2: {name: "entity.function.name.roff"}
+			patterns: [include: "#underline-first"]
 		}]

@@ -1489,3 +1537,146 @@
 				captures: 1: patterns: [include: "#string-escapes"]
 			}, include: "#string-escapes"]
 		}]
+
+
+
+	# Embolden first argument only
+	"bold-first":
+		patterns: [{
+
+			# Unquoted string
+			name: "markup.bold.roff"
+			begin: "\\G[ \t]*(?!\")(?=(?:[^\\s\\\\]|\\\\(?!\").)+)"
+			end:   "(?<![^\\\\]\\\\|^\\\\)(?=\\s|$)|(?=\\\\\")"
+			patterns: [include: "#escapes"]
+		},{
+
+			# Null argument
+			name: "markup.bold.roff"
+			match: '(")(")'
+			captures:
+				0: {name: "string.quoted.double.empty.roff"}
+				1: {name: "punctuation.definition.string.begin.roff"}
+				2: {name: "punctuation.definition.string.end.roff"}
+		},{
+			# Quoted string
+			name: "markup.bold.roff"
+			contentName: "string.quoted.double.roff"
+			begin: '\\G[ \t]*(")'
+			end:   '((?:"")*)"(?!")|(?<!\\\\)(?:$|\\n)|(?=\\\\\")'
+			beginCaptures:
+				0: name: "string.quoted.double.roff"
+				1: name: "punctuation.definition.string.begin.roff"
+			endCaptures:
+				0: name: "punctuation.definition.string.end.roff"
+				1: name: "markup.bold.roff", patterns: [include: "#string-escapes"]
+			patterns: [include: "#string-escapes"]
+		}
+		{include: "#escapes"}
+		{include: "#string"}]
+
+
+	# Italicise first argument only
+	"italic-first":
+		patterns: [{
+
+			# Unquoted string
+			name: "markup.italic.roff"
+			begin: "\\G[ \t]*(?!\")(?=(?:[^\\s\\\\]|\\\\(?!\").)+)"
+			end:   "(?<![^\\\\]\\\\|^\\\\)(?=\\s|$)|(?=\\\\\")"
+			patterns: [include: "#escapes"]
+		},{
+
+			# Null argument
+			name: "markup.italic.roff"
+			match: '(")(")'
+			captures:
+				0: {name: "string.quoted.double.empty.roff"}
+				1: {name: "punctuation.definition.string.begin.roff"}
+				2: {name: "punctuation.definition.string.end.roff"}
+		},{
+			# Quoted string
+			name: "markup.italic.roff"
+			contentName: "string.quoted.double.roff"
+			begin: '\\G[ \t]*(")'
+			end:   '((?:"")*)"(?!")|(?<!\\\\)(?:$|\\n)|(?=\\\\\")'
+			beginCaptures:
+				0: name: "string.quoted.double.roff"
+				1: name: "punctuation.definition.string.begin.roff"
+			endCaptures:
+				0: name: "punctuation.definition.string.end.roff"
+				1: name: "markup.italic.roff", patterns: [include: "#string-escapes"]
+			patterns: [include: "#string-escapes"]
+		}
+		{include: "#escapes"}
+		{include: "#string"}]
+
+
+
+	# Embolden and italicise first argument only
+	"bold-italic-first":
+		patterns: [{
+
+			# Unquoted string
+			name: "markup.bold.italic.roff"
+			begin: "\\G[ \t]*(?!\")(?=(?:[^\\s\\\\]|\\\\(?!\").)+)"
+			end:   "(?<![^\\\\]\\\\|^\\\\)(?=\\s|$)|(?=\\\\\")"
+			patterns: [include: "#escapes"]
+		},{
+
+			# Null argument
+			name: "markup.bold.italic.roff"
+			match: '(")(")'
+			captures:
+				0: {name: "string.quoted.double.empty.roff"}
+				1: {name: "punctuation.definition.string.begin.roff"}
+				2: {name: "punctuation.definition.string.end.roff"}
+		},{
+			# Quoted string
+			name: "markup.bold.italic.roff"
+			contentName: "string.quoted.double.roff"
+			begin: '\\G[ \t]*(")'
+			end:   '((?:"")*)"(?!")|(?<!\\\\)(?:$|\\n)|(?=\\\\\")'
+			beginCaptures:
+				0: name: "string.quoted.double.roff"
+				1: name: "punctuation.definition.string.begin.roff"
+			endCaptures:
+				0: name: "punctuation.definition.string.end.roff"
+				1: name: "markup.bold.italic.roff", patterns: [include: "#string-escapes"]
+			patterns: [include: "#string-escapes"]
+		}
+		{include: "#escapes"}
+		{include: "#string"}]
+
+
+
+	# Underline first argument only
+	"underline-first":
+		patterns: [{
+
+			# Unquoted string
+			contentName: "markup.underline.roff"
+			begin: "\\G[ \t]*(?!\")(?=(?:[^\\s\\\\]|\\\\(?!\").)+)"
+			end:   "(?<![^\\\\]\\\\|^\\\\)(?=\\s|$)|(?=\\\\\")"
+			patterns: [include: "#escapes"]
+		},{
+
+			# Null argument
+			name: "string.quoted.double.empty.roff"
+			match: '(")(")'
+			beginCaptures: {0: {name: "punctuation.definition.string.begin.roff"}}
+			endCaptures:   {0: {name: "punctuation.definition.string.end.roff"}}
+		},{
+			# Quoted string
+			name: "string.quoted.double.roff"
+			contentName: "markup.underline.roff"
+			begin: '\\G[ \t]*(")'
+			end:   '((?:"")*)"(?!")|(?<!\\\\)$|(?=\\\\\")'
+			beginCaptures: 1: name: "punctuation.definition.string.begin.roff"
+			endCaptures:
+				0: name: "punctuation.definition.string.end.roff"
+				1: name: "markup.underline.roff", patterns: [include: "#string-escapes"]
+			patterns: [include: "#string-escapes"]
+		}
+		{include: "#escapes"}
+		{include: "#string"}]


manyboxplots2: In top figure, can hover over anywhere in the column

--- manyboxplots2/manyboxplots2.coffee
+++ manyboxplots2/manyboxplots2.coffee
@@ -127,8 +127,8 @@
      .attr("class", "axis")
      .attr("y1", pad.top)
      .attr("y2", h-pad.bottom)
-     .attr("x1", (d) -> xScale(d))
-     .attr("x2", (d) -> xScale(d))
+     .attr("x1", (d) -> xScale(d-1))
+     .attr("x2", (d) -> xScale(d-1))
      .attr("stroke", "white")
      .attr("pointer-events", "none")

@@ -140,7 +140,7 @@
      .attr("class", "axis")
      .text((d) -> d)
      .attr("y", h-pad.bottom*0.75)
-     .attr("x", (d) -> xScale(d))
+     .attr("x", (d) -> xScale(d-1))
      .attr("dominant-baseline", "middle")
      .attr("text-anchor", "middle")

@@ -181,6 +181,22 @@
                  .attr("fill", "purple")
                  .attr("stroke", "none")
                  .attr("opacity", "0")
+                 .attr("pointer-events", "none")
+
+  # vertical rectangles representing each array
+  longRectGrp = svg.append("g").attr("id", "longRect")
+
+  longRect = indRectGrp.selectAll("empty")
+                 .data(indindex)
+                 .enter()
+                 .append("rect")
+                 .attr("x", (d) -> xScale(d) - recWidth/2)
+                 .attr("y", pad.top)
+                 .attr("width", recWidth)
+                 .attr("height", h - pad.top - pad.bottom)
+                 .attr("fill", "purple")
+                 .attr("stroke", "none")
+                 .attr("opacity", "0")

   # label quantiles on right
   rightAxis = svg.append("g").attr("id", "rightAxis")
@@ -268,7 +284,6 @@
         .y((d) -> lowyScale(d))

   randomInd = indindex[Math.floor(Math.random()*data.ind.length)]
-  randomInd = 0
   d3.select("rect#rect#{data.ind[randomInd]}").attr("opacity", "1")

   hist = lowsvg.append("path")
@@ -296,9 +311,9 @@
   for d in indindex
     clickStatus.push(0)

-  indRect
+  longRect
     .on "mouseover", (d) ->
-              d3.select(this)
+              d3.select("rect#rect#{data.ind[d]}")
                  .attr("opacity", "1")
               d3.select("#histline")
                  .datum(data.counts[d])
@@ -309,17 +324,17 @@

     .on "mouseout", (d) ->
               if !clickStatus[d]
-                d3.select(this).attr("opacity", "0")
+                d3.select("rect#rect#{data.ind[d]}").attr("opacity", "0")

     .on "click", (d) ->
               console.log("Click: #{data.ind[d]} (#{d})")
               clickStatus[d] = 1 - clickStatus[d]
-              d3.select(this).attr("opacity", clickStatus[d])
+              d3.select("rect#rect#{data.ind[d]}").attr("opacity", clickStatus[d])
               if clickStatus[d]
                 curcolor = histColors.shift()
                 histColors.push(curcolor)

-                d3.select(this).attr("fill", curcolor)
+                d3.select("rect#rect#{data.ind[d]}").attr("fill", curcolor)

                 grp4BkgdHist.append("path")
                       .datum(data.counts[d])
@@ -375,7 +390,10 @@
     text += "#{q*100}"
   text += " percentiles for each of #{data.ind.length} distributions.\n"

-  d3.select("div#legend").append("p")
+  d3.select("div#legend")
+    .style("margin-left", "70px")
+    .style("width", "500px")
+    .append("p")
     .text(text)

   d3.select("div#legend").append("p")


Compatibilidade do shipping calculator: função window.ShippingValue

--- src/coffee/portal-shipping-calculator.coffee
+++ src/coffee/portal-shipping-calculator.coffee
@@ -98,4 +98,8 @@
 		invalidPostalCode: 'CEP inválido.'
 		requiredQuantity: 'É necessário informar a quantidade do mesmo Produto.'
 		siteName: 'Vtex.Commerce.Web.CommerceContext.Current.WebSite.Name'
-		close: 'Fechar'+		close: 'Fechar'
+
+# COMPATIBILIDADE (DEPRECATED)
+window.ShippingValue = ->
+	$('.show-shipping-calculator').click()


beschleunige touch moves

beschleunige touch moves

--- lib/app-list.coffee
+++ lib/app-list.coffee
@@ -78,7 +78,7 @@
       @_start=false
       @setTouchDirection()
     if not e.end
-      @touchFunction e.avg.diff.x
+      @touchFunction e.avg.diff.x*2
     else
       @_start=true
       @end()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

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

   object = engine.add
     class: "GameObject"
-    velocity: Point(1, 0)
+    velocity: Point(, 0)

   engine.frameAdvance()


Follow mixin

Follow mixin

--- test/follow.coffee
+++ test/follow.coffee
@@ -2,6 +2,6 @@

 test "testing for equality", ->
   player = GameObject
-
+    x:

 module()


#copy

#copy

--- test/matrix.coffee
+++ test/matrix.coffee
@@ -36,6 +36,18 @@
     equals(matrix.d, 0, "d")
     equals(matrix.tx, 0, "tx")
     equals(matrix.ty, 0, "ty")
+
+  test "#copy", ->
+    matrix = Matrix(2, 0, 0, 2)
+
+    copyMatrix = matrix.copy()
+
+    matrixEqual copyMatrix, matrix
+
+    copyMatrix.a = 4
+
+    equals copyMatrix.a, 4
+    equals matrix.a, 2, "Old 'a' value is unchanged"

   test ".scale", ->
     matrix = Matrix.scale(2, 2)


expectDelete

expectDelete

--- src/extras/testing/model_expectations.coffee
+++ src/extras/testing/model_expectations.coffee
@@ -13,6 +13,13 @@

     @stub instance, 'save', (callback) =>
       @completeExpectation('expectUpdate')
+      callback(options.error, options.response ? instance )
+
+  expectDelete: (instance, options = {}) ->
+    @addExpectation('expectDelete')
+
+    @stub instance, 'destroy', (callback) =>
+      @completeExpectation('expectDelete')
       callback(options.error, options.response ? instance )

   expectLoad: (klass, options = {}) ->


Update parser test to clarify the use of fixtures.

--- test/parser.coffee
+++ test/parser.coffee
@@ -22,28 +22,28 @@

       # Read data from an output fixture.
       #
-      outputFilename = "#{index}.css"
-      outputFilepath = path.join outputFixturesDir, fixtureName, outputFilename
-      outputData = fs.readFileSync outputFilepath, { encoding: 'utf8' }
+      outputFixtureFilename = "#{index}.css"
+      outputFixtureFilepath = path.join outputFixturesDir, fixtureName, outputFixtureFilename
+      outputFixtureData = fs.readFileSync outputFixtureFilepath, { encoding: 'utf8' }

       # Remove whitespace from both data sets.
       #
       parserData = parserData.replace(/\s+/g, '');
-      outputData = outputData.replace(/\s+/g, '');
+      outputFixtureData = outputFixtureData.replace(/\s+/g, '');

-      expect(parserData).to.equal outputData
+      expect(parserData).to.equal outputFixtureData

   # Build up a context from input fixture files.
   #
-  inputFilename = "#{fixtureName}.css"
-  context = "with data from the fixture \"#{inputFilename}\""
+  inputFixtureFilename = "#{fixtureName}.css"
+  context = "with data from the fixture \"#{inputFixtureFilename}\""

   spec.Parser[context] = {}

-  inputFilepath = path.join inputFixturesDir, inputFilename
-  inputData = fs.readFileSync inputFilepath, { encoding: 'utf8' }
-  result = bless inputData
+  inputFixtureFilepath = path.join inputFixturesDir, inputFixtureFilename
+  inputFixtureData = fs.readFileSync inputFixtureFilepath, { encoding: 'utf8' }
+  result = bless inputFixtureData

   # Add the predicate and test case to the context.
@@ -60,13 +60,13 @@

 # Add a new context for each input fixture file.
 #
-inputFiles = fs.readdirSync inputFixturesDir
+inputFixtureFiles = fs.readdirSync inputFixturesDir

-for inputFilename in inputFiles
-  continue unless /\.css$/.test inputFilename
-  inputFileExtension = path.extname inputFilename
-  inputFile = path.basename inputFilename, inputFileExtension
-  addContext inputFile
+for filename in inputFixtureFiles
+  continue unless /\.css$/.test filename
+  fileExtension = path.extname filename
+  fixtureName = path.basename filename, fileExtension
+  addContext fixtureName

 # Export the spec to the test runner.


temporarily disable idle timeout for now -- causes too much trouble and there are too many subtle edge cases

--- src/smc-webapp/client_browser.coffee
+++ src/smc-webapp/client_browser.coffee
@@ -19,7 +19,6 @@
 #
 ###############################################################################

-
 client = require('smc-util/client')

 {Idle} = require('./external/idle')
@@ -38,7 +37,8 @@
         window.smc = {}
         window.smc.client = @
         window.smc.misc = require('smc-util/misc')
-        @_init_idle()
+        # Disable for now -- too many issues.  Need this soon though!
+        #@_init_idle()
         super(opts)

     _init_idle: () =>
@@ -83,11 +83,15 @@
                     @_conn?.open()
         @_idle.start()

+    reset_idle: =>
+        console.log("idle: reset_idle got called")
+        @_idle?.stop()
+        @_idle?.start()

     set_standby_timeout_m: (time_m) =>
         @_idle_timeout = time_m * 60 * 1000
-        @_idle.setAwayTimeout(@_idle_timeout)
-        @_idle.start()
+        @_idle?.setAwayTimeout(@_idle_timeout)
+        @_idle?.start()

     _connect: (url, ondata) ->
         @url = url


Remove all given upgrades when deleting a student

--- src/smc-webapp/course/actions.coffee
+++ src/smc-webapp/course/actions.coffee
@@ -367,6 +367,7 @@
         store = @get_store()
         return if not store?
         student = store.get_student(student)
+        @redux.getActions('projects').clear_project_upgrades(student.get('project_id'))
         @_set
             deleted    : true
             student_id : student.get('student_id')


Removed debug from inspector ui

Removed debug from inspector ui

--- src/javascript/inspector/inspector_ui.coffee
+++ src/javascript/inspector/inspector_ui.coffee
@@ -71,7 +71,6 @@

     componentViews = if @state.foldOpen
       @props.components.map((comp,cid) =>
-        console.log comp
         React.createElement Component, {component: comp, key: cid, inspectorConfig: @props.inspectorConfig}
       ).toList()
     else


Add section flow indices

Add section flow indices

--- app/assets/javascripts/alongslide/layout.coffee
+++ app/assets/javascripts/alongslide/layout.coffee
@@ -76,6 +76,9 @@
     @setPositionOf background, to: @nextFramePosition() if background.length
     background.addClass('unstaged')

+    # Reset section index before building another section
+    @currentSectionFlowIndex = 0
+
     @renderFrame(flowName)

   # Render one frame and its containing columns.
@@ -92,6 +95,10 @@
     # for each column in frame
     while frame.find('.'+@regionCls).length < @numFrameColumns(frame)
       column = @buildRegion frame, flowName
+
+      # Give each section flow an index
+      @currentSectionFlowIndex++
+      column.find('.section').attr('data-section-flow-idx', @currentSectionFlowIndex)

       # Move three-columns class from .section to .frame
       hasThreeColumns = (column.children('.three-columns').length)


Added method to the sessions model to see if a user is logged in.

--- app/assets/javascripts/models/session.js.coffee
+++ app/assets/javascripts/models/session.js.coffee
@@ -9,6 +9,8 @@

   # Returns true if the user is not a new user.
   isRegistered: -> !@get('user').get('isRegistered')
+  # Returns true if the session user is an actual record
+  isLoggedIn: -> @get('user').get('is_transient') == false

   # Returns true if user is affiliated with any clouds.
   hasClouds: -> @get('clouds').length > 1


Remove console log

Remove console log

--- app/assets/javascripts/sunrise/manage.js.coffee
+++ app/assets/javascripts/sunrise/manage.js.coffee
@@ -156,8 +156,6 @@
     new_id = new Date().getTime();
     regexp = new RegExp("new_" + method, "g")

-    console.log link
-
     $(link).parents("div.nested_bottom").before(content.replace(regexp, new_id))

   remove_fields: (link) ->
@@ -166,8 +164,6 @@
     if hidden_field.length isnt 0
       hidden_field.val('1')

-    console.log link
-
     $(link).closest("div.nested_item").hide()

 $(document).ready ->


ability to close vote view

ability to close vote view

Former-commit-id: c784412d6ddc2c756952e1a124e3341b829e17b4 [formerly 7ca473d96e0d077ca3e9be17c9169a7a1f5e8640] [formerly 5453c5e7cad7a2a0842e25fc00a354c5516c5061 [formerly 5453c5e7cad7a2a0842e25fc00a354c5516c5061 [formerly 4f02dff744721dd1e50c7fce3283674f155f5b53]]]
Former-commit-id: daee3df7f681ed294e344d88894aae23e6cbe018 [formerly c8c39454bd0b937225b8d6c3c63bdbf0616ef761]
Former-commit-id: fc5632921d664c3a56db482dfe2b0faa9f554ab7
Former-commit-id: 6123648ddccf3dc71927f9423b504cf909728b2e

--- app/assets/javascripts/views/resultsview.coffee
+++ app/assets/javascripts/views/resultsview.coffee
@@ -4,6 +4,7 @@

   initialize : (options) ->
     @proposal = options.proposal
+
     num_participants = ($.parseJSON(@model.get('participants'))||[]).length
     @tile_size = Math.min 50, ConsiderIt.utils.get_tile_size(@PARTICIPANT_WIDTH, @PARTICIPANT_HEIGHT, num_participants)

@@ -55,10 +56,19 @@
     @state = 1

+  implode_participants : ->
+    @proposal.view.set_state(2)
+    $participants = @$el.find('.l-message-speaker .l-group-container')
+    $participants.find('.avatar').css {position: '', zIndex: '', '-ms-transform': "", '-moz-transform': "", '-webkit-transform': "", transform: ""}
+
+    @$el.find('.m-bar-percentage').fadeOut()
+    @$el.find('.m-histogram').fadeOut =>
+      @$el.find('.m-histogram').css('opacity', '')
+      $participants.fadeIn()
+
   explode_participants : ->
     @proposal.view.set_state(4)

-    speed = 1500

     modern = Modernizr.csstransforms && Modernizr.csstransitions

@@ -68,18 +78,10 @@
       @$el.find('.m-histogram').css 'opacity', 1
       $participants.fadeOut()
     else
+      speed = 1500
       from_tile_size = $participants.find('.avatar:first').width()
       to_tile_size = @$el.find(".m-histogram .avatar:first").width()
       ratio = to_tile_size / from_tile_size
-
-      $participants
-        .css({'position':'absolute','z-index':99})
-        .find('.avatar').css {
-          #'-o-transition': "all #{speed}ms ease",
-          '-ms-transition': "-ms-transform #{speed}ms ease",
-          '-moz-transition': "-moz-transform #{speed}ms ease",
-          '-webkit-transition': "-webkit-transform #{speed}ms ease",
-          'transition': "transform #{speed}ms ease"}

       # compute all offsets first, before applying changes, for perf reasons
       positions = {}
@@ -123,6 +125,7 @@
   events :
     'click .m-results-responders, .l-message-speaker.l-group-container' : 'transition_explorer'
     'click [data-action="results-explode-participants"]' : 'explode_participants'
+    'click [data-action="results-implode-participants"]' : 'implode_participants'

   transition_explorer : ->
     ConsiderIt.router.navigate(Routes.proposal_path( @proposal.model.get('long_id') ), {trigger: true}) if @state==0
@@ -136,7 +139,7 @@

   render : () ->

-    if @proposal.top_pro && @proposal.top_con && @proposal.model.participants().length > 0
+    if @proposal.has_participants
       this.$el.html ConsiderIt.SummaryView.template($.extend({}, @model.attributes, {
         top_pro : @proposal.top_pro
         top_con : @proposal.top_con
@@ -213,7 +216,7 @@

     _.extend histogram,
       biggest_segment : Math.max.apply(null, _.map(histogram.breakdown, (bar) -> bar.positions.length))
-      num_positions : _.keys(@proposal.positions).length
+      num_positions : if !@proposal.positions? 0 else _.keys(@proposal.positions).length

     for bar,idx in histogram.breakdown
       height = bar.positions.length / histogram.biggest_segment


Make default actual function

Make default actual function

--- apps/settings/components/form_card/index.coffee
+++ apps/settings/components/form_card/index.coffee
@@ -1,7 +1,7 @@
 Promise = require 'bluebird-q'
 Serializer = require '../../../../components/form/serializer.coffee'

-module.exports = ($el, onSubmit = Promise.resolve()) ->
+module.exports = ($el, onSubmit = -> Promise.resolve()) ->
   $submit = $el.find('button')
   $errors = $el.find('.js-form-errors')


update group page to filter thumbnails when user moves year slider

--- app/assets/javascripts/components/group-page.cjsx
+++ app/assets/javascripts/components/group-page.cjsx
@@ -12,7 +12,8 @@
   getInitialState: ->
     all_institutions: []
     all_playwrights: []
-    all_years: []
+    min_year: 1920
+    max_year: 1940

   componentDidMount: ->
     # make a request to http://localhost:3000/subject_set_first_pages?group_id={{requested group id}}
@@ -46,9 +47,6 @@
           if year_int > max_year
             max_year = year_int

-      min_max_year_array = [min_year, max_year]
-      console.log(min_max_year_array)
-
       @setState
         all_first_pages: first_pages_json
         all_institutions: all_institutions
@@ -75,11 +73,10 @@
     @setState
       first_page_array: first_pages_view

-
   updateFirstPageArray: ->
-    console.log("updating first page array")
     selected_institution = $(".collection-institution select").val()
     selected_playwright  = $(".collection-playwright select").val()
+    start_and_end_years  = @refs.ReactYearSlider.state.value

     # define the selection criteria to be used to filter first page objects
     selection_criteria_options = [
@@ -102,18 +99,23 @@
       if selection_criterion.value?
         selection_criteria.push(selection_criterion)

-    console.log(selection_criteria)
-
     # iterate over the first page array and retain only those elements that match
     # the user-specified selection criteria
     first_pages_to_display = []
     for first_page in @state.all_first_pages
       keep_page = 1
+
+      # ensure year falls within user-selected range
+      page_year = parseInt(first_page.meta_data.year)
+      if page_year < start_and_end_years[0]
+        keep_page = 0
+      if page_year > start_and_end_years[1]
+        keep_page = 0
+
+      # iterate over the selection criteria and continue filtering
       for selection_criterion in selection_criteria
-        console.log(first_page.meta_data[selection_criterion.key_in_first_page_json], selection_criterion.value)
         if first_page.meta_data[selection_criterion.key_in_first_page_json] != selection_criterion.value
           keep_page = 0
-          console.log("not keeping page")
       if keep_page == 1
         first_pages_to_display.push(first_page)

@@ -123,7 +125,6 @@
       first_pages_view.push <FirstPageThumbnail page_json={page_json} key={index} />
     @setState
       first_page_array: first_pages_view
-

   render: ->
     if ! @state.group?
@@ -155,9 +156,12 @@

                 <div className="collection-range-slider">

-                  <ReactSlider min={@state.min_year}
-                      max={@state.max_year}
-                      defaultValue={[@state.min_year, @state.max_year]} withBars />
+                  <ReactSlider
+                    onAfterChange={@updateFirstPageArray}
+                    ref="ReactYearSlider"
+                    min={@state.min_year}
+                    max={@state.max_year}
+                    defaultValue={[@state.min_year, @state.max_year]} withBars />

                 </div>


Add new utils.

Add new utils.

--- app/assets/javascripts/lib/common_utils.js.coffee
+++ app/assets/javascripts/lib/common_utils.js.coffee
@@ -3,11 +3,24 @@
   w.gl       or= {}
   w.gl.utils or= {}

+  w.gl.utils.isInGroupsPage = ->
+
+    return $('body').data('page').split(':')[0] is 'groups'
+
+
+  w.gl.utils.isInProjectPage = ->
+
+    return $('body').data('page').split(':')[0] is 'projects'
+
+
   w.gl.utils.getProjectSlug = ->

-    $body = $ 'body'
-    isInProjectPage = $body.data('page').split(':')[0] is 'projects'
+    return if @isInProjectPage() then $('body').data 'project' else null

-    return if isInProjectPage then $body.data 'project' else null
+
+  w.gl.utils.getGroupSlug = ->
+
+    return if @isInGroupsPage() then $('body').data 'group' else null
+

 ) window


remove debug line

remove debug line

--- app/assets/javascripts/s3_direct_upload.js.coffee
+++ app/assets/javascripts/s3_direct_upload.js.coffee
@@ -51,7 +51,6 @@
         current_files.splice($.inArray(data, current_files), 1) # remove that element from the array
         if current_files.length == 0
           $(document).trigger("s3_uploads_complete")
-          console.log "uploads completed"

       fail: (e, data) ->
         alert("#{data.files[0].name} failed to upload.")


removing stray comment

removing stray comment

--- apps/show/components/related_articles/view.coffee
+++ apps/show/components/related_articles/view.coffee
@@ -21,7 +21,7 @@

   events:
     'click .related-articles-show-all': 'showAll'
-#
+
   showAll: (e) ->
     e.preventDefault()
     @numToShow = @collection.length


Ensure that natural query changes when input is empty

--- client/header.coffee
+++ client/header.coffee
@@ -24,11 +24,12 @@

   'keyup .search-input': (e, template) ->
     val = $(template.findAll '.search-input').val()
+
     # If user focused with tab or pressed some other non-content key we don't want to activate the search
-    return unless val
+    if val
+      Session.set 'searchActive', true
+      Session.set 'searchFocused', true

-    Session.set 'searchActive', true
-    Session.set 'searchFocused', true
     naturalQueryChange val

   'paste .search-input': (e, template) ->


Improve autocomplete provider parenthesis management

--- lib/services/php-file-parser.coffee
+++ lib/services/php-file-parser.coffee
@@ -64,12 +64,17 @@
       text = editor.getTextInBufferRange([[position.row - idx, 0], position])
       idx++

+    text = text.substr(text.lastIndexOf("$"), text.length)
+
+    # Remove parenthesis content
+    regx = /\((?:[^\])\(\)]+|(?:[^\(\)\])]*\([^\(\)\])]*\)[^\)]*))*\)*/g
+    text = text.replace regx, ""
+
     # Get the full text
     return [] if not text

     elements = text.split("->")
-    elements[0] = elements[0].substr(text.lastIndexOf("$"), text.length)
-
+
     # Remove parenthesis and whitespaces
     for key, element of elements
       element = element.replace /^\s+|\s+$/g, ""
@@ -77,8 +82,6 @@
         element = element.substring(1)

       elements[key] = element
-      if element.indexOf("(") != -1
-        elements[key] = element.substr(0, element.indexOf("(")) + element.substr(element.indexOf(")")+1, element.length)

     return elements


CoffeeScript 1.6.3

CoffeeScript 1.6.3

--- coffee-script.coffee
+++ coffee-script.coffee
@@ -13,7 +13,7 @@
 SourceMap     = require './sourcemap'

 # The current CoffeeScript version number.
-exports.VERSION = '1.6.2'
+exports.VERSION = '1.6.3'

 # Expose helpers for testing.
 exports.helpers = helpers


Add check for cabin image cache

Add check for cabin image cache

--- coffee/server.coffee
+++ coffee/server.coffee
@@ -32,10 +32,13 @@
 ]

 server.ext 'onPreResponse', (request, next) ->
-  #console.log request.response() instanceof Error
-  #console.log request.path.substr 0, 21
-  #console.log request.response().isBoom
-  #console.log request.response()._code
+  if request.path.substr(0, 21) is '/static/images/cabin/'
+    if request.response() instanceof Error
+      id = request.path.replace('/static/images/cabin/', '')
+      return cabin.fetchImage(id, next) if /^[0-9a-f]{24}$/.test id
+    else
+      request._response.headers['content-type'] = 'image/jpeg'
+
   next()

 if not module.parent


add link to blockscanner form, improve comments

--- combine-users.coffee
+++ combine-users.coffee
@@ -7,8 +7,6 @@
 request = require 'request'
 fs = require 'fs'

-
-userDoc = "https://docs.google.com/spreadsheet/pub?key=0Al5UYaVoRpW3dE12bzRTVEp2RlJDQXdUYUFmODNiTHc&single=true&gid=0&output=csv";
 userHash = {}

 total = 0
@@ -80,9 +78,10 @@
 console.log("#{csvusers} added from manual list of users")

-
-# BLOCKSPLORER FORM SUBMISSIONS ------------------------------------------------
-# pull from the form provided by bocoup for blockscanner
+# BL.OCKSPLORER FORM SUBMISSIONS ------------------------------------------------
+# pull from the Google form provided by @ireneros @bocoup for blockscanner & http://bl.ocksplorer.org/
+# https://docs.google.com/forms/d/1VdDdycNuqJVw3Ik6-ZLj6v7X9g2vWlw_RCC3RCfD9-I/viewform
+userDoc = "https://docs.google.com/spreadsheet/pub?key=0Al5UYaVoRpW3dE12bzRTVEp2RlJDQXdUYUFmODNiTHc&single=true&gid=0&output=csv";
 column = 'Provide a github username to the person whose blocks (gists) we should scan for d3 API usage'
 request.get userDoc, (err, response, body) ->
   d3.csv.parse body, (user) ->


graph: fixed wrong sorting

graph: fixed wrong sorting

--- server/lib/server/graph/fetch.coffee
+++ server/lib/server/graph/fetch.coffee
@@ -87,13 +87,14 @@
     return {}  if overview.length is 0

     overview = _.sortBy(overview, (activity)-> activity.createdAt.first)
-    allTimes = _.map(overview, (activity)-> activity.createdAt)
-    allTimes = _.flatten allTimes
-    sortedAllTimes = _.sortBy(allTimes, (activity)-> activity)

     # TODO: we're throwing away results if more than 20, ideally we'll only
     # get the right number of results
     overview = overview[-20..overview.length]
+
+    allTimes = _.map(overview, (activity)-> activity.createdAt)
+    allTimes = _.flatten allTimes
+    sortedAllTimes = _.sortBy(allTimes, (activity)-> activity)

     for activity, index in overview when activity.type is "CNewMemberBucketActivity"
       @newMemberBucketIndex = index


init notifier after stack

init notifier after stack

--- app/main.coffee
+++ app/main.coffee
@@ -18,9 +18,9 @@
 seasons = require './lib/seasons'
 TopBar = require 'zooniverse/controllers/top-bar'
 Footer = require 'zooniverse/controllers/footer'
+Notifier = require './lib/notifier'
 User = require 'zooniverse/models/user'
 googleAnalytics = require 'zooniverse/lib/google-analytics'
-Notifier = require('./lib/notifier').init()

 {Stack} = require 'spine/lib/manager'
 ContentPage = require './controllers/content_page'
@@ -89,6 +89,8 @@

 User.fetch()

+Notifier.init()
+
 app.topBar = new TopBar
 app.footer = new Footer


Update invalid JSON test for new test server

--- test/server.coffee
+++ test/server.coffee
@@ -39,9 +39,13 @@

 app.get '/test/json', (req, res) ->
   if /json/.test req.headers['accept']
-    res.json
-      query: req.query
-      hello: 'world'
+    if req.query.invalid
+      res.set 'Content-Type', 'application/json'
+      res.send 'invalidJSON'
+    else
+      res.json
+        query: req.query
+        hello: 'world'
   else
     res.send 400, 'FAIL'


testing 3

testing 3

--- test/server.coffee
+++ test/server.coffee
@@ -16,7 +16,7 @@
 Tower.View.loadPaths  = ["./test/example/app/views"]
 Tower.port            = 3001

-require '../lib/tower/server/generator/tst'
+require '../src/tower/server/generator/tst'

 Tower.requestOLD = (method, action, options, callback) ->
   if typeof options == "function"


fixing collides bounds

fixing collides bounds

--- src/bounded.coffee
+++ src/bounded.coffee
@@ -94,7 +94,7 @@
   @returns {Point} The position of this object
   ###
   collides: (bounds) ->
-    Collision.rectangular(I, bounds)
+    Collision.rectangular(self.bounds(), bounds)

   ###*
   This returns a modified bounds based on the collision margin.


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/bounded.coffee
+++ src/bounded.coffee
@@ -43,7 +43,7 @@
   ###*
   Distance between two objects. Proxies to Point.distance.
   In order for this to work, `otherObj` must have a
-  position
+  position method.

   player = Core


Update config.cson for Atom

Update config.cson for Atom

--- atom/config.cson
+++ atom/config.cson
@@ -41,6 +41,6 @@
     layoutMode: "Compact"
   "autocomplete-plus":
     enableAutoActivation: false
-".text.git-commit":
+".git-commit.text":
   editor:
     preferredLineLength: 72


cleanup

cleanup

--- test/zorium.coffee
+++ test/zorium.coffee
@@ -6,8 +6,6 @@
 Qs = require 'qs'

 z = require 'zorium'
-
-# TODO: batch redraws

 htmlToNode = (html) ->
   root = document.createElement 'div'


logCommandResult => logCommandResults

logCommandResult => logCommandResults

--- src/command.coffee
+++ src/command.coffee
@@ -52,7 +52,7 @@
     else
       process.stdout.write '\u2713\n'.green

-  logCommandResult: (callback, code, stderr='', stdout='') =>
+  logCommandResults: (callback, code, stderr='', stdout='') =>
     if code is 0
       @logSuccess()
       callback()


Fix tests if no collection

Fix tests if no collection

--- tests/index.coffee
+++ tests/index.coffee
@@ -48,10 +48,10 @@
   ]

   yield [
-    Test._collection().dropIndexes()
-    User._collection().dropIndexes()
-    Post._collection().dropIndexes()
-    MaybeID._collection().dropIndexes()
+    Test._collection()?.dropIndexes()
+    User._collection()?.dropIndexes()
+    Post._collection()?.dropIndexes()
+    MaybeID._collection()?.dropIndexes()
   ]


don't access model getters when changing class

--- src/compile.coffee
+++ src/compile.coffee
@@ -24,14 +24,14 @@
       controller[ast.value](node.element, model, e)

   class: (ast, node, model, controller) ->
-    update = ->
-      if model[ast.value]
+    set = (value) ->
+      if value
         node.boundClasses.push(ast.name) unless node.boundClasses.includes(ast.name)
       else
         node.boundClasses.delete(ast.name)
       node.updateClass()
-    update()
-    node.bindEvent(model["#{ast.value}_property"], update)
+    set(model[ast.value])
+    node.bindEvent(model["#{ast.value}_property"], (_, value) -> set(value))

   binding: (ast, node, model, controller) ->
     element = node.element


context.test returns child context

context.test returns child context

--- src/context.coffee
+++ src/context.coffee
@@ -3,6 +3,9 @@
 FSM = require "./minfinite"

 module.exports = class Context
+
+  on: (args...) ->
+    @emitter.on(args...)

   once: (args...) ->
     @emitter.once(args...)
@@ -170,6 +173,7 @@
     @children.push(child)
     @emitter.emit "child", child
     child._run()
+    child

   _run: (args...) ->


context: fix function binding

context: fix function binding

--- src/context.coffee
+++ src/context.coffee
@@ -27,16 +27,16 @@
     @INAPPLICABLE_MSG = 'SKIPPED'
     @toto = 'toto'
     @tmp = {}
-  run: (module) ->
+  run: (ctx, module) ->
     if typeof module is 'function'
-      module.call @, @
+      module.call ctx, @
     else
       throw new Error 'Only accept functions for now'
   context: (host, modules=[]) ->
     host_ctx = @hosts[host]
     modules = [modules] unless Array.isArray modules
     for module in modules
-      host_ctx.run module
+      host_ctx.run host_ctx, module
     host_ctx
   contexts: (query={}, modules=[]) ->
     query = modules: query if typeof query is 'string' or Array.isArray query


re-add making binaries executable.

re-add making binaries executable.

fixes what was originally broken in #996b517
because it was trying to do a for-loop with
a variable named file that didnt exist.

this doesnt even actually quite work yet because
of the copy function not having a callback. Soon™.

--- src/creator.coffee
+++ src/creator.coffee
@@ -63,12 +63,19 @@
       "package.json",
       "README.md",
       ".gitignore",
-      "bin/hubot",
-      "bin/hubot.cmd",
       "hubot-scripts.json",
       "external-scripts.json"
     ]

     @copy "#{@templateDir}/#{file}", "#{@path}/#{file}" for file in files

+    bins = [
+      "bin/hubot",
+      "bin/hubot.cmd"
+    ]
+
+    for bin in bins
+      @copy "#{@templateDir}/#{bin}", "#{@path}/#{bin}"
+      Fs.chmodSync "#{@path}/#{bin}", 0o755
+
 module.exports = Creator


Add missing continue

Add missing continue

--- src/grafana.coffee
+++ src/grafana.coffee
@@ -95,6 +95,7 @@
           #put imagesize stuff into its own dict
           if part.split('=')[0] of imagesize
             imagesize[part.split('=')[0]] = part.split('=')[1]
+            continue

           variables = "#{variables}&var-#{part}"
           template_params.push { "name": part.split('=')[0], "value": part.split('=')[1] }


Fix documentation formatting.

Fix documentation formatting.

--- src/grammar.coffee
+++ src/grammar.coffee
@@ -41,7 +41,7 @@
   #
   # @param input [Array<String>, String] A list of characters, or a string.
   # @return [String] A string representation of the object passed to the
-  #   method.
+  # method.
   #
   @_toString: (input) ->
     return input if toString.call(input) is '[object String]'
@@ -145,7 +145,7 @@
   # Statements.
   #
   # @return [Object] An object consisting of functions for handling various
-  #   types of statement.
+  # types of statement.
   #
   statement: ->
     return {
@@ -574,7 +574,7 @@
       #
       # @param line [Number] The line number where the invalid directive exists.
       # @param column [Number] The column number where the invalid directive
-      #   exists.
+      # exists.
       # @return [String] A message explaining the validity of the directive.
       #
       invalid: (line, column) ->


added scanline rasterization (slow), no z-buffering

--- src/js/main.coffee
+++ src/js/main.coffee
@@ -53,10 +53,10 @@
     index = ((x >> 0) + (y >> 0) * @canvas.width) * 4

     # RGBA color space is used by the HTML5 canvas
-    @backbufferdata[index + 0] = color.r * 255
-    @backbufferdata[index + 1] = color.g * 255
-    @backbufferdata[index + 2] = color.b * 255
-    @backbufferdata[index + 3] = color.a * 255
+    @backbufferdata[index + 0] = color[0] * 255
+    @backbufferdata[index + 1] = color[1] * 255
+    @backbufferdata[index + 2] = color[2] * 255
+    @backbufferdata[index + 3] = color[3] * 255

   # Project takes some 3D coordinates and transforms them in 2D
   # coordinates using the transformation matrix
@@ -78,11 +78,12 @@
     return Vec2.fromValues(x, y)

   # drawPoint calls putPixel but does the clipping operation before
-  drawPoint: (point) ->
+  drawPoint: (point, color) ->
+    color ||= Vec4.fromValues(1, 1, 1, 1)
     # Clipping what's visible on screen
     if 0 <= point[0] < @canvas.width && 0 <= point[1] < @canvas.height
       # draw white
-      @putPixel point[0], point[1], {r:1, g:1, b:1, a:1}
+      @putPixel point[0], point[1], color

   drawLine: (p0, p1) ->
     p0p1 = Vec2.subtract(Vec2.create(), p1, p0)
@@ -98,6 +99,7 @@
     @drawLine(p0, midPoint)
     @drawLine(midPoint, p1)

+  # http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
   drawBLine: (p0, p1) ->
     x0 = p0[0] >> 0
     y0 = p0[1] >> 0
@@ -119,6 +121,11 @@
         err += dx
         y0 += sy

+  drawScanLine: (x1, x2, y, color) ->
+    [x1, x2] = [x2, x1] if x1 > x2
+    for x in [(x1 | 0)..(x2 | 0)] by 1
+      @drawPoint(Vec2.fromValues(x, y), color)
+
   # The main method of the engine that recomputes each vertex
   # projection on every frame
   render: (camera, meshes) ->
@@ -150,16 +157,68 @@
       #   point1 = @project(mesh.vertices[i+1], transformMatrix)
       #   @drawLine(point0, point1)

-      for face in mesh.faces
+      ### Wireframe, Bresenham's ###
+      # for face in mesh.faces
+      #   vertexA = mesh.vertices[face[0]]
+      #   vertexB = mesh.vertices[face[1]]
+      #   vertexC = mesh.vertices[face[2]]
+      #   pixelA = @project(vertexA, transformMatrix)
+      #   pixelB = @project(vertexB, transformMatrix)
+      #   pixelC = @project(vertexC, transformMatrix)
+      #   @drawBLine(pixelA, pixelB)
+      #   @drawBLine(pixelB, pixelC)
+      #   @drawBLine(pixelC, pixelA)
+
+
+      for face, faceIndex in mesh.faces
         vertexA = mesh.vertices[face[0]]
         vertexB = mesh.vertices[face[1]]
         vertexC = mesh.vertices[face[2]]
         pixelA = @project(vertexA, transformMatrix)
         pixelB = @project(vertexB, transformMatrix)
         pixelC = @project(vertexC, transformMatrix)
-        @drawBLine(pixelA, pixelB)
-        @drawBLine(pixelB, pixelC)
-        @drawBLine(pixelC, pixelA)
+        grayVal = (faceIndex % mesh.faces.length) / mesh.faces.length
+        color = Vec4.fromValues(grayVal, grayVal, grayVal, 1)
+        @drawTriangle(pixelA, pixelB, pixelC, color)
+
+
+  _fillBottomFlatTriangle: (v1, v2, v3, color) ->
+    invSlope1 = (v2[0] - v1[0]) / (v2[1] - v1[1])
+    invSlope2 = (v3[0] - v1[0]) / (v3[1] - v1[1])
+    curx1 = v1[0]
+    curx2 = v1[0]
+    for scanlineY in [ v1[1] .. v2[1] ] by 1
+      @drawScanLine(curx1, curx2, scanlineY, color)
+      curx1 += invSlope1
+      curx2 += invSlope2
+
+  _fillTopFlatTriangle: (v1, v2, v3, color) ->
+    invSlope1 = (v3[0] - v1[0]) / (v3[1] - v1[1])
+    invSlope2 = (v3[0] - v2[0]) / (v3[1] - v2[1])
+    curx1 = v3[0]
+    curx2 = v3[0]
+    for scanlineY in [ v3[1] .. v1[1] ] by -1
+      @drawScanLine(curx1, curx2, scanlineY, color)
+      curx1 -= invSlope1
+      curx2 -= invSlope2
+
+  # http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html
+  drawTriangle: (v1, v2, v3, color) ->
+    # sort vertices by Y ascending (so v1 is topmost point)
+    [v1, v2] = [v2, v1] if v1[1] > v2[1]
+    [v2, v3] = [v3, v2] if v2[1] > v3[1]
+    [v1, v2] = [v2, v1] if v1[1] > v2[1]
+
+    if v1[1] == v2[1]
+      @_fillTopFlatTriangle(v1, v2, v3, color)
+    else if v2[1] == v3[1]
+      @_fillBottomFlatTriangle(v1, v2, v3, color)
+    else
+     # general case - split triangle into a top-flat and a bottom-flat
+     v4 = Vec2.fromValues(v1[0] + ((v2[1] - v1[1]) / (v3[1] - v1[1])) * (v3[0] - v1[0]), v2[1])
+     v4[0] = v4[0] | 0
+     @_fillBottomFlatTriangle(v1, v2, v4, color)
+     @_fillTopFlatTriangle(v2, v4, v3, color)

 canvas = document.getElementById('front-buffer')
@@ -169,14 +228,14 @@

 cubeMesh = new Mesh("Cube", 8, 12)
 cubeMesh.vertices = [
-  [ -1,  1,  1 ]
-  [  1,  1,  1 ]
-  [ -1, -1,  1 ]
-  [  1, -1,  1 ]
-  [ -1,  1, -1 ]
-  [  1,  1, -1 ]
-  [  1, -1, -1 ]
-  [ -1, -1, -1 ]
+  [ -10,  10,  10 ]
+  [  10,  10,  10 ]
+  [ -10, -10,  10 ]
+  [  10, -10,  10 ]
+  [ -10,  10, -10 ]
+  [  10,  10, -10 ]
+  [  10, -10, -10 ]
+  [ -10, -10, -10 ]
 ]
 cubeMesh.faces = [
   [ 0, 1, 2 ]


Fixed ROM ID generation on server.

Fixed ROM ID generation on server.

--- server/services/roms-service.coffee
+++ server/services/roms-service.coffee
@@ -7,10 +7,10 @@
     file[-4..].toLowerCase() is ".nes"

 getROMId = (file) ->
-    file.replace "'", ""
-        .replace /\s*-\s*/g, "-"
-        .replace /\s+/g, "-"
-        .replace /\.nes$/i, ""
+    file.replace /\.nes$/i, ""
+        .replace /[^a-zA-Z0-9]+/g, "-"
+        .replace /^-/, ""
+        .replace /-$/, ""
         .toLowerCase()

 getROMName = (file) ->
@@ -46,7 +46,9 @@
             romList.push { id: id, name: name, image: imageFile isnt null }
             romMap[id] = { file: file, imageFile: imageFile }

-        romList.sort (a, b) -> a.name.localeCompare b.name
+        romList.sort (a, b) ->
+            a.name.replace(/^The /i, "").localeCompare b.name.replace(/^The /i, "")
+
         @romList = romList
         @romMap = romMap
         console.log "Found #{@romList.length} ROMs"


Revert "Connect to ColumnDataSource.change slot instead of data property"

This reverts commit c8faa1db411c690c694f9ba2bb1cd98fddaeea05.

--- bokehjs/src/coffee/models/sources/cds_view.coffee
+++ bokehjs/src/coffee/models/sources/cds_view.coffee
@@ -27,12 +27,14 @@
       @compute_indices()
       @change.emit()
     )
-    if @source?.change?
-      @connect(@source.change, () -> @compute_indices())
     if @source?.streaming?
       @connect(@source.streaming, () -> @compute_indices())
     if @source?.patching?
       @connect(@source.patching, () -> @compute_indices())
+    if @source?
+      @connect(@source.properties.data.change, () ->
+        @compute_indices()
+      )

   compute_indices: () ->
     indices = (filter.compute_indices(@source) for filter in @filters)


Add spec for opening file to line number

--- spec/integration/startup-spec.coffee
+++ spec/integration/startup-spec.coffee
@@ -1,10 +1,10 @@
 # These tests are excluded by default. To run them from the command line:
 #
 # ATOM_INTEGRATION_TESTS_ENABLED=true apm test
-return unless process.env.ATOM_INTEGRATION_TESTS_ENABLED
+# return unless process.env.ATOM_INTEGRATION_TESTS_ENABLED
 # Integration tests require a fast machine and, for now, we cannot afford to
 # run them on Travis.
-return if process.env.TRAVIS
+# return if process.env.TRAVIS

 fs = require "fs"
 path = require "path"
@@ -41,21 +41,43 @@
           .then ({value}) -> expect(value).toBe "Hello!"
           .dispatchCommand("editor:delete-line")

-    it "removes all trailing whitespace and colons from the specified path", ->
-      runAtom [path.join(tempDirPath, "new-file:  ")], {ATOM_HOME: atomHome}, (client) ->
+    it "opens the parent directory and creates an empty text editor", ->
+      filePath = path.join(fs.realpathSync(tempDirPath), "new-file")
+      fs.writeFileSync filePath, """
+        1
+        2
+        3
+        4
+      """
+
+      runAtom ["#{filePath}:3"], {ATOM_HOME: atomHome}, (client) ->
         client
           .waitForWindowCount(1, 1000)
           .waitForExist("atom-workspace", 5000)
           .waitForPaneItemCount(1, 1000)
-
-          .treeViewRootDirectories()
-          .then ({value}) -> expect(value).toEqual([tempDirPath])
-
           .waitForExist("atom-text-editor", 5000)
           .then (exists) -> expect(exists).toBe true
-          .click("atom-text-editor")
+
           .execute -> atom.workspace.getActiveTextEditor().getPath()
-          .then ({value}) -> expect(value).toBe path.join(tempDirPath, "new-file")
+          .then ({value}) -> expect(value).toBe filePath
+
+          .execute -> atom.workspace.getActiveTextEditor().getCursorBufferPosition()
+          .then ({value}) ->
+            expect(value.row).toBe 2
+            expect(value.column).toBe 0
+
+    it "removes all trailing whitespace and colons from the specified path", ->
+      filePath = path.join(tempDirPath, "new-file")
+      runAtom ["#{filePath}:  "], {ATOM_HOME: atomHome}, (client) ->
+        client
+          .waitForWindowCount(1, 1000)
+          .waitForExist("atom-workspace", 5000)
+          .waitForPaneItemCount(1, 1000)
+          .waitForExist("atom-text-editor", 5000)
+          .then (exists) -> expect(exists).toBe true
+
+          .execute -> atom.workspace.getActiveTextEditor().getPath()
+          .then ({value}) -> expect(value).toBe filePath

   describe "when there is already a window open", ->
     it "reuses that window when opening files, but not when opening directories", ->


:memo: Convert EditorView docs

:memo: Convert EditorView docs

--- src/editor-view.coffee
+++ src/editor-view.coffee
@@ -10,7 +10,9 @@
 #
 # The EditorView manages the {Editor}, which manages the file buffers.
 #
-# ## Requiring in packages
+# ## Examples
+#
+# Requiring in packages
 #
 # ```coffee
 # {EditorView} = require 'atom'
@@ -18,14 +20,14 @@
 # miniEditorView = new EditorView(mini: true)
 # ```
 #
-# ## Iterating over the open editor views
+# Iterating over the open editor views
 #
 # ```coffee
 # for editorView in atom.workspaceView.getEditorViews()
 #   console.log(editorView.getModel().getPath())
 # ```
 #
-# ## Subscribing to every current and future editor
+# Subscribing to every current and future editor
 #
 # ```coffee
 # atom.workspace.eachEditorView (editorView) ->
@@ -67,7 +69,7 @@

   # The constructor for setting up an `EditorView` instance.
   #
-  # editorOrParams - Either an {Editor}, or an object with one property, `mini`.
+  # * `editorOrParams` Either an {Editor}, or an object with one property, `mini`.
   #                  If `mini` is `true`, a "miniature" `Editor` is constructed.
   #                  Typically, this is ideal for scenarios where you need an Atom editor,
   #                  but without all the chrome, like scrollbars, gutter, _e.t.c._.
@@ -125,7 +127,7 @@

   # Public: Get the underlying editor model for this view.
   #
-  # Returns an {Editor}.
+  # Returns an {Editor}
   getModel: -> @editor

   getEditor: -> @editor
@@ -173,17 +175,17 @@

   # Public: Scrolls the editor to the given screen position.
   #
-  # screenPosition - An object that represents a buffer position. It can be either
-  #                  an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
-  # options - A hash matching the options available to {::scrollToScreenPosition}
+  # * `screenPosition` An object that represents a buffer position. It can be either
+  #    an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
+  # * `options` (optional) {Object} matching the options available to {::scrollToScreenPosition}
   scrollToScreenPosition: (screenPosition, options) ->
     @editor.scrollToScreenPosition(screenPosition, options)

   # Public: Scrolls the editor to the given buffer position.
   #
-  # bufferPosition - An object that represents a buffer position. It can be either
-  #                  an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
-  # options - A hash matching the options available to {::scrollToBufferPosition}
+  # * `bufferPosition` An object that represents a buffer position. It can be either
+  #   an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
+  # * `options` (optional) {Object} matching the options available to {::scrollToBufferPosition}
   scrollToBufferPosition: (bufferPosition, options) ->
     @editor.scrollToBufferPosition(bufferPosition, options)

@@ -192,17 +194,17 @@

   # Public: Converts a buffer position to a pixel position.
   #
-  # position - An object that represents a buffer position. It can be either
-  #            an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
-  #
-  # Returns an object with two values: `top` and `left`, representing the pixel positions.
+  # * `bufferPosition` An object that represents a buffer position. It can be either
+  #   an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
+  #
+  # Returns an {Object} with two values: `top` and `left`, representing the pixel positions.
   pixelPositionForBufferPosition: (bufferPosition) ->
     @editor.pixelPositionForBufferPosition(bufferPosition)

   # Public: Converts a screen position to a pixel position.
   #
-  # position - An object that represents a screen position. It can be either
-  #            an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
+  # * `screenPosition` An object that represents a screen position. It can be either
+  #   an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
   #
   # Returns an object with two values: `top` and `left`, representing the pixel positions.
   pixelPositionForScreenPosition: (screenPosition) ->
@@ -290,7 +292,7 @@

   # Public: Sets the font family for the editor.
   #
-  # fontFamily - A {String} identifying the CSS `font-family`.
+  # * `fontFamily` A {String} identifying the CSS `font-family`.
   setFontFamily: (fontFamily) ->
     @component?.setFontFamily(fontFamily)

@@ -302,7 +304,7 @@

   # Public: Sets the font size for the editor.
   #
-  # fontSize - A {Number} indicating the font size in pixels.
+  # * `fontSize` A {Number} indicating the font size in pixels.
   setFontSize: (fontSize) ->
     @component?.setFontSize(fontSize)

@@ -313,27 +315,26 @@
   #
   # Calling this method has no effect when called on a mini editor.
   #
-  # lineHeight - A {Number} without a unit suffix identifying the CSS
-  # `line-height`.
+  # * `lineHeight` A {Number} without a unit suffix identifying the CSS `line-height`.
   setLineHeight: (lineHeight) ->
     @component.setLineHeight(lineHeight)

   # Public: Sets whether you want to show the indentation guides.
   #
-  # showIndentGuide - A {Boolean} you can set to `true` if you want to see the
-  #                   indentation guides.
+  # * `showIndentGuide` A {Boolean} you can set to `true` if you want to see the
+  #   indentation guides.
   setShowIndentGuide: (showIndentGuide) ->
     @component.setShowIndentGuide(showIndentGuide)

   # Public: Enables/disables soft wrap on the editor.
   #
-  # softWrap - A {Boolean} which, if `true`, enables soft wrap
+  # * `softWrap` A {Boolean} which, if `true`, enables soft wrap
   setSoftWrap: (softWrap) ->
     @editor.setSoftWrap(softWrap)

   # Public: Set whether invisible characters are shown.
   #
-  # showInvisibles - A {Boolean} which, if `true`, show invisible characters.
+  # * `showInvisibles` A {Boolean} which, if `true`, show invisible characters.
   setShowInvisibles: (showInvisibles) ->
     @component.setShowInvisibles(showInvisibles)

@@ -368,7 +369,7 @@
   #
   # This only affects mini editors.
   #
-  # placeholderText - A {String} of text to display when empty.
+  # * `placeholderText` A {String} of text to display when empty.
   setPlaceholderText: (placeholderText) ->
     if @component?
       @component.setProps({placeholderText})


Spy on shell.beep() to prevent an audible beep when specs run

--- spec/bookmarks-view-spec.coffee
+++ spec/bookmarks-view-spec.coffee
@@ -1,5 +1,6 @@
 RootView = require 'root-view'
 _ = require 'underscore'
+shell = require 'shell'

 describe "Bookmarks package", ->
   [editor, editSession, displayBuffer] = []
@@ -13,6 +14,7 @@
     editor = rootView.getActiveView()
     editSession = editor.activeEditSession
     displayBuffer = editSession.displayBuffer
+    spyOn(shell, 'beep')

   describe "toggling bookmarks", ->
     it "creates a marker when toggled", ->
@@ -55,9 +57,11 @@

       editor.trigger 'bookmarks:jump-to-next-bookmark'
       expect(editSession.getCursor().getBufferPosition()).toEqual [5, 10]
+      expect(shell.beep.callCount).toBe 1

       editor.trigger 'bookmarks:jump-to-previous-bookmark'
       expect(editSession.getCursor().getBufferPosition()).toEqual [5, 10]
+      expect(shell.beep.callCount).toBe 2

     describe "with one bookmark", ->
       beforeEach ->


Fix specs

Fix specs

--- spec/display-buffer-spec.coffee
+++ spec/display-buffer-spec.coffee
@@ -1048,13 +1048,13 @@

     it "can add decorations associated with markers and remove them", ->
       expect(decoration).toBeDefined()
-      expect(decoration.getParams()).toBe decoration
+      expect(decoration.getParams()).toBe decorationParams
       expect(displayBuffer.decorationForId(decoration.id)).toBe decoration
       expect(displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id][0]).toBe decoration

       decoration.destroy()
-      expect(displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id]).not.toBeDefined()
-      expect(displayBuffer.decorationForId(decoration.id)).not.toBeDefined()
+      expect(!!displayBuffer.decorationsForScreenRowRange(2, 3)[marker.id]).toBeFalsy()
+      expect(!!displayBuffer.decorationForId(decoration.id)).toBeFalsy()

     it "will not fail if the decoration is removed twice", ->
       decoration.destroy()


Fix leftover SettingsPanel test

Fix leftover SettingsPanel test

--- spec/settings-panel-spec.coffee
+++ spec/settings-panel-spec.coffee
@@ -85,7 +85,7 @@
       atom.config.setSchema("foo", config)
       atom.config.setDefaults("foo", gong: 'gong')
       expect(_.size(atom.config.get('foo'))).toBe 3
-      settingsPanel = new SettingsPanel("foo", {includeTitle: false})
+      settingsPanel = new SettingsPanel({namespace: "foo", includeTitle: false})

     it 'ensures default stays default', ->
       expect(settingsPanel.getDefault('foo.haz')).toBe 'haz'