Define and Edit a Map in Command Script

I have been adapting a button script ([url]"Move to Server" Button Script]) that I wrote in VBScript into an add-on command using JavaScript instead (mainly so I could learn it).

I have used tbone's 'Demo.Generic: ConfigHelper' to set-up the configuration options for the Preferences/Scripts section. These options had to be modified within the script previously.

I initially set up a vector (until I realised I couldn't use a vector for what I wanted). After a bit of trial and error, I found that I could set up a Map object in the configuration section.

The Map object works great in the script with pre-configured 'key,value' pairs, but I have found that I am unable to edit the Map elements from within the configuration option in the preferences/scripts. I double-click the FileStem entry and the Configuration Editor window opens up but it is empty. If I add anything to it, it breaks my script (see below).

This is the portion of the code I am using that creates the Map configuration entry (and the script works fine with this line):

cfg.add("FileStem", DOpus.NewMap("cal","Calibre\\","ccs","CCleaner\\","cdb","CDBXP\\","DOp","DOpus\\V11\\","Dro","Dropbox\\","Med","MediaMonkey\\","Goo","GoodSync\\V9\\","iTu","Apple\\","Tea","TeamViewer\\"),"Define the 1st 3 (or keyLength value) unique chars of file name and matching folder.");

This what I see in preferences:


I have also tried defining an empty Map in the configuration line above and then entering the elements via the preferences/scripts/.../configuration editor - although I'm not sure of the correct format for the 'key,value' pair (I tried '"key,value", '"key","value"', both with and without opening and closing brackets '()'. When I do this, the script produces an error saying that '...method is not supported in line..." which is where the I use this bit of code:

    [code]selStem = desFile.slice(0,Script.config.keyLength); // get 1st 3 (or whatever keyLength is set to) chars of selected file name

if (Script.config.FileStem.exists(selStem)) // script breaks here with an empty Map in configuration section[/code]
Is this a 'bug' or am I not able to add/delete/edit the Map elements from the configuration editor? Obviously if anyone else wanted to use my script then they would need to add their own elements to the map object.

I hope that all makes sense.

The ScriptConfig object doesn't support Maps as a value type. See the docs for the full list of supported types.

Hi Rebel.. o)

You could do the scriptconfig item like this (using a vector, seperating search-string and target folder by ":"):

cfg.add("FileStems", DOpus.NewVector()). des("Define the 1st 3 (or keyLength value) unique chars of file name and matching folder."). val("cal:Calibre\\","cdb","CDBXP\\"). val("ccs:CCleaner'). val("cdb:CDBXP\\"); //etc.

And in the script:

var fileStems = Script.config["FileStems"];
for(var c=0;c<fileStems.length;c++){
    if (fileStems(c).substring(0,2)=="//") continue; //just to be able to temporarily disable single pairs
    var parts = fileStems(c).split(":"); //I suggested ":" as split-character, because it should never be part of a file or foldername
    DOpus.Output("Chars: " + parts[0] + "Folder: " + parts[1]);
}

A quick suggestion to your script:
Use regular expressions instead of a fixed width of characters to match against filenames.
RegExps also allow to be more flexible, allowing multiple strings, various lengths - and if used correctly - should be more save while looking for a perfect match.

To sort the dopus installation exe, following examples would be possible to really make sure to hit a dopus installation file:
"DOpusInstall.exe", "DOpus\V11\" - fullfilename, because there's no fixed number of chars compared
"^DOp.*exe$", "DOpus\V11\" - a file starting with "DOp" ending with "exe"
"^DOpusInstall(64)?.exe$", "DOpus\V11\" - matches only "DOpusInstall.exe" and "DOpusInstall64.exe" (32 and 64 bit versions)

cya! o)

@jon, as I said, I was working with trial and error and was surprised that the config line worked as entered. It was only when I tried to modify it from with the preferences dialogs that I ran into trouble. As you hinted, a check of the docs would have put me right.

