Skip to content

Commit

Permalink
Add modifiers in unicode pretty printing; unify code using dictionary
Browse files Browse the repository at this point in the history
  • Loading branch information
moble committed Oct 10, 2013
1 parent 0a3bc54 commit f1b36ec
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 23 deletions.
50 changes: 32 additions & 18 deletions sympy/printing/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,36 @@
other_symbols = set(['aleph', 'beth', 'daleth', 'gimel', 'ell', 'eth', 'hbar',
'hslash', 'mho', 'wp', ])

# Make sure to keep this list sorted by decreasing length so that,
# e.g., "ddot" is not confused for "d" followed by "dot"
modifier_keys = ['mathring', 'check', 'breve', 'acute', 'grave', 'tilde', 'prime', 'ddot',
'bold', 'norm', 'avg', 'hat', 'dot', 'bar', 'vec', 'abs', 'mag', 'prm', 'bm']
# Variable name modifiers
modifier_dict = {
# Accents
'mathring': lambda s: r'\mathring{'+s+r'}',
'ddddot': lambda s: r'\ddddot{'+s+r'}',
'dddot': lambda s: r'\dddot{'+s+r'}',
'ddot': lambda s: r'\ddot{'+s+r'}',
'dot': lambda s: r'\dot{'+s+r'}',
'check': lambda s: r'\check{'+s+r'}',
'breve': lambda s: r'\breve{'+s+r'}',
'acute': lambda s: r'\acute{'+s+r'}',
'grave': lambda s: r'\grave{'+s+r'}',
'tilde': lambda s: r'\tilde{'+s+r'}',
'hat': lambda s: r'\hat{'+s+r'}',
'bar': lambda s: r'\bar{'+s+r'}',
'vec': lambda s: r'\vec{'+s+r'}',
'prime': lambda s: "{"+s+"}'",
'prm': lambda s: "{"+s+"}'",
# Faces
'bold': lambda s: r'\boldsymbol{'+s+r'}',
'bm': lambda s: r'\boldsymbol{'+s+r'}',
'cal': lambda s: r'\mathcal{'+s+r'}',
'scr': lambda s: r'\mathscr{'+s+r'}',
'frak': lambda s: r'\mathfrak{'+s+r'}',
# Brackets
'norm': lambda s: r'\left\lVert{'+s+r'}\right\rVert',
'avg': lambda s: r'\left\langle{'+s+r'}\right\rangle',
'abs': lambda s: r'\left\lvert{'+s+r'}\right\rvert',
'mag': lambda s: r'\left\lvert{'+s+r'}\right\rvert',
}

greek_letters_set = frozenset(greeks)

Expand Down Expand Up @@ -1648,21 +1674,9 @@ def translate(s):
return "\\" + s
else:
# Process modifiers, if any, and recurse
for key in modifier_keys:
for key in sorted(modifier_dict.keys(), key=lambda k:len(k), reverse=True):
if s.lower().endswith(key) and len(s)>len(key):
if(key in ['prime', 'prm']):
# MathJax can fail on primes without braces
return "{" + translate(s[:-len(key)]) + "}'"
if(key in ['abs', 'mag']):
return "\\left\\lvert{" + translate(s[:-len(key)]) + "}\\right\\rvert"
if(key=='norm'):
return "\\left\\lVert{" + translate(s[:-len(key)]) + "}\\right\\rVert"
if(key=='avg'):
return "\\left\\langle{" + translate(s[:-len(key)]) + "}\\right\\rangle"
if(key in ['bm', 'bold']):
# MathJax doesn't know \bm
return "\\boldsymbol{" + translate(s[:-len(key)]) + "}"
return "\\" + key + "{" + translate(s[:-len(key)]) + "}"
return modifier_dict[key](translate(s[:-len(key)]))
return s

def latex(expr, **settings):
Expand Down
48 changes: 43 additions & 5 deletions sympy/printing/pretty/pretty_symbology.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,38 @@ def xstr(*args):
sub[s] = SSUB(s)
sup[s] = SSUP(s)

# Variable modifiers
# TODO: Is it worth trying to handle faces with, e.g., 'MATHEMATICAL BOLD CAPITAL A'?
# TODO: Make brackets adjust to height of contents
modifier_dict = {
# Accents
'mathring': lambda s: s+u'\u030A',
# 'ddddot': lambda s: s,
# 'dddot': lambda s: s,
'ddot': lambda s: s+u'\u0308',
'dot': lambda s: s+u'\u0307',
'check': lambda s: s+u'\u030C',
'breve': lambda s: s+u'\u0306',
'acute': lambda s: s+u'\u0301',
'grave': lambda s: s+u'\u0300',
'tilde': lambda s: s+u'\u0303',
'hat': lambda s: s+u'\u0302',
'bar': lambda s: s+u'\u0305',
'vec': lambda s: s+u'\u20D7',
'prime': lambda s: s+u'\u030D',
'prm': lambda s: s+u'\u030D',
# Faces
# 'bold': lambda s:,
# 'bm': lambda s:,
# 'cal': lambda s:,
# 'scr': lambda s:,
# 'frak': lambda s:,
# Brackets
'norm': lambda s: u'\u2016'+s+u'\u2016',
'avg': lambda s: u'\u27E8'+s+u'\u27E9',
'abs': lambda s: u'\u007C'+s+u'\u007C',
'mag': lambda s: u'\u007C'+s+u'\u007C',
}

