# 函数:glance - 快速概览目录内容 # # 作者: Gemini & anduin # 功能: # - 自动检测 Git 仓库,智能选择文件列表模式。 # - 动态计算并调整 tree 的显示深度。 # - 文件内容输出严格遵循 tree 的显示深度。 # - 限制单个文件的最大输出行数。 # - 支持按文件名模式筛选文件。 # # 用法: # glance [目录] [选项...] # # 选项: # --max-files-preview <数量> : tree 显示的最大条目数 (默认: 100) # --max-file-lines <数量> : 单个文件的最大显示行数 (默认: 150) # --filter <模式> : 按扩展名筛选,逗号分隔 (例: '*.md,*.cs') # glance() { local target_dir="." local max_items_preview=100 local max_file_lines=150 local filter_patterns="" local positional_args=() # --- 内部辅助函数:处理单个文件的打印 (无改动) --- _glance_process_file() { local file="$1" if [ ! -f "$file" ]; then return; fi if file -b --mime-type "$file" | grep -q '^text/'; then local total_lines; total_lines=$(wc -l < "$file") local extension="${file##*.}"; local lang="" case "$extension" in js) lang="javascript" ;; py) lang="python" ;; rb) lang="ruby" ;; sh) lang="bash" ;; css) lang="css" ;; html) lang="html" ;; json) lang="json" ;; md) lang="markdown" ;; yml|yaml) lang="yaml" ;; java) lang="java" ;; c) lang="c" ;; cpp) lang="cpp" ;; go) lang="go" ;; *) lang="" ;; esac echo; echo "Content of file \"$file\":"; echo "\`\`\`$lang" if [ "$total_lines" -gt "$max_file_lines" ]; then head -n "$max_file_lines" "$file"; echo; echo "... (Only shown top $max_file_lines lines of $total_lines) ..." else cat "$file" fi echo; echo "\`\`\`"; echo "----------------------------------------------------------" else echo; echo "--> 已跳过二进制文件: \"$file\""; echo "----------------------------------------------------------" fi } # --- 步骤 1: 解析参数 --- while [[ $# -gt 0 ]]; do case "$1" in --max-files-preview) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then max_items_preview="$2"; shift 2; else echo "错误: '--max-files-preview' 需要一个正整数参数。" >&2; return 1; fi ;; --max-file-lines) if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then max_file_lines="$2"; shift 2; else echo "错误: '--max-file-lines' 需要一个正整数参数。" >&2; return 1; fi ;; --filter) if [[ -n "$2" && "$2" != -* ]]; then filter_patterns="$2"; shift 2; else echo "错误: '--filter' 需要一个模式字符串参数。" >&2; return 1; fi ;; -*) echo "错误: 未知选项 '$1'" >&2; return 1 ;; *) positional_args+=("$1"); shift ;; esac done [[ ${#positional_args[@]} -gt 0 ]] && target_dir="${positional_args[0]}" # --- 步骤 2: 依赖和目录检查 --- if ! command -v tree &>/dev/null; then echo "错误: 'tree' 命令未找到。" >&2; return 1; fi if [ ! -d "$target_dir" ]; then echo "错误: 目录 '$target_dir' 不存在。" >&2; return 1; fi echo "==========================================================" echo "🔎 概览目录: $(realpath "$target_dir")" echo "==========================================================" echo # --- 步骤 3: 动态计算 tree 的最佳深度 (基于未筛选的完整目录) --- echo "🌳 目录结构:" local best_depth=1; local max_depth_to_check=6; local prev_item_count=-1 for depth in $(seq 1 $max_depth_to_check); do local current_item_count; current_item_count=$(tree -L "$depth" -a --noreport "$target_dir" | wc -l) if [ "$depth" -gt 1 ] && [ "$current_item_count" -gt "$max_items_preview" ]; then best_depth=$((depth - 1)); break; fi if [ "$depth" -gt 1 ] && [ "$current_item_count" -eq "$prev_item_count" ]; then best_depth=$depth; break; fi best_depth=$depth; prev_item_count=$current_item_count done # --- 步骤 3.5: 应用筛选并打印 tree --- local tree_args=(-L "$best_depth") if [ -n "$filter_patterns" ]; then local tree_pattern; tree_pattern=$(echo "$filter_patterns" | tr ',' '|') tree_args+=(-P "$tree_pattern") echo "(筛选模式: ${filter_patterns})" fi echo "(动态调整深度至 L${best_depth} 以适应预览数限制: ${max_items_preview})" tree "${tree_args[@]}" "$target_dir" echo # --- 步骤 4: 遍历并打印文件内容 (应用筛选和深度限制) --- local header_suffix="" if [ -n "$filter_patterns" ]; then header_suffix=" (筛选: ${filter_patterns})"; fi echo "📄 文件内容详情 (深度 L${best_depth} 以内, 单文件最多 ${max_file_lines} 行${header_suffix}):" ( cd "$target_dir" || exit 1 echo "----------------------------------------------------------" local filter_array=() [ -n "$filter_patterns" ] && IFS=',' read -ra filter_array <<< "$filter_patterns" if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then # Git 模式 local git_files if [ ${#filter_array[@]} -gt 0 ]; then git_files=$(git ls-files -- "${filter_array[@]}") else git_files=$(git ls-files) fi echo "$git_files" | awk -F'/' -v depth="$best_depth" 'NF <= depth' | while read -r file; do _glance_process_file "$file" done else # 普通模式 local find_args=(-maxdepth "$best_depth" -type f) if [ ${#filter_array[@]} -gt 0 ]; then find_args+=("(") for i in "${!filter_array[@]}"; do [ "$i" -ne 0 ] && find_args+=("-o") find_args+=(-name "${filter_array[$i]}") done find_args+=(")") fi find . "${find_args[@]}" | while read -r file; do _glance_process_file "${file#./}" done fi ) }