From d0bb49dea08f5b4f0721076e40d1e9fdf565b02d Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 23 Sep 2014 15:32:42 -0700 Subject: [PATCH] Add type filter system to config --- spec/config-spec.coffee | 28 +++++++++++++++++++++++++++ src/config.coffee | 42 ++++++++++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 45c3f4104..bc9c4600d 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -486,3 +486,31 @@ describe "Config", -> type: 'integer' default: 12 + describe 'when the value has an integer type', -> + beforeEach -> + schema = + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + atom.config.setSchema('foo.bar', schema) + + it 'coerces a string to an int', -> + atom.config.set('foo.bar.anInt', '123') + expect(atom.config.get('foo.bar.anInt')).toBe 123 + + it 'coerces a float to an int', -> + atom.config.set('foo.bar.anInt', 12.3) + expect(atom.config.get('foo.bar.anInt')).toBe 12 + + describe 'when the value has a number type', -> + beforeEach -> + schema = + type: 'number' + default: 12.1 + atom.config.setSchema('foo.bar.anInt', schema) + + it 'coerces a string to a float', -> + atom.config.set('foo.bar.anInt', '12.23') + expect(atom.config.get('foo.bar.anInt')).toBe 12.23 diff --git a/src/config.coffee b/src/config.coffee index 911cffacb..b770883a8 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -27,6 +27,22 @@ pathWatcher = require 'pathwatcher' module.exports = class Config EmitterMixin.includeInto(this) + @typeFilters = {} + + @addTypeFilter: (typeName, filterFunction) -> + @typeFilters[typeName] ?= [] + @typeFilters[typeName].push(filterFunction) + + @addTypeFilters: (filters) -> + for typeName, functions of filters + for name, filterFunction of functions + @addTypeFilter(typeName, filterFunction) + + @executeTypeFilters: (value, schema) -> + if filterFunctions = @typeFilters[schema.type] + for filter in filterFunctions + value = filter.call(this, value, schema) + value # Created during initialization, available as `atom.config` constructor: ({@configDirPath, @resourcePath}={}) -> @@ -124,6 +140,7 @@ class Config # # Returns the `value`. set: (keyPath, value) -> + value = @scrubValue(keyPath, value) if @get(keyPath) isnt value defaultValue = _.valueForKeyPath(@defaultSettings, keyPath) value = undefined if _.isEqual(defaultValue, value) @@ -169,6 +186,7 @@ class Config keys = keyPath.split('.') schema = @schema for key in keys + break unless schema? schema = schema.properties[key] schema @@ -309,6 +327,15 @@ class Config @watchSubscription?.close() @watchSubscription = null + update: -> + return if @configFileHasErrors + @save() + @emit 'updated' + @emitter.emit 'did-change' + + save: -> + CSON.writeFileSync(@configFilePath, @settings) + setDefaults: (keyPath, defaults) -> if typeof defaults isnt 'object' return _.setValueForKeyPath(@defaultSettings, keyPath, defaults) @@ -351,11 +378,12 @@ class Config defaults[key] = @extractDefaultsFromSchema(value) for key, value of properties defaults - update: -> - return if @configFileHasErrors - @save() - @emit 'updated' - @emitter.emit 'did-change' + scrubValue: (keyPath, value) -> + value = @constructor.executeTypeFilters(value, schema) if schema = @getSchema(keyPath) + value - save: -> - CSON.writeFileSync(@configFilePath, @settings) +Config.addTypeFilters + 'integer': + coercion: (value, schema) -> parseInt(value) + 'number': + coercion: (value, schema) -> parseFloat(value)