<commit_before>
var defaults = {
  // storage
  origins: {},
  header: false,
  // static
  protocols: ['https', 'http', '*'],
  // UI
  protocol: 'https',
  origin: '',
  timeout: null,
  file: true,
  encodings: {
    'Unicode': ['UTF-8', 'UTF-16LE'],
    'Arabic': ['ISO-8859-6', 'Windows-1256'],
    'Baltic': ['ISO-8859-4', 'ISO-8859-13', 'Windows-1257'],
    'Celtic': ['ISO-8859-14'],
    'Central European': ['ISO-8859-2', 'Windows-1250'],
    'Chinese Simplified': ['GB18030', 'GBK'],
    'Chinese Traditional': ['BIG5'],
    'Cyrillic': ['ISO-8859-5', 'IBM866', 'KOI8-R', 'KOI8-U', 'Windows-1251'],
    'Greek': ['ISO-8859-7', 'Windows-1253'],
    'Hebrew': ['Windows-1255', 'ISO-8859-8', 'ISO-8859-8-I'],
    'Japanese': ['EUC-JP', 'ISO-2022-JP', 'Shift_JIS'],
    'Korean': ['EUC-KR'],
    'Nordic': ['ISO-8859-10'],
    'Romanian': ['ISO-8859-16'],
    'South European': ['ISO-8859-3'],
    'Thai': ['Windows-874'],
    'Turkish': ['Windows-1254'],
    'Vietnamese': ['Windows-1258'],
    'Western': ['ISO-8859-15', 'Windows-1252', 'Macintosh'],
  }
}
var state = Object.assign({}, defaults)

var events = {
  file: () => {
    chrome.tabs.create({url: 'chrome://extensions/?id=' + chrome.runtime.id})
  },

  header: (e) => {
    state.header = !state.header
    chrome.runtime.sendMessage({
      message: 'options.header',
      header: state.header,
    })
  },

  origin: {
    protocol: (e) => {
      state.protocol = state.protocols[e.target.selectedIndex]
    },

    name: (e) => {
      state.origin = e.target.value
    },

    add: () => {
      var domain = state.origin.replace(/.*:\/\/([^/]+).*/i, '$1')
      if (!domain) {
        return
      }
      var origin = state.protocol + '://' + domain
      chrome.permissions.request({origins: [origin + '/*']}, (granted) => {
        if (granted) {
          chrome.runtime.sendMessage({message: 'origin.add', origin}, init)
        }
      })
    },

    all: () => {
      var origin = '*://*'
      chrome.permissions.request({origins: [origin + '/*']}, (granted) => {
        if (granted) {
          chrome.runtime.sendMessage({message: 'origin.add', origin}, init)
        }
      })
    },

    remove: (origin) => () => {
      chrome.permissions.remove({origins: [origin + '/*']}, (removed) => {
        if (removed) {
          chrome.runtime.sendMessage({message: 'origin.remove', origin}, init)
        }
      })
    },

    refresh: (origin) => () => {
      chrome.permissions.request({origins: [origin + '/*']})
    },

    match: (origin) => (e) => {
      state.origins[origin].match = e.target.value
      clearTimeout(state.timeout)
      state.timeout = setTimeout(() => {
        var {match, csp, encoding} = state.origins[origin]
        chrome.runtime.sendMessage({
          message: 'origin.update',
          origin,
          options: {match, csp, encoding},
        })
      }, 750)
    },

    csp: (origin) => () => {
      state.origins[origin].csp = !state.origins[origin].csp
      var {match, csp, encoding} = state.origins[origin]
      chrome.runtime.sendMessage({
        message: 'origin.update',
        origin,
        options: {match, csp, encoding},
      })
      webRequest()
    },

    encoding: (origin) => (e) => {
      state.origins[origin].encoding = e.target.value
      var {match, csp, encoding} = state.origins[origin]
      chrome.runtime.sendMessage({
        message: 'origin.update',
        origin,
        options: {match, csp, encoding},
      })
      webRequest()
    },
  },
}

function webRequest () {
  // ff: webRequest is required permission
  if (/Firefox/.test(navigator.userAgent)) {
    return
  }

  var intercept = false
  for (var key in state.origins) {
    if (state.origins[key].csp || state.origins[key].encoding) {
      intercept = true
      break
    }
  }

  chrome.permissions[intercept ? 'request' : 'remove']({
    permissions: ['webRequest', 'webRequestBlocking']
  }, () => {
    chrome.runtime.sendMessage({
      message: 'options.intercept',
      intercept,
    })
  })
}

chrome.extension.isAllowedFileSchemeAccess((isAllowedAccess) => {
  state.file = /Firefox/.test(navigator.userAgent)
    ? true // ff: `Allow access to file URLs` option isn't available
    : isAllowedAccess
  m.redraw()
})

var init = () => {
  chrome.runtime.sendMessage({message: 'options'}, (res) => {
    state = Object.assign({}, defaults, {file: state.file}, res)
    m.redraw()
  })
}

init()

var oncreate = {
  ripple: (vnode) => {
    mdc.ripple.MDCRipple.attachTo(vnode.dom)
  },
  textfield: (vnode) => {
    mdc.textfield.MDCTextField.attachTo(vnode.dom)
  }
}

var onupdate = {
  header: (vnode) => {
    if (vnode.dom.classList.contains('is-checked') !== state.header) {
      vnode.dom.classList.toggle('is-checked')
    }
  },
  csp: (origin) => (vnode) => {
    if (vnode.dom.classList.contains('is-checked') !== state.origins[origin].csp) {
      vnode.dom.classList.toggle('is-checked')
    }
  }
}

m.mount(document.querySelector('main'), {
  view: () =>
    m('#options',

      // allowed origins
      m('.bs-callout m-origins',

        // add origin
        m('.m-add-origin',
          m('h4.mdc-typography--headline', 'Allowed Origins'),
          m('select.mdc-elevation--z2 m-select', {
            onchange: events.origin.protocol
            },
            state.protocols.map((protocol) =>
            m('option', {
              value: protocol,
              selected: protocol === state.protocol
              },
              protocol + '://'
            )
          )),
          m('.mdc-text-field m-textfield', {
            oncreate: oncreate.textfield,
            },
            m('input.mdc-text-field__input', {
              type: 'text',
              value: state.origin,
              onchange: events.origin.name,
              placeholder: 'raw.githubusercontent.com'
            }),
            m('.mdc-line-ripple')
          ),
          m('button.mdc-button mdc-button--raised m-button', {
            oncreate: oncreate.ripple,
            onclick: events.origin.add
            },
            'Add'
          ),
          m('button.mdc-button mdc-button--raised m-button', {
            oncreate: oncreate.ripple,
            onclick: events.origin.all
            },
            'Allow All'
          )
        ),

        // global options
        m('.m-global',
          // header detection - ff: disabled
          (!/Firefox/.test(navigator.userAgent) || null) &&
          m('label.mdc-switch m-switch', {
            onupdate: onupdate.header,
            title: 'Toggle header detection'
            },
            m('input.mdc-switch__native-control', {
              type: 'checkbox',
              checked: state.header,
              onchange: events.header
            }),
            m('.mdc-switch__background', m('.mdc-switch__knob')),
            m('span.mdc-switch-label',
              'Detect ',
              m('code', 'text/markdown'),
              ' and ',
              m('code', 'text/x-markdown'),
              ' content type'
            )
          ),

          // file access is disabled
          (!state.file || null) &&
          m('button.mdc-button mdc-button--raised m-button', {
            oncreate: oncreate.ripple,
            onclick: events.file
            },
            'Allow Access to file:// URLs'
          )
        ),

        // allowed origins
        m('ul.m-list',
          Object.keys(state.origins).sort().map((origin) =>
            (
              (
                state.file && origin === 'file://' &&
                // ff: access to file:// URLs is not allowed
                !/Firefox/.test(navigator.userAgent)
              )
              || origin !== 'file://' || null
            ) &&
            m('li.mdc-elevation--z2', {
              class: state.origins[origin].expanded ? 'm-expanded' : null,
              },
              m('.m-summary', {
                onclick: (e) => state.origins[origin].expanded = !state.origins[origin].expanded
                },
                m('.m-origin', origin),
                m('.m-options',
                  state.origins[origin].match !== state.match ? m('span', 'match') : null,
                  state.origins[origin].csp ? m('span', 'csp') : null,
                  state.origins[origin].encoding ? m('span', 'encoding') : null,
                ),
                m('i.material-icons', {
                  class: state.origins[origin].expanded ? 'icon-arrow-up' : 'icon-arrow-down'
                })
              ),
              m('.m-content',
                // match
                m('.m-option m-match',
                  m('.m-name', m('span', 'match')),
                  m('.m-control',
                    m('.mdc-text-field m-textfield', {
                      oncreate: oncreate.textfield
                      },
                      m('input.mdc-text-field__input', {
                        type: 'text',
                        onkeyup: events.origin.match(origin),
                        value: state.origins[origin].match,
                      }),
                      m('.mdc-line-ripple')
                    )
                  )
                ),
                // csp
                (origin !== 'file://' || null) &&
                m('.m-option m-csp',
                  m('.m-name', m('span', 'csp')),
                  m('.m-control',
                    m('label.mdc-switch m-switch', {
                      onupdate: onupdate.csp(origin),
                      },
                      m('input.mdc-switch__native-control', {
                        type: 'checkbox',
                        checked: state.origins[origin].csp,
                        onchange: events.origin.csp(origin)
                      }),
                      m('.mdc-switch__background', m('.mdc-switch__knob')),
                      m('span.mdc-switch-label',
                        'Disable ',
                        m('code', 'Content Security Policy'),
                      )
                    )
                  )
                ),
                // encoding
                (origin !== 'file://' || null) &&
                m('.m-option m-encoding',
                  m('.m-name', m('span', 'encoding')),
                  m('.m-control',
                    m('select.mdc-elevation--z2 m-select', {
                      onchange: events.origin.encoding(origin),
                      },
                      m('option', {
                        value: '',
                        selected: state.origins[origin].encoding === ''
                        },
                        'auto'
                      ),
                      Object.keys(state.encodings).map((label) =>
                        m('optgroup', {label}, state.encodings[label].map((encoding) =>
                          m('option', {
                            value: encoding,
                            selected: state.origins[origin].encoding === encoding
                            },
                            encoding
                          )
                        ))
                      )
                    )
                  )
                ),
                // refresh/remove
                (origin !== 'file://' || null) &&
                m('.m-footer',
                  m('span',
                    m('button.mdc-button mdc-button--raised m-button', {
                      oncreate: oncreate.ripple,
                      onclick: events.origin.refresh(origin)
                      },
                      'Refresh'
                    ),
                    m('button.mdc-button mdc-button--raised m-button', {
                      oncreate: oncreate.ripple,
                      onclick: events.origin.remove(origin)
                      },
                      'Remove'
                    )
                  )
                )
              )
            )
          )
        )
      ),
    )
})

