Skip to content

Commit

Permalink
Feature: increment/decrementNumber (#56)
Browse files Browse the repository at this point in the history
Adds command to increment and decrement numbers.
  • Loading branch information
haberdashPI authored Sep 20, 2024
1 parent 05371f8 commit 4bd2bf6
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 4 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Change Log

## [0.6.9]

- **Feature**: add `increment/decrementNumber`

## [0.6.7-8]

- **Bugfix**: thorough examination of edge-cases for unit motions (e.g. subword, word, paragraph, etc...)

## [0.6.6]

- **Feature**: add `select` flag for command `activePageMove` command
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![CI](https://github.com/haberdashPI/vscode-selection-utilities/actions/workflows/ci.yml/badge.svg)](https://github.com/haberdashPI/vscode-selection-utilities/actions/workflows/ci.yml)
[![Code Style: Google](https://img.shields.io/badge/code%20style-google-blueviolet)](https://github.com/google/gts)

> [!WARNING] 🚧 under construction 🚧
> [!WARNING] 🚧 documentation under construction 🚧
> The documentation for selection utilities is under construction. The [older docs](https://haberdashpi.github.io/vscode-selection-utilities/stable/README.html) are currently accurate, but are missing some new commands, and upcoming updates may change some of the names of commands and their arguments
This extension provides a series of utilities for manipulating, saving and creating both single and multiple selections, many of which are inspired by [Kakoune](http://kakoune.org/).
Expand Down
22 changes: 21 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"publisher": "haberdashPI",
"repository": "https://github.com/haberdashPI/vscode-selection-utilities",
"description": "Kakaune-inspired collection of useful commands for manipulating selections.",
"version": "0.6.8",
"version": "0.6.9",
"icon": "logo.png",
"engines": {
"vscode": "^1.92.0"
Expand Down Expand Up @@ -401,6 +401,26 @@
"command": "selection-utilities.adjustSelections",
"title": "Adjust selections inwards or outwards",
"category": "Selection Utilities"
},
{
"command": "selection-utilities.incrementNumber",
"title": "Increment Number",
"category": "Selection Utilities"
},
{
"command": "selection-utilities.decrementNumber",
"title": "Decrement Number",
"category": "Selection Utilities"
},
{
"command": "selection-utilities.incrementNumberPerSelection",
"title": "Increment Number Per Selection",
"category": "Selection Utilities"
},
{
"command": "selection-utilities.decrementNumberPerSelection",
"title": "Decrement Number Per Selection",
"category": "Selection Utilities"
}
]
},
Expand Down
2 changes: 2 additions & 0 deletions src/web/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {registerSelectionModifiers} from './selectionModifiers';
import {registerSelectionFilters} from './selectionFilters';
import {registerSelectionAlignments} from './selectionAlignment';
import {registerSymmetricModifiers} from './symmetricModifiers';
import {registerTextModifiers} from './textModifiers';

declare let __coverage__: object;
export function activate(context: vscode.ExtensionContext) {
Expand All @@ -26,6 +27,7 @@ export function activate(context: vscode.ExtensionContext) {
registerSelectionFilters(context);
registerSelectionAlignments(context);
registerSymmetricModifiers(context);
registerTextModifiers(context);

if (process.env.COVERAGE) {
context.subscriptions.push(
Expand Down
66 changes: 66 additions & 0 deletions src/web/textModifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as vscode from 'vscode';

interface NumberUpdateArgs {
by?: number;
stepEachSelection?: boolean;
}

function changeNumberHelper(text: string, index: number, args: NumberUpdateArgs) {
let number = parseInt(text);
const step = args.by || 1;
if (args.stepEachSelection) {
number += step * index;
} else {
number += step;
}
return number.toString();
}

function changeNumber(args: NumberUpdateArgs) {
const editor = vscode.window.activeTextEditor;
if (editor) {
const selTexts = editor.selections.map(s => editor.document.getText(s));
const badTexts = selTexts.filter(s => !/[0-9]/.test(s));
if (badTexts.length > 0) {
vscode.window.showErrorMessage(
`The selected text '${badTexts[0]}' is not a number.`
);
return;
}

editor.edit(edit => {
for (let i = 0; i < editor.selections.length; i++) {
edit.replace(
editor.selections[i],
changeNumberHelper(selTexts[i], i, args)
);
}
return edit;
});
}
}

export function registerTextModifiers(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('selection-utilities.incrementNumber', () =>
changeNumber({by: 1})
)
);
context.subscriptions.push(
vscode.commands.registerCommand('selection-utilities.decrementNumber', () =>
changeNumber({by: -1})
)
);
context.subscriptions.push(
vscode.commands.registerCommand(
'selection-utilities.incrementNumberPerSelection',
() => changeNumber({by: 1, stepEachSelection: true})
)
);
context.subscriptions.push(
vscode.commands.registerCommand(
'selection-utilities.decrementNumberPerSelection',
() => changeNumber({by: -1, stepEachSelection: true})
)
);
}
129 changes: 129 additions & 0 deletions test/specs/changeNumbers.ux.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import '@wdio/globals';
import 'wdio-vscode-service';
import {cleanWhitespace, setupEditor, storeCoverageStats} from './utils.mts';
import {sleep, TextEditor} from 'wdio-vscode-service';

describe('Number changes', () => {
let editor: TextEditor;

async function setupCursors() {
await browser.executeWorkbench(vscode => {
vscode.commands.executeCommand('selection-utilities.cancelSelection');
});

await editor.moveCursor(1, 1);

for (let i = 0; i < 3; i++) {
await browser.executeWorkbench(async vscode => {
await vscode.commands.executeCommand('editor.action.insertCursorBelow');
});
sleep(100);
}

await browser.executeWorkbench(vscode => {
vscode.commands.executeCommand('selection-utilities.moveBy', {
unit: 'word',
value: 1,
boundary: 'both',
selectWhole: true,
});
});
}

before(async () => {
editor = await setupEditor(`1
1
1
1
`);

await setupCursors();
});

it('can increment numbers', async () => {
await browser.executeWorkbench(async vscode => {
await vscode.commands.executeCommand('selection-utilities.incrementNumber');
});
await sleep(100);
expect(await editor.getText()).toEqual(
cleanWhitespace(`2
2
2
2
`)
);
});

it('can decrement numbers', async () => {
await setupCursors();
await browser.executeWorkbench(async vscode => {
await vscode.commands.executeCommand('selection-utilities.decrementNumber');
});
await sleep(100);
expect(await editor.getText()).toEqual(
cleanWhitespace(`1
1
1
1
`)
);
});

it('can increment numbers per selection', async () => {
await setupCursors();
await browser.executeWorkbench(async vscode => {
await vscode.commands.executeCommand(
'selection-utilities.incrementNumberPerSelection'
);
});
expect(await editor.getText()).toEqual(
cleanWhitespace(`1
2
3
4
`)
);
});

it('can decrement numbers per selection', async () => {
await setupCursors();
await browser.executeWorkbench(async vscode => {
await vscode.commands.executeCommand(
'selection-utilities.decrementNumberPerSelection'
);
});
expect(await editor.getText()).toEqual(
cleanWhitespace(`1
1
1
1
`)
);
});

it('errors with bad selection', async () => {
editor = await setupEditor('a\n');
await browser.executeWorkbench(async vscode => {
await vscode.commands.executeCommand('selection-utilities.moveBy', {
unit: 'word',
value: 1,
boundary: 'both',
selectWhole: true,
});
});

await browser.executeWorkbench(async vscode => {
await vscode.commands.executeCommand('selection-utilities.incrementNumber');
});

const workbench = await browser.getWorkbench();
const notifs = await Promise.all(
(await workbench.getNotifications()).map(n => n.getMessage())
);
expect(notifs).toContain("The selected text 'a' is not a number.");
});

after(async () => {
await storeCoverageStats('changeNumbers');
});
});
2 changes: 0 additions & 2 deletions test/specs/moveBySubword.ux.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// start with just some basic tests to verify all is well

import '@wdio/globals';
import 'wdio-vscode-service';
import {setupEditor, storeCoverageStats, waitUntilCursorUnmoving} from './utils.mts';
Expand Down

0 comments on commit 4bd2bf6

Please sign in to comment.