scorpion-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Table Rendering Utility
3
+ * Creates beautiful ASCII tables for terminal display
4
+ */
5
+
6
+ import { colors, chalk } from './formatter.js';
7
+
8
+ /**
9
+ * Render a table
10
+ * @param {Array} data - Array of objects
11
+ * @param {Object} options - Table options
12
+ */
13
+ export function renderTable(data, options = {}) {
14
+ const {
15
+ headers = null,
16
+ maxWidth = 100,
17
+ compact = false
18
+ } = options;
19
+
20
+ if (!data || data.length === 0) {
21
+ console.log(colors.dim(' (No data)'));
22
+ return;
23
+ }
24
+
25
+ // Auto-detect headers from first object
26
+ const keys = headers || Object.keys(data[0]);
27
+
28
+ // Calculate column widths
29
+ const columnWidths = {};
30
+ for (const key of keys) {
31
+ columnWidths[key] = Math.max(
32
+ key.length,
33
+ ...data.map(row => String(row[key] || '').length)
34
+ );
35
+ // Cap at reasonable width
36
+ columnWidths[key] = Math.min(columnWidths[key], 40);
37
+ }
38
+
39
+ // Top border
40
+ const topBorder = ' ┌' + keys.map(key => '─'.repeat(columnWidths[key] + 2)).join('┬') + '┐';
41
+ console.log(colors.dim(topBorder));
42
+
43
+ // Header row
44
+ const headerRow = ' │ ' + keys.map(key => {
45
+ const padded = key.padEnd(columnWidths[key]);
46
+ return chalk.bold.cyan(padded);
47
+ }).join(' │ ') + ' │';
48
+ console.log(headerRow);
49
+
50
+ // Header separator
51
+ const headerSep = ' ├' + keys.map(key => '─'.repeat(columnWidths[key] + 2)).join('┼') + '┤';
52
+ console.log(colors.dim(headerSep));
53
+
54
+ // Data rows
55
+ for (let i = 0; i < data.length; i++) {
56
+ const row = data[i];
57
+ const rowStr = ' │ ' + keys.map(key => {
58
+ let value = String(row[key] || '');
59
+ // Truncate if too long
60
+ if (value.length > columnWidths[key]) {
61
+ value = value.slice(0, columnWidths[key] - 3) + '...';
62
+ }
63
+ return value.padEnd(columnWidths[key]);
64
+ }).join(' │ ') + ' │';
65
+
66
+ console.log(rowStr);
67
+
68
+ // Row separator (optional)
69
+ if (!compact && i < data.length - 1) {
70
+ const rowSep = ' ├' + keys.map(key => '─'.repeat(columnWidths[key] + 2)).join('┼') + '┤';
71
+ console.log(colors.dim(rowSep));
72
+ }
73
+ }
74
+
75
+ // Bottom border
76
+ const bottomBorder = ' └' + keys.map(key => '─'.repeat(columnWidths[key] + 2)).join('┴') + '┘';
77
+ console.log(colors.dim(bottomBorder));
78
+ }
79
+
80
+ /**
81
+ * Render a simple key-value table
82
+ * @param {Object} data - Object with key-value pairs
83
+ */
84
+ export function renderKeyValueTable(data) {
85
+ if (!data || Object.keys(data).length === 0) {
86
+ console.log(colors.dim(' (No data)'));
87
+ return;
88
+ }
89
+
90
+ const entries = Object.entries(data);
91
+ const maxKeyLength = Math.max(...entries.map(([key]) => key.length));
92
+
93
+ console.log(colors.dim(' ┌' + '─'.repeat(maxKeyLength + 2) + '┬' + '─'.repeat(40) + '┐'));
94
+
95
+ for (let i = 0; i < entries.length; i++) {
96
+ const [key, value] = entries[i];
97
+ const paddedKey = key.padEnd(maxKeyLength);
98
+ let valueStr = String(value);
99
+
100
+ // Truncate long values
101
+ if (valueStr.length > 38) {
102
+ valueStr = valueStr.slice(0, 35) + '...';
103
+ }
104
+ valueStr = valueStr.padEnd(38);
105
+
106
+ const row = ` │ ${chalk.bold.cyan(paddedKey)} │ ${valueStr} │`;
107
+ console.log(row);
108
+
109
+ if (i < entries.length - 1) {
110
+ console.log(colors.dim(' ├' + '─'.repeat(maxKeyLength + 2) + '┼' + '─'.repeat(40) + '┤'));
111
+ }
112
+ }
113
+
114
+ console.log(colors.dim(' └' + '─'.repeat(maxKeyLength + 2) + '┴' + '─'.repeat(40) + '┘'));
115
+ }
116
+
117
+ /**
118
+ * Render a compact list
119
+ * @param {Array} items - Array of strings or objects
120
+ * @param {Object} options - Options
121
+ */
122
+ export function renderList(items, options = {}) {
123
+ const {
124
+ numbered = false,
125
+ icon = '•',
126
+ color = colors.white
127
+ } = options;
128
+
129
+ if (!items || items.length === 0) {
130
+ console.log(colors.dim(' (No items)'));
131
+ return;
132
+ }
133
+
134
+ for (let i = 0; i < items.length; i++) {
135
+ const item = typeof items[i] === 'string' ? items[i] : String(items[i]);
136
+ const prefix = numbered ? colors.dim(` ${i + 1}. `) : colors.dim(` ${icon} `);
137
+ console.log(prefix + color(item));
138
+ }
139
+ }
140
+
141
+ export default {
142
+ renderTable,
143
+ renderKeyValueTable,
144
+ renderList
145
+ };