Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
d6fdca1
logging prior commit messages
meganrogge Sep 28, 2020
c8f852e
Logging prior commit messages
meganrogge Sep 25, 2020
27149d5
Logging prior commit messages
meganrogge Sep 25, 2020
88a4531
now works in forward and backward directions
meganrogge Sep 28, 2020
e4ebf2c
reset index on empty input
meganrogge Sep 28, 2020
4fa9056
cleaning up code
meganrogge Sep 30, 2020
42a3422
introduce historyNavigator, working but not persisting on window reload
meganrogge Sep 30, 2020
bde00c2
introduce historyNavigator, working but not persisting on window reload
meganrogge Sep 30, 2020
f5d70f7
add history
meganrogge Sep 30, 2020
c364f2f
saves search entries on window reload but doesn't save last typed mes…
meganrogge Sep 30, 2020
3346e91
save input
meganrogge Oct 1, 2020
9f2003d
change where the save occurs
meganrogge Oct 12, 2020
c97e54f
working
meganrogge Oct 13, 2020
146fd7d
add remove last method
meganrogge Oct 13, 2020
bcc0a57
now replaces most recent input
meganrogge Oct 14, 2020
48db8f5
remove check for null value
meganrogge Oct 14, 2020
1ffa3cc
now at least lets you see most recent commit
meganrogge Oct 14, 2020
3bf2e46
before adding objects
meganrogge Oct 14, 2020
8af29be
add scmi value class
meganrogge Oct 15, 2020
1a527ba
add scmi value class
meganrogge Oct 15, 2020
3405e1c
new commit
meganrogge Oct 15, 2020
fe7f4ce
fix removal / insertion order
meganrogge Oct 15, 2020
adb870d
change function modifiers
meganrogge Oct 15, 2020
ed9012f
working correctly
meganrogge Oct 15, 2020
bd0f287
change conditional
meganrogge Oct 15, 2020
37573b1
undo inadvertant changes
meganrogge Oct 15, 2020
bbbb299
Update README.md
meganrogge Oct 15, 2020
d9382a8
fix tricky bug
meganrogge Oct 15, 2020
b8277dd
working and removed unnecessary conditional
meganrogge Oct 15, 2020
55c6f88
fix another bug
meganrogge Oct 15, 2020
3914a37
make elements private again
meganrogge Oct 16, 2020
116bb04
change order of save
meganrogge Oct 17, 2020
8527d56
now working as expected, about to add context keys
meganrogge Oct 17, 2020
f30b941
hook up context keys
meganrogge Oct 17, 2020
3429b56
save on shutdown
meganrogge Oct 18, 2020
415f3be
improve variable name
meganrogge Oct 18, 2020
a80d5f7
disable show prior/next commit when there's no history and ensure tha…
meganrogge Oct 18, 2020
65df40e
formatting
joaomoreno Oct 19, 2020
e6ab00a
add new history navigator
joaomoreno Oct 19, 2020
8f1862e
fix bad ==
joaomoreno Oct 19, 2020
38f1f47
rename scm input history methods
joaomoreno Oct 19, 2020
0aa94a5
adopt HistoryNavigator2 in SCMInput
joaomoreno Oct 19, 2020
c4d9e46
remove unnecessary method
joaomoreno Oct 19, 2020
ae59e8c
revert history.ts
joaomoreno Oct 19, 2020
44bdd44
:lipstick:
joaomoreno Oct 19, 2020
4f147e0
change size of history required to be valid
meganrogge Oct 19, 2020
ef19cff
revert change
meganrogge Oct 19, 2020
14b6f96
on reload, display latest input
meganrogge Oct 19, 2020
1e422e7
Merge branch 'master' into pr/107619
joaomoreno Oct 20, 2020
eaa2e81
remove rogue console.log
joaomoreno Oct 20, 2020
dba636c
fix issue with saving uncommitted message
joaomoreno Oct 20, 2020
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
92 changes: 92 additions & 0 deletions src/vs/base/common/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,95 @@ export class HistoryNavigator<T> implements INavigator<T> {
return elements;
}
}

interface HistoryNode<T> {
value: T;
previous: HistoryNode<T> | undefined;
next: HistoryNode<T> | undefined;
}

