Clean up grammars file

Clean up grammars file

This file is becoming unruly and difficult to maintain. This commit simplifies the code, reduces duplication and resolves a lot of inconsistency.

Signed-off-by: Daniel Bayley <a8999ec6105921a5e047cd21489d1a78436cfb40@me.com>

--- lib/grammars.coffee
+++ lib/grammars.coffee
@@ -1,976 +1,957 @@
 # Maps Atom Grammar names to the command used by that language
 # As well as any special setup for arguments.

+path = require 'path'
+{shell} = require 'electron'
 _ = require 'underscore'
-path = require 'path'
-GrammarUtils = require '../lib/grammar-utils'
-shell = require('electron').shell
+{OperatingSystem} = GrammarUtils = require '../lib/grammar-utils'
+
+os = OperatingSystem.platform()
+windows = OperatingSystem.isWindows()

 module.exports =
   '1C (BSL)':
     'File Based':
-      command: "oscript"
-      args: (context) -> ['-encoding=utf-8', context.filepath]
+      command: 'oscript'
+      args: ({filepath}) -> ['-encoding=utf-8', filepath]

   Ansible:
-    "File Based":
-      command: "ansible-playbook"
+    'File Based':
+      command: 'ansible-playbook'
+      args: ({filepath}) -> [filepath]
+
+  AppleScript:
+    'Selection Based':
+      command: 'osascript'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'osascript'
+      args: ({filepath}) -> [filepath]
+
+  AutoHotKey:
+    'Selection Based':
+      command: 'AutoHotKey'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'AutoHotKey'
+      args: ({filepath}) -> [filepath]
+
+  'Babel ES6 JavaScript':
+    'Selection Based':
+      command: 'babel-node'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'babel-node'
       args: (context) -> [context.filepath]

-  AppleScript:
-    'Selection Based':
-      command: 'osascript'
-      args: (context)  -> ['-e', context.getCode()]
-    'File Based':
-      command: 'osascript'
-      args: (context) -> [context.filepath]
-
-  AutoHotKey:
-    "File Based":
-      command: "AutoHotKey"
-      args: (context) -> [context.filepath]
-    "Selection Based":
-      command: "AutoHotKey"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-
-  'Babel ES6 JavaScript':
-    "Selection Based":
-      command: "babel-node"
-      args: (context) -> ['-e', context.getCode()]
-    "File Based":
-      command: "babel-node"
-      args: (context) -> [context.filepath]
-
   'Bash Automated Test System (Bats)':
-    "File Based":
-      command: "bats"
-      args: (context) -> [context.filepath]
-    "Selection Based":
+    'Selection Based':
       command: 'bats'
       args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'bats'
+      args: ({filepath}) -> [filepath]

   Batch:
-    "File Based":
-      command: "cmd.exe"
-      args: (context) -> ['/q', '/c', context.filepath]
+    'File Based':
+      command: 'cmd.exe'
+      args: ({filepath}) -> ['/q', '/c', filepath]

   'Behat Feature':
-    "File Based":
-      command: "behat"
-      args: (context) -> [context.filepath]
-    "Line Number Based":
-      command: "behat"
+    'File Based':
+      command: 'behat'
+      args: ({filepath}) -> [filepath]
+    'Line Number Based':
+      command: 'behat'
       args: (context) -> [context.fileColonLine()]

   BuckleScript:
-    "Selection Based":
-      command: "bsc"
-      args: (context) ->
-        code = context.getCode()
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        ['-c', tmpFile]
-    "File Based":
-      command: "bsc"
-      args: (context) -> ['-c', context.filepath]
+    'Selection Based':
+      command: 'bsc'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return ['-c', tmpFile]
+    'File Based':
+      command: 'bsc'
+      args: ({filepath}) -> ['-c', filepath]

   C:
-    "File Based":
-      command: "bash"
-      args: (context) ->
-        args = []
-        if GrammarUtils.OperatingSystem.isDarwin()
-          args = ['-c', "xcrun clang -fcolor-diagnostics -Wall -include stdio.h '" + context.filepath + "' -o /tmp/c.out && /tmp/c.out"]
-        else if GrammarUtils.OperatingSystem.isLinux()
-          args = ["-c", "cc -Wall -include stdio.h '" + context.filepath + "' -o /tmp/c.out && /tmp/c.out"]
-        return args
-    "Selection Based":
-      command: "bash"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".c")
-        args = []
-        if GrammarUtils.OperatingSystem.isDarwin()
-          args = ['-c', "xcrun clang -fcolor-diagnostics -Wall -include stdio.h '" + tmpFile + "' -o /tmp/c.out && /tmp/c.out"]
-        else if GrammarUtils.OperatingSystem.isLinux()
-          args = ["-c", "cc -Wall -include stdio.h '" + tmpFile + "' -o /tmp/c.out && /tmp/c.out"]
-        return args
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) ->
+        args = switch os
+          when 'darwin'
+            "xcrun clang -fcolor-diagnostics -Wall -include stdio.h '#{filepath}' -o /tmp/c.out && /tmp/c.out"
+          when 'linux'
+            "cc -Wall -include stdio.h '#{filepath}' -o /tmp/c.out && /tmp/c.out"
+        return ['-c', args]
+
+    'Selection Based':
+      command: 'bash'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.c')
+        args = switch os
+          when 'darwin'
+            "xcrun clang -fcolor-diagnostics -Wall -include stdio.h #{tmpFile} -o /tmp/c.out && /tmp/c.out"
+          when 'linux'
+            "cc -Wall -include stdio.h #{tmpFile} -o /tmp/c.out && /tmp/c.out"
+        return ['-c', args]

   'C#':
-    "File Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "cmd" else "bash"
-      args: (context) ->
-        progname = context.filename.replace /\.cs$/, ""
-        args = []
-        if GrammarUtils.OperatingSystem.isWindows()
-          args = ["/c csc #{context.filepath} && #{progname}.exe"]
-        else
-          args = ['-c', "csc #{context.filepath} && mono #{progname}.exe"]
-        return args
-    "Selection Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "cmd" else "bash"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".cs")
-        progname = tmpFile.replace /\.cs$/, ""
-        args = []
-        if GrammarUtils.OperatingSystem.isWindows()
-          args = ["/c csc /out:#{progname}.exe #{tmpFile} && #{progname}.exe"]
-        else
-          args = ['-c', "csc /out:#{progname}.exe #{tmpFile} && mono #{progname}.exe"]
-        return args
+    'Selection Based':
+      command: if windows then 'cmd' else 'bash'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.cs')
+        progname = tmpFile.replace /\.cs$/, ''
+        if windows
+          return ["/c csc /out:#{progname}.exe #{tmpFile} && #{progname}.exe"]
+        else ['-c', "csc /out:#{progname}.exe #{tmpFile} && mono #{progname}.exe"]
+
+    'File Based':
+      command: if windows then 'cmd' else 'bash'
+      args: ({filepath, filename}) ->
+        progname = filename.replace /\.cs$/, ''
+        if windows
+          return ["/c csc #{filepath} && #{progname}.exe"]
+        else ['-c', "csc '#{filepath}' && mono #{progname}.exe"]

   'C# Script File':
-    "File Based":
-      command: "scriptcs"
-      args: (context) -> ['-script', context.filepath]
-    "Selection Based":
-      command: "scriptcs"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".csx")
-        ['-script', tmpFile]
+    'Selection Based':
+      command: 'scriptcs'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.csx')
+        return ['-script', tmpFile]
+    'File Based':
+      command: 'scriptcs'
+      args: ({filepath}) -> ['-script', filepath]

   'C++':
