GP SoftwareTwitter
Opus FAQsManualCommandsObjects

Multiline or JSON ScriptConfig type

#1

There are a few scrips that require config that is too complex for a string and often stored at the top of the script as a JSON object.

It would be nice to have a ScriptConfig that could allow multiple line strings or JSON objects (with some syntax highlighting and pretty printed) to be entered in the UI.

#2

You can have multiple line strings already. I'm not sure what a JSON object is :slight_smile:

#3

Do you have a code sample of how to have a multiple line string. I couldn't figure it out.

If there was a JSON ScriptConfig type, storing the value as a string would be fine, as we can use the parse method to convert it to jscript object. The JSON type would allow the UI to pretty print and validate the structure.

This is the kind of text I would like have as a config value.

{ //Configuration for different patterns columns: [{ name:"pid", re: /\[(PID_\d*)]/ }, { name:"Numeric Id", re: /\[(\d*)\]/ }] }

#4

Hi Wowbagger,

you could see a sample of the multi line string config option within the Play music albums when their folders are double-clicked from Leo.

But Probably this would not help for your Idea regarding the config of the custom columns, because you need the information in the init function, but you don't have access to the config in the init, only in the command or column functions.

Bye,

Miran

#5

Possible workaround:
I remember there's an OnAbout() event for scripts? One could probably use that to open a dialog with a multiline element and save to a config-file what was entered there. Not very nice, but could work for those urgent cases. Are there urgent cases in a filemanager, not sure though. o)

#6

Maybe there's a case for the config to be available in OnInit?
Or we could have another optional event (e.g. OnAddCommands, OnAddColumns) where you could add commands or columns with access to the configuration.

Thoughts?

#7

[quote="jon"]Maybe there's a case for the config to be available in OnInit?
Or we could have another optional event (e.g. OnAddCommands, OnAddColumns) where you could add commands or columns with access to the configuration.

Thoughts?[/quote]

There surely are usecases where it would be helpfull to have the current configuration available during init, eg the reason why wowbagger asked for the multiline config and why I came accross the problem Custom Column - Custom Text.
To configure the actual columns and initiate them afterwards the access to the current config during init is required.

But just access to the config would probably not solve it. As far as I understood the init is only run once (during DOpus start or Change of Scriptcode/file) this would lead to possible intransparent behaviour for the user. Because some config is applied directly (when referenzed in the actual commands or columns) and others are not (that influenze the init and are only applied after restart of dopus or change of script)

Maybe a Scenario could be to have the commands "AddColumn" and "AddCommand" available in acutal scripts not only within the initObject, together with the Event "OnConfigchanged" we could verify and reinitialise everything. Important to keep in mind is only the garbage collection eg. removing columns that are removed from config....

#8

[quote="tbone"]Possible workaround:
I remember there's an OnAbout() event for scripts? One could probably use that to open a dialog with a multiline element and save to a config-file what was entered there. Not very nice, but could work for those urgent cases. Are there urgent cases in a filemanager, not sure though. o)[/quote]

I thought about a separate config file, but haven't tried to implement it, because of possible further problems. Where to keep the file, Write Access to the file? How to reinitialise the script after change of config file etc.

#9

[quote="jon"]Maybe there's a case for the config to be available in OnInit?
Or we could have another optional event (e.g. OnAddCommands, OnAddColumns) where you could add commands or columns with access to the configuration.

Thoughts?[/quote]
Adding a new optional event that are called after onInit and had access to the config would work well. Perhaps something more generic would be enough onPostInit or onSetUp allowing the script add columns or commands as needed. Could this/these new methods be run after onInit as well as after the script config had been updated and saved? That will solve the issue Miran raised, of things becoming out of sync.

Some scripts that use a JSON style internal config.
These ones need access to the config during the setup. These would need the new event to function correctly, if the config was editable by the user.
Custom Column - Custom Text V1.2
Custom Column - Example custom sort

These ones only use the config when public functions are called. Don't need a new event to work.
External Compare and Merge Tools v1.4
Tab-Labelizer - Extend the folder names shown in your tabs

Any thoughts on the UI for editing this type of config? The multi line string seems to me to be a way of creating an array of string, not a single multi line sting.

#10

It's easy enough to turn an array into a single string, just loop through and add them together.

#11

I Agree. The ExtendedExif columns and the columns I uploaded today to allow for custom grouping of filesizes would benefit from a post-init event, just something that fires right after the Script config is accessible and probably before any column/command is - or can be - added.

The ExtendedExif columns need to be configured in the code because of that and cannot be altered by the scripts config GUI.
Watch screenie: Columns: Extended EXIF (Picasa faces e.g.)
The CustomGrouping columns would need to access groupnames, stored in the scripts config to allow for setting the group_order property properly o). I got around it by adding numbers in front of them, to let the alphabetical default-order kick in, but that leads to a cluttered look in the grouping area of the file display.
Watch screenie: Columns: CustomGrouping (group by SizeRange/FileTypeGroup..)

