2

I want to add some shortcuts in ISPF Edit.

For instance, I'd like to type T for "TOP" and B for "BOT". How can I do this? I tried to enter

define t alias top

in the command line, but it didn't work: I have "COMMAND TOP NOT FOUND" if I use the shortcut.

How can I achieve this? And how to have this shortcut available each time I open Edit?

zarchasmpgmr
  • 1,422
  • 10
  • 21
FredericP
  • 1,119
  • 1
  • 14
  • 27
  • What a coincidence.Yesterday I was working with an initial edit macro (although a program rather than a script, but the concepts are the same). – zarchasmpgmr Jun 15 '17 at 15:09

2 Answers2

3

TOP and BOTTOM are commands in the ISPF command table. They are not EDIT commands. They are ALIAS's for UP MAX and DOWN MAX. An ISPF command must be at least 2 bytes in length, so you can not create a new ALIAS in the command table for UP MAX using a 1 byte character. You can define an Edit macro called T. The macro could do something like

/* REXX */
address ISREDIT "MACRO"
address ISREDIT "LOCATE 0"
exit(0)

B for BOTTOM could be

/* REXX */
address ISREDIT "MACRO"
address ISREDIT "LOCATE .ZLAST"
exit(0)

Note that B would put you on the last line and not the last full page like BOTTOM actually does. For TOP and BOTTOM I would personally just use PF7 or PF8 with M on the command line to do the max scroll. Its just 1 character with a PFKEY as opposed to the enter key.

Marv Knight
  • 416
  • 2
  • 4
3

A flexible solution would be to create an initial edit macro that does double duty. On first invocation as the initial edit macro, it defines commands such as T and B as aliases to itself. These commands then cause ISPF to invoke the same macro and perform the appropriate action. For this, use the ISPF variable ZEDTMCMD as the main logic driver; it is set by the editor with the command that invoked the macro.

Here is a very general REXX solution called MYMACRO:

/* REXX */                                                               
address 'ISREDIT'                                                        
parse source . . s3 .                                                    
'MACRO'  /* You can specify optional arguments if you want */            

/* Easier to work with upper case and no leading or trailing blanks */   
address 'ISPEXEC' 'VGET (ZEDTMCMD)'                                      
invoke_cmd = translate(strip(zedtmcmd))                                  

select                                                                   
  when invoke_cmd == s3 then do /* first time call */                    
    'DEFINE T ALIAS' s3                                                  
    'DEFINE B ALIAS' s3                                                  
  end                                                                    
  when invoke_cmd == 'T' then 'UP MAX'                                   
  when invoke_cmd == 'B' then 'DOWN MAX'                                 
  otherwise nop                                                          
end                                                                      
exit 0                                                                   

Next, specify MYMACRO as a initial edit macro. This can be specified in several places, but the easiest is on the main edit panel (option 2).

ISPF Edit Entry Panel with highlight of initial macro field

Note that your macro needs to be in the standard lookup (DD SYSEXEC, SYSPROC, or DD SYSUEXEC or SYSUPROC if ALTLIB is active, or ISPCLIB) to be found.

If you decide to write a program, it is a little bit more complicated. You have to:

  • prefix the name in the initial edit macro field with an exclamation point ! so ISPF knows to invoke it as a program rather than a script (this means 7 characters maximum for the name);
  • remove the leading exclamation point before executing the SELECT;
  • and add 'DEFINE MYMACRO MACRO PGM' as the first line in the first time call logic, so ISPF knows that it is a program, not a script.

In this scenario, when executed as the initial edit macro, ZEDTMCMD will have the leading exclamation point.

By creating one macro, you can make it easier to add new commands in the future.

The ISPF installation SAMPLIB (usually named ISP.SISPSAMP, but it may be different at your installation) has several example macros, all beginning with ISR*. There are REXX scripts, CLISTs, COBOL, and PL/I examples. (No assembler, but creating one is a trivial exercise.)

zarchasmpgmr
  • 1,422
  • 10
  • 21
  • Thanks for your detaillled answer. Unfortunately, it seems that I can't write in SYSEXEC nor SYSPROC, so I assume I have no solution available here... – FredericP Jun 16 '17 at 11:40
  • You should be able to use `ALTLIB`; you'd have to do this every time you log on, but in addition to pointing to SYSUPROC and SYSUEXEC, you can also point to your own library, e.g., `ALTLIB ACT USER(*) DATASET(dsn)`. I only touched on it lightly above, but if you let me know that you can issue `ALTLIB`, I'll add it to the answer. `ALTLIB` is documented [here](https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.ikjc500/altlib.htm), and there is a good discussion about using `ALTLIB` under ISPF. If you have an exec that runs at logon, you can add `ALTLIB` to it. – zarchasmpgmr Jun 16 '17 at 22:08
  • I tried to use ALTLIB myself but didn't achieve... Can you point to the correct way to write it? – FredericP Jun 21 '17 at 10:27
  • Try `ALTLIB ACT APPLICATION(EXEC) DATASET name` where name is the name of your REXX dataset, using the TSO rules regarding quotes and high level qualifers. If you are in ISPF, prefix with `TSO`. In ISPF with multiple screens, `ALTLIB` applies only to the current screen. – zarchasmpgmr Jun 21 '17 at 18:15
  • It didn't work for me. I used ALTLIB to be able to use the macro in Edit. It is OK, but the macro didn't do anything. It seems that WHEN INVOKE_CMD == 'MYMACRO' doesn't work. I don't understand why... – FredericP Jul 10 '17 at 22:17
  • I looked at the above code, and apparently when I did a cut/paste, the cut didn't actually occur, and it pasted an earlier version. A `VGET` is missing. My sincere apologies. I have updated the example, and I've also made it more flexible, in that it gets the name of itself from `PARSE SOURCE`. – zarchasmpgmr Jul 11 '17 at 16:49