diff --git a/.travis.yml b/.travis.yml
index b2e8d24..751475a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,5 +13,6 @@ install:
export DISPLAY=':99.0'
/usr/bin/Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
fi
+ - npm install
script:
- npm test
diff --git a/.vscodeignore b/.vscodeignore
index 3b76c81..1001b20 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -11,4 +11,4 @@ vsc-extension-quickstart.md
temp/**
test-temp/**
.idea/**
-images/examles
\ No newline at end of file
+images/examples
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff76fdb..1e6905e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,29 @@
# Change Log
-All notable changes to the "git-semantic-commit" extension will be documented in this file.
+All notable changes to this project will be documented in this file.
-Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## [Unreleased]
+## [2.0.0] - 2020-02-06
-- Initial release
+### Added
+
+- Add new types with helpful descriptions

+- Add new option to show description for types ([#de88ff6](https://github.com/nitayneeman/vscode-git-semantic-commit/commit/de88ff66cab1bc3788915aafc7b3756209f08dc2)) - thanks to [@balazsorban44](https://github.com/balazsorban44) 
+
+## [1.1.0] - 2019-10-25
+
+### Added
+
+- Add new option to change the scope template through a placeholder ([#610a3fc](https://github.com/nitayneeman/vscode-git-semantic-commit/commit/610a3fc9550b4a88fcea06741c3cd6602a2051d3)) - thanks to [@axelprox](https://github.com/axelprox) 
+
+## [1.0.1] - 2019-10-22
+
+### Changed
+
+- Change to use `git diff` for checking the staging area
+
+## [1.0.0] - 2019-10-21
+
+- 🎉 Initial release
diff --git a/README.md b/README.md
index d658a60..b548524 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,8 @@ This Visual Studio Code extension enables to commit simply by the semantic messa
+Notice that the default types are aligned with the Angular commit message [conventions](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type).
+
## 👨🏻🏫 How to Use
@@ -39,7 +41,7 @@ Well, there are two ways to trigger the "Semantic Commit" command:
Open the Command Palette and start typing `Git: Semantic Commit`:
-
+
Then, choose the appropriate command and follow the steps.
@@ -49,7 +51,7 @@ Then, choose the appropriate command and follow the steps.
Alternatively, you can use the primary and secondary actions within the Source Control view:
-
+
@@ -62,9 +64,26 @@ The extension allows you to customize the following configuration settings:
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `gitSemanticCommit.commitOptions` | Specifies which [arguments](https://git-scm.com/docs/git-commit#_options) to be passed when the commit is executed |
| `gitSemanticCommit.preserveScope` | Determines whether to preserve the last message scope that was inserted |
+| `gitSemanticCommit.scopeTemplate` | Specifies scope template (`$scope` placeholder will be replaced with the passed scope) |
| `gitSemanticCommit.stageAll` | Determines whether to stage all changes before the commit, in case the staging area (index) is empty |
| `gitSemanticCommit.types` | Specifies the supported message types |
+### Customize Your Types
+
+Besides the fact you can add new message types, it's also possible to modify the existing values and their descriptions:
+
+
+
+
+
+### Customize Your Scope
+
+You can modify the scope template through a placeholder:
+
+
+
+
+
## 💁🏻 Contributing
diff --git a/images/examples/settings/scope-template.gif b/images/examples/settings/scope-template.gif
new file mode 100644
index 0000000..b4188de
Binary files /dev/null and b/images/examples/settings/scope-template.gif differ
diff --git a/images/examples/settings/types-with-emojis.png b/images/examples/settings/types-with-emojis.png
new file mode 100644
index 0000000..47a7826
Binary files /dev/null and b/images/examples/settings/types-with-emojis.png differ
diff --git a/images/examples/usage/types-with-descriptions.png b/images/examples/usage/types-with-descriptions.png
new file mode 100644
index 0000000..e72e742
Binary files /dev/null and b/images/examples/usage/types-with-descriptions.png differ
diff --git a/package-lock.json b/package-lock.json
index d2556a1..f994d49 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "git-semantic-commit",
- "version": "1.0.0",
+ "version": "2.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -452,9 +452,9 @@
}
},
"https-proxy-agent": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz",
- "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==",
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
+ "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
"dev": true,
"requires": {
"agent-base": "^4.3.0",
@@ -561,9 +561,9 @@
}
},
"lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true
},
"log-symbols": {
@@ -986,9 +986,9 @@
"dev": true
},
"y18n": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
- "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
+ "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
"dev": true
},
"yargs": {
diff --git a/package.json b/package.json
index 0507765..2df1e2b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "git-semantic-commit",
- "version": "1.0.0",
+ "version": "2.0.0",
"license": "MIT",
"author": "Nitay Neeman",
"description": "💬 A Visual Studio Code extension which enables to commit simply by the semantic message conventions",
@@ -21,7 +21,7 @@
"icon": "images/logo.png",
"galleryBanner": {
"color": "#eae9e1",
- "theme": "dark"
+ "theme": "light"
},
"engines": {
"vscode": "^1.39.0"
@@ -29,6 +29,13 @@
"categories": [
"Other"
],
+ "badges": [
+ {
+ "description": "Build",
+ "url": "https://travis-ci.com/nitayneeman/vscode-git-semantic-commit.svg?token=vHfpxFNvotCsScqrpvMs&branch=master",
+ "href": "https://travis-ci.com/nitayneeman/vscode-git-semantic-commit"
+ }
+ ],
"activationEvents": [
"*"
],
@@ -48,6 +55,11 @@
"default": false,
"markdownDescription": "Determines whether to preserve the last message scope that was inserted."
},
+ "gitSemanticCommit.scopeTemplate": {
+ "type": "string",
+ "default": "($scope)",
+ "markdownDescription": "Specifies scope template (`$scope` placeholder will be replaced with the passed scope). Check out [this](https://github.com/nitayneeman/vscode-git-semantic-commit#customize-your-scope) example."
+ },
"gitSemanticCommit.stageAll": {
"type": "boolean",
"default": true,
@@ -56,20 +68,53 @@
"gitSemanticCommit.types": {
"type": "array",
"default": [
- "chore",
- "docs",
- "feat",
- "fix",
- "refactor",
- "style",
- "test"
+ {
+ "type": "build",
+ "description": "Development changes related to the build system"
+ },
+ {
+ "type": "ci",
+ "description": "Development changes related to the continuous integration and deployment system"
+ },
+ {
+ "type": "docs",
+ "description": "Documentation changes related to the project"
+ },
+ {
+ "type": "feat",
+ "description": "Production changes related to new backward-compatible abilities or functionality"
+ },
+ {
+ "type": "fix",
+ "description": "Production changes related to backward-compatible bug fixes"
+ },
+ {
+ "type": "perf",
+ "description": "Production changes related to backward-compatible performance improvements"
+ },
+ {
+ "type": "refactor",
+ "description": "Development changes related to modifying the codebase"
+ },
+ {
+ "type": "style",
+ "description": "Development changes related to styling the codebase"
+ },
+ {
+ "type": "test",
+ "description": "Development changes related to tests"
+ }
],
"items": {
- "type": "string"
+ "type": [
+ "string",
+ "object"
+ ],
+ "description": "Can be either a string, or an object. If an object, use type for the commit type, and description to give a short description for the particular commit type."
},
"minItems": 1,
"uniqueItems": true,
- "markdownDescription": "Specifies the supported message types."
+ "markdownDescription": "Specifies the supported message types. Check out [this](https://github.com/nitayneeman/vscode-git-semantic-commit#customize-your-types) example."
}
}
},
@@ -109,7 +154,7 @@
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
- "pretest": "npm run compile && ./scripts/pretest.sh",
+ "pretest": "npm run compile && git init test-temp --quiet",
"test": "node ./out/test/runTest.js"
},
"devDependencies": {
diff --git a/scripts/pretest.sh b/scripts/pretest.sh
deleted file mode 100755
index fd07655..0000000
--- a/scripts/pretest.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-mkdir test-temp
-
-cd test-temp
-
-git init --quiet
\ No newline at end of file
diff --git a/src/commands/semantic-commit.ts b/src/commands/semantic-commit.ts
index fdb0d49..45ee6f9 100644
--- a/src/commands/semantic-commit.ts
+++ b/src/commands/semantic-commit.ts
@@ -2,7 +2,7 @@ import { window, workspace, ExtensionContext, QuickPickItem } from 'vscode';
import { getConfiguration, ConfigurationProperties } from '../config';
import { Git } from '../git';
-import { workspaceStorageKey } from '../constants';
+import { workspaceStorageKey, scopeTemplatePlaceholder } from '../constants';
import { Command } from './common';
const enum ActionType {
@@ -17,7 +17,7 @@ export class SemanticCommitCommand extends Command {
context: ExtensionContext;
scope: string;
- types: string[];
+ types: (string | {type: string, description: string})[];
constructor(context: ExtensionContext) {
super();
@@ -75,6 +75,11 @@ export class SemanticCommitCommand extends Command {
return getConfiguration()[ConfigurationProperties.stageAll];
}
+ private get scopeTemplate() {
+ const template = getConfiguration()[ConfigurationProperties.scopeTemplate];
+ return template.length ? template : scopeTemplatePlaceholder;
+ }
+
private hasScope() {
return this.scope.length > 0;
}
@@ -105,13 +110,17 @@ export class SemanticCommitCommand extends Command {
private createQuickPickItems(): QuickPickItem[] {
const hasScope = this.hasScope();
- const typeItems = this.types.map(type => ({
- label: `$(git-commit) Commit with "${type}" type`,
- alwaysShow: true,
- actionType: ActionType.subject,
- type,
- description: ''
- }));
+ const typeItems = this.types.map(item => {
+ const description = typeof item === "string" ? "" : item.description
+ const type = typeof item === "string" ? item : item.type
+ return ({
+ label: `$(git-commit) Commit with "${type}" type`,
+ alwaysShow: true,
+ actionType: ActionType.subject,
+ type,
+ description
+ })
+ });
return [
{
@@ -129,7 +138,10 @@ export class SemanticCommitCommand extends Command {
private async performCommit(type: string, subject: string) {
if (subject.length > 0) {
- const message = `${type}${this.hasScope() ? `(${this.scope})` : ''}: ${subject}`;
+ const scope = this.hasScope()
+ ? this.scopeTemplate.replace(scopeTemplatePlaceholder, this.scope)
+ : '';
+ const message = `${type}${scope}: ${subject}`;
if (this.isStageAllEnabled()) {
try {
diff --git a/src/config.ts b/src/config.ts
index fbdbac3..fd9b719 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -8,6 +8,7 @@ enum ConfigurationProperties {
commitOptions = 'commitOptions',
preserveScope = 'preserveScope',
stageAll = 'stageAll',
+ scopeTemplate = 'scopeTemplate',
types = 'types'
}
diff --git a/src/constants.ts b/src/constants.ts
index 8ae7f0d..2bf3a4b 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -2,4 +2,6 @@ const extensionIdentifier = 'gitSemanticCommit';
const workspaceStorageKey = 'gitSemanticCommit';
-export { extensionIdentifier, workspaceStorageKey };
+const scopeTemplatePlaceholder = '$scope';
+
+export { extensionIdentifier, workspaceStorageKey, scopeTemplatePlaceholder };
diff --git a/src/git.ts b/src/git.ts
index 75f30b4..be71cb0 100644
--- a/src/git.ts
+++ b/src/git.ts
@@ -9,9 +9,9 @@ export class Git {
}
static async add() {
- const { stdout: hasStaged } = await this.status(['--porcelain', '--untracked-files=no']);
+ const { stdout: changes } = await this.diff(['--cached']);
- if (!hasStaged) {
+ if (changes.length === 0) {
return this.execute(getWorkspaceFolder(), 'add', [`--all`]);
}
}
@@ -24,7 +24,7 @@ export class Git {
return exec(`git ${command} ${options.join(' ')}`, { cwd });
}
- private static async status(options: string[] = []) {
- return this.execute(getWorkspaceFolder(), 'status', [...options]);
+ private static async diff(options: string[] = []) {
+ return this.execute(getWorkspaceFolder(), 'diff', [...options]);
}
}
diff --git a/src/test/runTest.ts b/src/test/runTest.ts
index b317851..01bfac7 100644
--- a/src/test/runTest.ts
+++ b/src/test/runTest.ts
@@ -5,7 +5,7 @@ async function main() {
try {
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
const extensionTestsPath = path.resolve(__dirname, './suite/index');
- const testWorkspace = path.resolve(__dirname, './test-temp');
+ const testWorkspace = path.resolve(__dirname, '../../test-temp');
await runTests({
extensionDevelopmentPath,
diff --git a/src/test/suite/extension.test.ts b/src/test/suite/extension.test.ts
index 80cb566..25da345 100644
--- a/src/test/suite/extension.test.ts
+++ b/src/test/suite/extension.test.ts
@@ -1,44 +1,54 @@
-import * as assert from 'assert';
-import * as vscode from 'vscode';
+import * as assert from "assert";
+import * as vscode from "vscode";
-import { createFile, clearDirectory, getLastMessage } from './common';
+import { createFile, clearDirectory, getLastMessage } from "./common";
-suite('Extension Test Suite', () => {
+suite("Extension Test Suite", () => {
const { workspaceFolders } = vscode.workspace;
- const directoryPath = workspaceFolders ? workspaceFolders[0].uri.fsPath : '';
+ const directoryPath = workspaceFolders ? workspaceFolders[0].uri.fsPath : "";
suiteTeardown(() => clearDirectory(directoryPath));
- test('should commit with "chore" type', async () => {
- const sampleSubject = 'add new file';
- const expectedMessage = `chore: ${sampleSubject}`;
+ test('should commit with "build" type', async () => {
+ const sampleSubject = "add new file";
+ const expectedMessage = `build: ${sampleSubject}`;
- await createFile(directoryPath, 'Hello World');
+ await createFile(directoryPath, "Hello World");
await vscode.env.clipboard.writeText(sampleSubject);
- await vscode.commands.executeCommand('gitSemanticCommit.semanticCommit');
- await vscode.commands.executeCommand('editor.action.clipboardPasteAction');
- await vscode.commands.executeCommand('workbench.action.quickOpenSelectNext');
- await vscode.commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem');
+ await vscode.commands.executeCommand("gitSemanticCommit.semanticCommit");
+ await vscode.commands.executeCommand("editor.action.clipboardPasteAction");
+ await vscode.commands.executeCommand(
+ "workbench.action.quickOpenSelectNext"
+ );
+ await vscode.commands.executeCommand(
+ "workbench.action.acceptSelectedQuickOpenItem"
+ );
await new Promise(resolve => setTimeout(resolve, 3000));
const { stdout: message } = await getLastMessage(directoryPath);
assert.equal(message.includes(expectedMessage), true);
});
- test('should commit with a scope and "chore" type', async () => {
- const sampleScope = 'scope';
- const sampleSubject = 'add new file';
- const expectedMessage = `chore(${sampleScope}): ${sampleSubject}`;
+ test('should commit with a scope and "build" type', async () => {
+ const sampleScope = "scope";
+ const sampleSubject = "add new file";
+ const expectedMessage = `build(${sampleScope}): ${sampleSubject}`;
- await createFile(directoryPath, 'Hello World');
+ await createFile(directoryPath, "Hello World");
await vscode.env.clipboard.writeText(sampleScope);
- await vscode.commands.executeCommand('gitSemanticCommit.semanticCommit');
- await vscode.commands.executeCommand('editor.action.clipboardPasteAction');
- await vscode.commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem');
+ await vscode.commands.executeCommand("gitSemanticCommit.semanticCommit");
+ await vscode.commands.executeCommand("editor.action.clipboardPasteAction");
+ await vscode.commands.executeCommand(
+ "workbench.action.acceptSelectedQuickOpenItem"
+ );
await vscode.env.clipboard.writeText(sampleSubject);
- await vscode.commands.executeCommand('editor.action.clipboardPasteAction');
- await vscode.commands.executeCommand('workbench.action.quickOpenSelectNext');
- await vscode.commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem');
+ await vscode.commands.executeCommand("editor.action.clipboardPasteAction");
+ await vscode.commands.executeCommand(
+ "workbench.action.quickOpenSelectNext"
+ );
+ await vscode.commands.executeCommand(
+ "workbench.action.acceptSelectedQuickOpenItem"
+ );
await new Promise(resolve => setTimeout(resolve, 3000));
const { stdout: message } = await getLastMessage(directoryPath);