finetune override from rsyncOpts

finetune override from rsyncOpts

--- app/templates/gulpfile.coffee
+++ app/templates/gulpfile.coffee
@@ -259,16 +259,15 @@
     isToRemote: true
   }, opts

+  dest = rsyncOpts.dest || conf.rsync[type].dest
+  src = rsyncOpts.src || conf.rsync[type].src
+
   if opts.isToRemote
-    dest = "#{scrt.username}@#{scrt.domain}:#{conf.rsync[type].dest}"
-    src = conf.rsync[type].src
+    dest = "#{scrt.username}@#{scrt.domain}:#{dest}"
   else
-    dest = conf.rsync[type].dest
-    src = "#{scrt.username}@#{scrt.domain}:#{conf.rsync[type].src}"
+    src = "#{scrt.username}@#{scrt.domain}:#{src}"

   rsyncOpts = extend {
-    dest: dest
-    src: src
     dryRun: opts.isDry
     exclude: conf.rsync[type].exclude || ""
     port: conf.ssh.port
@@ -276,7 +275,10 @@
     recursive: true
     compareMode: "checksum"
     args: ["--verbose"]
-  }, rsyncOpts
+  }, rsyncOpts, {
+    dest: dest
+    src: src
+  }

   rsync rsyncOpts, (error, stdout, stderr, cmd) ->
     if error


fixed indent

fixed indent

