#!/bin/bash set -euo pipefail # --- Defaults --- COPY=true CLIP_CMD="" # --- Detect clipboard tool --- detect_clipboard() { if command -v xclip &> /dev/null; then CLIP_CMD="xclip -selection clipboard" elif command -v xsel &> /dev/null; then CLIP_CMD="xsel --clipboard --input" else CLIP_CMD="" fi } # --- Help --- usage() { cat << 'EOF' cat-md — concatenate files as a Markdown code block, copy to clipboard. Usage: cat-md [OPTIONS] [FILE|DIR]... Each file is printed as: path/to/file: `` ` `` ` Directories are expanded non-recursively (all files inside). Options: -n, --no-copy Print to stdout only, skip clipboard copy -h, --help Show this help and exit Examples: cat-md file1.txt file2.txt cat-md src/ cat-md -n file.txt # no clipboard cat-md file.txt | wl-copy # Wayland clipboard (manual override) Requirements (one of): xclip — X11 clipboard (preferred) xsel — alternative X11 clipboard tool EOF exit 0 } # --- Parse arguments --- ARGS=() while [[ $# -gt 0 ]]; do case "$1" in -n | --no-copy) COPY=false shift ;; -h | --help) usage ;; --) shift ARGS+=("$@") break ;; -*) echo "Unknown option: $1" >&2 echo "Try -h for help." >&2 exit 1 ;; *) ARGS+=("$1") shift ;; esac done # --- Validate --- if [[ ${#ARGS[@]} -eq 0 ]]; then echo "Error: no files or directories provided. Try -h for help." >&2 exit 1 fi detect_clipboard if $COPY && [[ -z "$CLIP_CMD" ]]; then echo "Warning: neither xclip nor xsel found. Output will go to stdout only." >&2 COPY=false fi # --- Generate output --- generate() { for path in "$@"; do if [[ -d "$path" ]]; then for file in "$path"/*; do if [[ -f "$file" ]]; then generate "$file" fi done elif [[ -f "$path" ]]; then echo "$path:" echo '```' cat "$path" echo echo '```' echo fi done } if $COPY; then generate "${ARGS[@]}" | $CLIP_CMD echo "Copied to clipboard." >&2 else generate "${ARGS[@]}" fi