-    if GrammarUtils.OperatingSystem.isDarwin()
-      "Selection Based":
-        command: "bash"
-        args: (context) ->
-          code = context.getCode(true)
-          tmpFile = GrammarUtils.createTempFileWithCode(code, ".cpp")
-          ["-c", "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream '" + tmpFile + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-      "File Based":
-        command: "bash"
-        args: (context) -> ['-c', "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream '" + context.filepath + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-    else if GrammarUtils.OperatingSystem.isLinux()
-      "Selection Based":
-        command: "bash"
-        args: (context) ->
-          code = context.getCode(true)
-          tmpFile = GrammarUtils.createTempFileWithCode(code, ".cpp")
-          ["-c", "g++ -std=c++14 -Wall -include stdio.h -include iostream '" + tmpFile + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-      "File Based":
-        command: "bash"
-        args: (context) -> ["-c", "g++ -std=c++14 -Wall -include stdio.h -include iostream '" + context.filepath + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-    else if GrammarUtils.OperatingSystem.isWindows() and GrammarUtils.OperatingSystem.release().split(".").slice -1 >= '14399'
-      "File Based":
-        command: "bash"
-        args: (context) -> ["-c", "g++ -std=c++14 -Wall -include stdio.h -include iostream '/mnt/" + path.posix.join.apply(path.posix, [].concat([context.filepath.split(path.win32.sep)[0].toLowerCase()], context.filepath.split(path.win32.sep).slice(1))).replace(":", "") + "' -o /tmp/cpp.out && /tmp/cpp.out"]
+    'Selection Based':
+      command: 'bash'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.cpp')
+        args = switch os
+          when 'darwin'
+            "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream #{tmpFile} -o /tmp/cpp.out && /tmp/cpp.out"
+          when 'linux'
+            "g++ -std=c++14 -Wall -include stdio.h -include iostream #{tmpFile} -o /tmp/cpp.out && /tmp/cpp.out"
+        return ['-c', args]
+
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) ->
+        args = switch os
+          when 'darwin'
+            "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream '#{filepath}' -o /tmp/cpp.out && /tmp/cpp.out"
+          when 'linux'
+            "g++ -std=c++14 -Wall -include stdio.h -include iostream '#{filepath}' -o /tmp/cpp.out && /tmp/cpp.out"
+          when 'win32'
+            if GrammarUtils.OperatingSystem.release().split('.').slice -1 >= '14399'
+              filepath = path.posix.join.apply(path.posix, [].concat([filepath.split(path.win32.sep)[0].toLowerCase()], filepath.split(path.win32.sep).slice(1))).replace(':', '')
+              "g++ -std=c++14 -Wall -include stdio.h -include iostream '/mnt/#{filepath}' -o /tmp/cpp.out && /tmp/cpp.out"
+        return ['-c', args]

   'C++14':
-    if GrammarUtils.OperatingSystem.isDarwin()
-      "Selection Based":
-        command: "bash"
-        args: (context) ->
-          code = context.getCode(true)
-          tmpFile = GrammarUtils.createTempFileWithCode(code, ".cpp")
-          ["-c", "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream '" + tmpFile + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-      "File Based":
-        command: "bash"
-        args: (context) -> ['-c', "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream '" + context.filepath + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-    else if GrammarUtils.OperatingSystem.isLinux()
-      "Selection Based":
-        command: "bash"
-        args: (context) ->
-          code = context.getCode(true)
-          tmpFile = GrammarUtils.createTempFileWithCode(code, ".cpp")
-          ["-c", "g++ -std=c++14 -Wall -include stdio.h -include iostream '" + tmpFile + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-      "File Based":
-        command: "bash"
-        args: (context) -> ["-c", "g++ -std=c++14 -Wall -include stdio.h -include iostream '" + context.filepath + "' -o /tmp/cpp.out && /tmp/cpp.out"]
-    else if GrammarUtils.OperatingSystem.isWindows() and GrammarUtils.OperatingSystem.release().split(".").slice -1 >= '14399'
-      "File Based":
-        command: "bash"
-        args: (context) -> ["-c", "g++ -std=c++14 -Wall -include stdio.h -include iostream '/mnt/" + path.posix.join.apply(path.posix, [].concat([context.filepath.split(path.win32.sep)[0].toLowerCase()], context.filepath.split(path.win32.sep).slice(1))).replace(":", "") + "' -o /tmp/cpp.out && /tmp/cpp.out"]
+    'Selection Based':
+      command: 'bash'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.cpp')
+        args = switch os
+          when 'darwin'
+            "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream #{tmpFile} -o /tmp/cpp.out && /tmp/cpp.out"
+          when 'linux'
+            "g++ -std=c++14 -Wall -include stdio.h -include iostream #{tmpFile} -o /tmp/cpp.out && /tmp/cpp.out"
+        return ['-c', args]
+
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) ->
+        args = switch os
+          when 'darwin'
+            "xcrun clang++ -fcolor-diagnostics -std=c++14 -Wall -include stdio.h -include iostream '#{filepath}' -o /tmp/cpp.out && /tmp/cpp.out"
+          when 'linux'
+            "g++ -std=c++14 -Wall -include stdio.h -include iostream '#{filepath}' -o /tmp/cpp.out && /tmp/cpp.out"
+          when 'win32'
+            if GrammarUtils.OperatingSystem.release().split('.').slice -1 >= '14399'
+              filepath = path.posix.join.apply(path.posix, [].concat([filepath.split(path.win32.sep)[0].toLowerCase()], filepath.split(path.win32.sep).slice(1))).replace(':', '')
+              "g++ -std=c++14 -Wall -include stdio.h -include iostream '/mnt/#{filepath}' -o /tmp/cpp.out && /tmp/cpp.out"
+        return ['-c', args]

   Clojure:
-    "Selection Based":
-      command: "lein"
-      args: (context)  -> ['exec', '-e', context.getCode()]
-    "File Based":
-      command: "lein"
-      args: (context) -> ['exec', context.filepath]
+    'Selection Based':
+      command: 'lein'
+      args: (context) -> ['exec', '-e', context.getCode()]
+    'File Based':
+      command: 'lein'
+      args: ({filepath}) -> ['exec', filepath]

   CoffeeScript:
-    "Selection Based":
-      command: "coffee"
+    'Selection Based':
+      command: 'coffee'
       args: (context) -> ['--transpile', '-e', context.getCode()]
-    "File Based":
-      command: "coffee"
-      args: (context) -> ['-t', context.filepath]
-
-  "CoffeeScript (Literate)":
+    'File Based':
+      command: 'coffee'
+      args: ({filepath}) -> ['-t', filepath]
+
+  'CoffeeScript (Literate)':
     'Selection Based':
       command: 'coffee'
       args: (context) -> ['-t', '-e', context.getCode()]
     'File Based':
       command: 'coffee'
-      args: (context) -> ['-t', context.filepath]
-
-  "Common Lisp":
-    "File Based":
-      command: "clisp"
-      args: (context) -> [context.filepath]
+      args: ({filepath}) -> ['-t', filepath]
+
+  'Common Lisp':
+    'File Based':
+      command: 'clisp'
+      args: ({filepath}) -> [filepath]

   Crystal:
-    "Selection Based":
-      command: "crystal"
-      args: (context)  -> ['eval', context.getCode()]
-    "File Based":
-      command: "crystal"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'crystal'
+      args: (context) -> ['eval', context.getCode()]
+    'File Based':
+      command: 'crystal'
+      args: ({filepath}) -> [filepath]

   D:
-    "Selection Based":
-      command: "rdmd"
-      args: (context)  ->
-        code = context.getCode(true)
+    'Selection Based':
+      command: 'rdmd'
+      args: (context) ->
+        code = context.getCode()
         tmpFile = GrammarUtils.D.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "rdmd"
-      args: (context) -> [context.filepath]
+        return [tmpFile]
+    'File Based':
+      command: 'rdmd'
+      args: ({filepath}) -> [filepath]

   Dart:
-    "Selection Based":
-      command: "dart"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".dart")
-        [tmpFile]
-    "File Based":
-      command: "dart"
-      args: (context) -> [context.filepath]
-
-  "Graphviz (DOT)":
-    "Selection Based":
-      command: "dot"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".dot")
+    'Selection Based':
+      command: 'dart'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.dart')
+        return [tmpFile]
+    'File Based':
+      command: 'dart'
+      args: ({filepath}) -> [filepath]
+
+  DOT:
+    'Selection Based':
+      command: 'dot'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.dot')
         ['-Tpng', tmpFile, '-o', tmpFile + '.png']
-    "File Based":
-      command: "dot"
-      args: (context) -> ['-Tpng', context.filepath, '-o', context.filepath + '.png']
-  DOT:
-    "Selection Based":
-      command: "dot"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".dot")
-        ['-Tpng', tmpFile, '-o', tmpFile + '.png']
-    "File Based":
-      command: "dot"
-      args: (context) -> ['-Tpng', context.filepath, '-o', context.filepath + '.png']
+    'File Based':
+      command: 'dot'
+      args: ({filepath}) -> ['-Tpng', filepath, '-o', filepath + '.png']

   Elixir:
-    "Selection Based":
-      command: "elixir"
+    'Selection Based':
+      command: 'elixir'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'elixir'
+      args: ({filepath}) -> ['-r', filepath]
+
+  Erlang:
+    'Selection Based':
+      command: 'erl'
+      args: (context) -> ['-noshell', '-eval', "#{context.getCode()}, init:stop()."]
+
+  'F*':
+    'File Based':
+      command: 'fstar'
+      args: ({filepath}) -> [filepath]
+
+  'F#':
+    'File Based':
+      command: if windows then 'fsi' else 'fsharpi'
+      args: ({filepath}) -> ['--exec', filepath]
+
+  Fable:
+    'Selection Based':
+      command: 'fable'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'fable'
+      args: ({filepath}) -> [filepath]
+
+  Forth:
+    'File Based':
+      command: 'gforth'
+      args: ({filepath}) -> [filepath]
+
+  'Fortran - Fixed Form':
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) -> ['-c', "gfortran '#{filepath}' -ffixed-form -o /tmp/f.out && /tmp/f.out"]
+
+  'Fortran - Free Form':
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) -> ['-c', "gfortran '#{filepath}' -ffree-form -o /tmp/f90.out && /tmp/f90.out"]
+
+  'Fortran - Modern':
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) -> ['-c', "gfortran '#{filepath}' -ffree-form -o /tmp/f90.out && /tmp/f90.out"]
+
+  'Fortran - Punchcard':
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) -> ['-c', "gfortran '#{filepath}' -ffixed-form -o /tmp/f.out && /tmp/f.out"]
+
+  'Free Pascal':
+    'Selection Based':
+      command: 'fsc'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'fsc'
+      args: ({filepath}) -> [filepath]
+
+  Gherkin:
+    'File Based':
+      command: 'cucumber'
+      args: ({filepath}) -> ['--color', filepath]
+    'Line Number Based':
+      command: 'cucumber'
+      args: (context) -> ['--color', context.fileColonLine()]
+
+  gnuplot:
+    'File Based':
+      command: 'gnuplot'
+      workingDirectory: atom.workspace.getActivePaneItem()?.buffer?.file?.getParent?().getPath?()
+      args: ({filepath}) -> ['-p', filepath]
+
+  Go:
+    'File Based':
+      command: 'go'
+      workingDirectory: atom.workspace.getActivePaneItem()?.buffer?.file?.getParent?().getPath?()
+      args: ({filepath}) ->
+        if filepath.match(/_test.go/) then ['test', '']
+        else ['run', filepath]
+
+  'Graphviz (DOT)':
+    'Selection Based':
+      command: 'dot'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.dot')
+        return ['-Tpng', tmpFile, '-o', tmpFile + '.png']
+    'File Based':
+      command: 'dot'
+      args: ({filepath}) -> ['-Tpng', filepath, '-o', filepath + '.png']
+
+  Groovy:
+    'Selection Based':
+      command: 'groovy'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'groovy'
+      args: ({filepath}) -> [filepath]
+
+  Haskell:
+    'Selection Based':
+      command: 'ghc'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'runhaskell'
+      args: ({filepath}) -> [filepath]
+
+  HTML:
+    'File Based':
+      command: 'echo'
+      args: ({filepath}) ->
+        uri = 'file://' + filepath
+        shell.openExternal(uri)
+        return ['HTML file opened at:', uri]
+
+  Hy:
+    'Selection Based':
+      command: 'hy'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.hy')
+        return [tmpFile]
+    'File Based':
+      command: 'hy'
+      args: ({filepath}) -> [filepath]
+
+  IcedCoffeeScript:
+    'Selection Based':
+      command: 'iced'
       args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "elixir"
-      args: (context) -> ['-r', context.filepath]
-
-  Erlang:
-    "Selection Based":
-      command: "erl"
-      args: (context)  -> ['-noshell', '-eval', "#{context.getCode()}, init:stop()."]
-
-  'F#':
-    "File Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "fsi" else "fsharpi"
-      args: (context) -> ['--exec', context.filepath]
-
-  'F*':
-    "File Based":
-      command: "fstar"
-      args: (context) -> [context.filepath]
-
-  Fable:
-    "Selection Based":
-      command: "fable"
-      args: (context) ->
-        code = context.getCode()
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "fable"
-      args: (context) -> [context.filepath]
-
-  Forth:
-    "File Based":
-      command: "gforth"
-      args: (context) -> [context.filepath]
-
-  "Fortran - Fixed Form":
-    "File Based":
-      command: "bash"
-      args: (context) -> ['-c', "gfortran '" + context.filepath + "' -ffixed-form -o /tmp/f.out && /tmp/f.out"]
-
-  "Fortran - Free Form":
-    "File Based":
-      command: "bash"
-      args: (context) -> ['-c', "gfortran '" + context.filepath + "' -ffree-form -o /tmp/f90.out && /tmp/f90.out"]
-
-  "Fortran - Modern":
-    "File Based":
-      command: "bash"
-      args: (context) -> ['-c', "gfortran '" + context.filepath + "' -ffree-form -o /tmp/f90.out && /tmp/f90.out"]
-
-  "Fortran - Punchcard":
-    "File Based":
-      command: "bash"
-      args: (context) -> ['-c', "gfortran '" + context.filepath + "' -ffixed-form -o /tmp/f.out && /tmp/f.out"]
-
-  "Free Pascal":
-    "Selection Based":
-      command: "fsc"
-      args: (context) ->
-        code = context.getCode()
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "fsc"
-      args: (context) -> [context.filepath]
-
-  Gherkin:
-    "File Based":
-      command: "cucumber"
-      args: (context) -> ['--color', context.filepath]
-    "Line Number Based":
-      command: "cucumber"
-      args: (context) -> ['--color', context.fileColonLine()]
-
-  gnuplot:
-    "File Based":
-      command: "gnuplot"
-      args: (context) -> ['-p', context.filepath]
-      workingDirectory: atom.workspace.getActivePaneItem()?.buffer?.file?.getParent?().getPath?()
-
-  Go:
-    "File Based":
-      command: "go"
-      args: (context) ->
-        if context.filepath.match(/_test.go/) then ['test', '' ]
-        else ['run', context.filepath]
-      workingDirectory: atom.workspace.getActivePaneItem()?.buffer?.file?.getParent?().getPath?()
-
-  Groovy:
-    "Selection Based":
-      command: "groovy"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "groovy"
-      args: (context) -> [context.filepath]
-
-  Haskell:
-    "File Based":
-      command: "runhaskell"
-      args: (context) -> [context.filepath]
-    "Selection Based":
-      command: "ghc"
-      args: (context)  -> ['-e', context.getCode()]
-
-  Hy:
-    "File Based":
-      command: "hy"
-      args: (context) -> [context.filepath]
-    "Selection Based":
-      command: "hy"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".hy")
-        [tmpFile]
-
-  IcedCoffeeScript:
-    "Selection Based":
-      command: "iced"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "iced"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'iced'
+      args: ({filepath}) -> [filepath]

   Idris:
-    "File Based":
-      command: "idris"
-      args: (context) -> [context.filepath, '-o', path.basename(context.filepath, path.extname(context.filepath))]
+    'File Based':
+      command: 'idris'
+      args: ({filepath}) -> [filepath, '-o', path.basename(filepath, path.extname(filepath))]

   InnoSetup:
-    "File Based":
-      command: "ISCC.exe"
-      args: (context) -> ['/Q', context.filepath]
+    'File Based':
+      command: 'ISCC.exe'
+      args: ({filepath}) -> ['/Q', filepath]

   ioLanguage:
-    "Selection Based":
-      command: "io"
+    'Selection Based':
+      command: 'io'
       args: (context) -> [context.getCode()]
-    "File Based":
-      command: "io"
-      args: (context) -> ['-e', context.filepath]
+    'File Based':
+      command: 'io'
+      args: ({filepath}) -> ['-e', filepath]

   Java:
-    "File Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "cmd" else "bash"
+    'File Based':
+      command: if windows then 'cmd' else 'bash'
       args: (context) ->
         className = GrammarUtils.Java.getClassName context
         classPackages = GrammarUtils.Java.getClassPackage context
         sourcePath = GrammarUtils.Java.getProjectPath context
-
-        args = []
-        if GrammarUtils.OperatingSystem.isWindows()
-          args = ["/c javac -Xlint #{context.filename} && java #{className}"]
-        else
-          args = ['-c', "javac -sourcepath #{sourcePath} -d /tmp '#{context.filepath}' && java -cp /tmp #{classPackages}#{className}"]
-
-        return args
+        if windows
+          return ["/c javac -Xlint '#{context.filename}' && java #{className}"]
+        else ['-c', "javac -sourcepath #{sourcePath} -d /tmp '#{context.filepath}' && java -cp /tmp #{classPackages}#{className}"]

   JavaScript:
-    "Selection Based":
-      command: "babel-node"
+    'Selection Based':
+      command: 'babel-node'
       args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "babel-node"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'babel-node'
+      args: ({filepath}) -> [filepath]
+
+  'JavaScript for Automation (JXA)':
+    'Selection Based':
+      command: 'osascript'
+      args: (context)  -> ['-l', 'JavaScript', '-e', context.getCode()]
+    'File Based':
+      command: 'osascript'
+      args: ({filepath}) -> ['-l', 'JavaScript', filepath]

   'JavaScript with JSX':
-    "Selection Based":
-      command: "babel-node"
+    'Selection Based':
+      command: 'babel-node'
       args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "babel-node"
-      args: (context) -> [context.filepath]
-
-  "JavaScript for Automation (JXA)":
-    "Selection Based":
-      command: "osascript"
-      args: (context)  -> ['-l', 'JavaScript', '-e', context.getCode()]
-    "File Based":
-      command: "osascript"
-      args: (context) -> ['-l', 'JavaScript', context.filepath]
+    'File Based':
+      command: 'babel-node'
+      args: ({filepath}) -> [filepath]

   Jolie:
-    "File Based":
-      command: "jolie"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'jolie'
+      args: ({filepath}) -> [filepath]

   Julia:
-    "Selection Based":
-      command: "julia"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "julia"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'julia'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'julia'
+      args: ({filepath}) -> [filepath]

   Kotlin:
-    "Selection Based":
-      command: "bash"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".kt")
-        jarName = tmpFile.replace /\.kt$/, ".jar"
-        args = ['-c', "kotlinc #{tmpFile} -include-runtime -d #{jarName} && java -jar #{jarName}"]
-        return args
-    "File Based":
-      command: "bash"
-      args: (context) ->
-        jarName = context.filename.replace /\.kt$/, ".jar"
-        args = ['-c', "kotlinc #{context.filepath} -include-runtime -d /tmp/#{jarName} && java -jar /tmp/#{jarName}"]
-        return args
+    'Selection Based':
+      command: 'bash'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.kt')
+        jarName = tmpFile.replace /\.kt$/, '.jar'
+        return ['-c', "kotlinc #{tmpFile} -include-runtime -d #{jarName} && java -jar #{jarName}"]
+    'File Based':
+      command: 'bash'
+      args: ({filepath, filename}) ->
+        jarName = filename.replace /\.kt$/, '.jar'
+        return ['-c', "kotlinc '#{filepath}' -include-runtime -d /tmp/#{jarName} && java -jar /tmp/#{jarName}"]

   LAMMPS:
-    if GrammarUtils.OperatingSystem.isDarwin() || GrammarUtils.OperatingSystem.isLinux()
-      "File Based":
-        command: "lammps"
-        args: (context) -> ['-log', 'none', '-in', context.filepath]
+    if os in ['darwin', 'linux']
+      'File Based':
+        command: 'lammps'
+        args: ({filepath}) -> ['-log', 'none', '-in', filepath]

   LaTeX:
-    "File Based":
-      command: "latexmk"
-      args: (context) -> ['-cd', '-quiet', '-pdf', '-pv', '-shell-escape', context.filepath]
+    'File Based':
+      command: 'latexmk'
+      args: ({filepath}) -> ['-cd', '-quiet', '-pdf', '-pv', '-shell-escape', filepath]

   'LaTeX Beamer':
-    "File Based":
-      command: "latexmk"
-      args: (context) -> ['-cd', '-quiet', '-pdf', '-pv', '-shell-escape', context.filepath]
+    'File Based':
+      command: 'latexmk'
+      args: ({filepath}) -> ['-cd', '-quiet', '-pdf', '-pv', '-shell-escape', filepath]

   LilyPond:
-    "File Based":
-      command: "lilypond"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'lilypond'
+      args: ({filepath}) -> [filepath]

   Lisp:
-    "Selection Based":
-      command: "sbcl"
+    'Selection Based':
+      command: 'sbcl'
       args: (context) ->
         statements = _.flatten(_.map(GrammarUtils.Lisp.splitStatements(context.getCode()), (statement) -> ['--eval', statement]))
-        args = _.union ['--noinform', '--disable-debugger', '--non-interactive', '--quit'], statements
-        return args
-    "File Based":
-      command: "sbcl"
-      args: (context) -> ['--noinform', '--script', context.filepath]
+        return _.union ['--noinform', '--disable-debugger', '--non-interactive', '--quit'], statements
+    'File Based':
+      command: 'sbcl'
+      args: ({filepath}) -> ['--noinform', '--script', filepath]

   'Literate Haskell':
-    "File Based":
-      command: "runhaskell"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'runhaskell'
+      args: ({filepath}) -> [filepath]

   LiveScript:
-    "Selection Based":
-      command: "lsc"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "lsc"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'lsc'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'lsc'
+      args: ({filepath}) -> [filepath]

   Lua:
-    "Selection Based":
-      command: "lua"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "lua"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'lua'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'lua'
+      args: ({filepath}) -> [filepath]

   'Lua (WoW)':
-    "Selection Based":
-      command: "lua"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "lua"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'lua'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'lua'
+      args: ({filepath}) -> [filepath]
+
+  MagicPython:
+    'Selection Based':
+      command: 'python'
+      args: (context) -> ['-u', '-c', context.getCode()]
+    'File Based':
+      command: 'python'
+      args: ({filepath}) -> ['-u', filepath]

   Makefile:
-    "Selection Based":
-      command: "bash"
+    'Selection Based':
+      command: 'bash'
       args: (context) -> ['-c', context.getCode()]
-    "File Based":
-      command: "make"
-      args: (context) -> ['-f', context.filepath]
-
-  MagicPython:
-    "Selection Based":
-      command: "python"
-      args: (context)  -> ['-u', '-c', context.getCode()]
-    "File Based":
-      command: "python"
-      args: (context) -> ['-u', context.filepath]
+    'File Based':
+      command: 'make'
+      args: ({filepath}) -> ['-f', filepath]

   MATLAB:
-    "Selection Based":
-      command: "matlab"
+    'Selection Based':
+      command: 'matlab'
       args: (context) ->
         code = context.getCode()
         tmpFile = GrammarUtils.MATLAB.createTempFileWithCode(code)
-        ['-nodesktop','-nosplash','-r',"try, run('" + tmpFile + "');while ~isempty(get(0,'Children')); pause(0.5); end; catch ME; disp(ME.message); exit(1); end; exit(0);"]
-    "File Based":
-      command: "matlab"
-      args: (context) -> ['-nodesktop','-nosplash','-r',"try run('" + context.filepath + "');while ~isempty(get(0,'Children')); pause(0.5); end; catch ME; disp(ME.message); exit(1); end; exit(0);"]
+        return ['-nodesktop', '-nosplash', '-r', "try, run('#{tmpFile}');while ~isempty(get(0,'Children')); pause(0.5); end; catch ME; disp(ME.message); exit(1); end; exit(0);"]
+    'File Based':
+      command: 'matlab'
+      args: ({filepath}) -> ['-nodesktop', '-nosplash', '-r', "try run('#{filepath}');while ~isempty(get(0,'Children')); pause(0.5); end; catch ME; disp(ME.message); exit(1); end; exit(0);"]

   'MIPS Assembler':
-    "File Based":
-      command: "spim"
-      args: (context) -> ['-f', context.filepath]
+    'File Based':
+      command: 'spim'
+      args: ({filepath}) -> ['-f', filepath]
+
+  'mongoDB (JavaScript)':
+    'Selection Based':
+      command: 'mongo'
+      args: (context) -> ['--eval', context.getCode()]
+    'File Based':
+      command:  'mongo'
+      args: ({filepath}) -> [filepath]

   MoonScript:
-    "Selection Based":
-      command: "moon"
-      args: (context) -> ['-e', context.getCode()]
-    "File Based":
-      command: "moon"
-      args: (context) -> [context.filepath]
-
-  'mongoDB (JavaScript)':
-    "Selection Based":
-      command: "mongo"
-      args: (context) -> ['--eval', context.getCode()]
-    "File Based":
-      command:  "mongo"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'moon'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'moon'
+      args: ({filepath}) -> [filepath]

   NCL:
-    "Selection Based":
-      command: "ncl"
-      args: (context) ->
-        code = context.getCode(true)
-        code = code + """
-
-        exit"""
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "ncl"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'ncl'
+      args: (context) ->
+        code = context.getCode() + '\n\nexit'
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'ncl'
+      args: ({filepath}) -> [filepath]

   newLISP:
-    "Selection Based":
-      command: "newlisp"
-      args: (context) -> ['-e', context.getCode()]
-    "File Based":
-      command: "newlisp"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'newlisp'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'newlisp'
+      args: ({filepath}) -> [filepath]

   Nim:
-    "File Based":
-      command: "bash"
-      args: (context) ->
-        file = GrammarUtils.Nim.findNimProjectFile(context.filepath)
-        path = GrammarUtils.Nim.projectDir(context.filepath)
-        ['-c', 'cd "' + path + '" && nim c --hints:off --parallelBuild:1 -r "' + file + '" 2>&1']
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) ->
+        file = GrammarUtils.Nim.findNimProjectFile(filepath)
+        path = GrammarUtils.Nim.projectDir(filepath)
+        return ['-c', "cd '#{path}' && nim c --hints:off --parallelBuild:1 -r '#{file}' 2>&1"]

   NSIS:
-    "Selection Based":
-      command: "makensis"
-      args: (context) ->
-        code = context.getCode()
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "makensis"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'makensis'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'makensis'
+      args: ({filepath}) -> [filepath]

   'Objective-C':
-    if GrammarUtils.OperatingSystem.isDarwin()
-      "File Based":
-        command: "bash"
-        args: (context) -> ['-c', "xcrun clang -fcolor-diagnostics -Wall -include stdio.h -framework Cocoa " + context.filepath + " -o /tmp/objc-c.out && /tmp/objc-c.out"]
+    if os is 'darwin'
+      'File Based':
+        command: 'bash'
+        args: ({filepath}) -> ['-c', "xcrun clang -fcolor-diagnostics -Wall -include stdio.h -framework Cocoa '#{filepath}' -o /tmp/objc-c.out && /tmp/objc-c.out"]

   'Objective-C++':
-    if GrammarUtils.OperatingSystem.isDarwin()
-      "File Based":
-        command: "bash"
-        args: (context) -> ['-c', "xcrun clang++ -fcolor-diagnostics -Wc++11-extensions -Wall -include stdio.h -include iostream -framework Cocoa " + context.filepath + " -o /tmp/objc-cpp.out && /tmp/objc-cpp.out"]
+    if os is 'darwin'
+      'File Based':
+        command: 'bash'
+        args: ({filepath}) -> ['-c', "xcrun clang++ -fcolor-diagnostics -Wc++11-extensions -Wall -include stdio.h -include iostream -framework Cocoa '#{filepath}' -o /tmp/objc-cpp.out && /tmp/objc-cpp.out"]

   OCaml:
-    "File Based":
-      command: "ocaml"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'ocaml'
+      args: ({filepath}) -> [filepath]

   Octave:
-    "Selection Based":
-      command: "octave"
+    'Selection Based':
+      command: 'octave'
       args: (context) -> ['-p', context.filepath.replace(/[^\/]*$/, ''), '--eval', context.getCode()]
-    "File Based":
-      command: "octave"
-      args: (context) -> ['-p', context.filepath.replace(/[^\/]*$/, ''), context.filepath]
+    'File Based':
+      command: 'octave'
+      args: ({filepath}) -> ['-p', filepath.replace(/[^\/]*$/, ''), filepath]

   Oz:
-    "Selection Based":
-      command: "ozc"
-      args: (context) ->
-        code = context.getCode()
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        ['-c', tmpFile]
-    "File Based":
-      command: "ozc"
-      args: (context) -> ['-c', context.filepath]
+    'Selection Based':
+      command: 'ozc'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return ['-c', tmpFile]
+    'File Based':
+      command: 'ozc'
+      args: ({filepath}) -> ['-c', filepath]

   'Pandoc Markdown':
-    "File Based":
-      command: "panzer"
-      args: (context) -> [context.filepath, "--output=" + context.filepath + ".pdf"]
+    'File Based':
+      command: 'panzer'
+      args: ({filepath}) -> [filepath, "--output='#{filepath}.pdf'"]

   Perl:
-    "Selection Based":
-      command: "perl"
-      args: (context) ->
-        code = context.getCode()
-        file = GrammarUtils.Perl.createTempFileWithCode(code)
-        [file]
-    "File Based":
-      command: "perl"
-      args: (context) -> [context.filepath]
-
-  "Perl 6":
-    "Selection Based":
-      command: "perl6"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "perl6"
-      args: (context) -> [context.filepath]
-
-  "Perl 6 FE":
-    "Selection Based":
-      command: "perl6"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "perl6"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'perl'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'perl'
+      args: ({filepath}) -> [filepath]
+
+  'Perl 6':
+    'Selection Based':
+      command: 'perl6'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'perl6'
+      args: ({filepath}) -> [filepath]
+
+  'Perl 6 FE':
+    'Selection Based':
+      command: 'perl6'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'perl6'
+      args: ({filepath}) -> [filepath]

   PHP:
-    "Selection Based":
-      command: "php"
-      args: (context) ->
-        code = context.getCode()
-        file = GrammarUtils.PHP.createTempFileWithCode(code)
-        [file]
-    "File Based":
-      command: "php"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'php'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.PHP.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'php'
+      args: ({filepath}) -> [filepath]

   PowerShell:
-    "Selection Based":
-      command: "powershell"
+    'Selection Based':
+      command: 'powershell'
       args: (context) -> [context.getCode()]
-    "File Based":
-      command: "powershell"
-      args: (context) -> [context.filepath.replace /\ /g, "` "]
+    'File Based':
+      command: 'powershell'
+      args: ({filepath}) -> [filepath.replace /\ /g, '` ']

   Processing:
-    "File Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "cmd" else "bash"
-      args: (context) ->
-        if GrammarUtils.OperatingSystem.isWindows()
-          return ['/c processing-java --sketch='+context.filepath.replace("\\"+context.filename,"")+' --run']
-        else
-          return ['-c', 'processing-java --sketch='+context.filepath.replace("/"+context.filename,"")+' --run']
-
+    'File Based':
+      command: if windows then 'cmd' else 'bash'
+      args: ({filepath, filename}) ->
+        if windows
+          return ['/c processing-java --sketch=' + filepath.replace("\\#{filename}", '') + ' --run']
+        else ['-c', 'processing-java --sketch=' + filepath.replace("/#{filename}", '') + ' --run']

   Prolog:
-    "File Based":
-      command: "bash"
-      args: (context) -> ['-c', 'cd \"' + context.filepath.replace(/[^\/]*$/, '') + '\"; swipl -f \"' + context.filepath + '\" -t main --quiet']
+    'File Based':
+      command: 'bash'
+      args: ({filepath}) -> ['-c', "cd '" + filepath.replace(/[^\/]*$/, '') + "'; swipl -f '#{filepath}' -t main --quiet"]

   PureScript:
-    "File Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "cmd" else "bash"
-      args: (context) ->
-        if GrammarUtils.OperatingSystem.isWindows()
-          ['/c cd "' + context.filepath.replace(/[^\/]*$/, '') + '" && pulp run']
-        else
-          ['-c', 'cd "' + context.filepath.replace(/[^\/]*$/, '') + '" && pulp run']
+    'File Based':
+      command: if windows then 'cmd' else 'bash'
+      args: ({filepath}) ->
+        filepath = filepath.replace(/[^\/]*$/, '')
+        command = "cd '#{filepath}' && pulp run"
+        if windows then ["/c #{command}"] else ['-c', command]

   Python:
-    "Selection Based":
-      command: "python"
-      args: (context)  -> ['-u', '-c', context.getCode()]
-    "File Based":
-      command: "python"
-      args: (context) -> ['-u', context.filepath]
+    'Selection Based':
+      command: 'python'
+      args: (context) -> ['-u', '-c', context.getCode()]
+    'File Based':
+      command: 'python'
+      args: ({filepath}) -> ['-u', filepath]

   R:
-    "Selection Based":
-      command: "Rscript"
-      args: (context) ->
-        code = context.getCode()
-        file = GrammarUtils.R.createTempFileWithCode(code)
-        [file]
-    "File Based":
-      command: "Rscript"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'Rscript'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.R.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'Rscript'
+      args: ({filepath}) -> [filepath]

   Racket:
-    "Selection Based":
-      command: "racket"
-      args: (context) -> ['-e', context.getCode()]
-    "File Based":
-      command: "racket"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'racket'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'racket'
+      args: ({filepath}) -> [filepath]

   RANT:
-    "Selection Based":
-      command: "RantConsole.exe"
-      args: (context) ->
-        code = context.getCode(true)
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        ['-file', tmpFile]
-    "File Based":
-      command: "RantConsole.exe"
-      args: (context) -> ['-file', context.filepath]
+    'Selection Based':
+      command: 'RantConsole.exe'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return ['-file', tmpFile]
+    'File Based':
+      command: 'RantConsole.exe'
+      args: ({filepath}) -> ['-file', filepath]

   Reason:
-    "File Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "cmd" else "bash"
-      args: (context) ->
-        progname = context.filename.replace /\.re$/, ""
-        args = []
-        if GrammarUtils.OperatingSystem.isWindows()
-          args = ["/c rebuild #{progname}.native && #{progname}.native"]
-        else
-          args = ['-c', "rebuild '#{progname}.native' && '#{progname}.native'"]
-        return args
+    'File Based':
+      command: if windows then 'cmd' else 'bash'
+      args: ({filename}) ->
+        progname = filename.replace /\.re$/, ''
+        command = "rebuild '#{progname}.native' && '#{progname}.native'"
+        if windows then ["/c #{command}"] else ['-c', command]

   "Ren'Py":
-    "File Based":
-      command: "renpy"
-      args: (context) -> [context.filepath.substr(0, context.filepath.lastIndexOf("/game"))]
+    'File Based':
+      command: 'renpy'
+      args: ({filepath}) -> [filepath.substr(0, filepath.lastIndexOf('/game'))]

   'Robot Framework':
-    "File Based":
+    'File Based':
       command: 'robot'
-      args: (context) -> [context.filepath]
+      args: ({filepath}) -> [filepath]

   RSpec:
-    "Selection Based":
-      command: "ruby"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "rspec"
-      args: (context) -> ['--tty', '--color', context.filepath]
-    "Line Number Based":
-      command: "rspec"
+    'Selection Based':
+      command: 'ruby'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'rspec'
+      args: ({filepath}) -> ['--tty', '--color', filepath]
+    'Line Number Based':
+      command: 'rspec'
       args: (context) -> ['--tty', '--color', context.fileColonLine()]

   Ruby:
-    "Selection Based":
-      command: "ruby"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "ruby"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'ruby'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'ruby'
+      args: ({filepath}) -> [filepath]

   'Ruby on Rails':
-    "Selection Based":
-      command: "rails"
-      args: (context)  -> ['runner', context.getCode()]
-    "File Based":
-      command: "rails"
-      args: (context) -> ['runner', context.filepath]
+    'Selection Based':
+      command: 'rails'
+      args: (context) -> ['runner', context.getCode()]
+    'File Based':
+      command: 'rails'
+      args: ({filepath}) -> ['runner', filepath]

   Rust:
-    "File Based":
-      command: if GrammarUtils.OperatingSystem.isWindows() then "cmd" else "bash"
-      args: (context) ->
-        progname = context.filename.replace /\.rs$/, ""
-        args = []
-        if GrammarUtils.OperatingSystem.isWindows()
-          args = ["/c rustc #{context.filepath} && #{progname}.exe"]
-        else
-          args = ['-c', "rustc '#{context.filepath}' -o /tmp/rs.out && /tmp/rs.out"]
-        return args
+    'File Based':
+      command: if windows then 'cmd' else 'bash'
+      args: ({filepath, filename}) ->
+        progname = filename.replace /\.rs$/, ''
+        if windows
+          return ["/c rustc #{filepath} && #{progname}.exe"]
+        else ['-c', "rustc '#{filepath}' -o /tmp/rs.out && /tmp/rs.out"]

   Sage:
-    "Selection Based":
-      command: "sage"
+    'Selection Based':
+      command: 'sage'
       args: (context) -> ['-c', context.getCode()]
-    "File Based":
-      command: "sage"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'sage'
+      args: ({filepath}) -> [filepath]

   Sass:
-    "File Based":
-      command: "sass"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'sass'
+      args: ({filepath}) -> [filepath]

   Scala:
-    "Selection Based":
-      command: "scala"
-      args: (context)  -> ['-e', context.getCode()]
-    "File Based":
-      command: "scala"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'scala'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'scala'
+      args: ({filepath}) -> [filepath]

   Scheme:
-    "Selection Based":
-      command: "guile"
-      args: (context)  -> ['-c', context.getCode()]
-    "File Based":
-      command: "guile"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'guile'
+      args: (context) -> ['-c', context.getCode()]
+    'File Based':
+      command: 'guile'
+      args: ({filepath}) -> [filepath]

   SCSS:
-    "File Based":
-      command: "sass"
-      args: (context) -> [context.filepath]
-
-  "Shell Script":
-    "Selection Based":
+    'File Based':
+      command: 'sass'
+      args: ({filepath}) -> [filepath]
+
+  'Shell Script':
+    'Selection Based':
       command: process.env.SHELL
-      args: (context)  -> ['-c', context.getCode()]
-    "File Based":
+      args: (context) -> ['-c', context.getCode()]
+    'File Based':
       command: process.env.SHELL
-      args: (context) -> [context.filepath]
-
-  "Shell Script (Fish)":
-    "Selection Based":
-      command: "fish"
-      args: (context)  -> ['-c', context.getCode()]
-    "File Based":
-      command: "fish"
-      args: (context) -> [context.filepath]
-
-  "SQL":
-    "Selection Based":
-      command: "echo"
-      args: (context) -> ['SQL requires setting \'Script: Run Options\' directly. See https://github.com/rgbkrk/atom-script/tree/master/examples/hello.sql for further information.']
-    "File Based":
-      command: "echo"
-      args: (context) -> ['SQL requires setting \'Script: Run Options\' directly. See https://github.com/rgbkrk/atom-script/tree/master/examples/hello.sql for further information.']
-
-  "SQL (PostgreSQL)":
-    "Selection Based":
-      command: "psql"
+      args: ({filepath}) -> [filepath]
+
+  'Shell Script (Fish)':
+    'Selection Based':
+      command: 'fish'
       args: (context) -> ['-c', context.getCode()]
-    "File Based":
-      command: "psql"
-      args: (context) -> ['-f', context.filepath]
-
-  "Standard ML":
-    "File Based":
-      command: "sml"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'fish'
+      args: ({filepath}) -> [filepath]
+
+  SQL:
+    'Selection Based':
+      command: 'echo'
+      args: -> ["SQL requires setting 'Script: Run Options' directly. See https://github.com/rgbkrk/atom-script/tree/master/examples/hello.sql for further information."]
+    'File Based':
+      command: 'echo'
+      args: -> ["SQL requires setting 'Script: Run Options' directly. See https://github.com/rgbkrk/atom-script/tree/master/examples/hello.sql for further information."]
+
+  'SQL (PostgreSQL)':
+    'Selection Based':
+      command: 'psql'
+      args: (context) -> ['-c', context.getCode()]
+    'File Based':
+      command: 'psql'
+      args: ({filepath}) -> ['-f', filepath]
+
+  'Standard ML':
+    'File Based':
+      command: 'sml'
+      args: ({filepath}) -> [filepath]

   Stata:
-    "Selection Based":
-      command: "stata"
-      args: (context)  -> ['do', context.getCode()]
-    "File Based":
-      command: "stata"
-      args: (context) -> ['do', context.filepath]
+    'Selection Based':
+      command: 'stata'
+      args: (context) -> ['do', context.getCode()]
+    'File Based':
+      command: 'stata'
+      args: ({filepath}) -> ['do', filepath]

   Swift:
-    "File Based":
-      command: "swift"
-      args: (context) -> [context.filepath]
+    'File Based':
+      command: 'swift'
+      args: ({filepath}) -> [filepath]

   Tcl:
-    "Selection Based":
-      command: "tclsh"
-      args: (context) ->
-        code = context.getCode()
-        tmpFile = GrammarUtils.createTempFileWithCode(code)
-        [tmpFile]
-    "File Based":
-      command: "tclsh"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'tclsh'
+      args: (context) ->
+        code = context.getCode()
+        tmpFile = GrammarUtils.createTempFileWithCode(code)
+        return [tmpFile]
+    'File Based':
+      command: 'tclsh'
+      args: ({filepath}) -> [filepath]

   Turing:
-    "File Based":
-      command: "turing"
-      args: (context) -> ['-run', context.filepath]
+    'File Based':
+      command: 'turing'
+      args: ({filepath}) -> ['-run', filepath]

   TypeScript:
-    "Selection Based":
-      command: "ts-node"
-      args: (context) -> ['-e', context.getCode()]
-    "File Based":
-      command: "ts-node"
-      args: (context) -> [context.filepath]
+    'Selection Based':
+      command: 'ts-node'
+      args: (context) -> ['-e', context.getCode()]
+    'File Based':
+      command: 'ts-node'
+      args: ({filepath}) -> [filepath]

   VBScript:
     'Selection Based':
       command: 'cscript'
       args: (context) ->
         code = context.getCode()
-        tmpFile = GrammarUtils.createTempFileWithCode(code, ".vbs")
-        ['//NOLOGO',tmpFile]
+        tmpFile = GrammarUtils.createTempFileWithCode(code, '.vbs')
+        return ['//NOLOGO', tmpFile]
     'File Based':
       command: 'cscript'
-      args: (context) -> ['//NOLOGO', context.filepath]
-
-  HTML:
-    "File Based":
-      command: 'echo'
-      args: (context) ->
-        uri = 'file://' + context.filepath
-        shell.openExternal(uri)
-        ['HTML file opened at:', uri]
+      args: ({filepath}) -> ['//NOLOGO', filepath]


RIP updateCollection

RIP updateCollection

--- resources/assets/coffee/osu_common.coffee
+++ resources/assets/coffee/osu_common.coffee
@@ -332,14 +332,6 @@
     Turbolinks.uuid() # no point rolling our own

-  # Update collection item with newItems and remove old items.
-  updateCollection: (collection, newItems) ->
-    _(newItems)
-      .concat(collection)
-      .uniqBy('id')
-      .value()
-
-
   updateQueryString: (url, params) ->
     urlObj = new URL(url ? window.location.href, document.location.origin)
     for own key, value of params


link publishing added

link publishing added

--- client/landing/app/MainApp/kodingappscontroller.coffee
+++ client/landing/app/MainApp/kodingappscontroller.coffee
@@ -330,13 +330,24 @@

       @kiteController.run "kdc #{appPath}", (err, response)=>
         if not err
-          loader.notificationSetTitle "Fetching compiled app..."
-          @fetchCompiledAppSource app, (err, res)=>
-            if not err
-              @defineApp name, res
-              loader.notificationSetTitle "App compiled successfully"
-              loader.notificationSetTimer 2000
-            callback? err, res
+          nickname    = KD.nick()
+          publishPath = "/home/#{nickname}/Sites/#{nickname}.koding.kd.io/.applications"
+          @kiteController.run
+            kiteName    : "os"
+            method      : "fs.createDirectory"
+            withArgs    :
+              path      : publishPath
+              recursive : yes
+          , (err, response)=>
+            loader.notificationSetTitle "Publishing app static files..."
+            @kiteController.run "ln -s #{appPath} #{publishPath}/#{KD.utils.slugify name}", (err, response)=>
+              loader.notificationSetTitle "Fetching compiled app..."
+              @fetchCompiledAppSource app, (err, res)=>
+                if not err
+                  @defineApp name, res
+                  loader.notificationSetTitle "App compiled successfully"
+                  loader.notificationSetTimer 2000
+                callback? err, res
         else
           loader.destroy()


Bongo: added existential check for equals function

--- node_modules_koding/bongo/lib/model/index.coffee
+++ node_modules_koding/bongo/lib/model/index.coffee
@@ -794,7 +794,7 @@

   equals:(model, deep=no)->
     unless deep
-      @getId()?.equals model?.getId?()
+      @getId()?.equals? model?.getId?()
     # TODO: I'm not currently interested in "deep", but it might be needed later CT

   prune:do ->


Matchers converted to class.

Matchers converted to class.

--- lib/matchers.coffee
+++ lib/matchers.coffee
@@ -1,71 +1,81 @@
-emptyLineMatcher = /^\s*$/
+class Matcher
+	emptyLineMatcher = /^\s*$/

-newlineMatcher = /[\r\n]+/g
+	newlineMatcher = /[\r\n]+/g

-# NOTE: Lines are trimmed before trying the match against those RegExp.
-# So they don't care about whitespace at the beginning or the end of the input.
+	# NOTE: Lines are trimmed before trying the match against those RegExp.
+	# So they don't care about whitespace at the beginning or the end of the input.

-# A comment:
-# 	-starts with #
-commentLineMatcher = /^#/
+	# A comment:
+	# 	-starts with #
+	commentLineMatcher = /^#/

-# A section header:
-#	-starts with [
-#	-ends with ]
-# 	-between those 2 symbols it must contain just a valid javascript object key, although it can be surrounded by whitespace
-# [HEADER] => it's a header
-# [ HEADER ] => it's a header
-# [ HEADER_NAME ] => it's a header
-# [ HEADER.NAME ] => it's a header
-# [ HEADER NAME ] => it's NOT a header
-sectionHeaderMatcher = /^\[(\s*[a-zA-Z_][a-zA-Z0-9._]*\s*)\]$/i;
+	commentMatcher = /^#(.*)$/i

-# A key=value line:
-#	-starts with a valid javascript key
-#	-continues with a =
-#	-ends with any combination of characters
-# key=value => it's a key/value line
-# key = value => it's a key/value line
-# key.subkey = value => it's a key/value line
-# key = value includes a second = but and it's fine => it's a key/value line
-# 1key=value => it's NOT a key/value line
-# key subkey = value => it's NOT a key/value line
-keyValueMatcher = /^([a-zA-Z_][a-zA-Z0-9._]*\s*\=.*)$/i
+	# A section header:
+	#	-starts with [
+	#	-ends with ]
+	# 	-between those 2 symbols it must contain just a valid javascript object key, although it can be surrounded by whitespace
+	# [HEADER] => it's a header
+	# [ HEADER ] => it's a header
+	# [ HEADER_NAME ] => it's a header
+	# [ HEADER.NAME ] => it's a header
+	# [ HEADER NAME ] => it's NOT a header
+	sectionHeaderMatcher = /^\[(\s*[a-zA-Z_][a-zA-Z0-9._]*\s*)\]$/i;

-keyMatcher = /^([a-zA-Z_][a-zA-Z0-9._]*\s*)\=/i
+	# A key=value line:
+	#	-starts with a valid javascript key
+	#	-continues with a =
+	#	-ends with any combination of characters
+	# key=value => it's a key/value line
+	# key = value => it's a key/value line
+	# key.subkey = value => it's a key/value line
+	# key = value includes a second = but and it's fine => it's a key/value line
+	# 1key=value => it's NOT a key/value line
+	# key subkey = value => it's NOT a key/value line
+	keyValueMatcher = /^([a-zA-Z_][a-zA-Z0-9._]*\s*\=.*)$/i

-valueMatcher = /^[a-zA-Z_][a-zA-Z0-9._]*\s*\=(.*)$/i
+	keyMatcher = /^([a-zA-Z_][a-zA-Z0-9._]*\s*)\=/i