// ff: set appropriate footer icon
document.querySelector(
  '.icon-' + (/Firefox/.test(navigator.userAgent) ? 'firefox' : 'chrome')
).classList.remove('icon-hidden')
<commit_msg>Minor refactoring in advanced options view<commit_after>
var defaults = {
  // storage
  origins: {},
  header: false,
  match: '',
  // UI
  scheme: 'https',
  host: '',
  timeout: null,
  file: true,
  // static
  schemes: ['https', 'http', '*'],
  encodings: {
    'Unicode': ['UTF-8', 'UTF-16LE'],
    'Arabic': ['ISO-8859-6', 'Windows-1256'],
    'Baltic': ['ISO-8859-4', 'ISO-8859-13', 'Windows-1257'],
    'Celtic': ['ISO-8859-14'],
    'Central European': ['ISO-8859-2', 'Windows-1250'],
    'Chinese Simplified': ['GB18030', 'GBK'],
    'Chinese Traditional': ['BIG5'],
    'Cyrillic': ['ISO-8859-5', 'IBM866', 'KOI8-R', 'KOI8-U', 'Windows-1251'],
    'Greek': ['ISO-8859-7', 'Windows-1253'],
    'Hebrew': ['Windows-1255', 'ISO-8859-8', 'ISO-8859-8-I'],
    'Japanese': ['EUC-JP', 'ISO-2022-JP', 'Shift_JIS'],
    'Korean': ['EUC-KR'],
    'Nordic': ['ISO-8859-10'],
    'Romanian': ['ISO-8859-16'],
    'South European': ['ISO-8859-3'],
    'Thai': ['Windows-874'],
    'Turkish': ['Windows-1254'],
    'Vietnamese': ['Windows-1258'],
    'Western': ['ISO-8859-15', 'Windows-1252', 'Macintosh'],
  }
}

var state = Object.assign({}, defaults)

chrome.extension.isAllowedFileSchemeAccess((isAllowedAccess) => {
  state.file = /Firefox/.test(navigator.userAgent)
    ? true // ff: `Allow access to file URLs` option isn't available
    : isAllowedAccess
  m.redraw()
})

chrome.runtime.sendMessage({message: 'options'}, (res) => {
  state = Object.assign({}, defaults, {file: state.file}, res)
  m.redraw()
})

var events = {
  file: () => {
    chrome.tabs.create({url: `chrome://extensions/?id=${chrome.runtime.id}`})
  },

  header: (e) => {
    state.header = !state.header
    chrome.runtime.sendMessage({
      message: 'options.header',
      header: state.header,
    })
  },

  origin: {
    scheme: (e) => {
      state.scheme = state.schemes[e.target.selectedIndex]
    },

    host: (e) => {
      state.host = e.target.value.replace(/.*:\/\/([^/]+).*/i, '$1')
    },

    add: (all) => () => {
      if (!all && !state.host) {
        return
      }
      var origin = all ? '*://*' : `${state.scheme}://${state.host}`
      chrome.permissions.request({origins: [`${origin}/*`]}, (granted) => {
        if (granted) {
          chrome.runtime.sendMessage({message: 'origin.add', origin})
          state.origins[origin] = {
            match: state.match,
            csp: false,
            encoding: '',
          }
          state.host = ''
          m.redraw()
        }
      })
    },

    remove: (origin) => () => {
      chrome.permissions.remove({origins: [`${origin}/*`]}, (removed) => {
        if (removed) {
          chrome.runtime.sendMessage({message: 'origin.remove', origin})
          webRequest()
          delete state.origins[origin]
          m.redraw()
        }
      })
    },

    refresh: (origin) => () => {
      chrome.permissions.request({origins: [`${origin}/*`]})
    },

    match: (origin) => (e) => {
      state.origins[origin].match = e.target.value
      clearTimeout(state.timeout)
      state.timeout = setTimeout(() => {
        var {match, csp, encoding} = state.origins[origin]
        chrome.runtime.sendMessage({
          message: 'origin.update',
          origin,
          options: {match, csp, encoding},
        })
      }, 750)
    },

    csp: (origin) => () => {
      state.origins[origin].csp = !state.origins[origin].csp
      var {match, csp, encoding} = state.origins[origin]
      chrome.runtime.sendMessage({
        message: 'origin.update',
        origin,
        options: {match, csp, encoding},
      })
      webRequest()
    },

    encoding: (origin) => (e) => {
      state.origins[origin].encoding = e.target.value
      var {match, csp, encoding} = state.origins[origin]
      chrome.runtime.sendMessage({
        message: 'origin.update',
        origin,
        options: {match, csp, encoding},
      })
      webRequest()
    },
  },
}

var webRequest = () => {
  // ff: webRequest is required permission
  if (/Firefox/.test(navigator.userAgent)) {
    return
  }

  var intercept = false
  for (var key in state.origins) {
    if (state.origins[key].csp || state.origins[key].encoding) {
      intercept = true
      break
    }
  }

  chrome.permissions[intercept ? 'request' : 'remove']({
    permissions: ['webRequest', 'webRequestBlocking']
  }, () => {
    chrome.runtime.sendMessage({
      message: 'options.intercept',
      intercept,
    })
  })
}

var oncreate = {
  ripple: (vnode) => {
    mdc.ripple.MDCRipple.attachTo(vnode.dom)
  },
  textfield: (vnode) => {
    mdc.textfield.MDCTextField.attachTo(vnode.dom)
  }
}

var onupdate = {
  header: (vnode) => {
    if (vnode.dom.classList.contains('is-checked') !== state.header) {
      vnode.dom.classList.toggle('is-checked')
    }
  },
  csp: (origin) => (vnode) => {
    if (vnode.dom.classList.contains('is-checked') !== state.origins[origin].csp) {
      vnode.dom.classList.toggle('is-checked')
    }
  }
}

m.mount(document.querySelector('main'), {
  view: () =>
    m('#options',

      // allowed origins
      m('.bs-callout m-origins',

        // add origin
        m('.m-add-origin',
          m('h4.mdc-typography--headline', 'Allowed Origins'),
          m('select.mdc-elevation--z2 m-select', {
            onchange: events.origin.scheme
            },
            state.schemes.map((scheme) =>
            m('option', {
              value: scheme,
              selected: scheme === state.scheme
              },
              scheme + '://'
            )
          )),
          m('.mdc-text-field m-textfield', {
            oncreate: oncreate.textfield,
            },
            m('input.mdc-text-field__input', {
              type: 'text',
              value: state.host,
              onchange: events.origin.host,
              placeholder: 'raw.githubusercontent.com'
            }),
            m('.mdc-line-ripple')
          ),
          m('button.mdc-button mdc-button--raised m-button', {
            oncreate: oncreate.ripple,
            onclick: events.origin.add()
            },
            'Add'
          ),
          m('button.mdc-button mdc-button--raised m-button', {
            oncreate: oncreate.ripple,
            onclick: events.origin.add(true)
            },
            'Allow All'
          )
        ),

        // global options
        m('.m-global',
          (
            (
              // header detection - ff: disabled
              !/Firefox/.test(navigator.userAgent) &&
              Object.keys(state.origins).length > 1
            )
            || null
          ) &&
          m('label.mdc-switch m-switch', {
            onupdate: onupdate.header,
            title: 'Toggle header detection'
            },
            m('input.mdc-switch__native-control', {
              type: 'checkbox',
              checked: state.header,
              onchange: events.header
            }),
            m('.mdc-switch__background', m('.mdc-switch__knob')),
            m('span.mdc-switch-label',
              'Detect ',
              m('code', 'text/markdown'),
              ' and ',
              m('code', 'text/x-markdown'),
              ' content type'
            )
          ),

          // file access is disabled
          (!state.file || null) &&
          m('button.mdc-button mdc-button--raised m-button', {
            oncreate: oncreate.ripple,
            onclick: events.file
            },
            'Allow Access to file:// URLs'
          )
        ),

        // allowed origins
        (state.file || Object.keys(state.origins).length > 1 || null) &&
        m('ul.m-list',
          Object.keys(state.origins).sort().map((origin) =>
            (
              (
                state.file && origin === 'file://' &&
                // ff: access to file:// URLs is not allowed
                !/Firefox/.test(navigator.userAgent)
              )
              || origin !== 'file://' || null
            ) &&
            m('li.mdc-elevation--z2', {
              class: state.origins[origin].expanded ? 'm-expanded' : null,
              },
              m('.m-summary', {
                onclick: (e) => state.origins[origin].expanded = !state.origins[origin].expanded
                },
                m('.m-origin', origin),
                m('.m-options',
                  state.origins[origin].match !== state.match ? m('span', 'match') : null,
                  state.origins[origin].csp ? m('span', 'csp') : null,
                  state.origins[origin].encoding ? m('span', 'encoding') : null,
                ),
                m('i.material-icons', {
                  class: state.origins[origin].expanded ? 'icon-arrow-up' : 'icon-arrow-down'
                })
              ),
              m('.m-content',
                // match
                m('.m-option m-match',
                  m('.m-name', m('span', 'match')),
                  m('.m-control',
                    m('.mdc-text-field m-textfield', {
                      oncreate: oncreate.textfield
                      },
                      m('input.mdc-text-field__input', {
                        type: 'text',
                        onkeyup: events.origin.match(origin),
                        value: state.origins[origin].match,
                      }),
                      m('.mdc-line-ripple')
                    )
                  )
                ),
                // csp
                (origin !== 'file://' || null) &&
                m('.m-option m-csp',
                  m('.m-name', m('span', 'csp')),
                  m('.m-control',
                    m('label.mdc-switch m-switch', {
                      onupdate: onupdate.csp(origin),
                      },
                      m('input.mdc-switch__native-control', {
                        type: 'checkbox',
                        checked: state.origins[origin].csp,
                        onchange: events.origin.csp(origin)
                      }),
                      m('.mdc-switch__background', m('.mdc-switch__knob')),
                      m('span.mdc-switch-label',
                        'Disable ',
                        m('code', 'Content Security Policy'),
                      )
                    )
                  )
                ),
                // encoding
                (origin !== 'file://' || null) &&
                m('.m-option m-encoding',
                  m('.m-name', m('span', 'encoding')),
                  m('.m-control',
                    m('select.mdc-elevation--z2 m-select', {
                      onchange: events.origin.encoding(origin),
                      },
                      m('option', {
                        value: '',
                        selected: state.origins[origin].encoding === ''
                        },
                        'auto'
                      ),
                      Object.keys(state.encodings).map((label) =>
                        m('optgroup', {label}, state.encodings[label].map((encoding) =>
                          m('option', {
                            value: encoding,
                            selected: state.origins[origin].encoding === encoding
                            },
                            encoding
                          )
                        ))
                      )
                    )
                  )
                ),
                // refresh/remove
                (origin !== 'file://' || null) &&
                m('.m-footer',
                  m('span',
                    m('button.mdc-button mdc-button--raised m-button', {
                      oncreate: oncreate.ripple,
                      onclick: events.origin.refresh(origin)
                      },
                      'Refresh'
                    ),
                    m('button.mdc-button mdc-button--raised m-button', {
                      oncreate: oncreate.ripple,
                      onclick: events.origin.remove(origin)
                      },
                      'Remove'
                    )
                  )
                )
              )
            )
          )
        )
      ),
    )
})

// ff: set appropriate footer icon
document.querySelector(
  '.icon-' + (/Firefox/.test(navigator.userAgent) ? 'firefox' : 'chrome')
).classList.remove('icon-hidden')
<|endoftext|>