@tbone, thanks for your tips and suggestions. I'll certainly look at the vector suggestion and as for the regex suggestion, I don't really need to search for any particular file name as I actually select each downloaded file (and the names don't change other than a version number for some) and then click a button to move them. The one thing I do search for - either in the file name of within the file properties - is a file version number and the regex I already use for that seems to work OK.

Your'e welcome. o)
I for one, could make good use of something, that allows me to select files or folders and copy/move them to pre-defined locations if a regex matches their name and/or path.
Isn't that exactly what your script is about (despite the adding of a version string).

I still see no reason why you would use a fixed number of chars to find the matching pair (filename/target folder), but maybe I do not fully understand yet what your script does.

Yes, that is what my script does - it moves or copies files (not folders at the moment) to predefined locations. I use it on download installation/updates files for programs that I use (DOpus, Calibre etc) to move them from my Downloads folder to predefined locations on my server for backup purposes. I tend to keep 2 or 3 previous releases/updates just in case of issues with the latest release - hence the use of version numbers.

I wrote the script (initially as a rename and now a command script) to fulfil my needs as well as improving my scripting skills. It was also tedious having to navigate to each individual folder in turn when I needed to move the files - even with using DOpus Favourites etc.

Going back to your suggestions, I managed to break out the pairs of file stems and folders so thank you again for showing me how. I'm still working on getting a match between the pairs and the selected files but I'm sure I'll get there.

I will look at using regex although I'm struggling to visualise how regex could be used to identify a particular named file or folder. Using the example you gave in your earlier post:

[quote]To sort the dopus installation exe, following examples would be possible to really make sure to hit a dopus installation file:
"DOpusInstall.exe", "DOpus\V11\" - fullfilename, because there's no fixed number of chars compared
"^DOp.*exe$", "DOpus\V11\" - a file starting with "DOp" ending with "exe"
"^DOpusInstall(64)?.exe$", "DOpus\V11\" - matches only "DOpusInstall.exe" and "DOpusInstall64.exe" (32 and 64 bit versions).[/quote]
Surely that is not much different to what I am doing as you still need to match the actual file name to a particular folder and would therefore still need to spell out the individual files and folders. This certainly applies with my usage where I am only dealing with one file of each particular program (which rarely changes other than the version number included in the file name for some) but thinking about it, I can see how you could use regex to move similarly named files like images. I'll take a look and see what I can figure out (unless you beat me to it :slight_smile: ).

Thanks again for your interest and comments.

Yes, it would not make a difference to you and how you use that script, I agree.

Yep, my point was just about making your script a bit more versatile. With regex you'd also get rid of some script configurations (number of chars e.g.).

I guess you'd need a for loop which iterates over the selected items and nested within, another for loop iterating over the pairs.
And then it's probably something like this, to match the file part(s) against the selected item:

if (String(selectedItem.name).match( filePart )) DOpus.NewCommand.Runcommand('Copy FILE="'+selectedItem.realpath+'" TO="'+folderPart+'"');
filePart and folderPart represent a pair splitted by ":". Writing this, using ":::" as splitting character in the config probably is even better, when thinking about evaluating paths and system-folders as well. Maybe your pair should be a triplet then, so path and filename can be given separatly, the path can be empty/omitted if not necessary. Just an idea, of course I cannot force you to create something, that meets more of my requirements than yours. o)

Again, thanks for your comments tbone. You are more than welcome to use my script as a basis for something that suits your own needs better.

I've actually got my script working the way I want it to. It takes the selected files and moves them to either a predefined folder or asks for a destination folder in a predefined root directory. Optionally, the script will determine the version number and if not found will ask the user to provide one (or not use one if the dialog is cancelled) - in my original button script, this wasn't a configuration option but is now.

I will publish my script shortly once I've tidied the code etc.

Please consider using the scriptwizard add-in and its "Prepare Upload" functionality before uploading your script, find it here: Command: ScriptWizard (multipurpose scripting resources aid)
Your script will support updating, a multipurpose about dialog (ScriptAbout (About Dialog helper for script add-ins)) and the whole process of uploading is streamlined.
It's easy to do: Install the add-in and the provided button, select your script and choose "Prepare Upload".

Ok, I kind of like the swiss knifes approach for scripts and add-ins, but I understand your position, no problem - I'll be back for the next script of yours! o))
Have a nice weekend. o)

Already have done :smiley:

[quote]Ok, I kind of like the swiss knifes approach for scripts and add-ins, but I understand your position, no problem - I'll be back for the next script of yours! o))
Have a nice weekend. o)[/quote]
Might be a while before I come up with another one as I cannot think of a suitable 'topic' at the moment. I keep looking at the scripts of others (especially yours) for ideas and inspiration but nothing happening yet. My current script was born out of a personal need.