Browse Source

Improves performance of blame annotations

main
Eric Amodio 6 years ago
parent
commit
cd3dbb3e6c
5 changed files with 39 additions and 32 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +1
    -1
      src/annotations/annotations.ts
  3. +1
    -1
      src/annotations/gutterBlameAnnotationProvider.ts
  4. +7
    -5
      src/git/formatters/formatter.ts
  5. +29
    -25
      src/system/string.ts

+ 1
- 0
CHANGELOG.md View File

@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Adds *Checkout Commit (via Terminal)* command (`gitlens.terminalCheckoutCommit`) to commit node(s) of the *GitLens* explorer — closes [#463](https://github.com/eamodio/vscode-gitlens/issues/463) - Adds *Checkout Commit (via Terminal)* command (`gitlens.terminalCheckoutCommit`) to commit node(s) of the *GitLens* explorer — closes [#463](https://github.com/eamodio/vscode-gitlens/issues/463)
### Changed ### Changed
- Improves performance of blame annotation rendering
- Changes commit search by sha to jump directly to the commit (if one is found), rather than having to click through to the commit - Changes commit search by sha to jump directly to the commit (if one is found), rather than having to click through to the commit
- Updates settings descriptions to better support the new settings editor in vscode - Updates settings descriptions to better support the new settings editor in vscode
- Changes *Rebase to Commit (via Terminal)* command (`gitlens.terminalRebaseCommit`) to apply to all commit node(s) of the *GitLens* explorer - Changes *Rebase to Commit (via Terminal)* command (`gitlens.terminalRebaseCommit`) to apply to all commit node(s) of the *GitLens* explorer

+ 1
- 1
src/annotations/annotations.ts View File

@ -288,7 +288,7 @@ export class Annotations {
if (width >= 0) { if (width >= 0) {
// Add the width of the template string (without tokens) // Add the width of the template string (without tokens)
width += Strings.width(Strings.interpolate(format, undefined));
width += Strings.getWidth(Strings.interpolate(format, undefined));
// If we have some width, add a bit of padding // If we have some width, add a bit of padding
if (width > 0) { if (width > 0) {
width += 3; width += 3;

+ 1
- 1
src/annotations/gutterBlameAnnotationProvider.ts View File

@ -68,7 +68,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
before: { before: {
...gutter.renderOptions!.before, ...gutter.renderOptions!.before,
contentText: GlyphChars.Space.repeat( contentText: GlyphChars.Space.repeat(
Strings.width(gutter.renderOptions!.before!.contentText!)
Strings.getWidth(gutter.renderOptions!.before!.contentText!)
) )
} }
}; };

+ 7
- 5
src/git/formatters/formatter.ts View File

@ -52,37 +52,39 @@ export abstract class Formatter
let max = options.truncateTo; let max = options.truncateTo;
const width = Strings.width(s);
if (max === undefined) { if (max === undefined) {
if (this.collapsableWhitespace === 0) return s; if (this.collapsableWhitespace === 0) return s;
const width = Strings.getWidth(s);
// If we have left over whitespace make sure it gets re-added // If we have left over whitespace make sure it gets re-added
const diff = this.collapsableWhitespace - width; const diff = this.collapsableWhitespace - width;
this.collapsableWhitespace = 0; this.collapsableWhitespace = 0;
if (diff <= 0) return s; if (diff <= 0) return s;
if (options.truncateTo === undefined) return s; if (options.truncateTo === undefined) return s;
return Strings.padLeft(s, diff);
return Strings.padLeft(s, diff, undefined, width);
} }
max += this.collapsableWhitespace; max += this.collapsableWhitespace;
this.collapsableWhitespace = 0; this.collapsableWhitespace = 0;
const width = Strings.getWidth(s);
const diff = max - width; const diff = max - width;
if (diff > 0) { if (diff > 0) {
if (options.collapseWhitespace) { if (options.collapseWhitespace) {
this.collapsableWhitespace = diff; this.collapsableWhitespace = diff;
} }
if (options.padDirection === 'left') return Strings.padLeft(s, max);
if (options.padDirection === 'left') return Strings.padLeft(s, max, undefined, width);
if (options.collapseWhitespace) { if (options.collapseWhitespace) {
max -= diff; max -= diff;
} }
return Strings.padRight(s, max);
return Strings.padRight(s, max, undefined, width);
} }
if (diff < 0) return Strings.truncate(s, max);
if (diff < 0) return Strings.truncate(s, max, undefined, width);
return s; return s;
} }

+ 29
- 25
src/system/string.ts View File

@ -74,37 +74,37 @@ export namespace Strings {
return `${before === 0 ? '' : padding.repeat(before)}${s}${after === 0 ? '' : padding.repeat(after)}`; return `${before === 0 ? '' : padding.repeat(before)}${s}${after === 0 ? '' : padding.repeat(after)}`;
} }
export function padLeft(s: string, padTo: number, padding: string = '\u00a0') {
const diff = padTo - width(s);
export function padLeft(s: string, padTo: number, padding: string = '\u00a0', width?: number) {
const diff = padTo - (width || getWidth(s));
return diff <= 0 ? s : padding.repeat(diff) + s; return diff <= 0 ? s : padding.repeat(diff) + s;
} }
export function padLeftOrTruncate(s: string, max: number, padding?: string) {
const len = width(s);
if (len < max) return padLeft(s, max, padding);
if (len > max) return truncate(s, max);
export function padLeftOrTruncate(s: string, max: number, padding?: string, width?: number) {
width = width || getWidth(s);
if (width < max) return padLeft(s, max, padding, width);
if (width > max) return truncate(s, max, undefined, width);
return s; return s;
} }
export function padRight(s: string, padTo: number, padding: string = '\u00a0') {
const diff = padTo - width(s);
export function padRight(s: string, padTo: number, padding: string = '\u00a0', width?: number) {
const diff = padTo - (width || getWidth(s));
return diff <= 0 ? s : s + padding.repeat(diff); return diff <= 0 ? s : s + padding.repeat(diff);
} }
export function padOrTruncate(s: string, max: number, padding?: string) {
export function padOrTruncate(s: string, max: number, padding?: string, width?: number) {
const left = max < 0; const left = max < 0;
max = Math.abs(max); max = Math.abs(max);
const len = width(s);
if (len < max) return left ? padLeft(s, max, padding) : padRight(s, max, padding);
if (len > max) return truncate(s, max);
width = width || getWidth(s);
if (width < max) return left ? padLeft(s, max, padding, width) : padRight(s, max, padding, width);
if (width > max) return truncate(s, max, undefined, width);
return s; return s;
} }
export function padRightOrTruncate(s: string, max: number, padding?: string) {
const len = width(s);
if (len < max) return padRight(s, max, padding);
if (len > max) return truncate(s, max);
export function padRightOrTruncate(s: string, max: number, padding?: string, width?: number) {
width = width || getWidth(s);
if (width < max) return padRight(s, max, padding, width);
if (width > max) return truncate(s, max);
return s; return s;
} }
@ -122,18 +122,18 @@ export namespace Strings {
.digest(encoding); .digest(encoding);
} }
export function truncate(s: string, truncateTo: number, ellipsis: string = '\u2026') {
export function truncate(s: string, truncateTo: number, ellipsis: string = '\u2026', width?: number) {
if (!s) return s; if (!s) return s;
const len = width(s);
if (len <= truncateTo) return s;
if (len === s.length) return `${s.substring(0, truncateTo - 1)}${ellipsis}`;
width = width || getWidth(s);
if (width <= truncateTo) return s;
if (width === s.length) return `${s.substring(0, truncateTo - 1)}${ellipsis}`;
// Skip ahead to start as far as we can by assuming all the double-width characters won't be truncated // Skip ahead to start as far as we can by assuming all the double-width characters won't be truncated
let chars = Math.floor(truncateTo / (len / s.length));
let count = width(s.substring(0, chars));
let chars = Math.floor(truncateTo / (width / s.length));
let count = getWidth(s.substring(0, chars));
while (count < truncateTo) { while (count < truncateTo) {
count += width(s[chars++]);
count += getWidth(s[chars++]);
} }
if (count >= truncateTo) { if (count >= truncateTo) {
@ -144,9 +144,13 @@ export namespace Strings {
} }
const ansiRegex = /[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))/g; const ansiRegex = /[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))/g;
const containsNonAsciiRegex = /[^\x20-\x7F\u00a0\u2026]/;
export function width(s: string): number {
if (!s || s.length === 0) return 0;
export function getWidth(s: string): number {
if (s == null || s.length === 0) return 0;
// Shortcut to avoid needless string `RegExp`s, replacements, and allocations
if (!containsNonAsciiRegex.test(s)) return s.length;
s = s.replace(ansiRegex, ''); s = s.replace(ansiRegex, '');

Loading…
Cancel
Save