Off the cuff I can only offer a \romannumeral0-expansion-driven recursive routine \ReplaceEveryPar:
\ReplaceEveryPar{⟨replacement text⟩}%
{⟨arbitrary token-sequence where to replace \par⟩}%
Each control word token \par of the ⟨arbitrary token-sequence where to replace \par⟩ will be replaced by ⟨replacement text⟩.
You obtain the result after two expansion-steps, i.e., in expansion-contexts you get the result after "hitting" \ReplaceEveryPar by two \expandafter.
As a side-effect the routine does replace matching pairs of explicit character tokens of catcode 1 and 2 by matching pairs of curly braces of catcode 1 and 2.
I suppose this won't be a problem in most situations as usually the curly braces are the only characters of category code 1 / 2...
In some situations you can use that routine for replacing every token \par, e.g., by \csname par\endcsname when having a token-sequence which forms the call to a short macro with \par occurring in the short macro's arguments:
With
\def\removemacrophrase#1>{}%
\def\MyShortMacro#1#2{%
\ifvmode\noindent\else\hfil\break\fi
\def\tempa{#1}%
Short macro's first argument in parentheses: (\expandafter\removemacrophrase\meaning\tempa)%
\hfil\break
\def\tempa{#2}%
Short macro's second argument in parentheses: (\expandafter\removemacrophrase\meaning\tempa)%
}%
the sequence
\ReplaceEveryPar{\csname par\endcsname}{%
\MyShortMacro{A\par B}{C\par D}%
}%
yields
\MyShortMacro{A\csname par\endcsname B}{C\csname par\endcsname D}%
, which in turn yields
\ifvmode\noindent\else\hfil\break\fi
\def\tempa{A\csname par\endcsname B}%
Short macro's first argument in parentheses: (\expandafter\removemacrophrase\meaning\tempa)%
\hfil\break
\def\tempa{C\csname par\endcsname D}%
Short macro's second argument in parentheses: (\expandafter\removemacrophrase\meaning\tempa)%
Above I wrote "in some situations" because there are situations where things get tricky:
E.g., with (short) macros whose arguments are delimited by the control word token \par replacing that control word token should take place with the arguments but not with the argument-delimiters.
Things get even worse in case \par was let equal to { at the time of using #\par-notation for definig a macro whose last argument is delimited by a control-word-token \par which will get reinserted into the token-stream behind the replacement-text of that macro.
\catcode`\@=11
%%=============================================================================
%% Paraphernalia:
%% \UD@firstoftwo, \UD@secondoftwo,
%% \UD@PassFirstToSecond, \UD@Exchange, \UD@removespace
%% \UD@CheckWhetherNull, \UD@CheckWhetherBrace,
%% \UD@CheckWhetherLeadingSpace, \UD@ExtractFirstArg
%%=============================================================================
\long\def\UD@firstoftwo#1#2{#1}%
\long\def\UD@secondoftwo#1#2{#2}%
\long\def\UD@PassFirstToSecond#1#2{#2{#1}}%
\long\def\UD@Exchange#1#2{#2#1}%
\UD@firstoftwo{\def\UD@removespace}{} {}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\long\def\UD@CheckWhetherNull#1{%
\romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
\UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\UD@firstoftwo\expandafter{} \UD@secondoftwo}%
{\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has leading
%% catcode-1-token>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked has no leading
%% catcode-1-token>}%
\long\def\UD@CheckWhetherBrace#1{%
\romannumeral0\expandafter\UD@secondoftwo\expandafter{\expandafter{%
\string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
\UD@secondoftwo\string}\UD@firstoftwo\expandafter{} \UD@firstoftwo}%
{\UD@firstoftwo\expandafter{} \UD@secondoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument's first token is an explicit
%% space token
%%.............................................................................
%% \UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is a
%% space-token>}%
%% {<Tokens to be delivered in case <argument
%% which is to be checked>'s 1st token is not
%% a space-token>}%
\long\def\UD@CheckWhetherLeadingSpace#1{%
\romannumeral0\UD@CheckWhetherNull{#1}%
{\UD@firstoftwo\expandafter{} \UD@secondoftwo}%
{\expandafter\UD@secondoftwo\string{\UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
\long\def\UD@CheckWhetherLeadingSpaceB#1 {%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@secondoftwo#1{}}%
{\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
{\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
\expandafter\expandafter\expandafter}\expandafter\expandafter
\expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%
%% \UD@ExtractFirstArg{ABCDE} yields {A}
%%
%% \UD@ExtractFirstArg{{AB}CDE} yields {AB}
%%
%% The `\romannumeral0-expansion-driven loop in terms of
%% \UD@ExtractFirstArgLoop has
%% ( <amount of non-brace-nested \UD@Seldom not occurring as
%% the very first token within \UD@ExtractFirstArg's
%% argument> + 2 )
%% iterations.
%% This implies: Usage of \UD@SelDOm within \UD@ExtractFirstArg's
%% argument is _not_ forbidden.
%%.............................................................................
\long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
\long\def\UD@ExtractFirstArg#1{%
\romannumeral0%
\UD@ExtractFirstArgLoop{#1\UD@SelDOm}%
}%
\long\def\UD@ExtractFirstArgLoop#1{%
\expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
{ #1}%
{\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% Check Whether argument which must consist of a single token is the token
%% \par
%%-----------------------------------------------------------------------------
\long\def\UD@CheckWhetherpar#1#2#3{%
\UD@@Checkkwhetherparfork#1{#2}\par{#3}\par\par\par
}%
\long\def\UD@@Checkkwhetherparfork#1\par#2#3\par\par\par{#2}%
%%=============================================================================
%% \ReplaceEveryPar{<replacement text>}{<argument where to replace \par>}%
%%
%% Each control word token \par of the <argument where to replace \par>
%% will be replaced by <replacement text>.
%%
%% You obtain the result after two expansion-steps, i.e.,
%% in expansion-contexts you get the result after "hitting"
%% \ReplaceEveryPar by two \expandafter.
%%
%% As a side-effect, the routine does replace matching pairs of explicit
%% character tokens of catcode 1 and 2 by matching pairs of curly braces
%% of catcode 1 and 2.
%% I suppose this won't be a problem in most situations as usually the
%% curly braces are the only characters of category code 1 / 2...
%%-----------------------------------------------------------------------------
\long\def\ReplaceEveryPar#1#2{%
\romannumeral0\UD@ReplaceEveryParLoop{#2}{}{#1}%
}%
\long\def\UD@ReplaceEveryParLoop#1#2#3{%
% #1 = remaining arbitrary token-sequence where to replace \par
% #2 = token-sequence with replacement applied constructed so far
% #3 = replacement text
\UD@CheckWhetherNull{#1}{ #2}{%
\expandafter\UD@ReplaceEveryParLoop
\romannumeral0%
\UD@CheckWhetherLeadingSpace{#1}{%
\expandafter{\UD@removespace#1}{#2 }%
}{%
\expandafter\UD@PassFirstToSecond\expandafter{%
\romannumeral0%
\UD@CheckWhetherBrace{#1}{%
\expandafter\UD@PassFirstToSecond
\expandafter{%
\romannumeral0%
\expandafter\UD@ReplaceEveryParLoop
\romannumeral0%
\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{}{#3}%
}{ #2}%
}{%
\expandafter\UD@CheckWhetherpar
\romannumeral0\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{ #2#3}{%
\expandafter\UD@Exchange
\romannumeral0\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{ #2}%
}%
}%
}{%
\expandafter{\UD@firstoftwo{}#1}%
}%
}%
{#3}%
}%
}%
\catcode`\@=12
%%=============================================================================
\tt\frenchspacing
\ReplaceEveryPar{\Rap}{%
\def\macro#1{text\par #1 text{\par}}%
}%
\string\macro: \meaning\macro
\bigskip
\def\removemacrophrase#1>{}%
\def\MyShortMacro#1#2{%
\ifvmode\noindent\else\hfil\break\fi
\def\tempa{#1}%
Short macro's first argument in parentheses: (\expandafter\removemacrophrase\meaning\tempa)%
\hfil\break
\def\tempa{#2}%
Short macro's second argument in parentheses: (\expandafter\removemacrophrase\meaning\tempa)%
}%
\ReplaceEveryPar{\csname par\endcsname}{%
\MyShortMacro{A\par B}{C\par D}%
}%
\bye

\endgrafrather than\hiddenparwhich is there for exactly that reason. (at least when\parhas its normal meaning) – David Carlisle Jun 14 '15 at 23:53TeX's error checking), then I will accept it if you post it as an answer. – LSpice Jun 15 '15 at 00:00\shortmacro that's "long"? – Mico Jun 15 '15 at 00:03\long'd version. – LSpice Jun 15 '15 at 01:22