Reply to topic  [ 10 posts ] 
undefined docpath 
Author Message

Joined: 2007-04-12 14:59:36
Posts: 229
I can‘t get to grips with a seemingly simple macro problem:
I want Nisus to check if a certain document myDoc is open, and if not, to open or to activate it. I wrote this:

Code:
$docPath =  "~/Documents/myDoc"
$actDoc = Document.active
$actDocPath = $actDoc.filePath
if $actDoc == undefined
   Document.open $docPath
elsif $actDocPath !=  $docPath
   Document.open $docPath
end


The problem is: This works well, if myDoc is not open, or if it is not active. But if no document at all is open Nisus complains that the filepath property requires an object, but get‘s „undefined“ . But that is just why I want to open it: that it is not undefined anymore.

BTW My if-construction is meant to say: (If A) OR (if B) then do C. Is there another way to this?


2015-09-21 09:21:46
Profile
Official Nisus Person
User avatar

Joined: 2002-07-11 17:14:10
Posts: 4251
Location: San Diego, CA
js wrote:
But if no document at all is open Nisus complains that the filepath property requires an object, but get‘s „undefined“ .

You see that error message because (as you say) there's no document open. Without a document object, you cannot access its "filePath" property.

The solution is to check if a document is open before trying to get its file path, eg:
Code:
$actDoc = Document.active
If $actDoc
   $actDocPath = $actDoc.filePath
   ...
End

You could omit the temporary path variable, resulting in a macro like this:
Code:
$docPath =  "~/Desktop/test.rtf"
$actDoc = Document.active
If ! $actDoc
   Document.open $docPath
ElseIf $actDoc.filePath != $docPath
   Document.open $docPath
End

Of course, as the (somewhat gruesome) saying goes, there's more than one way to skin a cat. Let's consider your other question:
Quote:
My if-construction is meant to say: (If A) OR (if B) then do C. Is there another way to this?

Hrm, I was going to say that you could do this, but there's a problem. While you can use an OR operator to include two conditions in a single "if" statement, you run into the same problem with the undefined Document object. For example, this works correctly:
Code:
$number = 999
If ($number < 1) || ($number > 100)
   Prompt "The number $number is not from 1-100."
End

However, in your case this does NOT work properly:
Code:
$docPath =  "~/Desktop/test.rtf"
$actDoc = Document.active
If (! $actDoc) || ($actDoc.filePath != $docPath) # FAILS: possible undefined object
   Document.open $docPath
End

The problem is that the || OR operator isn't doing something that's called short-circuit evaluation. This is a common feature of programming language's logical operators, where subsequent expressions are only evaluated as required based on the value of earlier expressions. I found the lack of this feature in the Nisus macro language somewhat surprising, but I see that the macro reference doesn't make any claims to support it. I'll have to file an enhancement.

If you really want a single code path (a good programming habit) for opening the desired document, you can do so if you contort your code a little:
Code:
$docPath =  "~/Desktop/test.rtf"
$actDoc = Document.active

$actDocPath = ""
If $actDoc
   $actDocPath = $actDoc.filePath
End

If $actDocPath != $docPath
   Document.open $docPath
End

I hope that helps.


2015-09-21 13:52:23
Profile WWW

Joined: 2007-04-12 14:59:36
Posts: 229
Thank you for the generous explanations. This works well for me.
Now I had sent only the first half of my macro. But unfortunately I find myself with quite a similar problem with it’s second half, which let's me stuck again. My original macro (with your help) is this:
Code:
$docPath =  "~/Documents/test.rtf"
$actDoc = Document.active
If ! $actDoc
   Document.open $docPath
ElseIf $actDoc.filePath != $docPath
   Document.open $docPath
End


That works fine. It continues like this:

Code:
$sel = $actDoc.textSelection
$parStyle = $sel.paragraphStyle
$parName = $parStyle.name
If $parName == "myPARNAME"
execute myCODE
end


The purpose of this part 2 of the macro is to check the front document just opened, and see if the insertion is in paragraph with the Style myPARNAME, in which case it should execute myCODE.
But if I start out with no document open the macro complains: „The 'textSelection' property requires an object, bot found 'undefined' from '$actDoc'.“ Why is that? Part 1 of the macro was meant to make sure that my document is open and in front? How can it be 'undefined'?


2015-09-22 11:05:22
Profile
User avatar

Joined: 2007-02-07 00:58:12
Posts: 876
Location: Japan
js wrote:
The purpose of this part 2 of the macro is to check the front document just opened, and see if the insertion is in paragraph with the Style myPARNAME, in which case it should execute myCODE.
But if I start out with no document open the macro complains: „The 'textSelection' property requires an object, bot found 'undefined' from '$actDoc'.“ Why is that? Part 1 of the macro was meant to make sure that my document is open and in front? How can it be 'undefined'?

