mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2025-12-11 07:22:19 +01:00
Support for flipped bits
Signed-off-by: BorysLevytskyi <blevitsky@yandex.ru>
This commit is contained in:
committed by
BorysLevytskyi
parent
252e940328
commit
263f34c06d
@@ -20,6 +20,8 @@ code { font-size: 1.2em; font-weight: bold; }
|
||||
|
||||
.expression .label { font-weight: bold; padding-right: 5px; text-align: right; }
|
||||
.expression .bin { letter-spacing: 3px; }
|
||||
.expression .flipable { cursor: pointer; opacity: 1 }
|
||||
.expression .flipable:hover { opacity: 0.8 }
|
||||
.expression .byte { margin: 0 3px; }
|
||||
.expression-result td { border-top: dotted 1px gray; }
|
||||
.expression { font-size: 1.5em; font-family: monospace }
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
<script data-template="numbersList" data-compiled="" type="text/template">
|
||||
<table class="expression">
|
||||
{each op in m.operands}
|
||||
<tr>
|
||||
<tr data-kind="{op.kind}">
|
||||
<td class="label">{op.input}</td>
|
||||
<td class="bin">{op.bin.padLeft(m.bitsSize, '0')}</td>
|
||||
<td class="other">{op.other}</td>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
this.initialize();
|
||||
};
|
||||
|
||||
|
||||
window.app = app;
|
||||
|
||||
})(window.core);
|
||||
@@ -5,44 +5,6 @@ app.set('expression', function() {
|
||||
var listRegex = /^(-?(?:\d+|0x[\d,a-f]+)\s?)+$/;
|
||||
var notRex = /^(~)(-?(?:\d+|0x[\d,a-f]+))$/;
|
||||
|
||||
return {
|
||||
canParse: function(string) {
|
||||
return exprRegex.test(string) || listRegex.test(string) || notRex.test(string)
|
||||
},
|
||||
parse: function(string) {
|
||||
var trimmed = string.replace(/^\s+|\s+$/, '');
|
||||
|
||||
var matches = exprRegex.exec(trimmed);
|
||||
|
||||
if(matches != null) {
|
||||
return createTwoOperandExpr(matches);
|
||||
}
|
||||
|
||||
matches = notRex.exec(trimmed);
|
||||
if(matches != null) {
|
||||
return createSingleOperandExpr(matches);
|
||||
}
|
||||
|
||||
matches = listRegex.exec(string);
|
||||
if(matches != null) {
|
||||
return createListOfNumbersExpression(string)
|
||||
}
|
||||
|
||||
},
|
||||
parseOperand: function(input) {
|
||||
return new Operand(input);
|
||||
},
|
||||
createOperand: function(number, kind) {
|
||||
var str = number.toString(getBase(kind));
|
||||
if(kind == 'hex') {
|
||||
str = toHex(str);
|
||||
}
|
||||
|
||||
return new Operand(str);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function createTwoOperandExpr(matches) {
|
||||
|
||||
var m = new app.models.BitwiseOperation();
|
||||
@@ -87,6 +49,20 @@ app.set('expression', function() {
|
||||
return hex.indexOf('-') == 0 ? '-0x' + hex.substr(1) : '0x' + hex;
|
||||
}
|
||||
|
||||
function toKindString(value, kind) {
|
||||
switch(kind) {
|
||||
case 'hex':
|
||||
var hexVal = Math.abs(value).toString(16);
|
||||
return value >= 0 ? '0x' + hexVal : '-0x' + hexVal;
|
||||
case 'bin':
|
||||
return (value>>>0).toString(2);
|
||||
case 'dec':
|
||||
return value.toString(10);
|
||||
default:
|
||||
throw new Error("Unexpected kind: " + kind)
|
||||
}
|
||||
}
|
||||
|
||||
function Operand(input) {
|
||||
this.input = input;
|
||||
this.value = parseInt(input);
|
||||
@@ -97,4 +73,50 @@ app.set('expression', function() {
|
||||
this.kind = this.input.indexOf('0x') > -1 ? 'hex' : 'dec';
|
||||
this.other = this.kind == 'dec' ? this.hex : this.dec;
|
||||
}
|
||||
|
||||
return {
|
||||
canParse: function(string) {
|
||||
return exprRegex.test(string) || listRegex.test(string) || notRex.test(string)
|
||||
},
|
||||
parse: function(string) {
|
||||
var trimmed = string.replace(/^\s+|\s+$/, '');
|
||||
|
||||
var matches = exprRegex.exec(trimmed);
|
||||
|
||||
if(matches != null) {
|
||||
return createTwoOperandExpr(matches);
|
||||
}
|
||||
|
||||
matches = notRex.exec(trimmed);
|
||||
if(matches != null) {
|
||||
return createSingleOperandExpr(matches);
|
||||
}
|
||||
|
||||
matches = listRegex.exec(string);
|
||||
if(matches != null) {
|
||||
return createListOfNumbersExpression(string)
|
||||
}
|
||||
|
||||
},
|
||||
parseOperand: function(input) {
|
||||
return new Operand(input);
|
||||
},
|
||||
createOperand: function(number, kind) {
|
||||
var str = number.toString(getBase(kind));
|
||||
if(kind == 'hex') {
|
||||
str = toHex(str);
|
||||
}
|
||||
|
||||
return new Operand(str);
|
||||
},
|
||||
getOtherKind: function(kind) {
|
||||
switch(kind) {
|
||||
case 'dec': return 'hex';
|
||||
case 'hex': return 'dec';
|
||||
default : throw new Error(kind + " kind doesn't have opposite kind")
|
||||
}
|
||||
},
|
||||
toKindString: toKindString
|
||||
};
|
||||
|
||||
});
|
||||
@@ -11,10 +11,10 @@ app.compose(function () {
|
||||
var expression = app.get('expression');
|
||||
|
||||
// TODO: move to protojs
|
||||
String.prototype.padLeft = function(size, char) { return formatter.padLeft(this, size, char); }
|
||||
String.prototype.padLeft = function(size, char) { return formatter.padLeft(this, size, char); };
|
||||
|
||||
|
||||
app.modelView(app.models.BitwiseOperation, function() {
|
||||
app.modelView(app.models.BitwiseOperation, function() {
|
||||
function getTemplateId(model) {
|
||||
switch (model.sign) {
|
||||
case '<<':
|
||||
@@ -49,7 +49,16 @@ app.compose(function () {
|
||||
app.modelView(app.models.BitwiseNumbers, {
|
||||
renderView: function(model) {
|
||||
model.bitsSize = getBinaryLength(model.numbers);
|
||||
return colorizeBits(app.template('numbersList').render(model));
|
||||
var templateElement = colorizeBits(app.template('numbersList').render(model));
|
||||
var list = templateElement.querySelectorAll('.bit');
|
||||
|
||||
Array.prototype.forEach.call(list, function(el) {
|
||||
el.classList.add('flipable');
|
||||
el.setAttribute('title', 'Click to flip this bit');
|
||||
el.addEventListener('click', flipBits);
|
||||
});
|
||||
|
||||
return templateElement;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -98,8 +107,8 @@ app.compose(function () {
|
||||
}
|
||||
|
||||
el.innerHTML = bin
|
||||
.replace(/0/g, '<span class="zero">0</span>')
|
||||
.replace(/1/g, '<span class="one">1</span>');
|
||||
.replace(/0/g, '<span class="bit zero">0</span>')
|
||||
.replace(/1/g, '<span class="bit one">1</span>');
|
||||
});
|
||||
return container;
|
||||
}
|
||||
@@ -113,5 +122,34 @@ app.compose(function () {
|
||||
|
||||
return 'dec';
|
||||
}
|
||||
|
||||
function flipBits(evt) {
|
||||
var el = evt.target;
|
||||
var content = el.textContent;
|
||||
if(content == '0') {
|
||||
el.innerHTML = '1';
|
||||
el.classList.remove('zero');
|
||||
el.classList.add('one');
|
||||
} else {
|
||||
el.innerHTML = '0';
|
||||
el.classList.add('zero');
|
||||
el.classList.remove('one');
|
||||
}
|
||||
|
||||
var row = findParent(el, 'TR');
|
||||
var value = parseInt(row.cells[1].textContent, 2);
|
||||
var kind = row.dataset.kind;
|
||||
|
||||
row.cells[0].innerHTML = expression.toKindString(value, kind);
|
||||
row.cells[2].innerHTML = expression.toKindString(value, expression.getOtherKind(kind));
|
||||
}
|
||||
|
||||
function findParent(el, tageName) {
|
||||
var parent = el.parentNode;
|
||||
while(parent.tagName != tageName) {
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -161,12 +161,37 @@ describe('launch of application', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('interaction with results', function() {
|
||||
it('should flip bits', function () {
|
||||
|
||||
// Given: 0x2a 00101010 42
|
||||
// Expected: 0x6a 01101010 106
|
||||
|
||||
goToApp()
|
||||
.then(function() { return sendCommand('clear')})
|
||||
.then(function() { return sendCommand('0x2a')})
|
||||
.then(function() { assertExpressionResult(driver, [{ label: "0x2a", bin: '00101010', other: '42' }]); })
|
||||
.then(function() { return flipBit(2); })
|
||||
.then(function() { return assertExpressionResult(driver, [{ label: "0x6a", bin: '01101010', other: '106' }]); })
|
||||
.then(function() { return flipBit(6); })
|
||||
.then(function() { return assertExpressionResult(driver, [{ label: "0x6e", bin: '01101110', other: '110' }]); });
|
||||
})
|
||||
});
|
||||
|
||||
function sendCommand(cmd) {
|
||||
return driver.findElement(By.id('in')).then(function (el) {
|
||||
return el.sendKeys(cmd + Key.ENTER);
|
||||
});
|
||||
}
|
||||
|
||||
function flipBit(bitNumber) {
|
||||
return driver.findElements(By.css('.flipable'))
|
||||
.then(function(rows) {
|
||||
var bitElemet = rows[bitNumber-1]; // Flip 2nd bit;
|
||||
return bitElemet.click();
|
||||
});
|
||||
}
|
||||
|
||||
function assertNoErrors() {
|
||||
return driver.findElements(By.css('.result .error')).then(function(els) {
|
||||
expect(els.length).toBe(0, "There should be no errors");
|
||||
|
||||
@@ -90,6 +90,20 @@ describe('negative operands', function () {
|
||||
})
|
||||
});
|
||||
|
||||
describe('should format to kind strings', function() {
|
||||
var dec = expression.toKindString(15, 'dec'),
|
||||
hexNegative = expression.toKindString(-2, 'hex'),
|
||||
hex = expression.toKindString(11, 'hex'),
|
||||
bin = expression.toKindString(10, 'bin');
|
||||
|
||||
it('should be correctly formatted', function() {
|
||||
expect(dec).toBe('15');
|
||||
expect(hexNegative).toBe('-0x2');
|
||||
expect(hex).toBe('0xb');
|
||||
expect(bin).toBe('1010')
|
||||
});
|
||||
});
|
||||
|
||||
function rundOperandsTest(hexOperand, decOperand) {
|
||||
it('should remember input form', function() {
|
||||
expect(hexOperand.input).toBe('0x10');
|
||||
|
||||
Reference in New Issue
Block a user