Thanks for reading! o)

#12

Can you not have a global variable, set to False initially, and a function that you call which checks if its' false, does whatever extra init you need if it is, and sets it to true? You can then call the function before anything that needs the extra init.

#13

I think no, that wouldn't help, let me have another try to explain my view on this.

The first thing is, we cannot access Script.config.MyColumnName at the time AddColumn() is called in OnInit().
We can access the default value in onInitData.config.MyColumnName, but that's of no valuable use, because it could have been changed in the scripts config section. So in case we want to create a dynamic number of columns, column group_orders or commands, based on what the user put into the scripts config, there's no way right now. That leaves us with putting the configuration in the code, which puts unexperienced people off I guess.

The second thing is, after a scripts config has been changed, there is no event to react on that. So even if we had addressed the first issue and can access ready to use script config items to setup columns and commands dynamically, there's still the need for some re-initialization (event preferred I think) for the whole script, to get the existing columns/commands removed and re-added with the altered configuration.

Personally I don't mind messing with script code, but you gave us script config and we just like to make real heavy use of it! o)

#14

Ah ok, that makes sense. Seems like what Jon was suggesting above would cover that.

#15

The next update will address these issues.

#16

Yabba Dabba Doo! Congratulations to another awesome update, incorporating dozens of awesome fixes and enhancements! Thank you, this will really keep us busy trying the new things! o)

#17

Dopus V11.7 has multiline config. Thanks for the update.

I was playing with this today when updating the Tab-Labelizer. I wanted to share my solution.

The Tab-Labelizer has some advanced config that is stored in script as a JSON object. Its to complex to put in to other config types. I wanted to allow the user to edit that confict without opening the script. I also wanted it to look nice, and not to have to store the default config in a string literal as that would require escaping values and make it hard to read.

This is the pattern I used (A cut down version of the code):

function OnInit(data) {
  data.name = "test multiline script";
  data.desc = "Display advanced JSON config in a multi line config.";
  data.default_enable = true;
  data.min_version = "11.7"

  data.config_desc = DOpus.NewMap();
  
  //Set ExtendedConfig default to be defaultExtendedConfig pretty printed.
  data.config.ExtendedConfig = JSON.stringify(defaultExtendedConfig, undefined, 2).replace(/(\n)+/g,"\r\n");
  data.config_desc("ExtendedConfig") = "Extended configuration, Be careful editing";  
}
 
//Default values for extendedConfig
var defaultExtendedConfig = {
  value1: true,
  value2: "test",
  AGroupOfSettings: {
    enabled: true,
    alist: [
        "value1",
        "value2",
        "value3"
    ]
  },
}

function OnMyCustomFunction(data) {
  var extendedConfig = JSON.parse(Script.config.ExtendedConfig);
  // Do stuff
}

Keen to hear any feedback, specifically regarding performance issues. I have a couple of other scripts that could use a similar set-up.

Issue with Var: Object turns into Unknown
#18

My mindset on this is, that now we have descriptions for config items and OnConfigChange(), putting JSON configurations into the script config section should be used only for dynamically adding things like columns and callback handlers eg. For static configurations, I see no direct advantage in putting them into a JSON string anymore. But as said, situations remain where you can still make proper use of that, to not force anybody to alter scripts directly.

For JSON or regex configs in multiline strings, we also need to remember to make sure, no parsing errors break the whole script. So adding a requester in OnConfigChange() if there is invalid/unparsable content probably is a good idea. Some try/catch blocks around the critical sections should do the trick.