From 4b004f72a12215eb6e85c8ed19ce8cd02765547e Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Wed, 14 Jan 2026 17:51:13 -0800 Subject: [PATCH 1/5] feat: Preserve number padding using increment/decrement --- .../src/actions/incrementDecrement.ts | 57 +++++++++++++++---- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/packages/cursorless-engine/src/actions/incrementDecrement.ts b/packages/cursorless-engine/src/actions/incrementDecrement.ts index 17d1d3685e..78cc2e6bdf 100644 --- a/packages/cursorless-engine/src/actions/incrementDecrement.ts +++ b/packages/cursorless-engine/src/actions/incrementDecrement.ts @@ -88,23 +88,60 @@ function createDestination( return target.toDestination("to"); } +function hasLeadingZeros(text: string): boolean { + const withoutSign = text.replace(/^-/, ""); + const integerPart = withoutSign.split(".")[0]; + return integerPart.startsWith("0") && integerPart.length > 1; +} + +function formatNumber( + value: number, + text: string, + decimalPlaces?: number, +): string { + const sign = value < 0 ? "-" : ""; + const absValue = Math.abs(value); + + if (hasLeadingZeros(text)) { + const integerPartLength = text.replace(/^-/, "").split(".")[0].length; + const integerPart = Math.floor(absValue) + .toString() + .padStart(integerPartLength, "0"); + + if (decimalPlaces !== undefined) { + const fractionPart = (absValue - Math.floor(absValue)) + .toFixed(decimalPlaces) + .slice(2); + return `${sign}${integerPart}.${fractionPart}`; + } + + return `${sign}${integerPart}`; + } + + return decimalPlaces !== undefined + ? value.toFixed(decimalPlaces) + : value.toString(); +} + function updateNumber(isIncrement: boolean, text: string): string { return text.includes(".") - ? updateFloat(isIncrement, text).toString() - : updateInteger(isIncrement, text).toString(); + ? updateFloat(isIncrement, text) + : updateInteger(isIncrement, text); } -function updateInteger(isIncrement: boolean, text: string): number { - const original = parseInt(text); - const diff = 1; - return original + (isIncrement ? diff : -diff); +function updateInteger(isIncrement: boolean, text: string): string { + const value = parseInt(text) + (isIncrement ? 1 : -1); + return formatNumber(value, text); } -function updateFloat(isIncrement: boolean, text: string): number { +function updateFloat(isIncrement: boolean, text: string): string { const original = parseFloat(text); const isPercentage = Math.abs(original) <= 1.0; const diff = isPercentage ? 0.1 : 1; - const updated = original + (isIncrement ? diff : -diff); - // Remove precision problems that would add a lot of extra digits - return parseFloat(updated.toPrecision(15)) / 1; + const value = parseFloat( + (original + (isIncrement ? diff : -diff)).toPrecision(15), + ); + + const decimalPlaces = text.split(".")[1]?.length || 1; + return formatNumber(value, text, decimalPlaces); } From c9be913c90bf82cd63dd9cd2341960e9caa5d887 Mon Sep 17 00:00:00 2001 From: Trillium Smith Date: Wed, 14 Jan 2026 17:56:41 -0800 Subject: [PATCH 2/5] feat: Add incrementDecrement test cases --- .../incrementDecrement/decrementFile.yml | 248 ++++++++++++++++++ .../incrementDecrement/decrementFirstSub.yml | 32 +++ .../incrementDecrement/incrementFile.yml | 248 ++++++++++++++++++ .../incrementDecrement/incrementSecondSub.yml | 32 +++ .../incrementDecrement/incrementThis.yml | 40 +++ 5 files changed, 600 insertions(+) create mode 100644 data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml create mode 100644 data/fixtures/recorded/actions/incrementDecrement/decrementFirstSub.yml create mode 100644 data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml create mode 100644 data/fixtures/recorded/actions/incrementDecrement/incrementSecondSub.yml create mode 100644 data/fixtures/recorded/actions/incrementDecrement/incrementThis.yml diff --git a/data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml b/data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml new file mode 100644 index 0000000000..46db205d87 --- /dev/null +++ b/data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml @@ -0,0 +1,248 @@ +languageId: plaintext +command: + version: 7 + spokenForm: decrement file + action: + name: decrement + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: document} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + 4.0 + 11.0 + 0.1 + + 008 + 002 + 001 + 0008 + + 100 + 010 + + 00101 + 011 + + 005.60 + 002.5 + 100.99 + + 004.0 + 100.0 + 000.2 + + -006 + 000 + -002.0 + -98 + + 000.6 + 000.2 + + 002.234 + 004.00 + 008.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + marks: {} +finalState: + documentContents: |- + 3.0 + 10.0 + 0.0 + + 007 + 001 + 000 + 0007 + + 99 + 009 + + 00100 + 010 + + 004.60 + 001.5 + 99.99 + + 003.0 + 99.0 + 000.1 + + -007 + -001 + -003.0 + -99 + + 000.5 + 000.1 + + 001.234 + 003.00 + 007.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + thatMark: + - type: UntypedTarget + contentRange: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 1, character: 0} + end: {line: 1, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 2, character: 0} + end: {line: 2, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 4, character: 0} + end: {line: 4, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 5, character: 0} + end: {line: 5, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 6, character: 0} + end: {line: 6, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 7, character: 0} + end: {line: 7, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 9, character: 0} + end: {line: 9, character: 2} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 10, character: 0} + end: {line: 10, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 12, character: 0} + end: {line: 12, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 13, character: 0} + end: {line: 13, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 15, character: 0} + end: {line: 15, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 16, character: 0} + end: {line: 16, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 17, character: 0} + end: {line: 17, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 19, character: 0} + end: {line: 19, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 20, character: 0} + end: {line: 20, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 21, character: 0} + end: {line: 21, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 23, character: 0} + end: {line: 23, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 24, character: 0} + end: {line: 24, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 25, character: 0} + end: {line: 25, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 26, character: 0} + end: {line: 26, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 28, character: 0} + end: {line: 28, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 29, character: 0} + end: {line: 29, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 31, character: 0} + end: {line: 31, character: 7} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 32, character: 0} + end: {line: 32, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 33, character: 0} + end: {line: 33, character: 7} + isReversed: false + hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/decrementFirstSub.yml b/data/fixtures/recorded/actions/incrementDecrement/decrementFirstSub.yml new file mode 100644 index 0000000000..f498b7c9e2 --- /dev/null +++ b/data/fixtures/recorded/actions/incrementDecrement/decrementFirstSub.yml @@ -0,0 +1,32 @@ +languageId: plaintext +command: + version: 7 + spokenForm: decrement first sub + action: + name: decrement + target: + type: primitive + modifiers: + - type: ordinalScope + scopeType: {type: word} + start: 0 + length: 1 + usePrePhraseSnapshot: true +initialState: + documentContents: "2026_015" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + marks: {} +finalState: + documentContents: "2025_015" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + thatMark: + - type: UntypedTarget + contentRange: + start: {line: 0, character: 0} + end: {line: 0, character: 4} + isReversed: false + hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml b/data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml new file mode 100644 index 0000000000..cdc0972b32 --- /dev/null +++ b/data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml @@ -0,0 +1,248 @@ +languageId: plaintext +command: + version: 7 + spokenForm: increment file + action: + name: increment + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: document} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + 3.0 + 10.0 + 0.0 + + 007 + 001 + 000 + 0007 + + 99 + 009 + + 00100 + 010 + + 004.60 + 001.5 + 99.99 + + 003.0 + 99.0 + 000.1 + + -007 + -001 + -003.0 + -99 + + 000.5 + 000.1 + + 001.234 + 003.00 + 007.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + marks: {} +finalState: + documentContents: |- + 4.0 + 11.0 + 0.1 + + 008 + 002 + 001 + 0008 + + 100 + 010 + + 00101 + 011 + + 005.60 + 002.5 + 100.99 + + 004.0 + 100.0 + 000.2 + + -006 + 000 + -002.0 + -98 + + 000.6 + 000.2 + + 002.234 + 004.00 + 008.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + thatMark: + - type: UntypedTarget + contentRange: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 1, character: 0} + end: {line: 1, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 2, character: 0} + end: {line: 2, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 4, character: 0} + end: {line: 4, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 5, character: 0} + end: {line: 5, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 6, character: 0} + end: {line: 6, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 7, character: 0} + end: {line: 7, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 9, character: 0} + end: {line: 9, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 10, character: 0} + end: {line: 10, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 12, character: 0} + end: {line: 12, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 13, character: 0} + end: {line: 13, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 15, character: 0} + end: {line: 15, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 16, character: 0} + end: {line: 16, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 17, character: 0} + end: {line: 17, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 19, character: 0} + end: {line: 19, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 20, character: 0} + end: {line: 20, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 21, character: 0} + end: {line: 21, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 23, character: 0} + end: {line: 23, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 24, character: 0} + end: {line: 24, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 25, character: 0} + end: {line: 25, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 26, character: 0} + end: {line: 26, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 28, character: 0} + end: {line: 28, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 29, character: 0} + end: {line: 29, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 31, character: 0} + end: {line: 31, character: 7} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 32, character: 0} + end: {line: 32, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 33, character: 0} + end: {line: 33, character: 7} + isReversed: false + hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/incrementSecondSub.yml b/data/fixtures/recorded/actions/incrementDecrement/incrementSecondSub.yml new file mode 100644 index 0000000000..2f9a962937 --- /dev/null +++ b/data/fixtures/recorded/actions/incrementDecrement/incrementSecondSub.yml @@ -0,0 +1,32 @@ +languageId: plaintext +command: + version: 7 + spokenForm: increment second sub + action: + name: increment + target: + type: primitive + modifiers: + - type: ordinalScope + scopeType: {type: word} + start: 1 + length: 1 + usePrePhraseSnapshot: true +initialState: + documentContents: "2026_014" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + marks: {} +finalState: + documentContents: "2026_015" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + thatMark: + - type: UntypedTarget + contentRange: + start: {line: 0, character: 5} + end: {line: 0, character: 8} + isReversed: false + hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/incrementThis.yml b/data/fixtures/recorded/actions/incrementDecrement/incrementThis.yml new file mode 100644 index 0000000000..8d0407784f --- /dev/null +++ b/data/fixtures/recorded/actions/incrementDecrement/incrementThis.yml @@ -0,0 +1,40 @@ +languageId: plaintext +command: + version: 7 + spokenForm: increment this + action: + name: increment + target: + type: primitive + mark: {type: cursor} + usePrePhraseSnapshot: true +initialState: + documentContents: "1_01_001" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + marks: {} +finalState: + documentContents: "2_02_002" + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + thatMark: + - type: UntypedTarget + contentRange: + start: {line: 0, character: 0} + end: {line: 0, character: 1} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 0, character: 2} + end: {line: 0, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 0, character: 5} + end: {line: 0, character: 8} + isReversed: false + hasExplicitRange: true From bd1326a4f93659e10f6a752876f63581fcbea605 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 20 Jan 2026 14:49:32 +0100 Subject: [PATCH 3/5] Small clean up --- .../recorded/actions/decrementFile.yml | 162 ------------ .../incrementDecrement/decrementFile.yml | 226 +++++----------- .../incrementDecrement/decrementFile2.yml | 248 ++++++++++++++++++ .../incrementDecrement/incrementFile.yml | 226 +++++----------- .../incrementDecrement/incrementFile2.yml | 248 ++++++++++++++++++ .../incrementLineFourAndEveryTokenOne.yml | 0 .../incrementThree.yml | 0 .../recorded/actions/incrementFile.yml | 162 ------------ .../src/actions/incrementDecrement.ts | 53 ++-- 9 files changed, 662 insertions(+), 663 deletions(-) delete mode 100644 data/fixtures/recorded/actions/decrementFile.yml create mode 100644 data/fixtures/recorded/actions/incrementDecrement/decrementFile2.yml create mode 100644 data/fixtures/recorded/actions/incrementDecrement/incrementFile2.yml rename data/fixtures/recorded/actions/{ => incrementDecrement}/incrementLineFourAndEveryTokenOne.yml (100%) rename data/fixtures/recorded/actions/{ => incrementDecrement}/incrementThree.yml (100%) delete mode 100644 data/fixtures/recorded/actions/incrementFile.yml diff --git a/data/fixtures/recorded/actions/decrementFile.yml b/data/fixtures/recorded/actions/decrementFile.yml deleted file mode 100644 index 3a359d2da3..0000000000 --- a/data/fixtures/recorded/actions/decrementFile.yml +++ /dev/null @@ -1,162 +0,0 @@ -languageId: plaintext -command: - version: 6 - spokenForm: decrement file - action: - name: decrement - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: document} - usePrePhraseSnapshot: true -initialState: - documentContents: |- - foo - - 0 - 1 - 0.5 - 1.5 - - -0 - -1 - -0.5 - -1.5 - - 0rem - 1rem - 0.5rem - 1.5rem - - -0rem - -1rem - -0.5rem - -1.5rem - selections: - - anchor: {line: 0, character: 0} - active: {line: 0, character: 0} - marks: {} -finalState: - documentContents: |- - foo - - -1 - 0 - 0.4 - 0.5 - - -1 - -2 - -0.6 - -2.5 - - -1rem - 0rem - 0.4rem - 0.5rem - - -1rem - -2rem - -0.6rem - -2.5rem - selections: - - anchor: {line: 0, character: 0} - active: {line: 0, character: 0} - thatMark: - - type: UntypedTarget - contentRange: - start: {line: 2, character: 0} - end: {line: 2, character: 2} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 3, character: 0} - end: {line: 3, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 4, character: 0} - end: {line: 4, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 5, character: 0} - end: {line: 5, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 7, character: 0} - end: {line: 7, character: 2} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 8, character: 0} - end: {line: 8, character: 2} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 9, character: 0} - end: {line: 9, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 10, character: 0} - end: {line: 10, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 12, character: 0} - end: {line: 12, character: 2} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 13, character: 0} - end: {line: 13, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 14, character: 0} - end: {line: 14, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 15, character: 0} - end: {line: 15, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 17, character: 0} - end: {line: 17, character: 2} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 18, character: 0} - end: {line: 18, character: 2} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 19, character: 0} - end: {line: 19, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 20, character: 0} - end: {line: 20, character: 4} - isReversed: false - hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml b/data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml index 46db205d87..3a359d2da3 100644 --- a/data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml +++ b/data/fixtures/recorded/actions/incrementDecrement/decrementFile.yml @@ -1,6 +1,6 @@ languageId: plaintext command: - version: 7 + version: 6 spokenForm: decrement file action: name: decrement @@ -12,100 +12,68 @@ command: usePrePhraseSnapshot: true initialState: documentContents: |- - 4.0 - 11.0 - 0.1 - - 008 - 002 - 001 - 0008 - - 100 - 010 - - 00101 - 011 - - 005.60 - 002.5 - 100.99 - - 004.0 - 100.0 - 000.2 - - -006 - 000 - -002.0 - -98 - - 000.6 - 000.2 - - 002.234 - 004.00 - 008.999 + foo + + 0 + 1 + 0.5 + 1.5 + + -0 + -1 + -0.5 + -1.5 + + 0rem + 1rem + 0.5rem + 1.5rem + + -0rem + -1rem + -0.5rem + -1.5rem selections: - - anchor: {line: 18, character: 0} - active: {line: 18, character: 0} + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} marks: {} finalState: documentContents: |- - 3.0 - 10.0 - 0.0 - - 007 - 001 - 000 - 0007 - - 99 - 009 - - 00100 - 010 - - 004.60 - 001.5 - 99.99 - - 003.0 - 99.0 - 000.1 - - -007 - -001 - -003.0 - -99 - - 000.5 - 000.1 - - 001.234 - 003.00 - 007.999 + foo + + -1 + 0 + 0.4 + 0.5 + + -1 + -2 + -0.6 + -2.5 + + -1rem + 0rem + 0.4rem + 0.5rem + + -1rem + -2rem + -0.6rem + -2.5rem selections: - - anchor: {line: 18, character: 0} - active: {line: 18, character: 0} + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} thatMark: - type: UntypedTarget contentRange: - start: {line: 0, character: 0} - end: {line: 0, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 1, character: 0} - end: {line: 1, character: 4} + start: {line: 2, character: 0} + end: {line: 2, character: 2} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 2, character: 0} - end: {line: 2, character: 3} + start: {line: 3, character: 0} + end: {line: 3, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget @@ -122,127 +90,73 @@ finalState: hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 6, character: 0} - end: {line: 6, character: 3} + start: {line: 7, character: 0} + end: {line: 7, character: 2} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 7, character: 0} - end: {line: 7, character: 4} + start: {line: 8, character: 0} + end: {line: 8, character: 2} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 9, character: 0} - end: {line: 9, character: 2} + end: {line: 9, character: 4} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 10, character: 0} - end: {line: 10, character: 3} + end: {line: 10, character: 4} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 12, character: 0} - end: {line: 12, character: 5} + end: {line: 12, character: 2} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 13, character: 0} - end: {line: 13, character: 3} + end: {line: 13, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 15, character: 0} - end: {line: 15, character: 6} + start: {line: 14, character: 0} + end: {line: 14, character: 3} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 16, character: 0} - end: {line: 16, character: 5} + start: {line: 15, character: 0} + end: {line: 15, character: 3} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 17, character: 0} - end: {line: 17, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 19, character: 0} - end: {line: 19, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 20, character: 0} - end: {line: 20, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 21, character: 0} - end: {line: 21, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 23, character: 0} - end: {line: 23, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 24, character: 0} - end: {line: 24, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 25, character: 0} - end: {line: 25, character: 6} + end: {line: 17, character: 2} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 26, character: 0} - end: {line: 26, character: 3} + start: {line: 18, character: 0} + end: {line: 18, character: 2} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 28, character: 0} - end: {line: 28, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 29, character: 0} - end: {line: 29, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 31, character: 0} - end: {line: 31, character: 7} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 32, character: 0} - end: {line: 32, character: 6} + start: {line: 19, character: 0} + end: {line: 19, character: 4} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 33, character: 0} - end: {line: 33, character: 7} + start: {line: 20, character: 0} + end: {line: 20, character: 4} isReversed: false hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/decrementFile2.yml b/data/fixtures/recorded/actions/incrementDecrement/decrementFile2.yml new file mode 100644 index 0000000000..46db205d87 --- /dev/null +++ b/data/fixtures/recorded/actions/incrementDecrement/decrementFile2.yml @@ -0,0 +1,248 @@ +languageId: plaintext +command: + version: 7 + spokenForm: decrement file + action: + name: decrement + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: document} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + 4.0 + 11.0 + 0.1 + + 008 + 002 + 001 + 0008 + + 100 + 010 + + 00101 + 011 + + 005.60 + 002.5 + 100.99 + + 004.0 + 100.0 + 000.2 + + -006 + 000 + -002.0 + -98 + + 000.6 + 000.2 + + 002.234 + 004.00 + 008.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + marks: {} +finalState: + documentContents: |- + 3.0 + 10.0 + 0.0 + + 007 + 001 + 000 + 0007 + + 99 + 009 + + 00100 + 010 + + 004.60 + 001.5 + 99.99 + + 003.0 + 99.0 + 000.1 + + -007 + -001 + -003.0 + -99 + + 000.5 + 000.1 + + 001.234 + 003.00 + 007.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + thatMark: + - type: UntypedTarget + contentRange: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 1, character: 0} + end: {line: 1, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 2, character: 0} + end: {line: 2, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 4, character: 0} + end: {line: 4, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 5, character: 0} + end: {line: 5, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 6, character: 0} + end: {line: 6, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 7, character: 0} + end: {line: 7, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 9, character: 0} + end: {line: 9, character: 2} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 10, character: 0} + end: {line: 10, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 12, character: 0} + end: {line: 12, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 13, character: 0} + end: {line: 13, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 15, character: 0} + end: {line: 15, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 16, character: 0} + end: {line: 16, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 17, character: 0} + end: {line: 17, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 19, character: 0} + end: {line: 19, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 20, character: 0} + end: {line: 20, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 21, character: 0} + end: {line: 21, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 23, character: 0} + end: {line: 23, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 24, character: 0} + end: {line: 24, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 25, character: 0} + end: {line: 25, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 26, character: 0} + end: {line: 26, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 28, character: 0} + end: {line: 28, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 29, character: 0} + end: {line: 29, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 31, character: 0} + end: {line: 31, character: 7} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 32, character: 0} + end: {line: 32, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 33, character: 0} + end: {line: 33, character: 7} + isReversed: false + hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml b/data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml index cdc0972b32..46f764d49e 100644 --- a/data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml +++ b/data/fixtures/recorded/actions/incrementDecrement/incrementFile.yml @@ -1,6 +1,6 @@ languageId: plaintext command: - version: 7 + version: 6 spokenForm: increment file action: name: increment @@ -12,100 +12,68 @@ command: usePrePhraseSnapshot: true initialState: documentContents: |- - 3.0 - 10.0 - 0.0 - - 007 - 001 - 000 - 0007 - - 99 - 009 - - 00100 - 010 - - 004.60 - 001.5 - 99.99 - - 003.0 - 99.0 - 000.1 - - -007 - -001 - -003.0 - -99 - - 000.5 - 000.1 - - 001.234 - 003.00 - 007.999 + foo + + 0 + 1 + 0.5 + 1.5 + + -0 + -1 + -0.5 + -1.5 + + 0rem + 1rem + 0.5rem + 1.5rem + + -0rem + -1rem + -0.5rem + -1.5rem selections: - - anchor: {line: 18, character: 0} - active: {line: 18, character: 0} + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} marks: {} finalState: documentContents: |- - 4.0 - 11.0 - 0.1 - - 008 - 002 - 001 - 0008 - - 100 - 010 - - 00101 - 011 - - 005.60 - 002.5 - 100.99 - - 004.0 - 100.0 - 000.2 - - -006 - 000 - -002.0 - -98 - - 000.6 - 000.2 - - 002.234 - 004.00 - 008.999 + foo + + 1 + 2 + 0.6 + 2.5 + + 1 + 0 + -0.4 + -0.5 + + 1rem + 2rem + 0.6rem + 2.5rem + + 1rem + 0rem + -0.4rem + -0.5rem selections: - - anchor: {line: 18, character: 0} - active: {line: 18, character: 0} + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} thatMark: - type: UntypedTarget contentRange: - start: {line: 0, character: 0} - end: {line: 0, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 1, character: 0} - end: {line: 1, character: 4} + start: {line: 2, character: 0} + end: {line: 2, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 2, character: 0} - end: {line: 2, character: 3} + start: {line: 3, character: 0} + end: {line: 3, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget @@ -122,127 +90,73 @@ finalState: hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 6, character: 0} - end: {line: 6, character: 3} + start: {line: 7, character: 0} + end: {line: 7, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 7, character: 0} - end: {line: 7, character: 4} + start: {line: 8, character: 0} + end: {line: 8, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 9, character: 0} - end: {line: 9, character: 3} + end: {line: 9, character: 4} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 10, character: 0} - end: {line: 10, character: 3} + end: {line: 10, character: 4} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 12, character: 0} - end: {line: 12, character: 5} + end: {line: 12, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 13, character: 0} - end: {line: 13, character: 3} + end: {line: 13, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 15, character: 0} - end: {line: 15, character: 6} + start: {line: 14, character: 0} + end: {line: 14, character: 3} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 16, character: 0} - end: {line: 16, character: 5} + start: {line: 15, character: 0} + end: {line: 15, character: 3} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: start: {line: 17, character: 0} - end: {line: 17, character: 6} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 19, character: 0} - end: {line: 19, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 20, character: 0} - end: {line: 20, character: 5} + end: {line: 17, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 21, character: 0} - end: {line: 21, character: 5} + start: {line: 18, character: 0} + end: {line: 18, character: 1} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 23, character: 0} - end: {line: 23, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 24, character: 0} - end: {line: 24, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 25, character: 0} - end: {line: 25, character: 6} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 26, character: 0} - end: {line: 26, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 28, character: 0} - end: {line: 28, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 29, character: 0} - end: {line: 29, character: 5} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 31, character: 0} - end: {line: 31, character: 7} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 32, character: 0} - end: {line: 32, character: 6} + start: {line: 19, character: 0} + end: {line: 19, character: 4} isReversed: false hasExplicitRange: true - type: UntypedTarget contentRange: - start: {line: 33, character: 0} - end: {line: 33, character: 7} + start: {line: 20, character: 0} + end: {line: 20, character: 4} isReversed: false hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementDecrement/incrementFile2.yml b/data/fixtures/recorded/actions/incrementDecrement/incrementFile2.yml new file mode 100644 index 0000000000..cdc0972b32 --- /dev/null +++ b/data/fixtures/recorded/actions/incrementDecrement/incrementFile2.yml @@ -0,0 +1,248 @@ +languageId: plaintext +command: + version: 7 + spokenForm: increment file + action: + name: increment + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: document} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + 3.0 + 10.0 + 0.0 + + 007 + 001 + 000 + 0007 + + 99 + 009 + + 00100 + 010 + + 004.60 + 001.5 + 99.99 + + 003.0 + 99.0 + 000.1 + + -007 + -001 + -003.0 + -99 + + 000.5 + 000.1 + + 001.234 + 003.00 + 007.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + marks: {} +finalState: + documentContents: |- + 4.0 + 11.0 + 0.1 + + 008 + 002 + 001 + 0008 + + 100 + 010 + + 00101 + 011 + + 005.60 + 002.5 + 100.99 + + 004.0 + 100.0 + 000.2 + + -006 + 000 + -002.0 + -98 + + 000.6 + 000.2 + + 002.234 + 004.00 + 008.999 + selections: + - anchor: {line: 18, character: 0} + active: {line: 18, character: 0} + thatMark: + - type: UntypedTarget + contentRange: + start: {line: 0, character: 0} + end: {line: 0, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 1, character: 0} + end: {line: 1, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 2, character: 0} + end: {line: 2, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 4, character: 0} + end: {line: 4, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 5, character: 0} + end: {line: 5, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 6, character: 0} + end: {line: 6, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 7, character: 0} + end: {line: 7, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 9, character: 0} + end: {line: 9, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 10, character: 0} + end: {line: 10, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 12, character: 0} + end: {line: 12, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 13, character: 0} + end: {line: 13, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 15, character: 0} + end: {line: 15, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 16, character: 0} + end: {line: 16, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 17, character: 0} + end: {line: 17, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 19, character: 0} + end: {line: 19, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 20, character: 0} + end: {line: 20, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 21, character: 0} + end: {line: 21, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 23, character: 0} + end: {line: 23, character: 4} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 24, character: 0} + end: {line: 24, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 25, character: 0} + end: {line: 25, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 26, character: 0} + end: {line: 26, character: 3} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 28, character: 0} + end: {line: 28, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 29, character: 0} + end: {line: 29, character: 5} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 31, character: 0} + end: {line: 31, character: 7} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 32, character: 0} + end: {line: 32, character: 6} + isReversed: false + hasExplicitRange: true + - type: UntypedTarget + contentRange: + start: {line: 33, character: 0} + end: {line: 33, character: 7} + isReversed: false + hasExplicitRange: true diff --git a/data/fixtures/recorded/actions/incrementLineFourAndEveryTokenOne.yml b/data/fixtures/recorded/actions/incrementDecrement/incrementLineFourAndEveryTokenOne.yml similarity index 100% rename from data/fixtures/recorded/actions/incrementLineFourAndEveryTokenOne.yml rename to data/fixtures/recorded/actions/incrementDecrement/incrementLineFourAndEveryTokenOne.yml diff --git a/data/fixtures/recorded/actions/incrementThree.yml b/data/fixtures/recorded/actions/incrementDecrement/incrementThree.yml similarity index 100% rename from data/fixtures/recorded/actions/incrementThree.yml rename to data/fixtures/recorded/actions/incrementDecrement/incrementThree.yml diff --git a/data/fixtures/recorded/actions/incrementFile.yml b/data/fixtures/recorded/actions/incrementFile.yml deleted file mode 100644 index 46f764d49e..0000000000 --- a/data/fixtures/recorded/actions/incrementFile.yml +++ /dev/null @@ -1,162 +0,0 @@ -languageId: plaintext -command: - version: 6 - spokenForm: increment file - action: - name: increment - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: document} - usePrePhraseSnapshot: true -initialState: - documentContents: |- - foo - - 0 - 1 - 0.5 - 1.5 - - -0 - -1 - -0.5 - -1.5 - - 0rem - 1rem - 0.5rem - 1.5rem - - -0rem - -1rem - -0.5rem - -1.5rem - selections: - - anchor: {line: 0, character: 0} - active: {line: 0, character: 0} - marks: {} -finalState: - documentContents: |- - foo - - 1 - 2 - 0.6 - 2.5 - - 1 - 0 - -0.4 - -0.5 - - 1rem - 2rem - 0.6rem - 2.5rem - - 1rem - 0rem - -0.4rem - -0.5rem - selections: - - anchor: {line: 0, character: 0} - active: {line: 0, character: 0} - thatMark: - - type: UntypedTarget - contentRange: - start: {line: 2, character: 0} - end: {line: 2, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 3, character: 0} - end: {line: 3, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 4, character: 0} - end: {line: 4, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 5, character: 0} - end: {line: 5, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 7, character: 0} - end: {line: 7, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 8, character: 0} - end: {line: 8, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 9, character: 0} - end: {line: 9, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 10, character: 0} - end: {line: 10, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 12, character: 0} - end: {line: 12, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 13, character: 0} - end: {line: 13, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 14, character: 0} - end: {line: 14, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 15, character: 0} - end: {line: 15, character: 3} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 17, character: 0} - end: {line: 17, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 18, character: 0} - end: {line: 18, character: 1} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 19, character: 0} - end: {line: 19, character: 4} - isReversed: false - hasExplicitRange: true - - type: UntypedTarget - contentRange: - start: {line: 20, character: 0} - end: {line: 20, character: 4} - isReversed: false - hasExplicitRange: true diff --git a/packages/cursorless-engine/src/actions/incrementDecrement.ts b/packages/cursorless-engine/src/actions/incrementDecrement.ts index 78cc2e6bdf..6dc7ca5f31 100644 --- a/packages/cursorless-engine/src/actions/incrementDecrement.ts +++ b/packages/cursorless-engine/src/actions/incrementDecrement.ts @@ -88,10 +88,28 @@ function createDestination( return target.toDestination("to"); } -function hasLeadingZeros(text: string): boolean { - const withoutSign = text.replace(/^-/, ""); - const integerPart = withoutSign.split(".")[0]; - return integerPart.startsWith("0") && integerPart.length > 1; +function updateNumber(isIncrement: boolean, text: string): string { + return text.includes(".") + ? updateFloat(isIncrement, text) + : updateInteger(isIncrement, text); +} + +function updateInteger(isIncrement: boolean, text: string): string { + const original = parseInt(text); + const diff = 1; + const value = original + (isIncrement ? diff : -diff); + return formatNumber(value, text); +} + +function updateFloat(isIncrement: boolean, text: string): string { + const original = parseFloat(text); + const isPercentage = Math.abs(original) <= 1.0; + const diff = isPercentage ? 0.1 : 1; + const updated = original + (isIncrement ? diff : -diff); + // Remove precision problems that would add a lot of extra digits + const value = parseFloat(updated.toPrecision(15)) / 1; + const decimalPlaces = text.split(".")[1]?.length; + return formatNumber(value, text, decimalPlaces); } function formatNumber( @@ -108,7 +126,7 @@ function formatNumber( .toString() .padStart(integerPartLength, "0"); - if (decimalPlaces !== undefined) { + if (decimalPlaces != null) { const fractionPart = (absValue - Math.floor(absValue)) .toFixed(decimalPlaces) .slice(2); @@ -118,30 +136,11 @@ function formatNumber( return `${sign}${integerPart}`; } - return decimalPlaces !== undefined + return decimalPlaces != null ? value.toFixed(decimalPlaces) : value.toString(); } -function updateNumber(isIncrement: boolean, text: string): string { - return text.includes(".") - ? updateFloat(isIncrement, text) - : updateInteger(isIncrement, text); -} - -function updateInteger(isIncrement: boolean, text: string): string { - const value = parseInt(text) + (isIncrement ? 1 : -1); - return formatNumber(value, text); -} - -function updateFloat(isIncrement: boolean, text: string): string { - const original = parseFloat(text); - const isPercentage = Math.abs(original) <= 1.0; - const diff = isPercentage ? 0.1 : 1; - const value = parseFloat( - (original + (isIncrement ? diff : -diff)).toPrecision(15), - ); - - const decimalPlaces = text.split(".")[1]?.length || 1; - return formatNumber(value, text, decimalPlaces); +function hasLeadingZeros(text: string): boolean { + return /^-?0\d/.test(text); } From 540954767694b83e224a9dc00faced9da79c2f43 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 20 Jan 2026 14:57:47 +0100 Subject: [PATCH 4/5] More clean up --- packages/cursorless-engine/src/actions/incrementDecrement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cursorless-engine/src/actions/incrementDecrement.ts b/packages/cursorless-engine/src/actions/incrementDecrement.ts index 6dc7ca5f31..616f69bde3 100644 --- a/packages/cursorless-engine/src/actions/incrementDecrement.ts +++ b/packages/cursorless-engine/src/actions/incrementDecrement.ts @@ -121,7 +121,7 @@ function formatNumber( const absValue = Math.abs(value); if (hasLeadingZeros(text)) { - const integerPartLength = text.replace(/^-/, "").split(".")[0].length; + const integerPartLength = /^-?(\d+)/.exec(text)![1].length; const integerPart = Math.floor(absValue) .toString() .padStart(integerPartLength, "0"); From 46be2f9efdb4bc150c8b7450629da8618cf58c51 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 20 Jan 2026 15:05:04 +0100 Subject: [PATCH 5/5] Additional clean up --- .../cursorless-engine/src/actions/incrementDecrement.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/cursorless-engine/src/actions/incrementDecrement.ts b/packages/cursorless-engine/src/actions/incrementDecrement.ts index 616f69bde3..51b60709bf 100644 --- a/packages/cursorless-engine/src/actions/incrementDecrement.ts +++ b/packages/cursorless-engine/src/actions/incrementDecrement.ts @@ -121,7 +121,7 @@ function formatNumber( const absValue = Math.abs(value); if (hasLeadingZeros(text)) { - const integerPartLength = /^-?(\d+)/.exec(text)![1].length; + const integerPartLength = getIntegerPartLength(text); const integerPart = Math.floor(absValue) .toString() .padStart(integerPartLength, "0"); @@ -129,6 +129,7 @@ function formatNumber( if (decimalPlaces != null) { const fractionPart = (absValue - Math.floor(absValue)) .toFixed(decimalPlaces) + // Remove "0." .slice(2); return `${sign}${integerPart}.${fractionPart}`; } @@ -144,3 +145,7 @@ function formatNumber( function hasLeadingZeros(text: string): boolean { return /^-?0\d/.test(text); } + +function getIntegerPartLength(text: string): number { + return /^-?(\d+)/.exec(text)![1].length; +}