<commit_before>(function(global) {
  var RS = RemoteStorage;
  /**
   * Dropbox backend for RemoteStorage.js
   */
  var haveLocalStorage;
  var AUTH_URL = 'https://www.dropbox.com/1/oauth2/authorize';

  var SETTINGS_KEY = 'remotestorage:dropbox';
  RS.Dropbox = function(rs) {
    this.rs = rs;
    this.connected = false;
    this.rs = rs;
    RS.eventHandling(this, 'change', 'connected');
    rs.on('error', function(error){
      if(error instanceof RemoteStorage.Unauthorized) {
        //TODO deconfiguer the dropbox here and now
      }
    });
    this.clientId = rs.apiKeys.dropbox.api_key;
    if(haveLocalStorage){
      var settings;
      try{
        settings = JSON.parse(localStorage[SETTINGS_KEY]);
      } catch(e){
        console.error(e);
      }
      if(settings) {
        this.configure(settings.userAdress, undefined, undefined, settings.token);
      }
    }
    if(this.connected) {
      setTimeout(this._emit.bind(this), 0, 'connected');
    }
  };

  RS.Dropbox.prototype = {

    connect: function() {
      this.rs.setBackend('dropbox');
      RS.Authorize(AUTH_URL, '', String(document.location), this.clientId);
    },

    configure: function(useradress, href, storageApi, token) {
      console.log('dropbox configure',arguments);
      if(typeof(token) !== 'undefined') this.token = token;
      if(typeof(useradress) !== 'undefined') this.useradress = token;

      if(this.token){
        this.connected = true;
        this._emit('connected');
      } else {
        this.connected = false;
      }
      if(haveLocalStorage){
        localStorage[SETTINGS_KEY] = JSON.stringify( { token: this.token,
                                                       useradress: this.useradress } );
      }
    },
    _getDir: function(path, options){
      var url = 'https://api.dropbox.com/1/metadata/auto'+path;
      var promise = promising();
      this._request('GET', url, {}, function(err, resp){
        if(err){
          promise.reject(err);
        }else{
          console.log(resp);
          var status = resp.status;
          if(status==304){
            promise.fulfill(status);
            return;
          }
          var listing, body, mime, rev;
          try{
            body = JSON.parse(resp.responseText)
          } catch(e) {
            promise.reject(e);
            return;
          }
          rev = body.rev;
          mime = 'application/json; charset=UTF-8'
          if(body.contents)
            listing = body.contents.reduce(function(m, item) {
              m[item.path.split('/').slice(-1)[0] +
                         ( item.is_dir ? '/' : '' ) ] = item.rev;
              return m;
            }, {});

          promise.fulfill(status, listing, mime, rev);
        }
      });
      return promise;
    },
    get: function(path, options){
      console.log('dropbox.get', arguments);
      if(path.substr(-1) == '/')
        return this._getDir(path, options);
      var url = 'https://api-content.dropbox.com/1/files/auto' + path
      var promise = promising();
      this._request('GET', url, {}, function(err, resp){
        if(err){
          promise.reject(err);
        }else{
          console.log(resp);
          var status = resp.status;
          var meta, body, mime, rev;
          if(status == 200){
            body = resp.responseText;
            try {
              meta = JSON.parse( resp.getResponseHeader('x-dropbox-metadata') );
            } catch(e) {
              promise.reject(e);
              return;
            }
            mime = meta.mime_type;
            rev = meta.rev;
            if(mime.search('application/json') >= 0)
              try {
                body = JSON.parse(body);
              } catch(e) {
                this.rs.log(e);
              }
          }
          promise.fulfill(status, body, mime, rev);
        }
      });
      return promise;
    },

    put: function(path, body, contentType, options){

      if(! this.connected) throw new Error("not connected (path: " + path + ")");
      var promise = promising();
      //check if file has changed and return 412
      var url = 'https://api-content.dropbox.com/1/files_put/auto/' + path + '?'
      this._request('PUT', url, {body:body, headers:{'Content-Type':contentType}}, function(err, resp) {
          if(err) {
            promise.reject(err)
          } else {
            console.log(resp);
            promise.fulfill(resp.status);
          }

      })
      return promise;
    },

    'delete': function(path, options){
      console.log('dropbox.delete ', arguemnts);
      //check if file has changed and return 412
      var url = 'https://api.dropbox.com/1/fileops/delete?root=auto&path='+encodeURIComponent(path);
      this._request('POST', url, {}, function(err, resp){
         if(err){
            promise.reject(error)
          }else{
            console.log(resp);
            promise.fulfill(resp.status);
          }
      })
    },

    _request: function(method, url, options, callback) {
      callback = callback.bind(this);
      if(! options.headers) options.headers = {};
      options.headers['Authorization'] = 'Bearer ' + this.token;
      RS.WireClient.request.call(this, method, url, options, function(err, xhr) {
        // google tokens expire from time to time...
        if(xhr.status == 401) {
          this.connect();
          return;
        }
        callback(err, xhr);
      });
    }
  };

  RS.Dropbox._rs_init = function(rs) {
    console.log("Dropbox init",rs);
    var config = rs.apiKeys.dropbox;
    if(config) {
      console.log('dropbox init ',config);
      rs.dropbox = new RS.Dropbox(rs);
    }
    if(rs.backend == 'dropbox'){
      rs._origRemote = rs.remote;
      rs.remote = rs.dropbox;
    }
  };

  RS.Dropbox._rs_supported = function() {
    haveLocalStorage = 'localStorage' in global;
    console.log("Dropbox _rs_supported ??");
    return true;
  };

  RS.Dropbox._rs_cleanup = function(rs) {
    console.log('rs_cleanup :P');
    if(haveLocalStorage){
      delete localStorage[SETTINGS_KEY];
      rs.setBackend(undefined);
    }
  };
})(this);
<commit_msg>info and useradress in dropbox<commit_after>(function(global) {
  var RS = RemoteStorage;
  /**
   * Dropbox backend for RemoteStorage.js
   */
  var haveLocalStorage;
  var AUTH_URL = 'https://www.dropbox.com/1/oauth2/authorize';

  var SETTINGS_KEY = 'remotestorage:dropbox';
  RS.Dropbox = function(rs) {
    this.rs = rs;
    this.connected = false;
    this.rs = rs;
    RS.eventHandling(this, 'change', 'connected');
    rs.on('error', function(error){
      if(error instanceof RemoteStorage.Unauthorized) {
        //TODO deconfiguer the dropbox here and now
      }
    });
    this.clientId = rs.apiKeys.dropbox.api_key;
    if(haveLocalStorage){
      var settings;
      try{
        settings = JSON.parse(localStorage[SETTINGS_KEY]);
      } catch(e){
        console.error(e);
      }
      if(settings) {
        this.configure(settings.userAdress, undefined, undefined, settings.token);
      }
    }
    if(this.connected) {
      setTimeout(this._emit.bind(this), 0, 'connected');
    }
  };

  RS.Dropbox.prototype = {

    connect: function() {
      this.rs.setBackend('dropbox');
      RS.Authorize(AUTH_URL, '', String(document.location), this.clientId);
    },

    configure: function(useradress, href, storageApi, token) {
      console.log('dropbox configure',arguments);
      if(typeof(token) !== 'undefined') this.token = token;
      if(typeof(useradress) !== 'undefined') this.useradress = token;

      if(this.token){
        this.connected = true;
        this._emit('connected');
        if(!this.useradress){
          this.info().then(function(info){
            this.configure(info.display_name);
          })
        }
      } else {
        this.connected = false;
      }
      if(haveLocalStorage){
        localStorage[SETTINGS_KEY] = JSON.stringify( { token: this.token,
                                                       useradress: this.useradress } );
      }
    },
    _getDir: function(path, options){
      var url = 'https://api.dropbox.com/1/metadata/auto'+path;
      var promise = promising();
      this._request('GET', url, {}, function(err, resp){
        if(err){
          promise.reject(err);
        }else{
          console.log(resp);
          var status = resp.status;
          if(status==304){
            promise.fulfill(status);
            return;
          }
          var listing, body, mime, rev;
          try{
            body = JSON.parse(resp.responseText)
          } catch(e) {
            promise.reject(e);
            return;
          }
          rev = body.rev;
          mime = 'application/json; charset=UTF-8'
          if(body.contents)
            listing = body.contents.reduce(function(m, item) {
              m[item.path.split('/').slice(-1)[0] +
                         ( item.is_dir ? '/' : '' ) ] = item.rev;
              return m;
            }, {});

          promise.fulfill(status, listing, mime, rev);
        }
      });
      return promise;
    },
    get: function(path, options){
      console.log('dropbox.get', arguments);
      if(path.substr(-1) == '/')
        return this._getDir(path, options);
      var url = 'https://api-content.dropbox.com/1/files/auto' + path
      var promise = promising();
      this._request('GET', url, {}, function(err, resp){
        if(err){
          promise.reject(err);
        }else{
          console.log(resp);
          var status = resp.status;
          var meta, body, mime, rev;
          if(status == 200){
            body = resp.responseText;
            try {
              meta = JSON.parse( resp.getResponseHeader('x-dropbox-metadata') );
            } catch(e) {
              promise.reject(e);
              return;
            }
            mime = meta.mime_type;
            rev = meta.rev;
            if(mime.search('application/json') >= 0)
              try {
                body = JSON.parse(body);
              } catch(e) {
                this.rs.log(e);
              }
          }
          promise.fulfill(status, body, mime, rev);
        }
      });
      return promise;
    },

    put: function(path, body, contentType, options){

      if(! this.connected) throw new Error("not connected (path: " + path + ")");
      var promise = promising();
      //check if file has changed and return 412
      var url = 'https://api-content.dropbox.com/1/files_put/auto/' + path + '?'
      this._request('PUT', url, {body:body, headers:{'Content-Type':contentType}}, function(err, resp) {
          if(err) {
            promise.reject(err)
          } else {
            console.log(resp);
            promise.fulfill(resp.status);
          }

      })
      return promise;
    },

    'delete': function(path, options){
      console.log('dropbox.delete ', arguemnts);
      //check if file has changed and return 412
      var url = 'https://api.dropbox.com/1/fileops/delete?root=auto&path='+encodeURIComponent(path);
      this._request('POST', url, {}, function(err, resp){
         if(err){
            promise.reject(error)
          }else{
            console.log(resp);
            promise.fulfill(resp.status);
          }
      })
    },
    info: function(){
      var url = 'https://api.dropbox.com/1/account/info'
      var promise = promising();
      this._request('GET', url, {}, function(err, resp){
        if(err) {
          promise.reject(err);
        } else {
          try {
            var info = JSON.parse(resp.responseText)
            promise.fulfill(info);
          } catch(e) {
            promise.reject(err);
          }
        }
      })
      return promise;
    },
    _request: function(method, url, options, callback) {
      callback = callback.bind(this);
      if(! options.headers) options.headers = {};
      options.headers['Authorization'] = 'Bearer ' + this.token;
      RS.WireClient.request.call(this, method, url, options, function(err, xhr) {
        // google tokens expire from time to time...
        if(xhr.status == 401) {
          this.connect();
          return;
        }
        callback(err, xhr);
      });
    }
  };

  RS.Dropbox._rs_init = function(rs) {
    console.log("Dropbox init",rs);
    var config = rs.apiKeys.dropbox;
    if(config) {
      console.log('dropbox init ',config);
      rs.dropbox = new RS.Dropbox(rs);
    }
    if(rs.backend == 'dropbox'){
      rs._origRemote = rs.remote;
      rs.remote = rs.dropbox;
    }
  };

  RS.Dropbox._rs_supported = function() {
    haveLocalStorage = 'localStorage' in global;
    console.log("Dropbox _rs_supported ??");
    return true;
  };

  RS.Dropbox._rs_cleanup = function(rs) {
    console.log('rs_cleanup :P');
    if(haveLocalStorage){
      delete localStorage[SETTINGS_KEY];
      rs.setBackend(undefined);
    }
  };
})(this);
<|endoftext|>


