mepcli 1.0.1 → 1.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.
- package/dist/highlight.d.ts +6 -0
- package/dist/highlight.js +133 -28
- package/dist/prompts/code.js +46 -31
- package/dist/types.d.ts +1 -1
- package/dist/utils.js +1 -1
- package/package.json +1 -1
package/dist/highlight.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
1
|
export declare function highlightJson(json: string): string;
|
|
2
|
+
export declare function highlightEnv(env: string): string;
|
|
3
|
+
export declare function highlightToml(toml: string): string;
|
|
4
|
+
export declare function highlightCsv(csv: string): string;
|
|
5
|
+
export declare function highlightShell(script: string): string;
|
|
6
|
+
export declare function highlightProperties(props: string): string;
|
|
7
|
+
export declare function highlight(code: string, language: string): string;
|
package/dist/highlight.js
CHANGED
|
@@ -1,39 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.highlightJson = highlightJson;
|
|
4
|
+
exports.highlightEnv = highlightEnv;
|
|
5
|
+
exports.highlightToml = highlightToml;
|
|
6
|
+
exports.highlightCsv = highlightCsv;
|
|
7
|
+
exports.highlightShell = highlightShell;
|
|
8
|
+
exports.highlightProperties = highlightProperties;
|
|
9
|
+
exports.highlight = highlight;
|
|
4
10
|
const ansi_1 = require("./ansi");
|
|
5
11
|
const theme_1 = require("./theme");
|
|
12
|
+
// --- 1. JSON Highlighter ---
|
|
6
13
|
function highlightJson(json) {
|
|
7
14
|
if (!json)
|
|
8
15
|
return '';
|
|
9
|
-
// Updated Regex for better partial matching and separation
|
|
10
|
-
// 1. Strings (keys or values), allowing unclosed quotes for partial typing
|
|
11
|
-
// 2. Numbers
|
|
12
|
-
// 3. Booleans/Null
|
|
13
|
-
// 4. Punctuation (separated colon from keys logic)
|
|
14
|
-
// Regex explanation:
|
|
15
|
-
// ("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"?) -> Captures strings, optionally unclosed at the end
|
|
16
|
-
// (-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?) -> Captures numbers
|
|
17
|
-
// (true|false|null) -> Captures keywords
|
|
18
|
-
// ([{}[\],:]) -> Captures punctuation
|
|
19
16
|
const tokenRegex = /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"?)|(-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)|(true|false|null)|([{}[\],:])/g;
|
|
20
17
|
let result = '';
|
|
21
18
|
let lastIndex = 0;
|
|
22
19
|
let match;
|
|
23
20
|
while ((match = tokenRegex.exec(json)) !== null) {
|
|
24
|
-
// Add any non-matching text (whitespace/invalid) as-is
|
|
25
21
|
if (match.index > lastIndex) {
|
|
26
22
|
result += json.substring(lastIndex, match.index);
|
|
27
23
|
}
|
|
28
24
|
const token = match[0];
|
|
29
|
-
// 1. Strings (Key or Value determination is context-based, but here we do simple check)
|
|
30
|
-
// Note: In strict JSON, keys are strings followed by :, but since we separated colon,
|
|
31
|
-
// we can't easily distinguish keys just by regex lookahead safely without lookbehind support.
|
|
32
|
-
// However, for visual highlighting, colouring all strings consistently is often acceptable
|
|
33
|
-
// or we can try to peek ahead.
|
|
34
25
|
if (token.startsWith('"')) {
|
|
35
|
-
// Simple heuristic: If the NEXT non-whitespace char is ':', treat as key
|
|
36
26
|
const remaining = json.substring(tokenRegex.lastIndex);
|
|
27
|
+
// Heuristic for keys: followed by optional whitespace and a colon
|
|
37
28
|
if (/^\s*:/.test(remaining)) {
|
|
38
29
|
result += `${theme_1.theme.syntax.key}${token}${ansi_1.ANSI.RESET}`;
|
|
39
30
|
}
|
|
@@ -41,32 +32,146 @@ function highlightJson(json) {
|
|
|
41
32
|
result += `${theme_1.theme.syntax.string}${token}${ansi_1.ANSI.RESET}`;
|
|
42
33
|
}
|
|
43
34
|
}
|
|
44
|
-
// 2. Numbers
|
|
45
35
|
else if (/^-?\d/.test(token)) {
|
|
46
36
|
result += `${theme_1.theme.syntax.number}${token}${ansi_1.ANSI.RESET}`;
|
|
47
37
|
}
|
|
48
|
-
// 3. Booleans/Null
|
|
49
38
|
else if (/^(true|false|null)$/.test(token)) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
else {
|
|
54
|
-
result += `${theme_1.theme.syntax.boolean}${token}${ansi_1.ANSI.RESET}`;
|
|
55
|
-
}
|
|
39
|
+
result += (token === 'null')
|
|
40
|
+
? `${theme_1.theme.syntax.null}${token}${ansi_1.ANSI.RESET}`
|
|
41
|
+
: `${theme_1.theme.syntax.boolean}${token}${ansi_1.ANSI.RESET}`;
|
|
56
42
|
}
|
|
57
|
-
// 4. Punctuation
|
|
58
43
|
else if (/^[{}[\],:]$/.test(token)) {
|
|
59
44
|
result += `${theme_1.theme.syntax.punctuation}${token}${ansi_1.ANSI.RESET}`;
|
|
60
45
|
}
|
|
61
|
-
// Fallback
|
|
62
46
|
else {
|
|
63
47
|
result += token;
|
|
64
48
|
}
|
|
65
49
|
lastIndex = tokenRegex.lastIndex;
|
|
66
50
|
}
|
|
67
|
-
// Append remaining text
|
|
68
51
|
if (lastIndex < json.length) {
|
|
69
52
|
result += json.substring(lastIndex);
|
|
70
53
|
}
|
|
71
54
|
return result;
|
|
72
55
|
}
|
|
56
|
+
// --- 2. ENV Highlighter ---
|
|
57
|
+
function highlightEnv(env) {
|
|
58
|
+
if (!env)
|
|
59
|
+
return '';
|
|
60
|
+
return env.split('\n').map(line => {
|
|
61
|
+
if (line.trim().startsWith('#')) {
|
|
62
|
+
return `${theme_1.theme.muted}${line}${ansi_1.ANSI.RESET}`;
|
|
63
|
+
}
|
|
64
|
+
const match = line.match(/^([^=]+)=(.*)$/);
|
|
65
|
+
if (match) {
|
|
66
|
+
const [, key, value] = match;
|
|
67
|
+
return `${theme_1.theme.syntax.key}${key}${theme_1.theme.syntax.punctuation}=${theme_1.theme.syntax.string}${value}${ansi_1.ANSI.RESET}`;
|
|
68
|
+
}
|
|
69
|
+
return line;
|
|
70
|
+
}).join('\n');
|
|
71
|
+
}
|
|
72
|
+
// --- 3. TOML Highlighter ---
|
|
73
|
+
function highlightToml(toml) {
|
|
74
|
+
if (!toml)
|
|
75
|
+
return '';
|
|
76
|
+
return toml.split('\n').map(line => {
|
|
77
|
+
const trimmed = line.trim();
|
|
78
|
+
if (trimmed.startsWith('#')) {
|
|
79
|
+
return `${theme_1.theme.muted}${line}${ansi_1.ANSI.RESET}`;
|
|
80
|
+
}
|
|
81
|
+
// [section]
|
|
82
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
83
|
+
return `${theme_1.theme.syntax.key}${line}${ansi_1.ANSI.RESET}`;
|
|
84
|
+
}
|
|
85
|
+
// Key = Value
|
|
86
|
+
const match = line.match(/^(\s*[\w\d_-]+)(\s*=)/);
|
|
87
|
+
if (match) {
|
|
88
|
+
const fullMatch = match[0];
|
|
89
|
+
const keyPart = match[1];
|
|
90
|
+
const eqPart = match[2];
|
|
91
|
+
const rest = line.substring(fullMatch.length);
|
|
92
|
+
return `${theme_1.theme.syntax.key}${keyPart}${ansi_1.ANSI.RESET}${theme_1.theme.syntax.punctuation}${eqPart}${theme_1.theme.syntax.string}${rest}${ansi_1.ANSI.RESET}`;
|
|
93
|
+
}
|
|
94
|
+
return line;
|
|
95
|
+
}).join('\n');
|
|
96
|
+
}
|
|
97
|
+
// --- 4. CSV Highlighter ---
|
|
98
|
+
function highlightCsv(csv) {
|
|
99
|
+
if (!csv)
|
|
100
|
+
return '';
|
|
101
|
+
// Cycle through colors to differentiate columns
|
|
102
|
+
const colors = [theme_1.theme.syntax.string, theme_1.theme.syntax.key, theme_1.theme.syntax.number, theme_1.theme.syntax.boolean];
|
|
103
|
+
return csv.split('\n').map(line => {
|
|
104
|
+
if (!line.trim())
|
|
105
|
+
return line;
|
|
106
|
+
// Split by comma, ignoring commas inside double quotes
|
|
107
|
+
// Regex explanation: Match comma only if followed by an even number of quotes (or 0) until end of line
|
|
108
|
+
const parts = line.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
|
|
109
|
+
return parts.map((part, index) => {
|
|
110
|
+
const color = colors[index % colors.length];
|
|
111
|
+
return `${color}${part}${ansi_1.ANSI.RESET}`;
|
|
112
|
+
}).join(`${theme_1.theme.syntax.punctuation},${ansi_1.ANSI.RESET}`);
|
|
113
|
+
}).join('\n');
|
|
114
|
+
}
|
|
115
|
+
// --- 5. Shell/Bash Highlighter ---
|
|
116
|
+
function highlightShell(script) {
|
|
117
|
+
if (!script)
|
|
118
|
+
return '';
|
|
119
|
+
// Simple replacements for common shell patterns
|
|
120
|
+
// 1. Comments
|
|
121
|
+
// 2. Keywords
|
|
122
|
+
// 3. Variables
|
|
123
|
+
const keywords = /\b(if|then|else|elif|fi|for|in|do|done|while|case|esac|return|exit|export|source|echo|printf)\b/g;
|
|
124
|
+
return script.split('\n').map(line => {
|
|
125
|
+
if (line.trim().startsWith('#')) {
|
|
126
|
+
return `${theme_1.theme.muted}${line}${ansi_1.ANSI.RESET}`;
|
|
127
|
+
}
|
|
128
|
+
// Temporarily hide strings properly is hard with regex replace,
|
|
129
|
+
// so we just do best-effort highlights for keywords and vars outside of checking quote context.
|
|
130
|
+
const processed = line
|
|
131
|
+
.replace(keywords, match => `${theme_1.theme.syntax.boolean}${match}${ansi_1.ANSI.RESET}`)
|
|
132
|
+
.replace(/(\$[\w\d_]+|\$\{[^}]+\})/g, match => `${theme_1.theme.syntax.key}${match}${ansi_1.ANSI.RESET}`)
|
|
133
|
+
.replace(/(\s|^)(-{1,2}[a-zA-Z0-9_-]+)/g, (_match, prefix, flag) => `${prefix}${theme_1.theme.syntax.number}${flag}${ansi_1.ANSI.RESET}`);
|
|
134
|
+
return processed;
|
|
135
|
+
}).join('\n');
|
|
136
|
+
}
|
|
137
|
+
// --- 6. Properties Highlighter ---
|
|
138
|
+
function highlightProperties(props) {
|
|
139
|
+
if (!props)
|
|
140
|
+
return '';
|
|
141
|
+
return props.split('\n').map(line => {
|
|
142
|
+
const trimmed = line.trim();
|
|
143
|
+
// Supports # or ! for comments
|
|
144
|
+
if (trimmed.startsWith('#') || trimmed.startsWith('!')) {
|
|
145
|
+
return `${theme_1.theme.muted}${line}${ansi_1.ANSI.RESET}`;
|
|
146
|
+
}
|
|
147
|
+
// Keys can be separated by = or :
|
|
148
|
+
const match = line.match(/^([^=:]+)([=:])(.*)$/);
|
|
149
|
+
if (match) {
|
|
150
|
+
const [, key, sep, value] = match;
|
|
151
|
+
return `${theme_1.theme.syntax.key}${key}${theme_1.theme.syntax.punctuation}${sep}${theme_1.theme.syntax.string}${value}${ansi_1.ANSI.RESET}`;
|
|
152
|
+
}
|
|
153
|
+
return line;
|
|
154
|
+
}).join('\n');
|
|
155
|
+
}
|
|
156
|
+
// --- Main Mapping ---
|
|
157
|
+
const highlighters = {
|
|
158
|
+
'json': highlightJson,
|
|
159
|
+
'env': highlightEnv,
|
|
160
|
+
'toml': highlightToml,
|
|
161
|
+
'csv': highlightCsv,
|
|
162
|
+
'sh': highlightShell,
|
|
163
|
+
'bash': highlightShell,
|
|
164
|
+
'zsh': highlightShell,
|
|
165
|
+
'properties': highlightProperties,
|
|
166
|
+
'props': highlightProperties,
|
|
167
|
+
'conf': highlightProperties // loose convention
|
|
168
|
+
};
|
|
169
|
+
function highlight(code, language) {
|
|
170
|
+
const lang = language.toLowerCase();
|
|
171
|
+
const highlightFunc = highlighters[lang];
|
|
172
|
+
if (highlightFunc) {
|
|
173
|
+
return highlightFunc(code);
|
|
174
|
+
}
|
|
175
|
+
// Fallback: If no highlighter found, return original code
|
|
176
|
+
return code;
|
|
177
|
+
}
|
package/dist/prompts/code.js
CHANGED
|
@@ -5,6 +5,7 @@ const ansi_1 = require("../ansi");
|
|
|
5
5
|
const base_1 = require("../base");
|
|
6
6
|
const theme_1 = require("../theme");
|
|
7
7
|
const utils_1 = require("../utils");
|
|
8
|
+
const highlight_1 = require("../highlight");
|
|
8
9
|
class CodePrompt extends base_1.Prompt {
|
|
9
10
|
constructor(options) {
|
|
10
11
|
super(options);
|
|
@@ -76,44 +77,58 @@ class CodePrompt extends base_1.Prompt {
|
|
|
76
77
|
let highlighted = '';
|
|
77
78
|
const shouldHighlight = this.options.highlight !== false;
|
|
78
79
|
if (shouldHighlight) {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
let
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
80
|
+
const lang = this.options.language || 'json';
|
|
81
|
+
const highlightedText = (0, highlight_1.highlight)(fullRawText, lang);
|
|
82
|
+
let visibleIdx = 0;
|
|
83
|
+
let activeColor = ''; // Tracks the last set color
|
|
84
|
+
for (let i = 0; i < highlightedText.length; i++) {
|
|
85
|
+
const char = highlightedText[i];
|
|
86
|
+
if (char === '\x1b') {
|
|
87
|
+
// Start of ANSI sequence
|
|
88
|
+
let sequence = char;
|
|
89
|
+
i++;
|
|
90
|
+
while (i < highlightedText.length && highlightedText[i] !== 'm') {
|
|
91
|
+
sequence += highlightedText[i];
|
|
92
|
+
i++;
|
|
93
|
+
}
|
|
94
|
+
if (i < highlightedText.length)
|
|
95
|
+
sequence += 'm'; // Append terminator
|
|
96
|
+
// Interpret sequence (naive)
|
|
97
|
+
if (sequence === ansi_1.ANSI.RESET || sequence === '\x1b[0m') {
|
|
98
|
+
activeColor = '';
|
|
94
99
|
}
|
|
95
100
|
else {
|
|
96
|
-
|
|
101
|
+
// Assuming it's a color code.
|
|
102
|
+
activeColor = sequence;
|
|
97
103
|
}
|
|
104
|
+
// If we are INSIDE the active range, and we encounter a color change/reset,
|
|
105
|
+
// we must ensure UNDERLINE is kept/restored.
|
|
106
|
+
if (visibleIdx >= activeVarStart && visibleIdx < activeVarEnd) {
|
|
107
|
+
// Output the sequence (e.g. a color change)
|
|
108
|
+
highlighted += sequence;
|
|
109
|
+
// Then re-assert underline
|
|
110
|
+
highlighted += ansi_1.ANSI.UNDERLINE;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
highlighted += sequence;
|
|
114
|
+
}
|
|
115
|
+
continue;
|
|
98
116
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
else if (/^(true|false|null)$/.test(tokenText)) {
|
|
103
|
-
color = (tokenText === 'null')
|
|
104
|
-
? (theme_1.theme.syntax?.null || ansi_1.ANSI.FG_RED)
|
|
105
|
-
: (theme_1.theme.syntax?.boolean || ansi_1.ANSI.FG_MAGENTA);
|
|
117
|
+
// Normal char
|
|
118
|
+
if (visibleIdx === activeVarStart) {
|
|
119
|
+
highlighted += `${theme_1.theme.main}${ansi_1.ANSI.UNDERLINE}`;
|
|
106
120
|
}
|
|
107
|
-
|
|
108
|
-
|
|
121
|
+
highlighted += char;
|
|
122
|
+
visibleIdx++;
|
|
123
|
+
if (visibleIdx === activeVarEnd) {
|
|
124
|
+
highlighted += ansi_1.ANSI.RESET;
|
|
125
|
+
// Restore previous color if any
|
|
126
|
+
if (activeColor) {
|
|
127
|
+
highlighted += activeColor;
|
|
128
|
+
}
|
|
109
129
|
}
|
|
110
|
-
this.appendSegment(tokenText, tokenStart, activeVarStart, activeVarEnd, color, (s) => highlighted += s);
|
|
111
|
-
lastIndex = jsonTokenRegex.lastIndex;
|
|
112
|
-
}
|
|
113
|
-
if (lastIndex < fullRawText.length) {
|
|
114
|
-
const tail = fullRawText.substring(lastIndex);
|
|
115
|
-
this.appendSegment(tail, lastIndex, activeVarStart, activeVarEnd, ansi_1.ANSI.FG_WHITE, (s) => highlighted += s);
|
|
116
130
|
}
|
|
131
|
+
highlighted += ansi_1.ANSI.RESET;
|
|
117
132
|
}
|
|
118
133
|
else {
|
|
119
134
|
this.appendSegment(fullRawText, 0, activeVarStart, activeVarEnd, ansi_1.ANSI.RESET, (s) => highlighted += s);
|
package/dist/types.d.ts
CHANGED
|
@@ -190,7 +190,7 @@ export interface WaitOptions extends BaseOptions {
|
|
|
190
190
|
}
|
|
191
191
|
export interface CodeOptions extends BaseOptions {
|
|
192
192
|
template: string;
|
|
193
|
-
language?: 'json';
|
|
193
|
+
language?: 'json' | 'env' | 'toml' | 'csv' | 'sh' | 'bash' | 'zsh' | 'properties' | 'props' | 'conf';
|
|
194
194
|
/**
|
|
195
195
|
* Enable syntax highlighting (Experimental).
|
|
196
196
|
* @default true
|
package/dist/utils.js
CHANGED
|
@@ -20,7 +20,7 @@ function detectCapabilities() {
|
|
|
20
20
|
// Check if it is a TTY
|
|
21
21
|
const isTTY = process.stdout.isTTY;
|
|
22
22
|
const isWindows = process.platform === 'win32';
|
|
23
|
-
//
|
|
23
|
+
// Better Unicode detection logic
|
|
24
24
|
const isUnicodeSupported = () => {
|
|
25
25
|
// 1. Windows: Check specific environmental variables
|
|
26
26
|
if (isWindows) {
|