Maple's Standard GUI has context-sensitive menus. Those are the menus that appear when one right-clicks on a output (or input, in a Dcoument).

Those context-menus can be customized.

Below is an example which adds a new submenu. The new submenu is populated automatically according to the types of thing found within the object itself.

It's an alternative to a menu-item that already exists, which shows up as "Help on Command". But that existing item only comes up if the object is a function call, and only allows for a single help-page to get displayed. This alternative submenu gets populated with a dynamic number of entries (according to what is found in the object).

restart:

with(ContextMenu):

newCM := CurrentContext[Copy]():

tset := proc(t)
           Typesetting:-mover(
               Typesetting:-mo("→"),
               Typesetting:-mrow(
                   Typesetting:-mi("Help"),
                   Typesetting:-mo("⁢"),
                   Typesetting:-mi("on"),
                   Typesetting:-mo("⁢"),
                   Typesetting:-mtext(t)
                                ));
        end proc:

newCM[EntryGenerators][Add]( "Help Topics",
   proc(e)
   local x, f;
       f:=proc(t)
          local s;
              if not type(t,'And'(name,constant)) then
                  op(0,t);
              end if;
          end proc:
       [seq([ convert(x, 'string'), [x] ],
            x=subs([':-Fraction'=NULL,Int=int],
                   map(f,indets(e,algebraic))
                         minus {':-Float',':-Integer',symbol,`+`,`-`,`*`,`/`} ))];
   end proc);

newCM:-Queries:-Add(
    "Is Help Constant",
    proc(t)
        if hastype(t,'And'(name,constant)) then
            true;
        else
            false;
        end if;
    end proc):

newCM:-Queries:-Add(
    "Is Help ArithOp",
    proc(t)
        if {`+`,`-`,`*`,`/`} minus map(x->op(0,x),indets(t,algebraic)) <> {} then
            true;
        else
            false;
        end if;
    end proc):

newCM[Entries][Add]("Help  ( related )",
                    "proc(t) print(INTERFACE_HELP(':-display',':-topic'=%ARG1)); t; end proc(%EXPR)",
                    algebraic, 
                    'entry_generator'="Help Topics",
                    'operator'=tset("%ARG1"),
                    'helpstring'="Help on select subtopic"
                   ):

newCM[Entries][Add]("Pi, gamma, Catalan",
                    "proc(t) print(INTERFACE_HELP(':-display',':-topic'=constant)); t; end proc(%EXPR)",
                    algebraic, 
                    'test'="Is Help Constant",
                    'operator'=tset("constants"),
                    'helpstring'="Help on special constants",
                    'submenu'=["Help  ( related )"]
                   ):

newCM[Entries][Add]("`+`,`-`,`*`,`/`",
                    "proc(t) print(INTERFACE_HELP(':-display',':-topic'=`+`)); t; end proc(%EXPR)",
                    algebraic, 
                    'test'="Is Help ArithOp",
                    'operator'=tset("arithmetic"),
                    'helpstring'="Help on arithmetic operators",
                    'submenu'=["Help  ( related )"]
                   ):

Install(newCM);

newCM:-Entries:-Enable("Help  ( related )");

# Right-click on the output of this below (or on it
# as input, in a Document)
Int((1/7)*sqrt(Pi*gamma)-GAMMA(x)*sin(x), x);

# The new entries can be disabled, preventing them
# from appearing.
#newCM:-Entries:-Disable("Help  ( related )");

See the ?ContextMenu help-pages for more details.

There are a few things which could make the context-menu system more powerful:

  • Optional in-place actions for such context-menu entries specified programmatically with Maple code. The object could get replaced. This would allow menu entries like Units->Replace Units to reformat in-place (like the numeric formatting entry does).
  • Optional "no change" entries. This would be suitable for entries such as those given above, where help-pages could get raised without causing any change to the output at all.
  • Telescoping output from context-menu actions. A series of concurrent menu actions could be telescoped together, so that only the ends were visible.

The Maple experts will recognize the procedure which does the extraction of candidate help-topics from the object. Improvements to this are most welcome.

On the topic of improvement, a right-click menuing system available from the GUI's white background (no object involved) would be much more modern than the current top-bar menu system.

There are other things that can be done with customized context menus. Here are a few below.

restart:

with(ContextMenu):

# procedure used to form 2D Math for display over context-menu
# action arrows when performed in a Document.
ts := proc(x) Typesetting:-mover(Typesetting:-mo("&rarr;"),Typesetting:-mtext(x)) end proc:

newCM := CurrentContext[Copy]():  # New():

