Newsgroups: vmsnet.tpu
Subject: Re: Control keys and EDIT/TPU
From: Peter Galbraith <galbrth@ac.dal.ca>
Date: 04 Nov 1992 12:59:41 -0400
Reply-To: Peter Galbraith <GALBRTH@AC.DAL.CA>
Organization: The Internet
Return-Path: <TPU-Mgr@SHSU.edu>
Errors-To: TPU-Mgr@SHSU.edu
X-Listname: Text Processing Utility (TPU) Language Discussion List
CC: ritley@uimrl7.mrl.uiuc.edu
X-Vms-To: INFO-TPU
X-Vms-Cc: IN%"ritley@uimrl7.mrl.uiuc.edu",GALBRTH
Mime-Version: 1.0
Content-Transfer-Encoding: 7BIT

In a message of 29 Oct 1992 23:22:16 +0000 (GMT)
Received on Wed, 4 Nov 1992 08:07:14 -0400

Dave Cantor <cantor@star.enet.dec.com> wrote
to: Text Processing Utility (TPU) Language Discussion List <INFO-TPU@SHSU.edu>
Subj: RE: Control keys and EDIT/TPU

>In article <1992Oct29.101456.1@slacvx.slac.stanford.edu>, fairfield@slacvx.slac
   .stanford.edu writes...

>>    The alternative (dirty!) is to write a TPU procedure that gets bound
>>to ctrl-k.  When that procedure is executed, have it read the next key and
>>determine which procedure is to be executed for that 2nd key.
>
>Another way, less dirty, but more complicated, would be to write a TPU
>procedure, bound to control-k, which will activate new bindings for
>some or all the keys.  In general, all procedures invoked by the new
>bindings must eventually restore the old bindings which were in effect
>before control-k was struck.
>


History repeats itself.  Follows is one of my post from March 91.
It deals with both cases mentionned above.

    #34          7-MAR-1991 17:51:59.14                                 INFO-TPU
From: Peter Galbraith, Dalhousie Oceanography <GALBRTH@AC.DAL.CA>
To:   info-tpu@SHSU
Subj: Skeleton Procedures for Embedded CTRL Keymaps

Date sent: Thu, 7 Mar 91 13:26 AST
Received:  Thu, 7 Mar 91 17:51 AST

!I thought about the embedded CTRL keymaps last night while waiting for
!Quantum Leap on TV.  I came up with two alternatives.
!
!I have quoted my comments to allow you to strip out the mail header and
!EXTEND ALL.
!
!RULES
!~~~~~
!   There is a tree of CTRL keymaps.  When you press a valid CTRL prefix,
!   the editor then waits for further keys to be pressed.  You can then:
!
!   o Press a defined key -> function executed, exit CTRL prefix tree
!   o Press an undefined key -> editor says so, stays at that tree level
!   o Press an embedded CTRL prefix -> Go deeper in CTRL prefix tree
!   o Press CTRL-G to escape CTRL prefix tree
!
!As an example, I show a simple branch of a tree
!
!  Main        level 1       level 2
!  ~~~~        ~~~~~~~       ~~~~~~~
!o CTRL-\  ->  CTRL-\   ->   CTRL-G
!              CTRL-G          to esacpe
!                to escape   M
!              L               defined
!                defined
!
!VERSION 1
!~~~~~~~~~
!In this version, you stay within a procedure until a proper sequence leads
!to completion (either a defined function or CTRL-G).
!
!o Define a keymap for TPU$KEY_MAP_LIST to put keys that invoke first layer
!  of CTRL prefixes
!o Add it to TPU$KEY_MAP_LIST
!o For each CTRL prefix:
!  o Create a unique keymap
!  o Define function keys (L and M in this example) to do stuff
!  o Define a key (or many) to escape the prefix tree (CTRL-G in this example)
!  o Define keys to call embedded CTRL prefixes
!    (an extra CTRL-\ in this example)
!o A single recursive procedure is called to go deeper into the prefix tree.
!  Keys that call it pass the keymap to go to as an argument:
!   for ex:        peve$ctrl_keymap_prefix('eve$fs_keys_2')
!
!! Global variables:
!!  o various keymaps
!!  o peve$x_message - message displayed i.e. "CTRL-\ CTRL-\"
!
!Note that the eve_build_ex1 procedure would NOT normally exist.  this code
!would be found at the end of a module and executed once at build time.
!(or give it a name which doesn't start in "eve_", use it once and SAVE your
!section file).