<commit_before>Components.utils.import("resource://places-in-tab/vars.js");

var placesInTab = {
  init: function () {
    if (nsPreferences.getBoolPref("extensions.places-in-tab.hide-original-menu-items", false)) {
      placesInTab.hideOriginal(document);
    }
  },

  showBookmarks: function (event) {
    query.leftPane = "AllBookmarks";
    openUILink("chrome://places-in-tab/content/places.xul", event, false, true);
  },

  showHistory: function (event) {
    query.leftPane = "History";
    openUILink("chrome://places-in-tab/content/places.xul", event, false, true);
  },

  hideOriginal: function (t) {
    t.getElementById("menu_showAllHistory").style.display = "none";
    t.getElementById("bookmarksShowAll").style.display    = "none";
  },

  showOriginal: function (t) {
    t.getElementById("menu_showAllHistory").style.display = "-moz-box";
    t.getElementById("bookmarksShowAll").style.display    = "-moz-box";
  },

  loadPrefs: function () {
    document.getElementById("hide-original-menu-items").checked = nsPreferences.getBoolPref("extensions.places-in-tab.hide-original-menu-items", false);
  },

  savePrefs: function () {
    var boolHideOriginal = document.getElementById("hide-original-menu-items").checked;
    nsPreferences.setBoolPref("extensions.places-in-tab.hide-original-menu-items", boolHideOriginal);

    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
    var mainWindow = wm.getMostRecentWindow("navigator:browser");

    if (boolHideOriginal) {
      placesInTab.hideOriginal(mainWindow.document);
    } else {
      placesInTab.showOriginal(mainWindow.document);
    }
  }
};

window.addEventListener("load", placesInTab.init, false);
<commit_msg>apply prefs to all browser window<commit_after>Components.utils.import("resource://places-in-tab/vars.js");

var placesInTab = {
  init: function () {
    if (nsPreferences.getBoolPref("extensions.places-in-tab.hide-original-menu-items", false)) {
      placesInTab.hideOriginal(document);
    }
  },

  showBookmarks: function (event) {
    query.leftPane = "AllBookmarks";
    openUILink("chrome://places-in-tab/content/places.xul", event, false, true);
  },

  showHistory: function (event) {
    query.leftPane = "History";
    openUILink("chrome://places-in-tab/content/places.xul", event, false, true);
  },

  hideOriginal: function (t) {
    t.getElementById("menu_showAllHistory").style.display = "none";
    t.getElementById("bookmarksShowAll").style.display    = "none";
  },

  showOriginal: function (t) {
    t.getElementById("menu_showAllHistory").style.display = "-moz-box";
    t.getElementById("bookmarksShowAll").style.display    = "-moz-box";
  },

  loadPrefs: function () {
    document.getElementById("hide-original-menu-items").checked = nsPreferences.getBoolPref("extensions.places-in-tab.hide-original-menu-items", false);
  },

  savePrefs: function () {
    var boolHideOriginal = document.getElementById("hide-original-menu-items").checked;
    nsPreferences.setBoolPref("extensions.places-in-tab.hide-original-menu-items", boolHideOriginal);

    var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
    var enumerator = wm.getEnumerator("navigator:browser");

    while (enumerator.hasMoreElements()) {
      var t = enumerator.getNext().document;

      if (boolHideOriginal) {
        placesInTab.hideOriginal(t);
      } else {
        placesInTab.showOriginal(t);
      }
    }
  }
};

window.addEventListener("load", placesInTab.init, false);
<|endoftext|>


<commit_before>'use strict';
const util = require('util');

/**
 * Reusable helper functions and defaults for effects.
 * Pass in the attribute/whatever else changes, along with the config.
 */

const defaultDuration = 10 * 1000;

const getTargetName = config => config.player ?
	config.player.getName() : config.target.getShortDesc('en');

const debuff = (attribute, config) => {
	config.magnitude = -config.magnitude;
	return buff(attribute, config);
};

const buff = (attribute, config) => {
	util.log('Buffing ' + attribute + ': ', getTargetName(config));
	util.log(config.magnitude);

	const original = config.target.getAttribute(attribute);
	return {
		duration: config.duration || defaultDuration,
		activate: () => {
			config.target.setAttribute(attribute, original + config.magnitude);
			if (config.activate) { config.activate(); }
		},
		deactivate: () => {
			if (config.target) {
				config.target.setAttribute(attribute, original);
				if (config.deactivate) { config.deactivate(); }
			}
		}
	};
};

const buffWithMax = (attribute, config) => {
	util.log('Buffing ' + attribute + ': ', getTargetName(config));
	util.log(config.magnitude);

	const max = 'max_' + attribute;
	const original = config.player.getAttribute(attribute);
	const originalMax = config.player.getAttribute(max);

	return {
		activate: () => {
			config.player.setAttribute(max, originalMax + config.magnitude);
			config.player.setAttribute(attribute, original + config.magnitude);
		},
		deactivate: () => {
			config.player.setAttribute(max, originalMax);
			config.player.setAttribute(attribute, Math.min(originalMax, config.player.getAttribute(attribute)));
			if (config.deactivate) { config.deactivate(); }
		},
		duration: config.duration || defaultDuration,
		event: config.event

	};
};

const multiply = (attribute, config) => {
	util.log('Multiplying ' + attribute + ': ', getTargetName(config));
	util.log(config.magnitude);

	const original = config.target.getAttribute(attribute);
	return {
		duration: config.duration || defaultDuration,
		activate: () => {
			config.target.setAttribute(attribute, original * config.magnitude);
			if (config.activate) { config.activate(); }
		},
		deactivate: () => {
			if (config.target) {
				config.target.setAttribute(attribute, original);
				if (config.deactivate) { config.deactivate(); }
			}
		}
	};
};

const Effects = {
  /**
   * Slow
	 * config.target: NPC to slow
	 * config.magnitude: amount to slow by (.5 would be half)
	 * [config.duration]: time in ms to slow for
	 * [config.deactivate]: function to execute after duration is over
   */
  slow: config => multiply('speed', config),

	/**
	 * Haste
	 * config.player: Player doing the targeting (or hasting themselves)
	 * config.targer: Player targeted
	 * config.magnitude
	 * [config.duration]: time in ms to haste for
	 * [config.deactivate]: function to execute after haste
	 */
	haste: config => {
		if (!config.target) { config.target = config.player; }
		return multiply('quickness', config);
	},

  /**
   * Health boost
	 * config.player: player whose health is boosted
   * config.magnitude: amount to boost health by
   * [config.duration]: amount of time to boost health
   * [config.event]: event to trigger health boost
   */
  health_boost:  config => buffWithMax('health', config),

	fortify: config => {
		if (!config.target) { config.target = config.player; }
		return buff('stamina', config);
	},

	regen: config => {
		const stat = config.stat || 'health';
		const max = 'max_' + stat;
		const attr = stat === 'health' ? 'stamina' : 'willpower';

		let regenHandle = null;

		return {
			activate: bonus => {
	      bonus = bonus || config.bonus || 1;
	      const self = config.player;
	      const regenInterval = config.interval || 2000;

	      regenHandle = setInterval(() => {
	        const current = self.getAttribute(stat);

	        let regenerated = Math.floor(Math.random() * self.getAttribute(attr) + bonus);
	        regenerated = Math.min(self.getAttribute(max), current + regenerated);

	        util.log(self.getName() + ' has regenerated up to ' + regenerated + ' ' + stat + '.');
	        self.setAttribute(stat, regenerated);

					self.setAttribute('energy', Math.max(regenerated, self.getAttribute('max_energy')));

	        if (regenerated === self.getAttribute(max)) {
	          clearInterval(regenHandle);
	        }
	      }, regenInterval);
    	},

			deactivate: () => {
				const verb = stat === 'health' ? 'resting' : 'meditating';
				clearInterval(regenHandle);
				player.say("<blue>You stop " + verb + '.</blue>');
			},
		};
	},

};

exports.Effects = Effects;
<commit_msg>Add checks for max energy, fix math.<commit_after>'use strict';
const util = require('util');

/**
 * Reusable helper functions and defaults for effects.
 * Pass in the attribute/whatever else changes, along with the config.
 */

const defaultDuration = 10 * 1000;

const getTargetName = config => config.player ?
	config.player.getName() : config.target.getShortDesc('en');

const debuff = (attribute, config) => {
	config.magnitude = -config.magnitude;
	return buff(attribute, config);
};

const buff = (attribute, config) => {
	util.log('Buffing ' + attribute + ': ', getTargetName(config));
	util.log(config.magnitude);

	const original = config.target.getAttribute(attribute);
	return {
		duration: config.duration || defaultDuration,
		activate: () => {
			config.target.setAttribute(attribute, original + config.magnitude);
			if (config.activate) { config.activate(); }
		},
		deactivate: () => {
			if (config.target) {
				config.target.setAttribute(attribute, original);
				if (config.deactivate) { config.deactivate(); }
			}
		}
	};
};

const buffWithMax = (attribute, config) => {
	util.log('Buffing ' + attribute + ': ', getTargetName(config));
	util.log(config.magnitude);

	const max = 'max_' + attribute;
	const original = config.player.getAttribute(attribute);
	const originalMax = config.player.getAttribute(max);

	return {
		activate: () => {
			config.player.setAttribute(max, originalMax + config.magnitude);
			config.player.setAttribute(attribute, original + config.magnitude);
		},
		deactivate: () => {
			config.player.setAttribute(max, originalMax);
			config.player.setAttribute(attribute, Math.min(originalMax, config.player.getAttribute(attribute)));
			if (config.deactivate) { config.deactivate(); }
		},
		duration: config.duration || defaultDuration,
		event: config.event

	};
};

const multiply = (attribute, config) => {
	util.log('Multiplying ' + attribute + ': ', getTargetName(config));
	util.log(config.magnitude);

	const original = config.target.getAttribute(attribute);
	return {
		duration: config.duration || defaultDuration,
		activate: () => {
			config.target.setAttribute(attribute, original * config.magnitude);
			if (config.activate) { config.activate(); }
		},
		deactivate: () => {
			if (config.target) {
				config.target.setAttribute(attribute, original);
				if (config.deactivate) { config.deactivate(); }
			}
		}
	};
};