-module.exports =
-	splitOnNewLine: (text) ->
+	valueMatcher = /^[a-zA-Z_][a-zA-Z0-9._]*\s*\=(.*)$/i
+
+	@splitOnNewLine = (text) ->
 		return text.split newlineMatcher

-	isEmpty: (text) ->
+	@isEmpty = (text) ->
 		return emptyLineMatcher.test text.trim()

-	isComment: (text) ->
+	@isComment = (text) ->
 		return commentLineMatcher.test text.trim()

-	isSectionHeader: (text) ->
+	@getComment = (text) ->
+		if not @isComment text
+			return null
+		else
+			return text.trim().match(commentMatcher)[1].trim()
+
+	@isSectionHeader = (text) ->
 		return sectionHeaderMatcher.test text.trim()

-	getSectionHeader: (text) ->
+	@getSectionHeader = (text) ->
 		if not @isSectionHeader text
 			return null
 		else
 			return text.trim().match(sectionHeaderMatcher)[1].trim()

-	isKeyValue: (text) ->
+	@isKeyValue = (text) ->
 		return keyValueMatcher.test text.trim()

-	getKey: (text) ->
+	@getKey = (text) ->
 		if not @isKeyValue text
 			return null
 		else
 			return text.trim().match(keyMatcher)[1].trim()

-	getValue: (text) ->
+	@getValue = (text) ->
 		if not @isKeyValue text
 			return null
 		else
-			return text.trim().match(valueMatcher)[1].trim()+			return text.trim().match(valueMatcher)[1].trim()
+
+module.exports = Matcher


Default to all directions

Default to all directions

--- framer/GestureManager.coffee
+++ framer/GestureManager.coffee
@@ -38,8 +38,8 @@

 		# Add other recognizers if they existed already
 		existingRecognizers = @_getDependentRecognizersForEventFamily(eventFamily)
-
-		if existingRecognizers.length > 0
+
+		if existingRecognizers.length
 			@_manager.add(recognizer).recognizeWith(existingRecognizers)
 		else
 			@_manager.add(recognizer)
@@ -87,8 +87,11 @@

 	_getRecognizer: (eventFamily) ->

-		if @_manager?.get(eventFamily)
-			return @_manager.get(eventFamily)
+		existingRecognizer = @_manager.get(eventFamily)
+
+		if existingRecognizer
+			if eventFamily in [Gestures.Swipe, Gestures.Pan]
+			return existingRecognizer

 		switch eventFamily


Make video captions respect course author's setting.

--- common/lib/xmodule/xmodule/js/src/video/display.coffee
+++ common/lib/xmodule/xmodule/js/src/video/display.coffee
@@ -5,7 +5,7 @@
     @start = @el.data('start')
     @end = @el.data('end')
     @caption_asset_path = @el.data('caption-asset-path')
-    @show_captions = @el.data('show-captions') == "true"
+    @show_captions = !!@el.data('show-captions')
     window.player = null
     @el = $("#video_#{@id}")
     @parseVideos @el.data('streams')
@@ -13,7 +13,7 @@
     @parseSpeed()
     $("#video_#{@id}").data('video', this).addClass('video-load-complete')

-    @hide_captions = $.cookie('hide_captions') == 'true'
+    @hide_captions = $.cookie('hide_captions') == 'true' or (not @show_captions)

     if YT.Player
       @embed()


#396 fix, unnoticed broken at cleanup before push to repo

Carelessly removed options passing.

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -181,9 +181,10 @@
     @patternForOccurence ?= @getPatternForOccurrence()

     fn()
+
+    scanRanges ?= @editor.getSelectedBufferRanges()
     options = {includeIntersects: true, exclusiveIntersects: wasVisual}
-    scanRanges ?= @editor.getSelectedBufferRanges()
-    ranges = scanInRanges(@editor, @patternForOccurence, scanRanges)
+    ranges = scanInRanges(@editor, @patternForOccurence, scanRanges, options)

     if ranges.length
       @editor.setSelectedBufferRanges(ranges)


:tada: pass spec again

:tada: pass spec again

--- lib/operator.coffee
+++ lib/operator.coffee
@@ -227,29 +227,28 @@
     @observeSelectTarget()
     @pointBySelection = new Map
     wasVisual = @isMode('visual')
-    if wasVisual
-      if @needStay()
-        for selection in @editor.getSelections()
-          head = swrap(selection).getBufferPositionFor('head', fromProperty: true)
-          # console.log 'visual and stay', head.toString()
-          @requestRestoreCursorPosition(selection, head)
-        # @requestRestoreCursorPositions('head')
+
+    saveCursorsToRestoreAfterSelect = null
+    if @needStay()
+      if wasVisual
+        console.log 'case-1'
+        @requestRestoreCursorPositions('head', fromProperty: true, allowFallback: true) # visual-stay
       else
-        @requestRestoreCursorPositions('start')
-    else
-      if @needStay()
-        unless @instanceof('Select')
-          @requestRestoreCursorPositions('head')
+        console.log 'case-2'
+        @requestRestoreCursorPositions('head') unless @instanceof('Select') # stay
+    else
+      if wasVisual
+        console.log 'case-3'
+        @requestRestoreCursorPositions('start') # visual-notStay
       else
-        null
-
-        # @updateSelectionProperties() # [FIXME] don't store to swrap, explicitly store and clear
-        # console.log 'update prop on will-select-target'
+        console.log 'case-4'
+        # normal-mode
+        saveCursorsToRestoreAfterSelect = =>
+          @requestRestoreCursorPositions('start')

     @emitWillSelectTarget()
     @target.select()
-    if not wasVisual and not @needStay()
-      @requestRestoreCursorPositions('start')
+    saveCursorsToRestoreAfterSelect?()

     @flashIfNecessary(@editor.getSelectedBufferRanges())
     @trackChangeIfNecessary()
@@ -268,17 +267,12 @@
     globalState.previousSelection = {properties, submode}

   requestRestoreCursorPosition: (selection, point) ->
-    console.log 'requested', point.toString()
+    # console.log 'requested', point.toString()
     @pointBySelection.set(selection, point)

-  requestRestoreCursorPositions: (which) ->
+  requestRestoreCursorPositions: (which, options={}) ->
     for selection in @editor.getSelections()
-      if which is 'start'
-        point = selection.getBufferRange().start
-      else if 'head'
-        point = swrap(selection).detectCharacterwiseProperties().head
-        # point = selection.getHeadBufferPosition()
-        console.log 'head', point.toString()
+      point = swrap(selection).getBufferPositionFor(which, options)
       @requestRestoreCursorPosition(selection, point)

   isRestorableCursorPositionForSelection: (selection) ->
@@ -286,7 +280,7 @@

   restoreCursorPositionForSelection: (selection) ->
     if point = @pointBySelection.get(selection)
-      console.log 'restore', point.toString()
+      # console.log 'restore', point.toString()
       selection.cursor.setBufferPosition(point)

   restoreCursorPositions: ->


change demo text

change demo text

--- cistrans/sparql_demo.coffee
+++ cistrans/sparql_demo.coffee
@@ -35,8 +35,8 @@
 	[probeobj, genoobj]

 reloadQueries = () ->
-	document.getElementById("genotext").innerHTML = "Parsed genotypes for probe #{probe_number}";
-	document.getElementById("phenoparsedtext").innerHTML = "Parsed phenotypes and lods for probe #{probe_number}, marker #{marker}";
+	document.getElementById("genotext").innerHTML = "Parsed phenotypes and LODs for probe #{probe_number}";
+	document.getElementById("phenoparsedtext").innerHTML = "Genotypes for #{probe_number}, marker #{marker}";
 	document.getElementById("genoraw").innerHTML = "Raw Markers/LODs/gene for probe #{probe_number}";
 	document.getElementById("phenotext").innerHTML = "Raw JSON for Pheno/Geno/individual for probe #{probe_number}, marker #{marker}";


Update base controller to use new beforeLoad api

--- class/BaseController.coffee
+++ class/BaseController.coffee
@@ -6,7 +6,7 @@
 		@view = new View view, @response
 		@view.setLayout layout

-	beforeLoad: ->
+	beforeAction: ->

 	beforeRender: ->


Changed visibility of functions

Changed visibility of functions

--- lib/provider.coffee
+++ lib/provider.coffee
@@ -32,7 +32,7 @@
   # Returns true/false if is valid
   #
   # Sets up request variables for easier access down the line
-  valid_request: (req, callback=()->) ->
+  valid_request: (req, callback=()->) =>
     @parse_request(req)
     if not @_valid_parameters(req)
       return callback(new Error('Invalid LTI parameters'), false)
@@ -52,7 +52,7 @@
   # Helper to validate the OAuth information in the request
   #
   # Returns true/false if is valid OAuth signatue and nonce
-  _valid_oauth: (req, callback) =>
+  _valid_oauth: (req, callback) ->
     generated = @signer.build_signature req, @consumer_secret
     valid_signature = generated is req.body.oauth_signature
     return callback new Error('Invalid Signature'), false if not valid_signature


Main: generated include additions

Main: generated include additions

--- client/Main/includes.coffee
+++ client/Main/includes.coffee
@@ -278,6 +278,12 @@
   "VirtualizationController.coffee",
   "CommonViews/modalappslistitemview.coffee",

+  # these are generated dependencies
+  # do not delete they're ignored in git
+  # created in compile time.
+  "__generatedapps__.coffee",
+  "__generatedroutes__.coffee",
+
   "status.coffee",
   "main.coffee",
   "rollbar.coffee",


Uses new database connect method

Uses new database connect method

--- coffee/tools/updater.coffee
+++ coffee/tools/updater.coffee
@@ -7,58 +7,25 @@
 "use strict"

 mongodb = require 'mongodb'
-database = require './../database'
+database = require './../database.coffee'

 database.connect 'ntb_07', (err, db) ->
-  return console.log 'db err', err if err
+  return console.log err if err

-
-  db.on 'error', (error, db) ->
-    console.log 'db.error', error
-    db.close()
-
   console.log 'Database connection is open'

-  db.collection 'turer', (err, collection) ->
-    if err
-      console.log 'db connection failed'
-      console.log err
-      return db.close()
+  db.collection 'bilder', (err, collection) ->
+    return console.log err if err

     console.log "Collection is open"

-    update = (doc, cb) ->
-      #if doc.privat.lenker
-      #  for link in doc.privat.lenker
-      #    if not link.url.match(/^http(s?):\/\//m)
-      #      console.log link.url
-      #      #return cb new Error('end')
-      #
-      #if doc.privat.eier
-      #  for eier in doc.privat.eier
-      #    if eier.url and not eier.url.match(/^http(s?):\/\//m)
-      #      console.log eier.url
-
+    cursor = collection.find().limit(2)
+    #$where : "this.geojson && this.geojson.coordinates[0] > 50"
+
+    database.each cursor, (doc, cb) ->
+      console.log doc
       cb()
+    , (err, i) ->
+      console.log 'cursor end', i
+      db.close()

-    collection.find {"privat" : {$exists: true}}, (err, cursor) ->
-      console.log 'collection.find run'
-
-      if err
-        console.log 'collection.find() failed'
-        console.log err
-        return db.close()
-
-      database.each cursor, update, (err, count) ->
-        console.log 'count', count
-
-        if err
-          console.log 'database update failed'
-          console.log err
-        else
-          console.log 'databse update success'
-
-        db.close()
-
-
-


Use info alert until suite completes or failure occurs

--- spec/atom-reporter.coffee
+++ spec/atom-reporter.coffee
@@ -43,7 +43,7 @@
       @div outlet: 'userArea', class: 'symbol-area', =>
         @div outlet: 'userHeader', class: 'symbol-header'
         @ul outlet: 'userSummary', class: 'symbol-summary list-unstyled'
