Fix hasStream, kill the portbuffer interface that we don't need

--- src/lib/Component.coffee
+++ src/lib/Component.coffee
@@ -319,7 +319,6 @@
     @port = @context.port
     @result = @context.result
     @scope = @context.scope
-    @buffer = new PortBuffer(@)
     @activated = false

   # When preconditions are met, set component state to `activated`
@@ -358,17 +357,30 @@
     return @has.apply @, args

   # Returns true if a port has a complete stream in its input buffer.
-  hasStream: (port) ->
-    buffer = @buffer.get port
-    return false if buffer.length is 0
-    # check if we have everything until end of a complete stream
-    received = 0
-    for packet in buffer
-      if packet.type is 'openBracket'
-        ++received
-      else if packet.type is 'closeBracket'
-        --received
-    received is 0
+  hasStream: (args...) ->
+    args = ['in'] unless args.length
+    for port in args
+      portBrackets = []
+      hasData = false
+      validate = (ip) ->
+        console.log ip.type, hasData, portBrackets
+        if ip.type is 'openBracket'
+          portBrackets.push ip.data
+          return false
+        if ip.type is 'data'
+          # Data IP on its own is a valid stream
+          return true unless portBrackets.length
+          # Otherwise we need to check for complete stream
+          hasData = true
+          return false
+        if ip.type is 'closeBracket'
+          portBrackets.pop()
+          return false if portBrackets.length
+          return false unless hasData
+      return false unless @ports[port].has @scope, validate
+    res = true
+    res and= @ports[port].ready @scope for port in args
+    res

   # ## Input processing
   #
@@ -468,57 +480,6 @@
       buf = buf.slice 1
       buf.pop()
     buf
-
-class PortBuffer
-  constructor: (@context) ->
-
-  set: (name, buffer) ->
-    if name? and typeof name isnt 'string'
-      buffer = name
-      name = null
-
-    if @context.scope?
-      if name?
-        @context.ports[name].scopedBuffer[@context.scope] = buffer
-        return @context.ports[name].scopedBuffer[@context.scope]
-      @context.port.scopedBuffer[@context.scope] = buffer
-      return @context.port.scopedBuffer[@context.scope]
-
-    if name?
-      @context.ports[name].buffer = buffer
-      return @context.ports[name].buffer
-
-    @context.port.buffer = buffer
-    return @context.port.buffer
-
-  # Get a buffer (scoped or not) for a given port
-  # if name is optional, use the current port
-  get: (name = null) ->
-    if @context.scope?
-      if name?
-        return @context.ports[name].scopedBuffer[@context.scope]
-      return @context.port.scopedBuffer[@context.scope]
-
-    if name?
-      return @context.ports[name].buffer
-    return @context.port.buffer
-
-  # Find packets matching a callback and return them without modifying the buffer
-  find: (name, cb) ->
-    b = @get name
-    b.filter cb
-
-  # Find packets and modify the original buffer
-  # cb is a function with 2 arguments (ip, index)
-  filter: (name, cb) ->
-    if name? and typeof name isnt 'string'
-      cb = name
-      name = null
-
-    b = @get name
-    b = b.filter cb
-
-    @set name, b

 class ProcessOutput
   constructor: (@ports, @context) ->


Delete old todos

Delete old todos

--- src/honeybadger.coffee
+++ src/honeybadger.coffee
@@ -5,7 +5,6 @@

   configured: false

-  # TODO: Test partial override
   configure: (options = {}) ->
    if @configured == false
      options['disabled'] = false if typeof options.disabled == 'undefined'
@@ -33,7 +32,6 @@
   beforeNotify: (handler) ->
     @beforeNotifyHandlers.push handler

-  # TODO: Test setting options from notify
   notify: (error, options = {}) ->
    return false if !@configured || @configuration.disabled == true
    options['error'] = error if error


decided not to throw an error

decided not to throw an error

--- src/ihackernews.coffee
+++ src/ihackernews.coffee
@@ -29,7 +29,8 @@

     @from: (json) ->
         {comment, id, parentId, postedAgo, postedBy, postId} = json
-        new HNComment id, postedBy, parse_date(postedAgo), comment, json, parentId
+        date = parse_date(postedAgo) or new Date()
+        new HNComment id, postedBy, date, comment, json, parentId

 class HNUserComments extends Timeline
     constructor: (@userid, options) ->
