<commit_before>fs = require 'fs'
_ = require 'underscore'
EventEmitter = require 'event-emitter'

configDirPath = fs.absolute("~/.atom")
configJsonPath = fs.join(configDirPath, "config.json")
userInitScriptPath = fs.join(configDirPath, "atom.coffee")
bundledPackagesDirPath = fs.join(resourcePath, "src/packages")
userPackagesDirPath = fs.join(configDirPath, "packages")

require.paths.unshift userPackagesDirPath

module.exports =
class Config
  configDirPath: configDirPath
  packageDirPaths: [userPackagesDirPath, bundledPackagesDirPath]
  settings: null

  constructor: ->
    @settings = {}
    @setDefaults "core", require('root-view').configDefaults
    @setDefaults "editor", require('editor').configDefaults

  load: ->
    @loadUserConfig()
    @requireUserInitScript()
    atom.loadPackages()

  loadUserConfig: ->
    if fs.exists(configJsonPath)
      userConfig = JSON.parse(fs.read(configJsonPath))
      _.extend(@settings, userConfig)

  get: (keyPath) ->
    keys = @keysForKeyPath(keyPath)
    value = @settings
    for key in keys
      break unless value = value[key]
    value

  set: (keyPath, value) ->
    keys = @keysForKeyPath(keyPath)
    hash = @settings
    while keys.length > 1
      key = keys.shift()
      hash[key] ?= {}
      hash = hash[key]
    hash[keys.shift()] = value

    @update()
    value

  setDefaults: (keyPath, defaults) ->
    keys = @keysForKeyPath(keyPath)
    hash = @settings
    for key in keys
      hash[key] ?= {}
      hash = hash[key]

    _.defaults hash, defaults
    @update()

  keysForKeyPath: (keyPath) ->
    if typeof keyPath is 'string'
      keyPath.split(".")
    else
      new Array(keyPath...)

  observe: (keyPath, callback) ->
    value = @get(keyPath)
    previousValue = _.clone(value)
    updateCallback = =>
      value = @get(keyPath)
      unless _.isEqual(value, previousValue)
        previousValue = _.clone(value)
        callback(value)

    subscription = { cancel: => @off 'update', updateCallback  }
    @on 'update', updateCallback
    callback(value)
    subscription

  update: ->
    @save()
    @trigger 'update'

  save: ->
    fs.write(configJsonPath, JSON.stringify(@settings, undefined, 2) + "\n")

  requireUserInitScript: ->
    try
      require userInitScriptPath if fs.exists(userInitScriptPath)
    catch error
      console.error "Failed to load `#{userInitScriptPath}`", error.stack, error

_.extend Config.prototype, EventEmitter
<commit_msg>Oops. Don't overwrite user config w/ defaults before its loaded<commit_after>fs = require 'fs'
_ = require 'underscore'
EventEmitter = require 'event-emitter'

configDirPath = fs.absolute("~/.atom")
configJsonPath = fs.join(configDirPath, "config.json")
userInitScriptPath = fs.join(configDirPath, "atom.coffee")
bundledPackagesDirPath = fs.join(resourcePath, "src/packages")
userPackagesDirPath = fs.join(configDirPath, "packages")

require.paths.unshift userPackagesDirPath

module.exports =
class Config
  configDirPath: configDirPath
  packageDirPaths: [userPackagesDirPath, bundledPackagesDirPath]
  settings: null

  constructor: ->
    @settings =
      core: require('root-view').configDefaults
      editor: require('editor').configDefaults

  load: ->
    @loadUserConfig()
    @requireUserInitScript()
    atom.loadPackages()

  loadUserConfig: ->
    if fs.exists(configJsonPath)
      userConfig = JSON.parse(fs.read(configJsonPath))
      _.extend(@settings, userConfig)

  get: (keyPath) ->
    keys = @keysForKeyPath(keyPath)
    value = @settings
    for key in keys
      break unless value = value[key]
    value

  set: (keyPath, value) ->
    keys = @keysForKeyPath(keyPath)
    hash = @settings
    while keys.length > 1
      key = keys.shift()
      hash[key] ?= {}
      hash = hash[key]
    hash[keys.shift()] = value

    @update()
    value

  setDefaults: (keyPath, defaults) ->
    keys = @keysForKeyPath(keyPath)
    hash = @settings
    for key in keys
      hash[key] ?= {}
      hash = hash[key]

    _.defaults hash, defaults
    @update()

  keysForKeyPath: (keyPath) ->
    if typeof keyPath is 'string'
      keyPath.split(".")
    else
      new Array(keyPath...)

  observe: (keyPath, callback) ->
    value = @get(keyPath)
    previousValue = _.clone(value)
    updateCallback = =>
      value = @get(keyPath)
      unless _.isEqual(value, previousValue)
        previousValue = _.clone(value)
        callback(value)

    subscription = { cancel: => @off 'update', updateCallback  }
    @on 'update', updateCallback
    callback(value)
    subscription

  update: ->
    @save()
    @trigger 'update'

  save: ->
    fs.write(configJsonPath, JSON.stringify(@settings, undefined, 2) + "\n")

  requireUserInitScript: ->
    try
      require userInitScriptPath if fs.exists(userInitScriptPath)
    catch error
      console.error "Failed to load `#{userInitScriptPath}`", error.stack, error

_.extend Config.prototype, EventEmitter

{'fraction_non_alphanumeric': 0.12324873096446701, 'fraction_numerical': 0.0008121827411167512, 'mean_word_length': 3.309711286089239, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6848753', 'n_tokens_mistral': 1549, 'n_tokens_neox': 1514, 'n_words': 347}