Browse Source

Removes lookbehind & improves input help

main
Eric Amodio 1 year ago
parent
commit
e1bc0d67db
1 changed files with 33 additions and 51 deletions
  1. +33
    -51
      src/webviews/apps/shared/components/search/search-input.ts

+ 33
- 51
src/webviews/apps/shared/components/search/search-input.ts View File

@ -1,5 +1,6 @@
import { attr, css, customElement, FASTElement, html, observable, ref, volatile, when } from '@microsoft/fast-element';
import type { SearchQuery } from '../../../../../git/search';
import type { Deferrable } from '../../../../../system/function';
import { debounce } from '../../../../../system/function';
import '../code-icon';
import type { PopMenu } from '../overlays/pop-menu';
@ -18,7 +19,6 @@ export type SearchOperators =
export type HelpTypes = 'message:' | 'author:' | 'commit:' | 'file:' | 'change:';
const searchRegex = /(?:^|(?<= ))(=:|message:|@:|author:|#:|commit:|\?:|file:|~:|change:)/gi;
const operatorsHelpMap = new Map<SearchOperators, HelpTypes>([
['=:', 'message:'],
['message:', 'message:'],
@ -479,29 +479,47 @@ export class SearchInput extends FASTElement {
this.debouncedEmitSearch();
}
private _updateHelpTextDebounced: Deferrable<SearchInput['updateHelpText']> | undefined;
updateHelpText() {
if (this.input == null || this.value === '' || !this.value.includes(':') || this.input.selectionStart == null) {
this.helpType = undefined;
return;
if (this._updateHelpTextDebounced == null) {
this._updateHelpTextDebounced = debounce(this.updateHelpTextCore.bind(this), 200);
}
const query = getSubstringFromCursor(this.value, this.input.selectionStart, this.input.selectionEnd);
const helpOperator = query ? getHelpOperatorsFromQuery(query) : undefined;
// console.log('updateHelpText operator', helpOperator, 'start', this.input.selectionStart, 'end', this.input.selectionEnd);
this.helpType = helpOperator;
this._updateHelpTextDebounced();
}
debouncedUpdateHelpText = debounce(this.updateHelpText.bind(this), 200);
updateHelpTextCore() {
const cursor = this.input?.selectionStart;
const value = this.value;
if (cursor != null && value.length !== 0 && !value.includes(':')) {
const regex =
/(?:^|[\b\s]*)((=:|message:|@:|author:|#:|commit:|\?:|file:|~:|change:)(?:"[^"]*"?|\w*))(?:$|[\b\s])/gi;
let match;
do {
match = regex.exec(value);
if (match == null) break;
const [, part, op] = match;
console.log('updateHelpText', cursor, match.index, match.index + part.trim().length, match);
if (cursor > match.index && cursor <= match.index + part.trim().length) {
this.helpType = operatorsHelpMap.get(op as SearchOperators);
return;
}
} while (true);
}
this.helpType = undefined;
}
handleInputClick(_e: MouseEvent) {
this.debouncedUpdateHelpText();
this.updateHelpText();
}
handleInput(e: InputEvent) {
const value = (e.target as HTMLInputElement)?.value;
this.value = value;
this.debouncedUpdateHelpText();
this.updateHelpText();
this.debouncedEmitSearch();
}
@ -521,7 +539,7 @@ export class SearchInput extends FASTElement {
}
handleKeyup(_e: KeyboardEvent) {
this.debouncedUpdateHelpText();
this.updateHelpText();
}
handleShortcutKeys(e: KeyboardEvent) {
@ -542,7 +560,7 @@ export class SearchInput extends FASTElement {
const value = this.searchHistory[nextPos];
if (value !== this.value) {
this.value = value;
this.debouncedUpdateHelpText();
this.updateHelpText();
this.debouncedEmitSearch();
}
}
@ -554,7 +572,7 @@ export class SearchInput extends FASTElement {
handleInsertToken(token: string) {
this.value += `${this.value.length > 0 ? ' ' : ''}${token}`;
window.requestAnimationFrame(() => {
this.debouncedUpdateHelpText();
this.updateHelpText();
// `@me` can be searched right away since it doesn't need additional text
if (token === '@me') {
this.debouncedEmitSearch();
@ -592,39 +610,3 @@ export class SearchInput extends FASTElement {
this.searchHistoryPos = this.searchHistory.length - 1;
}
}
function getSubstringFromCursor(value: string, start: number | null, end: number | null): string | undefined {
if (value === '' || !value.includes(':') || start === null) {
return;
}
const len = value.length;
const cursor = end === null ? start : Math.max(start, end);
if (cursor === len) {
return value;
}
let query = cursor === 0 ? '' : value.substring(0, cursor);
if (cursor < len - 1) {
const next = value.charAt(cursor);
if (next !== ' ') {
// If the cursor is touching a word, include that word in the query
const match = /^[^\s]+/gi.exec(value.substring(cursor));
if (match !== null) {
query += match[0];
}
}
}
return query;
}
function getHelpOperatorsFromQuery(value: string): HelpTypes | undefined {
const matches = value.match(searchRegex);
if (matches === null) {
return;
}
const operator = operatorsHelpMap.get(matches.pop() as SearchOperators);
return operator;
}

Loading…
Cancel
Save