diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index e96d54d708e6167f444a5d47762784ed1e97a131..abdd8184ffaa6efc3cd4548361b1f35ae0397d46 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -519,6 +519,7 @@ export class Repository implements Disposable { this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message (press {0} to commit)"); this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] }; this._sourceControl.quickDiffProvider = this; + this._sourceControl.inputBox.warningLength = 72; this.disposables.push(this._sourceControl); this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "Merge Changes")); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index b02773f70b9966ef2bc00d90bbdd5812515bffef..3198839661814b78da6997e35f547a4b5f1ef5db 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5782,6 +5782,11 @@ declare module 'vscode' { * A string to show as place holder in the input box to guide the user. */ placeholder: string; + + /** + * The warning threshold for commit messages. + */ + warningLength: number | undefined; } interface QuickDiffProvider { diff --git a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts index 88c6377b3c46a08057eeb6eb0668a358bc3b11a5..7e728e798bddf7df3b5e0a974c3731ede619db42 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadSCM.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadSCM.ts @@ -391,4 +391,14 @@ export class MainThreadSCM implements MainThreadSCMShape { repository.input.placeholder = placeholder; } + + $setWarningLength(sourceControlHandle: number, warningLength: number): void { + const repository = this._repositories[sourceControlHandle]; + + if (!repository) { + return; + } + + repository.input.warningLength = warningLength; + } } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 111a4643be84edf11d8bdc0e8b830fdb139c9274..d3efe056b8dbd6aa440e961dedfbf8fb4189ccab 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -410,6 +410,7 @@ export interface MainThreadSCMShape extends IDisposable { $setInputBoxValue(sourceControlHandle: number, value: string): void; $setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void; + $setWarningLength(sourceControlHandle: number, warningLength: number): void; } export type DebugSessionUUID = string; diff --git a/src/vs/workbench/api/node/extHostSCM.ts b/src/vs/workbench/api/node/extHostSCM.ts index 9444ef007441510abd29a0ee148111b62bd50c80..2f8ea94d5b69fceb9ddc75290f6c85b6669336d4 100644 --- a/src/vs/workbench/api/node/extHostSCM.ts +++ b/src/vs/workbench/api/node/extHostSCM.ts @@ -110,7 +110,7 @@ function compareResourceStates(a: vscode.SourceControlResourceState, b: vscode.S return result; } -export class ExtHostSCMInputBox { +export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { private _value: string = ''; @@ -140,6 +140,17 @@ export class ExtHostSCMInputBox { this._placeholder = placeholder; } + private _warningLength: number | undefined; + + get warningLength(): number | undefined { + return this._warningLength; + } + + set warningLength(warningLength: number) { + this._proxy.$setWarningLength(this._sourceControlHandle, warningLength); + this._warningLength = warningLength; + } + constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) { // noop } diff --git a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts index 4530cff6727f2dd7ebe0b3d77ce5af8e851fda9e..982d059e3375987e8bdea894699f2846f13b30d5 100644 --- a/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts +++ b/src/vs/workbench/parts/scm/electron-browser/scmViewlet.ts @@ -45,7 +45,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IStorageService } from 'vs/platform/storage/common/storage'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IExtensionsViewlet, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/parts/extensions/common/extensions'; -import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; +import { IMessage, InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { Command } from 'vs/editor/common/modes'; @@ -753,7 +753,33 @@ export class RepositoryPanel extends ViewletPanel { this.inputBox.setPlaceHolder(placeholder); }; - this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { flexibleHeight: true }); + const validation = (text: string): IMessage => { + const warningLength = this.repository.input.warningLength; + if (warningLength === undefined) { + return { + content: localize('commitMessageInfo', "{0} characters", text.length), + type: MessageType.INFO + }; + } + + const charactersLeft = warningLength - text.length; + if (charactersLeft > 0) { + return { + content: localize('commitMessageCountdown', "{0} characters left", text.length), + type: MessageType.INFO + }; + } else { + return { + content: localize('commitMessageWarning', "{0} characters over", text.length), + type: MessageType.WARNING + }; + } + }; + + this.inputBox = new InputBox(this.inputBoxContainer, this.contextViewService, { + flexibleHeight: true, + validationOptions: { validation: validation } + }); this.disposables.push(attachInputBoxStyler(this.inputBox, this.themeService)); this.disposables.push(this.inputBox); diff --git a/src/vs/workbench/services/scm/common/scm.ts b/src/vs/workbench/services/scm/common/scm.ts index 78c1252f599ec96ccb1e9c3fc4624cf085476a09..b10ab4dc7cc54c3c0aef2526d49a49b5a3de4c55 100644 --- a/src/vs/workbench/services/scm/common/scm.ts +++ b/src/vs/workbench/services/scm/common/scm.ts @@ -74,6 +74,8 @@ export interface ISCMInput { placeholder: string; readonly onDidChangePlaceholder: Event; + + warningLength: number | undefined; } export interface ISCMRepository extends IDisposable { diff --git a/src/vs/workbench/services/scm/common/scmService.ts b/src/vs/workbench/services/scm/common/scmService.ts index db569fc7c5774046870874822deb2987c99d564e..a16e88a7436623b91f69d77396e46226e1cdf11e 100644 --- a/src/vs/workbench/services/scm/common/scmService.ts +++ b/src/vs/workbench/services/scm/common/scmService.ts @@ -39,6 +39,16 @@ class SCMInput implements ISCMInput { private _onDidChangePlaceholder = new Emitter(); get onDidChangePlaceholder(): Event { return this._onDidChangePlaceholder.event; } + + private _warningLength: number | undefined; + + get warningLength(): number | undefined { + return this._warningLength; + } + + set warningLength(warningLength: number) { + this._warningLength = warningLength; + } } class SCMRepository implements ISCMRepository { @@ -106,4 +116,4 @@ export class SCMService implements ISCMService { return repository; } -} \ No newline at end of file +}