How to change primary command in Edit - macros

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?

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).
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.)

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.

Related

notepad++ How to assign two macro to same key?

Using the GUI: I assigned a macro to allow me to select the current line my cursor is on. I assigned it to 'ctrl+a', and reassigned 'select all' to 'ctrl+alt+a'. I now want, when I press 'ctrl+a' a second time, to have it highlight the remainder of the paragraph. Currently these commands are available via the following key-press:
Instruction:
1. Home->shift+end --highlights one line
2. Home->shift+end->shift+end -- highlights connected lines
So 1. is assigned to 'ctrl+a', but I'm stuck at this point. How do I assign ctrl+a when hit a second time to highlight the connected lines/paragraph? Details/specifics in layman's terms would be appreciated. Again, I've only been using the gui options, I'm not familiar with the more codey options. Note that it doesn't allow me to use
ctrl+a->shift+end.
I'm not overly familiar with macro and hotkey binding, so I'm unaware if this is a limitation or if there's a workaround, other than writing a program to fix it.
Not a coder, but from what I know of Lua I cameup with:
is_press=false
if btn(ctrl+a) and !is_press then btn(Home->shift+end) is_press=true end
if btn(ctrl+a) and is_press then btn(Home->shift+end->shift+end) is_press=false end
I could assign 2. to ctrl+shift+a, as a separate macro if all else fails.
Short answer, I don't think this is possible with a singe shortcut/macro.
Behind the scenes, Scintilla is doing the selecting. Once you've done the selection, going back to "home" the second time will reset the word wrap extension.

NppExec in Notepad++ to "Run a Macro Multiple Times..."

I use simple NPP_Exec commands in N++ which work fine for macros. Eg.:
NPP_MENUCOMMAND Macro/Action1
NPP_MENUCOMMAND Encoding/Convert to ANSI
NPP_SAVE
But how can I run a specific macro several times?
I have tried NPP_MENUCOMMAND Macro/Run but then I still have to manually select the macro I need and set it to "Run until the end of line" in the pop-up window.
You can use the NppExec plugin for simple loops like this:
:REPEAT
SCI_SENDMSG SCI_GETCURRENTPOS
set pos1 = $(MSG_RESULT)
// put your Macro invocation here instead of the linedown:
SCI_SENDMSG SCI_LINEDOWN
SCI_SENDMSG SCI_GETCURRENTPOS
set pos2 = $(MSG_RESULT)
// if the linedown (or your macro) doesnot give another pos, we have reached the end
if $(pos1) == $(pos2) goto END
// else loop
goto REPEAT
:END
it stores the current position
then it does something that advances the position (in this example a linedown, you would put your Macro invocation there, make sure it changes the cursor position)
then the position is compared with the stored position; we have reached the end, if the position has not changed;
in this case we leave the loop
I just found a simple and easy solution for that. I did not use command lines but it might work as well:
Make sure the macro ends with a Ctrl-Tab key
From Settings -> Preferences -> MISC, disable the doc switcher.
Open all files to be edited.
Use the "Run macro multiple times" dialog, and enter the number of files you have just opened.
Execute
Save all
I did not create this, found it here:https://sourceforge.net/p/notepad-plus/discussion/331754/thread/469ffec9/ , but it worked like a charm for me. I could edit 400 documents in less than 2 min.
I found another way to achieve this. Inspired by Wagner Fontes's answer, we can do the following:
Step 1: Record your Macro
Step 2 (Important): Before you finish the Macro, type the "Ctrl + Tab" as the last record in the Macro. This hotkey means moving to the next opening text file.
Step 3: Save the Marco.
Because of the Step 2, Notepad will move to the next text file after running the macro once. In this method, "Run a Macro Multiple Times" makes "Multiple Files".

How to assign a string ending in <CR> to a vimscript variable without it adding a <LF>?

