#!/usr/bin/env bash set -efu input_file=${1-/dev/stdin} # note: merge sibling comments into matched comment blocks, as tree-sitter does # not allow for matching sibling nodes function merge_matches() { matches=$(jq -c .matches[]) new_matches= last_match= new_match= while read -r cur_match; do if test -z "$new_match"; then new_match=$cur_match fi if ! test -z "$last_match"; then last_end_row=$(echo "$last_match" | jq -r .end.row) cur_start_row=$(echo "$cur_match" | jq -r .start.row) if test "$(($last_end_row + 1))" = "$cur_start_row"; then new_text=$(echo "$new_match" | jq -r .text) cur_text=$(echo "$cur_match" | jq -r .text) text=$(printf "%s\n%s" "$new_text" "$cur_text") end=$(echo "$cur_match" | jq -c .end) new_match=$( echo "$new_match" | # XXX "$end" seems to be forbidden as variable name jq -c \ --argjson end_ "$end" \ --arg text "$text" \ '. + { "end": $end_, "text": $text }' ) else new_matches=$(printf "%s\n%s" "$new_matches" "$new_match") new_match=$cur_match fi fi last_match=$cur_match done <<< "$matches" if ! test -z "$new_match"; then new_matches=$(printf "%s\n%s" "$new_matches" "$new_match") fi new_matches=$(echo "$new_matches" | jq -cs .) echo "$line" | jq -c --argjson matches "$new_matches" '. + { "matches": $matches }' } tree-grepper \ --query "$TREE_GREPPER_LANGUAGE" "$TREE_GREPPER_QUERY" \ --format json $input_file | jq -c '.[]' | while read -r line; do echo "$line" | merge_matches done | while read -r line; do file=$(echo "$line" | jq -r .file) file_type=$(echo "$line" | jq -r .file_type) items=$(echo "$line" | jq '.matches[] | { file: $file, file_type: $file_type, match: . }' --arg file "$file" --arg file_type "$file_type" | jq '. | select(.match.text | test("TODO .+"))' ) if test -z "$items"; then continue fi echo "$items" | jq --slurp '.[]' --indent 0 | while read -r item; do start_row=$(echo "$item" | jq '.match.start.row') end_row=$(echo "$item" | jq '.match.end.row') last_commit=$(git --no-pager blame -L "$start_row,$start_row" "$file" -p | head -n 1 | cut -d ' ' -f 1 ) text=$(echo "$item" | jq .match.text -r | sed 's/^'"$LINE_COMMENT_START"'\( *TODO *\| \?\)//g' | { if test -z "${BLOCK_COMMENT_START-}"; then cat else sed 's/^'"$BLOCK_COMMENT_START"'\( *TODO *\| \?\)//' fi } | { if test -z "${BLOCK_COMMENT_END-}"; then cat else sed 's/ *'"$BLOCK_COMMENT_END"' *$//' fi } ) echo "$item" | jq '. + {"text": $text, "last_commit": $last_commit}' \ --arg text "$text" \ --arg last_commit "$last_commit" \ -c done done