You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
2.7 KiB
130 lines
2.7 KiB
#!/bin/bash |
|
|
|
set -euo pipefail |
|
|
|
# --- Defaults --- |
|
COPY=true |
|
CLIP_CMD=() |
|
|
|
# --- Detect clipboard tool --- |
|
detect_clipboard() { |
|
# Pick the right tool for the session: |
|
# wl-copy on Wayland, xclip/xsel on X11. Fall back to whatever exists. |
|
if [[ "${XDG_SESSION_TYPE:-}" == "wayland" || -n "${WAYLAND_DISPLAY:-}" ]]; then |
|
if command -v wl-copy &> /dev/null; then |
|
CLIP_CMD=(wl-copy) |
|
elif command -v xclip &> /dev/null; then |
|
CLIP_CMD=(xclip -selection clipboard) |
|
elif command -v xsel &> /dev/null; then |
|
CLIP_CMD=(xsel --clipboard --input) |
|
fi |
|
else |
|
if command -v xclip &> /dev/null; then |
|
CLIP_CMD=(xclip -selection clipboard) |
|
elif command -v xsel &> /dev/null; then |
|
CLIP_CMD=(xsel --clipboard --input) |
|
elif command -v wl-copy &> /dev/null; then |
|
CLIP_CMD=(wl-copy) |
|
fi |
|
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: |
|
``` |
|
<contents> |
|
``` |
|
|
|
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 -n file.txt | less # pipe manually |
|
|
|
Requirements (one of): |
|
wl-copy — Wayland clipboard (from wl-clipboard) |
|
xclip — X11 clipboard (preferred on X11) |
|
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 && [[ ${#CLIP_CMD[@]} -eq 0 ]]; then |
|
echo "Warning: no clipboard tool found (tried wl-copy, xclip, xsel). 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
|
|
|