mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 08:07:49 +00:00
feat(debugger): Sort values alphabetically in the Variables view
Settings › Debugger › Data Views gains Sort values alphabetically (off by default). When on, variables and their children are listed by name, comparing numbers numerically; array and list elements keep their index order.
This commit is contained in:
@@ -218,6 +218,8 @@ pub struct DebuggerSettings {
|
||||
/// While suspended, hovering the start of a line shows a Run to Cursor button.
|
||||
pub run_to_cursor_inlay: bool,
|
||||
pub inline_values: bool,
|
||||
/// Data Views: list variables by name instead of the adapter's order.
|
||||
pub sort_values: bool,
|
||||
pub value_tooltip: bool,
|
||||
pub value_tooltip_delay: u32,
|
||||
/// Stepping: do not step into library code (debugpy `justMyCode`, js-debug `skipFiles`).
|
||||
@@ -234,6 +236,7 @@ impl Default for DebuggerSettings {
|
||||
breakpoints_any_file: false,
|
||||
run_to_cursor_inlay: true,
|
||||
inline_values: true,
|
||||
sort_values: false,
|
||||
value_tooltip: true,
|
||||
value_tooltip_delay: 700,
|
||||
skip_library_code: true,
|
||||
|
||||
@@ -2153,6 +2153,8 @@ export type DebuggerSettings = {
|
||||
/** While suspended, hovering the start of a line shows a Run to Cursor button. */
|
||||
runToCursorInlay?: boolean,
|
||||
inlineValues?: boolean,
|
||||
/** Data Views: list variables by name instead of the adapter's order. */
|
||||
sortValues?: boolean,
|
||||
valueTooltip?: boolean,
|
||||
valueTooltipDelay?: number,
|
||||
/** Stepping: do not step into library code (debugpy `justMyCode`, js-debug `skipFiles`). */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { classifyValue, identifiersIn, inlineValue } from "../values";
|
||||
import { classifyValue, identifiersIn, inlineValue, sortVariables } from "../values";
|
||||
import { inlineValuesFor } from "../editor/execution";
|
||||
import { frameLabel, groupFrames, isLibraryFrame } from "../frames";
|
||||
import type { StackFrame } from "@/platform/ipc";
|
||||
@@ -93,3 +93,19 @@ describe("frames", () => {
|
||||
expect(frameLabel(frame(1, null))).toBe("f1");
|
||||
});
|
||||
});
|
||||
|
||||
describe("sortVariables", () => {
|
||||
const names = (vs: { name: string }[]) => vs.map((v) => v.name);
|
||||
it("sorts by name, case-insensitively and with numbers compared numerically", () => {
|
||||
expect(names(sortVariables([{ name: "b" }, { name: "item10" }, { name: "A" }, { name: "item2" }]))).toEqual([
|
||||
"A",
|
||||
"b",
|
||||
"item2",
|
||||
"item10",
|
||||
]);
|
||||
});
|
||||
it("keeps array elements in index order", () => {
|
||||
const items = [{ name: "[0]" }, { name: "[1]" }, { name: "[10]" }, { name: "[2]" }];
|
||||
expect(names(sortVariables(items))).toEqual(["[0]", "[1]", "[10]", "[2]"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,8 @@ import { addFieldWatchpoint } from "../breakpoints/special";
|
||||
import { methodAt } from "../breakpoints/symbols";
|
||||
import { activeSession, addWatch, removeWatch, revealFrame, sessionSupports, setVariableValue } from "../state";
|
||||
import { blurDebugView, focusDebugView } from "./focusedView";
|
||||
import { classifyValue } from "../values";
|
||||
import { classifyValue, sortVariables } from "../values";
|
||||
import { workflowSettings } from "@/platform/workflowSettings";
|
||||
import styles from "./VariablesView.module.css";
|
||||
|
||||
export type VarRoot =
|
||||
@@ -196,7 +197,8 @@ export function VariablesView({
|
||||
loading.current.add(tag);
|
||||
let list: VarNode[];
|
||||
try {
|
||||
const vars = await call(commands.debugVariables(session, node.reference));
|
||||
const raw = await call(commands.debugVariables(session, node.reference));
|
||||
const vars = workflowSettings().debugger.sortValues ? sortVariables(raw) : raw;
|
||||
const seen = new Map<string, number>();
|
||||
list = vars.map((v) => {
|
||||
const n = (seen.get(v.name) ?? 0) + 1;
|
||||
|
||||
@@ -53,3 +53,14 @@ export function identifiersIn(text: string): string[] {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
const INDEX = /^\[?\d+\]?$/;
|
||||
|
||||
/**
|
||||
* Data Views › "Sort values alphabetically": children by name (numbers in
|
||||
* names compared numerically). Array / list elements keep their index order.
|
||||
*/
|
||||
export function sortVariables<T extends { name: string }>(vars: readonly T[]): T[] {
|
||||
if (vars.every((v) => INDEX.test(v.name))) return [...vars];
|
||||
return [...vars].sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: "base" }));
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ export const EXECUTION_PAGES: PageSpec[] = [
|
||||
label: "Show values inline",
|
||||
hint: "Values of local variables are shown after the lines that use them while suspended.",
|
||||
},
|
||||
{ kind: "toggle", key: "debugger.sortValues", label: "Sort values alphabetically" },
|
||||
{
|
||||
kind: "toggle",
|
||||
key: "debugger.valueTooltip",
|
||||
|
||||
@@ -2946,6 +2946,7 @@
|
||||
"Close button position:": "关闭按钮位置:",
|
||||
"Close button position": "关闭按钮位置",
|
||||
"Tab Order": "标签页顺序",
|
||||
"Sort values alphabetically": "按字母顺序对值排序",
|
||||
"Sort tabs alphabetically": "按字母顺序对标签页排序",
|
||||
"One row, and if tabs don't fit:": "单行,标签页放不下时:",
|
||||
"If tabs don't fit": "标签页放不下时",
|
||||
|
||||
@@ -83,6 +83,7 @@ export interface DebuggerSettingsValid {
|
||||
breakpointsAnyFile: boolean;
|
||||
runToCursorInlay: boolean;
|
||||
inlineValues: boolean;
|
||||
sortValues: boolean;
|
||||
valueTooltip: boolean;
|
||||
valueTooltipDelay: number;
|
||||
skipLibraryCode: boolean;
|
||||
@@ -242,6 +243,7 @@ export const DEFAULT_WORKFLOW: WorkflowSettings = {
|
||||
breakpointsAnyFile: false,
|
||||
runToCursorInlay: true,
|
||||
inlineValues: true,
|
||||
sortValues: false,
|
||||
valueTooltip: true,
|
||||
valueTooltipDelay: 700,
|
||||
skipLibraryCode: true,
|
||||
@@ -376,6 +378,7 @@ export function validateDebugger(raw: unknown): DebuggerSettingsValid {
|
||||
breakpointsAnyFile: bool(v.breakpointsAnyFile, d.breakpointsAnyFile),
|
||||
runToCursorInlay: bool(v.runToCursorInlay, d.runToCursorInlay),
|
||||
inlineValues: bool(v.inlineValues, d.inlineValues),
|
||||
sortValues: bool(v.sortValues, d.sortValues),
|
||||
valueTooltip: bool(v.valueTooltip, d.valueTooltip),
|
||||
valueTooltipDelay: num(v.valueTooltipDelay, d.valueTooltipDelay, WORKFLOW_LIMITS.tooltipDelay, true),
|
||||
skipLibraryCode: bool(v.skipLibraryCode, d.skipLibraryCode),
|
||||
|
||||
Reference in New Issue
Block a user