2015-02-26 18:02:20 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# encoding: utf-8
|
|
|
|
|
2015-02-27 16:46:16 +00:00
|
|
|
from .render import txt, tex
|
|
|
|
|
|
|
|
class Renderable(object):
|
2015-04-21 16:10:14 +00:00
|
|
|
"""
|
|
|
|
A Renderable object is an object which can work with Render class. It means that it has to have attribute postfix_tokens.
|
|
|
|
"""
|
2015-02-27 16:46:16 +00:00
|
|
|
STR_RENDER = tex
|
|
|
|
DEFAULT_RENDER = tex
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def set_render(cls, render):
|
|
|
|
cls.STR_RENDER = render
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_render(cls):
|
|
|
|
return cls.STR_RENDER
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def set_default_render(cls):
|
|
|
|
cls.set_render(cls.DEFAULT_RENDER)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tmp_render(cls, render = tex):
|
|
|
|
""" Create a container in which Expression render is temporary modify
|
|
|
|
|
|
|
|
The default temporary render is Expression in order to perform calculus inside numbers
|
|
|
|
|
2015-02-28 22:13:51 +00:00
|
|
|
>>> from .expression import Expression
|
2015-02-27 16:46:16 +00:00
|
|
|
>>> exp = Expression("2*3/5")
|
|
|
|
>>> print(exp)
|
|
|
|
2 \\times \\frac{ 3 }{ 5 }
|
|
|
|
>>> for i in exp.simplify().explain():
|
|
|
|
... print(i)
|
|
|
|
2 \\times \\frac{ 3 }{ 5 }
|
2015-04-06 15:57:13 +00:00
|
|
|
\\frac{ 3 }{ 5 } \\times 2
|
|
|
|
\\frac{ 3 \\times 2 }{ 5 }
|
2015-02-27 16:46:16 +00:00
|
|
|
\\frac{ 6 }{ 5 }
|
|
|
|
>>> with Expression.tmp_render(txt):
|
|
|
|
... for i in exp.simplify().explain():
|
|
|
|
... print(i)
|
|
|
|
2 * 3 / 5
|
2015-04-06 15:57:13 +00:00
|
|
|
3 / 5 * 2
|
|
|
|
( 3 * 2 ) / 5
|
2015-02-27 16:46:16 +00:00
|
|
|
6 / 5
|
|
|
|
>>> for i in exp.simplify().explain():
|
|
|
|
... print(i)
|
|
|
|
2 \\times \\frac{ 3 }{ 5 }
|
2015-04-06 15:57:13 +00:00
|
|
|
\\frac{ 3 }{ 5 } \\times 2
|
|
|
|
\\frac{ 3 \\times 2 }{ 5 }
|
2015-02-27 16:46:16 +00:00
|
|
|
\\frac{ 6 }{ 5 }
|
|
|
|
|
2015-04-06 15:57:13 +00:00
|
|
|
# TODO: essayer de ne pas afficher ce changement de position. |lun. avril 6 17:29:56 CEST 2015
|
|
|
|
|
2015-02-27 16:46:16 +00:00
|
|
|
"""
|
|
|
|
class TmpRenderEnv(object):
|
|
|
|
def __enter__(self):
|
|
|
|
self.old_render = Renderable.get_render()
|
|
|
|
Renderable.set_render(render)
|
|
|
|
|
|
|
|
def __exit__(self, type, value, traceback):
|
|
|
|
Renderable.set_render(self.old_render)
|
|
|
|
return TmpRenderEnv()
|
2015-04-21 16:10:14 +00:00
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
""" Two Renderable objects are the same if they have same postfix_tokens """
|
|
|
|
try:
|
|
|
|
return self.postfix_tokens == other.postfix_tokens
|
|
|
|
except AttributeError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2015-02-27 16:46:16 +00:00
|
|
|
|
|
|
|
class Explicable(Renderable):
|
2015-02-26 18:02:20 +00:00
|
|
|
|
|
|
|
""" An Explicable object is an object which can be explicable!
|
|
|
|
|
|
|
|
It's a parent class of a more classical Expression, Fraction and Polynom (and later square root)
|
|
|
|
Child class will have the following method
|
|
|
|
* explain: Generator which return steps which leed to himself
|
|
|
|
|
|
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
self.steps = []
|
|
|
|
|
2015-04-06 15:57:13 +00:00
|
|
|
def explain(self, noself = True):
|
|
|
|
""" Generate and render steps which leed to itself
|
|
|
|
|
|
|
|
:param noself: does explain return self
|
|
|
|
|
|
|
|
"""
|
2015-02-26 18:02:20 +00:00
|
|
|
old_s = ''
|
|
|
|
# les étapes pour l'atteindre
|
|
|
|
try:
|
|
|
|
for s in self.steps:
|
2015-02-27 17:02:27 +00:00
|
|
|
if hasattr(s, 'postfix_tokens'):
|
|
|
|
new_s = self.STR_RENDER(s.postfix_tokens)
|
|
|
|
else:
|
|
|
|
new_s = self.STR_RENDER(s)
|
2015-04-17 14:38:16 +00:00
|
|
|
if not self.is_same_step(new_s, old_s):
|
2015-02-26 18:02:20 +00:00
|
|
|
old_s = new_s
|
|
|
|
yield new_s
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
|
|
|
|
2015-04-06 15:57:13 +00:00
|
|
|
if noself:
|
|
|
|
# Lui même
|
|
|
|
new_s = self.STR_RENDER(self.postfix_tokens)
|
2015-04-17 14:38:16 +00:00
|
|
|
if not self.is_same_step(new_s, old_s):
|
2015-04-06 15:57:13 +00:00
|
|
|
yield new_s
|
2015-04-17 14:38:16 +00:00
|
|
|
|
|
|
|
def is_same_step(self, new, old):
|
|
|
|
"""Return whether the new step is the same than old step
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
if new.replace(" ", "") == old.replace(" ", ""):
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
except AttributeError:
|
|
|
|
if new == old:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return False
|
|
|
|
|
2015-02-26 18:02:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -----------------------------
|
|
|
|
# Reglages pour 'vim'
|
|
|
|
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
|
|
|
|
# cursor: 16 del
|