# VERTICAL OBJECTS
HUP = lambda symb: U('%s UPPER HOOK' % symb_2txt[symb])
Expand Down Expand Up @@ -452,10 +484,16 @@ def pretty_symbol(symb_name):

name, sups, subs = split_super_sub(symb_name)

# let's prettify name
gG = greek_unicode.get(name)
if gG is not None:
name = gG
def translate(s) :
gG = greek_unicode.get(s)
if gG is not None:
return gG
for key in sorted(modifier_dict.keys(), key=lambda k:len(k), reverse=True) :
if s.lower().endswith(key) and len(s)>len(key):
return modifier_dict[key](translate(s[:-len(key)]))
return s

name = translate(name)

# Let's prettify sups/subs. If it fails at one of them, pretty sups/subs are
# not used at all.
Expand All @@ -479,7 +517,7 @@ def pretty_list(l, mapping):

# glue the results into one string
if pretty_subs is None: # nice formatting of sups/subs did not work
return symb_name
return name + '_'+'_'.join([translate(s) for s in subs]) + '__'+'__'.join([translate(s) for s in sups])
else:
sups_result = ' '.join(pretty_sups)
subs_result = ' '.join(pretty_subs)
Expand Down
22 changes: 22 additions & 0 deletions sympy/printing/pretty/tests/test_pretty.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,28 @@ def test_upretty_subs_missingin_24():
assert upretty( Symbol('F_v') ) == u('Fᵥ')
assert upretty( Symbol('F_x') ) == u('Fₓ')

def test_upretty_modifiers():
# Accents
assert upretty( Symbol('Fmathring') ) == u('F̊')
assert upretty( Symbol('Fddot') ) == u('F̈')
assert upretty( Symbol('Fdot') ) == u('Ḟ')
assert upretty( Symbol('Fcheck') ) == u('F̌')
assert upretty( Symbol('Fbreve') ) == u('F̆')
assert upretty( Symbol('Facute') ) == u('F́')
assert upretty( Symbol('Fgrave') ) == u('F̀')
assert upretty( Symbol('Ftilde') ) == u('F̃')
assert upretty( Symbol('Fhat') ) == u('F̂')
assert upretty( Symbol('Fbar') ) == u('F̅')
assert upretty( Symbol('Fvec') ) == u('F⃗')
assert upretty( Symbol('Fprime') ) == u('F̍')
assert upretty( Symbol('Fprm') ) == u('F̍')
# No faces are implemented...
# Brackets
assert upretty( Symbol('Fnorm') ) == u('‖F‖')
assert upretty( Symbol('Favg') ) == u('⟨F⟩')
assert upretty( Symbol('Fabs') ) == u('|F|')
assert upretty( Symbol('Fmag') ) == u('|F|')


def test_pretty_basic():
assert pretty( -Rational(1)/2 ) == '-1/2'
Expand Down
3 changes: 3 additions & 0 deletions sympy/printing/tests/test_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,8 @@ def test_modifiers():
assert latex(symbols("xGrave")) == r"\grave{x}"
assert latex(symbols("xTilde")) == r"\tilde{x}"
assert latex(symbols("xPrime")) == r"{x}'"
assert latex(symbols("xddDDot")) == r"\ddddot{x}"
assert latex(symbols("xDdDot")) == r"\dddot{x}"
assert latex(symbols("xDDot")) == r"\ddot{x}"
assert latex(symbols("xBold")) == r"\boldsymbol{x}"
assert latex(symbols("xnOrM")) == r"\left\lVert{x}\right\rVert"
Expand Down Expand Up @@ -1097,6 +1099,7 @@ def test_modifiers():
assert latex(symbols("Mag")) == r"Mag"
assert latex(symbols("PrM")) == r"PrM"
assert latex(symbols("BM")) == r"BM"
assert latex(symbols("hbar")) == r"\hbar"
# Check a few combinations
assert latex(symbols("xvecdot")) == r"\dot{\vec{x}}"
assert latex(symbols("xDotVec")) == r"\vec{\dot{x}}"
Expand Down

0 comments on commit f1b36ec

Please sign in to comment.