#!/bin/sh # The MIT License (MIT) # # Copyright (c) 2026 pacman64 # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # mapa [options...] [regular expressions...] # # # MAtch PAragraphs only keeps multi-line paragraphs which match any of the # extended-mode regular expressions given. When not given any regex, match # all paragraphs by default. Input lines are always read from the standard # input. # # Each paragraph is defined as 1 or more consecutive non-empty lines. Each # paragraph is matched either as read, with line-feeds along the way, or # with each inner line-feed replaced by a single space. # # The handy case-insensitive shortcut options may cause this tool to fail, # if the main `awk` tool installed doesn't support the special `IGNORECASE` # variable. # # The options are, available both in single and double-dash versions # # -h, -help show this help message # -i, -ins match regexes case-insensitively # -l, -links add a regex to match HTTP/HTTPS links case-insensitively # -q, -quiet never emit output: exit code still succeeds/fails links=0 avoid=0 buf=0 ins=0 quiet=0 while [ $# -gt 0 ]; do case "$1" in -a|--a|-avoid|--avoid|-v|--v) avoid=1; shift; continue ;; -b|--b|-buffered|--buffered) buf=1; shift; continue ;; -h|--h|-help|--help) awk '/^# +mapa /, /^$/ { gsub(/^# ?/, ""); print }' "$0" exit 0 ;; -i|--i|-ins|--ins|-insensitive|--insensitive) ins=1; shift; continue ;; -ia|-ai|-iv|-vi) ins=1; avoid=1; shift; continue ;; -il|-li) ins=1; links=1; shift; continue ;; -ilq|-iql|-liq|-lqi|-qil|-qli|-ils|-isl|-lis|-lsi|-sil|-sli) ins=1; links=1; quiet=1; shift; continue ;; -ila|-ial|-lia|-lai|-ail|-ali|-ilv|-ivl|-liv|-lvi|-vil|-vli) ins=1; links=1; avoid=1; shift; continue ;; -iq|-qi|-is|-si) ins=1; quiet=1; shift; continue ;; -l|--l|-links|--links) links=1; shift; continue ;; -lq|-ql|-ls|-sl) links=1; quiet=1; shift; continue ;; -q|--q|-quiet|--quiet|-s|--s|-silent|--silent) quiet=1; shift; continue ;; -) break ;; --) shift; break ;; -*) printf "%s: unsupported option %s\n" "$0" "$1" >&2 exit 1 ;; esac break done if [ "${quiet}" -eq 1 ]; then buf=1 fi flush=0 if [ "${buf}" -eq 0 ] && { [ -p /dev/stdout ] || [ -t 1 ]; }; then flush=1 fi re='[Hh][Tt][Tt][Pp][Ss]?://[A-Za-z0-9+_.:%-]+(/[A-Za-z0-9+_.%/,#?&=-]*)*' awk -v flush="${flush}" -v ci="${ins}" -v add_links="${links}" \ -v links="${re}" -v quiet="${quiet}" -v avoid="${avoid}" ' BEGIN { if (ci && IGNORECASE == "") { msg = "'"$0"': default AWK lacks case-insensitive regex-matching" print(msg) > "/dev/stderr" exit 125 } if (ci) IGNORECASE = 1 for (i = 1; i < ARGC; i++) { re[i] = ARGV[i] delete ARGV[i] } n = ARGC - 1 if (add_links) re[++n] = links if (n == 0) re[++n] = "[^\\r]" if (quiet) flush = 0 FS = RS = "" } { plain = $0 # ignore cursor-movers and style-changers gsub(/\x1b\[[0-9;]*[A-Za-z]/, "", plain) # ignore OSC sequences gsub(/\x1b\][^\x1b]+\x1b\\/, "", plain) flat = plain gsub(/\r?\n/, " ", flat) for (i = 1; i <= n; i++) { expr = re[i] if ((plain ~ expr) || (flat ~ expr)) { if (avoid) next got++ if (quiet) next if (got > 1) print "" print if (flush) fflush() next } } if (avoid) { got++ if (quiet) next if (got > 1) print "" print if (flush) fflush() } } END { exit(got == 0) } ' "$@"