I have been playing around with vim macros lately (in MacVim at the moment), and sometimes I like to explicitly assign a macro into a register using e.g. :let #a='(macro keystrokes)'. This is generally working fine, but I found a weird behavior in which anytime I assign a string value that ends in Carriage Return / ^M, vim automatically adds a Linefeed / ^J to the end before putting it in the register, which affects the execution of the macro!
Example: Let's say I record a simple macro that gets into insert mode, types "hey", escapes out of insert mode, and then hits Enter twice to go down 2 lines. I record this into register #a by typing qaihey<Escape><Enter><Enter>q, which stores the following in #a:
ihey^[^M^M
So far so good, and executing the macro by typing #a does just what it's supposed to. Another perfectly ok way I can get this same macro into register #a would be by typing the whole thing (ihey<Ctrl-V><Escape><Ctrl-V><Enter><Ctrl-V><Enter>) into a buffer and then yanking it with "ay -- the end result is just the same. But here's the weird thing -- suppose I just wanted to assign that string directly into #a using a let statement:
:let #a='ihey^[^M^M'
Now if I type :reg to look at the value it says there's an extra ^J on the end for some reason:
"8 ...
"9 ...
"a ihey^[^M^M^J
"b ...
Having the extra ^J causes it to go down an extra line when I execute the macro, so it's actually changing the behavior.
Anybody know why this extra character is being added? Anyone know how I can get a string value ending with ^M into a register (or any variable), without having an extra ^J get added?
Some quick checking the vim help files says this:
:let #{reg-name} = {expr1} *:let-register* *:let-#*
...
If the result of {expr1} ends in a <CR> or <NL>, the
register will be linewise, otherwise it will be set to
characterwise.
In other words, ending the string with a carriage return will make Vim interpret it as a line ending
Quick googling give this from the VimTips wiki:
Note however, that the above method using :let will not work as expected for any macros which you make ending in a < CR > or < NL > character (carriage return or newline). This is because, as documented in :help :let-#, Vim will treat the register as "linewise" under these conditions. The reason for this is to make registers set with :let act "the right way" when dealing with yanked/deleted text, but it can cause headaches when dealing with recorded macros. Possible workarounds include using the setreg() function or adding "no-op" commands to the end of the macro, such as a < ESC >. See the discussion on vim_dev about unexpected behavior of the :let command for details.
So you have a few options: use setreg() or add some kind of no-op sequence (< ESC >) to the string when you use let.
In order to insert special keys easily using let, just use double quotes:
:let #a="ihey\<Esc>\<Return>\<Return>"
If you use single quotes vim will insert:
\<Esc>\<Return>\<Return> instead of their functions

How can I modify emacs' Search and Replace to perform a more complicated task?

total Emacs noob here. So right now I'm working on a fairly big LaTeX project in Emacs in which there are couple of places where I need to index some words, using the makeidx package. Because I also wanted indexed words to be bold, I created my own command \ind{} which would make the argument go bold and indexed. But right now I'm dissatisifed with this command so I'd like to change every instance of \ind{whatever} in my text by \textbf{whatever}\index{whatever by default}.
The thing is I know exactly what I want :
Go through the text, look for any instance of \ind{ and replace by \textbf{ using search-and-replace
Save the argument of \ind ("whatever" in this case) in memory
Ask me the user what should the argument of \index be. By default (by striking enter), it should be the first argument, but I can also change my mind and enter something different ("whatever by default" in this case). If there's no input (only a space " " for example) stop the program.
Write down \index{, the new argument and }.
Go to next occurance in the text.
But, alas!, I know not how to achieve this, so I need someone's help. If it should take too much time to explain how to do such a thing, would you please send me some tutorial about writing my own functions?
I hope I'm being clear, and thanks for your patience!
This approach seems vaguely unorthodox to me, but it works and seems sufficient for a one-off job...
In the replacement text for replace-regexp and query-replace-regexp (C-M-%), one newer escape sequence is \,(...), where ... can be any Lisp expression. There's a Lisp function read-from-minibuffer which reads arbitrary text typed by the user, with an optional default. Therefore:
C-M-%: Start query-replace-regexp.
\\ind{\([^}]+?\)}: The pattern to search for.
\\textbf{\1}\\index{\,(read-from-minibuffer "index content? " \1)}: The replacement text. The user will be prompted for the text to put in the braces following the \index{} element, using the original text between the braces following the \ind{} element as a default.
Note that when using query-replace-regexp, you'll have to confirm each choice by typing y after each. Use M-x replace-regexp if you want to avoid this step.
Vlad give you the LaTeX answer to your problem. An Emacs solution is the key-macro: start with
C-x (
to define a new macro, then do one step of your change, say:
C-s \ind{
<left>ex
Then copy and paste the argument in the \textbf macro... You have to be careful to move in a way that will be repeatable. Once the standard modification is done, you let the cursor after the whatever by default and end the definition by
C-x )
now C-x e will call the macro you just define, letting your cursor at the correct place to change the part you want to change You can also repeat the e to call the macro several time at once.
Why not just redefine the \ind so that it can get an optional argument?
For example:
\newcommand{\ind}[2][]{%
\def\first{#1}%
\ifx\first\empty
\textbf{#2}\index{#2}%
\else
\textbf{#2}\index{#1}%
\fi
}
This way you can use \ind{whatever} or \ind[whatever-else]{whatever}.

Is there a way to display a macro list similar to displaying your mappings in Vim?

I know there is a way to list mappings via :map (or :imap, :cmap, etc.), but I can't find a way to list macros I have stored in my vimrc file (as in let #a = 'blahblah').
Is there a way to do this without having to manually looking inside it (via :split [myvimrcfile] or whatever way)?
Also, if it is possible, is there a way to attach some sort of documentation that would display with the macro to explain what it is for? I have a handful that I use quite a bit, but about 6 weeks apart. It would be nice to just quickly list them along with a comment that tells me what the macro does (or even just a name so I make sure I use the right one).
Thanks
In vim, the macros are just stored in registers. You can recall the content of any register and execute it as a macro (which is what the # does). To see a list of what is in your registers, use :reg.
You can see the contents of all the registers using the
:reg
command. Or an argument string like this
:reg ahx
will show you the contents of registers a, h, and x.
That way you can at least see what sequence of commands will be run and hopefully that will be clear enough for you to tell one from another.
The registers simply contain text. You can paste the command sequence in as text or you can copy text into a register and then run it as a command, depending on how you access the register.
I have not found any direct way to edit the contents of a register, but you can paste it into the file, edit it, and then save it back to the same register.
IHTH.
As /u/jheddings wrote the macros are stored as registers and what counts is the assignment of the code to the register (usually done in the vimrc files with let #a=blahblah
To ease the way to display the macros you defined in your vimrc file (in my case it is in the ~/.vimrc path) you can use this vim function:
function! ShowMacros()
10new
exe 'r!' . 'grep -B 1 -E "^\s*let #" ~/.vimrc'
call cursor(1,1)
endfunction
What it does:
10new - open a new vim window with ten lines size
exe ... - execute a command and put in the window
call ... - go to the first line first column
You can execute this function by tipping in the normal mode
:call ShowMacros
You could additionally create a key mapping or a command to fasten the way to call the function:
:cnoremap sm call ShowMacros()<CR>
command! sm call ShowMacros()`
This is the original post where I wrote the function similar to the above.
The OP asked, "is there a way to attach some sort of documentation that would display with the macro to explain what it is for?"
I have found VI / VIM macros extremely obtuse to understand even a week after I've written them, so I heartily support the idea of documentation. I have a suggestion for that, in two parts.
First is the process of documenting the macro in your .vimrc. I've developed the following .vimrc comment format that helps me understand, a week or a year or more later, what a macro is supposed to be doing. E.g.:
"
"= GENERIC CLIPBOARD YANK <F2>y (Y for Yank)
"= Yank the entire contents of the file into the clipboard; quit without saving.
"
"define F2 followed by y to be:
"| Go to line 1.
"| | From there, into the * buffer (system clipboard),
"| | | yank to the end of the file.
"| | | | Go to sleep for 1 second (to allow the clipboard to be updated).
"| | | | | Quit without saving the file.
"| | | | | |
map #2y 1G"*yG1gs:q!<CR>
"-------"-"-"-"--"------
Second, I am imagining that Jakub's ShowMacros() function above could be modified to grep a specific set of Help lines for each macro that would be in the file along with the definition, much the way the above command-line breakdown is attached to the definition, that would provide the needed User Help.
I've flagged two lines above with "= at the beginning of each, so that they can become the User Help. Then Jakub's grep command would search for "^\"= ". Here's the command I used. I'm not sure if the -E for Extended Regular Expressions is needed and the -B 1 is a nice touch to include one line previous to a matching sequence, so here I have an explicitly empty comment line.
In my vimrc, I only needed one backslash, for the initial parsing of the definitions. Here's the line, replacing the one in Jakub's function definition above:
exe 'r!' . 'grep -B 1 -E "^\"= " ~/.vimrc'
Thanks to Jakub's hint, I now can generate help from my .vimrc in pretty much exactly the way the OP is asking for. I've been using vi since 1983, so I'm pretty stoked.
Thanks Jakub!
IHTH,
August