@@ -63,15 +64,22 @@
     hour   = 60 * minute
     day    = 24 * hour

-    [_, num, scale] = /([0-9]+) ([a-z]+)s? ago/.exec(str)
+    match = /([0-9]+) ([a-z]+)s? ago/.exec(str)
+
+    return null unless match?
+
+    [_, num, scale] = match

     diff = switch scale
         when "day",    "days"    then num * day
         when "hour",   "hours"   then num * hour
         when "minute", "minutes" then num * hour
-        else throw Error "couldn't parse date #{str}"
+        else null

-    new Date(now - diff)
+    if diff?
+        new Date(now - diff)
+    else
+        null

 smiley = (name) ->
     eyes = "$^*@;TQs><?uveazoO096~"
@@ -89,4 +97,3 @@
     o = eyes[ num % eyes.length ]

     "#{o}_#{o}"
-


Hack in hoisting into the match macro, need to populate scope correctly

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -308,42 +308,31 @@
 # exp followed by list of definitions
 compiled = (source) ->
   variableCounter = 1
-  compileTop parentize typifyTop astize tokenize "(#{source})"
+  compileTop preCompileTop source

 # single exp
 compiledExp = (source) ->
   variableCounter = 1
-  "(#{compileImpl parentize typify astize tokenize source})"
+  "(#{compileImpl preCompileExp source})"

 # list of definitions
 compileDefinitions = (source) ->
   variableCounter = 1
-  compileWheres parentize typifyDefinitions astize tokenize "(#{source})"
+  compileWheres preCompileDefs source

 # exported list of definitions
 compileDefinitionsInModule = (source) ->
   variableCounter = 1
-  compileWheresInModule parentize typifyDefinitions astize tokenize "(#{source})"
-
-pushScope = ({parent, ids, children}) ->
-  child =
-    parent:
-      parent: parent
-      ids: ids
-    ids: []
-    children: []
-  child.parent.children = children.concat [child]
-  child
-
-topScope = ->
-  parent: null
-  ids: []
-  children: []
-
-addIdToScope = ({parent, ids, children}, addedIds...) ->
-  parent: parent
-  ids: ids.concat addIds
-  children: children
+  compileWheresInModule preCompileDefs source
+
+preCompileExp = (source) ->
+  parentize typify astize tokenize source
+
+preCompileTop = (source) ->
+  parentize typifyTop astize tokenize "(#{source})"
+
+preCompileDefs = (source) ->
+  parentize typifyDefinitions astize tokenize "(#{source})"

 compileTop = (ast) ->
   ast.scope = {}
@@ -370,12 +359,26 @@
   else
     compileDef [name, def]

-compileImpl = (node) ->
+compileImpl = (node, hoistableWheres = []) ->
+  # For now special case match to allow definition hoisting up one level
+  if Array.isArray(node) and node.length > 0
+    [op, args...] = inside node
+    if op.type is 'operator' and op.token is 'match'
+      return trueMacros[op.token] hoistableWheres, args...
+
+    ###
+    if hoistableWheres.length > 0
+      allNames = []
+      for [_, _, names] in hoistableWheres
+        allNames.push names...
+      throw new Error "#{allNames.join ','} used but not defined yet"###
+
   switch node.type
     when 'comment' then 'null'
     when 'data' then 'null'
     when 'type' then 'null'
-    when 'function' then compileFn node
+    when 'function'
+      compileFn node
     else
       if Array.isArray node
         exps = inside node
@@ -503,14 +506,52 @@
 compileFnImpl = (body, wheres, doReturn) ->
   if not body
     throw new Error "Missing definition of a function"
+  # Find invalid (hoistable) wheres and let the function body
+  # define them
+  [validWheres, hoistableWheres] = findHoistableWheres wheres
+  wheresDef = compileWhereImpl validWheres
+  bodyDef = compileImpl body, hoistableWheres
   [
-    compileWhereImpl wheres
+    wheresDef
   ,
     if doReturn
-      "return #{compileImpl body};"
-    else
-      compileImpl body
+      "return #{bodyDef};"
+    else
+      bodyDef
   ].join '\n'
