• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

doScript (UndoModes) breaks InDesign's Undo (CS4)

People's Champ ,
Jun 04, 2009 Jun 04, 2009

Copy link to clipboard

Copied

I wrote a little script. To make sure that I can undo it all in one go, I used:

app.doScript(main, undefined, undefined, UndoModes.fastEntireScript,"My script");

Once the script completes, InDesign's regular undo is broken. It no longer undoes separate steps, but will only revert to the point before which the script has been run.

What can I add at the end of the script to return things to normal?

Thanks,

Ariel

TOPICS
Scripting

Views

10.6K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

LEGEND , Jun 04, 2009 Jun 04, 2009

If you use try/catch in your script, you should probably use

UndoModes.entireScript instead.

The reason is kind of complicated...

HTH,

Harbs

Votes

Translate

Translate
LEGEND ,
Jun 04, 2009 Jun 04, 2009

Copy link to clipboard

Copied

If you use try/catch in your script, you should probably use

UndoModes.entireScript instead.

The reason is kind of complicated...

HTH,

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
People's Champ ,
Jun 04, 2009 Jun 04, 2009

Copy link to clipboard

Copied

Well I'll be...

Amazing. That's done the trick.

Thank you!

Ariel

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 21, 2010 Sep 21, 2010

Copy link to clipboard

Copied

Harbs. wrote:

If you use try/catch in your script, you should probably use 

UndoModes.entireScript instead.

The reason is kind of complicated...

Hi Harbs,

I would love to have more details on that complicated reason. Can you tell me more?

[For performance purpose, one of my script needs the fastEntireScript mode, but I use a number of try...catch... So?]

Thanks!

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Sep 22, 2010 Sep 22, 2010

Copy link to clipboard

Copied

Very simple:

When you catch an error, InDesign rolls back to the last snapshot of the document state (to ensure the document is in a stable state).

What FAST_ENTIRE_SCRIPT does is that it does not take snapshots of the document while the script is running, so the last snapshot is at the start of the script (or in some extreme cases the before you enter certain functions, but I have not figured out how that works).

Therefore if you catch an error, the document state will roll back to the beginning of the script and continue from there. This undoes everything your script did until that point and very likely renders many of your variables invalid. This is not what you want 99% of the time...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Sep 22, 2010 Sep 22, 2010

Copy link to clipboard

Copied

Hmm...

First it was complicated and now it's simple...

I guess it depends on your frame of reference...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 22, 2010 Sep 22, 2010

Copy link to clipboard

Copied

Thanks Harbs. It's not that simple on my frame of reference 😉

I understand that a try...catch block needs a kind of "restoration point" which involves ID snapshot. So if there is no intermediate snapshot —due to the fastEntireScript mode— we have a problem. But is it supposed here that the app.doScript() call is embedded within a try...catch?

What I don't understand is the precondition of the "undo history bug" mentioned by Thomas Silkjær (http://indesigning.net/indesign-undo-history-ruined-by-doscript).

In other words, is it secure to use app.doScript(myProcess, ScriptLanguage.javascript, undefined, UndoModes.fastEntireScript) as the main statement of my script and to make the try...catch error management within myProcess?

Here is a test that doesn't seem to muddle the undo history up:

var main = function()
{
     var tf = app.activeDocument.textFrames[0];
     tf.contents = "foo bar";
     
     try{s.nonExistingProperty;}
     catch(_){}
}

app.doScript(
     main,
     ScriptLanguage.javascript,
     undefined,
     UndoModes.fastEntireScript
     );

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 02, 2010 Oct 02, 2010

Copy link to clipboard

Copied

Hi Marc,

Last week was a holiday for me...

I have no idea what Thomas's bug is. Would you care to elaborate?

Your script should end without the words "foo bar" in your text frame because it should revert to the beginning of your script. Are you seeing different results?

Hmm. I just tested, and it does not revert the way I said...

It's obviously not as simple as I thought. Maybe it depends on how intensive the script is?

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 02, 2010 Oct 02, 2010

Copy link to clipboard

Copied

I changed yourscript a bit, and it loses the changes:

var main = function()
{
     var tf = app.activeDocument.textFrames[0];
     tf.contents = "foo bar";
     var x;
     try{
     for(x in tf){
     var a=tf;
     }
     }catch(e){}
    
}

app.doScript(
     main,
     ScriptLanguage.javascript,
     undefined,
     UndoModes.fastEntireScript
     );


There appears to be some threshold where the scripting engine decides that it can't take snapshots...

I'd say that the safest path is to avoid FAST_ENTIRE_SCRIPT entirely when you use try-catch.

Also, I have found that FAST_ENTIRE_SCRIPT is much pickier about what is valid code. I have had more than one instance where I had code which executed fine in regular mode, but failed when run in FAST_ENTIRE_SCRIPT...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Oct 02, 2010 Oct 02, 2010

Copy link to clipboard

Copied

Hi Harbs,

Thanks a lot for your help. I'm really really not familiar with that 'Undo Modes' maze and I'm pretty sure I missed the obvious. My problem is in fact a paradox. I have a complete script which provides two main features —depending on what the user choose in a dialog:

(a) I need Feature_1 to be undoable, and the —safe— UndoModes.entireScript option is fine because it's not a huge process.

(b) However, Feature_2 is a time consuming function which is considerably slowed by the entireScript undo mode. I found that switching my global app.doScript() statement to fastEntireScript undo mode dramatically speeds up the process —as you explained, InDesign doesn't need to take intermediate snapshots during the script progress.

(c) But my script uses try-catch error management, including within Feature_2 code.

So I don't see any solution. I was wondering whether it's possible to embed an app.doScript(... UndoModes.fastEntireScript) statement within a block which is itself executed by app.doScript(... UndoModes.entireScript)... Crazy idea?

[Hope you had a good holiday.]

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 03, 2010 Oct 03, 2010

Copy link to clipboard

Copied

AFAIK, there's no solution other than going through the code and bending over backwards to remove all try/catch statements in you script.

I had a situation similar to yours, and I spent a week going through thousands of lines of code scattered over many, many functions in multiple files, removing any dependence on try/catch. It was a huge headache, and it took me about a week to do, but I did it...

There's very few situations where try/catch is REALLY necessary. It's usually possible to do a ridiculous amount of checking instead...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Oct 03, 2010 Oct 03, 2010

Copy link to clipboard

Copied

Harbs. wrote:

AFAIK, there's no solution other than going through the code and bending over backwards to remove all try/catch statements in you script.

(...)

Yeah, I knew you'd end up suggesting this solution 😉

But I really can't remove all try/catch, because my script is based on several included libraries that themselves use try-catch!

Bad news for me...

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 03, 2010 Oct 03, 2010

Copy link to clipboard

Copied

Marc Autret wrote:

[Hope you had a good holiday.]

Thanks. Yeah, it was great!

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advisor ,
Oct 03, 2010 Oct 03, 2010

Copy link to clipboard

Copied

Welcome back Harbs

--

tomaxxi

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Oct 20, 2010 Oct 20, 2010

Copy link to clipboard

Copied

I did go through my script and removed all try/catches. Unfortunately, I ran into the undo bug. What happens is after running a script with fastEntireScript if you do things in InDesign that both have the same "undo name" it will undo both when you press Ctrl+Z.

For example:

1) Run script that has a app.doScript() and is set to fastEntireScript.

2) Move a text frame

3) Move another text frame

4) Press Ctrl+Z, both steps 2&3 will become undone.

I had to go back to using entireScript .

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Oct 21, 2010 Oct 21, 2010

Copy link to clipboard

Copied

At this point, I think that only an Adobe developer may explain the internal mechanism of those tricky undo modes and how to prevent the undo bug. It would be really beneficial for scripters!

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Oct 21, 2010 Oct 21, 2010

Copy link to clipboard

Copied

I wonder if the bug is there in CS5, too?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Oct 21, 2010 Oct 21, 2010

Copy link to clipboard

Copied

Marc Autret wrote:

At this point, I think that only an Adobe developer may explain...

I asked Jonathan Brown if he has more to add to this and this was his response:

The undo modes feature involves a complicated interaction between the scripting architecture and the command processing architecture. In other words, it would take two Adobe developers to figure out what’s going on to a greater depth than has already been described.

So basically, (for better or for worse) the only way we might find out more is by trial and error.

If anyone can try to reproduce that undo bug with clear steps both in CS4 and CS5, you can either file the bug yourself, or I can do it through the Partner Portal. Chances are it has not been filed yet...

Harbs

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Oct 21, 2010 Oct 21, 2010

Copy link to clipboard

Copied

I tried it in CS4 on my laptop running Vista x86 and on my desktop running Vista x64 and I consistently have found the same bug. Even if the script that is called by doScript() is simply an alert it will ruin the undos when set to fastEntireScript.

However, in CS5 I have unable to produce it. Maybe it was fixed .

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Nov 17, 2010 Nov 17, 2010

Copy link to clipboard

Copied

Has anyone any idea how to fix the undo after the fastEntireScript broke it? I have some scripts which really need to use the fastEntireScript option for reasons of efficiency.

I've tried running a second script using a different option to see if it would restore functionality, but no joy as yet.

This is a real shame, as the option to 'suppress' Undo, or to at least put it all in one step, is something we've all wanted for a long time

Mike

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Nov 17, 2010 Nov 17, 2010

Copy link to clipboard

Copied

Changing from fastEntireScript to entireScript doesn't help for you?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Nov 17, 2010 Nov 17, 2010

Copy link to clipboard

Copied

Hi Fred

Yes, that gets around the problem; I was just trying to use FastEntireScript to squeeze the performce as tight as I could. Reckon I'll just have to make do for now

cheers

Mike

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 11, 2011 Feb 11, 2011

Copy link to clipboard

Copied

After further testing, it appears that the fastEntireScript undo mode always disturbs the InDesign history in CS4, regardless of error catching. I don't think that the try...catch block makes fastEntireScript unusable but that fastEntireScript itslef is faulty and makes try...catch unusable.

Run this innocent script in ID CS4:

var func1 = function(){/*noop*/};
app.doScript(
     func1,
     ScriptLanguage.javascript,
     undefined,
     UndoModes.fastEntireScript
     );

Once that's done InDesign sounds unable to restore the normal undo behavior until the next session. A simple test: create two text frames, move the first, move the 2nd, then call Edit / Undo. You see that several undo steps are made at once! And there is no way to get back to normal. The fastEntireScript undo mode causes a kind of offset error on the undo stack or something.

Then I tried different strategies to prevent ID from falling into Undo Hysteria after a fast-entire-script execution. The only solution I found is to enclose the fast-entire-script block within an entire-script block (other modes won't work). Like this:

var myLauncher = function()
     {
     alert('Undo mode:' + app.activeScriptUndoMode); // still in safe zone

     app.doScript(
          myFastFunc,
          undefined,
          undefined,
          UndoModes.fastEntireScript, // => dangerous zone
          "MyFastEntireScript");

     alert('Undo mode:' + app.activeScriptUndoMode); // safe zone restored
     };

var myFastFunc = function()
     {
     alert('Undo mode:' + app.activeScriptUndoMode); // dangerous zone
     // do something --but please avoid try...catch here
     };

app.doScript(
     myLauncher,
     ScriptLanguage.javascript,
     undefined,
     UndoModes.entireScript, // => safe zone
     "MyEntireScript");

If I rely on my tests InDesign returns to normal when the script terminates, i.e. you can undo actions one by one.

What I don't know is whether the fast-entire zone is actually 'fast'.

Also, it probably remains a very bad idea to allow try...catch within the fast zone.

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Aug 22, 2011 Aug 22, 2011

Copy link to clipboard

Copied

My attempt to summarize this discussion:

http://www.indiscripts.com/post/2011/08/notes-on-fastentirescript-undo-mode

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Aug 22, 2011 Aug 22, 2011

Copy link to clipboard

Copied

LATEST

That was an excellent write up. And the was a great find with the workaround! Wrapping the fastEntireScript and an entireScript was ingenius.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines