diff --git a/README.md b/README.md
index e4412c5..3a61d0f 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,7 @@ Undo-Redo history. Basic features:
* [`H.init({[maxCount, pushEquals, replacePeriod]}, value) ~> history`](#H-init) v0.1.0
* [Present](#present)
* [`H.present ~> valueLens`](#H-present) v0.2.0
+ * [`H.presentReplace ~> valueLens`](#H-presentReplace) v1.3.0
* [Undo](#undo)
* [`H.undoForget(history) ~> history`](#H-undoForget) v0.1.0
* [`H.undoIndex ~> numberLens`](#H-undoIndex) v0.2.0
@@ -285,6 +286,26 @@ thru(
Note that modifications through `H.present` are not referentially transparent
operations, because setting through `H.present` takes a timestamp underneath.
+#### [≡](#contents) [▶](https://calmm-js.github.io/partial.lenses.history/index.html#H-presentReplace) [`H.presentReplace ~> valueLens`](#H-presentReplace) v1.3.0
+
+`H.presentReplace` is a
+[lens](https://github.com/calmm-js/partial.lenses/#partial-lenses) that focuses
+on the present value of history. When read it behaves exactly as [`H.present`](#H-present). When written it does *not* create a new history entry but instead replaces the current one. This might be useful for applying multiple changes in squence without polluting the history.
+
+For example:
+
+```js
+thru(
+ H.init({}, 42),
+ L.modify(H.presentReplace, x => -x),
+ L.get(H.undoIndex)
+)
+// 0
+```
+
+Note that modifications through `H.presentReplace` are not referentially transparent
+operations, because setting through `H.presentReplace` takes a timestamp underneath.
+
### [≡](#contents) [▶](https://calmm-js.github.io/partial.lenses.history/index.html#undo) [Undo](#undo)
#### [≡](#contents) [▶](https://calmm-js.github.io/partial.lenses.history/index.html#H-undoForget) [`H.undoForget(history) ~> history`](#H-undoForget) v0.1.0
diff --git a/package.json b/package.json
index 14b234a..6b5e8f9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "partial.lenses.history",
- "version": "1.2.0",
+ "version": "1.3.0",
"description": "Partial Lenses History is a JavaScript library for Undo-Redo",
"module": "dist/partial.lenses.history.es.js",
"main": "dist/partial.lenses.history.cjs.js",
diff --git a/src/core.js b/src/core.js
index 326ad68..dc5638d 100644
--- a/src/core.js
+++ b/src/core.js
@@ -33,6 +33,26 @@ function setPresentU(value, history) {
)
}
+function setPresentReplaceU(value, history) {
+ const v = history.v
+ const i = history.i
+ const c = history.c
+ if (c.e) {
+ if (I.acyclicEqualsU(S.nth(i, v), value)) {
+ return history
+ }
+ }
+ const t = history.t
+ const now = Date.now()
+ const j0 = Math.max(0, i - c.m)
+ return construct(
+ i - j0,
+ S.append(now, S.slice(j0, i, t)),
+ S.append(value, S.slice(j0, i, v)),
+ c
+ )
+}
+
const setIndexU = (index, history) =>
construct(
Math.max(0, Math.min(index, indexMax(history))),
@@ -69,6 +89,10 @@ export const present = L.lens(function present(history) {
return S.nth(history.i, history.v)
}, setPresentU)
+export const presentReplace = L.lens(function presentReplace(history) {
+ return S.nth(history.i, history.v)
+}, setPresentReplaceU)
+
// Undo
export {index as undoIndex}
diff --git a/src/partial.lenses.history.js b/src/partial.lenses.history.js
index 4c0ca79..d1ad9b7 100644
--- a/src/partial.lenses.history.js
+++ b/src/partial.lenses.history.js
@@ -45,6 +45,7 @@ export const init = C(
// Present
export const present = C(H.present, lens(history, V.any))
+export const presentReplace = C(H.presentReplace, lens(history, V.any))
// Undo
diff --git a/test/tests.js b/test/tests.js
index 2ca5d6f..23997fa 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -113,6 +113,19 @@ describe('History', () => {
)
})
+ testEq([1, 2, 5, 6], async () => {
+ let h = H.init({pushEquals: true}, 1)
+ h = L.set(H.present, 2, h)
+ h = L.set(H.present, 3, h)
+ h = L.set(H.presentReplace, 4, h)
+ h = L.set(H.presentReplace, 5, h)
+ h = L.set(H.present, 6, h)
+ return R.map(
+ i => L.get(H.present, L.set(H.index, i, h)),
+ R.range(0, H.count(h))
+ )
+ })
+
testEq(16000, () => {
let h = H.init({maxCount: 5000}, 1)
for (let i = 2; i < 20000; ++i) h = L.set(H.present, i, h)