Fixes #107 - Double-byte characters break blame layout

This commit is contained in:
Eric Amodio
2017-07-27 00:56:33 -04:00
parent 68a42fd0c7
commit 9d9c3181f7
4 changed files with 56 additions and 17 deletions

39
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "gitlens", "name": "gitlens",
"version": "4.3.1", "version": "4.3.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@@ -16,7 +16,7 @@
"integrity": "sha1-qjuL2ivlErGuCgV7lC6GnDcKVWk=", "integrity": "sha1-qjuL2ivlErGuCgV7lC6GnDcKVWk=",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/node": "8.0.14" "@types/node": "8.0.17"
} }
}, },
"@types/mocha": { "@types/mocha": {
@@ -26,9 +26,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "8.0.14", "version": "8.0.17",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.14.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.17.tgz",
"integrity": "sha512-lrtgE/5FeTdcuxgsDbLUIFJ33dTp4TkbKkTDZt/ueUMeqmGYqJRQd908q5Yj9EzzWSMonEhMr1q/CQlgVGEt4w==", "integrity": "sha512-iq0LxqG6P9GV/2bVA2AQAQ58NvneLdVDVs9dJ+88Jk6gDK9opNC0SushdYqlAyvxo0dk0NJjTKCenq/l3AKtuA==",
"dev": true "dev": true
}, },
"@types/tmp": { "@types/tmp": {
@@ -1319,6 +1319,11 @@
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true "dev": true
}, },
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"is-glob": { "is-glob": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
@@ -2338,6 +2343,30 @@
"safe-buffer": "5.1.1" "safe-buffer": "5.1.1"
} }
}, },
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": {
"is-fullwidth-code-point": "2.0.0",
"strip-ansi": "4.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "3.0.0"
}
}
}
},
"stringstream": { "stringstream": {
"version": "0.0.5", "version": "0.0.5",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",

View File

@@ -1546,13 +1546,14 @@
"lodash.once": "4.1.1", "lodash.once": "4.1.1",
"moment": "2.18.1", "moment": "2.18.1",
"spawn-rx": "2.0.11", "spawn-rx": "2.0.11",
"string-width": "2.1.1",
"tmp": "0.0.31" "tmp": "0.0.31"
}, },
"devDependencies": { "devDependencies": {
"@types/copy-paste": "1.1.30", "@types/copy-paste": "1.1.30",
"@types/iconv-lite": "0.0.1", "@types/iconv-lite": "0.0.1",
"@types/mocha": "2.2.41", "@types/mocha": "2.2.41",
"@types/node": "8.0.14", "@types/node": "8.0.17",
"@types/tmp": "0.0.33", "@types/tmp": "0.0.33",
"mocha": "3.4.2", "mocha": "3.4.2",
"tslint": "5.5.0", "tslint": "5.5.0",

View File

@@ -51,11 +51,12 @@ export abstract class Formatter<TItem = any, TOptions extends IFormatOptions = I
let max = options.truncateTo; let max = options.truncateTo;
const width = Strings.getWidth(s);
if (max === undefined) { if (max === undefined) {
if (this.collapsableWhitespace === 0) return s; if (this.collapsableWhitespace === 0) return 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 - s.length; const diff = this.collapsableWhitespace - width;
this.collapsableWhitespace = 0; this.collapsableWhitespace = 0;
if (diff <= 0) return s; if (diff <= 0) return s;
@@ -66,7 +67,7 @@ export abstract class Formatter<TItem = any, TOptions extends IFormatOptions = I
max += this.collapsableWhitespace; max += this.collapsableWhitespace;
this.collapsableWhitespace = 0; this.collapsableWhitespace = 0;
const diff = max - s.length; const diff = max - width;
if (diff > 0) { if (diff > 0) {
if (options.collapseWhitespace) { if (options.collapseWhitespace) {
this.collapsableWhitespace = diff; this.collapsableWhitespace = diff;

View File

@@ -1,11 +1,16 @@
'use strict'; 'use strict';
const _escapeRegExp = require('lodash.escaperegexp'); const _escapeRegExp = require('lodash.escaperegexp');
const stringWidth = require('string-width');
export namespace Strings { export namespace Strings {
export function escapeRegExp(s: string): string { export function escapeRegExp(s: string): string {
return _escapeRegExp(s); return _escapeRegExp(s);
} }
export function getWidth(s: string): number {
return stringWidth(s);
}
const TokenRegex = /\$\{([^|]*?)(?:\|(\d+)(\-|\?)?)?\}/g; const TokenRegex = /\$\{([^|]*?)(?:\|(\d+)(\-|\?)?)?\}/g;
const TokenSanitizeRegex = /\$\{(\w*?)(?:\W|\d)*?\}/g; const TokenSanitizeRegex = /\$\{(\w*?)(?:\W|\d)*?\}/g;
@@ -63,18 +68,19 @@ export namespace Strings {
} }
export function padLeft(s: string, padTo: number, padding: string = '\u00a0') { export function padLeft(s: string, padTo: number, padding: string = '\u00a0') {
const diff = padTo - s.length; const diff = padTo - getWidth(s);
return (diff <= 0) ? s : '\u00a0'.repeat(diff) + s; return (diff <= 0) ? s : '\u00a0'.repeat(diff) + s;
} }
export function padLeftOrTruncate(s: string, max: number, padding?: string) { export function padLeftOrTruncate(s: string, max: number, padding?: string) {
if (s.length < max) return padLeft(s, max, padding); const len = getWidth(s);
if (s.length > max) return truncate(s, max); if (len < max) return padLeft(s, max, padding);
if (len > max) return truncate(s, max);
return s; return s;
} }
export function padRight(s: string, padTo: number, padding: string = '\u00a0') { export function padRight(s: string, padTo: number, padding: string = '\u00a0') {
const diff = padTo - s.length; const diff = padTo - getWidth(s);
return (diff <= 0) ? s : s + '\u00a0'.repeat(diff); return (diff <= 0) ? s : s + '\u00a0'.repeat(diff);
} }
@@ -82,19 +88,21 @@ export namespace Strings {
const left = max < 0; const left = max < 0;
max = Math.abs(max); max = Math.abs(max);
if (s.length < max) return left ? padLeft(s, max, padding) : padRight(s, max, padding); const len = getWidth(s);
if (s.length > max) return truncate(s, max); if (len < max) return left ? padLeft(s, max, padding) : padRight(s, max, padding);
if (len > max) return truncate(s, max);
return s; return s;
} }
export function padRightOrTruncate(s: string, max: number, padding?: string) { export function padRightOrTruncate(s: string, max: number, padding?: string) {
if (s.length < max) return padRight(s, max, padding); const len = getWidth(s);
if (s.length > max) return truncate(s, max); if (len < max) return padRight(s, max, padding);
if (len > max) return truncate(s, max);
return s; return s;
} }
export function truncate(s: string, truncateTo?: number) { export function truncate(s: string, truncateTo?: number) {
if (!s || truncateTo === undefined || s.length <= truncateTo) return s; if (!s || truncateTo === undefined || getWidth(s) <= truncateTo) return s;
return `${s.substring(0, truncateTo - 1)}\u2026`; return `${s.substring(0, truncateTo - 1)}\u2026`;
} }
} }