Skip to content

Commit

Permalink
from-to rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
75lb committed Nov 3, 2024
1 parent f10f0a5 commit 18681b2
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 86 deletions.
13 changes: 7 additions & 6 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
# See: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
push:
branches: [ master ]
branches: [ master, next ]
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}

strategy:
matrix:
node-version: [12, 14, 16, 18, 20, 22]
os: [ubuntu-latest]
node-version: [12, 14, 16, 18, 20, 22, 23]

steps:
- uses: actions/checkout@v4
Expand All @@ -25,5 +26,5 @@ jobs:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm install
- name: Run tests
run: npm run test:ci
- run: npm i @75lb/nature
- run: npm run test:ci
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014-24 Lloyd Brookes <75pound@gmail.com>
Copyright (c) 2014-24 Lloyd Brookes <opensource@75lb.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
119 changes: 85 additions & 34 deletions dist/index.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

var arrayBack = require('array-back');

/**
* Similar to find-replace with two exceptions:
* - fromTo finds multiple items, find-replace finds single items
Expand All @@ -9,56 +11,105 @@
* - Find one or more items and return (all return values are arrays)
* - Find one or more items, return them, remove them from the input array
*
* arr {string[]} - Input array. Only mutated if `options.remove` is set.
* [options.rtol] {boolean} - Enable right-to-left scans. Either that or pass in a custom iterator.
* [options.remove] {boolean} - Remove from source array
* [options.from] {boolean}
* [options.to] {boolean}
* [options.inclusive] {boolean} - If `true` includes the to item.
* [options.from] {function}
* [options.to] {function}
* [options.noFurtherThan] {function}
* @returns string[]
*/
function fromTo (arr, options = {}) {
const { from: fromFn, to: toFn, noFurtherThan, remove } = options;
const fromIndex = arr.findIndex(fromFn);
let { from: fromFn, to: toFn, noFurtherThan, remove, inclusive, toEnd } = options;
if (inclusive === undefined && !noFurtherThan && toFn) {
inclusive = true;
}
toFn = toFn || noFurtherThan;
fromFn = arrayBack(fromFn).map(fn => {
if (typeof fn === 'string') {
return function (val) { return val === fn }
} else {
return fn
}
});
toFn = arrayBack(toFn).map(fn => {
if (typeof fn === 'string') {
return function (item, index, arr, valueIndex) { return item === fn }
} else {
return fn
}
});

let fromIndex;
for (const fn of fromFn) {
fromIndex = arr.findIndex(fn);
if (fromIndex > -1) {
break
}
}

let toIndex;
if (toFn) {
toIndex = arr.findIndex((item, index, arr) => {
if (index > fromIndex) {
const valueIndex = index - fromIndex;
return toFn(valueIndex, item, index, arr)
} else {
return false
}
});
} else if (noFurtherThan) {
toIndex = arr.findIndex((item, index, arr) => {
if (index > fromIndex) {
const valueIndex = index - fromIndex;
return noFurtherThan(valueIndex, item, index, arr)
} else {
return false
for (const fn of toFn) {
toIndex = arr.findIndex((item, index, arr) => {
if (index > fromIndex) {
const valueIndex = index - fromIndex;
return fn(item, index, arr, valueIndex)
} else {
return false
}
});
if (toIndex > -1) {
break
}
});
if (toIndex > 0) {
toIndex -= 1;
} else if (toIndex === -1) {
toIndex = arr.length - 1;
}
} else {
toIndex = fromIndex;
}

if (remove) {
return arr.splice(fromIndex, toIndex === -1 ? 1 : toIndex - fromIndex + 1)
let deleteCount;
if (toEnd) {
deleteCount = arr.length;
}
if (toIndex === -1) {
/* TODO: If to is not found, should it behave the same as "no to" (just return the from value)? Scanning to the end supports `--option value value` */
deleteCount = arr.length;
} else if (toIndex === undefined) {
/* When to is omitted, just pick the single value at the from index */
/* This differs to arr.slice which slices to the end of the array if end is omitted */
deleteCount = 1;
} else {
if (inclusive) {
deleteCount = toIndex - fromIndex;
} else {
deleteCount = toIndex - fromIndex - 1;
}
}
return arr.splice(fromIndex, deleteCount)
/* deleteCount: An integer indicating the number of elements in the array to remove from start. */
/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice */
} else {
// return arr.slice(fromIndex, toIndex + 1)
if (toEnd) {
toIndex = arr.length + 1;
}
if (toIndex === -1) {
return arr.slice(fromIndex)
} else if (toIndex === undefined) {
/* When to is omitted, just pick the single value at the from index */
/* This differs to arr.slice which slices to the end of the array if end is omitted */
return arr.slice(fromIndex, fromIndex + 1)
} else {
if (inclusive) {
return arr.slice(fromIndex, toIndex + 1)
} else {
return arr.slice(fromIndex, toIndex)
}
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
return arr.slice(fromIndex, toIndex === -1 ? 1 : toIndex - fromIndex + 1)
/* End: Zero-based index at which to end extraction. slice() extracts up to but not including end. */
}
}

/*
TODO: add `noFurtherThan` function as an additional alternative, or replacement, for `to`.. Might result in easier code, e.g. "no further than a --option", rather than "stop here if the next item is an option or the end". This is also how slice() works: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
*/

class CommandLineArgs {
constructor (args, optionDefinitions) {
this.origArgv = args.slice();
Expand Down
114 changes: 85 additions & 29 deletions lib/from-to.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import arrayBack from 'array-back'

/**
* Similar to find-replace with two exceptions:
* - fromTo finds multiple items, find-replace finds single items
Expand All @@ -7,48 +9,102 @@
* - Find one or more items and return (all return values are arrays)
* - Find one or more items, return them, remove them from the input array
*
* arr {string[]} - Input array. Only mutated if `options.remove` is set.
* [options.rtol] {boolean} - Enable right-to-left scans. Either that or pass in a custom iterator.
* [options.remove] {boolean} - Remove from source array
* [options.from] {boolean}
* [options.to] {boolean}
* [options.inclusive] {boolean} - If `true` includes the to item.
* [options.from] {function}
* [options.to] {function}
* [options.noFurtherThan] {function}
* @returns string[]
*/
function fromTo (arr, options = {}) {
const { from: fromFn, to: toFn, noFurtherThan, remove } = options
const fromIndex = arr.findIndex(fromFn)
let { from: fromFn, to: toFn, noFurtherThan, remove, inclusive, toEnd } = options
if (inclusive === undefined && !noFurtherThan && toFn) {
inclusive = true
}
toFn = toFn || noFurtherThan
fromFn = arrayBack(fromFn).map(fn => {
if (typeof fn === 'string') {
return function (val) { return val === fn }
} else {
return fn
}
})
toFn = arrayBack(toFn).map(fn => {
if (typeof fn === 'string') {
return function (item, index, arr, valueIndex) { return item === fn }
} else {
return fn
}
})

let fromIndex
for (const fn of fromFn) {
fromIndex = arr.findIndex(fn)
if (fromIndex > -1) {
break
}
}

let toIndex
if (toFn) {
toIndex = arr.findIndex((item, index, arr) => {
if (index > fromIndex) {
const valueIndex = index - fromIndex
return toFn(valueIndex, item, index, arr)
} else {
return false
}
})
} else if (noFurtherThan) {
toIndex = arr.findIndex((item, index, arr) => {
if (index > fromIndex) {
const valueIndex = index - fromIndex
return noFurtherThan(valueIndex, item, index, arr)
} else {
return false
for (const fn of toFn) {
toIndex = arr.findIndex((item, index, arr) => {
if (index > fromIndex) {
const valueIndex = index - fromIndex
return fn(item, index, arr, valueIndex)
} else {
return false
}
})
if (toIndex > -1) {
break
}
})
if (toIndex > 0) {
toIndex -= 1
} else if (toIndex === -1) {
toIndex = arr.length - 1
}
} else {
toIndex = fromIndex
}

if (remove) {
return arr.splice(fromIndex, toIndex === -1 ? 1 : toIndex - fromIndex + 1)
let deleteCount
if (toEnd) {
deleteCount = arr.length
}
if (toIndex === -1) {
/* TODO: If to is not found, should it behave the same as "no to" (just return the from value)? Scanning to the end supports `--option value value` */
deleteCount = arr.length
} else if (toIndex === undefined) {
/* When to is omitted, just pick the single value at the from index */
/* This differs to arr.slice which slices to the end of the array if end is omitted */
deleteCount = 1
} else {
if (inclusive) {
deleteCount = toIndex - fromIndex
} else {
deleteCount = toIndex - fromIndex - 1
}
}
return arr.splice(fromIndex, deleteCount)
/* deleteCount: An integer indicating the number of elements in the array to remove from start. */
/* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice */
} else {
// return arr.slice(fromIndex, toIndex + 1)
if (toEnd) {
toIndex = arr.length + 1
}
if (toIndex === -1) {
return arr.slice(fromIndex)
} else if (toIndex === undefined) {
/* When to is omitted, just pick the single value at the from index */
/* This differs to arr.slice which slices to the end of the array if end is omitted */
return arr.slice(fromIndex, fromIndex + 1)
} else {
if (inclusive) {
return arr.slice(fromIndex, toIndex + 1)
} else {
return arr.slice(fromIndex, toIndex)
}
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
return arr.slice(fromIndex, toIndex === -1 ? 1 : toIndex - fromIndex + 1)
/* End: Zero-based index at which to end extraction. slice() extracts up to but not including end. */
}
}

Expand Down
Loading

0 comments on commit 18681b2

Please sign in to comment.