дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
fix(run): Give forked and debugged JVMs the console encoding and render colours in the Debug console (#220)
Only the JVM the IDE launched directly was told the console's output encoding, so forked JVMs (spring-boot:run, Surefire, bootRun, Gradle workers), debugger-launched JVMs and Build-window builds wrote GBK on Windows while the console decoded UTF-8. Every JVM the IDE starts on Windows now gets the console encoding: java gets -Dfile.encoding alongside the std* properties, build tools and their forks get JAVA_TOOL_OPTIONS (std* only) with the IDE's own 'Picked up JAVA_TOOL_OPTIONS' line filtered, shell command lines are recognised by their first word, and java-debug launches get the matching vmArgs. The Debug console now shares the Run console's ANSI parser. Encoding helpers moved to ide-core::output_encoding. Not verified on a Windows machine. Fixes #180 Fixes #182 Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
Цей коміт міститься в:
1 джерело
6767a5ff8c
коміт
c821ab144c
17 files changed
+861
-360
No files matched your search
@@ -5,6 +5,7 @@
|
||||
import { workflowSettings } from "@/platform/workflowSettings";
|
||||
import { executeAction } from "@/platform/actions";
|
||||
import { create } from "zustand";
|
||||
import { AnsiStream, appendSpans, type Span } from "@/ui/ansi";
|
||||
import { setContext } from "@/platform/context";
|
||||
import {
|
||||
call,
|
||||
@@ -55,7 +56,10 @@ export interface DebugSession {
|
||||
export interface ConsoleLine {
|
||||
id: number;
|
||||
category: string;
|
||||
/** Plain text without escape sequences. */
|
||||
text: string;
|
||||
/** `text` styled by its ANSI colours. */
|
||||
spans: Span[];
|
||||
}
|
||||
|
||||
export interface WatchResult {
|
||||
@@ -95,6 +99,16 @@ export const useExecutionPoint = create<ExecutionPoint>(() => ({ path: null, lin
|
||||
|
||||
const MAX_CONSOLE_LINES = 5000;
|
||||
let lineSeq = 0;
|
||||
/** ANSI state per session and output category (a colour can span several output events). */
|
||||
const ansiStreams = new Map<DebugSessionId, Map<string, AnsiStream>>();
|
||||
|
||||
function ansiStream(session: DebugSessionId, category: string): AnsiStream {
|
||||
let streams = ansiStreams.get(session);
|
||||
if (!streams) ansiStreams.set(session, (streams = new Map()));
|
||||
let stream = streams.get(category);
|
||||
if (!stream) streams.set(category, (stream = new AnsiStream()));
|
||||
return stream;
|
||||
}
|
||||
|
||||
// --- accessors ---------------------------------------------------------------
|
||||
|
||||
@@ -215,7 +229,10 @@ export function publishContext() {
|
||||
|
||||
// --- console -----------------------------------------------------------------
|
||||
|
||||
export function appendConsole(session: DebugSessionId, category: string, text: string) {
|
||||
export function appendConsole(session: DebugSessionId, category: string, raw: string) {
|
||||
if (!raw) return;
|
||||
const spans = ansiStream(session, category).parse(raw);
|
||||
const text = spans.map((sp) => sp.text).join("");
|
||||
if (!text) return;
|
||||
useDebug.setState((s) => {
|
||||
const prev = s.console[session] ?? [];
|
||||
@@ -223,9 +240,9 @@ export function appendConsole(session: DebugSessionId, category: string, text: s
|
||||
const last = next[next.length - 1];
|
||||
// Merge partial lines of the same category.
|
||||
if (last && last.category === category && !last.text.endsWith("\n")) {
|
||||
next[next.length - 1] = { ...last, text: last.text + text };
|
||||
next[next.length - 1] = { ...last, text: last.text + text, spans: appendSpans(last.spans, spans) };
|
||||
} else {
|
||||
next.push({ id: ++lineSeq, category, text });
|
||||
next.push({ id: ++lineSeq, category, text, spans });
|
||||
}
|
||||
if (next.length > MAX_CONSOLE_LINES) next.splice(0, next.length - MAX_CONSOLE_LINES);
|
||||
return { console: { ...s.console, [session]: next } };
|
||||
@@ -233,6 +250,7 @@ export function appendConsole(session: DebugSessionId, category: string, text: s
|
||||
}
|
||||
|
||||
export function clearConsole(session: DebugSessionId) {
|
||||
ansiStreams.delete(session);
|
||||
useDebug.setState((s) => ({ console: { ...s.console, [session]: [] } }));
|
||||
}
|
||||
|
||||
@@ -255,6 +273,7 @@ export async function startSession(
|
||||
useDebug.setState((s) => {
|
||||
const sessions = Object.fromEntries(Object.entries(s.sessions).filter(([, v]) => isLive(v)));
|
||||
const consoleLines = Object.fromEntries(Object.entries(s.console).filter(([k]) => sessions[+k]));
|
||||
for (const id of ansiStreams.keys()) if (!sessions[id]) ansiStreams.delete(id);
|
||||
return { sessions, console: consoleLines, active: s.active != null && sessions[s.active] ? s.active : null };
|
||||
});
|
||||
try {
|
||||
@@ -657,6 +676,7 @@ export function handleDebugEvent(id: DebugSessionId, event: DebugEvent) {
|
||||
export function resetSessions() {
|
||||
const { sessions } = useDebug.getState();
|
||||
for (const s of Object.values(sessions)) if (s.parent == null && isLive(s)) void stopSession(s.id);
|
||||
ansiStreams.clear();
|
||||
useDebug.setState({ sessions: {}, active: null, console: {}, stopSeq: 0 });
|
||||
useExecutionPoint.setState({ path: null, line: 0, top: true, values: {} });
|
||||
publishContext();
|
||||
|
||||
Reference in new issue
Заблокувати користувача