Permalink
Browse files

Add an allowFloat option to the number type

This commit adds an allowFloat option when creating a number.  It
defaults to false, which means that only integer values are accepted for
that number.  If allowFloat is false, float values are still accepted
for min, max, and step, but they are rounded to ints in the constructor.

Signed-off-by: Adam Goforth <code@adamgoforth.com>
  • Loading branch information...
1 parent 0ae077a commit 73eaebc7e713804822404254f1dcc17274daea3e @aag aag committed Feb 16, 2013
@@ -97,7 +97,7 @@ var gcliTwonums = {
{
name: 'p2',
defaultValue: 8,
- type: { name: 'number', min: -20, max: 42, step: 5 },
+ type: { name: 'number', allowFloat: true, min: -20, max: 42, step: 5 },
description: 'Second param'
},
{
View
@@ -80,6 +80,10 @@ var i18n = {
// When the command line is passed a number, but the number is lower than
// the smallest allowed number, this error message is displayed.
typesNumberMin: '%1$S is smaller than minimum allowed: %2$S.',
+
+ // When the command line is passed a number, but the number has a decimal
+ // part and floats are not allowed.
+ typesNumberNotInt: '\'%S\' must be an integer.',
// When the command line is passed an option with a limited number of
// correct values, but the passed value is not one of them, this error
View
@@ -86,9 +86,22 @@ function NumberType(typeSpec) {
this._min = typeSpec.min;
this._max = typeSpec.max;
this._step = typeSpec.step || 1;
+ this._allowFloat = typeSpec.allowFloat || false;
+
+ if (!this._allowFloat) {
+ if (typeof this._min === 'number') {
+ this._min = Math.ceil(this._min);
+ }
+ if (typeof this._max === 'number') {
+ this._max = Math.floor(this._max);
+ }
+ this._step = Math.round(this._step);
+ this.name = 'integer';
+ }
}
else {
this._step = 1;
+ this._allowFloat = false;
}
}
@@ -130,7 +143,19 @@ NumberType.prototype.parse = function(arg) {
return new Conversion(undefined, arg, Status.INCOMPLETE, '');
}
- var value = parseInt(arg.text, 10);
+ if (!this._allowFloat && (arg.text.indexOf('.') !== -1)) {
+ return new Conversion(undefined, arg, Status.ERROR,
+ l10n.lookupFormat('typesNumberNotInt', [ arg.text ]));
+ }
+
+ var value;
+ if (this._allowFloat) {
+ value = parseFloat(arg.text);
+ }
+ else {
+ value = parseInt(arg.text, 10);
+ }
+
if (isNaN(value)) {
return new Conversion(undefined, arg, Status.ERROR,
l10n.lookupFormat('typesNumberNan', [ arg.text ]));
@@ -45,6 +45,8 @@ mockCommands.setup = function() {
canon.addCommand(mockCommands.tsb);
canon.addCommand(mockCommands.tss);
canon.addCommand(mockCommands.tsu);
+ canon.addCommand(mockCommands.tsf);
+ canon.addCommand(mockCommands.tsif);
canon.addCommand(mockCommands.tsn);
canon.addCommand(mockCommands.tsnDif);
canon.addCommand(mockCommands.tsnExt);
@@ -72,6 +74,8 @@ mockCommands.shutdown = function() {
canon.removeCommand(mockCommands.tsb);
canon.removeCommand(mockCommands.tss);
canon.removeCommand(mockCommands.tsu);
+ canon.removeCommand(mockCommands.tsf);
+ canon.removeCommand(mockCommands.tsif);
canon.removeCommand(mockCommands.tsn);
canon.removeCommand(mockCommands.tsnDif);
canon.removeCommand(mockCommands.tsnExt);
@@ -204,6 +208,18 @@ mockCommands.tsu = {
exec: createExec('tsu')
};
+mockCommands.tsf = {
+ name: 'tsf',
+ params: [ { name: 'num', type: { name: 'number', allowFloat: true, max: 11.5, min: -6.5, step: 1.5 } } ],
+ exec: createExec('tsf')
+};
+
+mockCommands.tsif = {
+ name: 'tsif',
+ params: [ { name: 'num', type: { name: 'number', allowFloat: false, max: 7.5, min: -7.5, step: 1.3 } } ],
+ exec: createExec('tsif')
+};
+
mockCommands.tsn = {
name: 'tsn'
};
View
@@ -300,6 +300,52 @@ exports.testSingleNumber = function() {
assert.is('tsu', requ.commandAssignment.value.name);
assert.is('x', assign1.arg.text);
assert.is(undefined, assign1.value);
+
+ update({ typed: 'tsu 1.5', cursor: { start: 7, end: 7 } });
+ assert.is( 'VVVVEEE', statuses);
+ assert.is(Status.ERROR, status);
+ assert.is('tsu', requ.commandAssignment.value.name);
+ assert.is('1.5', assign1.arg.text);
+ assert.is(undefined, assign1.value);
+};
+
+exports.testSingleFloat = function() {
+ update({ typed: 'tsf', cursor: { start: 3, end: 3 } });
+ assert.is( 'VVV', statuses);
+ assert.is(Status.ERROR, status);
+ assert.is('tsf', requ.commandAssignment.value.name);
+ assert.is('', assign1.arg.text);
+ assert.is(undefined, assign1.value);
+
+ update({ typed: 'tsf ', cursor: { start: 4, end: 4 } });
+ assert.is( 'VVVV', statuses);
+ assert.is(Status.ERROR, status);
+ assert.is('tsf', requ.commandAssignment.value.name);
+ assert.is('', assign1.arg.text);
+ assert.is(undefined, assign1.value);
+
+ update({ typed: 'tsf 1', cursor: { start: 5, end: 5 } });
+ assert.is( 'VVVVV', statuses);
+ assert.is(Status.VALID, status);
+ assert.is('tsf', requ.commandAssignment.value.name);
+ assert.is('1', assign1.arg.text);
+ assert.is(1, assign1.value);
+ assert.is('number', typeof assign1.value);
+
+ update({ typed: 'tsf x', cursor: { start: 5, end: 5 } });
+ assert.is( 'VVVVE', statuses);
+ assert.is(Status.ERROR, status);
+ assert.is('tsf', requ.commandAssignment.value.name);
+ assert.is('x', assign1.arg.text);
+ assert.is(undefined, assign1.value);
+
+ update({ typed: 'tsf 1.5', cursor: { start: 7, end: 7 } });
+ assert.is( 'VVVVVVV', statuses);
+ assert.is(Status.VALID, status);
+ assert.is('tsf', requ.commandAssignment.value.name);
+ assert.is('1.5', assign1.arg.text);
+ assert.is(1.5, assign1.value);
+ assert.is('number', typeof assign1.value);
};
exports.testElement = function(options) {
@@ -266,7 +266,7 @@ exports.testLong = function(options) {
helpers.setInput('tslong --num ');
helpers.check({
input: 'tslong --num ',
- hints: '<number> <msg> [options]',
+ hints: '<integer> <msg> [options]',
markup: 'VVVVVVVIIIIIV'
});
@@ -179,6 +179,58 @@ exports.testIncrDecr = function() {
check('tsu 10', KEY_DOWNS_TO, 'tsu 9');
check('tsu 100', KEY_DOWNS_TO, 'tsu 10');
+ check('tsf -70', KEY_UPS_TO, 'tsf -6.5');
+ check('tsf -6.5', KEY_UPS_TO, 'tsf -6');
+ check('tsf -6', KEY_UPS_TO, 'tsf -4.5');
+ check('tsf -4.5', KEY_UPS_TO, 'tsf -3');
+ check('tsf -4', KEY_UPS_TO, 'tsf -3');
+ check('tsf -3', KEY_UPS_TO, 'tsf -1.5');
+ check('tsf -1.5', KEY_UPS_TO, 'tsf 0');
+ check('tsf 0', KEY_UPS_TO, 'tsf 1.5');
+ check('tsf 1.5', KEY_UPS_TO, 'tsf 3');
+ check('tsf 2', KEY_UPS_TO, 'tsf 3');
+ check('tsf 3', KEY_UPS_TO, 'tsf 4.5');
+ check('tsf 5', KEY_UPS_TO, 'tsf 6');
+ check('tsf 100', KEY_UPS_TO, 'tsf -6.5');
+
+ check('tsf -70', KEY_DOWNS_TO, 'tsf 11.5');
+ check('tsf -6.5', KEY_DOWNS_TO, 'tsf -6.5');
+ check('tsf -6', KEY_DOWNS_TO, 'tsf -6.5');
+ check('tsf -4.5', KEY_DOWNS_TO, 'tsf -6');
+ check('tsf -4', KEY_DOWNS_TO, 'tsf -4.5');
+ check('tsf -3', KEY_DOWNS_TO, 'tsf -4.5');
+ check('tsf -1.5', KEY_DOWNS_TO, 'tsf -3');
+ check('tsf 0', KEY_DOWNS_TO, 'tsf -1.5');
+ check('tsf 1.5', KEY_DOWNS_TO, 'tsf 0');
+ check('tsf 2', KEY_DOWNS_TO, 'tsf 1.5');
+ check('tsf 3', KEY_DOWNS_TO, 'tsf 1.5');
+ check('tsf 5', KEY_DOWNS_TO, 'tsf 4.5');
+ check('tsf 100', KEY_DOWNS_TO, 'tsf 11.5');
+
+ check('tsif -70', KEY_UPS_TO, 'tsif -7');
+ check('tsif -6', KEY_UPS_TO, 'tsif -5');
+ check('tsif -4', KEY_UPS_TO, 'tsif -3');
+ check('tsif -3', KEY_UPS_TO, 'tsif -2');
+ check('tsif 0', KEY_UPS_TO, 'tsif 1');
+ check('tsif 2', KEY_UPS_TO, 'tsif 3');
+ check('tsif 3', KEY_UPS_TO, 'tsif 4');
+ check('tsif 5', KEY_UPS_TO, 'tsif 6');
+ check('tsif 100', KEY_UPS_TO, 'tsif -7');
+
+ check('tsif -70', KEY_DOWNS_TO, 'tsif 7');
+ check('tsif -7', KEY_DOWNS_TO, 'tsif -7');
+ check('tsif -6', KEY_DOWNS_TO, 'tsif -7');
+ check('tsif -4', KEY_DOWNS_TO, 'tsif -5');
+ check('tsif -3', KEY_DOWNS_TO, 'tsif -4');
+ check('tsif 0', KEY_DOWNS_TO, 'tsif -1');
+ check('tsif 2', KEY_DOWNS_TO, 'tsif 1');
+ check('tsif 3', KEY_DOWNS_TO, 'tsif 2');
+ check('tsif 5', KEY_DOWNS_TO, 'tsif 4');
+ check('tsif 6', KEY_DOWNS_TO, 'tsif 5');
+ check('tsif 7', KEY_DOWNS_TO, 'tsif 6');
+ check('tsif 100', KEY_DOWNS_TO, 'tsif 7');
+
+
// Bug 707007 - GCLI increment and decrement operations cycle through
// selection options in the wrong order
check('tselarr 1', KEY_DOWNS_TO, 'tselarr 2');

0 comments on commit 73eaebc

Please sign in to comment.