lean_ctx/rules_inject/
content.rs1use std::path::{Path, PathBuf};
8
9use super::RulesFormat;
10use crate::core::config::CompressionLevel;
11use crate::core::rules_canonical::{self as rc, Wrapper};
12
13pub(super) fn cursor_wrapper_for_mdc(mdc_path: &Path) -> Wrapper {
19 let covered = mdc_path
20 .parent()
21 .and_then(Path::parent)
22 .is_some_and(|cursor_dir| {
23 crate::core::rules_channel::cursor_hooks_json_covers(&cursor_dir.join("hooks.json"))
24 });
25 if covered {
26 Wrapper::HookCovered
27 } else {
28 Wrapper::Dedicated
29 }
30}
31
32pub(crate) fn cursor_mdc_document(body: &str) -> String {
36 format!(
37 "---\n\
38 description: \"lean-ctx: context compression layer — \
39 tool guidance in rule body.\"\n\
40 globs: **/*\n\
41 alwaysApply: true\n\
42 ---\n\n\
43 {body}"
44 )
45}
46
47pub(super) fn rules_content(
48 format: &RulesFormat,
49 level: CompressionLevel,
50 wrapper: Wrapper,
51) -> String {
52 let shadow = crate::core::config::Config::load().shadow_mode;
53 match format {
54 RulesFormat::SharedMarkdown => rc::render(shadow, Wrapper::Shared, level),
55 RulesFormat::DedicatedMarkdown => rc::render(shadow, Wrapper::Dedicated, level),
56 RulesFormat::CursorMdc => cursor_mdc_document(&rc::render(shadow, wrapper, level)),
57 }
58}
59
60pub fn opencode_dedicated_rules_path(home: &std::path::Path) -> PathBuf {
61 home.join(".config/opencode/rules/lean-ctx.md")
62}
63
64pub fn gemini_dedicated_rules_path(home: &std::path::Path) -> PathBuf {
65 home.join(".gemini").join(GEMINI_DEDICATED_CONTEXT_FILENAME)
66}
67
68pub const GEMINI_DEDICATED_CONTEXT_FILENAME: &str = "LEANCTX.md";