Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ✨ add character length indicator for commit message #310

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,16 @@
"type": "boolean",
"default": false,
"markdownDescription": "%extension.configuration.editor.keepAfterSave.markdownDescription%"
},
"conventionalCommits.commitMaxLength.subject": {
"type": "number",
"default": 70,
"markdownDescription": "%extension.configuration.commitMaxLength.subject.markdownDescription%"
},
"conventionalCommits.commitMaxLength.body": {
"type": "number",
"default": 140,
"markdownDescription": "%extension.configuration.commitMaxLength.body.markdownDescription%"
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"extension.configuration.showEditor.markdownDescription": "Control whether the extension should show the commit message as a text document in a separate tab.",
"extension.configuration.showNewVersionNotes.markdownDescription": "Control whether the extension should show the new version notes.",
"extension.configuration.editor.keepAfterSave.markdownDescription": "Control whether the extension should keep the editor tab open, after saving the commit message.",
"extension.configuration.commitMaxLength.subject.markdownDescription": "Control the recommended maximum size displayed in the subject on commit message.",
"extension.configuration.commitMaxLength.body.markdownDescription": "Control the recommended maximum size displayed in the body on commit message.",
"extension.sources.repositoryNotFoundInPath": "Repository not found in path: ",
"extension.sources.repositoriesEmpty": "Please open a repository.",
"extension.sources.promptRepositoryPlaceholder": "Choose a repository.",
Expand Down
2 changes: 2 additions & 0 deletions package.nls.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"extension.configuration.showEditor.markdownDescription": "是否需要在新标签页用文本编辑器展示提交信息",
"extension.configuration.showNewVersionNotes.markdownDescription": "是否需要显示新版本说明。",
"extension.configuration.editor.keepAfterSave.markdownDescription": "是否需要在保存提交消息后保持编辑状态。",
"extension.configuration.commitMaxLength.subject.markdownDescription": "在“描述”输入框下方显示建议的最大长度值。",
"extension.configuration.commitMaxLength.body.markdownDescription": "在“正文”输入框下方显示建议的最大长度值。",
"extension.sources.repositoryNotFoundInPath": "以下路径中未找到仓库:",
"extension.sources.repositoriesEmpty": "请打开一个仓库。",
"extension.sources.promptRepositoryPlaceholder": "请选择一个仓库。",
Expand Down
40 changes: 40 additions & 0 deletions src/lib/commit-store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { getPromptLocalize } from './localize';

export class CommitStore {
private _data: Data[] = [];
private static INSTANCE: CommitStore;

static initialize() {
if (!this.INSTANCE) {
this.INSTANCE = new CommitStore();
}
return this.INSTANCE;
}

store(name: string, value: any = null): void {
const find = this._data.findIndex((x) => x.name === name);
if (find !== -1) {
this._data[find].value = value;
} else {
this._data.push({ name, value });
}
}

get(name: string): any {
const result = this._data.filter((e: Data) => e.name === name);
if (
!result ||
!result[0].value ||
result[0].value === getPromptLocalize('scope.noneItem.label') ||
result[0].value === getPromptLocalize('gitmoji.noneItem.label')
) {
return '';
}
return result[0].value;
}
}

type Data = {
name: string;
value: any;
};
19 changes: 19 additions & 0 deletions src/lib/commitlint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@ class Commitlint {
return this.getEnum('type-enum');
}

getValueConfig(key: keyof RulesConfig) {
const config = this.ruleConfigs[key];
if (!config) {
return undefined;
}

//@ts-ignore
const [level, condition, value] = config;
return value ?? undefined;
}

getSubjectMaxLength() {
return this.getValueConfig('subject-max-length');
}

getBodyMaxLength() {
return this.getValueConfig('body-max-length');
}

getScopeEnum() {
return this.getEnum('scope-enum');
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export type Configuration = {
promptCI: boolean;
showNewVersionNotes: boolean;
'editor.keepAfterSave': boolean;
'commitMaxLength.subject': number;
'commitMaxLength.body': number;
};

export function getConfiguration() {
Expand Down
8 changes: 5 additions & 3 deletions src/lib/conventional-commits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ async function getRepository({
}

export default function createConventionalCommits() {
return async function conventionalCommits(repoUri?: VSCodeGit.Repository | vscode.Uri) {
return async function conventionalCommits(
repoUri?: VSCodeGit.Repository | vscode.Uri,
) {
try {
output.info('Conventional commits started.');

Expand All @@ -121,11 +123,11 @@ export default function createConventionalCommits() {

// 3. get repository
let _repoUri = repoUri;
if (!(repoUri instanceof vscode.Uri) && (repoUri !== undefined)) {
if (!(repoUri instanceof vscode.Uri) && repoUri !== undefined) {
_repoUri = repoUri.rootUri;
}
const repository = await getRepository({
arg: (<vscode.Uri | undefined>_repoUri),
arg: <vscode.Uri | undefined>_repoUri,
git: git,
workspaceFolders: vscode.workspace.workspaceFolders,
});
Expand Down
1 change: 1 addition & 0 deletions src/lib/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default async function prompts({
}): Promise<CommitMessage> {
const commitMessage = new CommitMessage();
const conventionalCommitsTypes = getTypesByLocale(locale).types;
var storedCommitValues = {};

function lineBreakFormatter(input: string): string {
if (lineBreak) {
Expand Down
60 changes: 58 additions & 2 deletions src/lib/prompts/prompt-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import * as configuration from '../configuration';
import createSimpleQuickPick, { confirmButton } from './quick-pick';
import localize from '../localize';
import * as output from '../output';
import { CommitStore } from '../commit-store';
import commitlint from '../commitlint';

const storeCommit = CommitStore.initialize();

export enum PROMPT_TYPES {
QUICK_PICK,
Expand Down Expand Up @@ -36,6 +40,7 @@ type Options = {
step: number;
totalSteps: number;
buttons?: vscode.QuickInputButton[];
name: string;
};

type QuickPickOptions = {
Expand All @@ -53,6 +58,7 @@ async function createQuickPick({
totalSteps,
noneItem,
buttons = [],
name,
}: QuickPickOptions): Promise<PromptStatus> {
if (noneItem && !items.includes(noneItem)) {
items.unshift(noneItem);
Expand All @@ -68,12 +74,14 @@ async function createQuickPick({
step,
totalSteps,
buttons,
name,
});
return promptStatus;
}

type InputBoxOptions = {
validate?: (value: string) => string | undefined;
name: string;
} & Options;

function createInputBox({
Expand All @@ -83,6 +91,7 @@ function createInputBox({
totalSteps,
validate = () => undefined,
buttons,
name,
}: InputBoxOptions): Promise<PromptStatus> {
return new Promise(function (resolve, reject) {
const input = vscode.window.createInputBox();
Expand All @@ -97,6 +106,7 @@ function createInputBox({
input.onDidChangeValue(function () {
try {
input.validationMessage = validate(input.value);
promptMessageMaxLength({ input, placeholder, name });
} catch (e) {
output.error(`step.${input.step}`, e);
reject(e);
Expand All @@ -108,17 +118,17 @@ function createInputBox({
if (input.validationMessage) {
return;
}
storeCommit.store(name, input.value);
resolve({ value: input.value, activeItems: [] });
input.dispose();
} catch (e) {
output.error(`step.${input.step}`, e);
reject(e);
}
});
input.onDidTriggerButton(function (e) {
input.onDidTriggerButton(function (e: any) {
if (e === confirmButton) {
try {
input.validationMessage = validate(input.value);
if (input.validationMessage) {
return;
}
Expand All @@ -138,6 +148,7 @@ function createInputBox({
}
});
input.prompt = placeholder;
promptMessageMaxLength({ input, placeholder, name });
input.show();
});
}
Expand All @@ -162,6 +173,7 @@ async function createConfigurableQuickPick({
newItemWithoutSetting,
validate = () => undefined,
buttons,
name,
}: ConfigurableQuickPickOptions): Promise<PromptStatus> {
const currentValues: string[] = configuration.get<string[]>(configurationKey);
const workspaceConfigurationItemInfo = {
Expand Down Expand Up @@ -207,6 +219,7 @@ async function createConfigurableQuickPick({
totalSteps,
noneItem,
buttons,
name,
});
if (
promptStatus.activeItems[0] &&
Expand All @@ -219,6 +232,7 @@ async function createConfigurableQuickPick({
totalSteps,
validate,
buttons,
name,
});
promptStatus.value = newItemInputStatus.value;
if (promptStatus.value) {
Expand Down Expand Up @@ -247,6 +261,7 @@ async function createConfigurableQuickPick({
totalSteps,
validate,
buttons,
name,
})
).value,
activeItems: [newItemWithoutSetting],
Expand All @@ -260,3 +275,44 @@ export default {
[PROMPT_TYPES.INPUT_BOX]: createInputBox,
[PROMPT_TYPES.CONFIGURABLE_QUICK_PICK]: createConfigurableQuickPick,
};

/**
* @description this function represent a complete commit message for help the user regulate the limit of characters in commit
*/
function promptMessageMaxLength({
input,
placeholder,
name,
}: {
input: vscode.InputBox;
placeholder: string;
name?: string;
}) {
const subjectMax: number =
Number(commitlint.getSubjectMaxLength()) ||
configuration.get<number>('commitMaxLength.subject');
const bodyMax: number =
Number(commitlint.getBodyMaxLength()) ||
configuration.get<number>('commitMaxLength.body');
if (name && name === 'subject') {
const type = storeCommit.get('type');
const scope = storeCommit.get('scope');
const gitmoji = storeCommit.get('gitmoji');

var string = type;

if (scope.length > 0) {
string += `(${scope})`;
}
string += ': ';

// If emoji just two caractere count
if (gitmoji.length > 0) string += 'A ';

string += input.value;
input.prompt = `(${string.length.toString()}/${subjectMax.toString()}) ${placeholder}`;
}
if (name && name === 'body') {
input.prompt = `(${input.value.length.toString()}/${bodyMax.toString()}) ${placeholder}`;
}
}
11 changes: 9 additions & 2 deletions src/lib/prompts/quick-pick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
* @author vivaxy
*/
import * as vscode from 'vscode';
import { CommitStore } from '../commit-store';

const storeCommit = CommitStore.initialize();

export const confirmButton: vscode.QuickInputButton = {
iconPath: new vscode.ThemeIcon('arrow-right'),
Expand All @@ -17,7 +20,8 @@ export default function createQuickPick<T extends vscode.QuickPickItem>({
step,
totalSteps,
buttons = [],
}: Partial<vscode.QuickPick<T>>): Promise<{
name,
}: Partial<vscode.QuickPick<T>> & { name?: string }): Promise<{
value: string;
activeItems: T[];
}> {
Expand All @@ -36,14 +40,17 @@ export default function createQuickPick<T extends vscode.QuickPickItem>({
picker.buttons = [...buttons, confirmButton];
picker.onDidAccept(function () {
if (picker.activeItems.length) {
if (name) {
storeCommit.store(name, picker.activeItems[0].label);
}
resolve({
value: picker.value,
activeItems: picker.activeItems as T[],
});
picker.dispose();
}
});
picker.onDidTriggerButton(function (e) {
picker.onDidTriggerButton(function (e: any) {
if (e === confirmButton) {
if (picker.activeItems.length) {
resolve({
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"lib": ["es6"],
"sourceMap": true,
"rootDir": "src",
"noImplicitAny": false,
"strict": true /* enable all strict type-checking options */
/* Additional Checks */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
Expand Down