-      @div outlet: "status", class: 'status alert alert-success', =>
+      @div outlet: "status", class: 'status alert alert-info', =>
         @div outlet: "time", class: 'time'
         @div outlet: "specCount", class: 'spec-count'
         @div outlet: "message", class: 'message'
@@ -68,6 +68,7 @@

   reportRunnerResults: (runner) ->
     @updateSpecCounts()
+    @status.addClass('alert-success').removeClass('alert-info') if @failedCount is 0
     if @failedCount is 1
       @message.text "#{@failedCount} failure"
     else
@@ -101,7 +102,7 @@

   updateStatusView: (spec) ->
     if @failedCount > 0
-      @status.addClass('alert-danger').removeClass('alert-success')
+      @status.addClass('alert-danger').removeClass('alert-info')

     @updateSpecCounts()


Remove unused class

Remove unused class

--- spec/atom-reporter.coffee
+++ spec/atom-reporter.coffee
@@ -32,7 +32,7 @@
 module.exports =
 class AtomReporter extends View
   @content: ->
-    @div class: 'jasmine_reporter spec-reporter', =>
+    @div class: 'spec-reporter', =>
       @div outlet: "suites"
       @div outlet: 'coreArea', class: 'symbol-area', =>
         @div outlet: 'coreHeader', class: 'symbol-header'


Set suite description as text

Set suite description as text

--- spec/atom-reporter.coffee
+++ spec/atom-reporter.coffee
@@ -179,7 +179,7 @@

   initialize: (@suite) ->
     @attr('id', "suite-view-#{@suite.id}")
-    @description.html @suite.description
+    @description.text(@suite.description)

   attach: ->
     (@parentSuiteView() or $('.results')).append this


Highlight constructors

Highlight constructors


remove debug

remove debug

--- assets/javascripts/views/post.js.coffee
+++ assets/javascripts/views/post.js.coffee
@@ -47,7 +47,6 @@
         id: @post.get('id')
     }

-    console.log data
     new HTTP 'POST', "#{TentStatus.config.current_tent_api_root}/posts", data, (post, xhr) =>
       return unless xhr.status == 200
       post = new TentStatus.Models.Post post


Fix karma test using favorites flow

Fix karma test using favorites flow

--- karma/flows/test_controllers.coffee
+++ karma/flows/test_controllers.coffee
@@ -233,7 +233,7 @@
       ruleset = flowService.flow.rule_sets[0]

       # four rules and our other
-      expect(ruleset.rules.length).toBe(5)
+      expect(ruleset.rules.length).toBe(6)

       editRules ruleset, (scope) ->
         scope.formData.hasTimeout = true
@@ -241,7 +241,7 @@

       # now we have four rules, our other, and a timeout
       ruleset = flowService.flow.rule_sets[0]
-      expect(ruleset.rules.length).toBe(6)
+      expect(ruleset.rules.length).toBe(7)

       # checkout our timeout rule as the right settings
       lastRule = ruleset.rules[ruleset.rules.length - 1]


:fire: Remove an invalid spec

:fire: Remove an invalid spec

--- spec/validate-spec.coffee
+++ spec/validate-spec.coffee
@@ -57,7 +57,4 @@
       expect ->
         validate.messages([{type: 'Error', html: 'a', trace: 1}], {name: ''})
       .toThrow()
-      expect ->
-        validate.messages([{type: 'Error', html: 'a', trace: false}], {name: ''})
-      .toThrow()
       validate.messages([{type: 'Error', html: 'a', trace: false}], {name: ''})


removed request object helper methods. not practical for every use.  Simplified regex to only look for new lines then spaces and replace with single space.

--- lib/coffee/helper.coffee
+++ lib/coffee/helper.coffee
@@ -3,30 +3,6 @@

 _    = require 'underscore'
 util = require 'util'
-
-
-
-is_express_req_obj = (obj) ->
-  obj or= {}
-  return _.has(obj, "route") and _.has(obj, "res") and _.has(obj, "next")
-
-
-item_by_keys = (obj, keyArr) ->
-  item = obj
-  for key in keyArr
-    return null unless _.has(item, key)
-    item = item[key]
-
-  return item.toString()
-
-
-req_item_by_keys = (keyArr) ->
-  return (mod) ->
-    return (level, args) ->
-      reqObj = args[0] or {}
-      return null unless is_express_req_obj(reqObj)
-
-      return item_by_keys(reqObj, keyArr)

 exports.iso_date = (opts = {}) ->
@@ -39,18 +15,6 @@
   return (mod) ->
     return (level, args, realTitle) ->
       return realTitle
-
-
-exports.session_user_id = ({init, defArr} = {}) ->
-  defArr ?= ["session", "user", "id"]
-  init   ?= null
-  return req_item_by_keys(defArr)
-
-
-exports.session_user_email = ({init, defArr} = {}) ->
-  defArr ?= ["session", "user", "email"]
-  init   ?= null
-  return req_item_by_keys(defArr) or init

 exports.line_number = (opts = {}) ->
@@ -89,7 +53,8 @@
       return mod_title_fn(level, args) + ":" + line_fn(level, args)

-inspectToSingleLineRegex = /(?:^|\n) */g
+# no "start of line" because that is user generated, not inspect generated.
+inspectToSingleLineRegex = /\n */g
 exports.single_line_message = (opts = {}) ->
   showHidden = opts.showHidden
   depth      = opts.depth
@@ -105,8 +70,8 @@
           ret.push(util.inspect(item, showHidden, depth))

       ret = ret.join(separator)
-      # remove all '\n' but not '\\n' as that is an escaped '\n' and not something introduced by util.inspect
-      ret = ret.replace(inspectToSingleLineRegex, '') or init
+      # remove all '\n' and spaces as they are something introduced by util.inspect
+      ret = ret.replace(inspectToSingleLineRegex, ' ') or init
       return ret

@@ -129,25 +94,6 @@
       return ret

-
-do_but_ignore_req_at_first = (fn) ->
-
-  return (opts = {}) ->
-    fn_after_opts = fn(opts)
-    return (mod) ->
-      fn_after_mod = fn_after_opts(mod)
-      return (level, args) ->
-        args or= []
-        if is_express_req_obj(args[0] or null)
-          return fn_after_mod(level, args.slice(1))
-        else
-          return fn_after_mod(level, args)
-
-
-exports.single_line_message_ignore_express_req_at_first = do_but_ignore_req_at_first(exports.single_line_message)
-exports.message_ignore_express_req_at_first             = do_but_ignore_req_at_first(exports.message)
-
-
 exports.string = (x) ->
   return _.once (mod) ->
     return _.once (level, args) ->


Outdated Node Production

Outdated Node Production

--- lib/deps/outdated.coffee
+++ lib/deps/outdated.coffee
@@ -44,7 +44,19 @@
       next ++index

-# ## outdatedNodeDev()
+
+# ## npm Error Code Humanizer
+#
+# The error responses from npm can be a bit cryptic when dealing with the
+# process itself (as we are), so this simply returns new errors based on
+# known code responses.
+_npmErrCodeHumanizer = (err) ->
+  switch err.code
+    when 34 then return new Error 'package.json not found'
+    else return err
+
+
+# ## Node Development Outdated
 #
 # Check the given directory for Node Dev deps.
 #
@@ -53,24 +65,50 @@
 # for the better part of a year. This has been fixed, but i believe it will
 # not be available until npm version `1.3.11`. So until that is more reliably
 # on installed systems.. or for that matter, even out, we are defaulting
-# Node Dev to always failing the check.
-#
+# Node Dev to always saying outdated.
 # See https://github.com/isaacs/npm/pull/3863 for reference.
 #
 outdatedNodeDev = (dir, opts={}, callback=->) ->
   if opts instanceof Function
     callback = opts
     opts = {}
-  opts.command    ?= 'npm'
+  opts.command    ?= 'npm outdated'
   opts.transport  ?= autoTransport

   #transport = opts.transport
   #transport opts.command, (err, stdout, stderr) ->
   callback null, true, []

+
+
+# ## Node Production Outdated
+outdatedNodeProd = (dir, opts={}, callback=->) ->
+  if opts instanceof Function
+    callback = opts
+    opts = {}
+  opts.command    ?= 'npm outdated' # should use --production once the npm
+                                    # update goes live.
+  opts.transport  ?= autoTransport
+
+  transportOpts =
+    cwd: dir

+  args = opts.command.split ' '
+  transport args, transportOpts, (err, stdout, stderr) ->
+    if err? then return callback _npmErrCodeHumanizer err
+    if stderr isnt ''
+      return callback new Error "Unknown NPM Response '#{stderr}'"
+
+    # Split the response from npm, which is a list of outdated packages.
+    # Note that removal of the last result, as npm tends to add a additional
+    # line end character, so we want to trim that.
+    packages    = stdout.split('\n')[...-1]
+    outdated   = packages.length > 0
+    callback null, outdated, packages

-exports.outdatedNodeDev     = outdatedNodeDev
+exports._npmErrCodeHumanizer  = _npmErrCodeHumanizer
+exports.outdatedNodeDev       = outdatedNodeDev
+exports.outdatedNodeProd      = outdatedNodeProd


Fix more specs

Fix more specs

--- spec_app/spec/javascripts/up/link_spec.js.coffee
+++ spec_app/spec/javascripts/up/link_spec.js.coffee
@@ -586,16 +586,6 @@
         up.link.makeFollowable($link[0])
         expect($link.attr('up-follow')).toBeMissing()

-      it "does not add [up-follow] to a link that is already [up-modal]", ->
-        $link = $fixture('a[href="/path"][up-modal=".target"]').text('label')
-        up.link.makeFollowable($link[0])
-        expect($link.attr('up-follow')).toBeMissing()
-
-      it "does not add [up-follow] to a link that is already [up-popup]", ->
-        $link = $fixture('a[href="/path"][up-popup=".target"]').text('label')
-        up.link.makeFollowable($link[0])
-        expect($link.attr('up-follow')).toBeMissing()
-
     describe 'up.visit', ->

       it 'should have tests'


completely remove panel when uninstalling package

--- lib/settings-view.coffee
+++ lib/settings-view.coffee
@@ -155,6 +155,7 @@
   removePanel: (name) ->
     if panel = @panelsByName?[name]
       panel.remove()
+      delete @panelsByName[name]
       @panelMenu.find("li[name=\"#{name}\"]").remove()

   getTitle: ->


Handle toggling quoted invalid regions

Handle toggling quoted invalid regions

--- lib/toggle-quotes.coffee
+++ lib/toggle-quotes.coffee
@@ -7,6 +7,14 @@

 toggleQuoteAtPosition = (editor, position) ->
   range = editor.displayBuffer.bufferRangeForScopeAtPosition('.string.quoted', position)
+
+  unless range?
+    # Attempt to match the current invalid region if it is wrapped in quotes
+    # This is useful for languages where changing the quotes makes the range
+    # invalid and so toggling again should properly restore the valid quotes
+    if range = editor.displayBuffer.bufferRangeForScopeAtPosition('.invalid.illegal', position)
+      return unless /^(".*"|'.*')$/.test(editor.getTextInBufferRange(range))
+
   return unless range?

   text = editor.getTextInBufferRange(range)


Conform to NoFlo convention

Conform to NoFlo convention

--- components/Assembler.coffee
+++ components/Assembler.coffee
@@ -33,7 +33,7 @@
       @cache.beginGroup(group)

     @inPorts.replacement.on "data", (data) =>
