Skip to content

Commit

Permalink
#471 Spaces can be automatically substituted with hyphens or undersco…
Browse files Browse the repository at this point in the history
…res in reference inputs on dialogs.
  • Loading branch information
mhutchie committed Mar 3, 2021
1 parent 7877900 commit ac69033
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 8 deletions.
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,21 @@
"default": false,
"description": "Default state of the \"Prune Tags\" checkbox."
},
"git-graph.dialog.general.referenceInputSpaceSubstitution": {
"type": "string",
"enum": [
"None",
"Hyphen",
"Underscore"
],
"enumDescriptions": [
"Don't replace spaces.",
"Replace space characters with hyphens, for example: \"new branch\" -> \"new-branch\".",
"Replace space characters with underscores, for example: \"new branch\" -> \"new_branch\"."
],
"default": "None",
"description": "Specifies a substitution that is automatically performed when space characters are entered or pasted into reference inputs on dialogs (e.g. Create Branch, Add Tag, etc.)."
},
"git-graph.dialog.merge.noCommit": {
"type": "boolean",
"default": false,
Expand Down
4 changes: 4 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class Config {
get dialogDefaults(): DialogDefaults {
let resetCommitMode = this.config.get<string>('dialog.resetCurrentBranchToCommit.mode', 'Mixed');
let resetUncommittedMode = this.config.get<string>('dialog.resetUncommittedChanges.mode', 'Mixed');
let refInputSpaceSubstitution = this.config.get<string>('dialog.general.referenceInputSpaceSubstitution', 'None');

return {
addTag: {
Expand All @@ -199,6 +200,9 @@ class Config {
prune: !!this.config.get('dialog.fetchRemote.prune', false),
pruneTags: !!this.config.get('dialog.fetchRemote.pruneTags', false)
},
general: {
referenceInputSpaceSubstitution: refInputSpaceSubstitution === 'Hyphen' ? '-' : refInputSpaceSubstitution === 'Underscore' ? '_' : null
},
merge: {
noCommit: !!this.config.get('dialog.merge.noCommit', false),
noFastForward: !!this.config.get('dialog.merge.noFastForward', true),
Expand Down
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,9 @@ export interface DialogDefaults {
readonly prune: boolean,
readonly pruneTags: boolean
};
readonly general: {
readonly referenceInputSpaceSubstitution: string | null
};
readonly merge: {
readonly noCommit: boolean,
readonly noFastForward: boolean,
Expand Down
84 changes: 77 additions & 7 deletions tests/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,7 @@ describe('Config', () => {
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchIntoLocalBranch.forceFetch', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.prune', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.pruneTags', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.general.referenceInputSpaceSubstitution', 'None');
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noCommit', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noFastForward', true);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.squashCommits', false);
Expand Down Expand Up @@ -874,6 +875,9 @@ describe('Config', () => {
prune: true,
pruneTags: true
},
general: {
referenceInputSpaceSubstitution: null
},
merge: {
noCommit: true,
noFastForward: true,
Expand Down Expand Up @@ -939,6 +943,7 @@ describe('Config', () => {
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchIntoLocalBranch.forceFetch', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.prune', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.pruneTags', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.general.referenceInputSpaceSubstitution', 'None');
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noCommit', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noFastForward', true);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.squashCommits', false);
Expand Down Expand Up @@ -975,6 +980,9 @@ describe('Config', () => {
prune: false,
pruneTags: false
},
general: {
referenceInputSpaceSubstitution: null
},
merge: {
noCommit: false,
noFastForward: false,
Expand Down Expand Up @@ -1040,6 +1048,7 @@ describe('Config', () => {
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchIntoLocalBranch.forceFetch', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.prune', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.pruneTags', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.general.referenceInputSpaceSubstitution', 'None');
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noCommit', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noFastForward', true);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.squashCommits', false);
Expand Down Expand Up @@ -1076,6 +1085,9 @@ describe('Config', () => {
prune: true,
pruneTags: true
},
general: {
referenceInputSpaceSubstitution: null
},
merge: {
noCommit: true,
noFastForward: true,
Expand Down Expand Up @@ -1141,6 +1153,7 @@ describe('Config', () => {
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchIntoLocalBranch.forceFetch', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.prune', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.pruneTags', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.general.referenceInputSpaceSubstitution', 'None');
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noCommit', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noFastForward', true);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.squashCommits', false);
Expand Down Expand Up @@ -1177,6 +1190,9 @@ describe('Config', () => {
prune: false,
pruneTags: false
},
general: {
referenceInputSpaceSubstitution: null
},
merge: {
noCommit: false,
noFastForward: false,
Expand Down Expand Up @@ -1227,6 +1243,7 @@ describe('Config', () => {
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchIntoLocalBranch.forceFetch', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.prune', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.pruneTags', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.general.referenceInputSpaceSubstitution', 'None');
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noCommit', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noFastForward', true);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.squashCommits', false);
Expand Down Expand Up @@ -1263,6 +1280,9 @@ describe('Config', () => {
prune: false,
pruneTags: false
},
general: {
referenceInputSpaceSubstitution: null
},
merge: {
noCommit: false,
noFastForward: true,
Expand Down Expand Up @@ -1306,6 +1326,7 @@ describe('Config', () => {
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchIntoLocalBranch.forceFetch', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.prune', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.fetchRemote.pruneTags', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.general.referenceInputSpaceSubstitution', 'None');
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noCommit', false);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.noFastForward', true);
expect(workspaceConfiguration.get).toBeCalledWith('dialog.merge.squashCommits', false);
Expand Down Expand Up @@ -1342,6 +1363,9 @@ describe('Config', () => {
prune: false,
pruneTags: false
},
general: {
referenceInputSpaceSubstitution: null
},
merge: {
noCommit: false,
noFastForward: true,
Expand Down Expand Up @@ -1371,7 +1395,7 @@ describe('Config', () => {
});

describe('dialogDefaults.addTag.type', () => {
it('Should return "annotated" the configuration value is "Annotated"', () => {
it('Should return TagType.Annotated when the configuration value is "Annotated"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.addTag.type', 'Annotated');

Expand All @@ -1382,7 +1406,7 @@ describe('Config', () => {
expect(value.addTag.type).toBe(TagType.Annotated);
});

it('Should return "lightweight" the configuration value is "Annotated"', () => {
it('Should return TagType.Lightweight when the configuration value is "Lightweight"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.addTag.type', 'Lightweight');

Expand All @@ -1394,8 +1418,54 @@ describe('Config', () => {
});
});

describe('dialogDefaults.general.referenceInputSpaceSubstitution', () => {
it('Should return NULL when the configuration value is "None"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.general.referenceInputSpaceSubstitution', 'None');

// Run
const value = config.dialogDefaults;

// Assert
expect(value.general.referenceInputSpaceSubstitution).toBe(null);
});

it('Should return "-" when the configuration value is "Hyphen"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.general.referenceInputSpaceSubstitution', 'Hyphen');

// Run
const value = config.dialogDefaults;

// Assert
expect(value.general.referenceInputSpaceSubstitution).toBe('-');
});

it('Should return "_" when the configuration value is "Underscore"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.general.referenceInputSpaceSubstitution', 'Underscore');

// Run
const value = config.dialogDefaults;

// Assert
expect(value.general.referenceInputSpaceSubstitution).toBe('_');
});

it('Should return the default value (NULL) when the configuration value is invalid', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.general.referenceInputSpaceSubstitution', 'invalid');

// Run
const value = config.dialogDefaults;

// Assert
expect(value.general.referenceInputSpaceSubstitution).toBe(null);
});
});

describe('dialogDefaults.resetCommit.mode', () => {
it('Should return GitResetMode.Hard the configuration value is "Hard"', () => {
it('Should return GitResetMode.Hard when the configuration value is "Hard"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.resetCurrentBranchToCommit.mode', 'Hard');

Expand All @@ -1406,7 +1476,7 @@ describe('Config', () => {
expect(value.resetCommit.mode).toBe(GitResetMode.Hard);
});

it('Should return GitResetMode.Mixed the configuration value is "Mixed"', () => {
it('Should return GitResetMode.Mixed when the configuration value is "Mixed"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.resetCurrentBranchToCommit.mode', 'Mixed');

Expand All @@ -1417,7 +1487,7 @@ describe('Config', () => {
expect(value.resetCommit.mode).toBe(GitResetMode.Mixed);
});

it('Should return GitResetMode.Soft the configuration value is "Soft"', () => {
it('Should return GitResetMode.Soft when the configuration value is "Soft"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.resetCurrentBranchToCommit.mode', 'Soft');

Expand All @@ -1430,7 +1500,7 @@ describe('Config', () => {
});

describe('dialogDefaults.resetUncommitted.mode', () => {
it('Should return GitResetMode.Hard the configuration value is "Hard"', () => {
it('Should return GitResetMode.Hard when the configuration value is "Hard"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.resetUncommittedChanges.mode', 'Hard');

Expand All @@ -1441,7 +1511,7 @@ describe('Config', () => {
expect(value.resetUncommitted.mode).toBe(GitResetMode.Hard);
});

it('Should return GitResetMode.Mixed the configuration value is "Mixed"', () => {
it('Should return GitResetMode.Mixed when the configuration value is "Mixed"', () => {
// Setup
vscode.mockExtensionSettingReturnValue('dialog.resetUncommittedChanges.mode', 'Mixed');

Expand Down
10 changes: 9 additions & 1 deletion web/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class Dialog {
private type: DialogType | null = null;
private customSelects: { [inputIndex: string]: CustomSelect } = {};

private static readonly WHITESPACE_REGEXP = /\s/gu;

/**
* Show a confirmation dialog to the user.
* @param message A message outlining what the user is being asked to confirm.
Expand Down Expand Up @@ -269,7 +271,13 @@ class Dialog {
if (dialogInput.value === '') this.elem!.classList.add(CLASS_DIALOG_NO_INPUT);
dialogInput.addEventListener('keyup', () => {
if (this.elem === null) return;
let noInput = dialogInput.value === '', invalidInput = dialogInput.value.match(REF_INVALID_REGEX) !== null;
if (initialState.config.dialogDefaults.general.referenceInputSpaceSubstitution !== null) {
const selectionStart = dialogInput.selectionStart, selectionEnd = dialogInput.selectionEnd;
dialogInput.value = dialogInput.value.replace(Dialog.WHITESPACE_REGEXP, initialState.config.dialogDefaults.general.referenceInputSpaceSubstitution);
dialogInput.selectionStart = selectionStart;
dialogInput.selectionEnd = selectionEnd;
}
const noInput = dialogInput.value === '', invalidInput = dialogInput.value.match(REF_INVALID_REGEX) !== null;
alterClass(this.elem, CLASS_DIALOG_NO_INPUT, noInput);
if (alterClass(this.elem, CLASS_DIALOG_INPUT_INVALID, !noInput && invalidInput)) {
dialogAction.title = invalidInput ? 'Unable to ' + actionName + ', one or more invalid characters entered.' : '';
Expand Down

0 comments on commit ac69033

Please sign in to comment.