+
+# Returns two lists, first the wheres that can be defined, second
+# the wheres which use an identifier which is not in scope (possibly
+# defined inside match)
+
+  # get list of names from wheres
+  # for each where, get list of used names
+  #   if some used name is not in newly defined or any parent scope
+  #     save it for later, maybe it's defined inside body
+findHoistableWheres = (wheres) ->
+  names = {}
+  hoistable = []
+  valid = []
+  for [pattern, def], i in wheres
+    crawl pattern, (node) ->
+      if node.label is 'name'
+        names[node.token] = yes
+  for [pattern, def], i in wheres
+    log "def", printAst def
+    decided = no
+    crawl def, (node) ->
+      if not node.label
+        name = node.token
+        if not names[name] and not lookupIdentifier name, node
+          if not decided
+            hoistable.push [pattern, def]
+            decided = yes
+          # also save all undefined names
+          (hoistable[hoistable.length - 1][2] ?= []).push name
+    if not decided
+      valid.push [pattern, def]
+  [valid, hoistable]
+

 compileWhereImpl = (wheres) ->
   sorted = (sortTopologically constructDependencyGraph wheres).map ({def}) -> def
@@ -614,6 +655,7 @@
     trigger: pattern.label is 'name'
     assignTo: (exp) ->
       if exp isnt identifier = validIdentifier stripSplatFromName pattern.token
+        addToEnclosingScope identifier, pattern
         [[identifier, exp]]
       else
         []
@@ -722,7 +764,8 @@

 trueMacros =
-  'match': (onwhat, cases...) ->
+  'match': (hoistableWheres, onwhat, cases...) ->
+    #log printAst hoistableWheres
     varNames = []
     if not onwhat
       throw new Error 'match `onwhat` missing'
@@ -737,8 +780,11 @@
       else
         varNames.push vars...
       {conds, preassigns} = constructCond precs
+      hoistedWheres = hoistWheres hoistableWheres, assigns
+      #log "assigns", printAst assigns
       """#{control} (#{conds}) {
            #{preassigns.concat(assigns).map(compileAssign).join '\n'}
+           #{hoistedWheres}
            return #{compileImpl result};
         }"""
       )
@@ -754,6 +800,21 @@
   'list': (items...) ->
     "$listize(#{compileList items})"

+hoistWheres = (possible, assigns) ->
+  defined = (n for [n, _] in assigns)
+  hoisted = []
+  log printAst possible
+  for [pattern, def, names] in possible
+    canHoist = yes
+    for name in names when name not in defined
+      canHoist = no
+    if canHoist
+      hoisted.push [pattern, def]
+  if hoisted.length > 0
+    compileWhereImpl hoisted
+  else
+    ''
+
 toJsString = (token) ->
   "'#{token}'"


Enable printing of types again

Enable printing of types again

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -5039,6 +5039,7 @@
 exports.astizeExpressionWithWrapper = astizeExpressionWithWrapper
 exports.syntaxedExpHtml = syntaxedExpHtml
 exports.syntaxedType = syntaxedType
+exports.prettyPrint = prettyPrint

 # exports.compileModule = (source) ->
 #   """


Fixed origin on sequence pattern matching

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -1054,7 +1054,7 @@
     elemType = ctx.freshTypeVariable star
     # TODO use (Seq c e) instead of (Array e)
     form.tea = new Constrained (concatMap _constraints, (map _tea, elems)),
-      (withOrigin (new TypeApp arrayType, elemType), form)
+      (mapOrigin (new TypeApp (cloneType arrayType), elemType), form)

     for elem in elems
       unify ctx, elem.tea.type,


Fixed the case where nested definition depends on deferred definition from parent scope

--- src/js/app/compilers/teascript/compiler.coffee
+++ src/js/app/compilers/teascript/compiler.coffee
@@ -496,8 +496,8 @@
   isPreTyped: (name) ->
     !!(@preDeclaredType name)

-  isFinallyTyped: (name) ->
-    !!@finalType name
+  isFinallyTyped: (name, scopeIndex) ->
+    !!@finalType name, scopeIndex

   declaredId: (name) ->
     (@_declaration name)?.id
@@ -510,8 +510,9 @@
   type: (name) ->
     (@_declaration name)?.type

-  finalType: (name) ->
-    (type = @type name) and (type not instanceof TempType) and type
+  finalType: (name, scopeIndex) ->
+    (type = (@savedDeclaration name, scopeIndex)?.type) and
+      (type not instanceof TempType) and type

   preDeclaredType: (name) ->
     (@_preDeclaration name)?.type
