generate_commands_markdown.sh 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. PROJECT_PATH="."
  4. OUTPUT_FILE="COMMANDS.md"
  5. declare -A VISITED
  6. # Create temp files for the Tree structure and the Body content
  7. TREE_TEMP=$(mktemp)
  8. BODY_TEMP=$(mktemp)
  9. # Ensure temp files are cleaned up when script exits
  10. trap 'rm -f "$TREE_TEMP" "$BODY_TEMP"' EXIT
  11. # ----------------------------
  12. # Helpers
  13. # ----------------------------
  14. strip_colors() {
  15. sed -r "s/\x1B\[[0-9;]*[mK]//g"
  16. }
  17. run_help() {
  18. local project="./RackPeek"
  19. local runtime="osx-arm64"
  20. local config="Release"
  21. local publish_dir="$project/bin/$config/net10.0/$runtime/publish"
  22. local exe="$publish_dir/RackPeek"
  23. if [[ ! -x "$exe" ]]; then
  24. echo "Publishing RackPeek ($config)..." >&2
  25. if ! dotnet publish "$project" \
  26. -c "$config" \
  27. -r "$runtime" \
  28. --self-contained false \
  29. -p:PublishSingleFile=true; then
  30. echo "ERROR: dotnet publish failed" >&2
  31. return 1
  32. fi
  33. fi
  34. echo "Running: $exe $*" >&2
  35. local output
  36. if ! output=$("$exe" "$@" 2>&1 | strip_colors); then
  37. echo "WARNING: command failed: $exe $*" >&2
  38. echo "$output" >&2
  39. return 1
  40. fi
  41. echo "$output"
  42. }
  43. get_commands() {
  44. local help_output="$1"
  45. echo "$help_output" | awk '
  46. BEGIN { in_commands = 0 }
  47. /^COMMANDS:/ { in_commands = 1; next }
  48. in_commands {
  49. if ($0 ~ /^[[:space:]]{4}[a-zA-Z0-9-]+[[:space:]]+/) {
  50. print $1
  51. next
  52. }
  53. if ($0 !~ /^[[:space:]]*$/) {
  54. exit
  55. }
  56. }
  57. '
  58. }
  59. # ----------------------------
  60. # Recursion
  61. # ----------------------------
  62. generate_help_recursive() {
  63. local current_path=("$@")
  64. local flat_cmd="${current_path[*]}"
  65. local map_key="${flat_cmd:-root}"
  66. # --- TREE GENERATION LOGIC ---
  67. # 1. Calculate depth for indentation (2 spaces per level)
  68. local depth=${#current_path[@]}
  69. local indent=""
  70. if [[ $depth -gt 0 ]]; then
  71. printf -v indent "%*s" $((depth * 2)) ""
  72. fi
  73. # 2. Determine the display label for the tree (Leaf name only)
  74. local tree_label
  75. if [[ $depth -eq 0 ]]; then
  76. tree_label="rpk"
  77. else
  78. tree_label="${current_path[-1]}" # Last element of array
  79. fi
  80. # 3. Create a clean anchor link for Markdown (lowercase, replace spaces with dashes)
  81. # e.g., "rpk switches list" -> "#rpk-switches-list"
  82. local anchor_text="rpk $flat_cmd"
  83. # Trim leading space if flat_cmd was empty
  84. anchor_text="${anchor_text% }"
  85. local anchor_link
  86. anchor_link=$(echo "$anchor_text" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
  87. # 4. Append to Tree Temp File
  88. echo "${indent}- [${tree_label}](Commands.md#${anchor_link})" >> "$TREE_TEMP"
  89. # -----------------------------
  90. if [[ -n "${VISITED["$map_key"]:-}" ]]; then
  91. return
  92. fi
  93. VISITED["$map_key"]=1
  94. local help_output
  95. if ! help_output=$(run_help "${current_path[@]}" --help); then
  96. echo "Skipping: $map_key (help failed)" >&2
  97. return
  98. fi
  99. # --- BODY GENERATION ---
  100. # Determine header title
  101. local display_header
  102. if [[ -z "$flat_cmd" ]]; then
  103. display_header="rpk"
  104. else
  105. display_header="rpk $flat_cmd"
  106. fi
  107. {
  108. echo "## \`${display_header}\`"
  109. echo '```'
  110. echo "$help_output"
  111. echo '```'
  112. echo ""
  113. } >> "$BODY_TEMP"
  114. # -----------------------
  115. local commands
  116. mapfile -t commands < <(get_commands "$help_output")
  117. for cmd in "${commands[@]}"; do
  118. echo "Recursing into: ${display_header} ${cmd}" >&2
  119. generate_help_recursive "${current_path[@]}" "$cmd"
  120. done
  121. }
  122. # ----------------------------
  123. # Main
  124. # ----------------------------
  125. echo "Generating documentation..."
  126. # Start recursion
  127. generate_help_recursive
  128. # Write command index
  129. {
  130. echo "# CLI Command Index"
  131. echo ""
  132. cat "$TREE_TEMP"
  133. } > "CommandIndex.md"
  134. # Write full command documentation
  135. {
  136. echo "# CLI Commands"
  137. echo ""
  138. cat "$BODY_TEMP"
  139. } > "Commands.md"
  140. echo "Generated $OUTPUT_FILE successfully."