-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d136067
commit 37fc2f4
Showing
2 changed files
with
164 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,4 @@ | ||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. | ||
import { isInvalidDate, isTypedArray, TypedArray } from "https://raw.githubusercontent.com/denoland/deno/3314b463215a8e59ec46d722adb70a22cd3ef832/cli/js/web/util.ts"; | ||
import { cliTable } from "https://raw.githubusercontent.com/denoland/deno/3314b463215a8e59ec46d722adb70a22cd3ef832/cli/js/web/console_table.ts"; | ||
|
||
import { | ||
stripColor, | ||
|
@@ -12,6 +10,7 @@ import { | |
magenta, | ||
bold, | ||
} from "https://deno.land/[email protected]/fmt/colors.ts"; | ||
import { cliTable, isInvalidDate, isTypedArray , TypedArray} from "./utils/table.ts"; | ||
|
||
type ConsoleContext = Set<unknown>; | ||
type InspectOptions = Partial<{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
|
||
function hasOwnProperty(obj: unknown, v: PropertyKey): boolean { | ||
if (obj == null) { | ||
return false; | ||
} | ||
return Object.prototype.hasOwnProperty.call(obj, v); | ||
} | ||
|
||
const ANSI_PATTERN = new RegExp( | ||
[ | ||
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", | ||
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", | ||
].join("|"), | ||
"g" | ||
); | ||
|
||
function stripColor(string: string): string { | ||
return string.replace(ANSI_PATTERN, ""); | ||
} | ||
|
||
const tableChars = { | ||
middleMiddle: "─", | ||
rowMiddle: "┼", | ||
topRight: "┐", | ||
topLeft: "┌", | ||
leftMiddle: "├", | ||
topMiddle: "┬", | ||
bottomRight: "┘", | ||
bottomLeft: "└", | ||
bottomMiddle: "┴", | ||
rightMiddle: "┤", | ||
left: "│ ", | ||
right: " │", | ||
middle: " │ ", | ||
}; | ||
|
||
function isFullWidthCodePoint(code: number): boolean { | ||
// Code points are partially derived from: | ||
// http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt | ||
return ( | ||
code >= 0x1100 && | ||
(code <= 0x115f || // Hangul Jamo | ||
code === 0x2329 || // LEFT-POINTING ANGLE BRACKET | ||
code === 0x232a || // RIGHT-POINTING ANGLE BRACKET | ||
// CJK Radicals Supplement .. Enclosed CJK Letters and Months | ||
(code >= 0x2e80 && code <= 0x3247 && code !== 0x303f) || | ||
// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A | ||
(code >= 0x3250 && code <= 0x4dbf) || | ||
// CJK Unified Ideographs .. Yi Radicals | ||
(code >= 0x4e00 && code <= 0xa4c6) || | ||
// Hangul Jamo Extended-A | ||
(code >= 0xa960 && code <= 0xa97c) || | ||
// Hangul Syllables | ||
(code >= 0xac00 && code <= 0xd7a3) || | ||
// CJK Compatibility Ideographs | ||
(code >= 0xf900 && code <= 0xfaff) || | ||
// Vertical Forms | ||
(code >= 0xfe10 && code <= 0xfe19) || | ||
// CJK Compatibility Forms .. Small Form Variants | ||
(code >= 0xfe30 && code <= 0xfe6b) || | ||
// Halfwidth and Fullwidth Forms | ||
(code >= 0xff01 && code <= 0xff60) || | ||
(code >= 0xffe0 && code <= 0xffe6) || | ||
// Kana Supplement | ||
(code >= 0x1b000 && code <= 0x1b001) || | ||
// Enclosed Ideographic Supplement | ||
(code >= 0x1f200 && code <= 0x1f251) || | ||
// Miscellaneous Symbols and Pictographs 0x1f300 - 0x1f5ff | ||
// Emoticons 0x1f600 - 0x1f64f | ||
(code >= 0x1f300 && code <= 0x1f64f) || | ||
// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane | ||
(code >= 0x20000 && code <= 0x3fffd)) | ||
); | ||
} | ||
|
||
function getStringWidth(str: string): number { | ||
str = stripColor(str).normalize("NFC"); | ||
let width = 0; | ||
|
||
for (const ch of str) { | ||
width += isFullWidthCodePoint(ch.codePointAt(0)!) ? 2 : 1; | ||
} | ||
|
||
return width; | ||
} | ||
|
||
function renderRow(row: string[], columnWidths: number[]): string { | ||
let out = tableChars.left; | ||
for (let i = 0; i < row.length; i++) { | ||
const cell = row[i]; | ||
const len = getStringWidth(cell); | ||
const needed = (columnWidths[i] - len) / 2; | ||
// round(needed) + ceil(needed) will always add up to the amount | ||
// of spaces we need while also left justifying the output. | ||
out += `${" ".repeat(needed)}${cell}${" ".repeat(Math.ceil(needed))}`; | ||
if (i !== row.length - 1) { | ||
out += tableChars.middle; | ||
} | ||
} | ||
out += tableChars.right; | ||
return out; | ||
} | ||
|
||
export function cliTable(head: string[], columns: string[][]): string { | ||
const rows: string[][] = []; | ||
const columnWidths = head.map((h: string): number => getStringWidth(h)); | ||
const longestColumn = columns.reduce( | ||
(n: number, a: string[]): number => Math.max(n, a.length), | ||
0 | ||
); | ||
|
||
for (let i = 0; i < head.length; i++) { | ||
const column = columns[i]; | ||
for (let j = 0; j < longestColumn; j++) { | ||
if (rows[j] === undefined) { | ||
rows[j] = []; | ||
} | ||
const value = (rows[j][i] = hasOwnProperty(column, j) ? column[j] : ""); | ||
const width = columnWidths[i] || 0; | ||
const counted = getStringWidth(value); | ||
columnWidths[i] = Math.max(width, counted); | ||
} | ||
} | ||
|
||
const divider = columnWidths.map((i: number): string => | ||
tableChars.middleMiddle.repeat(i + 2) | ||
); | ||
|
||
let result = | ||
`${tableChars.topLeft}${divider.join(tableChars.topMiddle)}` + | ||
`${tableChars.topRight}\n${renderRow(head, columnWidths)}\n` + | ||
`${tableChars.leftMiddle}${divider.join(tableChars.rowMiddle)}` + | ||
`${tableChars.rightMiddle}\n`; | ||
|
||
for (const row of rows) { | ||
result += `${renderRow(row, columnWidths)}\n`; | ||
} | ||
|
||
result += | ||
`${tableChars.bottomLeft}${divider.join(tableChars.bottomMiddle)}` + | ||
tableChars.bottomRight; | ||
|
||
return result; | ||
} | ||
|
||
export function isInvalidDate(x: Date): boolean { | ||
return isNaN(x.getTime()); | ||
} | ||
|
||
export type TypedArray = | ||
| Int8Array | ||
| Uint8Array | ||
| Uint8ClampedArray | ||
| Int16Array | ||
| Uint16Array | ||
| Int32Array | ||
| Uint32Array | ||
| Float32Array | ||
| Float64Array; | ||
|
||
export function isTypedArray(x: unknown): x is TypedArray { | ||
return ArrayBuffer.isView(x) && !(x instanceof DataView); | ||
} |