Skip to content

Commit

Permalink
support step arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Melyukov committed Aug 5, 2019
1 parent 02dfce5 commit ed49ae6
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 14 deletions.
33 changes: 29 additions & 4 deletions src/buildin.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,37 @@ module.exports = Object.freeze({

return value !== undefined ? fn(value) : value;
},
slice: function(value, from, to) {
if (Array.isArray(value) || typeof value === 'string') {
return value.slice(from, to);
slice: function(value, from, to, step) {
if (!Array.isArray(value) && typeof value !== 'string') {
return value;
}

return value;
if (step && step !== 1) {
const result = [];
const reverse = step < 0;

step *= Math.sign(step);

if (from < 0) {
from = value.length + from;
}

if (to < 0) {
to = value.length + to;
}

for (let i = from; i < to; i += step) {
result.push(value[i]);
}

if (reverse) {
result.reverse();
}

return result;
}

return value.slice(from, to);
},
recursive: function(value, getter) {
const result = new Set();
Expand Down
26 changes: 18 additions & 8 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,15 @@ const grammar = {
['.. SYMBOL', code`fn.recursive(/*@2*/current, "$2")`],
['..( block )', code`fn.recursive(current, current => { $2 })`],
['.[ block ]', code`fn.filter(current, current => { $2 })`],
['[ e : e ]', code`fn.slice(current, $2, $4)`],
['[ : e ]', code`fn.slice(current, 0, $3)`],
['[ e : ]', code`fn.slice(current, $2, current.legnth)`],
['[ : ]', code`fn.slice(current, 0, current.legnth)`]
['[ e : e ]', code`fn.slice(current, $2, $4, 1)`],
['[ e : e : e ]', code`fn.slice(current, $2, $4, $6)`],
['[ : e ]', code`fn.slice(current, 0, $3, 1)`],
['[ : e : e ]', code`fn.slice(current, 0, $3, $5)`],
['[ e : ]', code`fn.slice(current, $2, current.length, 1)`],
['[ e : : e ]', code`fn.slice(current, $2, current.length, $5)`],
['[ : ]', code`fn.slice(current, 0, current.length, 1)`],
['[ : : e ]', code`fn.slice(current, 0, current.length, $4)`],
['[ : : ]', code`fn.slice(current, 0, current.length, 1)`]
],

relativePath: [
Expand All @@ -271,10 +276,15 @@ const grammar = {
['query ..( block )', code`fn.recursive($1, current => { $3 })`],
['query .[ block ]', code`fn.filter($1, current => { $3 })`],
['query [ e ]', code`fn.map($1, $3)`],
['query [ e : e ]', code`fn.slice($1, $3, $5)`],
['query [ : e ]', code`fn.slice($1, 0, $4)`],
['query [ e : ]', code`fn.slice($1, $3, $1.length)`],
['query [ : ]', code`fn.slice($1, 0, $1.length)`]
['query [ e : e ]', code`fn.slice($1, $3, $5, 1)`],
['query [ e : e : e ]', code`fn.slice($1, $3, $5, $7)`],
['query [ : e ]', code`fn.slice($1, 0, $4, 1)`],
['query [ : e : e ]', code`fn.slice($1, 0, $4, $6)`],
['query [ e : ]', code`fn.slice($1, $3, $1.length, 1)`],
['query [ e : : e ]', code`fn.slice($1, $2, $1.length, $6)`],
['query [ : ]', code`fn.slice($1, 0, $1.length, 1)`],
['query [ : : e ]', code`fn.slice($1, 0, $1.length, $5)`],
['query [ : : ]', code`fn.slice($1, 0, $1.length, 1)`]
],

arguments: [
Expand Down
127 changes: 125 additions & 2 deletions test/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ const data = require('./fixture/simple');
const query = require('../src');

// https://github.com/tc39/proposal-slice-notation/blob/master/README.md
// without a `step` argument

describe('size | [N:N]', () => {
describe('slice | [from:to]', () => {
it('should be a data root', () => {
assert.deepEqual(
query('[0:3]')(data),
Expand Down Expand Up @@ -63,3 +62,127 @@ describe('size | [N:N]', () => {
);
});
});

describe('[from:to:step]', () => {
it('should be a data root', () => {
const fixture = data.slice(0, 3);

assert.deepEqual(
query('[0:3:2]')(data),
[fixture[0], fixture[2]]
);
});

it('should be a subquery', () => {
const fixture = data.slice(0, 3).map(i => i.filename);

assert.deepEqual(
query('filename[0:3:2]')(data),
[fixture[0], fixture[2]]
);
});

it('nagative from/to from root', () => {
const fixture = data.slice(-4, -1);

assert.deepEqual(
query('[-4:-1:2]')(data),
[fixture[0], fixture[2]]
);
});

it('nagative from/to from subquery', () => {
const fixture = data.slice(-4, -1).map(i => i.filename);

assert.deepEqual(
query('filename[-4:-1:2]')(data),
[fixture[0], fixture[2]]
);
});

it('reverse from root', () => {
const fixture = data.slice(0, 3);

assert.deepEqual(
query('[0:3:-1]')(data),
[fixture[2], fixture[1], fixture[0]]
);
});

it('reverse from subquery', () => {
const fixture = data.slice(0, 3).map(i => i.filename);

assert.deepEqual(
query('filename[0:3:-1]')(data),
[fixture[2], fixture[1], fixture[0]]
);
});

it('reverse with nagative from/to from root', () => {
const fixture = data.slice(-4, -1);

assert.deepEqual(
query('[-4:-1:-2]')(data),
[fixture[2], fixture[0]]
);
});

it('reverse with nagative from/to from subquery', () => {
const fixture = data.slice(-4, -1).map(i => i.filename);

assert.deepEqual(
query('filename[-4:-1:-2]')(data),
[fixture[2], fixture[0]]
);
});

it('negative from root', () => {
const fixture = data.slice(0, 3);

assert.deepEqual(
query('[0:3:-2]')(data),
[fixture[2], fixture[0]]
);
});

it('negative from subquery', () => {
const fixture = data.slice(0, 3).map(i => i.filename);

assert.deepEqual(
query('filename[0:3:-2]')(data),
[fixture[2], fixture[0]]
);
});

it('pass from/to args from root', () => {
const fixture = data.slice();

assert.deepEqual(
query('[::-2]')(data),
[fixture[6], fixture[4], fixture[2], fixture[0]]
);
});

it('pass from/to args from query', () => {
const fixture = data.map(i => i.filename);

assert.deepEqual(
query('filename[::-2]')(data),
[fixture[6], fixture[4], fixture[2], fixture[0]]
);
});

it('pass all args from root', () => {
assert.deepEqual(
query('[::]')(data),
data.slice()
);
});

it('pass all args from query', () => {
assert.deepEqual(
query('filename[::]')(data),
data.map(i => i.filename)
);
});
});

0 comments on commit ed49ae6

Please sign in to comment.