export class HistoryNavigator2<T> {

private head: HistoryNode<T>;
private tail: HistoryNode<T>;
private cursor: HistoryNode<T>;
private size: number;

constructor(history: readonly T[], private capacity: number = 10) {
if (history.length < 1) {
Copy link
Member

@joaomoreno joaomoreno Oct 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, my bad! 👍

throw new Error('not supported');
}

this.size = 1;
this.head = this.tail = this.cursor = {
value: history[0],
previous: undefined,
next: undefined
};

for (let i = 1; i < history.length; i++) {
this.add(history[i]);
}
}

add(value: T): void {
const node: HistoryNode<T> = {
value,
previous: this.tail,
next: undefined
};

this.tail.next = node;
this.tail = node;
this.cursor = this.tail;
this.size++;

while (this.size > this.capacity) {
this.head = this.head.next!;
this.head.previous = undefined;
this.size--;
}
}

replaceLast(value: T): void {
this.tail.value = value;
}

isAtEnd(): boolean {
return this.cursor === this.tail;
}

current(): T {
return this.cursor.value;
}

previous(): T {
if (this.cursor.previous) {
this.cursor = this.cursor.previous;
}

return this.cursor.value;
}

next(): T {
if (this.cursor.next) {
this.cursor = this.cursor.next;
}

return this.cursor.value;
}

resetCursor(): T {
this.cursor = this.tail;
return this.cursor.value;
}

*[Symbol.iterator](): Iterator<T> {
let node: HistoryNode<T> | undefined = this.head;

while (node) {
yield node.value;
node = node.next;
}
}
}
2 changes: 1 addition & 1 deletion src/vs/workbench/api/browser/mainThreadSCM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ export class MainThreadSCM implements MainThreadSCMShape {
return;
}

repository.input.value = value;
repository.input.setValue(value, false);
}

$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void {
Expand Down
29 changes: 28 additions & 1 deletion src/vs/workbench/contrib/scm/browser/scm.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
if (!repository || !repository.provider.acceptInputCommand) {
return Promise.resolve(null);
}

const id = repository.provider.acceptInputCommand.id;
const args = repository.provider.acceptInputCommand.arguments;

Expand All @@ -230,6 +229,34 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'scm.viewNextCommit',
description: { description: localize('scm view next commit', "SCM: View Next Commit"), args: [] },
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.has('scmInputIsInLastLine'),
primary: KeyCode.DownArrow,
handler: accessor => {
const contextKeyService = accessor.get(IContextKeyService);
const context = contextKeyService.getContext(document.activeElement);
const repository = context.getValue<ISCMRepository>('scmRepository');
repository?.input.showNextHistoryValue();
}
});

KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'scm.viewPriorCommit',
description: { description: localize('scm view prior commit', "SCM: View Prior Commit"), args: [] },
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.has('scmInputIsInFirstLine'),
primary: KeyCode.UpArrow,
handler: accessor => {
const contextKeyService = accessor.get(IContextKeyService);
const context = contextKeyService.getContext(document.activeElement);
const repository = context.getValue<ISCMRepository>('scmRepository');
repository?.input.showPreviousHistoryValue();
}
});

CommandsRegistry.registerCommand('scm.openInTerminal', async (accessor, provider: ISCMProvider) => {
if (!provider || !provider.rootUri) {
return;
Expand Down
16 changes: 14 additions & 2 deletions src/vs/workbench/contrib/scm/browser/scmViewPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1307,14 +1307,14 @@ class SCMInputWidget extends Disposable {
if (value === textModel.getValue()) { // circuit breaker
return;
}
textModel.setValue(input.value);
textModel.setValue(value);
this.inputEditor.setPosition(textModel.getFullModelRange().getEndPosition());
}));

// Keep API in sync with model, update placeholder visibility and validate
const updatePlaceholderVisibility = () => this.placeholderTextContainer.classList.toggle('hidden', textModel.getValueLength() > 0);
this.repositoryDisposables.add(textModel.onDidChangeContent(() => {
input.value = textModel.getValue();
input.setValue(textModel.getValue(), true);
updatePlaceholderVisibility();
triggerValidation();
}));
Expand Down Expand Up @@ -1433,6 +1433,18 @@ class SCMInputWidget extends Disposable {
this.validationDisposable.dispose();
}));

const firstLineKey = contextKeyService2.createKey('scmInputIsInFirstLine', false);
const lastLineKey = contextKeyService2.createKey('scmInputIsInLastLine', false);