Because you set $actDoc first, before you check anything. The way you have coded it $actDoc 'preserves' the status quo at the start of the macro, i.e., the document that was open when you ran the macro.

Looking at what you're trying to do I'm wondering why you're doing all this. It seems you want your macro to work with "~/Documents/test.rtf" no matter what document is open at the time (if any). If that is true, dispense with all the code Martin sent and just do:
Code:
$actDoc = Document.open "~/Documents/test.rtf"

This one line will:
  1. Guarantee that "~/Documents/test.rtf" is open
  2. Guarantee that "~/Documents/test.rtf" is frontmost and active
  3. Set $actDoc to "~/Documents/test.rtf"

If you also want to keep the previously active document (if any), just precede that one line with:
Code:
$previouslyActiveDoc = Document.active

But remember that this variable will possibly be 'undefined' so you will have to test it before use.

_________________
philip


2015-09-22 14:21:00
Profile

Joined: 2007-04-12 14:59:36
Posts: 229
Thank you. This sounds very convincing,and finally my complete macro works fine.


2015-09-23 00:41:27
Profile

Joined: 2007-04-12 14:59:36
Posts: 229
Hopefully not boring anybody with a supplementary question. Please consider this code:

Code:
$docPath =  "~/Documents/myFile"
$actDoc = Document.active
If ! $actDoc # if no file is active (open) at all ...
   Document.open $docPath # open myFile and exit
   exit
 elseIf $actDoc.filePath != $docPath  # if the active file is not myFile ...
   Document.open $docPath # open myFile and exit
   exit
end

prompt “Who cares for your code! I do what _I_ want!”


The first conditions checks if a file is active at all; the second if the active file is myFile.
In both cases I want the macro to open myFile and exit.

Now myFile is sure to be open and active. Therefore neither condition 1 nor condition 2 is true. Therefore running the macro again I should see the prompt, shouldn't I? But I don't.
Of course the ultimate goal is not to see the prompt, but to do something with my file, in case it is open and active. (But do nothing with it in case it had just to be opened or activated).


2015-09-23 02:28:14
Profile
User avatar

Joined: 2007-02-07 00:58:12
Posts: 876
Location: Japan
You can test what the problem is by using a prompt statement after the test to see what Nisus is testing:
Code:
elseIf $actDoc.filePath != $docPath 
    prompt $actDoc.filePath & ' != ' & $docPath 


If you do this, you will see that the problem is fairly trivial. $actDoc.filePath will be a full/expanded file path which starts with '/Users/…', while the $docPath is as written in the code. If you compare with $docPath.expandedFilePath instead, the code will work as you expected.

_________________
philip


2015-09-23 05:49:38
Profile

Joined: 2007-04-12 14:59:36
Posts: 229
Thank you. That works fine now.

Maybe I should add this: After reading your explanation and realizing my mistake, I thought instead of changing the code from '$docPath' into '$docPath.expandedFilePath', I could alternatively enter the full form of the path of myFile. This did not work. I think the reason is the new sandboxing environment. From the complaint of the macro it turned out that myDoc does not in "Users/documents/myDoc", but in "~/Library/Containers/com.nisus.NisusWriter/Data/" followed by "Users/documents/myDoc". The user does not know this, but the macro does, and complains. Pleas correct if I am wrong.


2015-09-23 08:47:36
Profile
User avatar

Joined: 2007-02-07 00:58:12
Posts: 876
Location: Japan
Actually '$docPath.expandedFilePath' worked fine for me, but it might depend on the actual location of the file. I don't think your problem has anything to do with sandboxing. It looks like some kind of alias issue.

In order to check if two file paths point to the same you might want to use the following command instead:
Code:
File.isEquivalentPaths path, otherPath

However the manual states:
Quote:
Some other path normalizations are handled, like removing empty path components, but this does not include resolving aliases or symlinks in the path

so this might still not work.

_________________
philip


2015-09-23 22:05:26
Profile
Official Nisus Person
User avatar

Joined: 2002-07-11 17:14:10
Posts: 4251
Location: San Diego, CA
js wrote:
I think the reason is the new sandboxing environment. From the complaint of the macro it turned out that myDoc does not in "Users/documents/myDoc", but in "~/Library/Containers/com.nisus.NisusWriter/Data/" followed by "Users/documents/myDoc".

That is actually a side effect of sandboxing. I'm not sure why, but when OSX grants NWP access to some file outside its sandbox (eg: a normal user document) the system creates those kind of "shadow" files in NWP's sandbox container. It's probably some implementation detail that lets OSX keep track of which files NWP should have access to.

In any case, Philip's suggestion to use "File.isEquivalentPaths" is the best way to compare paths. It should correctly handle situations like this where one path is inside the sandbox and another is outside, but both resolve to the same file on disk.


2015-09-30 10:49:37
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 10 posts ] 

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software