Dealing with Hidden Indention Characters in Maple's Display of a Defined Procedure as Output

Maple displays a defined procedure (yours or Maple's)as output when you enter definition or when you execute eval(). It should be noticed that in either case, Maple uses its own well defined indention scheme, regardless of what indention scheme you used or didn't use when you input the procedure.

Now if you want to edit the procedure, and your only copy is gotten by copying Maple's output to an input line, you will have to deal with Maple's hidden indention characters at the beginning of each line. I have been unable to find any Help material on this, and, in particular, I have not been able to find any way to edit (delete or input) these characters directly. However, they are all invisibly located in the blank space, which is visible, at the start of each indented line. The code seems to be of the form "indent a fixed number of spaces more than the previous line". These fixed numbers are one of three values, a positive number (approx. 3), 0, or a negative number (approx. -3).

Now if you attempt to insert a new line in the usual way (Shift-Enter), it will always be a line without indention starting at the left margin. Then all the following code will be shifted left, messing up Maple's very nice indention scheme and making a visual mess.

What to do? Well, first copy a line with the appropriate indention code from elsewhere in the procedure. Then you can erase all of the line EXCEPT THE BLANK SPACE WITH THE INDENTION CODE AT THE BEGINNING. Finally you can replace the erased code with whatever you wanted.

Changing Maple's procedures is often important, due to errors or omissions in their code or in order to extend it or adapt it to your needs.

Comments

printing procedures

Here is another approach. Instead of using eval to print the body of a procedure, use the following procedure, which sets interface(prettyprint=1) so that the output is in a fixed-width font. The display is not quite as nice as the usual Maple outut (in a GUI), the line breaking is not quite as good, but it is acceptable for most usage and makes cutting/pasting the result into an input section simple and, because the indentation is done via spaces, is readily edited. You might consider assigning this procedure in your Maple initialization file.

PrintProc := proc(p)
local opaque,pretty,verbose,width;
    (pretty, verbose, width) := interface('prettyprint' = 1
                                          , 'verboseproc' = 2
                                          , 'screenwidth' = 120
                                         );
    opaque := kernelopts('opaquemodules' = false);
    try
        print(eval(p));
    finally
        interface('prettyprint' = pretty
                  , 'verboseproc' = verbose
                  , 'screenwidth' = width );
        kernelopts('opaquemodules' = opaque);
    end try;
    NULL;
end proc:
Axel Vogt's picture

can one set 'tab spacing'

I like Joe Riel's approach - how does one modify you solution
to get a tab spacing of 2 (which i prefer)?

increasing the indent

The way we should be able to do this (set indentation) is to modify the routine to set the interface('indentamount') value to that desired. Use a local variable to save and restore the previous value, if desired. Unfortunately, the print driver in the standard GUI ignores the indentamount setting (as it does the screenwidth). It works fine in cmaple or the classic GUI.

Here is one way to work around that. It uses the output of showstat to convert a procedure to a string, removes the line numbers, then doubles the number of blank space at the start of each line. Because showshat uses a nominal indent of two spaces per level, that effectively gives an indent of four spaces per level.

PS: After posting this, I reread your question. I originally thought you wanted an indent of 4 spaces per level, not 2. You shouldn't have to do anything to my original version of PrintProc to get an indent of 2 spaces per level.

PrintProc := proc(p)
local width,opaque,dummy_name,lead,lines,str;
option `Copyright (C) 2004 by Joseph S. Riel. All rights reserved.`;
description "Print like showstat, but without line numbers";
uses StringTools;
    if not p::procedure then
        lprint(eval(p));
        return NULL;
    end if;
    opaque := kernelopts('opaquemodules'=false);
    width := interface('screenwidth'=80);

    try
        str := RegSubs("\n ...." = "\n"
                       , debugopts('procdump'= p));
        str := RegSubs("\n( +)" = "\n\\1\\1", str);
        printf("%s:\n", str[1..-2]);
    catch "procedure name expected":
        error "%1 is not a procedure name",p;
    catch "cannot debug the debugger":
        dummy_name := eval(p);
        procname(dummy_name,args[2..-1]);
    catch "cannot debug built-in functions":
        printf("%A := %A\n", p, eval(p));
    finally
        interface('screenwidth' = width);
        kernelopts('opaquemodules' = opaque);
    end try;
    NULL;
end proc:

Note that showstat doesn't display options, so you won't ever see the

option `Copyright (c) ...`;

statement with this routine.

This does the trick for me, but first procedure doesn't

Joe Riel's first procedure doesn't do what I want because it prints everything in the middle of the page, and, when copied to an input line, makes all the lines but the first line very indented.

The second procedure does just fine, and you do not have to change prettyprint; prettyprint=3 is just fine. In fact, except for all the checking and the module consideration (and, of course, one has to have verboseproc=2o3 to print a Maple library procedure), one can just use one statement ("g" is the procedure to be printed):

printf("%s:\\n", RegSubs("\\n( +)" = "\\n\\\\1\\\\1\\\\1", RegSubs("\\n ...." = "\\n", debugopts('procdump' = g)))[1 .. -2]);

The thing I learned here is that the output of 'procdump' can be assigned to a name and otherwise used as input to other functions, whereas, as far as I can tell, the output of print(eval()) cannot be captured in this way. The output of 'procdump' is not a string but can be converted to a string by convert( ,string), and it seems that RegSubs() automatically does this conversion if its input is not a string. Then the output of RegSubs() is definitely a string.

When the output of this statement is copied to an input line (in standard 2D Maple), tripling the indention works out well. And all the indentions in it are done with simple manipulable spaces.

Thanks for the idea Joe.

re: this does the trick...

Your comments are mainly correct, though I don't understand why the first routine centers the output. What version and interface of Maple are you using? It prints flush left for me (Maple 10, standard and cmaple), on linux.

The output of debugopts with the procdump option is a name (not a string, as you note). I don't know why that is; probably a vestige of early Maple. Strings weren't introduced until Maple R5. I'm not sure why the backslashes are doubled in the line that you show; they shouldn't be.

(1) OK, I see, apparently

(1) OK, I see, apparently the only effect of setting prettyprint=1 when printing procedures is to start the printing in column 1 instead of centering it (which is what happens with prettyprint=3). However, print() does not seem to use any of the other prettyprinting features (with either prettyprint=1 or 3) that I can determine *when it is printing procedures outputted by eval()*.

(2) I do not know how how [but see last paragraph] the backslashes got doubled. I did not enter them that way on purpose, but obviously I did not catch them when proofreading the entry. Some software, somewhere, did that change on its own. I'll have to watch that in the future to see where it happens and correct it. It should correctly be:

printf("%s:\n", RegSubs("\n( +)" = "\n\\1\\1\\1", RegSubs("\n ...." = "\n", debugopts('procdump' = g)))[1 .. -2])

I just copied and pasted the above from a Maple worksheet, and lo and behold, when I pasted, all the backslashes were doubled! I then corrected them manually in the above statement.

Using ToInert for procedure printing

Another idea which is perhaps a bit more generalizable would be to use Maple's ToInert routine to convert the procedure to an inert form; this is essentially an abstract syntax tree representation of the procedure in question.

This could then be recursively traversed and printed in some specified way with printf or sprintf. One benefit would be that they could even be printed out to a file or other program.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
}