cmhughes / latexindent.pl

Perl script to add indentation (leading horizontal space) to LaTeX files. It can modify line breaks before, during and after code blocks; it can perform text wrapping and paragraph line break removal. It can also perform string-based and regex-based substitutions/replacements. The script is customisable through its YAML interface.
GNU General Public License v3.0
864 stars 84 forks source link

Could latexindent.pl provide appropriate spaces and text wraps before or after math operators? (sounds like many formatters doing for Python or C language) #524

Closed Saltsmart closed 5 months ago

Saltsmart commented 5 months ago

Please provide the following when posting an issue:

original .tex code

$a=1$  % one space before and one space after general binary operators
\((a ,b)=(1 ,2)\)  % one space between the comma and the following variable
\[( a+b ) * c = d\]  % no space between parentheses and variables
\[a + b\times  c = d\]  % \times is also an operator 
% Suppose if I want to have line break after = operator
\begin{equation}
a^2+b^2=c^2
\end{equation}

yaml settings

I have searched the documentation on CTAN, but found no yaml setting that could be used for this aim.

actual/given output

Just the same as original .tex code. Nothing changes.

desired or expected output

$a = 1$  % one space before and one space after general binary operators
\((a, b) = (1, 2)\)  % one space between the comma and the following variable
\[(a + b) * c = d\]  % no space between parentheses and variables
\[a + b \times c = d\]  % \times is also an operator 
% Suppose if I want to have line break after = operator
\begin{equation}
    a ^ 2 + b ^ 2 =
    c ^ 2
\end{equation}

anything else

If you are familiar with Python, here is a nice discussion for whitespaces in PEP 8: Does PEP 8 require whitespace around operators?

The BLACK formatting style is also strongly recommended for your reference: Line breaks & binary operators

cmhughes commented 5 months ago

Thanks for this, it's interesting.

Starting with

% \( ... \)
\((a ,b)=(1 ,2)\)  % one space between the comma and the following variable
\(( a+b ) * c = d(a ,b)\)  % no space between parentheses and variables
% $ ... $
$( a+b ) * c = d(a ,b)$    % no space between parentheses and variables
$a=1$  % one space before and one space after general binary operators
% \[ ... \]
\[( a+b ) * c = d\]  % no space between parentheses and variables
\[a + b\times  c = d\]  % \times is also an operator 
\[( a+b ) * c = d(a ,b)\]  % no space between parentheses and variables
% Suppose if I want to have line break after = operator
\begin{equation}
a^2+b^2=c^2
\end{equation}

and using the following, say issue-524.yaml

replacements:
  - 
    substitution: |-
      s@(
         (?:
          \\\(                     # \(
          .*?
          \\\)                     # \)
         )
         |
         (?:
           (?<!\$)(?<!\\)\$(?!\$)  # $
           [^\$]*?
           (?<!\\)\$(?!\$)         # $
          )
         |
         (?:
          \\\[                     # \[
          .*?
          \\\]                     # \]
         )
         |
         (?:
          \\begin\{                # \begin{equation|align|fleqn, etc}
            (
            equation|align|fleqn   # populate as necessary
            )
            \}
          .*?
          \\end\{\2\}              # \end{equation|align|fleqn, etc}
         )
        )
        @
      # store the middle
      my $middle = $1;
      # store the beginning
      $middle =~s/^(\\\(|\$|\\\[|\\begin\{[^}]+?\})//s;
      my $begin =  $1;
      # store the end
      $middle =~s/(\\\)|\$|\\\]|\\end\{[^}]+?\})$//s;
      my $end    = $1;
      #
      # perform the operations
      #
      # comma space unification
      $middle =~ s|([a-zA-Z0-9])\h*,\h*([a-zA-Z0-9])|$1, $2|sg;
      # <(> <space> <variable> into <(><variable>
      $middle =~ s|\(\h*([a-zA-Z0-9])|($1|sg;
      # <variable> <space> <)> into <variable><)>
      $middle =~ s|([a-zA-Z0-9])\h*\)|$1)|sg;
      # <variable-1>=<variable-2> into <variable-1> = <variable-2>
      $middle =~ s/([a-zA-Z0-9])\h*(=|\*|\+|\-)\h*([a-zA-Z0-9])/$1 $2 $3/sg;
      $middle =~ s/([a-zA-Z0-9])\h*(\\times)\h*([a-zA-Z0-9])/$1 $2 $3/sg;
      $begin.$middle.$end;@sgxe

and calling

latexindent.pl -r -l issue-524.yaml myfile.tex

gives

% \( ... \)
\((a, b)=(1, 2)\)  % one space between the comma and the following variable
\((a + b) * c = d(a, b)\)  % no space between parentheses and variables
% $ ... $
$(a + b) * c = d(a, b)$    % no space between parentheses and variables
$a = 1$  % one space before and one space after general binary operators
% \[ ... \]
\[(a + b) * c = d\]  % no space between parentheses and variables
\[a + b \times c = d\]  % \times is also an operator 
\[(a + b) * c = d(a, b)\]  % no space between parentheses and variables
% Suppose if I want to have line break after = operator
\begin{equation}
    a^2 + b^2 = c^2
\end{equation}

I hope this helps.

cmhughes commented 5 months ago

Let me know if you need anything else on this.

PiotrSokol commented 4 months ago

@cmhughes Any way to make this work with trailing comments?

Currently, with issue-524.yaml and input

\begin{equation}
 x=2 % a^2+b^2=c^2
a^2+b^2=c^2
x=2 % a^2+b^2=c^2
\end{equation}

one gets

\begin{equation}
  x = 2 %latexindenttrailingcomment6 - END
  a^2 + b^2 = c^2
  x = 2 %latexindenttrailingcomment7 - END
\end{equation}