Trailing-Edge - PDP-10 Archives - mit_emacs_170_teco_1220 - emacs/kbdmac.emacs
There are no other files named kbdmac.emacs in the archive.
!* []DXX:<EMACS>KBDMAC.EMACS.47,  5-Apr-96 18:18:50, Edit by ALDERSON!
!* Change naming convention for libraries from FOO.:EJ to FOO.ELIB on Tops-20!
!* <EMACS>KBDMAC.EMACS.46, 29-May-83 02:30:29, Edit by GERGELY!

!* A keyboard macro's data is represented using two ascii characters
 to describe each 9-bit character.  The first ascii character holds
 the top 2 bits of the 9-bit character, and the second ascii character
 holds the low 7 bits.  When the macro is run, pairs of characters are
 converted back into single 9-bit characters.
 Keyboard macros are encapsulated in TECO macros by putting the 37 chars
 "<Excl>temp<Excl>fm(m.m& Immediate Kbd Macro)" in front.
 This serves to make the TECO macro recognizable and to make
 it push the kbd macro when invoked.

 The keyboard macro call stack is a qvector in q..m.
 It has three slots for each call on the stack.
 The first slot contains the macro string.
   This string includes the call to & Immediate Kbd Macro.
 The second slot contains the index at which we are fetching from the string.
   The initial value of this slot is 37.
 The third slot contains the repeat count.!

