Skip to content

Commit

Permalink
Support Transform to Kebab Case (#147956)
Browse files Browse the repository at this point in the history
* 🍡 Support `Transform to Kebab Case`

* Fix eslint warnings

Co-authored-by: Alexandru Dima <alexdima@microsoft.com>
  • Loading branch information
mbelsky and alexdima authored Jun 28, 2022
1 parent 393099a commit 5ab9f86
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 1 deletion.
47 changes: 47 additions & 0 deletions src/vs/editor/contrib/linesOperations/browser/linesOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,49 @@ export class SnakeCaseAction extends AbstractCaseAction {
}
}

export class KebabCaseAction extends AbstractCaseAction {

public static isSupported(): boolean {
const areAllRegexpsSupported = [
this.caseBoundary,
this.singleLetters,
this.underscoreBoundary,
].every((regexp) => regexp.isSupported());

return areAllRegexpsSupported;
}

private static caseBoundary = new BackwardsCompatibleRegExp('(\\p{Ll})(\\p{Lu})', 'gmu');
private static singleLetters = new BackwardsCompatibleRegExp('(\\p{Lu}|\\p{N})(\\p{Lu}\\p{Ll})', 'gmu');
private static underscoreBoundary = new BackwardsCompatibleRegExp('(\\S)(_)(\\S)', 'gm');

constructor() {
super({
id: 'editor.action.transformToKebabcase',
label: nls.localize('editor.transformToKebabcase', 'Transform to Kebab Case'),
alias: 'Transform to Kebab Case',
precondition: EditorContextKeys.writable
});
}

protected _modifyText(text: string, _: string): string {
const caseBoundary = KebabCaseAction.caseBoundary.get();
const singleLetters = KebabCaseAction.singleLetters.get();
const underscoreBoundary = KebabCaseAction.underscoreBoundary.get();

if (!caseBoundary || !singleLetters || !underscoreBoundary) {
// one or more regexps aren't supported
return text;
}

return text
.replace(underscoreBoundary, '$1-$3')
.replace(caseBoundary, '$1-$2')
.replace(singleLetters, '$1-$2')
.toLocaleLowerCase();
}
}

registerEditorAction(CopyLinesUpAction);
registerEditorAction(CopyLinesDownAction);
registerEditorAction(DuplicateSelectionAction);
Expand Down Expand Up @@ -1189,3 +1232,7 @@ if (SnakeCaseAction.caseBoundary.isSupported() && SnakeCaseAction.singleLetters.
if (TitleCaseAction.titleBoundary.isSupported()) {
registerEditorAction(TitleCaseAction);
}

if (KebabCaseAction.isSupported()) {
registerEditorAction(KebabCaseAction);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Selection } from 'vs/editor/common/core/selection';
import { Handler } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
import { DeleteAllLeftAction, DeleteAllRightAction, DeleteDuplicateLinesAction, DeleteLinesAction, IndentLinesAction, InsertLineAfterAction, InsertLineBeforeAction, JoinLinesAction, LowerCaseAction, SnakeCaseAction, SortLinesAscendingAction, SortLinesDescendingAction, TitleCaseAction, TransposeAction, UpperCaseAction } from 'vs/editor/contrib/linesOperations/browser/linesOperations';
import { DeleteAllLeftAction, DeleteAllRightAction, DeleteDuplicateLinesAction, DeleteLinesAction, IndentLinesAction, InsertLineAfterAction, InsertLineBeforeAction, JoinLinesAction, KebabCaseAction, LowerCaseAction, SnakeCaseAction, SortLinesAscendingAction, SortLinesDescendingAction, TitleCaseAction, TransposeAction, UpperCaseAction } from 'vs/editor/contrib/linesOperations/browser/linesOperations';
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { createTextModel } from 'vs/editor/test/common/testTextModel';

Expand Down Expand Up @@ -814,6 +814,80 @@ suite('Editor Contrib - Line Operations', () => {
assertSelection(editor, new Selection(2, 2, 2, 2));
}
);

withTestCodeEditor(
[
'hello world',
'öçşğü',
'parseHTMLString',
'getElementById',
'PascalCase',
'öçşÖÇŞğüĞÜ',
'audioConverter.convertM4AToMP3();',
'Capital_Snake_Case',
'parseHTML4String',
'_accessor: ServicesAccessor',
'Kebab-Case',
], {}, (editor) => {
const model = editor.getModel()!;
const kebabCaseAction = new KebabCaseAction();

editor.setSelection(new Selection(1, 1, 1, 12));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(1), 'hello world');
assertSelection(editor, new Selection(1, 1, 1, 12));

editor.setSelection(new Selection(2, 1, 2, 6));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(2), 'öçşğü');
assertSelection(editor, new Selection(2, 1, 2, 6));

editor.setSelection(new Selection(3, 1, 3, 16));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(3), 'parse-html-string');
assertSelection(editor, new Selection(3, 1, 3, 18));

editor.setSelection(new Selection(4, 1, 4, 15));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(4), 'get-element-by-id');
assertSelection(editor, new Selection(4, 1, 4, 18));

editor.setSelection(new Selection(5, 1, 5, 11));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(5), 'pascal-case');
assertSelection(editor, new Selection(5, 1, 5, 12));

editor.setSelection(new Selection(6, 1, 6, 11));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(6), 'öçş-öç-şğü-ğü');
assertSelection(editor, new Selection(6, 1, 6, 14));

editor.setSelection(new Selection(7, 1, 7, 34));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(7), 'audio-converter.convert-m4a-to-mp3();');
assertSelection(editor, new Selection(7, 1, 7, 38));

editor.setSelection(new Selection(8, 1, 8, 19));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(8), 'capital-snake-case');
assertSelection(editor, new Selection(8, 1, 8, 19));

editor.setSelection(new Selection(9, 1, 9, 17));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(9), 'parse-html4-string');
assertSelection(editor, new Selection(9, 1, 9, 19));

editor.setSelection(new Selection(10, 1, 10, 28));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(10), '_accessor: services-accessor');
assertSelection(editor, new Selection(10, 1, 10, 29));

editor.setSelection(new Selection(11, 1, 11, 11));
executeAction(kebabCaseAction, editor);
assert.strictEqual(model.getLineContent(11), 'kebab-case');
assertSelection(editor, new Selection(11, 1, 11, 11));
}
);
});

suite('DeleteAllRightAction', () => {
Expand Down

0 comments on commit 5ab9f86

Please sign in to comment.