! To try both versions:
! o EXTEND ALL
! o BUILD EX1
! o try the first with CTRL-\ (see above for possible scenarios)
! o BUILD EX2 (you must have done BUILD EX1 first!)
! o try the second the same way (the message may be wrong the first time
!   because I use the same variable as in the first example!)

procedure eve_build_ex1
 ! Define a keymap to put the CTRL prefixes in for TPU$KEY_MAP_LIST
 eve$ctrl_prefix_keys := create_key_map("eve$ctrl_prefix_keys");

 ! Put it into TPU$KEY_MAP_LIST.  This will put USER keys back on top
 remove_key_map("TPU$KEY_MAP_LIST","eve$user_keys");
 add_key_map("TPU$KEY_MAP_LIST","first","eve$ctrl_prefix_keys");
 add_key_map("TPU$KEY_MAP_LIST","first","eve$user_keys");

 ! Give CTRL-\ a good name, instead of FS
 ! See my post of last week about this...
 define_key("eve$null",key_name("\",ctrl_modified),"CTRL-\",
             eve$x_current_language_keymap);

 ! Create CTRL-\ keymap (layer 1)
 eve$fs_keys_1 := create_key_map("eve$fs_keys_1");

 ! Define CTRL-\ key in TPU$KEY_MAP_LIST to go to it and initialize message
 define_key("peve$x_message := '';peve$ctrl_keymap_prefix('eve$fs_keys_1')",
           key_name("\",ctrl_modified),"CTRL_PREFIX_\","eve$ctrl_prefix_keys");
 ! I'll use comment to ID it -----------^^^^^^^^^^^^^

 ! Define CTRL-G to exit CTRL prefix tree
 define_key("eve$null",key_name("G",ctrl_modified),"CTRL_BACK","eve$fs_keys_1");
 ! I'll use comment to ID it -----------------------^^^^^^^^^
 ! No actual procedure defined

 ! Define a test key in layer 1 of CTRL-\
 define_key("message('Pressed L')",key_name("l"),"test","eve$fs_keys_1");

 ! Create a second layer CTRL-\
 eve$fs_keys_2 := create_key_map("eve$fs_keys_2");
 define_key("peve$ctrl_keymap_prefix('eve$fs_keys_2')",
           key_name("\",ctrl_modified),"CTRL_PREFIX_\","eve$fs_keys_1");
 ! Define CTRL-G to exit CTRL prefix tree
 define_key("eve$null",key_name("G",ctrl_modified),"CTRL_BACK","eve$fs_keys_2");
 ! Define a test key in layer 2 of CTRL-\
 define_key("message('Pressed M')",key_name("m"),"test","eve$fs_keys_2");
endprocedure;

procedure peve$ctrl_keymap_prefix(peve$arg1)
local pkey, lcomment;

! Display key sequence pressed; store in peve$x_message
    if (peve$x_message = "") then
      peve$x_message := eve$key_name(last_key);
    else
      peve$x_message := peve$x_message + " " + eve$key_name(last_key);
    endif;
    message(peve$x_message);

    loop
      pkey := read_key;
      lcomment := lookup_key (PKEY, comment, peve$arg1);
      if lcomment = "" then
        message(peve$x_message + " " + eve$key_name(pkey) + " Not defined");
      else
! Check if a CTRL_BACK key
        if substr(lcomment,1,9) = "CTRL_BACK" then
          message("");
        else
          execute(lookup_key (pkey, program, peve$arg1));
        endif;
        exitif (1);
      endif;
    endloop;
    return;
endprocedure;


!VERSION 2
!~~~~~~~~~
!
!This (more elegant?) version actually changes the KEY MAP LIST of the current
!buffer to one associated with the CTRL prefix typed.  It then exits the
!procedure and let eve do the work.  It is very easy to add-on to.
!
!I'll assume eve_build_ex1 was executed to:
!  o Create `eve$ctrl_prefix_keys' keymap to hold first layer CTRL prefixes
!  o Add it to TPU$KEY_MAP_LIST
!  o Give CTRL-\ a good name, instead of FS
!  o Create CTRL-\ keymap (layer 1)
!  o Create a second CTRL-\ keymap (layer 2)
!  o Define test keys for each keymap ("L" and "M" keys)
!
!o For each CTRL prefix:
!  o Create a keymap for each CTRL prefix (done above)
!  o Create a unique key map list and assign prefix keymap to it
!  o Define a (or many) key to escape prefix tree (CTRL-G in this example)
!  o Define keys to call embedded CTRL prefixes
!   (an extra CTRL-\ in this example)
!
!o The key map list of the buffer will actually be changed from
!  TPU$KEY_MAP_LIST to a prefix key map list.
!o A SET(UNDEFINED_KEY) call sets a distinct message to be dsiplay when you
!  then press undefined keys.
!o A SET(POST_KEY_PROCEDURE) call sets a procedure to execute after each
!  defined key is preesed to go back to TPU$KEY_MAP_LIST, except when you
!  go deeper into the CTRL prefix tree.
!o A SET(SELF_INSERT) call prevents eve from typing-in regular typing keys
!  in CTRL prefix key map lists.


procedure eve_build_ex2

! create both key map lists, with their initial CTRL prefix keymaps.
 eve$fs_keymap_list_1 :=
   create_key_map_list("eve$fs_keymap_list_1","eve$fs_keys_1");
 eve$fs_keymap_list_2 :=
   create_key_map_list("eve$fs_keymap_list_2","eve$fs_keys_2");

 ! Define CTRL-\ key in TPU$KEY_MAP_LIST to change KEY MAP LIST
 define_key("peve$ctrl_keymaplist_prefix('eve$fs_keymap_list_1')",
           key_name("\",ctrl_modified),"CTRL-\ Prefix","eve$ctrl_prefix_keys");

 ! Define CTRL-\ key in layer 1 (eve$fs_keys_1) to go to layer 2
 define_key("peve$ctrl_keymaplist_prefix('eve$fs_keymap_list_2')",
           key_name("\",ctrl_modified),"CTRL-\ Prefix","eve$fs_keys_1");

 ! Define CTRL-G to exit CTRL prefix tree (for each layer)
 define_key("peve$ctrl_post_key;message('');",key_name("G",ctrl_modified),
            "Escape CTRL prefix","eve$fs_keys_1");
 define_key("peve$ctrl_post_key;message('');",key_name("G",ctrl_modified),
            "Escape CTRL prefix","eve$fs_keys_2");

 ! Set what_do_to on undefined keys in CTRL prefix key map lists
 set(undefined_key,"eve$fs_keymap_list_1",
    "message(peve$x_message + ' ' + eve$key_name(last_key) + ' Not defined')");
 set(undefined_key,"eve$fs_keymap_list_2",
    "message(peve$x_message + ' ' + eve$key_name(last_key) + ' Not defined')");

 ! Set post-key procedures in CTRL prefix key map lists to go back to
 ! TPU$KEY_MAP_LIST
 set(post_key_procedure,"eve$fs_keymap_list_1","peve$ctrl_post_key");
 set(post_key_procedure,"eve$fs_keymap_list_2","peve$ctrl_post_key");

 ! Set SELF_INSERT to off to avoid typing-in regular typing keys
 set(self_insert,"eve$fs_keymap_list_1",off);
 set(self_insert,"eve$fs_keymap_list_2",off);
endprocedure;

procedure peve$ctrl_keymaplist_prefix(peve$arg1)
    if (get_info(peve$x_message,"type") = UNSPECIFIED) or
       (peve$x_message = "") then
      peve$x_message := eve$key_name(last_key);
    else
      peve$x_message := peve$x_message + " " + eve$key_name(last_key);
    endif;
    message(peve$x_message);
    if get_info(current_buffer, "key_map_list") <> "TPU$KEY_MAP_LIST" then
       peve$x_no_exit := TRUE;  !Inhibit peve$ctrl_post_key from exiting now
    endif;
    set (key_map_list, peve$arg1, current_buffer);
endprocedure;

procedure peve$ctrl_post_key
    if peve$x_no_exit then peve$x_no_exit := FALSE; return; endif;
    set (key_map_list, "TPU$KEY_MAP_LIST", current_buffer);
    peve$x_message := "";
endprocedure;

! Hope this will be useful for someone!
! Peter

 _____________________________________________________________________________
 Peter Galbraith       [Phone: (902) 494-7007] |  GALBRTH@AC.DAL.CA (InterNet)
 Dept. of Oceanography,  Dalhousie University  |  GALBRTH@DALAC     (BitNet)
 Halifax, Nova Scotia, Canada, B3H 4J1         |  rhogee@dalcs      (UUCP)