picocode-core 0.9.119 → 0.9.121
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/package.json +1 -1
- package/src/ansi.js +52 -0
- package/src/tools/bash.js +5 -5
package/package.json
CHANGED
package/src/ansi.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const CSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]/g
|
|
2
|
+
const MAX_ACTIVE_SGR = 32
|
|
3
|
+
|
|
4
|
+
export function stripAnsi(text) {
|
|
5
|
+
return String(text).replace(CSI_RE, '')
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function isReset(params) {
|
|
9
|
+
return params === '' || params === '0' || params.split(';').every((code) => code === '0' || code === '')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// remembers which sgr sequences are still in effect so a line that starts
|
|
13
|
+
// mid-style can be prefixed with exactly the sequences the terminal would
|
|
14
|
+
// have applied, without interpreting colors at all
|
|
15
|
+
export function createSgrTracker() {
|
|
16
|
+
let active = []
|
|
17
|
+
let pending = ''
|
|
18
|
+
|
|
19
|
+
function feed(text) {
|
|
20
|
+
const input = pending + String(text)
|
|
21
|
+
pending = ''
|
|
22
|
+
let i = 0
|
|
23
|
+
while (i < input.length) {
|
|
24
|
+
const start = input.indexOf('\x1b[', i)
|
|
25
|
+
if (start === -1) break
|
|
26
|
+
let end = start + 2
|
|
27
|
+
while (end < input.length && !(input.charCodeAt(end) >= 0x40 && input.charCodeAt(end) <= 0x7e)) end++
|
|
28
|
+
if (end >= input.length) {
|
|
29
|
+
pending = input.slice(start)
|
|
30
|
+
break
|
|
31
|
+
}
|
|
32
|
+
if (input[end] === 'm') apply(input.slice(start + 2, end))
|
|
33
|
+
i = end + 1
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function apply(params) {
|
|
38
|
+
if (isReset(params)) {
|
|
39
|
+
active = []
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
if (params.startsWith('0;')) active = []
|
|
43
|
+
active.push(params.startsWith('0;') ? params.slice(2) : params)
|
|
44
|
+
if (active.length > MAX_ACTIVE_SGR) active = active.slice(-MAX_ACTIVE_SGR)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function style() {
|
|
48
|
+
return active.map((params) => `\x1b[${params}m`).join('')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { feed, style }
|
|
52
|
+
}
|
package/src/tools/bash.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process'
|
|
2
|
-
import {
|
|
2
|
+
import { stripAnsi, createSgrTracker } from '../ansi.js'
|
|
3
3
|
|
|
4
4
|
const MAX_OUTPUT_CHARS = 30000
|
|
5
5
|
const MAX_BUFFER_BYTES = 10 * 1024 * 1024
|
|
@@ -17,19 +17,19 @@ function createOutputPreview() {
|
|
|
17
17
|
let current = ''
|
|
18
18
|
let currentStartStyle = ''
|
|
19
19
|
let completed = 0
|
|
20
|
-
const
|
|
20
|
+
const sgr = createSgrTracker()
|
|
21
21
|
|
|
22
22
|
function add(chunk) {
|
|
23
23
|
const parts = String(chunk).split('\n')
|
|
24
24
|
current = (current + parts[0]).slice(0, MAX_PREVIEW_LINE_CHARS)
|
|
25
|
-
|
|
25
|
+
sgr.feed(parts[0])
|
|
26
26
|
for (let i = 1; i < parts.length; i++) {
|
|
27
27
|
lines.push({ text: current, startStyle: currentStartStyle })
|
|
28
28
|
if (lines.length > OUTPUT_PREVIEW_LINES) lines.shift()
|
|
29
29
|
completed++
|
|
30
|
-
currentStartStyle =
|
|
30
|
+
currentStartStyle = sgr.style()
|
|
31
31
|
current = parts[i].slice(0, MAX_PREVIEW_LINE_CHARS)
|
|
32
|
-
|
|
32
|
+
sgr.feed(parts[i])
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|