!~Filename~:! !Defining and calling keyboard macros.!
!& Setup KBDMAC Library:! !S Put commands on keys.  Create execution stack.!

    m.m ^R_Start_Kbd_Macro u:.x(()
    m.m ^R_End_Kbd_Macro u:.x())
    m.m ^R_Call_Last u:.x(E)
    m.m ^R_Kbd_Macro_Query u:.x(Q)
    :i* m.v Last_Kbd_Macro
    :i*Kbd_Macro_Query m.v Kbd_Macro_Query

    20.*5fs q vectoru..m
    q..m[..o hk 
!& Run Kbd Macro:! !S This is the FS TYI SOURCE for running keyboard macros.!

    q:..m(q2)[0			    !* Get innermost running keyboard macro string.!
    q:..m(%2)[1			    !* Fetch and increment the index at which we are fetching.!
    q1:g0*200.+(%1:g0) fs reread   !* Form next input character, from next!
				    !* two elements of string.!
    %1u:..m(q2)			    !* Store back index into string.!
    q1-fq0"l 0'		    !* If string is exhausted,!
    q:..m(%2)-1u0		    !* decrement repeat count,!
    q0f"nf"gu:..m(q2)'		    !* If not exhausted, decrement count unless it was 0!
       37u:..m(q2-1) 0'	    !* and anyway jump back to start of macro.!
    q..m[..o  zj -15d		    !* Repeat count exhausted => pop it off the pdl,!
    z"e 0 fs tyi source'	    !* and if the pdl is empty we are no longer in a macro.!
    0				    !* Return value for ^R, in case ^R is reading the char.!
!& Immediate Kbd Macro:! !S Push a kbd macro onto the execution stack of such.
Supply the repeat count as pre-comma argument
and a string pointer to the macro as post-comma argument.!

    fs tyi source"e hk'	    !* If an error turned off macro execution,!
				    !* clear out macro call stack.!
    zj 15,0i			    !* Make three more words in the call stack.!
    -1fsback str,.-15fs word	    !* Fill them with string, starting index, and rpt count.!
    37,.-10fs word
    ff"e 1' "#',.-5fs word

    m.m &_Run_Kbd_Macro fs tyi source
!^R Call Last Kbd Macro:! !^R Run the last defined temporary keyboard macro.
A numeric argument is a repeat count.!

!^R Start Kbd Macro:! !^R Begin defining keyboad macro.
After you type this command, everything you type becomes
part of the accumulating keyboard macro as well as being executed.
Numeric arg means append to last defined keyboard macro,
repeating its definition as if you typed it in from scratch.!

    0 fs b cons[1
    q1m.v Kbd_Macro_Defining_Body
    ff"n			    !* With arg, init it with contents!
      q1[..o			    !* of last kbd macro, sans the prefix!
      gLast_Kbd_Macro		    !* that makes it into a bona fide TECO program.!
      j 37d zj'
    m.m &_Define_Kbd_Macro fs tyi sink
    fsvers-751"g 1fs mode ch'
!& Define Kbd Macro:! !S FS TYI SINK for defining kbd macros.
Takes characters typed and accumulates them in a buffer
which will be formed into a keyboard macro when the definition is finished.!

    qKbd_Macro_Defining_Body[..o zj	    !* Select the buffer we use to accumulate.!
    /200.i &177.i 0	    !* Insert the two characters for this command character.!
!^R End Kbd Macro:! !^R Terminate definition of a keyboard macro.
All that you have typed since starting the definition,
except this command itself, becomes the definition.
An argument means re-execute the macro immediately, with the
argument as repeat count, counting defining the macro as once.
^R Call Last Kbd Macro re-executes the last macro defined.!

    fs tyi sink"e @fe nimfs err' !* Complain if not defining a macro.!
    0 fs tyi sink
    zj fstyicount-(fs tyi beg)*2r .,zk
    j i !temp!fm(m.m&_Immediate_Kbd_Macro)  !* Put command to call kbd macro at beginning.!
    hx* m.v Last_Kbd_Macro	    !* make mLast_Kbd_Macro call the macro.!
    Q..o( ]..o
          ) fs bkill		    !* Flush the data structures used in defining.!
    fsvers-751"g 1fs mode ch'
    -1"e 0'			    !* If arg is 1, we are done.!
    f"g-1'mLast_Kbd_Macro'	    !* Else, repeat appropriate number of extra times.!
!Name Kbd Macro:! !C Give a name to the last kbd macro defined.
A function is created with the name you specify,
which when invoked runs that keyboard macro.  (Return means give no name.)
Then, you are asked to give the command character to
put the macro on.  Type C-G if you don't want one.
Combinations with prefix characters such as Altmode and C-X may be used.
Call this function with any numeric argument to inhibit its asking for a key.!

    1,fFunction_name:_[1	    !* Read name of MM command, and define it unless null.!
    fq1"g qLast_Kbd_Macro m.v MM_1'
    FF"E			    !* If user gave no numeric arg, then!
     @ft Put_kbd_macro_on_key:_    !* ask about a key to put it on.!
     m(m.m &_Read_Q-reg)[2	    !* Ask what character to put it in.!
     @ft__Go_ahead 1m(m.m&_Yes_or_No)"e 0'
     qLast_Kbd_Macrou2'	    !* Redefine it.!
!View Kbd Macro:! !C Print definition of a keyboard macro.
Supply a suffix string argument containing the command name.
If the string argument is null, you will be asked to type
the character which runs the macro.!

    1,fFunction_name:_[0	    !* Get the string arg.!
    fq0"e @ftCommand_key:_
	  m(m.m &_Read_Q-reg)u0'	    !* If null, read character from terminal.!
    "# :i0 MM_0'	    !* Otherwise, attach MM to get name of variable.!
    q0[1			    !* Get contents of string.!
    m.m ^R_Call_Last_Kbd-q1"e	    !* If it's the ^X^E command,!
      qLast_Kbd_Macrou1	    !* get the macro it would run.!
    f[b bind 1:< g1>		    !* Get the thing in a buffer.!
    j 6f~!temp!"n		    !* Prevent error in G cmd - get it here instead.!
      :i*Not_a_kbd_macro fs err'  !* Complain if command is not a kbd macro.!
    j s) 0,.k		    !* Flush the call to & immediate kbd macro.!

    j z/2< 1a*200.+(2c0a) m2 ft_>

!& Check Redefinition:! !S Verify that a certain command can be redefined.
Do not allow a command to be redefined unless it is undefined,
self-inserting, or a string starting with Temp.
The command is specified with a q-register name in a string
passed as a string pointer.!

    q1[0			    !* Q0 gets old definition.!
    fq0+1"g			    !* If old definition is a string not made by this macro,!
      f~(0,6:g0)!Temp!"n	    !* don't let user clobber useful command.!
!lose!  !"! :I*Can't_clobber_specified_character_1 fs err''
    "# Afs^r init-q0"n
         200.@ fs^rinit-q0"n	    !* Don't redefine built-ins except error and self-insert.!
	   q0"n			    !* Undefined slots in dispatch prefix are 0.!
	     o lose''''
!^R Kbd Macro Query:! !^R Query and continue macro execution.
If called from a macro, reads a character:
Space continues execution.
Rubout terminates this repetition of the macro.
Altmode terminates all repetitions of the macro.
. terminates after the end of this repetition of the macro.
^R enters a recursive edit;  when you exit, you are asked again.
^L clears the screen and asks you again.
Anything else exits all macros and is reread as a command.

With an argument, we unconditionally enter a recursive editing level
and proceed with the macro when it is exited.  This is the same as
what we do with no argument if the user were to type ^R Space;
but it is done even when the macro is being defined.!

    ff"n 0fstyi sink(	    !* With arg, temporarily turn of defining!
      0fstyi source(		    !* and when re-running turn off that!
      [..j :i..j Kbd_Macro_Edit    !* so that in either case the ^R reads things!
      0			    !* which are not part of the macro.!
      )fstyi source		    !* We DO NOT use F[ on these!
      )fstyi sink		    !* because an error coming out of the ^R!
      0'			    !* must be from C-], and we want to stop in that case.!

    fs tyi source"e 0'	    !* if not from inside macro, do nothing!
    [0[1 QKbd_Macro_Query[..j	    !* Want the same string (eq) each time.!
    0fstyi source( 0fs tyi sink(  !* Turn off macros so we can read from kbd.!
    2,m.i @:fiu1 fiu0		    !* get character, really from tty!
"e f+ Oread'
    q0-"e 0 Oread'
    )fs tyi sink		    !* Pop the two flags.  Don't use qreg pdl!
    )fs tyi source		    !* because we want them to remain 0 if we quit.!
    q0-32"e 0'		    !* space continues on!
    q0-."e 1u:..m(fq..m/5-1) 0' !* . ends after this, set rpt count to 1.!
    q0-"e 1u:..m(fq..m/5-1)'	    !* For Altmode, set rpt count to 1 so flush all repeats.!
    q0f:"l		    !* Both Rubout and Altmode end this repetition!
      fq:..m(fq..m/5-3)-2	    !* by skipping up to the last char
! u:..m(fq..m/5-2)
      fi '			    !* and reading it, causing macro to be popped.!
    0fs tyi source		    !* Other characters quit macro execution!
    q1fs reread		    !* and are unread.!
!Write Kbd Macro:! !C Write the keyboard macro(s) to a file.
	Writes one or more keyboard macros to a file.  The functions to
write are given as string arguments terminated by a null string
argument.  If there are no functions then you will be prompted for ONE
key to save.  If no errors in the preparation have occurred then you
will be asked for the filespec where to write the library (default
KMAC.ELIB).  You need only specify the file name.
	If the keyboard macros are bound to keys then those keys will
also be rebound upon the loading of the library, unless a numeric
argument is given to this function in which case just the function are
	To reload the library the user need only give the command
M-X Load Library<esc>libname, where libname is the name of the library
to load.
	A source file is written out and then deleted using the filename.EMACS
as the file spec.!

    101*5 fs q vector M.V Temp_Kbd_Q-Vector
    0 U:Temp_Kbd_Q-vector(0)		!* (0) contains the number of!
					!* functions!
    <56,FFunction_Name_(<Return>_to_quit):__[0	!* 0: Function name!
	fq0:"G ]0 0;'			!* If no function then quit!
	Q:Temp_Kbd_Q-vector(0)+1 U:Temp_Kbd_Q-vector(0)	!* Otherwise!
					!* increment the number of functions!
	:I*MM_0U0		!* Make the name of the variable!
	[1 1:<Q0 M(M.M &_Macro_Name)U1>"E	!* Try to get the long name!
	    FQ1"G :I*MM_1U0'' ]1	!* of it!
	Q0 U:Temp_Kbd_Q-vector(Q:Temp_Kbd_Q-vector(0)) ]0>	!* Save it!
					!* here for later use!

    Q:Temp_Kbd_Q-vector(0)"E  @ftCommand_key:_	!* If no functions!
	m(m.m &_Read_Q-reg)[0	!* given then read a command key!
	Q:Temp_Kbd_Q-vector(0)+1 U:Temp_Kbd_Q-vector(0)	!* Increment!
								!* the counter!
	Q0 U:Temp_Kbd_Q-vector(Q:Temp_Kbd_Q-vector(0)) ]0 '	!* Save it.!

    f[d file 1f[ fnam syntax		!* Push the file name and syntax!
    etKMAC_ELIB			!* Default to KMAC ELIB!
    :I*Cfsechodisp			!* Clear echo area!
    1m(m.m&_read_filename)Kbd_Macro_File	!* Read the filename!
					!* F:  The output filename!

    f[B Bind				!* Get a temporary buffer!
    [0 [1 [2 [3 [4 [5 [6 [7 [8 [9 [P	!* Temporary Q-registers!

    :I*				!* D:  Key redefinitions!
    M.M ^R_Call_Last_Kbd		!* K:  Macro value for this!
    0[I					!* I:  Index counter!
    0[O					!* O:  Nonzero if ok to write file!
    FF"'N [R			!* R:  Nonzero to omit key checking!
    0[S					!* S:  Nonzero if & setup required!

    Q:Temp_Kbd_Q-vector(0)F"G<	!* For the number of functions do!
	    Q:Temp_Kbd_Q-vector(%I) U0	!* 0:  Function name!
					!* 1:  Function contents!
	    1:<Q0 U1>"N		!* Error in getting the function!
		1,(fq0-1):G0 U3		!* Output just the functiuon name!
		   )fsechodisp 0fsechoactive w45 O Omitkbd'

	    QK-Q1"E			!* If its the ^X^E command!
		QLast_Kbd_MacroU1	!* The say its the last kbd macro!
		QI:\U4 q1 M.V MM_Unknown_KBD_Macro_4
		:I*MM_Unknown_Kbd_Macro_4 F(U0

	    .F(UP)( 1:<G1> )J		!* P:  The location of the start of!
					!* the contents!
	    6f~!temp!"N		!* Prevent error in G cmd - get it!
					!* here instead!
		1,(fq0-1):G0 U3		!* If it does not have!
					!* <excl>temp<excl> then not a kbd!
					!* macro !
		:I*A3_is_not_a_kbd_macro.  !*
		!  __Omitting_writing_it_to_the_file.(
		   )fsechodisp 0fsechoactive	!* Output the error!
		w45 O Omitkbd'	!* Give time to read!
	    1UO				!* Got one!
	    QPj m(m.mReplace_String)__	!* Fix underlines!
	    j m(m.mReplace_String)		
					!* TAB replacement.!
	    QPj m(m.mReplace_String)\\	!* back slashes !
	    12i 13i 10i			!* Put in a formfeed and CRLF!

	    .(G(Q:Temp_Kbd_Q-vector(qi)))J	!* Get the macro name!
	    4F~MM_"N		!* Check if a macro!
		fQ(Q:Temp_Kbd_Q-vector(qi))FX5	!* 5: gets real name!
		fq5:"G qi:\u4 :I5Unknown_KBD_Macro_4'
		I!5:!_	!* Set up for compressing!
	    "# 4D I!		!* Put out the description!
		S W-1D i:!_'	!* as a subroutine!
	    .( 0l 1c .,(FB! 2r .)X4)J	!* 4:  The function name we!
						!* put in!
	    @:i1\			!* Say where from and make sure KBDMAC!
					!* gets loaded in case!
	    zj i\ fm10 w13i10i	!* Make sure it gets macroed!
						!* at the end!
	    QR"N O Omitkbd'		!* Omit finding the keys!

	    J -1u5			!* 5:  Index counter!
	    Q:Temp_Kbd_Q-vector(qi)U0	!* Get the original name!
	    Q0u3			!* 3:  Get the function!
	    <%5,q3 :FU5 q5:;		!* Step through the dispatch table!
		1US			!* Got a key definition!
		IM.M4U		!* Create the command line to place it!
					!* on the given key!
		q5/200.f"g,46I'W I q5I 27i13i10i	!* Write out what key!
		-1l <:FB_; w-1d 95i>	!* Backup and replace the spaces with!
					!* underlines!
		!<! :IDD________4_==>_	!* Make the comment for the!
						!* key redefinition!
		q5&200."N :IDDControl-'
		q5&400."N :IDDMeta-'

		1l>			!* Position at the next line!

	    F[B BIND GPrefix_Char_List J	!* Now do the same for the!
					!* prefix characters!
	    :I9			!* 9:  The instruction lines!
	    < .-Z;			!* For all the prefix characters!
		FB__			!* Get the dispatch vector (q6)!
		2r 0X8 2c		!* 8:  The prefix character name!
		M(:X*)U6 1c:X7 1L	!* and its name(Q7)!
		   -1U5			!* For the whole vector!
		   < %5,Q3F6 U5 q5:;	!* find every occurence!
		      1US		!* Got a key definition!
		      zj .(IM.M4U:7(5) 13i10i)J
		      .(<:FB_; -1d95i>)J	!* make the instruction and!
						!* replace the blanks by!
						!* underlines !
		      @X9 zk		!* Save the instruction line and clean!
		      !<! :IDD________4_==>_8_5
					!* Save the key description!
					!* up!
		   )J>			!* Get back to where we were!
	    F]B BIND			!* Kill the temporary buffer!
	    FQ9"G G9'			!* Any instruction lines then insert!
					!* them !
	    zj				!* To the end and continue!

    QO"E :I*CNothing_to_savefsechodisp 0fsechoactive
	OEND'				!* Done nothing then save nothing!

    J  etF				    !* Setup default filespec.!
    i!~Filename~:!_!Saved_keyboard_macro.! 13i10i
					!* Put in the header for the library!
    G(fs d fn1F(u3)) 13i 10i		!* The filename is the name of the!
					!* library!
    QS"N				!* We require a key definition setup!
	12i 13i 10i			!* Make a new page!
	I!&_Setup_3_Library:!_    !*
	    !   !S_Setup_the_keys_for_this_library. 13i10i
					!* Put in the function name !
	IThe_following_key_redefinitions_will_be_made: 2<13i10i>
	f[bbind gd
	j <:S!; Excl>
	j <!<! :S==>_;
	    :L -S_ W1C
	    1:C; 0AU0
	    Q0-177"E -D IRubout Oloop'
	    Q0-32"G Oloop'
	    Q0-27"E  -D IAltmode Oloop'
	    Q0-8"E   -D IBackspace Oloop'
	    Q0-9"E   -D ITab Oloop'
	    Q0-13"E  10,1A-10"'N; W-D IReturn Oloop'
	    Q0-10"E  -D ILinefeed Oloop'
	    Q0-32"E  -D ISpace Oloop'
	    -D ICntrl- Q0+100.I
	GD I! 13i10i
	13i10i s
W 0L I0 13i10i'	!* Put in the pop at the end!
						!* of the page!

    etf				!* get output filespec.!
    etEMACS				!* Make it a source file!
    ei@hpef				!* Write out file.!
    fso fileu2				!* Actual filespec written!
    :I*AWritten:_2_!Source_file_(deleted) fsechodisp
    ED					!* delete the file!
    0fs echo active			!* is output!

	m(m.mload_library)PURIFY'	!* Load PURIFY if not present.!
    m(m.m&_Compress_Buffer)		!* Compress and Purify into :EJ form.!

    etF				!* Get output filespec.!
    ei@hpef				!* Write out file.!
    fso fileu2				!* Actual filespec written!
    :I*AWritten:_2__!Library_file fsechodisp
    0fs echo active			!* is output!
    M(M.M Kill_Variable)Temp_Kbd_Q-vector	!* Kill the variable we!
						!* created!
!Kbd Test End of Buffer:! !C Quit KBD macro execution if at end of buffer.!

 fs tyi source"n
 .-z"e 0fs tyi source''	    !* Quit execution if at end of buffer.!
/ Local Modes: \
/ MM Compile: 1:<M(M.MDate Edit)>
M(M.M^R Save File)
M(M.MGenerate Library)KBDMACKBDMAC
1:<M(M.MDelete File)KBDMAC.COMPRS>W \
/ End: \