@@ -520,7 +521,16 @@
     cloneMap @_scope()

   assignType: (name, type) ->
-    if declaration = @_declarationInCurrentScope name
+    @assignTypeTo name, (@_declarationInCurrentScope name), type
+
+  assignTypeLate: (name, scopeIndex, type) ->
+    if scopeIndex isnt @currentScopeIndex()
+      @assignTypeTo name, (@savedDeclaration name, scopeIndex), type
+    else
+      @assignType name, type
+
+  assignTypeTo: (name, declaration, type) ->
+    if declaration
       if declaration.type and declaration.type not instanceof TempType
         throw new Error "assignType: #{name} already has a type"
       declaration.type = type
@@ -528,6 +538,7 @@
     else
       throw new Error "assignType: #{name} is not declared"

+
   assignArity: (name, arity) ->
     (@_declarationInCurrentScope name).arity = arity

@@ -543,8 +554,8 @@
     declaration.final = no
     @_declare name, declaration

-  declareAsFinal: (name) ->
-    (@_declarationInCurrentScope name).final = yes
+  declareAsFinal: (name, scopeIndex) ->
+    (@savedDeclaration name, scopeIndex).final = yes

   _declare: (name, declaration) ->
     declaration.id ?= @freshId()
@@ -576,11 +587,11 @@
     @nameIndex++

   savedDeclaration: (name, scopeIndex) ->
-    if scopeIndex is 0
-      @_declaration name
-    else
+    if scopeIndex isnt @currentScopeIndex()
       saved = @savedScopes[scopeIndex]
       (lookupInMap saved.definitions, name) or @savedDeclaration name, saved.parent
+    else
+      @_declarationInCurrentScope name

   ## Deferring

@@ -589,6 +600,9 @@

   addToDeferred: (binding) ->
     @_scope().deferredBindings.push binding
+
+  addToParentDeferred: (binding) ->
+    @_outerScope().deferredBindings.push binding

   addToDefinedNames: (binding) ->
     @_currentDefinition()?.definedNames?.push binding
@@ -1254,6 +1268,7 @@
       currentType = substitute ctx.substitution, type
       ctx.addToDeferred
         name: name
+        scopeIndex: ctx.currentScopeIndex()
         type: currentType
         constraints: constraints
         polymorphic: polymorphic
@@ -1269,11 +1284,11 @@
   precs: precs ? []
   assigns: assigns ? []

-inferType = (ctx, name, type, constraints, polymorphic) ->
+inferType = (ctx, name, type, constraints, polymorphic, scopeIndex) ->
   # For explicitly typed bindings, we need to check that the inferred type
   #   corresponds to the annotated
   currentType = substitute ctx.substitution, type
-  if ctx.isFinallyTyped name
+  if ctx.isFinallyTyped name, scopeIndex or ctx.currentScopeIndex()
     # TODO: check class constraints
     if not includesJsType currentType.type
       # Check the declared type
@@ -1297,7 +1312,6 @@
         if _notEmpty retainedConstraints
           ctx.extendSubstitution substitutionFail "#{name}'s context is too weak, missing #{listOf (map printType, retainedConstraints)}"
   else
-    # log name, "constraints", (substituteList ctx.substitution, constraints)
     if not ctx.isAtNonDeferrableDefinition()
       {success, error} = deferConstraints ctx,
         (substituteList ctx.substitution, constraints),
@@ -1312,12 +1326,12 @@
     if includesJsType currentType.type
       ctx.extendSubstitution substitutionFail "#{name}'s inferred type #{plainPrettyPrint currentType} includes Js"
     else
-      ctx.assignType name,
+      ctx.assignTypeLate name, scopeIndex ? ctx.currentScopeIndex(),
         if polymorphic
           quantifyUnbound ctx, (addConstraints currentType, retainedConstraints)
         else
           toForAll currentType
-  ctx.declareAsFinal name
+  ctx.declareAsFinal name, scopeIndex ? ctx.currentScopeIndex()
   if deferredConstraints
     ctx.addToScopeConstraints deferredConstraints

@@ -1384,24 +1398,31 @@
     groups = topologicallySortedGroups ctx.deferredBindings()
     for group in groups
       bindings = newMap()
+      shouldBeDeferred = no
       for binding in ctx.deferredBindings() when inSet group, binding.name
         added = (lookupOrAdd bindings, binding.name, (types: []))
+        added.scopeIndex = binding.scopeIndex
         added.types.push binding.type
         added.constraints = binding.constraints
         added.polymorphic = binding.polymorphic
         added.deps = binding.deps
         for dep in binding.deps
-          (lookupOrAdd bindings, dep.name, (types: [])).types.push dep.type
+          added = (lookupOrAdd bindings, dep.name, (types: []))
+          added.scopeIndex ?= dep.scopeIndex
+          added.types.push dep.type

       # names = concatConcatMaps map (({name, type}) -> newMapWith name, type), groupBindings
       # First get rid of instances of already resolved types
       unresolvedNames = newMap()
       for name, binding of values bindings
-        if canonicalType = ctx.finalType name
+        if canonicalType = ctx.finalType name, binding.scopeIndex
           for type in binding.types
             unify ctx, type.type, (mapOrigin (freshInstance ctx, canonicalType).type, type.type.origin)
         else
-          addToMap unresolvedNames, name, binding
+          if (ctx.isDeclared name) and (not ctx.isCurrentlyDeclared name) and not binding.deps
+            shouldBeDeferred = yes
+          else
+            addToMap unresolvedNames, name, binding

       # Now assign the same type to all occurences of the given type and unify
       for name, binding of values unresolvedNames
@@ -1413,25 +1434,28 @@
           # log "done unifying one"

         # have to promote constraints from just compiled dependencies
-        depConstraints = concat (for dep in binding.deps or [] when cononicalType = ctx.finalType dep.name
+        depConstraints = concat (for dep in binding.deps or [] when cononicalType = ctx.finalType dep.name, binding.scopeIndex
           constraintsFromCanonicalType ctx, cononicalType, dep.type)
         allConstraints = (join binding.constraints or [], depConstraints)

-        # If the thing is not declared it must be coming from an outer scope
-        # add it is a missing name to the current definition
-
-        if (not ctx.isCurrentlyDeclared name)
-          if ctx.isInTopScope()
-            # TODO: error missing name
-          else
-            # TODO: add origin to canonicalType
-            ctx.addToDeferredNames
-              name: name
-              type: addConstraints canonicalType, allConstraints
+        # ---- If the thing is not declared it must be coming from an outer scope
+        # ---- add it as a missing name to the current definition
+        # ^ that should happen automatically when we dont infer type
+        # Instead push the current deferred binding with deps to outer scope
+
+        if shouldBeDeferred
+          # TODO: add origin to canonicalType
+          ctx.addToParentDeferred
+            name: name
+            scopeIndex: binding.scopeIndex
+            type: addConstraints canonicalType, allConstraints
+            constraints: allConstraints
+            polymorphic: binding.polymorphic
+            deps: binding.deps
         else
           # log binding.constraints, depConstraints
           inferType ctx, name, canonicalType,
-            allConstraints, binding.polymorphic
+            allConstraints, binding.polymorphic, binding.scopeIndex
   ctx.deferredBindings().length = 0 # clear

 compileDeferred = (ctx) ->
@@ -1521,6 +1545,7 @@
             docs: documentation

       newParamType = (param) ->
+        param.scope = ctx.currentScopeIndex()
         withOrigin (ctx.freshTypeVariable star), param
       paramTypeVars = map newParamType, params
       paramTypes = map (__ toForAll, toConstrained), paramTypeVars
@@ -2519,7 +2544,7 @@
     {error:
       substitutionFail
         message: "Constraint #{printType ambiguous[0]} is ambiguous for inferred type #{printType finalType}"
-        conflicts: [type.origin, ambiguous[0].origin]}
+        conflicts: [type.type.origin, ambiguous[0].origin]}
   else
     success: [deferred, retained]

@@ -2760,7 +2785,7 @@
         contextType instanceof TempType
       # Typing deferred, use an impricise type var
       type = toConstrained ctx.freshTypeVariable star
-      ctx.addToDeferredNames {name: symbol, type: (mapOrigin type, atom)}
+      ctx.addToDeferredNames {name: symbol, type: (mapOrigin type, atom), scopeIndex: ctx.currentScopeIndex()}
       nameTranslate ctx, atom, symbol, type
     else
       # log "deferring in rhs for #{symbol}", ctx._deferrableDefinition().name
