Repository: sympy/sympy (python)

Issue:
Dyadics and vectors do not pretty print well.

Using this script: https://gist.github.com/moorepants/8f0729c1a545945c10e01231f49e2200

```
In [3]: IT.simplify()
Out[3]: 
I_Hxx f_x⊗f_x + I_Hxz f_x⊗f_z +                          2        
I_Hyy⋅m_H + I_Hyy⋅m_W + d ⋅m_H⋅m_W
──────────────────────────────────
            m_H + m_W              f_y⊗f_y + I_Hxz f_z⊗f_x +                          2        
I_Hzz⋅m_H + I_Hzz⋅m_W + d ⋅m_H⋅m_W
──────────────────────────────────
            m_H + m_W              f_z⊗f_z

In [4]: To.pos_from(o)
Out[4]: 
m_H⋅x_H + m_W⋅(d + x_H)
───────────────────────
       m_H + m_W        f_x + m_H⋅y_H + m_W⋅y_H
─────────────────
    m_H + m_W     f_y + m_H⋅z_H + m_W⋅z_H
─────────────────
    m_H + m_W     f_z
```

This seems likely due to the fractions.



Patch:
diff --git a/.mailmap b/.mailmap
index 3d66a576e6c8..3a320dfd3bc8 100644
--- a/.mailmap
+++ b/.mailmap
@@ -810,6 +810,7 @@ Jatin Gaur <jatingaurchess@gmail.com> <jatin22101@iiitnr.edu.in>
 Jatin Yadav <jatinyadav25@gmail.com>
 Javed Nissar <javednissar@gmail.com>
 Jay Patankar <patankarjays@gmail.com> Jay-Patankar <107458263+Jay-Patankar@users.noreply.github.com>
+Jay Vijan <jvijan@umich.edu> Jay Sun Vijan <145924415+jvijan@users.noreply.github.com>
 Jayesh Lahori <jlahori92@gmail.com>
 Jayjayyy <vfhsln8s3l4b87t4c3@byom.de>
 Jean-François B <2589111+jfbu@users.noreply.github.com>
@@ -1666,6 +1667,7 @@ Wes Galbraith <galbwe92@gmail.com>
 Wes Turner <50891+westurner@users.noreply.github.com>
 Willem Melching <willem.melching@gmail.com>
 Wolfgang Stöcher <wolfgang@stoecher.com> coproc <wolfgang@stoecher.com>
+Wonsik Jung <algrthm@umich.edu> wonsik99 <algrthm@umich.edu>
 Wyatt Peak <wyattpeak@gmail.com>
 Xiang Wu <hsiangwu@fb.com>
 Xiao <muzumayao@126.com> Xiao <88570037+T90REAL@users.noreply.github.com>
diff --git a/sympy/physics/vector/dyadic.py b/sympy/physics/vector/dyadic.py
index 0adacab2c2be..1548c6388367 100644
--- a/sympy/physics/vector/dyadic.py
+++ b/sympy/physics/vector/dyadic.py
@@ -1,6 +1,7 @@
 from sympy import sympify, Add, ImmutableMatrix as Matrix
 from sympy.core.evalf import EvalfMixin
 from sympy.printing.defaults import Printable
+from sympy.printing.pretty.stringpict import prettyForm
 
 from mpmath.libmp.libmpf import prec_to_dps
 
@@ -209,51 +210,44 @@ class Fake:
             baseline = 0
 
             def render(self, *args, **kwargs):
-                ar = e.args  # just to shorten things
                 mpp = printer
-                if len(ar) == 0:
-                    return str(0)
-                bar = "\N{CIRCLED TIMES}" if printer._use_unicode else "|"
-                ol = []  # output list, to be concatenated to a string
-                for v in ar:
-                    # if the coef of the dyadic is 1, we skip the 1
-                    if v[0] == 1:
-                        ol.extend([" + ",
-                                  mpp.doprint(v[1]),
-                                  bar,
-                                  mpp.doprint(v[2])])
-
-                    # if the coef of the dyadic is -1, we skip the 1
-                    elif v[0] == -1:
-                        ol.extend([" - ",
-                                  mpp.doprint(v[1]),
-                                  bar,
-                                  mpp.doprint(v[2])])
-
-                    # If the coefficient of the dyadic is not 1 or -1,
-                    # we might wrap it in parentheses, for readability.
-                    elif v[0] != 0:
-                        if isinstance(v[0], Add):
-                            arg_str = mpp._print(
-                                v[0]).parens()[0]
+                if len(e.args) == 0:
+                    return mpp._print(0)
+
+                outstr = None
+                bar = prettyForm(u"\N{CIRCLED TIMES}" if mpp._use_unicode else "|")
+                for i, v in enumerate(e.args):
+                    p_v1 = mpp._print(v[1])
+                    p_v2 = mpp._print(v[2])
+                    p_dyad = prettyForm(*p_v1.right(bar, p_v2))
+
+                    c = v[0]
+                    if i == 0:
+                        sign = ""
+                    else:
+                        sign = " + "
+
+                    coeff, rest = c.as_coeff_Mul()
+                    if coeff < 0:
+                        if i == 0:
+                            sign = "- "
                         else:
-                            arg_str = mpp.doprint(v[0])
-                        if arg_str.startswith("-"):
-                            arg_str = arg_str[1:]
-                            str_start = " - "
-                        else:
-                            str_start = " + "
-                        ol.extend([str_start, arg_str, " ",
-                                  mpp.doprint(v[1]),
-                                  bar,
-                                  mpp.doprint(v[2])])
-
-                outstr = "".join(ol)
-                if outstr.startswith(" + "):
-                    outstr = outstr[3:]
-                elif outstr.startswith(" "):
-                    outstr = outstr[1:]
-                return outstr
+                            sign = " - "
+                        c = -c
+
+                    if c == 1:
+                        p_term = p_dyad
+                    else:
+                        p_c = mpp._print(c)
+                        if isinstance(c, Add):
+                            p_c = prettyForm(*p_c.parens())
+                        p_term = prettyForm(*p_c.right(" ", p_dyad))
+
+                    if outstr is None:
+                        outstr = prettyForm(*p_term.left(sign))
+                    else:
+                        outstr = prettyForm(*outstr.right(sign, p_term))
+                return outstr.__str__()
         return Fake()
 
     def __rsub__(self, other):


Test patch:
diff --git a/sympy/physics/vector/tests/test_printing.py b/sympy/physics/vector/tests/test_printing.py
index 0930fe9d0bc6..7235258677d7 100644
--- a/sympy/physics/vector/tests/test_printing.py
+++ b/sympy/physics/vector/tests/test_printing.py
@@ -10,6 +10,7 @@
 
 
 a, b, c = symbols('a, b, c')
+
 alpha, omega, beta = dynamicsymbols('alpha, omega, beta')
 
 A = ReferenceFrame('A')
@@ -187,12 +188,12 @@ def test_vector_latex_with_functions():
 def test_dyadic_pretty_print():
 
     expected = """\
- 2
+ 2                                           \n\
 a  n_x|n_y + b n_y|n_y + c*sin(alpha) n_z|n_y\
 """
 
     uexpected = """\
- 2
+ 2                                       \n\
 a  n_x⊗n_y + b n_y⊗n_y + c⋅sin(α) n_z⊗n_y\
 """
     assert ascii_vpretty(y) == expected
@@ -351,3 +352,78 @@ def test_issue_14041():
         r"\left(\dot{\phi} + \dot{\theta}\right)^{2}\mathbf{\hat{a}_x}"
     assert vlatex((phid*thetad)**a*A_frame.x) == \
         r"\left(\dot{\phi} \dot{\theta}\right)^{a}\mathbf{\hat{a}_x}"
+
+
+def test_issue_12157():
+    """
+    Test for proper pretty printing of vectors with fractions involved.
+    """
+
+    first_test = (a/b) * (N.x | N.y)
+
+    expected = '''\
+a        \n\
+- n_x|n_y\n\
+b        \
+'''
+    uexpected = '''\
+a        \n\
+─ n_x⊗n_y\n\
+b        \
+'''
+
+    assert ascii_vpretty(first_test) == expected
+    assert unicode_vpretty(first_test) == uexpected
+
+    second_test = ((a + b)/c) * (N.x | N.y)
+
+    expected = '''\
+a + b        \n\
+----- n_x|n_y\n\
+  c          \
+'''
+    uexpected = '''\
+a + b        \n\
+───── n_x⊗n_y\n\
+  c          \
+'''
+
+    assert ascii_vpretty(second_test) == expected
+    assert unicode_vpretty(second_test) == uexpected
+
+
+    third_test = (a/b) * (N.x | N.y) + (c/b) * (N.y | N.z)
+
+    expected ='''\
+a           c        \n\
+- n_x|n_y + - n_y|n_z\n\
+b           b        \
+'''
+    uexpected ='''\
+a           c        \n\
+─ n_x⊗n_y + ─ n_y⊗n_z\n\
+b           b        \
+'''
+
+    assert ascii_vpretty(third_test) == expected
+    assert unicode_vpretty(third_test) == uexpected
+
+    d = symbols('d')
+    # This case comes from the correct output example provided by @faze-geek in the issue
+    fourth_test = (d)*(N.x|N.z) + ((a*b**2 + (a*c)**2 + d*b*c)/(b + c))*(N.y|N.y)
+
+    expected = '''\
+             2  2      2                \n\
+            a *c  + a*b  + b*c*d        \n\
+d n_x|n_z + -------------------- n_y|n_y\n\
+                   b + c                \
+'''
+    uexpected = '''\
+             2  2      2                \n\
+            a ⋅c  + a⋅b  + b⋅c⋅d        \n\
+d n_x⊗n_z + ──────────────────── n_y⊗n_y\n\
+                   b + c                \
+'''
+
+    assert ascii_vpretty(fourth_test) == expected
+    assert unicode_vpretty(fourth_test) == uexpected