how to loop

Get help using and writing Nisus Writer Pro macros.
Post Reply
User avatar
Matze
Posts: 156
Joined: 2004-12-14 07:54:49
Location: Düsseldorf Germany
Contact:

how to loop

Post by Matze » 2015-07-09 21:33:13

Hi nise people.

I want to create a very simple macro that repeatedly finds some text and copies it.
Find @Text<(:?[^\t]*)>, 'E-i'
Kopieren

In NWC I would have started it with "loop" and ended it with "goto loop", when I remember correctly.
I did hope to find the solution in Macros Reference, but I don't get it.

Can please someone tell me, what I have to code?

Thanks and best regards, Matze

User avatar
phspaelti
Posts: 912
Joined: 2007-02-07 00:58:12
Location: Japan

Re: how to loop

Post by phspaelti » 2015-07-09 23:02:17

Hello Matze:
Matze wrote:In NWC I would have started it with "loop" and ended it with "goto loop", when I remember correctly.
Ahh… the "good" old days. Gotos are history.
Matze wrote:I did hope to find the solution in Macros Reference, but I don't get it.
It shouldn't be too hard. If you look in the table of contents, you would see a section under Control flow a section clearly labeled Loops (≈ page 7). There you would see that there are 4 types of loops: while, for … to, foreach … in and foreach … in range.

But let's leave that, and return to your question.
Matze wrote:I want to create a very simple macro that repeatedly finds some text and copies it.
Find @Text<(:?[^\t]*)>, 'E-i'
Kopieren

Can please someone tell me, what I have to code?
Assuming you really did want to code that you could do this:

Code: Select all

While Find @Text<(:?[^\t]*)>, 'E-i-W'
    Kopieren
end
Notice that I added a "-W" option to prevent the search from wrapping, otherwise you will have an endless loop!

But here's the thing. Why do you want to do this with a loop? Just do a Find all and copy once. Even NWC could do that!
philip

User avatar
phspaelti
Posts: 912
Joined: 2007-02-07 00:58:12
Location: Japan

Re: how to loop

Post by phspaelti » 2015-07-10 00:00:37

Part 2:

Maybe my earlier post answered all your questions, but I just have the feeling that maybe you wanted to do something else. If you really just wanted to copy all the find bits, you don't need a loop, in fact you don't need a macro. So maybe what you were really looking for is a way to do something to each found bit individually. As already mentioned you could use the while loop I just mentioned, but the truth is, this isn't really the best way to do things.
There is also another point: as you remember NWC, in NWC the clipboard was a really important part of writing macros. But in the current version of Nisus, we don't need to use the clipboard anymore.

So if you want to find all bits and do something to each bit, that is exactly what the foreach loop is for. For 90% (or maybe even 99%) of all loop tasks, I recommend using a foreach loop. This works like this.
When you do a Find All Nisus creates a non-contiguous (text) selection, that is, an array of individual text selections. The foreach loop allows you deal with arrays one piece at a time. It will know how many there are, and when to stop, etc.
To get the non-contiguous selection, we do need one more thing, the document object. You can get the document object with the following bit of code:

Code: Select all

$doc = Document.active
And with that we have what we need to make a loop. For your case that would look like this:

Code: Select all

$doc = Document.active
Find All @Text<(:?[^\t]*)>, 'E-i'
foreach $sel in $doc.textSelections
     … do stuff here …
end
Of course the (do stuff here) is where the action is. At that point you can do things to that one selected bit using the $sel variable. Since the $sel is a text selection. it will not only be able to tell you what the string content of the selected bit is, but also where in the file it is.

Finally one last point. If the (do stuff here) includes changing the text (adding or deleting) it is best to always work backwards. The reason is that Nisus deals with selections by counting characters, and if you change the file the number of characters will be off. If you work backwards, the ones you change will always be at the end, and so the ones you still have to deal with will still be in the same place. Anyhow to work backwards we just have to add the word reversed:

Code: Select all

$doc = Document.active
Find All @Text<(:?[^\t]*)>, 'E-i'
foreach $sel in reversed $doc.textSelections
     … do stuff here …
end
philip

User avatar
Matze
Posts: 156
Joined: 2004-12-14 07:54:49
Location: Düsseldorf Germany
Contact:

Re: how to loop

Post by Matze » 2015-07-10 01:02:08

Hi Philip and thanks a lot for your elaborate replies.

I did look up the table of contents and read the four loop entries – but I didn't understand them ;) too many unknown terms.

What I want (have) to do: there is a flash database, I work with in Safari. In each field I have to paste a certain textbit.
All the text I want to paste into the database is in an Excel-Sheet. I've copied it and pasted it into a nisus document and have got tab-spaced textbits.
So I now want to copy all those bits in a row and with "copy paste pro" I will have got all the textbits in loads of clipbaords.
I then will switch to my database and paste each textbit into the field it belongs to.

So "do stuff here" is not needed as far as I do the stuff in safari ;)

Best regards, Matze

User avatar
Matze
Posts: 156
Joined: 2004-12-14 07:54:49
Location: Düsseldorf Germany
Contact:

Re: how to loop

Post by Matze » 2015-07-10 01:14:43

I've tried this one:

While Find @Text<(:?[^\t]*)>, 'E-i-W'
Kopieren
end

It only copies the first bit. My Macbook Pro makes a disturbing sound while processing the macro.

Best Matze

User avatar
phspaelti
Posts: 912
Joined: 2007-02-07 00:58:12
Location: Japan

Re: how to loop

Post by phspaelti » 2015-07-10 17:38:13

Matze wrote:I've tried this one:

While Find @Text<(:?[^\t]*)>, 'E-i-W'
Kopieren
end

It only copies the first bit. My Macbook Pro makes a disturbing sound while processing the macro.
Yeah, the problem here is that you are using '[^\t]*' as your expression. The reality is that this expression is found everywhere, even when there is nothing, so the macro falls into an endless loop; at the end of the first selection it finds a stretch of 0 non-tab characters before the next tab. It never progresses from there.

You can change the expression to '[^\t]+' and then it will complete. But the truth is, I don't think you are going to get what you want. This macro will select each bit, and then copy it. Each copy instruction will overwrite the previous one, and when you finish you will have just the last one on the clipboard. According to your other comment you seem to be using some copy-widget ('Copy Paste Pro'). I don't have any experience with such things, but I assume it allows you to copy repeatedly to several clipboards. But this type of thing will work via the the GUI or something like that, and it will not happen during a macro. (Feel free to try it and let me know if I'm wrong.) Of course one could write a macro to copy things to multiple clipboards, but those would be Nisus clipboards, so it probably wouldn't help either.

The kind of thing you are trying to do isn't really what Nisus Macro Language is intended for. This would be one of those times to use Applescript. Applescript could copy all the bits at once and then paste them in one at a time in Safari.
philip

User avatar
Matze
Posts: 156
Joined: 2004-12-14 07:54:49
Location: Düsseldorf Germany
Contact:

Re: how to loop

Post by Matze » 2015-07-16 00:48:32

Dear Philip,

sorry for my late reply and thanks for the new expression. Indeed it doesn't work wit CPPro. It only copies the last bit of the text.

So an AppleScript would be the solution I guess. I am afraid I am as bad with AppleScript as I am with NisusWriter Pro Macros.
I'll try to find some AppleScripters out there who can help.

Best regards, Matze

Post Reply