@@ -5411,7 +5436,7 @@

 finalizeTypes = (ctx, ast) ->
   visitExpressions ast, (expression) ->
-    if expression.label is 'name' and (type = (ctx.typeForId expression.id) or (ctx.finalType expression.symbol))
+    if expression.label is 'name' and expression.scope and (type = (ctx.finalType expression.symbol, expression.scope))
       expression.tea = type
     else if expression.tea
       expression.tea = substitute ctx.substitution, expression.tea


Split output and unbold steps

Split output and unbold steps

--- app/assets/javascripts/machine.js.coffee
+++ app/assets/javascripts/machine.js.coffee
@@ -50,7 +50,8 @@
 # states: OFF, WAITING, RUNNING
 class Machine
   MILLIS_FOR_BOLD = 700
-  MILLIS_FOR_OUTPUT = 500
+  MILLIS_FOR_OUTPUT = 0
+  MILLIS_FOR_UNBOLD = 500
   MILLIS_FOR_MOVED_ARROW = 500

   constructor: (line_height, setTimeout, code_mirror) ->
@@ -121,11 +122,12 @@

   _continueRun: ->
     @_boldNextLine =>
-      @_executeAndUnboldNextLine =>
-        @_showNextLine =>
-          @refreshDisplays()
-          if @next_line != null
-            @_continueRun()
+      @_executeNextLine =>
+        @_unboldNextLine =>
+          @_showNextLine =>
+            @refreshDisplays()
+            if @next_line != null
+              @_continueRun()

   _boldNextLine: (callback) ->
     from = { line: @next_line - 1, ch: 0 }
@@ -134,12 +136,15 @@
       @code_mirror.markText from, to, className: 'running'
     @setTimeout callback, MILLIS_FOR_BOLD

-  _executeAndUnboldNextLine: (callback) ->
+  _executeNextLine: (callback) ->
     output = @_executeNextLineGettingOutput()
     $one('div.machine .before-cursor').textContent += output
+    @setTimeout callback, MILLIS_FOR_OUTPUT
+
+  _unboldNextLine: (callback) ->
     @being_bolded_marker.clear()
     @being_bolded_marker = null
-    @setTimeout callback, MILLIS_FOR_OUTPUT
+    @setTimeout callback, MILLIS_FOR_UNBOLD

   _showNextLine: (callback) ->
     if @next_line


http: Take documentRoot from constructor argument

--- http.coffee
+++ http.coffee
@@ -40,6 +40,7 @@
 class HTTPHandler
   constructor: (opts) ->
     @serverName = opts?.serverName ? DEFAULT_SERVER_NAME
+    @documentRoot = opts?.documentRoot ? STATIC_DIR

   setServerName: (name) ->
     @serverName = name
@@ -69,7 +70,7 @@
     else if filepath is '/500'
       @serverError req, callback
     else
-      @respondStaticPath "#{STATIC_DIR}/#{filepath[1..]}", req, callback
+      @respondStaticPath "#{@documentRoot}/#{filepath[1..]}", req, callback

   createHeader: (params) ->
     protocol = params.protocol ? 'HTTP/1.1'


update atom config

update atom config

--- atom.symlink/config.cson
+++ atom.symlink/config.cson
@@ -18,6 +18,7 @@
       "linter-elixirc"
       "autocomplete-elixir"
       "linter-htmlhint"
