Skip to content

Commit

Permalink
Merge pull request #135698 from thebinarysearchtree/TitleCaseAction
Browse files Browse the repository at this point in the history
Handle apostrophes in TitleCaseAction
  • Loading branch information
alexdima committed Oct 27, 2021
2 parents 8eae60d + 5baf3ab commit 7d8f55e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 48 deletions.
82 changes: 36 additions & 46 deletions src/vs/editor/contrib/linesOperations/linesOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1076,43 +1076,6 @@ export class LowerCaseAction extends AbstractCaseAction {
}
}

export class TitleCaseAction extends AbstractCaseAction {
constructor() {
super({
id: 'editor.action.transformToTitlecase',
label: nls.localize('editor.transformToTitlecase', "Transform to Title Case"),
alias: 'Transform to Title Case',
precondition: EditorContextKeys.writable
});
}

protected _modifyText(text: string, wordSeparators: string): string {
const separators = '\r\n\t ' + wordSeparators;
const excludedChars = separators.split('');

let title = '';
let startUpperCase = true;

for (let i = 0; i < text.length; i++) {
let currentChar = text[i];

if (excludedChars.indexOf(currentChar) >= 0) {
startUpperCase = true;

title += currentChar;
} else if (startUpperCase) {
startUpperCase = false;

title += currentChar.toLocaleUpperCase();
} else {
title += currentChar.toLocaleLowerCase();
}
}

return title;
}
}

class BackwardsCompatibleRegExp {

private _actual: RegExp | null;
Expand Down Expand Up @@ -1143,10 +1106,35 @@ class BackwardsCompatibleRegExp {
}
}

export class TitleCaseAction extends AbstractCaseAction {

public static titleBoundary = new BackwardsCompatibleRegExp('(^|[^\\p{L}\\p{N}\']|((^|\\P{L})\'))\\p{L}', 'gmu');

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

protected _modifyText(text: string, wordSeparators: string): string {
const titleBoundary = TitleCaseAction.titleBoundary.get();
if (!titleBoundary) {
// cannot support this
return text;
}
return text
.toLocaleLowerCase()
.replace(titleBoundary, (b) => b.toLocaleUpperCase());
}
}

export class SnakeCaseAction extends AbstractCaseAction {

public static regExp1 = new BackwardsCompatibleRegExp('(\\p{Ll})(\\p{Lu})', 'gmu');
public static regExp2 = new BackwardsCompatibleRegExp('(\\p{Lu}|\\p{N})(\\p{Lu})(\\p{Ll})', 'gmu');
public static caseBoundary = new BackwardsCompatibleRegExp('(\\p{Ll})(\\p{Lu})', 'gmu');
public static singleLetters = new BackwardsCompatibleRegExp('(\\p{Lu}|\\p{N})(\\p{Lu})(\\p{Ll})', 'gmu');

constructor() {
super({
Expand All @@ -1158,15 +1146,15 @@ export class SnakeCaseAction extends AbstractCaseAction {
}

protected _modifyText(text: string, wordSeparators: string): string {
const regExp1 = SnakeCaseAction.regExp1.get();
const regExp2 = SnakeCaseAction.regExp2.get();
if (!regExp1 || !regExp2) {
const caseBoundary = SnakeCaseAction.caseBoundary.get();
const singleLetters = SnakeCaseAction.singleLetters.get();
if (!caseBoundary || !singleLetters) {
// cannot support this
return text;
}
return (text
.replace(regExp1, '$1_$2')
.replace(regExp2, '$1_$2$3')
.replace(caseBoundary, '$1_$2')
.replace(singleLetters, '$1_$2$3')
.toLocaleLowerCase()
);
}
Expand All @@ -1192,8 +1180,10 @@ registerEditorAction(JoinLinesAction);
registerEditorAction(TransposeAction);
registerEditorAction(UpperCaseAction);
registerEditorAction(LowerCaseAction);
registerEditorAction(TitleCaseAction);

if (SnakeCaseAction.regExp1.isSupported() && SnakeCaseAction.regExp2.isSupported()) {
if (SnakeCaseAction.caseBoundary.isSupported() && SnakeCaseAction.singleLetters.isSupported()) {
registerEditorAction(SnakeCaseAction);
}
if (TitleCaseAction.titleBoundary.isSupported()) {
registerEditorAction(TitleCaseAction);
}
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,8 @@ suite('Editor Contrib - Line Operations', () => {
'foO[baR]BaZ',
'foO`baR~BaZ',
'foO^baR%BaZ',
'foO$baR!BaZ'
'foO$baR!BaZ',
'\'physician\'s assistant\''
], {}, (editor) => {
let model = editor.getModel()!;
let titlecaseAction = new TitleCaseAction();
Expand All @@ -759,7 +760,7 @@ suite('Editor Contrib - Line Operations', () => {

editor.setSelection(new Selection(2, 1, 2, 12));
executeAction(titlecaseAction, editor);
assert.strictEqual(model.getLineContent(2), 'Foo\'Bar\'Baz');
assert.strictEqual(model.getLineContent(2), 'Foo\'bar\'baz');

editor.setSelection(new Selection(3, 1, 3, 12));
executeAction(titlecaseAction, editor);
Expand All @@ -776,6 +777,10 @@ suite('Editor Contrib - Line Operations', () => {
editor.setSelection(new Selection(6, 1, 6, 12));
executeAction(titlecaseAction, editor);
assert.strictEqual(model.getLineContent(6), 'Foo$Bar!Baz');

editor.setSelection(new Selection(7, 1, 7, 23));
executeAction(titlecaseAction, editor);
assert.strictEqual(model.getLineContent(7), '\'Physician\'s Assistant\'');
}
);

Expand Down

0 comments on commit 7d8f55e

Please sign in to comment.