const Effects = {
  /**
   * Slow
	 * config.target: NPC to slow
	 * config.magnitude: amount to slow by (.5 would be half)
	 * [config.duration]: time in ms to slow for
	 * [config.deactivate]: function to execute after duration is over
   */
  slow: config => multiply('speed', config),

	/**
	 * Haste
	 * config.player: Player doing the targeting (or hasting themselves)
	 * config.targer: Player targeted
	 * config.magnitude
	 * [config.duration]: time in ms to haste for
	 * [config.deactivate]: function to execute after haste
	 */
	haste: config => {
		if (!config.target) { config.target = config.player; }
		return multiply('quickness', config);
	},

  /**
   * Health boost
	 * config.player: player whose health is boosted
   * config.magnitude: amount to boost health by
   * [config.duration]: amount of time to boost health
   * [config.event]: event to trigger health boost
   */
  health_boost:  config => buffWithMax('health', config),

	fortify: config => {
		if (!config.target) { config.target = config.player; }
		return buff('stamina', config);
	},

	regen: config => {
		const stat = config.stat || 'health';
		const max = 'max_' + stat;
		const attr = stat === 'health' ? 'stamina' : 'willpower';

		let regenHandle = null;

		return {
			activate: bonus => {
	      bonus = bonus || config.bonus || 1;
	      const self = config.player;
	      const regenInterval = config.interval || 2000;

	      regenHandle = setInterval(() => {
	        const current = self.getAttribute(stat);

	        let regenerated = Math.floor(Math.random() * self.getAttribute(attr) + bonus);
	        regenerated = Math.min(self.getAttribute(max), current + regenerated);

	        util.log(self.getName() + ' has regenerated up to ' + regenerated + ' ' + stat + '.');
	        self.setAttribute(stat, regenerated);

					if (regenerated > self.getAttribute('max_energy')) {
						self.setAttribute('energy', Math.min(regenerated, self.getAttribute('max_energy')));
					}

	        if (regenerated === self.getAttribute(max)) {
	          clearInterval(regenHandle);
	        }
	      }, regenInterval);
    	},

			deactivate: () => {
				const verb = stat === 'health' ? 'resting' : 'meditating';
				clearInterval(regenHandle);
				player.say("<blue>You stop " + verb + '.</blue>');
			},
		};
	},

};

exports.Effects = Effects;
<|endoftext|>


<commit_before>var Git      = require('../model/git'),
    mainView = require('../view/main');

var editor = require('./editor');

// model control
var git = new Git(__dirname);

var main = {
  screen: mainView.screen,

  moveToStaged: function (index) {
    mainView.list.staged.interactive   = true;
    mainView.list.unstaged.interactive = false;
    mainView.list.staged.select(index !== undefined ? index : mainView.list.unstaged.selected);
    mainView.list.staged.focus();
    mainView.screen.render();
  },

  moveToUnstaged: function (index) {
    mainView.list.staged.interactive   = false;
    mainView.list.unstaged.interactive = true;
    mainView.list.unstaged.select(index !== undefined ? index : mainView.list.staged.selected);
    mainView.list.unstaged.focus();
    mainView.screen.render();
  },

  // TODO: Fix crash if there is no item
  toggle: function (type, list) {
    var selected = git.isSelected(type, list.selected);

    if (selected) {
      git.deselect(type, list.selected);
      list.unmark();
    } else {
      git.select(type, list.selected);
      list.mark();
    }

    mainView.screen.render();
  },

  selectAll: function (type) {
    var selected = git.isSelected(type);

    if (selected) {
      git.deselect(type);
      mainView.setItems(git);
    } else {
      git.select(type);
      mainView.setItems(git);
    }

    mainView.screen.render();
  },

  // initialize
  reload: function () {
    git.status();

    mainView.setItems(git);

    main.moveToUnstaged(0);

    mainView.loading.stop();
  },

  commit: function (message) {
    // TODO: Check other exceptions

    git.commit(message);

    main.reload();
  }
};

// bind editor
editor.init(main);

// event binding
mainView.screen.key(['escape'], function () {
  return process.exit(0);
});

mainView.screen.key(['left'], function () {
  main.moveToStaged();
});

mainView.screen.key(['right'], function () {
  main.moveToUnstaged();
});

mainView.list.staged.key(['space'], function () {
  main.toggle('staged', this);
});

mainView.list.staged.key(['enter'], function () {
  main.selectAll('staged', this);
});

mainView.list.unstaged.key(['space'], function () {
  main.toggle('unstaged', this);
});

mainView.list.unstaged.key(['enter'], function () {
  main.selectAll('unstaged', this);
});

// git commands
mainView.screen.key(['C-a'], function () {
  git.add();

  main.reload();
});

mainView.screen.key(['C-r'], function () {
  git.reset();

  main.reload();
});

mainView.screen.key(['C-c'], function () {
  if (git.getStagedFiles().length < 1) {
    // TODO: alert
    return;
  }

  editor.show();
});

mainView.screen.key(['C-p'], function () {
  // Push
});

module.exports = main;

<commit_msg>Add #3 move to next item automatically<commit_after>var Git      = require('../model/git'),
    mainView = require('../view/main');

var editor = require('./editor');

// model control
var git = new Git(__dirname);

var main = {
  screen: mainView.screen,

  moveToStaged: function (index) {
    mainView.list.staged.interactive   = true;
    mainView.list.unstaged.interactive = false;
    mainView.list.staged.select(index !== undefined ? index : mainView.list.unstaged.selected);
    mainView.list.staged.focus();
    mainView.screen.render();
  },

  moveToUnstaged: function (index) {
    mainView.list.staged.interactive   = false;
    mainView.list.unstaged.interactive = true;
    mainView.list.unstaged.select(index !== undefined ? index : mainView.list.staged.selected);
    mainView.list.unstaged.focus();
    mainView.screen.render();
  },

  next: function (list) {
    list.move(1);
    mainView.screen.render();
  },

  // TODO: Fix crash if there is no item
  toggle: function (type, list) {
    var selected = git.isSelected(type, list.selected);

    if (selected) {
      git.deselect(type, list.selected);
      list.unmark();
    } else {
      git.select(type, list.selected);
      list.mark();
    }

    mainView.screen.render();
  },

  selectAll: function (type) {
    var selected = git.isSelected(type);

    if (selected) {
      git.deselect(type);
      mainView.setItems(git);
    } else {
      git.select(type);
      mainView.setItems(git);
    }

    mainView.screen.render();
  },

  // initialize
  reload: function () {
    git.status();

    mainView.setItems(git);

    main.moveToUnstaged(0);

    mainView.loading.stop();
  },

  commit: function (message) {
    // TODO: Check other exceptions

    git.commit(message);

    main.reload();
  }
};

// bind editor
editor.init(main);

// event binding
mainView.screen.key(['escape'], function () {
  return process.exit(0);
});

mainView.screen.key(['left'], function () {
  main.moveToStaged();
});

mainView.screen.key(['right'], function () {
  main.moveToUnstaged();
});

mainView.list.staged.key(['space'], function () {
  main.toggle('staged', this);
  main.next(this);
});

mainView.list.staged.key(['enter'], function () {
  main.selectAll('staged', this);
});

mainView.list.unstaged.key(['space'], function () {
  main.toggle('unstaged', this);
  main.next(this);
});

mainView.list.unstaged.key(['enter'], function () {
  main.selectAll('unstaged', this);
});

// git commands
mainView.screen.key(['C-a'], function () {
  git.add();

  main.reload();
});

mainView.screen.key(['C-r'], function () {
  git.reset();

  main.reload();
});

mainView.screen.key(['C-c'], function () {
  if (git.getStagedFiles().length < 1) {
    // TODO: alert
    return;
  }

  editor.show();
});

mainView.screen.key(['C-p'], function () {
  // Push
});

module.exports = main;

<|endoftext|>


<commit_before>class Space {
  constructor(iterable) {
    if (!iterable) {
      throw new Error();
    }
    this.table = new Map(iterable);
  }

  toString() {
    let object = Object.create(null);
    for (let [key, value] of this.table) {
      object[key] = value;
    }
    return JSON.stringify(object);
  }

  isValid() {
    return false;
  }

  clone() {
    throw new Error("clone() is not implemented");
  }

  hex() {
    throw new Error("hex() is not implemented");
  }

  rgb() {
    throw new Error("rgb() is not implemented");
  }

  hsl() {
    throw new Error("hsl() is not implemented");
  }

  cmyk() {
    throw new Error("cmyk() is not implemented");
  }

  get(key) {
    return this.table.get(key);
  }

  set(key, value) {
    return this.table.set(key, value);
  }

  getOrSet(key, value = null) {
    if (value == null) {
      return this.get(key);
    }
    this.set(key, value);
    return this;
  }

  values() {
    return this.table.values();
  }
}

export class Rgb extends Space {
  static KEY_R = "r";
  static KEY_G = "g";
  static KEY_B = "b";

  constructor(r, g, b) {
    super([[Rgb.KEY_R, r], [Rgb.KEY_G, g], [Rgb.KEY_B, b]]);
  }

  toString() {
    return `rgb(${this.r()}, ${this.g()}, ${this.b()})`;
  }

  isValid() {
    let values = this.values();
    for (let value of values) {
      if (value < 0x00 || value > 0xFF) {
        return false;
      }
    }
    return true;
  }

  clone() {
    return new Rgb(this.r(), this.g(), this.b());
  }

  r(value = null) {
    return this.getOrSet(Rgb.KEY_R, value);
  }

  g(value = null) {
    return this.getOrSet(Rgb.KEY_G, value);
  }

  b(value = null) {
    return this.getOrSet(Rgb.KEY_B, value);
  }

  hex() {
    let parts = [];
    for (let value of this.values()) {
      let text = value.toString(16);
      if (text.length === 1) {
        text = `0${text}`;
      }
      parts.push(text.toUppderCase());
    }
    return `#${parts.join('')}`;
  }

  rgb() {
    return this;
  }

  hsl() {
    let r = this.r() / 0xFF;
    let g = this.g() / 0xFF;
    let b = this.b() / 0xFF;

    let max   = Math.max(r, g, b);
    let min   = Math.min(r, g, b);
    let delta = max - min;
    if (delta === 0) {
      return new Hsl(0, 0, max);
    }

    let h = 0;
    if (max === r) {
      h = 60 * ((g - b) / delta % 360);
    } else if (max === g) {
      h = 60 * ((b - r) / delta + 2);
    } else if (max === b) {
      h = 60 * ((r - g) / delta + 4);
    }

    let l = (max + min) / 2;

    let s = delta / (1 - Math.abs(2 * l - 1))

    return new Hsl(h, s, l);
  }

  cmyk() {
    let r = this.r() / 0xFF;
    let g = this.g() / 0xFF;
    let b = this.b() / 0xFF;

    let k = 1 - Math.max(r, g, b);
    if (k === 1) {
      return new Cmyk(0, 0, 0, 1);
    }

    let c = (1 - r - k) / (1 - k);
    let m = (1 - g - k) / (1 - k);
    let y = (1 - b - k) / (1 - k);
    return new Cmyk(c, m, y, k);
  }
}

export class Hsl extends Space {
  static KEY_H = "h";
  static KEY_S = "s";
  static KEY_L = "l";

  constructor(h, s, l) {
    super([[Hsl.KEY_H, h], [Hsl.KEY_S, s], [Hsl.KEY_L, l]]);
  }

