дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-13 13:15:42 +02:00
Порівняти коміти
1
Коміти
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
6b3519c7f8 |
No files matched your search
@@ -48,11 +48,6 @@ import { forgetMemory } from "./memory/memoryState";
|
||||
const useAnyOverlay = () =>
|
||||
useOverlays((s) => !!(s.popover || s.evaluate || s.breakpoints || s.chooser || s.attach || s.smartStep));
|
||||
|
||||
/** The Debug stripe button's badge, like Run's: how many debug sessions (child sessions aside) are live. */
|
||||
function useLiveSessionCount(): number | null {
|
||||
return useDebug((s) => Object.values(s.sessions).filter((x) => x.parent === null && isLive(x)).length || null);
|
||||
}
|
||||
|
||||
export function activate(): () => void {
|
||||
useDebugRunSessions.setState({
|
||||
Console: lazyComponent(() => import("./ui/DebugConsole").then((m) => m.DebugServiceConsole)),
|
||||
@@ -76,7 +71,6 @@ export function activate(): () => void {
|
||||
order: 20,
|
||||
component: lazyComponent(() => import("./ui/DebugToolWindow").then((m) => m.DebugToolWindow)),
|
||||
headerContent: lazyComponent(() => import("./ui/DebugToolWindow").then((m) => m.DebugTabs)),
|
||||
useBadge: useLiveSessionCount,
|
||||
}),
|
||||
registerEditorKind(heapEditorKind),
|
||||
installHeapContext(),
|
||||
|
||||
@@ -176,7 +176,30 @@ export function DebugToolWindow() {
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<div className={styles.toolbar} role="toolbar" aria-label={tx("Debugger actions")}>
|
||||
{/* IDEA's XDebugger.ToolWindow.TopToolbar3 (+ its "More" group), then the views. */}
|
||||
<div role="tablist" aria-label={tx("Debug views")} className={styles.tabs}>
|
||||
{(
|
||||
[
|
||||
["variables", "Threads & Variables"],
|
||||
["console", "Console"],
|
||||
...(hasMemory ? [["memory", "Memory"] as const] : []),
|
||||
] as const
|
||||
).map(([id, label]) => (
|
||||
<button
|
||||
key={id}
|
||||
type="button"
|
||||
role="tab"
|
||||
id={`debug-tab-${id}`}
|
||||
aria-selected={tab === id}
|
||||
aria-controls={`debug-panel-${id}`}
|
||||
className={clsx(styles.tab, tab === id && styles.tabActive)}
|
||||
onClick={() => setView({ session: active.startedAt, status: active.status, tab: id })}
|
||||
>
|
||||
{tx(label)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
{/* IDEA's XDebugger.ToolWindow.TopToolbar3 (+ its "More" group). */}
|
||||
<span className={styles.sep} aria-hidden />
|
||||
<ToolButton action="debug.rerun" icon="rerun" />
|
||||
<ToolButton action="debug.stop" icon="stop" tone="danger" />
|
||||
<span className={styles.sep} aria-hidden />
|
||||
@@ -210,29 +233,6 @@ export function DebugToolWindow() {
|
||||
onClick={() => setMuted(!muted)}
|
||||
/>
|
||||
<MoreActions />
|
||||
<span className={styles.sep} aria-hidden />
|
||||
<div role="tablist" aria-label={tx("Debug views")} className={styles.tabs}>
|
||||
{(
|
||||
[
|
||||
["variables", "Threads & Variables"],
|
||||
["console", "Console"],
|
||||
...(hasMemory ? [["memory", "Memory"] as const] : []),
|
||||
] as const
|
||||
).map(([id, label]) => (
|
||||
<button
|
||||
key={id}
|
||||
type="button"
|
||||
role="tab"
|
||||
id={`debug-tab-${id}`}
|
||||
aria-selected={tab === id}
|
||||
aria-controls={`debug-panel-${id}`}
|
||||
className={clsx(styles.tab, tab === id && styles.tabActive)}
|
||||
onClick={() => setView({ session: active.startedAt, status: active.status, tab: id })}
|
||||
>
|
||||
{tx(label)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" id={`debug-panel-${tab}`} aria-labelledby={`debug-tab-${tab}`} className={styles.panel}>
|
||||
{tab === "variables" ? (
|
||||
@@ -251,12 +251,7 @@ export function DebugToolWindow() {
|
||||
|
||||
function ThreadsAndVariables({ session }: { session: DebugSession }) {
|
||||
return (
|
||||
<SplitGroup
|
||||
orientation="horizontal"
|
||||
id="debug-threads-variables"
|
||||
storageKey="openidea.debug.threadsVariables"
|
||||
className={styles.split}
|
||||
>
|
||||
<SplitGroup orientation="horizontal" id="debug-threads-variables" className={styles.split}>
|
||||
<SplitPanel id="frames" defaultSize="34%" minSize="160px">
|
||||
<FramesPane session={session} />
|
||||
</SplitPanel>
|
||||
|
||||
@@ -43,13 +43,23 @@ export function AddInterpreterDialog({
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const ids = { base: useId(), location: useId(), existing: useId() };
|
||||
|
||||
const baseValue = base ?? bases[0]?.path ?? null;
|
||||
const toOption = (s: { path: string; name: string }): SelectOption => ({
|
||||
value: s.path,
|
||||
label: s.name,
|
||||
detail: tildify(s.path),
|
||||
});
|
||||
const baseOptions = bases.map(toOption);
|
||||
// conda installs a fresh Python of the base's version: offer versions, not environments to copy.
|
||||
const versionOptions = (() => {
|
||||
const seen = new Map<string, SelectOption>();
|
||||
for (const s of bases) {
|
||||
const short = s.version?.split(".").slice(0, 2).join(".");
|
||||
if (short && !seen.has(short)) seen.set(short, { value: s.path, label: tx`Python ${short}` });
|
||||
}
|
||||
return [...seen.values()].sort((a, b) => b.label.localeCompare(a.label, undefined, { numeric: true }));
|
||||
})();
|
||||
const baseOptions = kind === "conda" ? versionOptions : bases.map(toOption);
|
||||
const baseValue =
|
||||
base ?? (kind === "conda" ? (versionOptions[0]?.value as string | undefined) : bases[0]?.path) ?? null;
|
||||
const existingOptions = [...browsed, ...list.filter((s) => !browsed.some((b) => b.path === s.path))].map((s) => ({
|
||||
value: s.path,
|
||||
label: `${s.name} — ${tildify(s.path)}`,
|
||||
@@ -108,7 +118,9 @@ export function AddInterpreterDialog({
|
||||
const canOk = !busy && (mode === "new" ? !!baseValue && !!location.trim() : !!existing?.trim());
|
||||
const note = {
|
||||
venv: tx("Runs “<base> -m venv <location>”; the new interpreter becomes the project interpreter."),
|
||||
conda: tx("Runs “conda create -p <location>”; the new interpreter becomes the project interpreter."),
|
||||
conda: tx(
|
||||
"Runs “conda create -p <location> python=<version>”: a new environment with only Python in it; the new interpreter becomes the project interpreter.",
|
||||
),
|
||||
uv: tx("Runs “uv venv <location> --python <base>”; the new interpreter becomes the project interpreter."),
|
||||
poetry: tx(
|
||||
"Runs “poetry env use <base>” in the project; poetry keeps the environment under its own cache directory.",
|
||||
@@ -143,6 +155,7 @@ export function AddInterpreterDialog({
|
||||
aria-current={kind === k.tool || undefined}
|
||||
onClick={() => {
|
||||
setKind(k.tool);
|
||||
setBase(null);
|
||||
setError(null);
|
||||
}}
|
||||
>
|
||||
@@ -199,9 +212,7 @@ export function AddInterpreterDialog({
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<label htmlFor={ids.base}>
|
||||
<T>Base interpreter:</T>
|
||||
</label>
|
||||
<label htmlFor={ids.base}>{kind === "conda" ? <T>Python version:</T> : <T>Base interpreter:</T>}</label>
|
||||
<div className={styles.pathRow}>
|
||||
<Select
|
||||
className={styles.pathInput}
|
||||
@@ -209,17 +220,19 @@ export function AddInterpreterDialog({
|
||||
options={baseOptions}
|
||||
onChange={setBase}
|
||||
placeholder={loading ? "Detecting…" : "No Python found"}
|
||||
aria-label="Base interpreter"
|
||||
/>
|
||||
<IconButton
|
||||
icon="folder-open"
|
||||
size="small"
|
||||
title="Browse…"
|
||||
onClick={async () => {
|
||||
const p = await choosePath({ directory: false, title: "Select Base Interpreter" });
|
||||
if (p) setBase(p);
|
||||
}}
|
||||
aria-label={kind === "conda" ? "Python version" : "Base interpreter"}
|
||||
/>
|
||||
{kind !== "conda" && (
|
||||
<IconButton
|
||||
icon="folder-open"
|
||||
size="small"
|
||||
title="Browse…"
|
||||
onClick={async () => {
|
||||
const p = await choosePath({ directory: false, title: "Select Base Interpreter" });
|
||||
if (p) setBase(p);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.note}>{note}</div>
|
||||
</>
|
||||
|
||||
@@ -68,6 +68,8 @@ export function PythonInterpreterPage() {
|
||||
const [activate, setActivate] = useSetting<boolean>("languages.python.activateVirtualenv");
|
||||
const root = useProject((s) => s.project?.root ?? null);
|
||||
const [auto, setAuto] = useState<string | null>(null);
|
||||
// Bumped when an environment is created: it may reuse the configured path, whose state changed.
|
||||
const [created, setCreated] = useState(0);
|
||||
// Detected interpreters plus the ones added to (or hidden from) the IDE-wide list.
|
||||
const { detected, rows, hidden } = usePythonInterpreters({ withProjects: false });
|
||||
const extras = useMemo(
|
||||
@@ -91,7 +93,7 @@ export function PythonInterpreterPage() {
|
||||
return () => {
|
||||
live = false;
|
||||
};
|
||||
}, [root]);
|
||||
}, [root, created]);
|
||||
|
||||
// The interpreter runs resolve to: the configured one while it exists, else the fallback.
|
||||
const [resolved, setResolved] = useState<{ interpreter: string; path: string | null } | null>(null);
|
||||
@@ -104,7 +106,7 @@ export function PythonInterpreterPage() {
|
||||
return () => {
|
||||
live = false;
|
||||
};
|
||||
}, [root, interpreter]);
|
||||
}, [root, interpreter, created]);
|
||||
// A configured interpreter whose executable is gone (PyCharm's "Invalid"): runs fall back.
|
||||
const invalid =
|
||||
!!interpreter && resolved?.interpreter === interpreter && !sameInterpreter(resolved.path, interpreter, root);
|
||||
@@ -362,6 +364,8 @@ export function PythonInterpreterPage() {
|
||||
onClose={() => setAdding(false)}
|
||||
onAdded={(path) => {
|
||||
setInterpreter(path);
|
||||
setCreated((n) => n + 1);
|
||||
reload();
|
||||
setAdding(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -5217,7 +5217,9 @@
|
||||
"{count} modified action": "已修改 {count} 个操作",
|
||||
"{count} modified actions": "已修改 {count} 个操作",
|
||||
"Runs “<base> -m venv <location>”; the new interpreter becomes the project interpreter.": "运行“<base> -m venv <location>”;新的解释器将成为项目解释器。",
|
||||
"Runs “conda create -p <location>”; the new interpreter becomes the project interpreter.": "运行“conda create -p <location>”;新的解释器将成为项目解释器。",
|
||||
"Runs “conda create -p <location> python=<version>”: a new environment with only Python in it; the new interpreter becomes the project interpreter.": "运行“conda create -p <location> python=<version>”:新建一个只包含 Python 的环境;新的解释器将成为项目解释器。",
|
||||
"Python version": "Python 版本",
|
||||
"Python {short}": "Python {short}",
|
||||
"Runs “poetry env use <base>” in the project; poetry keeps the environment under its own cache directory.": "在项目中运行“poetry env use <base>”;Poetry 会将环境保存在其自己的缓存目录下。",
|
||||
"Runs “uv venv <location> --python <base>”; the new interpreter becomes the project interpreter.": "运行“uv venv <location> --python <base>”;新的解释器将成为项目解释器。",
|
||||
"{vendor} {version} is unpacked into a folder of its own in {location}, where JDK detection finds it.": "{vendor} {version} 将解压到 {location} 下它自己的文件夹中,JDK 检测会在那里找到它。",
|
||||
|
||||
Reference in new issue
Заблокувати користувача