--- app/translations/en_us.coffee
+++ app/translations/en_us.coffee
@@ -926,13 +926,13 @@
           and to the application of this knowledge to benefit the people of the state, the nation, and the world.
         '''

-        natgeo:
-          name: 'National Geographic'
-          url: 'http://www.nationalgeographic.com'
-          image: 'images/about/organizations/natgeo.jpg'
-          description: '''
-            National Geographic is a global nonprofit membership organization driven by a passionate belief in the power of science, exploration and storytelling to change the world. Working to inspire, illuminate and teach, National Geographic reaches more than 700 million people a month through its media platforms, products, events and experiences.
-          '''
+      natgeo:
+        name: 'National Geographic'
+        url: 'http://www.nationalgeographic.com'
+        image: 'images/about/organizations/natgeo.jpg'
+        description: '''
+          National Geographic is a global nonprofit membership organization driven by a passionate belief in the power of science, exploration and storytelling to change the world. Working to inspire, illuminate and teach, National Geographic reaches more than 700 million people a month through its media platforms, products, events and experiences.
+        '''

       mnZoo:
         name: 'Minnesota Zoo'


Get individual notifications

Get individual notifications

--- app/routes/application.coffee
+++ app/routes/application.coffee
@@ -14,6 +14,9 @@
     that = @
     store = @get "store"
     allEvents =
+      analysis_new: (data)->
+        store.push store.normalize "analyses", data
+
       analysis_updated: (data)->
         risk = data.risk

@@ -34,10 +37,7 @@

       file_new: (data)->
         Notify.info "New file added"
-        project = store.push store.normalize "project", data.project
-        file = store.push store.normalize "file", data.file
-        for analysis in data.analyses
-          store.push store.normalize "analysis", analysis
+        file = store.push store.normalize "file", data
         project.set "lastFile", file

       file_updated: (data) ->


Fix typo

Fix typo

--- lib/Format.coffee
+++ lib/Format.coffee
@@ -63,7 +63,6 @@

   fmt += ' ' + serialize arg for arg in args if args.length
   fmt = fmt.replace(REGEX.escape, '%') if fmt.replace?
-
   serialize fmt

 module.exports = format


stub render

stub render

--- apps/order/test/routes.coffee
+++ apps/order/test/routes.coffee
@@ -6,7 +6,7 @@
 describe 'Order routes', ->
   beforeEach ->
     @req = { params: {} }
-    @res = { render: sinon.stub(), locals: { sd: {} } }
+    @res = { render: sinon.stub(), redirect: sinon.stub(), locals: { sd: {} } }

   describe '#index', ->


cleanup logging

cleanup logging

--- lib/client.coffee
+++ lib/client.coffee
@@ -132,10 +132,8 @@

   getCompletions: (filePath, bufferText, offset, noOfAutocompleteSuggestions, callback) =>
     tempFilePath = getTempDir() + filePath
-    console.log(['client.getCompletions', filePath, bufferText, offset, noOfAutocompleteSuggestions, callback])
     fs.outputFile(tempFilePath, bufferText, (err) =>
       if (err)
-        consolelog(['client.getCompletions error'])
         throw err
       else
         msg =


dog balls

dog balls

--- lib/bundle.coffee
+++ lib/bundle.coffee
@@ -8,7 +8,7 @@

 # helpers
 anonWrap = (code) ->
-  "(function(){\n#{code}\n})();"
+  "(function(){\n#{code}\n}());"

 makeWrapper = (ns, fnstr, hasArbiter) ->
   return anonWrap if !fnstr


improve config documentations

improve config documentations

--- lib/config.coffee
+++ lib/config.coffee
@@ -54,15 +54,15 @@
     # project specific configuration file name
     projectConfigFile: "_mdwriter.cson"
     # text styles related
-    #
-    # for `regexBefore`, `regexAfter`, DO NOT use capture group, it could break things!
-    # use non-capturing group `(?:)` instead.
     textStyles:
       code: before: "`", after: "`"
       bold: before: "**", after: "**"
       italic: before: "_", after: "_"
       keystroke: before: "<kbd>", after: "</kbd>"
       strikethrough: before: "~~", after: "~~"
+      # for `regexBefore`, `regexAfter`,
+      # DO NOT use capture group, it could break things!
+      # use non-capturing group `(?:)` instead.
       codeblock:
         before: "```\n"
         after: "\n```"
@@ -75,10 +75,18 @@
       h3: before: "### "
       h4: before: "#### "
       h5: before: "##### "
-      ul: before: "- ", regexBefore: "(?:-|\\*|\\d+\\.)\\s"
-      ol: before: "0. ", regexBefore: "(?:-|\\*|\\d+\\.)\\s"
-      task: before: "- [ ] ", regexBefore: "(?:- \\[ ]|- \\[x]|- \\[X]|-|\\*)\\s"
-      taskdone: before: "- [x] ", regexBefore: "(?:- \\[ ]|- \\[x]|- \\[X]|-|\\*)\\s"
+      ul:
+        before: "- ",
+        regexBefore: "(?:-|\\*|\\d+\\.)\\s"
+      ol:
+        before: "1. ",
+        regexBefore: "(?:-|\\*|\\d+\\.)\\s"
+      task:
+        before: "- [ ] ",
+        regexBefore: "(?:- \\[ ]|- \\[x]|- \\[X]|-|\\*)\\s"
+      taskdone:
+        before: "- [x] ",
+        regexBefore: "(?:- \\[ ]|- \\[x]|- \\[X]|-|\\*)\\s"
       blockquote: before: "> "
     # image tag template
     imageTag: "![<alt>](<src>)"


add some int64 const functions for ejsval bools

--- lib/consts.coffee
+++ lib/consts.coffee
@@ -42,3 +42,5 @@
         constant.constant_val = c
         constant

+exports.ejsval_true  = () -> exports.int64_lowhi(0xfff98000, 0x00000001)
+exports.ejsval_false = () -> exports.int64_lowhi(0xfff98000, 0x00000000)


Set viewbox for "finished" icon

Set viewbox for "finished" icon

Otherwise it fails to render properly

--- tutor/src/components/scores/pie-progress.cjsx
+++ tutor/src/components/scores/pie-progress.cjsx
@@ -87,7 +87,7 @@
         {if progress is 100 then q4}
       </svg>
     finishedIcon =
-      <svg className='finished'>
+      <svg width="#{size}" height="#{size}" viewBox={"0 0 24 24"} className='finished'>
         <g>
           <circle className="slice #{lateClass}" cx="11.778" cy="12.296" r="12"/>
           <g>


Correct a problem when the partial page render reponse included additional zones and zone content

--- tapestry-core/src/main/coffeescript/META-INF/modules/core/pageinit.coffee
+++ tapestry-core/src/main/coffeescript/META-INF/modules/core/pageinit.coffee
@@ -189,7 +189,7 @@
             zone = spi.wrap id

             if zone
-              zone.trigger events.zone.update, content
+              zone.trigger events.zone.update, { content }

           # Invoke the callback, if present.  The callback may do its own content updates.
           callback and callback(response)


Went back to master branch translation file, for posterity

--- app/translations/en_us.coffee
+++ app/translations/en_us.coffee
@@ -12,7 +12,6 @@
     subheading: "Massive galaxies warp space-time around themselves, bending light rays so that we can see around them. They're the Universe's own telescopes, but these gravitational lenses are very rare: we need your help to find them!"
     discover: "Discover Lenses"
     discover_snippet: "Help scientists identify these very rare astronomical objects."
-    refine_snippet: "Help scientists refine a sample of Space Warps lens candidates."
     learn: "Learn about Lenses"
     learn_snippet: "Find out more about the lenses you might spot in Space Warps."
     news: "Latest News"
@@ -53,8 +52,6 @@
     needles_text_2: "The ideal solution would be to get a computer to look through all of the images, but unfortunately this is not a straightforward solution. Teaching a computer to recognize the effects of gravitational lensing is not too difficult, but they can be easily confused by galaxies that look very similar to a distorted background galaxy. Also in order for the computer to run fast enough to analyse lots of images quickly, they have to cut a lot of corners, and this makes them less effective."
     discovering: "Discovering Lenses: A Human-Computer Partnership"
     discovering_text: "Human beings have a remarkable ability to recognise patterns and detect the unusual with only minimal training. With a basic understanding of what the distorted images of galaxies that have passed through a gravitational lens look like, participants in the SpaceWarps project can help discover new examples of this amazing phenomenon, and enable our survey scientists to carry out new investigations of stars and dark matter in the universe. We will be doing two types of lens search. In our blind searches, we’ll be asking volunteers to spot signs of gravitational lensing in images of the sky taken as part of the CFHT (Canada-France-Hawaii Telescope) legacy survey. This survey has been searched by computers, but we’re pretty sure they didn’t catch all the lenses to be found! These results will help us re-train the computers to do better on larger surveys in future. Then, in our targeted searches, in other upcoming sky surveys, we’ll be showing participants galaxies and groups of galaxies that our computers have selected as possibly being gravitational lenses. The task will then be to assess whether or not they actually are! In both cases, there will be confusing objects around - the challenge is to come up with the most plausible explanation for what is going on, in collaboration with the rest of the SpaceWarps community. Do you think you can spot outer space being warped? We do!"
-    searching: "Searching in Stages"
-    searching_text: "Each lens search has two stages. In the first one, we ask the community to 'spot' gravitational lens systems, with the emphasis on completeness. At this stage, we don't want to miss anything interesting! If in doubt, mark it and discuss it in Talk. In the second stage, 'refine', things are a little different: by this point, we'll have identified (together) several thousand lens candidates, and it's time to start refining this sample to identify the really promising ones. We want to reject the 'false positives', and focus on the objects that really look like lenses. We use the same interface - just with a more critical eye. The goal is to assemble, together, a small list of very good lens candidates for the Science Team to follow up with big telescopes. And big telescope time is not cheap, so we're after the very best lens candidates! You'll know which stage we are on by the color of the website: if it's blue, we're trying to spot the candidates, and if it's orange, we're trying to refine them."
     science_team: "Science Team"
     marshall_bio: "Phil is an astronomer at the University of Oxford Physics department. After deciding he liked doing maths and physics problems at school and university enough to want to make up his own questions, Phil did a PhD at Cambridge University on using gravitational lensing to map the distribution of dark matter in galaxy clusters. He then did several postdoctoral research jobs in California, using strong lenses to weigh galaxies, and investigating automated strong lens detection. He knows very well how hard it is to teach a robot to spot lenses - or at least, how hard it is to teach them not to be confused by large numbers of galaxies that are not lenses."
     verma_bio: "Aprajita is an astronomer at the University of Oxford, and previously worked at Imperial College London and the Max Planck Institute for Extraterrestrial Physics (Germany). She became fascinated by gravitational lenses during her PhD in which she studied some of the most luminous galaxies seen in the Universe, some of which have been gravitationally lensed. Aprajita is interested in making use of gravitational lenses as natural telescopes to study the galaxies that are being lensed in more detail than would normally be possible, as well as measuring the light and dark matter in the lensing galaxies themselves. Having worked with citizen scientists looking for gravitational lenses in Galaxy Zoo, she was inspired by their efforts, motivating the emergence of Space Warps."
@@ -106,13 +103,13 @@
     group_lenses_text_2: "Groups or clusters of massive red galaxies can lens background galaxies into long, bright arcs. These arcs are typically less curved and at larger separations from the lensing galaxies than would be seen for a single lensing galaxy. This is because groups and clusters of galaxies are much more massive than a single galaxy and so the deflection of the image (or separation) can be larger."
     group_lenses_text_3: "Groups and clusters of massive galaxies can form many images, often of more than one background galaxy. The bright images curve around the entire lens that can be several galaxies."

-    rings_spirals: "Star-forming galaxies"
+    rings_spirals: "Rings & Spirals"
     loners: "Loners"
     lightweights: "Lightweights"
     mergers_neighbors: "Mergers & Neighbors"

-    rings_spirals_text_1: "Star-forming galaxies are common and show a blue component of emission including spiral arms, a ring, or star-forming clumps. These are not massive galaxies but the active star-formation produces a lot of blue light. Spiral arms are a common feature, such as found in our own Milky Way. Ring galaxies may be formed by the interaction of two star-forming galaxies. Irregular and merging galaxies (those without a well defined shape) are often dominated by blue light from star-fromation. Depending on orientation, spiral arms and rings can look similar to gravitationally lensed images of a background galaxy, these are common false positives. They often have red bulges that can mimic a massive lensing galaxy; but the arms or rigns don't have the right shape to be lensed arcs. Sometimes star forming clumps in a galaxy can also be symmetrically arranged arounf the red core of a galaxy and resemble gravitationally lensed quasars. Some tips on how to distinguish these false positives from the real thing are below."
-    rings_spirals_text_2: "These often have yellow "bulges" and blue "spiral arms." Unlike gravitationally lensed arcs, the arms don't trace a rough circle around the bulge, and they are usually accompanied by some fuzzy distribution of light."
+    rings_spirals_text_1: "Ring and Spiral galaxies are common galaxy types. These are not massive galaxies but are typically actively forming-stars and therefore the rings and arms look blue. Spiral arms are a common feature, such as found in our own Milky Way. Ring galaxies may be formed by the interaction of two star-forming galaxies. Depending on orientation, spiral arms and rings can look similar to gravitationally lensed images of a background galaxy, these are common false positives. Some tips on how to distinguish them from the real thing are below."
+    rings_spirals_text_2: "These often have yellow "bulges" and blue "spiral arms." Unlike arcs, the arms don't trace a rough circle around the bulge, and is usually accompanied by some fuzzy distribution of light."
     rings_spirals_text_3: "Their yellow bulges are surrounded by complete, oval rings of blue light. In contrast, Einstein Rings are typically more circular, and brighter."

     loners_text_1: "We have put a selection of objects that look like blue arcs in this page, however these are not gravitationally lensed systems. The easiest check is that there is no plausible massive gravitational lens in their vicinity. See below for some examples."
@@ -124,7 +121,7 @@
     lightweights_text_2: "Sometimes a yellow/red galaxy is present near a blue arc but its too small to create such a large or separated arc. The arc might appear too curved or curved in the wrong direction (it doesn't encircle the lensing galaxy). In the case above, the arc is too far away to be lensed by such a small galaxy."
     lightweights_text_3: "The most massive galaxies have bulges of yellow/red stars – bulgeless, blue galaxies usually don't have enough mass to strongly deflect light. Such galaxies are less likely to act as lenses."

-    mergers_neighbors_text_1: "As you may have seen in Galaxy Zoo, galaxies are moving objects that sometime collide and interact. This produces a single more massive galaxy at the end, but as the interaction is very complex and slow, spiral arms and star forming regions from both of the merging galaxies can be tidally distorted and drawn out. Usually, these merging galaxies can be identified due to their similar colors since such galaxies have roughly similar stellar population and ages. Below we give an example of how such mergers can be mistaken to be a lensing galaxy. Arms & tidal tails around the central redder bulge of the merging galaxies can end up looking similar to long blue arcs seen in lensing by galaxy groups."
-    mergers_neighbors_text_2: "Sometimes two neighbouring galaxies, that aren't physically associated to each other, but are simply next to each other can look like a lens. This is just a chance or random alignment of galaxies. For lensing candidates remember to look for an arc that is defined and curved around a plausible lensing galaxy, and also look for hints of a counter image. If things look very nebulous & fuzzy or curved the wrong way, it's most likely this isn't a lens. Below we give examples of how such mergers or neighbours can be mistaken to be lensed systems."
-    mergers_neighbors_text_3: "Two galaxies merging together can look a bit like a lens system. Here two spiral galaxies appear to be merging with multiple arms visible and a fuzzy distribution of light. Sometimes mergers cause displaced arms, or tidal tails. Unlike arcs, the arms or tidal tails do not trace a circle around the red bulge."
-    mergers_neighbors_text_4: "Sometimes two neighbouring galaxies can look a bit like a lens system. In these cases, the supposed "arc" is usually not bright enough, it is not clearly defined or is fuzzy or the "lens" is not massive enough (as above)."
+    mergers_neighbors_text_1: "As you may have seen in Galaxy Zoo, galaxies are moving objects that sometime collide and interact. This produces a single more massive galaxy at the end, but as the interaction is very complex and slow, spiral arms and star forming regions from both of the merging galaxies can be tidally distorted and drawn out. Usually, these merging galaxies can be identified due to their similar colors since such galaxies have roughly similar stellar population and ages. Below we give an example of how such mergers can be mistaken to be a lensing galaxy. These arms & tidal tails can end up looking similar to long blue arcs seen in lensing around the central redder bulge of the merging galaxies. Below we give an example of how such mergers can be mistaken to be a lensing galaxy."
+    mergers_neighbors_text_2: "Sometimes two neighbouring galaxies, that aren't physically associated to each other, but are simply next to each other can look like a lens. This is just a chance or random alignment of galaxies. For lensing candidates remember to look for an arc that is defined and curved around a plausible lensing galaxy, and also look for hints of a counter image. If things look very nebulous & fuzzy or curved the wrong way, it's most likely this isn't a lens. See the example below."
+    mergers_neighbors_text_3: "Two galaxies merging together can look a bit like a lens system. Her two spiral galaxies appear to be merging with multiple arms and a fuzzy distribution of light. Sometimes mergers cause displaced arms, or tidal tails. Unlike arcs, the arms or tidal tails do not trace a circle around the red bulge."
+    mergers_neighbors_text_4: "Sometimes two neighbouring galaxies can look a bit like a lens system. In these cases usually the supposed "arc" is not bright enough, it is not clearly defined or is fuzzy or the "lens" is not massive enough (as above)."


Fix regression

Fix regression

Having no encrypt sources caused the submit callback no to be fired.
Therefore the single encryption use case was not functioning anymore.

--- js/gpg_form_encryptor.coffee
+++ js/gpg_form_encryptor.coffee
@@ -87,10 +87,13 @@

 group_encryption = (form, values, callback) ->
   elements = $("*[data-encrypt-source]")
-  buffer = collect_sources(elements)
   encryption_source_names = find_names_for(form, elements)
-  wipe_source_fields(values, encryption_source_names)
-  write_target(buffer, values, callback)
+  if encryption_source_names.length
+    buffer = collect_sources(elements)
+    wipe_source_fields(values, encryption_source_names)
+    write_target(buffer, values, callback)
+  else
+    callback()

 collect_sources = (elements)->
   buffer = ""


*twitch* we need to manually stick in signed_request because Facebook

--- src/Carrot.coffee
+++ src/Carrot.coffee
@@ -26,9 +26,9 @@
     Ok: 'Operation successful.'
     Error: 'Operation unsuccessful.'

-  @trackLoad: () ->
+  @trackLoad: (signedRequest) ->
     req = new XMLHttpRequest()
-    req.open 'GET', 'https://gocarrot.com/tracking'
+    req.open 'GET', 'https://gocarrot.com/tracking?signed_request=' + signed_request
     req.send()

   constructor: (appId, udid, appSecret, hostname) ->
@@ -165,4 +165,3 @@
     );

 (exports ? this).Carrot = Carrot
-Carrot.trackLoad();


fixed showDelay setting

fixed showDelay setting

--- lib/autohide-tree-view.coffee
+++ lib/autohide-tree-view.coffee
@@ -69,7 +69,7 @@
     return unless treeView?.isVisible()
     treeViewEl = atom.views.getView treeView
     width = treeViewEl.querySelector('.tree-view').clientWidth
-    if width > treeViewEl.clientWidth then noDelay = true
+    if width > treeViewEl.clientWidth > atom.config.get 'autohide-tree-view.minimizedWidth' then noDelay = true
     transitionDelay = if noDelay then 0 else atom.config.get 'autohide-tree-view.showDelay'
     treeViewEl.style.transitionDelay = "#{transitionDelay}s"
     treeViewEl.style.width = "#{width}px"
@@ -79,7 +79,7 @@
     return unless treeView?.isVisible()
     treeViewEl = atom.views.getView treeView
     width = atom.config.get 'autohide-tree-view.minimizedWidth'
-    transitionDelay = atom.config.get 'autohide-tree-view.hideDelay'
+    transitionDelay = if noDelay then 0 else atom.config.get 'autohide-tree-view.hideDelay'
     treeViewEl.style.transitionDelay = "#{transitionDelay}s"
     treeViewEl.style.width = "#{width}px"
     treeView.unfocus()


Export xpub from UI

Export xpub from UI

--- app/src/controllers/wallet/dialogs/wallet_dialogs_xpub_dialog_view_controller.coffee
+++ app/src/controllers/wallet/dialogs/wallet_dialogs_xpub_dialog_view_controller.coffee
@@ -6,8 +6,9 @@
   _xpub: null

   show: ->
-    @_xpub = "salut"
-    super
+    @_getAccount().getExtendedPublicKey (xpub) =>
+      @_xpub = xpub
+      super

   onAfterRender: ->
     super


fix(specs): Indentation issue causing bad code

--- src/flux/tasks/syncback-draft.coffee
+++ src/flux/tasks/syncback-draft.coffee
@@ -24,15 +24,16 @@
   shouldWaitForTask: (other) ->
     other instanceof SyncbackDraftTask and other.draftLocalId is @draftLocalId and other.creationDate < @creationDate

- performLocal: ->
-  # SyncbackDraftTask does not do anything locally. You should persist your changes
-  # to the local database directly or using a DraftStoreProxy, and then queue a
-  # SyncbackDraftTask to send those changes to the server.
-  if not @draftLocalId?
-    errMsg = "Attempt to call FileUploadTask.performLocal without @draftLocalId"
-    Promise.reject(new Error(errMsg))
-  else
-    Promise.resolve()
+  performLocal: ->
+    # SyncbackDraftTask does not do anything locally. You should persist your changes
+    # to the local database directly or using a DraftStoreProxy, and then queue a
+    # SyncbackDraftTask to send those changes to the server.
+    console.log('in performLocal')
+    if not @draftLocalId?
+      errMsg = "Attempt to call FileUploadTask.performLocal without @draftLocalId"
+      Promise.reject(new Error(errMsg))
+    else
+      Promise.resolve()

   performRemote: ->
     new Promise (resolve, reject) =>


Kick from interface.

Kick from interface.

--- src/frontend/modules/userList.coffee
+++ src/frontend/modules/userList.coffee
@@ -66,7 +66,7 @@
         columns  = parseInt (nbUsers / inOneCol + 0.5)
         @jqContainer.css 'width', columns * 118

-    muteStream  : (event) =>
+    muteStream   : (event) =>
         button = $ event.target
         mainLi = button.parents 'li.thumbnail-wrapper'
         video = (mainLi.find 'video')[0] # get the video tag for the li.
@@ -78,19 +78,30 @@
             @users[video.getAttribute 'rel']['volume'] = !@users[video.getAttribute 'rel']['volume']
             video.volume = @users[video.getAttribute 'rel']['volume']

+    kickUser     : (event) =>
+        mainLi = ($ event.target).parents 'li.thumbnail-wrapper'
+        uid = (mainLi.attr 'id').slice '6' # Skip the `video_`
+        msg =
+          type   : 'cmd.kick'
+          to     : uid
+          params :
+            message : ""
+        @emitter.trigger 'message.sendToOneId', msg
+
     addInterface : (jqLi, login) =>
         intrfc = ($ "

#{login}

mute

-
kick

+
kick

promote

#{login}

"
         ).appendTo jqLi
         (jqLi.find '.muteBtn').click @muteStream
+        (jqLi.find '.kickBtn').click @kickUser

     # Update the user list window.
     display         : () =>


configure: fix new context args

configure: fix new context args

--- lib/commands/configure.coffee
+++ lib/commands/configure.coffee
@@ -54,7 +54,7 @@
           for host in params.hosts
             throw Error "Host #{host} not found" unless host in Object.keys config.servers
         for fqdn, server of config.servers
-          ctx = contexts[fqdn] = context contexts, (merge {}, config, server)
+          ctx = contexts[fqdn] = context contexts, params, (merge {}, config, server)
           ctx.params = params
           ctx.config.runinfo = {}
           ctx.config.runinfo.date = now


zSort

zSort

--- src/engine.coffee
+++ src/engine.coffee
@@ -9,6 +9,7 @@
     includedModules: []
     paused: false
     showFPS: false
+    zSort: false

   ###*
   The Engine controls the game world and manages game state. Once you
@@ -134,7 +135,13 @@

         self.trigger "preDraw", canvas

-        I.objects.invoke("draw", canvas)
+        if I.zSort
+          drawObjects = I.objects.copy().sort (a, b) ->
+            a.I.zIndex - b.I.zIndex
+        else
+          drawObjects = I.objects
+
+        drawObjects.invoke("draw", canvas)

       self.trigger "draw", canvas


corrected counter values calculation

corrected counter values calculation

--- app/src/utils/converters.coffee
+++ app/src/utils/converters.coffee
@@ -38,7 +38,7 @@
     currency ?= ledger.preferences.instance.getCurrency()
     currencies = ledger.tasks.TickerTask.instance.getCache()
     # satoshiValueCurrency is the amount in Satoshi for 1 in the given currency
-    satoshiValueCurrency = findRate(ledger.config.network.tickerKey.to, currency) * Math.pow(10, 8)
+    satoshiValueCurrency = findRate(ledger.config.network.tickerKey.to, currency) * Math.pow(10, ledger.preferences.defaults.Display.units.bitcoin.unit)
     satoshiValue = satoshiValueCurrency * currencyValue
     Math.round(satoshiValue)

@@ -56,7 +56,7 @@

     # currencyValueBTC is the amount in the given currency for 1 BTC
     currencyValueBTC = findRate(ledger.config.network.tickerKey.from, currency)
-    val = currencyValueBTC * Math.pow(10, -8)
+    val = currencyValueBTC * Math.pow(10, -ledger.preferences.defaults.Display.units.bitcoin.unit)
     currencyValueSatoshi = val * satoshiValue
     ledger.i18n.formatNumber(parseFloat(currencyValueSatoshi.toFixed(2)))

@@ -74,7 +74,7 @@
     if rate > 0
       # currencyValueBTC is the amount in the given currency for 1 BTC
       currencyValueBTC = rate
-      val = currencyValueBTC * Math.pow(10, -8)
+      val = currencyValueBTC * Math.pow(10, -ledger.preferences.defaults.Display.units.bitcoin.unit)
       currencyValueSatoshi = val * satoshiValue
       res = parseFloat(currencyValueSatoshi.toFixed(2))
     else


Fixed hotkeys

Fixed hotkeys

--- def/fr/menu_win32.cson
+++ def/fr/menu_win32.cson
@@ -3,7 +3,7 @@
     value: "&Fichier"
     submenu:
       "New &Window":
-        value: "Nouvelle fenêtre (&W)"
+        value: "Nouvelle &fenêtre"
       "&New File":
         value: "&Nouveau fichier"
       "&Open File…":
@@ -13,14 +13,14 @@
       "Add Project Folder…":
         value: "Ajouter un dossier au projet..."
       "Reopen Project":
-        value: "Ouvrir un projet récent"
+        value: "Rouvrir un projet"
         submenu:
           "Clear Project History":
             value: "Effacer l'historique du projet"
       "Reopen Last &Item":
-        value: "Rouvr&ir le dernier élément"
+        value: "Rouvrir le &dernier élément"
       "Se&ttings":
-        value: "Préférences... (&T)"
+        value: "&Préférences..."
       "Config…":
         value: "Paramètres..."
       "Init Script…":
@@ -32,19 +32,19 @@
       "Stylesheet…":
         value: "Feuille de style..."
       "&Save":
-        value: "Enregi&strer"
+        value: "&Enregistrer"
       "Save &As…":
-        value: "Enregistrer sous... (&A)"
+        value: "Enregistrer &sous..."
       "Save A&ll":
-        value: "Enregistrer tout (&L)"
+        value: "Enre&gistrer tout"
       "&Close Tab":
-        value: "Fermer l'onglet (&C)"
+        value: "Fer&mer l'onglet"
       "Close &Pane":
-        value: "Fermer le &panneau"
+        value: "Fermer le p&anneau"
       "Clos&e Window":
-        value: "F&ermer la fenêtre"
+        value: "Fermer la fenêt&re"
       "E&xit":
-        value: "Quitter (&X)"
+        value: "&Quitter"
       "Close All Tabs":
         value: "Fermer tous les onglets"
   "&Edit":
@@ -53,73 +53,73 @@
       "&Undo":
         value: "Ann&uler"
       "&Redo":
-        value: "&Refaire"
+        value: "Re&faire"
       "Cu&t":
-        value: "Couper (&T)"
+        value: "Cou&per"
       "&Copy":
         value: "&Copier"
       "Copy Pat&h":
         value: "Copier le c&hemin"
       "&Paste":
-        value: "Coller (&P)"
+        value: "C&oller"
       "Select &All":
-        value: "Sélectionner tout (&A)"
+        value: "&Sélectionner tout"
       "&Toggle Comments":
-        value: "Commen&ter/Décommenter"
+        value: "Commenter/&Décommenter"
       Lines:
         value: "Lignes"
         submenu:
           "&Indent":
             value: "&Indenter"
           "&Outdent":
-            value: "Désindenter (&O)"
+            value: "&Désindenter"
           "&Auto Indent":
-            value: "Indentation &automatique"
+            value: "Indentation automati&que"
           "Move Line &Up":
-            value: "Remonter la ligne (&U)"
+            value: "&Remonter la ligne"
           "Move Line &Down":
-            value: "&Descendre la ligne"
+            value: "Des&cendre la ligne"
           "Du&plicate Lines":
-            value: "Du&pliquer les lignes"
+            value: "Dupliquer les li&gnes"
           "D&elete Line":
-            value: "Supprimer la lign&e"
+            value: "&Supprimer la ligne"
           "&Join Lines":
-            value: "Fusionner les lignes (&J)"
+            value: "&Fusionner les lignes"
       Columns:
         value: "Colonnes"
         submenu:
           "Move Selection &Left":
-            value: "Dép&lacer la sélection à gauche"
+            value: "Déplacer la sélection à &gauche"
           "Move Selection &Right":
-            value: "Déplacer la sélection à d&roite"
+            value: "Déplacer la sélection à &droite"
       Text:
         value: "Texte"
         submenu:
           "&Upper Case":
-            value: "Mettre en maj&uscule"
+            value: "Mettre en m&ajuscule"
           "&Lower Case":
-            value: "Mettre en minuscu&le"
+            value: "Mettre en m&inuscule"
           "Delete to End of &Word":
-            value: "Retirer la fin du mot (&W)"
+            value: "Retirer la fin du &mot"
           "Delete to Previous Word Boundary":
             value: "Retirer le début du mot"
           "Delete to Next Word Boundary":
             value: "Supprimer jusqu'au prochain mot"
           "&Delete Line":
-            value: "Supprimer la ligne (&D)"
+            value: "&Supprimer la ligne"
           "&Transpose":
-            value: "In&tervertir les caractères"
+            value: "Intervertir les &caractères"
       Folding:
         value: "Pliage"
         submenu:
           "&Fold":
-            value: "Plier (&F)"
+            value: "&Plier"
           "&Unfold":
-            value: "Déplier (&U)"
+            value: "&Déplier"
           "Unfold &All":
-            value: "Déplier tout (&A)"
+            value: "Déplier t&out"
           "Fol&d All":
-            value: "Plier tout (&D)"
+            value: "Plier to&ut"
           "Fold Level 1":
             value: "Plier au niveau 1"
           "Fold Level 2":
@@ -158,10 +158,10 @@
       "Select Grammar":
         value: "Choisir le langage"
   "&View":
-    value: "Affichage (&V)"
+    value: "&Affichage"
     submenu:
       "Toggle &Full Screen":
-        value: "Activer/Désactiver le mode plein écran (&F)"
+        value: "Activer/Désactiver le mode &plein écran"
       "Toggle Menu Bar":
         value: "Activer/Désactiver la barre de menu"
       Panes:
@@ -197,19 +197,19 @@
           "&Reload Window":
             value: "&Recharger la fenêtre"
           "Run Package &Specs":
-            value: "Lancer le&s tests unitaires du package"
+            value: "Lancer les tests &unitaires du package"
           "Run &Benchmarks":
-            value: "Lancer les tests de performance (&B)"
+            value: "Lancer les tests de &performance"
           "Toggle Developer &Tools":
-            value: "Afficher/Masquer les ou&tils de développement"
+            value: "Afficher/Masquer les &outils de développement"
       "&Increase Font Size":
-        value: "Augmenter la ta&ille de la police"
+        value: "&Augmenter la taille de la police"
       "&Decrease Font Size":
         value: "&Diminuer la taille de la police"
       "Re&set Font Size":
-        value: "Réinitiali&ser la taille de la police"
+        value: "&Réinitialiser la taille de la police"
       "Toggle Soft &Wrap":
-        value: "Activer/Désactiver le retour à la ligne souple (&W)"
+        value: "Activer/Désactiver le retour à la li&gne souple"
       "Toggle Command Palette":
         value: "Afficher/Masquer la liste des commandes"
       "Toggle Tree View":
@@ -218,35 +218,35 @@
     value: "&Sélection"
     submenu:
       "Add Selection &Above":
-        value: "Étendre la sélection &au-dessus"
+        value: "Étendre la sélection au-dess&us"
       "Add Selection &Below":
-        value: "Étendre la sélection en dessous (&B)"
+        value: "Étendre la sélection en dess&ous"
       "S&plit into Lines":
         value: "Sé&parer en lignes"
       "Single Selection":
         value: "Sélection unique"
       "Select to &Top":
-        value: "É&tendre la sélection au début"
+        value: "Étendre la sélection au &début"
       "Select to Botto&m":
-        value: "Étendre la sélection à la fin (&M)"
+        value: "Étendre la sélection à la &fin"
       "Select &Line":
-        value: "Sélectionner toute la &ligne"
+        value: "Sélectionner toute la li&gne"
       "Select &Word":
-        value: "Sélectionner le mot (&W)"
+        value: "Sélectionner le &mot"
       "Select to Beginning of W&ord":
-        value: "Étendre la sélection au début du m&ot"
+        value: "Étendre la sélection au dé&but du mot"
       "Select to Beginning of L&ine":
-        value: "Étendre la sélection au début de la l&igne"
+        value: "Étendre la sélection au début de la lig&ne"
       "Select to First &Character of Line":
         value: "Étendre la sélection au premier &caractère de la ligne"
       "Select to End of Wor&d":
-        value: "Étendre la sélection à la fin &du mot"
+        value: "Étendre la sélection à la fin du mo&t"
       "Select to End of Lin&e":
         value: "Étendre la sélection à la fin de la lign&e"
       "Select Inside Brackets":
         value: "Sélectionner l'intérieur des parenthèses"
   "F&ind":
-    value: "Chercher (&I)"
+    value: "&Recherche"
     submenu:
       "Find in Buffer":
         value: "Chercher dans le fichier courant"
@@ -283,12 +283,12 @@
   "&Packages":
     value: "&Packages"
   "&Help":
-    value: "Aide (&H)"
+    value: "Ai&de"
     submenu:
       "View &Terms of Use":
-        value: "Conditions d'u&tilisation"
+        value: "&Conditions d'utilisation"
       "View &License":
-        value: "Voir la &licence"
+        value: "&Voir la licence"
       "Check For Update":
         value: "Vérifier les mises à jour"
       "&Documentation":


fix upadte of profiles

fix upadte of profiles

--- app/views/profile/update.coffee
+++ app/views/profile/update.coffee
@@ -15,7 +15,10 @@
 $('#passphrase-error-primary-' + '<%= c %>')
   .append('<%= t('errors.profile.passphrase') %>')
 $('#course-card-' + '<%= c %>').addClass('border-danger')
+$('#collapse-course-<%= c %>').collapse('show')
 <% end %>
+$('#course-card-' + '<%= @errors[:primary_pass].first %>').closest('.programCollapse')
+  .collapse('show')
 <% end %>
 <% if @errors[:secondary_pass].present? %>
 <% @errors[:secondary_pass].each do |l| %>
@@ -24,6 +27,11 @@
   .append('<%= t('errors.profile.passphrase') %>')
 $('#course-card-' + '<%= Lecture.find_by_id(l).course.id %>')
   .addClass('border-danger')
+$('#collapse-course-<%= Lecture.find_by_id(l).course.id %>').collapse('show')
+<% end %>
+<% unless @errors[:primary_pass].present? %>
+$('#course-card-' + '<%= Lecture.find_by_id(@errors[:secondary_pass].first).course.id %>').closest('.programCollapse')
+  .collapse('show')
 <% end %>
 <% end %>
 <% if @errors[:courses].present? %>


follow docs

follow docs

--- src/follow.coffee
+++ src/follow.coffee
@@ -1,7 +1,7 @@
 ###*
 The Follow module provides a simple method to set an object's
 velocity so that it will approach another object. This method
-relies on the objects ha
+relies on the objects having

 player = GameObject


reschedule a save on slow connection to prevent conflict in flow editing

--- static/coffee/flows/services.coffee
+++ static/coffee/flows/services.coffee
@@ -388,7 +388,12 @@

       # schedule the save for a bit later in case more dirty events come in quick succession
       if $rootScope.saving
-        $timeout.cancel($rootScope.saving)
+        cancelled = $timeout.cancel($rootScope.saving)
+        if not cancelled
+          $timeout ->
+            $rootScope.dirty = true
+          , quietPeriod
+          return

       $rootScope.saving = $timeout ->


Update gitlab.coffee

Update gitlab.coffee

--- src/gitlab.coffee
+++ src/gitlab.coffee
@@ -135,7 +135,7 @@
             when "merge_request"
               unless hook.object_attributes.action == "update"
                 if showMergeDesc == "1"
-                  text = "Merge Request #{bold(hook.object_attributes.iid)}: #{hook.user.username} #{hook.object_attributes.action}ed  #{hook.object_attributes.title} (#{hook.object_attributes.state}) between #{bold(hook.object_attributes.source_branch)} and #{bold(hook.object_attributes.target_branch)} at #{bold(hook.object_attributes.url)}\n"
+                  text = "Merge Request #{bold(hook.object_attributes.iid)}: #{hook.user.username} #{hook.object_attributes.action}ed  #{hook.object_attributes.title} between #{bold(hook.object_attributes.source_branch)} and #{bold(hook.object_attributes.target_branch)} at #{bold(hook.object_attributes.url)}\n"
                   splitted = hook.object_attributes.description.split  "\r\n"
                   for i in [0...splitted.length]
                     splitted[i] = "> " + splitted[i]


Groups: temp fix for hiding hidden groups on clientside

--- client/landing/app/Applications/Groups.kdapplication/Views/GroupsListItemView.coffee
+++ client/landing/app/Applications/Groups.kdapplication/Views/GroupsListItemView.coffee
@@ -6,7 +6,10 @@
     super options,data

     group = @getData()
-    {title, slug, body} = group
+    {title, slug, body, visibility} = group
+
+    # temp fix
+    @hide()  if visibility is 'hidden'

     slugLink = if slug is KD.defaultSlug then '/' else "/#{slug}"


Handle request cascades

Handle request cascades

--- src/Carrot.coffee
+++ src/Carrot.coffee
@@ -170,7 +170,12 @@
     @ajaxPost("#{@scheme}://parsnip.gocarrot.com/notification_click", {user_id: @udid, platform_id: notifId})

   reportFeedClick: (postId, callback) ->
-    @ajaxPost("#{@scheme}://posts.gocarrot.com/#{postId}/clicks", {clicking_user_id: @udid, sig: "s"}, callback)
+    @ajaxPost("#{@scheme}://posts.gocarrot.com/#{postId}/clicks", {clicking_user_id: @udid, sig: "s"},
+      (response) =>
+        if response.cascade && response.cascade.method == "sendRequest"
+          sendRequest(response.cascade.arguments.request_id, response.cascade.arguments.opts)
+        callback(response) if callback
+    )

   # Available opts: object_type, object_id, object_properties, filters, suggestions, exclude_ids, max_recipients, data
   sendRequest: (requestId, opts, callback, postMethod) ->
@@ -202,7 +207,12 @@
       )

   acceptRequest: (requestId, callback) ->
-    @ajaxPost("#{@scheme}://posts.gocarrot.com/requests/#{postId}/clicks", {clicking_user_id: @udid, sig: "s"}, callback)
+    @ajaxPost("#{@scheme}://posts.gocarrot.com/requests/#{postId}/clicks", {clicking_user_id: @udid, sig: "s"},
+      (response) =>
+        if response.cascade && response.cascade.method == "sendRequest"
+          sendRequest(response.cascade.arguments.request_id, response.cascade.arguments.opts)
+        callback(response) if callback
+    )

   getTweet: (actionId, objectInstanceId, actionProperties, objectProperties, callback) ->
     actionProperties = if typeof actionProperties is "string" then actionProperties else JSON.stringify(actionProperties || {})


support factory-objects/arrays as exports and fix variable name

--- src/hinoki.coffee
+++ src/hinoki.coffee
@@ -428,14 +428,14 @@
         if extension is '.coffee'
           require('coffee-script/register')

-        extension = require(filepath)
-
-        Object.keys(extension).map (key) ->
-          unless 'function' is typeof extension[key]
-            throw new Error('export is not a function: ' + key + ' in :' + filepath)
+        exports = require(filepath)
+
+        Object.keys(exports).map (key) ->
+          unless hinoki.isFactory exports[key]
+            throw new Error('export is not a factory: ' + key + ' in :' + filepath)
           if object[key]?
             throw new Error('duplicate export: ' + key + ' in: ' + filepath + '. first was in: ' + object[key].__file)
-          object[key] = extension[key]
+          object[key] = exports[key]
           # add filename as metadata
           object[key].__file = filepath


Build a list of all raw metas encountered during preload, including exports

--- lib/loader.coffee
+++ lib/loader.coffee
@@ -10,6 +10,7 @@
 moduleSignature= /\.(js|coffee|json)$/
 skipThisFileSignature= /^\.|^_default\.meta\.(js|coffee|json)$/
 stripMetaExtension= /(.*)(?:\.meta\.(js|coffee|json))$/
+stripDotMeta= /(.*?)(?:_default)?(?:\.meta)$/
 moduleExtensions= ['.js','.coffee','.json']

@@ -58,8 +59,11 @@
     return c
   descend(name)

+rawmetas= {}
 load= (name,superMeta)->
-  extend(superMeta, require(name), name)
+  raw= require(name)
+  rawmetas[name.replace(stripDotMeta,'$1')]= raw
+  extend(superMeta, raw, name)

 loadTree= (rootdir,superMeta,supersites) ->
   modules= []
@@ -101,6 +105,7 @@
   for modname in modules
     m= require(modname)
     if m?.meta
+      rawmetas[modname]= m.meta
       itsMeta= meta_lookup(modname)
       metacache[modname]= extend(itsMeta,m.meta,modname)
     if sitesModuleSignature.test(modname)


(#216) Add missing `error` entry type to debug log

--- lib/logger.coffee
+++ lib/logger.coffee
@@ -133,5 +133,8 @@
     command: (msg) ->
       @write("[#{new Date().toLocaleTimeString('en-US', {hour12: false})}| Command] #{msg}")

+    error: (msg) ->
+      @write("[#{new Date().toLocaleTimeString('en-US', {hour12: false})}| Error] #{msg}")
+
     warn: (msg) ->
       @write("[#{new Date().toLocaleTimeString('en-US', {hour12: false})}| Warn] #{msg}")


Fixed: The second parameter of system.publish should be array.

--- src/routes/friendship.coffee
+++ src/routes/friendship.coffee
@@ -44,7 +44,7 @@
       sourceUserNickname: nickname
       version: timestamp

-  rongCloud.message.system.publish encodedUserId, encodedFriendId, 'RC:ContactNtf', contactNotificationMessage,
+  rongCloud.message.system.publish encodedUserId, [encodedFriendId], 'RC:ContactNtf', contactNotificationMessage,
     (err, resultText) ->
       # 暂不考虑回调的结果是否成功，后续可以考虑记录到系统错误日志中
       if err


util.log -> console.log

util.log -> console.log

--- src/monad.coffee
+++ src/monad.coffee
@@ -19,7 +19,7 @@
       value
   inspect : () -> util.inspect value                  # Inspectable!
   log : () ->                                         # Loggable!
-    util.log this
+    console.log this
     this

 # Just a simple value monad.
@@ -110,7 +110,7 @@

   # Normal iteration
   for item in (List 5, 6)
-    util.log item
+    console.log item

   # Some list operations
   (reverse (append (List 5, 6), (List 7, 8))).log()
@@ -119,14 +119,14 @@

   # Simple state computations
   countdown = get.bind (i) ->
-    util.log i
+    console.log i
     (put i-1).bind ->
       @unit i

   state = 10
   while state > 0
     state = execState countdown, state
-  util.log "Blast off!"
+  console.log "Blast off!"
 exports.test = demoTest

 exports.TMonad = TMonad


Correctly create local scopes for workers.

--- src/nodes.coffee
+++ src/nodes.coffee
@@ -1998,13 +1998,13 @@
       @name = o.root.assignModuleName()

     # create a new scope (hence overwriting the present, inherited scope)
-    o.scope = new Scope null, this, null
+    o.scope = new Scope null, @code, null
     o.level = LEVEL_TOP
     o.indent = ''
     # o.bare = yes

     # o.indent  += TAB
-    actualCode = @code.compile o
+    actualCode = @code.compileWithDeclarations o

     nulllog "using HTML5 worker" if o.worker
     nulllog "using node.js process" if o.nodejsprocess


updated async wrapper function

updated async wrapper function

--- src/nodes.coffee
+++ src/nodes.coffee
@@ -2289,6 +2289,7 @@

 UTILITIES =

+  # for async functions
   async: -> "
     (function(){
       var async = function(generator) {
@@ -2312,11 +2313,13 @@
           self.tick();
         };

-        this.failHandle = function(value) {
-          self.fail(value);
+        this.failHandle = function(err) {
+          self.result = err;
+          self.throw = true;
+          self.tick();
         };

-        this.send     = false;
+        this.throw    = false;
         this.result   = undefined;

         this.iterator = undefined;
@@ -2327,24 +2330,24 @@
       Tracker.prototype = {
         tick: function() {
           var next;
-          if (this.send) {
+          if (this.throw) {
+            next = this.iterator.throw(this.result);
+            this.throw = false;
+          } else {
             next = this.iterator.next(this.result);
-          } else {
-            next = this.iterator.next();
-            this.send = true;
           }

           if (next.done) {
             this.win(next.value);
           } else {
-            next.value.promise.then(this.thenHandle, this.failHandle);
+            next.value.then(this.thenHandle, this.failHandle);
           }
         }
       };

       return async;
     }())
-  "
+  "

   stream: -> "
     (function(){


Revert "deep datasource access ref."

Revert "deep datasource access ref."

This reverts commit 064bcdc6d1bb8d76b35511ba8ec4f583128f8940.

--- src/scripts/ui-scroll.coffee
+++ src/scripts/ui-scroll.coffee
@@ -49,7 +49,7 @@
 						getValueChain = (targetScope, target) ->
 							chain = target.match(/^([\w]+)\.(.+)$/)
 							if not chain or chain.length isnt 3
-								return targetScope[target]
+								return if not targetScope.hasOwnProperty(target) then null else targetScope[target]
 							return null if not targetScope.hasOwnProperty(chain[1])
 							getValueChain(targetScope[chain[1]], chain[2])


Remove non-standard doc comments

Remove non-standard doc comments

--- src/scripts/wikipedia.coffee
+++ src/scripts/wikipedia.coffee
@@ -89,28 +89,3 @@

 strCapitalize = (str) ->
   return str.charAt(0).toUpperCase() + str.substring(1);
-
-# Original Author: Brad Fults (h3h.net) - 2011-11-09
-#
-# Copyright (c) 2011 Gowalla Incorporated
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.


followup related to autosave and readonly

--- src/smc-webapp/editor.coffee
+++ src/smc-webapp/editor.coffee
@@ -1006,6 +1006,7 @@

     # add something visual to the UI to suggest that the file is read only
     set_readonly_ui: (readonly=true) =>
+        @opts.read_only = readonly
         if readonly
             @element.find(".salvus-editor-write-only").hide()
             @element.find(".salvus-editor-read-only").show()
@@ -3042,7 +3043,6 @@
     constructor: (@project_id, @filename, @content, opts) ->
         @element = $(".smc-jupyter-templates .smc-jupyter-nbviewer").clone()
         @init_buttons()
-        #window.w = @

     init_buttons: () =>
         # code duplication from editor_jupyter/JupyterNBViewer


fix for fix for issue 735

fix for fix for issue 735

--- src/smc-webapp/sagews.coffee
+++ src/smc-webapp/sagews.coffee
@@ -622,7 +622,7 @@
         else
             toplineno = cib.start + 1
         # added topline for jupyter decorator autocompletion
-        topline = cm.getLine(toplineno + 1)
+        topline = cm.getLine(toplineno)
         line = cm.getLine(pos.line).slice(0, pos.ch)
         if pos.ch == 0 or line[pos.ch-1] in ")]}'\"\t "
             if @editor.opts.spaces_instead_of_tabs


change drag-n-drop image width

change drag-n-drop image width

--- src/smc-webapp/smc_chat.cjsx
+++ src/smc-webapp/smc_chat.cjsx
@@ -687,7 +687,7 @@

     append_file: (file) ->
         if file.type.indexOf("image") isnt -1
-            final_insertion_text = ""
+            final_insertion_text = ""
         else
             final_insertion_text = "[#{file.name}](#{file.name})"


Doc text-utils.coffee

Doc text-utils.coffee

--- src/stdlib/text-utils.coffee
+++ src/stdlib/text-utils.coffee
@@ -1,18 +1,41 @@
+### Internal ###
+
 isHighSurrogate = (string, index) ->
   0xD800 <= string.charCodeAt(index) <= 0xDBFF

 isLowSurrogate = (string, index) ->
   0xDC00 <= string.charCodeAt(index) <= 0xDFFF

+### Public ###
+
+# Is the character at the given index the start of a high/low
+# surrogate pair?
+#
+# string - The {String} to check for a surrogate pair.
+# index - The {Number} index to look for a surrogate pair at.
+#
+# Return a {Boolean}.
 isSurrogatePair = (string, index) ->
   isHighSurrogate(string, index) and isLowSurrogate(string, index + 1)

+# Get the number of characters in the string accounting for surrogate pairs.
+#
+# This will always returns a value less than or equal to `string.length`.
+#
+# string - The {String} to count the number of full characters in.
+#
+# Returns a {Number}.
 getCharacterCount = (string) ->
   count = string.length
   for index in [0...string.length] when isSurrogatePair(string, index)
     count--
   count

+# Does the given string contain at least one surrogate pair?
+#
+# string - The {String} to check for the presence of surrogate pairs.
+#
+# Returns a {Boolean}.
 hasSurrogatePairs = (string) ->
   string.length isnt getCharacterCount(string)


Simplify condition.

Simplify condition.

--- blocks/password/script.coffee
+++ blocks/password/script.coffee
@@ -20,7 +20,7 @@
 		@on('mousedown', 'toggle', @toggle)

 	isSupported: ->
-		return supported  if supported isnt undefined
+		return supported  unless supported is undefined

 		# IE8+
 		supported = $('<!--[if lte IE 8]><i></i><![endif]-->').find('i').length isnt 1


vm.snapshot() returns the ref of the new snapshot.

--- src/api/vm.coffee
+++ src/api/vm.coffee
@@ -608,11 +608,9 @@
   catch
     @throw 'NO_SUCH_OBJECT'

-  xapi = @getXAPI VM
-
-  $wait xapi.call 'VM.snapshot', VM.ref, name
-
-  return true
+  ref = $wait (@getXAPI VM).call 'VM.snapshot', VM.ref, name
+
+  return ref
 exports.snapshot.permission = 'admin'
 exports.snapshot.params = {
   id: { type: 'string' }


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/string_extensions.coffee
+++ src/string_extensions.coffee
@@ -57,8 +57,7 @@
 String::capitalize = ->
   this.charAt(0).toUpperCase() + this.substring(1).toLowerCase()

-( ->
-root = exports ? this
+
 ###*
 Return the class or constant named in this string.

@@ -79,7 +78,7 @@
     that
   else
     throw "String#constantize: '#{this}' is not a valid constant name."
-)()
+
 ###*
 Returns a new string that is a more human readable version.


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/string_extensions.coffee
+++ src/string_extensions.coffee
@@ -75,6 +75,8 @@
   target = exports ? window

   target = target[item] for item in this.split '.'
+
+  return targe

 ###*
 Returns a new string that is a more human readable version.


conf can and will be null in serve. FES-10

--- lib/router.coffee
+++ lib/router.coffee
@@ -28,7 +28,7 @@
 the404 = fs.readFileSync(the404Path)

 serve = (req, res, proxy, conf)->
-  console.log new Date, req.headers.host, req.url, "=>", conf.target?.protocol || 404
+  console.log new Date, req.headers.host, req.url, "=>", conf?.target?.protocol || 404

   res.setHeader 'Server', serverAgent


testCase tearDown runned before the error handler

--- lib/runner.coffee
+++ lib/runner.coffee
@@ -33,8 +33,6 @@
     do @_addCustomAction

   _addCustomAction: ->
-    @_wd.addPromiseChainMethod 'runNextTest', @runNextTest
-
     for action in (require 'glob').sync(__dirname+'/action/*')
       new (require action) @_wd, @_browser, @_config, @errorHandler

@@ -47,12 +45,12 @@
     console.log 'Started: ' + testFile.replace @_config.root, ''

     @testCase = new (require testFile) @_wd, @_browser, @_config, @errorHandler
-    @_context = do @testCase
+    @_context = @testCase
       .setContext @_context
       .runTest()
+      .then => do @testCase.tearDown
       .fail @errorHandler
-      .then => do @testCase.tearDown
-      .runNextTest
+      .then => do @runNextTest

     @_fileIndex++


ensure that logger is a string

ensure that logger is a string

--- lib/sentry.coffee
+++ lib/sentry.coffee
@@ -10,7 +10,7 @@
   constructor: (settings) ->
     # first check if sentry dsn is set as environment variable
     @_parseDSN(process.env.SENTRY_DSN or "")
-
+
     # credentials are updated if explicitly passed in
     if settings?
       if _(settings).isString()
@@ -25,12 +25,12 @@
       else
         @enabled = false
         @disable_message = "Sentry client expected String or Object as argument. You passed: #{settings}."
-
+
     _(@).defaults
       hostname: os.hostname()
       enable_env: ['production']
     return
-
+
   error: (err, message, logger, extra) =>
     unless err instanceof Error
       console.error 'error must be an instance of Error', err
@@ -55,7 +55,7 @@
       extra: extra if extra?

     @_send data
-
+
   _parseDSN: (dsn) =>
     if dsn
       parsed = nodeurl.parse(dsn)
@@ -73,9 +73,16 @@
   _send: (data) =>
     unless @enabled
       return console.log @disable_message
-
+
     unless process.env.NODE_ENV in @enable_env
       return console.log "If #{process.env.NODE_ENV} was enabled, would have sent to Sentry:", data
+
+    # If you send data.logger and it's not a string, Sentry tells you that it succeeded and sends
+    # you an event ID, Sentry doesn't actually do anything and the event ID that they give you
+    # is nonexistant. #dealwithit
+    if data.logger?
+      unless _(data.logger).isString()
+        return console.log "Logger just be a string, was #{JSON.stringify data.logger}"

     options =
       uri: "https://app.getsentry.com/api/#{@project_id}/store/"


We can use mapSync as we don't need anything asynchronous, also we can return nothing as we're done with the stream data at that point.

--- src/supervisor-update.coffee
+++ src/supervisor-update.coffee
@@ -48,12 +48,12 @@
 				es.pipeline(
 					stream
 					es.split()
-					es.map (line, callback) ->
+					es.mapSync (line) ->
 						# ignore first 8 characters of every line that are a header sent by docker attach
 						data = line.substr(8)
 						if data is config.successMessage
 							resolve(container)
-						callback(null, data)
+						return
 				)
 				stream.on 'end', ->
 					reject(new Error('New supervisor stopped before success message'))


Bug caused by email

Bug caused by email

--- both/config/accounts.coffee
+++ both/config/accounts.coffee
@@ -1,5 +1,5 @@
 Accounts.config
-	sendVerificationEmail : true
+	sendVerificationEmail : false

 if Meteor.isClient
 	Meteor.startup ->


somehow manged to commit a dodgy char

somehow manged to commit a dodgy char

--- lib/assets/javascripts/appitude.js.coffee
+++ lib/assets/javascripts/appitude.js.coffee
@@ -16,7 +16,7 @@
   viewObjects = {}
   loadViews()

-loadViews = ()->§
+loadViews = ()->
   loadView.apply(this, view) for view in views

 loadView = (view, name)->


Setup and teardown sinon stubs in qunit test

--- test/javascripts/controllers/base_paper_controller_test.js.coffee
+++ test/javascripts/controllers/base_paper_controller_test.js.coffee
@@ -1,3 +1,4 @@
+# TODO use server.respondWith
 moduleFor 'controller:basePaper', 'BasePaperController',
   needs: ['controller:application']
   setup: ->
@@ -10,9 +11,12 @@
       title: 'test paper'
       phases: [ ]

+    sinon.stub(jQuery, "ajax")
+
+  teardown: ->
+    jQuery.ajax.restore()
+
 test '#export: calls the export url in Tahi', ->
-  sinon.stub(jQuery, "ajax")
-
   basePaperController = @subject()
   basePaperController.set('model', @paper)
   downloadType =


Array lib fix

Array lib fix

--- libs/array.coffee
+++ libs/array.coffee
@@ -1,5 +1,5 @@
 Array::remove = (value) ->
-  if typeof(value) === "string"
+  if typeof(value) == "string"
     value = [value]

   if value instanceof Array


fixes

fixes

--- src/popup.coffee
+++ src/popup.coffee
@@ -28,23 +28,23 @@
         return console.error MESSAGES.invalidParams if not yearNum or not monthNum
         yearNum = +yearNum
         monthNum = +monthNum
-
+        #TODO (S.Panfilov) check after add "+"
         scope.data.viewedDate =
           year:
-            first: Object.keys(bDataFactory.data.years)[0]
-            last: Object.keys(bDataFactory.data.years)[Object.keys(bDataFactory.data.years).length - 1]
-            number: yearNum
-            count: Object.keys(bDataFactory.data.years).length
+            first: +Object.keys(bDataFactory.data.years)[0]
+            last: +Object.keys(bDataFactory.data.years)[Object.keys(bDataFactory.data.years).length - 1]
+            number: +yearNum
+            count: +Object.keys(bDataFactory.data.years).length
           month:
-            first: Object.keys(bDataFactory.data.years[yearNum])[0]
-            last: Object.keys(bDataFactory.data.years[yearNum])[Object.keys(bDataFactory.data.years[yearNum]).length - 1]
-            daysTotal: bDataFactory.data.years[yearNum][monthNum].days_total
-            startDay: bDataFactory.data.years[yearNum][monthNum].start_day
-            number: monthNum
+            first: +Object.keys(bDataFactory.data.years[yearNum])[0]
+            last: +Object.keys(bDataFactory.data.years[yearNum])[Object.keys(bDataFactory.data.years[yearNum]).length - 1]
+            daysTotal: +bDataFactory.data.years[yearNum][monthNum].days_total
+            startDay: +bDataFactory.data.years[yearNum][monthNum].start_day
+            number: +monthNum
             name: bDateUtils.getMonthName monthNum
-            count: Object.keys(bDataFactory.data.years[yearNum]).length
+            count: +Object.keys(bDataFactory.data.years[yearNum]).length
           day:
-            number: dayNum
+            number: +dayNum

         scope.data.viewedDate.days = scope.data.getDaysArr scope.data.viewedDate.year, scope.data.viewedDate.month
       daysOfWeek:


Add i18n calls to Annotator code

Add i18n calls to Annotator code

--- src/range.coffee
+++ src/range.coffee
@@ -20,7 +20,7 @@
   else if r.start and typeof r.start is "object"
     new Range.NormalizedRange(r)
   else
-    console.error("Couldn't not sniff range type")
+    console.error(_t("Couldn't not sniff range type"))
     false

 # Public: Creates a wrapper around a range object obtained from a DOMSelection.
@@ -52,7 +52,7 @@
   # Returns an instance of Range.NormalizedRange
   normalize: (root) ->
     if @tainted
-      console.error("You may only call normalize() once on a BrowserRange!")
+      console.error(_t("You may only call normalize() once on a BrowserRange!"))
       return false
     else
       @tainted = true
@@ -284,7 +284,7 @@
         ).join('/')

         # Find the default document namespace.
-        namespace = document.lookupNamespaceURI null
+        namespace = document.lookupNamespaceURI null

         # Try and resolve the namespace, first seeing if it is an xhtml node
         # otherwise check the head attributes.
@@ -292,7 +292,7 @@
           if ns == 'xhtml' then namespace
           else document.documentElement.getAttribute('xmlns:' + ns)

-        node = evaluateXPath xpath, customResolver
+        node = evaluateXPath xpath, customResolver
       node

   # Public: Creates a NormalizedRange.
@@ -319,7 +319,7 @@
     range.commonAncestorContainer = this._nodeFromXPath(cacXPath)

     if not range.commonAncestorContainer
-      console.error("Error deserializing range: can't find XPath '" + cacXPath + "'. Is this the right document?")
+      console.error(_t("Error deserializing range: can't find XPath '") + cacXPath + _t("'. Is this the right document?"))
       return null

     # Unfortunately, we *can't* guarantee only one textNode per


Also emit the @data

Also emit the @data

--- src/robot.coffee
+++ src/robot.coffee
@@ -214,7 +214,7 @@
     for k of (data or { })
       @data[k] = data[k]

-    @emit 'loaded'
+    @emit 'loaded', @data

 class Robot.Message
   # Represents an incoming message from the chat.


mac: Search PATH for command.

mac: Search PATH for command.

--- src/runas.coffee
+++ src/runas.coffee
@@ -1,7 +1,24 @@
 runas = require('bindings')('runas.node')
+
+searchCommand = (command) ->
+  return command if command[0] is '/'
+
+  fs = require('fs')
+  path = require('path')
+  paths = process.env.PATH.split(path.delimiter)
+  for p in paths
+    try
+      filename = path.join(p, command)
+      return filename if fs.statSync(filename).isFile()
+    catch e
+  ''

 module.exports = (command, args=[], options={}) ->
   options.hide ?= true
   options.admin ?= false

+  # Convert command to its full path when using authorization service
+  if process.platform is 'darwin' and options.admin is true
+    command = searchCommand(command)
+
   runas.runas(command, args, options)


dead code

dead code

--- src/skuld.coffee
+++ src/skuld.coffee
@@ -92,7 +92,6 @@
   Trait.create {
     unit : (norns) -> Consensus norns
     add : (norn) ->
-      console.log "Adding #{norn} to #{@norns}"
       @norns.bind (old) ->
         Consensus old.concat (createNorn norn)
     prepare : (skuld) -> throw "NI"


Improved instance `trigger()` method comments

--- src/spine.coffee
+++ src/spine.coffee
@@ -488,9 +488,11 @@
     Events.unbind.apply record, arguments

   trigger: ->
-    Events.trigger.apply this, arguments # fire off the instance event
-    return true if arguments[0] is 'refresh' # Don't trigger refresh events, because ... ?
-    @constructor.trigger arguments... # fire off the class event
+    Events.trigger.apply this, arguments # Trigger the instance event.
+    # Don't trigger 'refresh' multiple times on the class - the class method
+    # will trigger it once for the whole refresh operation.
+    return true if arguments[0] is 'refresh'
+    @constructor.trigger arguments... # Trigger the class event.

 Model::on  = Model::bind
 Model::off = Model::unbind


Added rudimentary tweening, wut!

Added rudimentary tweening, wut!

--- src/tween.coffee
+++ src/tween.coffee
@@ -37,7 +37,7 @@
   @name tween
   @methodOf Tween#
   @param {Number} duration How long (in frames) until the object's properties reach their final values.
-  @param {Object}
+  @param {Object} properties
   ###
   tween: (duration, properties) ->
     properties = Object.extend({}, properties) # Make a local copy


Re-order functions.

Re-order functions.

--- src/types.coffee
+++ src/types.coffee
@@ -1,20 +1,23 @@
 'use strict'

-verifyUnemptyString = (arg, msg) ->
-  if isUnemptyString(arg) is false
-    throw new Error msg || 'Invalid string'
+quacksLike = (arg, duck) ->
+  verifyObject arg
+  verifyObject duck
+  for own property of duck
+    if arg.hasOwnProperty(property) isnt true
+      return false
+    if typeof arg[property] isnt typeof duck[property]
+      return false
+  true

-isUnemptyString = (arg) ->
-  if isString(arg) and arg isnt ''
-    return true
-  false
+verifyInstance = (arg, prototype, msg) ->
+  if isInstance(arg, prototype) is false
+    throw new Error msg || 'Invalid type'

-verifyString = (arg, msg) ->
-  if isString(arg) is false
-    throw new Error msg || 'Invalid string'
-
-isString = (arg) ->
-  if typeof arg is 'string'
+isInstance = (arg, prototype) ->
+  if typeof arg is 'undefined' or arg is null
+    return false
+  if isFunction(prototype) and arg instanceof prototype
     return true
   false

@@ -45,40 +48,37 @@
     return true
   false

-verifyInstance = (arg, prototype, msg) ->
-  if isInstance(arg, prototype) is false
-    throw new Error msg || 'Invalid type'
+verifyUnemptyString = (arg, msg) ->
+  if isUnemptyString(arg) is false
+    throw new Error msg || 'Invalid string'

-isInstance = (arg, prototype) ->
-  if typeof arg is 'undefined' or arg is null
-    return false
-  if isFunction(prototype) and arg instanceof prototype
+isUnemptyString = (arg) ->
+  if isString(arg) and arg isnt ''
     return true
   false

-quacksLike = (arg, duck) ->
-  verifyObject arg
-  verifyObject duck
-  for own property of duck
-    if arg.hasOwnProperty(property) isnt true
-      return false
-    if typeof arg[property] isnt typeof duck[property]
-      return false
-  true
+verifyString = (arg, msg) ->
+  if isString(arg) is false
+    throw new Error msg || 'Invalid string'
+
+isString = (arg) ->
+  if typeof arg is 'string'
+    return true
+  false

 module.exports = {
-  verifyUnemptyString
-  isUnemptyString
-  verifyString
-  isString
+  quacksLike
+  verifyInstance
+  isInstance
   verifyObject
   isObject
   verifyArray
   isArray
   verifyFunction
   isFunction
-  verifyInstance
-  isInstance
-  quacksLike
+  verifyUnemptyString
+  isUnemptyString
+  verifyString
+  isString
 }


Cleanup + add missing error handler

Cleanup + add missing error handler

--- src/bundle.coffee
+++ src/bundle.coffee
@@ -16,10 +16,13 @@
   createBundle: (dir, callback) ->

     console.log chalk.yellow('Creating bundle.tar.gz')
+
     bundleFilesInFolder dir, (err, bundlePath) ->
       if err then return callback err

       getBundleSize bundlePath, (err, bundleSize) ->
+        if err then return callback err
+
         console.log chalk.grey "bundle path: #{bundlePath}"
         console.log chalk.grey "bundle size: #{bundleSize}KB"

@@ -29,6 +32,7 @@
 getBundleSize = (bundlePath, callback) ->
   fs.stat bundlePath, (err, stats) ->
     if err then return callback err
+
     size = parseInt(stats.size / 1024, 10)
     callback null, size


Fix broken test

Fix broken test

--- lib/errors/errors.spec.coffee
+++ lib/errors/errors.spec.coffee
@@ -85,4 +85,4 @@
 			error.code = 'EACCES'
 			checkProcessExitOption error, false, (processExitStub, logErrorStub) ->
 				expect(logErrorStub).to.have.been.calledOnce
-				expect(logErrorStub).to.have.been.calledWith('You don\'t have enough privileges to run this operation.')
+				expect(logErrorStub.getCall(0).args[0]).to.match(/^You don\'t have enough privileges to run this operation./)


minor doc changes

minor doc changes

--- src/Option.coffee
+++ src/Option.coffee
@@ -102,7 +102,15 @@

 Some.prototype = new Option()
 Some.prototype.constructor = Some
+
+###*
+  See documentation in {@link Option}
+###
 Some.prototype.isEmpty = () -> false
+
+###*
+  See documentation in {@link Option}
+###
 Some.prototype.get = () -> this.__value

 ###*
@@ -117,7 +125,15 @@

 None.prototype = new Option()
 None.prototype.constructor = None
+
+###*
+  See documentation in {@link Option}
+###
 None.prototype.isEmpty = () -> true
+
+###*
+  See documentation in {@link Option}
+###
 None.prototype.get = () -> throw new Error("Get get a value in an instance of None")

 if exports?


overviewboxTop padding

overviewboxTop padding

Former-commit-id: 9dfd5c7ba5f45a4ccb2d4a70d053a4223ad65c05 [formerly c173bc7176f4a1dd572d61c9638a3755b5c83c47]
Former-commit-id: 411b0d1c801d6876d3ce433a885894280533c298

--- src/views/OverviewBox.coffee
+++ src/views/OverviewBox.coffee
@@ -11,7 +11,8 @@

   initialize: (data) ->
     @g = data.g
-    @listenTo @g.zoomer,"change:boxRectWidth change:boxRectHeight", @render
+    @listenTo @g.zoomer,"change:boxRectWidth change:boxRectHeight
+    change:overviewboxPaddingTop", @render
     @listenTo @g.selcol, "add reset change", @render
     @listenTo @g.columns, "change:hidden", @render
     @listenTo @g.colorscheme, "change:showLowerCase", @render
@@ -31,6 +32,7 @@
   render: ->
     @_createCanvas()
     @el.textContent = "overview"
+    @el.style.marginTop = @g.zoomer.get "overviewboxPaddingTop"

     # background bg for non-drawed area
     @ctx.fillStyle = "#999999"


fixes

fixes

--- lib/browser-plus-view.coffee
+++ lib/browser-plus-view.coffee
@@ -493,13 +493,13 @@
     fs.readFileSync "#{@model.browserPlus.resources}/jquery.hotkeys.min.js",'utf-8'

   @loadCSS: (filename,fullpath)->
-    filename = "file:///C:/Users/Administrator/.atom/packages/browser-plus/resources/#{filename}" unless fullpath
+    filename = "#{@model.browserPlus.resources}/#{filename}" unless fullpath
     """
     jQuery('head').append(jQuery('<link type="text/css" rel="stylesheet" href="#{filename}">'))
     """

   @loadJS: (filename,fullpath=false)->
-    filename = "file:///C:/Users/Administrator/.atom/packages/browser-plus/resources/#{filename}" unless fullpath
+    filename = "#{@model.browserPlus.resources}/#{filename}" unless fullpath
     """
     jQuery('head').append(jQuery('<script type="text/javascript" src="#{filename}">'))
     """


Filtering class on 'new' keyword and no label without new..

--- lib/php-class-provider.coffee
+++ lib/php-class-provider.coffee
@@ -26,13 +26,24 @@

   findSuggestionsForPrefix: (prefix) ->
     # Get rid of the leading "new" keyword
-    prefix = prefix.replace /^new /, ''
+    instanciation = false
+    if prefix.indexOf("new ") != -1
+      instanciation = true
+      prefix = prefix.replace /^new /, ''

     # Filter the words using fuzzaldrin
     words = fuzzaldrin.filter @classes.names, prefix

     # Builds suggestions for the words
-    suggestions = for word in words when word isnt prefix
-      params = @classes.methods[word].constructor.args.join(',')
-      new Suggestion this, word: word, prefix: prefix, label: "(#{params})"
+    suggestions = []
+    for word in words when word isnt prefix
+      # Just print classes with constructors with "new"
+      if instanciation and @classes.methods[word].constructor.has
+        params = @classes.methods[word].constructor.args.join(',')
+        suggestions.push new Suggestion this, word: word, prefix: prefix, label: "(#{params})"
+
+      # Not instanciation => not printing constructor params
+      else if not instanciation
+        suggestions.push new Suggestion this, word: word, prefix: prefix
+
     return suggestions


Remove debug log in modelchoicefield angularjs code.

--- django_cradmin/static/django_cradmin/src/lib/forms/modelchoicefield.coffee
+++ django_cradmin/static/django_cradmin/src/lib/forms/modelchoicefield.coffee
@@ -199,7 +199,6 @@

         resizeIfScrollHeightChanges = ->
           newScrollHeight = getIframeScrollHeight()
-          console.log 'newScrollHeight tick', newScrollHeight
           if newScrollHeight != currentScrollHeight
             currentScrollHeight = newScrollHeight
             $scope.setIframeSize()


Serialise POSTing of checkitems

Serialise POSTing of checkitems

Trello currently has a race condition where simultaneous creation of checkitems in the same checklist can result in some checkitems not being created properly. Until they fix it we force them to be created one at a time.


checkers

checkers

--- src/checkers.iced
+++ src/checkers.iced
@@ -113,6 +113,22 @@

 ##-----------------------------------------------------------------------

+checkers.check_array = check_array = (x, min = null, max = null) ->
+  if typeof(x) isnt 'object' or not Array.isArray(x) then E("expected an array")
+  else if min? and x.length < min then E("Array must have > #{min} elements")
+  else if max? and x.length > max then E("Array must have < #{max} elements")
+  else null
+
+##-----------------------------------------------------------------------
+
+checkers.check_buffer = check_buffer = (x, min = null, max = null) ->
+  if typeof(x) isnt 'object' or not Buffer.isBuffer(x) then E("expected a buffer")
+  else if min? and x.length < min then E("Buffer must have > #{min} bytes")
+  else if max? and x.length > max then E("Buffer must have < #{max} bytes")
+  else null
+
+##-----------------------------------------------------------------------
+
 exports.raw = checkers
 exports.curried = curried = {}


Add LinkView.search(itemPath).

Add LinkView.search(itemPath).

--- src/linkview/linkview.coffee
+++ src/linkview/linkview.coffee
@@ -110,8 +110,23 @@
         ul = document.createElement('ul')

         items = []
-        item = taskPaperOutline.root
-        while (item = item.nextItem)
+
+        itemPath = @itemPath or '*'
+        results = taskPaperOutline.evaluateItemPath(itemPath)
+
+        if itemPath isnt '*'
+            itemLI = document.createElement('li')
+            itemLI.innerHTML = "ItemPath: #{itemPath} (#{results.length} results)

"
+            items.push(itemLI.outerHTML)
+
+        knownParents =
+            'Birch': true
+
+        addItem = (item) =>
+            knownParents[item.id] = true
+            if item.parent and not knownParents[item.parent.id]
+                addItem(item.parent)
+
             itemLI = document.createElement('li')
             for attribute in item.attributeNames
                 itemLI.setAttribute attribute, item.getAttribute(attribute)
@@ -121,6 +136,8 @@

             items.push(linkifyHtml itemLI.outerHTML, @linkifyOptions)

+        for item in results
+            addItem(item)

         @$node.empty()
         @$node.append(htmlFragment)
@@ -130,3 +147,7 @@
             scrollElem: $('.clusterize-scroll', @node)[0]
             contentElem: $('.clusterize-content', @node)[0]

+    search: (itemPath) =>
+        @itemPath = itemPath
+        @render()
+


Fix create direct channel to support 4.0 api

--- src/client.coffee
+++ src/client.coffee
@@ -324,12 +324,11 @@
               return @customMessage(postData, channelID)
             return true

-    createDirectChannel: (userID) ->
-        postData =
-            user_id: userID
-        @_apiCall 'POST', @channelRoute('create_direct'), postData, (data, headers) =>
-            @logger.debug 'Created Direct Channel.'
-            return data
+    createDirectChannel: (userID, callback) ->
+        postData = [userID, @self.id]
+        @_apiCall 'POST', '/channels/direct', postData, (data, headers) =>
+            @logger.info 'Created Direct Channel.'
+            if callback? then callback(data)

     findChannelByName: (name) ->
         for c of @channels
@@ -406,7 +405,8 @@
                 if callback? then callback({'id': null, 'error': error.errno}, {}, callback_params)
             else
                 if callback?
-                    if res.statusCode is 200
+                    # some create method return 201 when successful, such as create channel
+                    if res.statusCode is 200 or res.statusCode is 201
                         if typeof value == 'string'
                             value = JSON.parse(value)
                         callback(value, res.headers, callback_params)


DEV-318 removed log

DEV-318 removed log

--- src/client.coffee
+++ src/client.coffee
@@ -38,7 +38,7 @@

       body = null

-      console.log "WE ARE HERE #{bodyBeforeJson}"
+      #console.log "WE ARE HERE #{bodyBeforeJson}"
       if bodyBeforeJson and bodyBeforeJson.length > 0
         try
           body = JSON.parse(bodyBeforeJson)


Fix reconnecting logic

Fix reconnecting logic

--- src/client.coffee
+++ src/client.coffee
@@ -180,6 +180,7 @@
         @ws = new WebSocket @socketUrl, options

         @ws.on 'error', (error) =>
+            @_connecting = false
             @emit 'error', error

         @ws.on 'open', =>
@@ -218,6 +219,7 @@

         @ws.on 'close', (code, message) =>
             @emit 'close', code, message
+            @_connecting = false
             @connected = false
             @socketUrl = null
             if @autoReconnect
@@ -226,8 +228,8 @@

     reconnect: ->
         if @_reconnecting
-            @logger.info 'Already reconnecting, skipping call.'
-            return
+            @logger.info 'WARNING: Already reconnecting.'
+        @_connecting = false
         @_reconnecting = true
         if @_pongTimeout
             clearInterval @_pongTimeout


Tweak comments

Tweak comments

--- lib/simple-flake8-view.coffee
+++ lib/simple-flake8-view.coffee
@@ -78,7 +78,6 @@
   initialize: ->
     super
     @addClass('simple-flake8')
-    # @addClass('simple-flake8 overlay from-top')

   getFilterKey: ->
     'message'
@@ -92,7 +91,6 @@
       @show()

   show: ->
-    console.log('hi');
     # Get out of here unless this is a python file
     editor = atom.workspace.getActiveEditor()
     return unless editor?
@@ -102,7 +100,6 @@
     @panel.show()

     @storeFocusedElement()
-
     @setLoading('Running Flake8 Linter...')

     if @previouslyFocusedElement[0] and @previouslyFocusedElement[0] isnt document.body
@@ -111,7 +108,6 @@
       @eventElement = atom.views.getView(atom.workspace)

     filePath = editor.getPath()
-
     flake filePath, (errors) =>
       error_list = []
       if errors.length == 0


Add way to access globals

Add way to access globals

--- src/aether.coffee
+++ src/aether.coffee
@@ -29,6 +29,9 @@

   # Current call depth
   depth: 0
+
+  getAddedGlobals: () ->
+    protectBuiltins.addedGlobals

   constructor: (options) ->
     options ?= {}


Fix color of existence operator

Fix color of existence operator

--- src/coffee.coffee
+++ src/coffee.coffee
@@ -171,7 +171,7 @@
         # basically like any other operator;
         # it has highest precedence.
         when 'Existence'
-          addBlock node, 7, colors.CONTROL, wrappingParen
+          addBlock node, 7, colors.VALUE, wrappingParen
           mark node.expression, 7

         # ### Value ####


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/color2.coffee
+++ src/color2.coffee
@@ -140,11 +140,16 @@
       other.a == @a

     grayscale: ->
+      @copy().grayscale()
+
+    grayscale$: ->
       hsl = @toHsl()

       g = (hsl[2] * 255).round()

-      return Color2(g, g, g)
+      @r = @g = @b = g
+
+      return this

     hue: (degrees) ->
       @copy().hue$(degrees)


dont crash when the skip is set too high

--- src/commit.coffee
+++ src/commit.coffee
@@ -63,6 +63,7 @@
     lines   = text.split "\n"
     while lines.length
       id   = _.last lines.shift().split(" ")
+      break if !id
       tree = _.last lines.shift().split(" ")

       parents = []


zuvor.run runs ids without order

zuvor.run runs ids without order

--- src/zuvor.coffee
+++ src/zuvor.coffee
@@ -374,6 +374,21 @@

     results = {}

+    # immediately run those that have no order
+
+    orderless = new Set(options.ids).delete(options.graph.keys()).keys()
+
+    options.pending.add orderless
+
+    orderlessPromise = Promise.all orderless.map (id) ->
+      promise = Promise.resolve options.callback id
+      promise.then (value) ->
+        options.pending.delete id
+        options.done.add id
+        results[id] = value
+
+    # run those with order in order
+
     start = (names) ->
       valid = new Set(names).delete(options.pending).delete(options.done)
       options.pending.add valid
@@ -397,11 +412,12 @@
             .keys()
           start next

-    # TODO we can start all those that are not in the graph
-    #
-    # if not strict ignore those in the graph that are not in ids
-
-    start if options.reversed
+    orderedPromise = start if options.reversed
       options.graph.childless()
     else
       options.graph.parentless()
+
+    # wait for everything to finish and return results
+
+    Promise.all([orderlessPromise, orderedPromise]).then ->
+      results


Now Operator Pending show on status-bar

Now Operator Pending show on status-bar

--- lib/status-bar-manager.coffee
+++ lib/status-bar-manager.coffee
@@ -1,6 +1,6 @@
 {ElementBuilder} = require './utils'

-modeToContent =
+modeStringToContent =
   "normal": "Normal"
   'insert': "Insert"
   'insert.replace': "Replace"
@@ -8,6 +8,7 @@
   "visual.characterwise": "Visual Char"
   "visual.linewise": "Visual Line"
   "visual.blockwise": "Visual Block"
+  "operator-pending": "Operator Pending"

 module.exports =
 class StatusBarManager
@@ -24,7 +25,7 @@
     modeString = mode
     modeString += "." + submode if submode?
     @element.className = "#{@prefix}-#{mode}"
-    @element.textContent = modeToContent[modeString]
+    @element.textContent = modeStringToContent[modeString]

   attach: ->
     @tile = @statusBar.addRightTile(item: @container, priority: 20)


tweak: using `.` for separator (thanks @maxbrunsfeld)

--- lib/status-bar-manager.coffee
+++ lib/status-bar-manager.coffee
@@ -1,14 +1,14 @@
 {Disposable, CompositeDisposable} = require 'event-kit'

-# mode names can be combined with submode names with the `$` character
+# mode names can be combined with submode names with the `.` character
 # the order matters - the last matching entry wins
 ContentsByMode =
-  insert:           ["status-bar-vim-mode-insert", "Insert"]
-  insert$replace:   ["status-bar-vim-mode-insert", "Replace"]
-  command:          ["status-bar-vim-mode-command", "Command"]
-  visual:           ["status-bar-vim-mode-visual", "Visual"]
-  visual$linewise:  ["status-bar-vim-mode-visual", "Visual Line"]
-  visual$blockwise: ["status-bar-vim-mode-visual", "Visual Block"]
+  'insert':           ["status-bar-vim-mode-insert",  "Insert"]
+  'insert.replace':   ["status-bar-vim-mode-insert",  "Replace"]
+  'command':          ["status-bar-vim-mode-command", "Command"]
+  'visual':           ["status-bar-vim-mode-visual",  "Visual"]
+  'visual.linewise':  ["status-bar-vim-mode-visual",  "Visual Line"]
+  'visual.blockwise': ["status-bar-vim-mode-visual",  "Visual Block"]

 module.exports =
 class StatusBarManager
@@ -20,7 +20,7 @@
   initialize: (@statusBar) ->

   update: (currentMode, currentSubmode) ->
-    currentFullMode = currentMode + "$" + currentSubmode if currentSubmode?
+    currentFullMode = currentMode + "." + currentSubmode if currentSubmode?
     for mode, [klass, html] of ContentsByMode
       if mode is currentMode or mode is currentFullMode
         @element.classList.add(klass)


Remove themes paths from config

Remove themes paths from config

Themes are now co-located with packages

--- src/config.coffee
+++ src/config.coffee
@@ -9,9 +9,7 @@

 configDirPath = fsUtils.absolute("~/.atom")
 nodeModulesDirPath = path.join(resourcePath, "node_modules")
-bundledThemesDirPath = path.join(resourcePath, "themes")
 bundledKeymapsDirPath = path.join(resourcePath, "keymaps")
-userThemesDirPath = path.join(configDirPath, "themes")
 userPackagesDirPath = path.join(configDirPath, "packages")
 userPackageDirPaths = [userPackagesDirPath]
 userPackageDirPaths.unshift(path.join(configDirPath, "dev", "packages")) if atom.getLoadSettings().devMode
@@ -39,7 +37,6 @@
   _.extend @prototype, EventEmitter

   configDirPath: configDirPath
-  themeDirPaths: [userThemesDirPath, bundledThemesDirPath]
   bundledPackageDirPaths: [nodeModulesDirPath]
   bundledKeymapsDirPath: bundledKeymapsDirPath
   nodeModulesDirPath: nodeModulesDirPath


The method is requestSave()

The method is requestSave()

--- src/config.coffee
+++ src/config.coffee
@@ -951,7 +951,7 @@
       @set(key, value, save: false) for key, value of newSettings
       if @pendingOperations.length
         op() for op in @pendingOperations
-        @debouncedSave()
+        @requestSave()
         @pendingOperations = []
       return


Update language specific constants

Update language specific constants

--- atom/atom.symlink/config.cson
+++ atom/atom.symlink/config.cson
@@ -31,3 +31,41 @@
     'command': 'bundle exec rspec'
   'cucumber-runner':
     'command': 'bundle exec cucumber'
+  'rails-rspec': {}
+'.js.rails.source source.jquery.js':
+  'editor': {}
+'.rails.rjs.ruby.source':
+  'editor': {}
+'.rails.ruby.source':
+  'editor': {}
+'.html.ruby.text':
+  'editor': {}
+'.erb.html.text':
+  'editor':
+    'tabLength': 2
+'.ruby.source.sql':
+  'editor': {}
+'.rspec.ruby.source':
+  'editor': {}
+'.objc.source ++ *':
+  'editor': {}
+'.source.swift':
+  'editor': {}
+'.gfm.source':
+  'editor': {}
+'.litcoffee.source':
+  'editor':
+    'tabLength': 2
+'.ruby.source':
+  'editor':
+    'tabLength': 2
+'.shell.source':
+  'editor':
+    'tabLength': 2
+'.objc.source':
+  'editor': {}
+'.source.strings':
+  'editor': {}
+'.coffee.source':
+  'editor':
+    'tabLength': 2


Simple number check for `isNumber`

Simple number check for `isNumber`

--- src/config.coffee
+++ src/config.coffee
@@ -29,18 +29,18 @@
       throw new Error "#{option} must be a non-empty string"

   isNumber: (option, value, lower, upper=null) ->
-    if _.any (fn value for fn in [_.isNull, _.isNaN, _.isUndefined])
+    if _.isNaN(value) or not _.isNumber value
       throw new Error "#{option}(#{value}) is not a number"

     if upper
       unless lower <= value <= upper
         throw new Error "#{lower} <= #{option}(#{value}) <= #{upper}"
     else
-      unless not _.isNumber(value) or lower <= value
+      unless lower <= value
         throw new Error "#{lower} <= #{option}(#{value})"

   isNumberExclusive: (option, value, lower, upper=null) ->
-    if _.any (fn value for fn in [_.isNull, _.isNaN, _.isUndefined])
+    if _.isNaN(value) or not _.isNumber value
       throw new Error "#{option}(#{value}) is not a number"

     if upper


use relative path to exec setup

use relative path to exec setup


Prevent erros in RoomManager if room no found

--- client/lib/RoomManager.coffee
+++ client/lib/RoomManager.coffee
@@ -88,20 +88,21 @@

 					room = ChatRoom.findOne query, { reactive: false }

-					openedRooms[typeName].rid = room._id
+					if room?
+						openedRooms[typeName].rid = room._id

-					msgStream.on openedRooms[typeName].rid, (msg) ->
-						ChatMessage.upsert { _id: msg._id }, msg
-						# If room was renamed then close current room and send user to the new one
-						Tracker.nonreactive ->
-							if msg.t is 'r'
-								if Session.get('openedRoom') is msg.rid
-									type = if FlowRouter.current().route.name is 'channel' then 'c' else 'p'
-									RoomManager.close type + FlowRouter.getParam('name')
-									FlowRouter.go FlowRouter.current().route.name, name: msg.msg
+						msgStream.on openedRooms[typeName].rid, (msg) ->
+							ChatMessage.upsert { _id: msg._id }, msg
+							# If room was renamed then close current room and send user to the new one
+							Tracker.nonreactive ->
+								if msg.t is 'r'
+									if Session.get('openedRoom') is msg.rid
+										type = if FlowRouter.current().route.name is 'channel' then 'c' else 'p'
+										RoomManager.close type + FlowRouter.getParam('name')
+										FlowRouter.go FlowRouter.current().route.name, name: msg.msg

-					deleteMsgStream.on openedRooms[typeName].rid, (msg) ->
-						ChatMessage.remove _id: msg._id
+						deleteMsgStream.on openedRooms[typeName].rid, (msg) ->
+							ChatMessage.remove _id: msg._id

 				Dep.changed()


Just use $scope.showGlobal

Just use $scope.showGlobal

--- web/volume/spreadsheet.coffee
+++ web/volume/spreadsheet.coffee
@@ -13,8 +13,7 @@

         Editing = $scope.editing = $attrs.edit != undefined
         ID = $scope.id = $attrs.id ? 'ss'
-        ShowGlobal = false
-        $scope.showGlobal = ShowGlobal
+        $scope.showGlobal = false
         Limit = $attrs.limit || Infinity
         Key = undefined

@@ -331,7 +330,7 @@
           all = Object.keys(volume.metrics).sort(byNumber).map((i) -> constants.category[i])
           if slot
             slot = undefined
-            cats = all.filter((c) -> ShowGlobal || (Cats[c.id] ? Editing))
+            cats = all.filter((c) -> $scope.showGlobal || (Cats[c.id] ? Editing))
             cats.push(pseudoCategory.asset)
             cats.unshift(pseudoCategory.slot)
             $scope.anyGlobal = all.some((c) -> Cats[c.id] == false)
@@ -1253,8 +1252,7 @@
           return

         $scope.showHideGlobal = ->
-          ShowGlobal = !ShowGlobal
-          $scope.showGlobal = ShowGlobal
+          $scope.showGlobal = !$scope.showGlobal
           $scope.setKey(Key.id)
           return


Update gruntfile

Update gruntfile

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -7,7 +7,7 @@

   grunt.registerTask 'default', ['clean', '6to5:dist', 'amd_tamer', 'uglify']

-  grunt.registerTask 'test', ['jshint', '6to5:test']
+  grunt.registerTask 'test', ['jshint', 'consolidate', '6to5:test', 'amd_tamer:test']

   grunt.registerTask 'doc', ['groc']


:boar: Update gruntfile

:boar: Update gruntfile

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -5,7 +5,7 @@
   require('load-grunt-config') grunt,
     jitGrunt: true

-  grunt.registerTask 'default', ['clean', 'bowercopy', 'amd_tamer', 'test', 'uglify']
+  grunt.registerTask 'default', ['clean', 'bowercopy', 'babel', 'amd_tamer', 'test', 'uglify']

   grunt.registerTask 'test', ['jshint']


minor change

minor change

--- library/membrane/bower.coffee
+++ library/membrane/bower.coffee
@@ -184,6 +184,6 @@
         sorter = (v, k) -> _.findIndex bowerings, match(k)
         finder = (v, k) -> _.find bowerings, match(k)
         list(paths: yes, options).on "end", (paths) =>
-            scope = [sorter, finder, paths]
+            assert scope = [sorter, finder, paths]
             bowerings.cached = @cachier scope...
             bowerings.cached context; next()


Add docs to the setup sockets method

Add docs to the setup sockets method

--- library/nucleus/kernel.coffee
+++ library/nucleus/kernel.coffee
@@ -206,6 +206,10 @@
         @server = http.createServer @connect
         @server?.listen server.port, hostname

+    # Setup and attach Socket.IO handlers to each of the servers.
+    # That is HTTP and HTTPS servers that are running and listening
+    # for new connections. The kernel itself does not use the sockets
+    # it just sets it up. Please refer to the Socket.IO docs for info.
     setupSocketServers: ->
         assert _.isObject(sconfig = nconf.get "socket")
         logger.info "Attaching Socket.IO to HTTPS server"


Minor reordering

Minor reordering

--- library/nucleus/kernel.coffee
+++ library/nucleus/kernel.coffee
@@ -219,9 +219,9 @@
         rserver = "Running HTTP server at %s:%s".magenta
         logger.info rserver, hostname, server.port
         @server = http.createServer @connect
+        @server?.listen server.port, hostname
         @server.on "connection", (socket) ->
             socket.setNoDelay yes
-        @server?.listen server.port, hostname

     # Setup and attach Socket.IO handlers to each of the servers.
     # That is HTTP and HTTPS servers that are running and listening


fallback to scaled instead of generic

fallback to scaled instead of generic

--- library/nucleus/loader.coffee
+++ library/nucleus/loader.coffee
@@ -76,7 +76,7 @@
 # most derived from the original one. If no such kernel can be found
 # then revert to returning the original kernel embedded in framework.
 module.exports.cachedKernel = (limits) ->
-    origin = require("./kernel").Generic
+    origin = require("./scaled").Scaled
     assert _.isString limits, "no limits"
     limits = paths.resolve limits.toString()
     assert _.isObject(origin), "no kernel origin"


Fix stupid mistake in the params plumbing

--- library/nucleus/plumbs.coffee
+++ library/nucleus/plumbs.coffee
@@ -43,7 +43,7 @@
         body = request.body or {}
         query = request.query or {}
         params = _.extend query, body
-        response.params = params
+        request.params = params
         next() unless request.headersSent

 # A middleware that adds a `redirect` method to the response object.


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/camera.coffee
+++ src/camera.coffee
@@ -35,10 +35,6 @@
       width: 2 * deadzone.x
       height: 2 * deadzone.y

-    if objectCenter.x > centerRect.right
-
-    else if objectCenter.x < centerRect.left
-

     I.scroll = Point(
       I.scroll.x.clamp(centerRect.left, centerRect.right)


添加没有框架的情况…

添加没有框架的情况…

--- lib/module/create-module-type-view.coffee
+++ lib/module/create-module-type-view.coffee
@@ -55,7 +55,10 @@
         if @frameworks.length > 1
           @parentView.setNextBtn()
         else
-          el.dataset.src = @frameworks[0].folderName
+          if @frameworks.length is 0
+            el.dataset.src = desc.defaultModule
+          else
+            el.dataset.src = @frameworks[0].folderName
           @parentView.setNextBtn 'finish'
     @parentView.enableNext()


Add minimum response length for random responses

--- src/markov.coffee
+++ src/markov.coffee
@@ -96,7 +96,9 @@
       randword = Math.floor(Math.random() * words.length)
       seed = words[randword]
       model.generate seed or '', max, (text) =>
-        msg.send text
+        res = text.match /\w+/g
+        if res.length > 2
+          msg.send text

   # Generate markov chains on demand, optionally seeded by some initial state.
   robot.respond /markov(\s+(.+))?$/i, (msg) ->


Added ability to query states

Added ability to query states

--- scripts/awesome.team.coffee
+++ scripts/awesome.team.coffee
@@ -94,3 +94,12 @@
       msg.reply "I don't know!!!"
     else
       msg.reply "Your board name is '" + robot.brain.board.name + "'"
+
+  robot.hear /what(’|'| i)s (our|my) (.*) state/i, (msg) ->
+    if robot.brain.board is undefined
+      msg.reply "I don't know!!! (you haven't set the board yet)"
+      exit
+    msg.http($baseurl+"/teams/"+robot.brain.team._id+"/boards/"+robot.brain.board._id+"/"+msg.match[3].toLowerCase()+"State")
+    .get() (err, res, body) ->
+      state = JSON.parse body
+      msg.send state.description


Fixing Mood Poll

Fixing Mood Poll

--- scripts/awesome.team.coffee
+++ scripts/awesome.team.coffee
@@ -28,13 +28,13 @@
     "http://i.imgur.com/aimsF.jpg"
   ]

-  achievementReminder = new CronJob '00 18 20 * * 5', ->
+  achievementReminder = new CronJob '00 00 16 * * 5', ->
     for room, board of robot.brain.data._private.board
       robot.messageRoom room, "Hello " + robot.brain.data._private.team[room].name + "!"
       robot.messageRoom room, "Are there any achievements from the week that someone @here needs to add to your board '" + board.name + "'?"
   , null, true, 'America/New_York'

-  moodPoll = new CronJob '00 37 20 * * 1-5', ->
+  moodPoll = new CronJob '00 40 20 * * 1-5', ->
     for room, board of robot.brain.data._private.board
       buttonName = "mood_" + robot.brain.data._private.team[room]._id
       robot.emit 'slack.attachment',


update

update

--- scripts/deepthoughts.coffee
+++ scripts/deepthoughts.coffee
@@ -1,5 +1,4 @@
 module.exports = (robot) ->
-	robot.respond /deep/i, (msg) ->
-		msg.http('http://andymatthews.net/code/deepthoughts/get.cfm')
-			.get()(error, response, body) ->
-				msg.send "Doesn't work"
+	robot.respond /deep/i, (res) ->
+		res.send "Thanks for ping"
+


Update chosen.coffee

Update chosen.coffee

--- src/chosen.coffee
+++ src/chosen.coffee
@@ -49,7 +49,8 @@
         # Update the value in options. Set the default texts again. Update message.
         attr.$observe key, (value) ->
           options[snakeCase(key)] = scope.$eval(value)
-          chosen.set_default_text();
+          if chosen
+            chosen.set_default_text();
           updateMessage();

         options[snakeCase(key)] = scope.$eval(value)