VectorScript Includes Management

From Vectorlab
Jump to: navigation, search

A method for organising include files. By Joel Sciamma

1st September, 2012


A brief introduction to include files

Over the years that I have used include files with my VectorScripts, I have tried various approaches to managing them as my needs became more complex but numerous problems always thwarted my efforts. This short article describes one solution that I have found to be successful.

Include files are segments of code, referenced by the main VectorScript but in a separate file, that are copied into the main script at the location referenced, when they are complied and run.

Pretty much anywhere in your script you can insert an include statement like this one:

{$INCLUDE MyHDName\FolderName\FolderName\MyInclude.px}

When the script is run, the code that is contained in the file named MyInclude.px will be copied from the file at the given location into the script, where it referenced, and executed as if it were part of the main script from the beginning.

Using includes is very handy for the following reasons:

1/. Reusing common subroutines that are used in more than one script

You can edit just the single instance of the subroutine in the include file and all the scripts that reference it will immediately respond to the change.

You get consistent behaviours for handling menus, processing lists etc. by making these routines common to all your scripts.

2/. Attaching libraries of common constants or deprecated functions held in an include file.

3/. Splitting a script into smaller pieces to make it more manageable or for staying below the maximum 32k allowed for the script size.

Putting big chunks of code such as dialog definitions into an include allows you to be editing two parts of your script at the same time and makes your main code block easier to read and understand.

If you do a lot of VectorScripting, there is one further benefit that saves a lot of time. If you set Vectorworks to recompile the script at every invocation, editing code in an include means that all you have to do is save the file and the changes will be applied immediately, saving a trip through the Plug-in Editor with copy and paste.

This suggests another trick which is to only write the bare bones of your code in the Plug-in Editor (description, constants, variables etc.) and call everything else from an include or just put everything in the include. Because the include can itself call other includes, you can still call your subroutines. Now you have a way to edit the majority of the code and see the effects just by saving the file and running the script.

Background to the problem of managing include files

So, this all looks terrific but there are some snags related to the referencing of includes, which are annoying.

That include statement at the beginning of the article looks harmless enough but it’s a booby trap waiting to snap shut.

Being a hard pathname from the disk down to the file means that if anything changes in that path, the script will fail with a file error and will not run. So changing any volume or folder name in the path or moving any folder or file will break your script. If you have a lot of scripts that might mean either never changing anything on your computer that affects the path or finding and replacing every include reference in every script should it change, which is neither realistic nor convenient.

So the first requirement of a system that manages includes is that no hard paths be used, or at least none that will create a headache.

As described in the Nemetschek Vectorworks Technical Note “Using Include Files with VectorScript”, Vectorworks will by default look for an include in the Plug-ins folder of your current user folder. This is the folder that is created by the application installer and is accessible through the Vectorworks preferences. Click the User Folders tab of the preferences window and click Reveal in Finder (Mac) or Explore (PC) to open the folder.

If your plug-in has been created in the Plug-ins folder by the VectorScript Plug-in Editor (PIE), then all you have to do to reference your include is insert a statement like this:

{$INCLUDE MyInclude.px}

Great! No hard path, so problem solved! Not quite. If your plug-ins are, quite sensibly, in a folder within the Plug-ins folder to keep them all together as your own area, this won't work.

What is not so clear from the documentation is that paths are relative to that of the plug-in file that references the include, not the Plug-ins folder. However, there is a syntactical solution which I will describe presently.

There is yet another issue that comes from me having an excessively tidy nature, because I like to keep all my code and anything related to it in one place that is not the Vectorworks user folder but part of my development environment. I don’t want to have to even think about synchronising my code between Vectorworks user folders…

To summarise, we need a system of managing code and include files that has the following properties:

1/. No hard paths that will easily break and a consistent method of referencing to make scripts maintainable and reusable.

2/. Quick to setup and rebuild as new versions of Vectorworks are released and your code files are reorganised.

3/. Keeps all files related to a script in one place which is not the Vectorworks user folder.

4/. Allows some flexibility for versioning files related to specific Vectorworks releases.