# Some test queries, to be used in defns of new entries.
newCM:-Queries:-Add(
    "Is Procedure Not Stopat",
    proc(t)
        if type(t,`procedure`)
          and not member(t,:-stopat()) then
            true;
        else
            false;
        end if;
    end proc
                   ):

newCM:-Queries:-Add(
    "Is Procedure Stopat",
    proc(t)
        if type(t,`procedure`)
          and member(t,:-stopat()) then
            true;
        else
            false;
        end if;
    end proc
                   ):

# The new context-menu entries.
newCM[Entries][Add](
    "print",
    "print(%EXPR)",
    `procedure`,
    'helpstring'="print/eval procedure",
    'operator'=ts("print"),
    'category'="Category 1",
    'submenu'=["procedure"],
    NULL
                   ):

newCM[Entries][Add](
    "parameters",
    "op(1,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure parameter sequence",
    'operator'=ts("parameters"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "locals",
    "op(2,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure locals",
    'operator'=ts("locals"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "options",
    "op(3,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure options",
    'operator'=ts("options"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "remember table",
    "op(4,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure remember table",
    'operator'=ts("remember table"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "description",
    "op(5,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure description sequence",
    'operator'=ts("description"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "globals",
    "op(6,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure globals",
    'operator'=ts("globals"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "lexicals",
    "op(7,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure lexical table",
    'operator'=ts("lexicals"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "return type",
    "op(8,eval(%EXPR))",
    `procedure`,
    'helpstring'="procedure return type",
    'operator'=ts("return type"),
    'category'="Category 1",
    'submenu'=["procedure", "operands"],
    NULL
                   ):

newCM[Entries][Add](
    "compile",
    "Compiler:-Compile(%EXPR)",
    `procedure`,
    'autoassign'=true,
    'helpstring'="compile procedure",
    'operator'=ts("compile"),
    'category'="Category 1",
    'submenu'=["procedure"],
    NULL
                   ):

newCM[Entries][Add](
    "remember table",
    "op(4,eval(%EXPR))",
    `procedure`,
    'helpstring'="return procedure's remember table",
    'operator'=ts("remember table"),
    'category'="Category 1",
    'submenu'=["procedure"],
    NULL
                   ):

newCM[Entries][Add](
    "dismantle",
    "dismantle(%EXPR)",
    anything,
    'helpstring'="dismantle expression",
    'operator'=ts("dismantle"),
    'submenu'=["hackware"],
    NULL
                   ):

newCM[Entries][Add](
    "memory address",
    "addressof(%EXPR)",
    anything,
    'helpstring'="memory address of expression",
    'operator'=ts("addressof"),
    'submenu'=["hackware"],
    NULL
                   ):

newCM[Entries][Add](
    "active to inert representation",
    "ToInert(%EXPR)",
    anything,
    'helpstring'="convert to inert representation of expression",
    'operator'=ts("ToInert"),
    'submenu'=["hackware"],
    NULL
                   ):

newCM[Entries][Add](
    "inert to active representation",
    "FromInert(%EXPR)",
    anything,
    'helpstring'="convert from inert to active representation of expression",
    'operator'=ts("FromInert"),
    'submenu'=["hackware"],
    NULL
                   ):

newCM[Entries][Add](
    "set trace",
    "trace(%EXPR)",
    `procedure`,
    'helpstring'="set procedure to trace",
    'operator'=ts("trace"),
    'submenu'=["hackware"],
    NULL
                   ):

newCM[Entries][Add](
    "unset trace",
    "untrace(%EXPR)",
    `procedure`,
    'helpstring'="unset procedure to trace",
    'operator'=ts("untrace"),
    'submenu'=["hackware"],
    NULL
                   ):

# Now add entries whose presence involves a test more complicated
# than merely a type-check.

newCM[Entries][Add](
    "set debug",
    "stopat(%EXPR)",
    `procedure`,
    'test'="Is Procedure Not Stopat",
    'helpstring'="set procedure to debug",
    'operator'=ts("stopat"),
    'submenu'=["hackware"],
    NULL
                   ):

newCM[Entries][Add](
    "unset debug",
    "unstopat(%EXPR)",
    `procedure`,
    'test'="Is Procedure Stopat",
    'helpstring'="unset procedure to debug",
    'operator'=ts("unstopat"),
    'submenu'=["hackware"],
    NULL
                   ):

Install(newCM):

f := proc(x::integer)::integer;
     option foobar;
     global a;
     local y::integer;
          y:=(x-1)*17;
          y;
     end proc:
f(3):=8/5:

# Now, right-click on this name below.
# The new submenus are titled "procedure" (appearing in the
# middle group) and "hackware" (appearing at bottom).
f;

acer


Please Wait...