+      "linter-jshint"
     ]
     excludeVcsIgnoredPaths: false
     ignoredNames: [
@@ -27,6 +28,8 @@
       "vendor"
       ".bundle"
       "coverage"
+      "*.class"
+      ".DS_Store"
     ]
     projectHome: "/Users/steveagalloco/Projects"
     themes: [
@@ -40,6 +43,7 @@
     showIndentGuide: true
     showInvisibles: true
   "git-blame": {}
+  "go-config": {}
   "go-plus": {}
   linter:
     subtleLinterErrors: [
@@ -47,8 +51,14 @@
     ]
   "linter-elixirc":
     elixircExecutablePath: "/usr/local/bin/elixirc"
-  "linter-jshint": {}
+  "linter-eslint":
+    fixOnSave: true
+  "linter-jshint":
+    disableWhenNoJshintrcFileInPath: true
   "linter-rubocop": {}
+  "linter-rust":
+    cargoPath: "/usr/local/bin/cargo"
+    rustcPath: "/usr/local/bin/rustc"
   minimap: {}
   "release-notes":
     viewedVersion: "0.89.0"
@@ -64,5 +74,4 @@
     colorStatusIndicatorsInTreeView: true
   welcome:
     showOnStartup: false
-  "xml-formatter":
-    numberCharIndent: 4
+  "xml-formatter": {}


Litt enklere passord

Litt enklere passord

--- app/assets/javascripts/pages/admin/controllers/users_controller.js.coffee
+++ app/assets/javascripts/pages/admin/controllers/users_controller.js.coffee
@@ -58,8 +58,8 @@
   # Generates a random password
   random_password: ->
     password = ""
-    pool = "1234567890abcdefghijkmnopqrstuvwxyz1234567890ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890!@#$%&*_+=?:;"
-    len = 12
+    pool = "23456789abcdefghjkmnpqrstuvwxyz1234567890ABCDEFGHJKLMNPQRSTUVWXYZ1234567890!@+=?"
+    len = 10
     a = 0

     while a < len


Fix default end time

Fix default end time


Machine: Use updated domain name as machine label.

--- client/Main/providers/machine.coffee
+++ client/Main/providers/machine.coffee
@@ -51,7 +51,12 @@
       @status, @uid, @domain, @queryString } = @jMachine

   getName: ->
-    @label or @ipAddress or @uid or "one of #{KD.nick()}'s machine"
+    {domain, uid, label, ipAddress} = this
+
+    if domain.indexOf(uid) is -1 # is domain updated
+      return domain.split('.').first
+
+    return label or ipAddress or uid or "one of #{KD.nick()}'s machine"

   getBaseKite: (createIfNotExists = yes)->


FIX : do not try to save deleted message

--- client/app/components/compose.coffee
+++ client/app/components/compose.coffee
@@ -119,6 +119,9 @@
     hasChanged: (props, state) ->
         (props.lastUpdate and props.lastUpdate isnt state.date) or false

+    resetChange: ->
+        delete @props.lastUpdate
+
     componentWillUnmount: ->
         @closeSaveDraft @state, hasChanged: @hasChanged(@props, @state)

@@ -139,7 +142,6 @@
                 if error? or not message?
                     msg = "#{t "message action draft ko"} #{error}"
                     LayoutActionCreator.alertError msg
-                    success error, message
                     return

                 fetch error, message
@@ -325,6 +327,10 @@
         return if @isNew()

         doDelete = =>
+            # Do not try to save client changes
+            # when componentWillUnmount
+            @resetChange()
+
             messageID = @state.id
             MessageActionCreator.delete {messageID}
             LayoutActionCreator.hideModal()
@@ -407,22 +413,12 @@
         else
             confirmMessage = t 'mail confirm delete nosubject'

-        doDelete = =>
-            @redirect
-                direction: 'first'
-                action: 'account.mailbox.messages'
-                fullWidth: true
-                parameters: [
-                    @props.selectedAccountID
-                    @props.selectedMailboxID
-                ]
-
         @showModal
             title       : t 'mail confirm delete title'
             subtitle    : confirmMessage
             closeLabel  : t 'mail confirm delete cancel'
             actionLabel : t 'mail confirm delete delete'
-        , doDelete
+        , @finalRedirect

     toggleField: (event) ->
         ref = event.currentTarget.getAttribute 'data-ref'


Generalize behaviour of init.coffee.

Generalize behaviour of init.coffee.

--- init.coffee
+++ init.coffee
@@ -48,15 +48,12 @@
 	needAnyDB()
 	mysqlConnection = anyDB.createConnection(config.MYSQL_DATABASE_URL)
 	utils.migration.getCurrentRevision mysqlConnection, (error, result) ->
-		if error?
-			console.log error
-			process.exit 1
-		else
-			newest = utils.migration.getNewestRevision()
-			status = if result < newest then 'needs update' else 'up to date'
-			console.log "init.js with #{newest + 1} revisions on board."
-			console.log "Current revision is #{result} (#{status})."
-			process.exit 0
+		checkError error
+		newest = utils.migration.getNewestRevision()
+		status = if result < newest then 'needs update' else 'up to date'
+		console.log "init.js with #{newest + 1} revisions on board."
+		console.log "Current revision is #{result} (#{status})."
+		process.exit 0

 createDatabase = (arg, callback) ->