this._register(this.inputEditor.onDidChangeCursorPosition(({ position }) => {
const viewModel = this.inputEditor._getViewModel()!;
const lastLineNumber = viewModel.getLineCount();
const viewPosition = viewModel.coordinatesConverter.convertModelPositionToViewPosition(position);

firstLineKey.set(viewPosition.lineNumber === 1);
lastLineKey.set(viewPosition.lineNumber === lastLineNumber);
}));

const onInputFontFamilyChanged = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('scm.inputFontFamily'));
this._register(onInputFontFamilyChanged(() => this.inputEditor.updateOptions({ fontFamily: this.getInputEditorFontFamily() })));

Expand Down
6 changes: 5 additions & 1 deletion src/vs/workbench/contrib/scm/common/scm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ export interface IInputValidator {
export interface ISCMInput {
readonly repository: ISCMRepository;

value: string;
readonly value: string;
setValue(value: string, fromKeyboard: boolean): void;
readonly onDidChange: Event<string>;

placeholder: string;
Expand All @@ -97,6 +98,9 @@ export interface ISCMInput {

visible: boolean;
readonly onDidChangeVisibility: Event<boolean>;

showNextHistoryValue(): void;
showPreviousHistoryValue(): void;
}

export interface ISCMRepository extends IDisposable {
Expand Down
81 changes: 62 additions & 19 deletions src/vs/workbench/contrib/scm/common/scmService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ISCMService, ISCMProvider, ISCMInput, ISCMRepository, IInputValidator } from './scm';
import { ILogService } from 'vs/platform/log/common/log';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { HistoryNavigator2 } from 'vs/base/common/history';

class SCMInput implements ISCMInput {

Expand All @@ -18,21 +19,6 @@ class SCMInput implements ISCMInput {
return this._value;
}

set value(value: string) {
if (value === this._value) {
return;
}

this._value = value;

if (this.repository.provider.rootUri) {
const key = `scm/input:${this.repository.provider.label}:${this.repository.provider.rootUri.path}`;
this.storageService.store(key, value, StorageScope.WORKSPACE);
}

this._onDidChange.fire(value);
}

private readonly _onDidChange = new Emitter<string>();
readonly onDidChange: Event<string> = this._onDidChange.event;

Expand Down Expand Up @@ -79,14 +65,71 @@ class SCMInput implements ISCMInput {
private readonly _onDidChangeValidateInput = new Emitter<void>();
readonly onDidChangeValidateInput: Event<void> = this._onDidChangeValidateInput.event;

private historyNavigator: HistoryNavigator2<string>;

constructor(
readonly repository: ISCMRepository,
@IStorageService private storageService: IStorageService
) {
if (this.repository.provider.rootUri) {
const key = `scm/input:${this.repository.provider.label}:${this.repository.provider.rootUri.path}`;
this._value = this.storageService.get(key, StorageScope.WORKSPACE, '');
const historyKey = `scm/input:${this.repository.provider.label}:${this.repository.provider.rootUri?.path}`;
let history: string[] | undefined;
let rawHistory = this.storageService.get(historyKey, StorageScope.WORKSPACE, '');

if (rawHistory) {
try {
history = JSON.parse(rawHistory);
} catch {
// noop
}
}

if (!history || history.length === 0) {
history = [this._value];
} else {
this._value = history[history.length - 1];
}

this.historyNavigator = new HistoryNavigator2(history, 50);

this.storageService.onWillSaveState(e => {
if (e.reason === WillSaveStateReason.SHUTDOWN) {
if (this.historyNavigator.isAtEnd()) {
this.historyNavigator.replaceLast(this._value);
}

if (this.repository.provider.rootUri) {
this.storageService.store(historyKey, JSON.stringify([...this.historyNavigator]), StorageScope.WORKSPACE);
}
}
});
}

setValue(value: string, transient: boolean) {
if (value === this._value) {
return;
}

if (!transient) {
this.historyNavigator.replaceLast(this._value);
this.historyNavigator.add(value);
}

this._value = value;
this._onDidChange.fire(value);
}

showNextHistoryValue(): void {
const value = this.historyNavigator.next();
this.setValue(value, true);
}

showPreviousHistoryValue(): void {
if (this.historyNavigator.isAtEnd()) {
this.historyNavigator.replaceLast(this._value);
}

const value = this.historyNavigator.previous();
this.setValue(value, true);
}
}

Expand Down