-      @cache.data(data)
+      @cache.send(data)

     @inPorts.replacement.on "endgroup", (group) =>
       @cache.endGroup(group)


General error handler

General error handler

--- components/StoreUser.coffee
+++ components/StoreUser.coffee
@@ -13,9 +13,8 @@
     fileReader.onload = (event) ->
       callback null, event.target.result
     fileReader.readAsDataURL req.response
-  req.ontimeout = ->
-    callback new Error 'Avatar request timed out'
-  req.timeout = 2000
+  req.onerror = ->
+    callback new Error 'Avatar request failed'
   req.send()

 cleanUpUrl = (callback) ->


:lipstick:

:lipstick:

--- src/app/keymaps/select-list.coffee
+++ src/app/keymaps/select-list.coffee
@@ -2,4 +2,3 @@
   'enter': 'core:confirm',
   'escape': 'core:cancel'
   'meta-w': 'core:cancel'
-


JProvisioner: check all data provided from client in update method, set them as needed

--- workers/social/lib/social/models/computeproviders/provisioner.coffee
+++ workers/social/lib/social/models/computeproviders/provisioner.coffee
@@ -238,26 +238,36 @@
   update$: permit

     advanced: [
-      { permission: 'update provisioner', validateWith: Validators.own }
+      { permission: 'update own provisioner', validateWith: Validators.own }
+      # { permission: 'update provisioner' }
     ]

-    success: (client, options, callback)->
-
-      {content, label} = options
+    success: (client, data, callback)->
+
+      {content, slug, label, type} = data
+
+      unless content or label or slug
+        return callback new KodingError "Nothing to update"
+
+      fieldsToUpdate = { "meta.modifiedAt" : new Date }

       if content?
-        [err, content] = checkContent type, content
+
+        [err, content, contentSum] = checkContent (type or @type), content
         if err? then return callback err

-      unless content or label
-        return callback new KodingError "Nothing to update"
-
-      fieldsToUpdate =
-        label             : label ? @label
-        'meta.modifiedAt' : new Date
-
-      fieldsToUpdate.content = content  if content?
+        fieldsToUpdate.content    = content
+        fieldsToUpdate.contentSum = contentSum
+
+      fieldsToUpdate.label = label if label?
+      fieldsToUpdate.slug  = slug  if slug?

       @update $set : fieldsToUpdate, (err)->
+
+        if slug and err and err.name is 'MongoError' and err.code is 11001
+          return callback new KodingError \
+            "Slug `#{slug}` in use, provide different one"
+
         return callback err  if err?
+
         callback null


simplify the test

simplify the test

--- BackofficeBundle/Resources/public/coffee/table/tableviewLoader.coffee
+++ BackofficeBundle/Resources/public/coffee/table/tableviewLoader.coffee
@@ -32,7 +32,7 @@
       values = response[collection_name][0]
       element = new TableviewModel
       element.set values
-      if language
+      if language?
         link = element.get('links')._self_without_parameters + '?language=' + language
         link = link + '&source_language=' + sourceLanguage if sourceLanguage != undefined
         link = link + '&version=' + version if version != undefined


+ initializeTo, isOriginal method to meta attributes class

--- src/attribute/abstract-type.coffee
+++ src/attribute/abstract-type.coffee
@@ -28,6 +28,11 @@
     defineProperty @, 'names', {}
     @initialize(aOptions)

+  initializeTo: (dest)->
+    for k,v of @names
+      continue if k is 'name'
+      value = @[k].value
+      dest[v] = value unless value is undefined
   assignTo: (src, dest, aExclude, aSerialized)->
     vNames = @names
     if isString aExclude
@@ -45,6 +50,14 @@
         if aSerialized or !isFunction(vAttr.assign) or !vAttr.assign(dest, src, v)
           dest[v] = src[v]
     return dest
+  isOriginal: (aObject)->
+    result = true
+    for k,v of @names
+      continue if k is 'name'
+      unless aObject[v] is @[k].value
+        result = false
+        break
+    result
   getNames: ->
     result = {}
     for k in getObjectKeys @


fix intinite loop problem...

fix intinite loop problem...

--- lib/bottom-dock/results-pane.coffee
+++ lib/bottom-dock/results-pane.coffee
@@ -91,6 +91,7 @@
                     if d[c["field"]] != null and d[c["field"]]?.toString()?.length > max
                         max = d[c["field"]].toString().length
             max = Math.max(max * 7.8 + 10, Math.round((c["name"].length * 8.4) + 12))
+            max = parseInt(max)
             c["width"] = if resultset.columns.length > 1 then Math.min(max, 250) else max
         if resultset.rowcount <= 100 and not resultset.onlyOne
             height = ''.concat(resultset.rowcount * 30 + 30, 'px')


Dramatically smarter buttons

Dramatically smarter buttons

--- app/assets/javascripts/custom-keyboards.coffee
+++ app/assets/javascripts/custom-keyboards.coffee
@@ -1,36 +1,23 @@
 # A rough implementation of 'custom keyboards', similar to
 # https://core.telegram.org/bots#keyboards
-
-parseMaybeJson = (text) ->
-  try
-    JSON.parse(text)
-  catch
-    return null

 fillMessageBar = (text) ->
   $("#message-input").val(text)
   $("#message-input").focus()

-# A button looks like <|button|text|.message to send>
-buttonRegex = /:\|button\|([^|]+)\|([^>]+):/g
+window.repaintKeyboards = ->
+  console.log "checking keyboards"
+  buttons = $('a').filter ->
+    @href.indexOf("https://a.button") == 0

-window.repaintKeyboards = ->
-  $('ts-message').each (_, el) ->
-    matched = false
-    messageBody = $(el).find('.message_body')
-    html = messageBody.html()
-    matchCommands = undefined
-
-    while match = buttonRegex.exec(html)
-      matchCommands ||= {}
-      matched = true
-      buttonText = "<button class='inserted_button' id='match-#{buttonRegex.lastIndex}'>#{match[1]}</button>"
-      html = html.replace(match[0], buttonText)
-      matchCommands[buttonRegex.lastIndex] = fillMessageBar.bind(@, match[2])
-
-    if matched
-      messageBody.html(html)
-      for key in Object.keys(matchCommands)
-        messageBody.find("#match-#{key}").click(matchCommands[key])
+  buttons.each (_, el) ->
+    fields = el.href.split("/", 5)
+    console.log fields
+    label = decodeURI(fields[3])
+    command = decodeURI(fields[4])
+    button = $("<button class='inserted_button'>#{label}</button>")
+    button.click ->
+      fillMessageBar(command)
+    $(el).replaceWith(button)

 slackReadyFunction(window.repaintKeyboards)


Adding modernizr to

Adding modernizr to

--- app/assets/javascripts/darkswarm/all.js.coffee
+++ app/assets/javascripts/darkswarm/all.js.coffee
@@ -14,6 +14,7 @@
 #= require angular-backstretch.js
 #= require angular-flash.min.js
 #= require moment
+#= require modernizr
 #
 #= require foundation
 #= require ./darkswarm


Bandango.Compra should include OrderItemsMixin

--- app/assets/javascripts/models/compra.js.coffee
+++ app/assets/javascripts/models/compra.js.coffee
@@ -1 +1,4 @@
-Bandango.Compra = DS.Model.extend()
+Bandango.Compra = DS.Model.extend Bandango.OrderItemsMixin,
+
+  sustentoComprobante: DS.belongsTo("sustentoComprobante")
+  orderItems:          DS.hasMany("orderItem")


update to modal

update to modal

--- app/assets/javascripts/pt/tags/modal.js.coffee
+++ app/assets/javascripts/pt/tags/modal.js.coffee
@@ -12,8 +12,24 @@
       if Object.has attr, 'modalSave'
         buttons.push
           label: attr.modalSave or 'Save'
-          id: 'ptModalSave'
-          callback: -> $('#pt-modal-body').find('form').submit()
+          # id: 'pt-modal-save'
+          class: 'btn-primary'
+          callback: ->
+            $body = $('#pt-modal-body')
+
+            $body.find('form').ajaxSubmit
+              data: pt_modal: true
+              error: (request) ->
+                $body.html request.responseText
+                $(document).trigger 'page:change'
+              success: (html) ->
+                $body.closest('.bootbox').modal('hide')
+            false
+
+      buttons.push
+        label: attr.modalClose or 'Close'
+        # id: 'pt-modal-close'
+        callback: -> $('#pt-modal-body').closest('.bootbox').modal('hide')

       unless $el.data 'ptModalLoaded'
         $el.data 'ptModalLoaded', true
@@ -21,8 +37,20 @@

         $.ajax
           url: url
+          data: pt_modal: true
           success: (html) ->
-            $html = $ html
             $bootbox = bootbox.dialog html, buttons, { header: title, keyboard: true  }
             $bootbox.find('.modal-body').attr id: 'pt-modal-body'
+
+            # Make close button gray
+            if Object.has attr, 'modalSave'
+              $bootbox.find('.modal-footer a:last').removeClass 'btn-primary'
+              # Make sure rails knows it from pt_modal
+              $ptModal = $ '<input>',
+                type: 'hidden'
+                name: 'pt_modal'
+                value: true
+              $bootbox.find('.modal-body form').append $ptModal
+
+            $(document).trigger 'page:change'
             $el.data 'ptModalLoaded', false


try to fix urls

try to fix urls

--- shorturlgenerator.coffee
+++ shorturlgenerator.coffee
@@ -3,7 +3,7 @@
 urlshortener = require "./urlshortener"

-filepath = __dirname + "sequence"
+filepath = __dirname + "/sequence"
 current = null
 last = null


add warnings.debug

add warnings.debug

--- app/assets/javascripts/uploadcare/utils/warnings.js.coffee
+++ app/assets/javascripts/uploadcare/utils/warnings.js.coffee
@@ -1,17 +1,19 @@
 uploadcare.namespace 'utils', (ns) ->

-  ns.log = (msg) ->
-    if window.console and console.log
-      console.log(msg)
+  ns.log = () ->
+    window.console?.log?(arguments...)
+
+  ns.debug = () ->
+    if window.console?.debug
+      window.console.debug(arguments...)
     else
-      # Uncomment this to see anything in ie8:
-      # $('<div style="display:none!important"/>').text(msg).appendTo('body')
+      ns.log("Debug:", arguments...)

-  ns.warn = (msg) ->
-    if window.console and console.warn
-      console.warn(msg)
+  ns.warn = () ->
+    if window.console?.warn
+      window.console.warn(arguments...)
     else
-      ns.log("Warning: #{msg}")
+      ns.log("Warning:", arguments...)

   messages = {}
   ns.warnOnce = (msg) ->


Don't prematurely optimize to avoid Tether.position()

--- app/js/jail_iframe/classes/icon_buttons.coffee
+++ app/js/jail_iframe/classes/icon_buttons.coffee
@@ -1,18 +1,13 @@
-there_are_icons = false
-
 FactlinkJailRoot.host_loaded_promise.then ->
   FactlinkJailRoot.trigger 'reposition_icons'

-FactlinkJailRoot.on 'reposition_icons', ->
-  if there_are_icons
-    Tether.position()
+FactlinkJailRoot.on 'reposition_icons', -> Tether.position()

 class IconButton
   constructor: (options) ->
     @_targetElement = options.targetElement
     @_targetOffset = options.targetOffset

-    there_are_icons = true
     @$el = $ """
       <factlink-icon-button>
         <factlink-icon-button-bubble>