Ticket #7897: trac_7897_improve_macaulay2_prompt_detection.patch

File trac_7897_improve_macaulay2_prompt_detection.patch, 4.4 KB (added by novoselt, 12 years ago)
  • sage/interfaces/macaulay2.py

    # HG changeset patch
    # User Andrey Novoseltsev <novoselt@gmail.com>
    # Date 1264997067 25200
    # Node ID fca3d8df3d5a420331fa85a40b821c9726b23337
    # Parent  82ca63441af4b8bc701d1d44b1ca39bdce971494
    Trac 7897: Improve prompt detection in Macaulay2 interface.
    
    diff -r 82ca63441af4 -r fca3d8df3d5a sage/interfaces/macaulay2.py
    a b  
    105105
    106106def remove_output_labels(s):
    107107    """
     108    Remove output labels of Macaulay2 from a string.
     109   
     110    :param s: output of Macaulay2
     111   
     112    :type s: string
     113   
     114    :returns: the input string with `n` symbols removed from the beginning
     115        of each line, where `n` is the minimal number of spaces or
     116        symbols of Macaulay2 output labels (looking like 'o39 = ')
     117        present on every non-empty line.
     118   
     119    :rtype: string
     120
     121    :note: If ``s`` consists of several outputs and their lables have
     122        different width, it is possible that some strings will have leading
     123        spaces (or maybe even pieces of output labels). However, this
     124        function will try not cut any messages.
     125   
    108126    EXAMPLES:
    109127        sage: from sage.interfaces.macaulay2 import remove_output_labels
    110128        sage: output = 'o1 = QQ [x, y]\n\no1 : PolynomialRing\n'
    111129        sage: remove_output_labels(output)
    112130        'QQ [x, y]\n\nPolynomialRing\n'
    113131    """
    114     m = re.search('o[0-9]+ = ', s)
    115     if m is None: return s
    116     i = m.start()
    117     j = m.end()
    118     n = j - i
    119     s = s[:i] + ' '*n + s[j:]
    120     # Now remove n spaces from beginning of each line.
    121     v = s.split('\n')
    122     s = '\n'.join([x[n:] for x in v])
    123     return s
    124 
     132    label = re.compile("^o[0-9]+ (=|:) |^ *")
     133    lines = s.split("\n")
     134    matches = [label.match(l) for l in lines if l != ""]
     135    if len(matches) == 0:
     136        return s
     137    else:
     138        n = min(m.end() - m.start() for m in matches)
     139        return "\n".join(l[n:] for l in lines)
    125140
    126141COMMANDS_CACHE = '%s/macaulay2_commandlist_cache.sobj'%DOT_SAGE
     142PROMPT = "_EGAS_ : "
    127143
    128144class Macaulay2(Expect):
    129145    """
     
    132148    def __init__(self, maxread=10000, script_subdirectory="",
    133149                 logfile=None, server=None,server_tmpdir=None):
    134150        """
     151        Initialize a Macaulay2 interface instance.
     152       
     153        We replace the standard input prompt with a strange one, so that
     154        we do not catch input prompts inside the documentation.
     155       
     156        We replace the standard input continuation prompt, which is
     157        just a bunch of spaces and cannot be automatically detected in a
     158        reliable way. This is necessary for allowing commands that occupy
     159        several strings.
     160       
     161        We also change the starting line number to make all the output
     162        labels to be of the same length. This allows correct stripping of
     163        the output of several commands.
     164       
    135165        TESTS:
    136166            sage: macaulay2 == loads(dumps(macaulay2))
    137167            True
    138168        """
     169        init_str = (
     170            # Prompt changing commands
     171            """ZZ#{Standard,Core#"private dictionary"#"InputPrompt"} = lineno -> "%s";""" % PROMPT +
     172            """ZZ#{Standard,Core#"private dictionary"#"InputContinuationPrompt"} = lineno -> "%s";""" % PROMPT +
     173            # Also prevent line wrapping in Macaulay2
     174            "printWidth = 0;" +
     175            # And make all output labels to be of the same width
     176            "lineNumber = 10^9;")       
    139177        Expect.__init__(self,
    140178                        name = 'macaulay2',
    141                         prompt = 'i[0-9]* : ',
    142                         command = "M2 --no-debug --no-readline --silent ",
     179                        prompt = PROMPT,
     180                        command = "M2 --no-debug --no-readline --silent -e '%s'" % init_str,
    143181                        maxread = maxread,
    144182                        server = server,
    145183                        server_tmpdir = server_tmpdir,
     
    227265            ans = remove_output_labels(ans)
    228266        return AsciiArtString(ans)
    229267
     268    def restart(self):
     269        r"""
     270        Restart Macaulay2 interpreter.
     271       
     272        TEST:
     273            sage: macaulay2.restart()  # optional
     274        """
     275        # If we allow restart to be called as a function, there will be
     276        # parasitic output
     277        self.eval("restart")
     278
    230279    def get(self, var):
    231280        """
    232281        Get the value of the variable var.