  toString() {
    return `hsl(${this.h()}, ${this.s()}%, ${this.l()}%)`;
  }

  clone() {
    return new Hsl(this.h(), this.s(), this.l());
  }

  isValid() {
    let h = this.h();
    if (!Number.isFinite(h) || h < 0 || h > 360) {
      return false;
    }

    let s = this.s();
    if (!Number.isFinite(s) || s < 0 || s > 100) {
      return false;
    }

    let l = this.l();
    if (!Number.isFinite(l) || l < 0 || l > 100) {
      return false;
    }
    return true;
  }

  h(value = null) {
    return this.getOrSet(Hsl.KEY_H, value);
  }

  s(value = null) {
    return this.getOrSet(Hsl.KEY_S, value);
  }

  l(value = null) {
    return this.getOrSet(Hsl.KEY_L, value);
  }

  hex() {
    return this.rgb().hex();
  }

  rgb() {
    let h = this.h();
    let s = this.s();
    let l = this.l();
    if (s === 0) {
      let value = Math.round(l * 0xFF);
      return new Rgb(value, value, value);
    }

    let m2 = 0;
    if (l < 0.5) {
      m2 = l * (s + 1);
    } else {
      m2 = l + s - l * s;
    }

    let m1 = 2 * l - m2;
    let r = Math.round(255 * Hsl.hueToRgb(m1, m2, h / 360 + 1 / 3));
    let g = Math.round(255 * Hsl.hueToRgb(m1, m2, h / 360));
    let b = Math.round(255 * Hsl.hueToRgb(m1, m2, h / 360 - 1 / 3));
    return new Rgb(r, g, b)
  }

  hsl() {
    return this;
  }

  cmyk() {
    return this.rgb().cmyk();
  }

  static hueToRgb(m1, m2, h) {
    if (h < 0) {
      h += 1;
    } else if (h > 1) {
      h -= 1;
    }

    if (h * 6 < 1) {
      return m1 + (m2 - m1) * h * 6;
    } else if (h * 2 < 1) {
      return m2;
    } else if (h * 3 < 2) {
      return m1 + (m2 - m1) * (2 / 3 - h) * 6;
    }
    return m1;
  }
}

export class Cmyk extends Space {
  static KEY_C = 'c';
  static KEY_M = 'm';
  static KEY_Y = 'y';
  static KEY_K = 'k';

  constructor(c, m, y, k) {
    super([[Cmyk.KEY_C, c], [Cmyk.KEY_M, m], [Cmyk.KEY_Y, y], [Cmyk.KEY_K]]);
  }

  isValid() {
    for (let value of this.values()) {
      if (!Number.isFinite(value)) {
        return false;
      }
      if (value < 0 || value > 1) {
        return false;
      }
    }
    return true;
  }

  clone() {
    return new Cmyk(this.c(), this.m(), this.y(), this.k());
  }

  c(value = null) {
    return this.getOrSet(Cmyk.KEY_C, value);
  }

  m(value = null) {
    return this.getOrSet(Cmyk.KEY_M, value);
  }

  y(value = null) {
    return this.getOrSet(Cmyk.KEY_Y, value);
  }

  k(value = null) {
    return this.getOrSet(Cmyk.KEY_K, value);
  }

  hex() {
    return this.rgb().hex();
  }

  rgb() {
    let k = this.k();
    if (k === 1) {
      return new Rgb(0, 0, 0);
    }

    let r = 0xFF * (1 - this.c()) * (1 - k);
    let g = 0xFF * (1 - this.m()) * (1 - k);
    let b = 0xFF * (1 - this.y()) * (1 - k);
    return new Rgb(r, g, b);
  }
}
<commit_msg>Added color space conversion method that converts from cmyk to hsl<commit_after>class Space {
  constructor(iterable) {
    if (!iterable) {
      throw new Error();
    }
    this.table = new Map(iterable);
  }

  toString() {
    let object = Object.create(null);
    for (let [key, value] of this.table) {
      object[key] = value;
    }
    return JSON.stringify(object);
  }

  isValid() {
    return false;
  }

  clone() {
    throw new Error("clone() is not implemented");
  }

  hex() {
    throw new Error("hex() is not implemented");
  }

  rgb() {
    throw new Error("rgb() is not implemented");
  }

  hsl() {
    throw new Error("hsl() is not implemented");
  }

  cmyk() {
    throw new Error("cmyk() is not implemented");
  }

  get(key) {
    return this.table.get(key);
  }

  set(key, value) {
    return this.table.set(key, value);
  }

  getOrSet(key, value = null) {
    if (value == null) {
      return this.get(key);
    }
    this.set(key, value);
    return this;
  }

  values() {
    return this.table.values();
  }
}

export class Rgb extends Space {
  static KEY_R = "r";
  static KEY_G = "g";
  static KEY_B = "b";

  constructor(r, g, b) {
    super([[Rgb.KEY_R, r], [Rgb.KEY_G, g], [Rgb.KEY_B, b]]);
  }

  toString() {
    return `rgb(${this.r()}, ${this.g()}, ${this.b()})`;
  }

  isValid() {
    let values = this.values();
    for (let value of values) {
      if (value < 0x00 || value > 0xFF) {
        return false;
      }
    }
    return true;
  }

  clone() {
    return new Rgb(this.r(), this.g(), this.b());
  }

  r(value = null) {
    return this.getOrSet(Rgb.KEY_R, value);
  }

  g(value = null) {
    return this.getOrSet(Rgb.KEY_G, value);
  }

  b(value = null) {
    return this.getOrSet(Rgb.KEY_B, value);
  }

  hex() {
    let parts = [];
    for (let value of this.values()) {
      let text = value.toString(16);
      if (text.length === 1) {
        text = `0${text}`;
      }
      parts.push(text.toUppderCase());
    }
    return `#${parts.join('')}`;
  }

  rgb() {
    return this;
  }

  hsl() {
    let r = this.r() / 0xFF;
    let g = this.g() / 0xFF;
    let b = this.b() / 0xFF;

    let max   = Math.max(r, g, b);
    let min   = Math.min(r, g, b);
    let delta = max - min;
    if (delta === 0) {
      return new Hsl(0, 0, max);
    }

    let h = 0;
    if (max === r) {
      h = 60 * ((g - b) / delta % 360);
    } else if (max === g) {
      h = 60 * ((b - r) / delta + 2);
    } else if (max === b) {
      h = 60 * ((r - g) / delta + 4);
    }

    let l = (max + min) / 2;

    let s = delta / (1 - Math.abs(2 * l - 1))

    return new Hsl(h, s, l);
  }

  cmyk() {
    let r = this.r() / 0xFF;
    let g = this.g() / 0xFF;
    let b = this.b() / 0xFF;

    let k = 1 - Math.max(r, g, b);
    if (k === 1) {
      return new Cmyk(0, 0, 0, 1);
    }

    let c = (1 - r - k) / (1 - k);
    let m = (1 - g - k) / (1 - k);
    let y = (1 - b - k) / (1 - k);
    return new Cmyk(c, m, y, k);
  }
}

export class Hsl extends Space {
  static KEY_H = "h";
  static KEY_S = "s";
  static KEY_L = "l";

  constructor(h, s, l) {
    super([[Hsl.KEY_H, h], [Hsl.KEY_S, s], [Hsl.KEY_L, l]]);
  }

  toString() {
    return `hsl(${this.h()}, ${this.s()}%, ${this.l()}%)`;
  }

  clone() {
    return new Hsl(this.h(), this.s(), this.l());
  }

  isValid() {
    let h = this.h();
    if (!Number.isFinite(h) || h < 0 || h > 360) {
      return false;
    }

    let s = this.s();
    if (!Number.isFinite(s) || s < 0 || s > 100) {
      return false;
    }

    let l = this.l();
    if (!Number.isFinite(l) || l < 0 || l > 100) {
      return false;
    }
    return true;
  }

  h(value = null) {
    return this.getOrSet(Hsl.KEY_H, value);
  }

  s(value = null) {
    return this.getOrSet(Hsl.KEY_S, value);
  }

  l(value = null) {
    return this.getOrSet(Hsl.KEY_L, value);
  }

  hex() {
    return this.rgb().hex();
  }

  rgb() {
    let h = this.h();
    let s = this.s();
    let l = this.l();
    if (s === 0) {
      let value = Math.round(l * 0xFF);
      return new Rgb(value, value, value);
    }

    let m2 = 0;
    if (l < 0.5) {
      m2 = l * (s + 1);
    } else {
      m2 = l + s - l * s;
    }

    let m1 = 2 * l - m2;
    let r = Math.round(255 * Hsl.hueToRgb(m1, m2, h / 360 + 1 / 3));
    let g = Math.round(255 * Hsl.hueToRgb(m1, m2, h / 360));
    let b = Math.round(255 * Hsl.hueToRgb(m1, m2, h / 360 - 1 / 3));
    return new Rgb(r, g, b)
  }

  hsl() {
    return this;
  }

  cmyk() {
    return this.rgb().cmyk();
  }

  static hueToRgb(m1, m2, h) {
    if (h < 0) {
      h += 1;
    } else if (h > 1) {
      h -= 1;
    }

    if (h * 6 < 1) {
      return m1 + (m2 - m1) * h * 6;
    } else if (h * 2 < 1) {
      return m2;
    } else if (h * 3 < 2) {
      return m1 + (m2 - m1) * (2 / 3 - h) * 6;
    }
    return m1;
  }
}

export class Cmyk extends Space {
  static KEY_C = 'c';
  static KEY_M = 'm';
  static KEY_Y = 'y';
  static KEY_K = 'k';

  constructor(c, m, y, k) {
    super([[Cmyk.KEY_C, c], [Cmyk.KEY_M, m], [Cmyk.KEY_Y, y], [Cmyk.KEY_K]]);
  }

  isValid() {
    for (let value of this.values()) {
      if (!Number.isFinite(value)) {
        return false;
      }
      if (value < 0 || value > 1) {
        return false;
      }
    }
    return true;
  }

  clone() {
    return new Cmyk(this.c(), this.m(), this.y(), this.k());
  }

  c(value = null) {
    return this.getOrSet(Cmyk.KEY_C, value);
  }

  m(value = null) {
    return this.getOrSet(Cmyk.KEY_M, value);
  }

  y(value = null) {
    return this.getOrSet(Cmyk.KEY_Y, value);
  }

  k(value = null) {
    return this.getOrSet(Cmyk.KEY_K, value);
  }

  hex() {
    return this.rgb().hex();
  }

  rgb() {
    let k = this.k();
    if (k === 1) {
      return new Rgb(0, 0, 0);
    }

    let r = 0xFF * (1 - this.c()) * (1 - k);
    let g = 0xFF * (1 - this.m()) * (1 - k);
    let b = 0xFF * (1 - this.y()) * (1 - k);
    return new Rgb(r, g, b);
  }

