diff --git a/CHANGELOG.md b/CHANGELOG.md index a0bc2b5..dcc8765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) ### 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 - 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 diff --git a/src/annotations/annotations.ts b/src/annotations/annotations.ts index f28b13e..a215c9a 100644 --- a/src/annotations/annotations.ts +++ b/src/annotations/annotations.ts @@ -288,7 +288,7 @@ export class Annotations { if (width >= 0) { // 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 (width > 0) { width += 3; diff --git a/src/annotations/gutterBlameAnnotationProvider.ts b/src/annotations/gutterBlameAnnotationProvider.ts index 2a129dc..4467844 100644 --- a/src/annotations/gutterBlameAnnotationProvider.ts +++ b/src/annotations/gutterBlameAnnotationProvider.ts @@ -68,7 +68,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { before: { ...gutter.renderOptions!.before, contentText: GlyphChars.Space.repeat( - Strings.width(gutter.renderOptions!.before!.contentText!) + Strings.getWidth(gutter.renderOptions!.before!.contentText!) ) } }; diff --git a/src/git/formatters/formatter.ts b/src/git/formatters/formatter.ts index fa6d5c2..49857b3 100644 --- a/src/git/formatters/formatter.ts +++ b/src/git/formatters/formatter.ts @@ -52,37 +52,39 @@ export abstract class Formatter 0) { if (options.collapseWhitespace) { 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) { 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; } diff --git a/src/system/string.ts b/src/system/string.ts index 696e258..c0e8156 100644 --- a/src/system/string.ts +++ b/src/system/string.ts @@ -74,37 +74,37 @@ export namespace Strings { 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; } - 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; } - 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); } - export function padOrTruncate(s: string, max: number, padding?: string) { + export function padOrTruncate(s: string, max: number, padding?: string, width?: number) { const left = max < 0; 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; } - 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; } @@ -122,18 +122,18 @@ export namespace Strings { .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; - 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 - 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) { - count += width(s[chars++]); + count += getWidth(s[chars++]); } 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 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, '');