Build a structured outline of a large file instead of returning all content. For markdown: extracts headings with line numbers. For code: extracts function/class signatures using simple heuristics. Always includes the first 20 lines as context.
(path: &str, content: &str, total_lines: usize)
| 1042 | /// For code: extracts function/class signatures using simple heuristics. |
| 1043 | /// Always includes the first 20 lines as context. |
| 1044 | fn build_file_outline(path: &str, content: &str, total_lines: usize) -> String { |
| 1045 | let mut out = format!( |
| 1046 | "File: {} ({} lines, {} bytes)\n\ |
| 1047 | Use read_file with start_line/end_line to read specific sections.\n\n", |
| 1048 | path, |
| 1049 | total_lines, |
| 1050 | content.len() |
| 1051 | ); |
| 1052 | |
| 1053 | let is_markdown = path.ends_with(".md") || path.ends_with(".mdx"); |
| 1054 | |
| 1055 | if is_markdown { |
| 1056 | // Extract headings with line numbers |
| 1057 | out.push_str("Outline (headings):\n"); |
| 1058 | for (i, line) in content.lines().enumerate() { |
| 1059 | let trimmed = line.trim(); |
| 1060 | if trimmed.starts_with('#') { |
| 1061 | out.push_str(&format!(" L{}: {}\n", i + 1, trimmed)); |
| 1062 | } |
| 1063 | } |
| 1064 | } else { |
| 1065 | // For code files, show the first 30 lines + any lines that look like |
| 1066 | // definitions (fn, class, struct, def, func, impl, etc.) |
| 1067 | out.push_str("First 20 lines:\n"); |
| 1068 | for (i, line) in content.lines().take(20).enumerate() { |
| 1069 | out.push_str(&format!(" {:>4}: {}\n", i + 1, line)); |
| 1070 | } |
| 1071 | out.push_str("\nDefinitions found:\n"); |
| 1072 | let def_patterns = [ |
| 1073 | "fn ", |
| 1074 | "pub fn ", |
| 1075 | "async fn ", |
| 1076 | "def ", |
| 1077 | "func ", |
| 1078 | "function ", |
| 1079 | "class ", |
| 1080 | "struct ", |
| 1081 | "enum ", |
| 1082 | "trait ", |
| 1083 | "impl ", |
| 1084 | "interface ", |
| 1085 | "type ", |
| 1086 | "const ", |
| 1087 | "#define ", |
| 1088 | "namespace ", |
| 1089 | ]; |
| 1090 | for (i, line) in content.lines().enumerate() { |
| 1091 | let trimmed = line.trim(); |
| 1092 | if def_patterns.iter().any(|p| trimmed.starts_with(p)) { |
| 1093 | let short = if trimmed.len() > 100 { |
| 1094 | format!("{}...", &trimmed[..97]) |
| 1095 | } else { |
| 1096 | trimmed.to_string() |
| 1097 | }; |
| 1098 | out.push_str(&format!(" L{}: {}\n", i + 1, short)); |
| 1099 | } |
| 1100 | } |
| 1101 | } |
no test coverage detected