Fortunately, there are solutions that will allow this kind of system to be created.

One solution that works for me

Here is the diagram of the system I have evolved:

Includes for robustness diagram.png

Download the PDF (102kB) Diagram

On the left is one of the the Vectorworks user folders. I keep all versions of Vectorworks that will run on the current OS, so there are lots of these. I try as much as possible to keep my scripts compatible with versions back to VW2008 because some of my clients still use it.

I keep all my plug-ins in a folder (MyPlugIns on the diagram) within the Plug-ins folder and these are the files listed in the PIE. As there are hundreds of them, leaving them loose in the Plug-ins folder is not to be borne.

I keep aliases/shortcuts of all my includes for this release of Vectorworks in a second folder (MyIncludes01). There are nearly a hundred of these so there needs to be one place to put them.

On the right of the diagram is illustrated a section of my development environment showing a folder for my current release of scripts containing folders for each script in the suite. Inside each script folder is the file that gets copied into the PIE, any includes specific to this script (dialogs, file handling routines etc.) notes about the development of the script, URLs and aliases to other files or folders in my system that might be useful. I could select them all and open them in one go and have the full view of my efforts for this script ready to go.

To connect the include to the plug-in, you need to think of everything being related to the location of the plug-in.

If the include is at the same level as your plug-in, both of which are in folder within the Plug-ins folder, the include statement is like this:

{$INCLUDE \\File}

e.g. {$INCLUDE \\IncludeLibrary.vss}

This is useful for libraries accessed by all your scripts.

If the include is in a separate folder from your plug-ins and both folders are at the same level, the statement is:

{$INCLUDE ..\Folder\File}

e.g. {$INCLUDE ..\MyIncludes01\MyInclude01.px}

What this is saying is; tunnel out of the folder containing the plug-in, look for the folder MyIncludes01 at that same level and then look for a file named MyInclude01.px inside that and open it.

What the script will find is actually an alias that points to the real file somewhere else on the system where I want to keep it.

My previous attempts to alias entire folders so as not to have to alias the individual files were never robust, so I had to develop this approach instead.

Completing the circuit

Now we have a way of referencing include files in scripts which is consistent and easy to manage. We have plug-ins and includes tidily in folders in the Plug-ins folder and we have all our code in one place elsewhere in the file system for easy editing.

The last job is to populate the contents of our includes folder within the Plug-ins folder.

Spotlight on the Mac makes this very easy for us. (Apologies to PC users, I don’t know the OSs well enough to give the equivalent procedure).

Open the folder containing all the script folders and touch Cmd-F.

If not already the default, click the name of this folder in the Search bar to constrain the search to be within it.

Kind is ‘Any’.

Type the file suffix you use for your includes. For me this is “.px”

You now have a list of all the .px files in the folder, regardless of how deeply nested they are.

Select them all and drag them to the includes folder holding Cmd-Alt to create a list of aliases.

The system is ready to go.

When new versions of Vectorworks are released

When a new version of Vectorworks is installed, copy your plug-ins folder from the old version and create a new includes folder with the same name as before. Find your includes as described above and drop them into the new folder as aliases. It’s better not to copy the aliases from a previous version but recreate them from scratch.

If you find the new version of VectorScript has new functions that are incompatible with previous releases, create a new includes folder for these and reference them in your scripts. Match that structure on the code side to make it easier.

Copy any other libraries or development folders from the old version to the new, keeping the locations the same.

If the new release of Vectorworks has deprecated some of the functions that you use, you can add a library (like {$INCLUDE \\IncludeLibrary.vss} above) which contains snippets of your code that stand in for both the current version and the newly deprecated one. Your code calls only your own function that is abstracting the actual VS function or procedure and the library file in each VW user folder does the right thing for that release.

The library must always have the same name in each Plug-ins folder so that your scripts remain agnostic as to the version they are running under. You can add some text to the metadata for each file to distinguish them.

A discussion about handling deprecated functions will form the basis of another article.

Joel M. Sciamma, 2012