diff --git a/.gitignore b/.gitignore index ba6d091..5cd5549 100644 --- a/.gitignore +++ b/.gitignore @@ -30,8 +30,8 @@ tocodex-docs/ .codex/ *.internal.md -# Local commit hooks are machine-specific policy and must never be published. -/.local-hooks/ +# Local commit policy is machine-specific and must never be published. +/.pre-commit-config.yaml # `docs/` is private by default. Public documentation must be reviewed and # explicitly added to this file one path at a time; never allowlist another subtree. diff --git a/nebula_app/src/ai_hook.rs b/nebula_app/src/ai_hook.rs index 581f8c4..5c58323 100644 --- a/nebula_app/src/ai_hook.rs +++ b/nebula_app/src/ai_hook.rs @@ -727,7 +727,8 @@ fn parse_envelope(bytes: &[u8]) -> Option { message: message.clone(), selection: context_string(&payload, &["selection", "selected_text", "selectedText"]), raw_context: sanitized_raw_context(&payload), - }); Some(AiHookEvent { + }); + Some(AiHookEvent { pane, source, kind, @@ -1250,11 +1251,15 @@ mod remote_tests { }; let mut gate = AiHookEventGate::default(); - let done = event("{\"kind\":\"done\",\"session_id\":\"s\",\"bridge_sequence\":3,\"event_id\":\"s:3\"}"); + let done = event( + "{\"kind\":\"done\",\"session_id\":\"s\",\"bridge_sequence\":3,\"event_id\":\"s:3\"}", + ); assert_eq!(gate.verdict(&done, 3), GateVerdict::Accepted); assert_eq!(gate.verdict(&done, 3), GateVerdict::DuplicateEventId); - let older = event("{\"kind\":\"prompt\",\"session_id\":\"s\",\"bridge_sequence\":2,\"event_id\":\"s:2\"}"); + let older = event( + "{\"kind\":\"prompt\",\"session_id\":\"s\",\"bridge_sequence\":2,\"event_id\":\"s:2\"}", + ); assert_eq!(gate.verdict(&older, 3), GateVerdict::StaleSequence); // 无序号但带 provider 时间戳:走时间判据。 diff --git a/nebula_app/src/display/i18n.rs b/nebula_app/src/display/i18n.rs index 63a5a7f..8067fdc 100644 --- a/nebula_app/src/display/i18n.rs +++ b/nebula_app/src/display/i18n.rs @@ -392,10 +392,7 @@ mod tests { let template_iterations = 200_000u128; let template_started = Instant::now(); for _ in 0..template_iterations { - black_box(UiLanguage::EnUs.tr_args( - "provider.test.success", - &[("status", "200")], - )); + black_box(UiLanguage::EnUs.tr_args("provider.test.success", &[("status", "200")])); } let template_ns = template_started.elapsed().as_nanos() / template_iterations; diff --git a/nebula_app/src/display/suggest_engine.rs b/nebula_app/src/display/suggest_engine.rs index c9cf7e9..ff9444c 100644 --- a/nebula_app/src/display/suggest_engine.rs +++ b/nebula_app/src/display/suggest_engine.rs @@ -235,8 +235,7 @@ pub(crate) fn suggest_update( // 远端目录是异步拉回来的,那一刻 cwd 与行都没变——少了这个代际,拉到的 // 条目要等用户再多打一个字符才会显形。 let remote_generation = crate::remote_dirs::generation(); - let key = - format!("{}\u{0}{line}\u{0}{command_generation}\u{0}{remote_generation}", state.cwd); + let key = format!("{}\u{0}{line}\u{0}{command_generation}\u{0}{remote_generation}", state.cwd); if state.completion_suppressed_line.as_deref() == Some(line.as_str()) { state.suggestion_key = key; state.suggestion.clear(); diff --git a/nebula_app/src/display/terminal_math.rs b/nebula_app/src/display/terminal_math.rs index 889c1c5..7db128d 100644 --- a/nebula_app/src/display/terminal_math.rs +++ b/nebula_app/src/display/terminal_math.rs @@ -2947,10 +2947,9 @@ mod tests { } // 同一批内容的行内形态被硬换行拆开时保持原文,不再跨行拼接。 assert!( - scan_grid(&TextGrid::from_rows(&[ - r"• $\lim_{x\to0}\frac{\sin", - r"x}{x}=1$,$PV=nRT$", - ])) + scan_grid(&TextGrid::from_rows( + &[r"• $\lim_{x\to0}\frac{\sin", r"x}{x}=1$,$PV=nRT$",] + )) .iter() .all(|overlay| !overlay.source.contains("lim")), "行内公式不得跨真实换行拼接" diff --git a/nebula_app/src/main.rs b/nebula_app/src/main.rs index 515fd70..f69d277 100644 --- a/nebula_app/src/main.rs +++ b/nebula_app/src/main.rs @@ -92,8 +92,8 @@ mod ssh_session; mod ssh_sftp; mod string; mod svn_status; -mod taskbar; mod sync; +mod taskbar; mod terminal_profiles; mod tray; mod update_check; diff --git a/nebula_app/src/panic.rs b/nebula_app/src/panic.rs index c363776..d3f85ec 100644 --- a/nebula_app/src/panic.rs +++ b/nebula_app/src/panic.rs @@ -25,9 +25,8 @@ pub fn attach_handler() { // MessageBox 的模态消息泵不能运行在发生 panic 的 GPUI 线程上,否则 // 会重入 AppCell 并把原始 panic 升级成无诊断信息的 double panic。 // 等待专用线程结束可保证主线程 unwind 退出前用户仍能看到并复制错误。 - if let Ok(dialog_thread) = thread::Builder::new() - .name("panic-dialog".into()) - .spawn(move || unsafe { + if let Ok(dialog_thread) = + thread::Builder::new().name("panic-dialog".into()).spawn(move || unsafe { MessageBoxW( ptr::null_mut(), dialog_message.as_ptr(), diff --git a/nebula_app/src/process_tree.rs b/nebula_app/src/process_tree.rs index c148b68..7466996 100644 --- a/nebula_app/src/process_tree.rs +++ b/nebula_app/src/process_tree.rs @@ -114,7 +114,10 @@ fn snapshot() -> Result, String> { let handle = unsafe { CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) }; if handle == INVALID_HANDLE_VALUE { - return Err(format!("CreateToolhelp32Snapshot failed: {}", std::io::Error::last_os_error())); + return Err(format!( + "CreateToolhelp32Snapshot failed: {}", + std::io::Error::last_os_error() + )); } let mut processes: HashMap = HashMap::new(); @@ -381,9 +384,7 @@ mod tests { /// 带自定义可执行名的进程表,用来构造「helper 上面隔着一层 shell」的链。 fn named_table(rows: &[(u32, u32, &str)]) -> HashMap { - rows.iter() - .map(|&(pid, parent, exe)| (pid, (parent, exe.to_owned()))) - .collect() + rows.iter().map(|&(pid, parent, exe)| (pid, (parent, exe.to_owned()))).collect() } /// hook helper 的父进程往往不是 agent 本身:Windows 上 claude 通过 diff --git a/nebula_app/src/remote_dirs.rs b/nebula_app/src/remote_dirs.rs index 2103f77..3db0a14 100644 --- a/nebula_app/src/remote_dirs.rs +++ b/nebula_app/src/remote_dirs.rs @@ -280,10 +280,11 @@ mod tests { assert!(!begin_fetch(&env, "/tmp/a"), "已经在拉了"); assert!(begin_fetch(&env, "/tmp/b"), "另一个目录不受影响"); - finish_fetch(&env, "/tmp/a", Some(vec![RemoteEntry { - name: "x".to_owned(), - is_dir: false, - }])); + finish_fetch( + &env, + "/tmp/a", + Some(vec![RemoteEntry { name: "x".to_owned(), is_dir: false }]), + ); assert!(lookup(&env, "/tmp/a").is_some(), "落了缓存"); assert!(begin_fetch(&env, "/tmp/a"), "拉完就解锁"); } diff --git a/nebula_app/src/runtime_api/cli.rs b/nebula_app/src/runtime_api/cli.rs index 52cb5dd..f8e175b 100644 --- a/nebula_app/src/runtime_api/cli.rs +++ b/nebula_app/src/runtime_api/cli.rs @@ -38,10 +38,7 @@ pub(super) fn request_once( Ok(serde_json::from_str(&line)?) } -pub(super) fn print_response( - response: &ApiResponse, - pretty: bool, -) -> Result<(), Box> { +pub(super) fn print_response(response: &ApiResponse, pretty: bool) -> Result<(), Box> { if pretty { println!("{}", serde_json::to_string_pretty(response)?); } else { @@ -225,8 +222,7 @@ fn run_cli_inner(options: ControlOptions) -> Result<(), Box> { print_response(&response, options.pretty) }, CliCommand::CloseWindow { window } => { - let response = - request_once("window.close", json!({ "window_id": window }), timeout)?; + let response = request_once("window.close", json!({ "window_id": window }), timeout)?; print_response(&response, options.pretty) }, CliCommand::Focus { window, pane } => { diff --git a/nebula_app/src/runtime_api/command.rs b/nebula_app/src/runtime_api/command.rs index 0763198..9dcf56a 100644 --- a/nebula_app/src/runtime_api/command.rs +++ b/nebula_app/src/runtime_api/command.rs @@ -238,10 +238,7 @@ impl RuntimeCommand { }, "tab.close" => { let params: TabTargetParams = parse_params(&request.params)?; - Ok(Self::CloseTab { - window_id: params.window_id, - tab_index: params.tab_index, - }) + Ok(Self::CloseTab { window_id: params.window_id, tab_index: params.tab_index }) }, "tab.rename" => { let params: RenameTabParams = parse_params(&request.params)?; @@ -555,9 +552,9 @@ fn validate_multiline_text(text: &str, label: &str) -> Result<(), ApiError> { ))); } if text.chars().any(|ch| ch.is_control() && !matches!(ch, '\n' | '\r' | '\t')) { - return Err(ApiError::invalid_params( - format!("{label} contains unsupported terminal control characters"), - )); + return Err(ApiError::invalid_params(format!( + "{label} contains unsupported terminal control characters" + ))); } Ok(()) } diff --git a/nebula_app/src/runtime_api/shortcuts.rs b/nebula_app/src/runtime_api/shortcuts.rs index 8e6788b..5fda978 100644 --- a/nebula_app/src/runtime_api/shortcuts.rs +++ b/nebula_app/src/runtime_api/shortcuts.rs @@ -34,9 +34,10 @@ use super::*; use crate::cli::{ AgentCommand, AgentOptions, AgentPasteOptions, AgentReadOptions, AgentSendOptions, AgentWaitOptions, EnvOptions, ListOptions, PaneCloseOptions, PaneCommand, PaneExecOptions, - PaneOptions, PanePasteOptions, PaneReadOptions, PaneResizeOptions, PaneSendOptions, PaneWaitOptions, - PaneZoomOptions, PasteSourceOptions, TabCloseOptions, TabCommand, TabMoveOptions, - TabRenameOptions, TabResourceOptions, WindowCloseOptions, WindowCommand, WindowResourceOptions, + PaneOptions, PanePasteOptions, PaneReadOptions, PaneResizeOptions, PaneSendOptions, + PaneWaitOptions, PaneZoomOptions, PasteSourceOptions, TabCloseOptions, TabCommand, + TabMoveOptions, TabRenameOptions, TabResourceOptions, WindowCloseOptions, WindowCommand, + WindowResourceOptions, }; use std::fs::File; use std::io::Read as _; @@ -153,11 +154,7 @@ pub fn agent(options: AgentOptions) -> Result<(), Box> { fn window_close(options: WindowCloseOptions) -> Result<(), Box> { let timeout = validated_timeout(options.timeout_ms)?; - let response = request_once( - "window.close", - json!({ "window_id": options.window }), - timeout, - )?; + let response = request_once("window.close", json!({ "window_id": options.window }), timeout)?; print_response(&response, options.output.pretty) } @@ -776,19 +773,15 @@ fn read_paste_source(source: PasteSourceOptions) -> Result Result> { let mut bytes = Vec::new(); - reader - .take((MAX_PROMPT_BYTES + 1) as u64) - .read_to_end(&mut bytes) - .map_err(|error| { - CliError::new("input_read_error", format!("could not read paste input {label}: {error}")) - })?; + reader.take((MAX_PROMPT_BYTES + 1) as u64).read_to_end(&mut bytes).map_err(|error| { + CliError::new("input_read_error", format!("could not read paste input {label}: {error}")) + })?; if bytes.len() > MAX_PROMPT_BYTES { return Err(CliError::new( "invalid_params", @@ -797,11 +790,8 @@ fn read_paste_utf8(reader: impl Read, label: &str) -> Result Result<(), ApiError> { + pub(crate) fn runtime_set_zoom(&mut self, pane_id: u64, zoomed: bool) -> Result<(), ApiError> { let Some(tab_index) = self.tabs.iter().position(|tab| { let mut panes = Vec::new(); tab.layout.leaves(&mut panes); @@ -344,11 +340,7 @@ impl WindowContext { Ok(()) } - pub(crate) fn runtime_resize_pane( - &mut self, - pane_id: u64, - ratio: f32, - ) -> Result<(), ApiError> { + pub(crate) fn runtime_resize_pane(&mut self, pane_id: u64, ratio: f32) -> Result<(), ApiError> { let Some(tab_index) = self.tabs.iter().position(|tab| { let mut panes = Vec::new(); tab.layout.leaves(&mut panes); diff --git a/nebula_app/src/window_context/split.rs b/nebula_app/src/window_context/split.rs index c08bcc8..05e5fdc 100644 --- a/nebula_app/src/window_context/split.rs +++ b/nebula_app/src/window_context/split.rs @@ -133,15 +133,7 @@ impl Layout { /// 设置目标 pane 在最近父 Split 中占用的比例。内部 ratio 描述 first, /// 因此 second 侧目标要换算成 `1 - target_ratio`。 pub(super) fn set_leaf_parent_ratio(&mut self, target: PaneId, target_ratio: f32) -> bool { - let Layout::Split { - ratio, - preview_ratio, - dragging, - first, - second, - .. - } = self - else { + let Layout::Split { ratio, preview_ratio, dragging, first, second, .. } = self else { return false; }; diff --git a/nebula_app/tests/file_line_budget.rs b/nebula_app/tests/file_line_budget.rs index d25cba1..4c89cf5 100644 --- a/nebula_app/tests/file_line_budget.rs +++ b/nebula_app/tests/file_line_budget.rs @@ -1,118 +1,118 @@ -//! 文件行数预算守护(docs/project-constraints.md 第 1 条)。 -//! -//! 单个 `.rs` 文件硬上限 2000 行;存量超标文件在 [`GRANDFATHERED`] 登记, -//! 登记值只允许下调。测试失败的正确动作是拆文件,不是上调预算。 - -use std::fs; -use std::path::{Path, PathBuf}; - -/// 新代码红线:超过它就必须拆(docs/project-constraints.md)。 -const MAX_LINES: usize = 2000; - -/// 存量豁免清单(相对仓库根,正斜杠路径 → 行数上限)。 -/// -/// 登记值 = 收录当天的行数加不足百行的呼吸空间:小修小补不触线,成规模 -/// 新增必须伴随拆分。拆小后同步下调或删除对应条目。 -const GRANDFATHERED: &[(&str, usize)] = &[ - ("nebula_app/src/display/mod.rs", 12000), - ("nebula_app/src/display/settings.rs", 8650), - // 2026-08-17 上调(4850 → 5150):git 树 VS Code 化 + 源码 tab 接线; - // 下一步应把 VCS 面板拆成独立文件后下调。 - ("nebula_app/src/gpui_shell/workspace.rs", 5150), - // 2026-08-17 下调(3600 → 3550):网络区拆到 network_settings.rs。 - ("nebula_app/src/gpui_shell/settings_pane.rs", 3550), - ("nebula_app/src/display/command_palette.rs", 3980), - ("nebula_app/src/window_context.rs", 3800), - ("nebula_app/src/event.rs", 3780), - ("nebula_terminal/src/term/mod.rs", 3650), - // 2026-08-17 上调(2900 → 2970):draw_overlays 几何抽成两壳共享的 plan。 - ("nebula_app/src/display/terminal_math.rs", 2970), - // 2026-08-17 上调(2680 → 2760):SVN wc.db 回退 + 单文件 stage/discard。 - ("nebula_app/src/display/side_panel.rs", 2760), - ("nebula_app/src/gpui_shell/terminal/view.rs", 2540), - ("nebula_app/src/display/chrome.rs", 2550), - ("nebula_app/src/display/markdown_view.rs", 2150), -]; - -/// 这些目录不受预算约束:构建产物、vendored 第三方代码、版本库内部。 -fn excluded(component: &str) -> bool { - component == ".git" - || component == "third_party" - || component == "target" - || component.starts_with(".target") -} - -fn collect_rust_files(root: &Path, out: &mut Vec) { - let Ok(entries) = fs::read_dir(root) else { - return; - }; - for entry in entries.flatten() { - let path = entry.path(); - let name = entry.file_name(); - let name = name.to_string_lossy(); - // 隐藏项(.git、.tmp_* 草稿等)不是源码,不受预算约束。 - if name.starts_with('.') { - continue; - } - if path.is_dir() { - if !excluded(&name) { - collect_rust_files(&path, out); - } - } else if path.extension().is_some_and(|extension| extension == "rs") { - out.push(path); - } - } -} - -#[test] -fn every_source_file_respects_its_line_budget() { - let repo_root = Path::new(env!("CARGO_MANIFEST_DIR")) - .parent() - .expect("nebula_app sits directly under the repo root") - .to_path_buf(); - - let mut files = Vec::new(); - collect_rust_files(&repo_root, &mut files); - assert!( - files.len() > 100, - "行数守护扫到的文件数异常({}),排除规则可能吞掉了源码目录", - files.len() - ); - - let mut violations = Vec::new(); - let mut stale_grants = Vec::new(); - for path in files { - let relative = path - .strip_prefix(&repo_root) - .expect("collected files live under the repo root") - .to_string_lossy() - .replace('\\', "/"); - let Ok(content) = fs::read(&path) else { - panic!("无法读取 {relative}"); - }; - // 按换行字节计数:与编码无关,空文件为 0 行。 - let lines = content.iter().filter(|byte| **byte == b'\n').count() - + usize::from(!content.is_empty() && content.last() != Some(&b'\n')); - let grant = - GRANDFATHERED.iter().find(|(name, _)| *name == relative).map(|(_, budget)| *budget); - let budget = grant.unwrap_or(MAX_LINES); - if lines > budget { - violations.push(format!("{relative}: {lines} 行 > 预算 {budget}")); - } - // 豁免文件瘦身到红线以内后,条目必须删除,防止预算复胖。 - if let Some(budget) = grant - && lines <= MAX_LINES - { - stale_grants.push(format!( - "{relative}: 已降到 {lines} 行(≤{MAX_LINES}),豁免条目({budget})应删除" - )); - } - } - - assert!( - violations.is_empty(), - "以下文件超出行数预算(docs/project-constraints.md 第 1 条,正确动作是拆文件):\n{}", - violations.join("\n") - ); - assert!(stale_grants.is_empty(), "以下豁免条目已过期:\n{}", stale_grants.join("\n")); -} +//! 文件行数预算守护(docs/project-constraints.md 第 1 条)。 +//! +//! 单个 `.rs` 文件硬上限 2000 行;存量超标文件在 [`GRANDFATHERED`] 登记, +//! 登记值只允许下调。测试失败的正确动作是拆文件,不是上调预算。 + +use std::fs; +use std::path::{Path, PathBuf}; + +/// 新代码红线:超过它就必须拆(docs/project-constraints.md)。 +const MAX_LINES: usize = 2000; + +/// 存量豁免清单(相对仓库根,正斜杠路径 → 行数上限)。 +/// +/// 登记值 = 收录当天的行数加不足百行的呼吸空间:小修小补不触线,成规模 +/// 新增必须伴随拆分。拆小后同步下调或删除对应条目。 +const GRANDFATHERED: &[(&str, usize)] = &[ + ("nebula_app/src/display/mod.rs", 12000), + ("nebula_app/src/display/settings.rs", 8650), + // 2026-08-17 上调(4850 → 5150):git 树 VS Code 化 + 源码 tab 接线; + // 下一步应把 VCS 面板拆成独立文件后下调。 + ("nebula_app/src/gpui_shell/workspace.rs", 5150), + // 2026-08-17 下调(3600 → 3550):网络区拆到 network_settings.rs。 + ("nebula_app/src/gpui_shell/settings_pane.rs", 3550), + ("nebula_app/src/display/command_palette.rs", 3980), + ("nebula_app/src/window_context.rs", 3800), + ("nebula_app/src/event.rs", 3780), + ("nebula_terminal/src/term/mod.rs", 3650), + // 2026-08-17 上调(2900 → 2970):draw_overlays 几何抽成两壳共享的 plan。 + ("nebula_app/src/display/terminal_math.rs", 2970), + // 2026-08-17 上调(2680 → 2760):SVN wc.db 回退 + 单文件 stage/discard。 + ("nebula_app/src/display/side_panel.rs", 2760), + ("nebula_app/src/gpui_shell/terminal/view.rs", 2540), + ("nebula_app/src/display/chrome.rs", 2550), + ("nebula_app/src/display/markdown_view.rs", 2150), +]; + +/// 这些目录不受预算约束:构建产物、vendored 第三方代码、版本库内部。 +fn excluded(component: &str) -> bool { + component == ".git" + || component == "third_party" + || component == "target" + || component.starts_with(".target") +} + +fn collect_rust_files(root: &Path, out: &mut Vec) { + let Ok(entries) = fs::read_dir(root) else { + return; + }; + for entry in entries.flatten() { + let path = entry.path(); + let name = entry.file_name(); + let name = name.to_string_lossy(); + // 隐藏项(.git、.tmp_* 草稿等)不是源码,不受预算约束。 + if name.starts_with('.') { + continue; + } + if path.is_dir() { + if !excluded(&name) { + collect_rust_files(&path, out); + } + } else if path.extension().is_some_and(|extension| extension == "rs") { + out.push(path); + } + } +} + +#[test] +fn every_source_file_respects_its_line_budget() { + let repo_root = Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .expect("nebula_app sits directly under the repo root") + .to_path_buf(); + + let mut files = Vec::new(); + collect_rust_files(&repo_root, &mut files); + assert!( + files.len() > 100, + "行数守护扫到的文件数异常({}),排除规则可能吞掉了源码目录", + files.len() + ); + + let mut violations = Vec::new(); + let mut stale_grants = Vec::new(); + for path in files { + let relative = path + .strip_prefix(&repo_root) + .expect("collected files live under the repo root") + .to_string_lossy() + .replace('\\', "/"); + let Ok(content) = fs::read(&path) else { + panic!("无法读取 {relative}"); + }; + // 按换行字节计数:与编码无关,空文件为 0 行。 + let lines = content.iter().filter(|byte| **byte == b'\n').count() + + usize::from(!content.is_empty() && content.last() != Some(&b'\n')); + let grant = + GRANDFATHERED.iter().find(|(name, _)| *name == relative).map(|(_, budget)| *budget); + let budget = grant.unwrap_or(MAX_LINES); + if lines > budget { + violations.push(format!("{relative}: {lines} 行 > 预算 {budget}")); + } + // 豁免文件瘦身到红线以内后,条目必须删除,防止预算复胖。 + if let Some(budget) = grant + && lines <= MAX_LINES + { + stale_grants.push(format!( + "{relative}: 已降到 {lines} 行(≤{MAX_LINES}),豁免条目({budget})应删除" + )); + } + } + + assert!( + violations.is_empty(), + "以下文件超出行数预算(docs/project-constraints.md 第 1 条,正确动作是拆文件):\n{}", + violations.join("\n") + ); + assert!(stale_grants.is_empty(), "以下豁免条目已过期:\n{}", stale_grants.join("\n")); +} diff --git a/nebula_hook/src/main.rs b/nebula_hook/src/main.rs index 48652ce..8f274b3 100644 --- a/nebula_hook/src/main.rs +++ b/nebula_hook/src/main.rs @@ -244,9 +244,7 @@ fn base64_encode(input: &[u8]) -> String { #[cfg(test)] mod tests { - use super::{ - FOREIGN_HOOK_RUNNERS, Outcome, base64_encode, foreign_hook_runner, outcome_line, - }; + use super::{FOREIGN_HOOK_RUNNERS, Outcome, base64_encode, foreign_hook_runner, outcome_line}; #[test] fn encodes_remote_hook_payload() { diff --git a/nebula_settings/src/lib.rs b/nebula_settings/src/lib.rs index 32a2e9b..e7b6f75 100644 --- a/nebula_settings/src/lib.rs +++ b/nebula_settings/src/lib.rs @@ -443,11 +443,8 @@ impl ThemeName { /// 两块深色面板会糊成一片,竖线是这种形态下唯一的结构分界。 pub fn card_geometry(self) -> ThemeCardGeometry { match self { - Self::Nord => ThemeCardGeometry { - radius: 0.0, - gutter: 0.0, - shadow: false, - divider: 1.0, + Self::Nord => { + ThemeCardGeometry { radius: 0.0, gutter: 0.0, shadow: false, divider: 1.0 } }, _ => ThemeCardGeometry { radius: DEFAULT_PANE_CARD_RADIUS, diff --git a/nebula_split/src/lib.rs b/nebula_split/src/lib.rs index 8807d84..44ff7b9 100644 --- a/nebula_split/src/lib.rs +++ b/nebula_split/src/lib.rs @@ -231,15 +231,7 @@ impl SplitTree { /// pane;目标在第二侧时必须写成 `1 - target_ratio`。递归到最近父节点再 /// 修改,避免嵌套 pane 的 resize 错改祖先 Split。 pub fn set_leaf_parent_ratio(&mut self, target: T, target_ratio: f32) -> bool { - let SplitTree::Split { - ratio, - preview_ratio, - dragging, - first, - second, - .. - } = self - else { + let SplitTree::Split { ratio, preview_ratio, dragging, first, second, .. } = self else { return false; };