  hsl() {
    return this.rgb().hsl();
  }
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var validator = require('validator');

var countries = require('../resources/countriesV1');

exports.index = function(req, res) {
  res.send({message : 'Welcome buddy!'});
};

exports.getAll = function(req, res) {
  res.json(200, countries)
}

exports.callingCode = function(req, res) {

  var calling_code = req.params.callingCode;

  var country = _.find(countries, function(co) {
    return validator.isIn(calling_code, co.callingCode)
  });

  res.json(200, country)
}

exports.region = function (req, res, next) {

  var result = [];
  var region_name = req.params.regionName;

  var country_region = _.reduce(countries, function(result, country, key) {

    if(country.region.toLowerCase() == region_name.toLowerCase()) {
      result.push(country);
    }
    return result;
  }, []);

  if(country_region == undefined) {
    res.json(204, { 'msg' : 'No country found'});
  } else {
    res.json(200, country_region);
  }
}
<commit_msg>status code 400 if country not found<commit_after>var _ = require('lodash');
var validator = require('validator');

var countries = require('../resources/countriesV1');

var notFound = function(res) {
  res.json(404, { "status": 404, "message": "Not Found" })
}

exports.index = function(req, res) {
  res.send({message : 'Welcome buddy!'});
};

exports.getAll = function(req, res) {
  res.json(200, countries)
}

exports.callingCode = function(req, res) {

  var calling_code = req.params.callingCode;

  var country = _.find(countries, function(co) {
    return validator.isIn(calling_code, co.callingCode)
  });

  if(!country) {
    notFound(res);
  }

  res.json(200, country)
}

exports.region = function (req, res, next) {

  var result = [];
  var region_name = req.params.regionName;

  var country_region = _.reduce(countries, function(result, country, key) {

    if(country.region.toLowerCase() == region_name.toLowerCase()) {
      result.push(country);
    }
    return result;
  }, []);

  if(country_region.length < 1) {
    notFound(res);
  }

  res.json(200, country_region);
}
<|endoftext|>


<commit_before>/**
 * Stack
 * notation key
 * a                    = function 'a'
 * [a]                  = an instance of Stack with the function 'a'
 * <action> => <result> = a transformation of the Stack/Stack sequence
 * <action> // <result> = a return value
 * <action> || <result> = the effect of the <action>
 * [a,b,c]              = an array of functions 'a', 'b', 'c'
 * [default]            = an instance of Stack with 'defaultFn' function
 * [a[b]]               = an instance of Stack with function 'a' and a next [b]
 * [a[b[c]]]            = an instance of Stack with the head [a] and tail [c]
 * {x}                  = some value x
 * [{x},{y}]            = an array of values {x} and {y}
 * a(x)                 = function 'a' invoked with argument {x}
 * a(x, y)              = function 'a' invoked with arguments {x} and {y}
 * ?                    = an object
 * &&                   = logical and
 */
(function(global, undef) {
    function makeArray(val) {
        return Array.isArray(val) ? val : val ? [val] : [];
    }
    function defaultFn() {
        return arguments.length > 1 ? arguments : arguments[0];
    }
    function recur(fn) {
        return function () {
            var bounce = fn.apply(this, arguments);
            while (typeof bounce === "function") {
                bounce = bounce();
            }
            return bounce;
        };
    }
    /**
     * Stack
     * Stack() => [default] //[default]
     * Stack(a) => [a] //[a]
     * Stack([a,b,c]) => [a[b[c]]] // [a[b[c]]]
     * Stack(a, [b]) => [a[b]] // [a[b]]
     * @param fn {Function|Array}
     * @param [next {Stack}]
     * @returns {Stack}
     * @constructor
     */
    function Stack(fn, next) {
        if (Array.isArray(fn)) {
            return fn.reduce(function (stack, f) {
                return stack.push(f);
            }, new Stack(fn.shift()));
        }
        if (!(this instanceof Stack)) {
            return new Stack(fn, next);
        }
        this.fn = fn || defaultFn;
        this.next = next || undef;
    }
    /**
     * push
     * [a].push(b) => [a[b]].push(c) => [a[b[c]]] // [a[b[c]]]
     * @param fn {Function}
     * @returns {Stack}
     */
    Stack.prototype.push = function(fn) {
        return new Stack(fn, this);
    };
    /**
     * insert
     * [a].insert(c) => [a[c]].insert(b) => [a[b[c]]] // [a[b[c]]]
     * @param fn
     * @returns {Stack}
     */
    Stack.prototype.insert = function (fn) {
        return this.next = new Stack(fn, this.next);
    };
    /**
     * index
     * [a[b[c]]].index(1) // [b]
     * @param idx
     * @returns {Stack|undefined}
     */
    Stack.prototype.index = recur(function index(idx) {
        var self = this;
        return function () {
            return !idx ? self : self.next && index.call(self.next, idx - 1);
        };
    });
    /**
     * priorNext
     * [a[b[c[d]]]].priorNext([d]) // [b]
     * @param [stack]
     * @returns {Stack|undefined}
     */
    Stack.prototype.priorNext = recur(function priorNext(stack) {
        var self = this;
        return function () {
            return self.next && self.next.next === stack ? self : self.next && priorNext.call(self.next, stack);
        };
    });
    /**
     * priorFn
     * [a[b[c]]].priorNext(b) // [a]
     * @param fn
     * @returns {Stack|undefined}
     */
    Stack.prototype.priorFn = recur(function priorFn(fn) {
        var self = this;
        return function () {
            return (self.next && self.next.fn === fn) ? self : self.next && priorFn.call(self.next, fn);
        };
    });
    /**
     * isNext
     * [a[b]].isNext([b]) //true
     * @param stack
     * @returns {boolean}
     */
    Stack.prototype.isNext = function (stack) {
        return stack === this.next;
    };
    /**
     * isFn
     * [a].isFn(a) //true
     * @param fn
     * @returns {boolean}
     */
    Stack.prototype.isFn = function (fn) {
        return fn === this.fn;
    };
    /**
     * searchNext
     * [a[b[c]]].searchNext([c]) //[b]
     * @param [stack]
     * @returns {Stack|undefined}
     */
    Stack.prototype.searchNext = recur(function searchNext(stack) {
        var self = this;
        return function () {
            return self.isNext(stack) && self || self.next && searchNext.call(self.next, stack);
        };
    });
    /**
     * searchFn
     * [a[b[c]]].searchFn(b) //[b]
     * @param fn
     * @returns {Stack|undefined}
     */
    Stack.prototype.searchFn = recur(function searchFn(fn) {
        var self = this;
        return function () {
            return self.isFn(fn) && self || self.next && searchFn.call(self.next, fn);
        };
    });
    /**
     * distribute
     * [a[b[c]]].distribute({x}) || a(x), b(x), c(x)
     * [a[b[c]]].distribute({x}, ?) || ?.a(x), ?.b(x), ?.c(x)
     * @param arg
     * @param receiver
     * @returns {undefined}
     */
    Stack.prototype.distribute = recur(function distribute(arg, receiver) {
        var self = this;
        return function () {
            self.fn.call(receiver || self, arg);
            return self.next && distribute.call(self.next, arg, receiver || self);
        };
    });
    /**
     * distributeAll
     * [a[b[c]]].distribute([{x},{y},{z}]) || a(x,y,z), b(x,y,z), c(x,y,z)
     * [a[b[c]]].distribute([{x},{y},{z}], ?) || ?.a(x,y,z), ?.b(x,y,z), ?.c(x,y,z)
     * @param args
     * @param receiver
     * @returns {undefined}
     */
    Stack.prototype.distributeAll = recur(function distributeAll(args, receiver) {
        var self = this;
        return function () {
            self.fn.apply(receiver|| self, args);
            return self.next && distributeAll.call(self.next, makeArray(args), receiver || self);
        };
    });
    /**
     * call
     * [a[b[c]]].call({x}) // a(b(c(x)))
     * [a[b[c]]].call({x}, ?) // ?.a(?.b(?.c(x)))
     * @param arg
     * @param receiver
     * @returns {*}
     */
    Stack.prototype.call = recur(function call(arg, receiver) {
        var self = this;
        return function () {
            var val = self.fn.call(receiver || self, arg);
            return self.next && call.call(self.next, val, receiver) || val;
        };
    });
    /**
     * apply
     * [a[b[c]]].apply([{x},{y},{z}]) // a(b(c(x,y,z)))
     * [a[b[c]]].apply([{x},{y},{z}], ?) // ?.a(?.b(?.c(x,y,z)))
     * @param args
     * @param receiver
     * @returns {*}
     */
    Stack.prototype.apply = recur(function apply(args, receiver) {
        var self = this;
        return function () {
            var val = self.fn.apply(receiver|| self, args);
            return self.next && apply.call(self.next, makeArray(val), receiver) || val;
        }
    });
    /**
     * clone
     * [a[b[c]]].clone() // [a[b[c]]]
     * [a[b[c]]].clone(d) // [d[b[c]]]
     * [a[b[c]]].clone(null, [d]) // [a[d]]
     * [a[b[c]]].clone(d, [e]) // [d[e]]
     * @param fn
     * @param next
     * @returns {Stack}
     */
    Stack.prototype.clone = function (fn, next) {
        return new Stack(fn || this.fn, next || this.next);
    };
    /**
     * tail
     * [a[b[c]]].tail() // [c]
     * @returns {Stack|undefined}
     */
    Stack.prototype.tail = function () {
        return this.searchNext();
    };
    /**
     * unshift
     * [a[b]].unshift(c) => [a[b[c]]] // [c]
     * @param fn
     * @returns {Stack}
     */
    Stack.prototype.unshift = function (fn) {
        return this.tail().insert(fn);
    };
    /**
     * before
     * [a[b[c]]].before(b, d) => [a[d[b[c]]]] // [d[b[c]]]
     * @param a
     * @param b
     * @returns {Stack}
     */
    Stack.prototype.before = function (a, b) {
        return (this.searchFn(a || undef) || this).insert(b);
    };
    /**
     * shift
     * [a[b[c]]].shift() => [a[b]] // [c]
     * @returns {Stack}
     */
    Stack.prototype.shift = function () {
        var p = this.priorNext();
        var removed = p.next;
        p.next = undef;
        return removed;
    };
    /**
     * [a[b[c]]].pop() => [a], [b[c]] // [a]
     * @returns {Stack}
     */
    Stack.prototype.pop = function () {
        this.next = undef;
        return this;
    };
    /**
     * some
     * [a[b[c]]].some() || !c() && !b() && !c() // true|false
     * [a[b[c]]].some({x}) || !c(x) && !b(x) && !c(x) // true|false
     * @param arg
     * @param receiver
     * @returns {boolean}
     */
    Stack.prototype.some = recur(function some(arg, receiver) {
        var self = this;
        return function () {
            var val = self.fn.call(receiver || self, arg);
            return val !== true && !self.next ? false :
                self.next && val !== true ? some.call(self.next, arg, receiver) :
                    true;
        };
    });
    /**
     * every
     * [a[b[c]]].every() || c() && b() && c() // true|false
     * [a[b[c]]].every({x}) || c(x) && b(x) && c(x) // true|false
     * @param arg
     * @param receiver
     * @returns {boolean}
     */
    Stack.prototype.every = recur(function every(arg, receiver) {
        var self = this;
        return function () {
            var val = self.fn.call(receiver || self, arg);
            return val !== false && !self.next ? true :
                self.next && val !== false ? every.call(self.next, arg, receiver) :
                    false;
        };
    });
    global.Stack = Stack;
}(this));
<commit_msg>corrected documentation<commit_after>/**
 * Stack
 * notation key
 * a                    = function 'a'
 * [a]                  = an instance of Stack with the function 'a'
 * <action> => <result> = a transformation of the Stack/Stack sequence
 * <action> // <result> = a return value
 * <action> || <result> = the effect of the <action>
 * [a,b,c]              = an array of functions 'a', 'b', 'c'
 * [default]            = an instance of Stack with 'defaultFn' function
 * [a[b]]               = an instance of Stack with function 'a' and a next [b]
 * [a[b[c]]]            = an instance of Stack with the head [a] and tail [c]
 * {x}                  = some value x
 * [{x},{y}]            = an array of values {x} and {y}
 * a(x)                 = function 'a' invoked with argument {x}
 * a(x, y)              = function 'a' invoked with arguments {x} and {y}
 * ?                    = an object
 * &&                   = logical and
 */
(function(global, undef) {
    function makeArray(val) {
        return Array.isArray(val) ? val : val ? [val] : [];
    }
    function defaultFn() {
        return arguments.length > 1 ? arguments : arguments[0];
    }
    function recur(fn) {
        return function () {
            var bounce = fn.apply(this, arguments);
            while (typeof bounce === "function") {
                bounce = bounce();
            }
            return bounce;
        };
    }
    /**
     * Stack
     * Stack() => [default] //[default]
     * Stack(a) => [a] //[a]
     * Stack([a,b,c]) => [a[b[c]]] // [a[b[c]]]
     * Stack(a, [b]) => [a[b]] // [a[b]]
     * @param fn {Function|Array}
     * @param [next {Stack}]
     * @returns {Stack}
     * @constructor
     */
    function Stack(fn, next) {
        if (Array.isArray(fn)) {
            return fn.reduce(function (stack, f) {
                return stack.push(f);
            }, new Stack(fn.shift()));
        }
        if (!(this instanceof Stack)) {
            return new Stack(fn, next);
        }
        this.fn = fn || defaultFn;
        this.next = next || undef;
    }
    /**
     * push
     * [a].push(b) => [a[b]].push(c) => [a[b[c]]] // [a[b[c]]]
     * @param fn {Function}
     * @returns {Stack}
     */
    Stack.prototype.push = function(fn) {
        return new Stack(fn, this);
    };
    /**
     * insert
     * [a].insert(c) => [a[c]] // [c]
     * @param fn
     * @returns {Stack}
     */
    Stack.prototype.insert = function (fn) {
        return this.next = new Stack(fn, this.next);
    };
    /**
     * index
     * [a[b[c]]].index(1) // [b]
     * @param idx
     * @returns {Stack|undefined}
     */
    Stack.prototype.index = recur(function index(idx) {
        var self = this;
        return function () {
            return !idx ? self : self.next && index.call(self.next, idx - 1);
        };
    });
    /**
     * priorNext
     * [a[b[c[d]]]].priorNext([d]) // [b]
     * @param [stack]
     * @returns {Stack|undefined}
     */
    Stack.prototype.priorNext = recur(function priorNext(stack) {
        var self = this;
        return function () {
            return self.next && self.next.next === stack ? self : self.next && priorNext.call(self.next, stack);
        };
    });
    /**
     * priorFn
     * [a[b[c]]].priorFn(b) // [a]
     * @param fn
     * @returns {Stack|undefined}
     */
    Stack.prototype.priorFn = recur(function priorFn(fn) {
        var self = this;
        return function () {
            return (self.next && self.next.fn === fn) ? self : self.next && priorFn.call(self.next, fn);
        };
    });
    /**
     * isNext
     * [a[b]].isNext([b]) //true
     * @param stack
     * @returns {boolean}
     */
    Stack.prototype.isNext = function (stack) {
        return stack === this.next;
    };
    /**
     * isFn
     * [a].isFn(a) //true
     * @param fn
     * @returns {boolean}
     */
    Stack.prototype.isFn = function (fn) {
        return fn === this.fn;
    };
    /**
     * searchNext
     * [a[b[c]]].searchNext([c]) //[b]
     * @param [stack]
     * @returns {Stack|undefined}
     */
    Stack.prototype.searchNext = recur(function searchNext(stack) {
        var self = this;
        return function () {
            return self.isNext(stack) && self || self.next && searchNext.call(self.next, stack);
        };
    });
    /**
     * searchFn
     * [a[b[c]]].searchFn(b) //[b]
     * @param fn
     * @returns {Stack|undefined}
     */
    Stack.prototype.searchFn = recur(function searchFn(fn) {
        var self = this;
        return function () {
            return self.isFn(fn) && self || self.next && searchFn.call(self.next, fn);
        };
    });
    /**
     * distribute
     * [a[b[c]]].distribute({x}) || a(x), b(x), c(x)
     * [a[b[c]]].distribute({x}, ?) || ?.a(x), ?.b(x), ?.c(x)
     * @param arg
     * @param receiver
     * @returns {undefined}
     */
    Stack.prototype.distribute = recur(function distribute(arg, receiver) {
        var self = this;
        return function () {
            self.fn.call(receiver || self, arg);
            return self.next && distribute.call(self.next, arg, receiver || self);
        };
    });
    /**
     * distributeAll
     * [a[b[c]]].distribute([{x},{y},{z}]) || a(x,y,z), b(x,y,z), c(x,y,z)
     * [a[b[c]]].distribute([{x},{y},{z}], ?) || ?.a(x,y,z), ?.b(x,y,z), ?.c(x,y,z)
     * @param args
     * @param receiver
     * @returns {undefined}
     */
    Stack.prototype.distributeAll = recur(function distributeAll(args, receiver) {
        var self = this;
        return function () {
            self.fn.apply(receiver|| self, args);
            return self.next && distributeAll.call(self.next, makeArray(args), receiver || self);
        };
    });
    /**
     * call
     * [a[b[c]]].call({x}) // a(b(c(x)))
     * [a[b[c]]].call({x}, ?) // ?.a(?.b(?.c(x)))
     * @param arg
     * @param receiver
     * @returns {*}
     */
    Stack.prototype.call = recur(function call(arg, receiver) {
        var self = this;
        return function () {
            var val = self.fn.call(receiver || self, arg);
            return self.next && call.call(self.next, val, receiver) || val;
        };
    });
    /**
     * apply
     * [a[b[c]]].apply([{x},{y},{z}]) // a(b(c(x,y,z)))
     * [a[b[c]]].apply([{x},{y},{z}], ?) // ?.a(?.b(?.c(x,y,z)))
     * @param args
     * @param receiver
     * @returns {*}
     */
    Stack.prototype.apply = recur(function apply(args, receiver) {
        var self = this;
        return function () {
            var val = self.fn.apply(receiver|| self, args);
            return self.next && apply.call(self.next, makeArray(val), receiver) || val;
        }
    });
    /**
     * clone
     * [a[b[c]]].clone() // [a[b[c]]]
     * [a[b[c]]].clone(d) // [d[b[c]]]
     * [a[b[c]]].clone(null, [d]) // [a[d]]
     * [a[b[c]]].clone(d, [e]) // [d[e]]
     * @param fn
     * @param next
     * @returns {Stack}
     */
    Stack.prototype.clone = function (fn, next) {
        return new Stack(fn || this.fn, next || this.next);
    };
    /**
     * tail
     * [a[b[c]]].tail() // [c]
     * @returns {Stack|undefined}
     */
    Stack.prototype.tail = function () {
        return this.searchNext();
    };
    /**
     * unshift
     * [a[b]].unshift(c) => [a[b[c]]] // [c]
     * @param fn
     * @returns {Stack}
     */
    Stack.prototype.unshift = function (fn) {
        return this.tail().insert(fn);
    };
    /**
     * before
     * [a[b[c]]].before(b, d) => [a[d[b[c]]]] // [d[b[c]]]
     * @param a
     * @param b
     * @returns {Stack}
     */
    Stack.prototype.before = function (a, b) {
        return (this.searchFn(a || undef) || this).insert(b);
    };
    /**
     * shift
     * [a[b[c]]].shift() => [a[b]] // [c]
     * @returns {Stack}
     */
    Stack.prototype.shift = function () {
        var p = this.priorNext();
        var removed = p.next;
        p.next = undef;
        return removed;
    };
    /**
     * [a[b[c]]].pop() => [a], [b[c]] // [a]
     * @returns {Stack}
     */
    Stack.prototype.pop = function () {
        this.next = undef;
        return this;
    };
    /**
     * some
     * [a[b[c]]].some() || !c() && !b() && !c() // true|false
     * [a[b[c]]].some({x}) || !c(x) && !b(x) && !c(x) // true|false
     * @param arg
     * @param receiver
     * @returns {boolean}
     */
    Stack.prototype.some = recur(function some(arg, receiver) {
        var self = this;
        return function () {
            var val = self.fn.call(receiver || self, arg);
            return val !== true && !self.next ? false :
                self.next && val !== true ? some.call(self.next, arg, receiver) :
                    true;
        };
    });
    /**
     * every
     * [a[b[c]]].every() || c() && b() && c() // true|false
     * [a[b[c]]].every({x}) || c(x) && b(x) && c(x) // true|false
     * @param arg
     * @param receiver
     * @returns {boolean}
     */
    Stack.prototype.every = recur(function every(arg, receiver) {
        var self = this;
        return function () {
            var val = self.fn.call(receiver || self, arg);
            return val !== false && !self.next ? true :
                self.next && val !== false ? every.call(self.next, arg, receiver) :
                    false;
        };
    });
    global.Stack = Stack;
}(this));
<|endoftext|>


<commit_before>var wolfram = {
 author: 'pironic',
 name: 'wa',
 description: '- ask the bot a question, via Wolfram|Alpha.',
 onCall: function(request) {
        var http = require('http');
        var config = require('../../config.js');

        if (typeof config.plugins.wolfram.wolfram.url !== 'undefined'
            && config.plugins.wolfram.wolfram.url > 0)
        {
            http.get(config.plugins.wolfram.wolfram.url+encodeURIComponent(request.params), function(res) {
                console.log("Got response: " + res.statusCode);
                res.setEncoding('utf8');

                res.on('data', function (chunk) {
                    request.sendChat(chunk);
                });
            }).on('error', function(e) {
                request.sendChat("Got error: " + e.message);
            });
        }
 }
};

module.exports = {mod: wolfram};
<commit_msg>tiny typo<commit_after>var wolfram = {
 author: 'pironic',
 name: 'wa',
 description: '- ask the bot a question, via Wolfram|Alpha.',
 config: {
     permission: ['isListener']
 },
 onCall: function(request) {
    var http = require('http');
    var config = require('../../config.js');

    if (typeof config.plugins.wolfram.wolfram.url !== 'undefined'
        && config.plugins.wolfram.wolfram.url.length > 0)
    {
        http.get(config.plugins.wolfram.wolfram.url+encodeURIComponent(request.params), function(res) {
            console.log("Got response: " + res.statusCode);
            res.setEncoding('utf8');

            res.on('data', function (chunk) {
                request.sendChat(chunk);
            });
        }).on('error', function(e) {
            request.sendChat("Got error: " + e.message);
        });
    }
 }
};

module.exports = {mod: wolfram};
<|endoftext|>