Running custom command makes destination lister the source

Environment: Check "Preferences / File Displays / Options / Single display Listers have source/destination modes".

When I run internal DOpus commands using dopusrt.exe (using voice commands, so without having to switch windows around to do that), these commands leave the active destination lister as the destination lister.

But as soon as I run a custom command that my JScript script add-in added - even if its first action is return; - the active destination lister becomes the source lister. I would expect that running a custom command behaves the same as an internal command in this regard.

I can't reproduce this unfortunately.

How is your custom command configured in the script?

What command line are you passing to dopusrt.exe ?

It also happens with this minimalized version of my script add-in:

function OnInit(initData) {
    initData.name = "TmpBugRepro Script Add-In";
    initData.version = "0.1";
    initData.desc = "The description.";
    initData.default_enable = true;
    initData.min_version = "13.0";
}

function OnAddCommands(addCmdData) {
    var cmd = addCmdData.AddCommand();
    cmd.name = "TmpBugRepro";
    cmd.method = "OnTmpBugRepro";
    cmd.desc = "The description.";
    cmd.label = cmd.name;
    cmd.hide = false;
    cmd.icon = "script";
}

function OnTmpBugRepro(scriptCmdData) {}

The command line is:

"C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe" /cmd:active,thisdesktop TmpBugRepro

But it also happens when typing >TmpBugRepro into the file display, while paying attention not to make the lister the source by other means. >Set NOOP lets it stay the destination.

Installing that script and running >TmpBugRepro from the lister does not change the source/destination here. I can't see anything in it which would do that either.

Running a user command TmpBugReproUserCommand (created using the customize-dialog) with either nothing inside it or just Set NOOP leaves the destination lister as the destination lister. So, no problem there.

I have the following XML elements in my prefs.oxc inside the top-level prefs element: colors, colors_dark, dblclk, fayt, fileop, filters, flags, foldertab_size, foldertab_size2, foldertab_size3, foldertab_size4, fonts, gridlines, jumplist, layout, lister_images, lister_images_dark, log, pathFields, recent, smartfav, smtp, status, thumbnails, thumbstretch, tiles, timing, toolbars, transanims, tree, viewer, viewpane, zip.

If you, @Leo and @Jon, or any other reader able or unable to reproduce the issue, would give your list of XML elements inside the prefs.oxc root element prefs, I could see which are different (when you can't reproduce the issue), or which are the same (when you can reproduce it). If this bug is caused by a preference, this would narrow down what preference changes to try.

Replace every occurrence of the following regex with nothing in a copy of your prefs.oxc to retrieve that list of elements:

^(?!\t<\w+\b|\w+\b).*\r?\n|^\t<(?=\w+\b)|[ >].*

Default path to prefs.oxc for pasting into address bar:

/dopusdata\ConfigFiles\prefs.oxc
1 Like

I can't reproduce it here, either, but the regex worked :+1:

fileop
flags
thumbstretch
timing
smtp
gridlines
status
tree
fonts
colors
colors_dark
viewpane
layout
dblclk
toolbars
log
lister_images
lister_images_dark
zip
thumbnails
tiles
recent
smartfav
viewer
foldertab_size
foldertab_size2
foldertab_size3
foldertab_size4
transanims
jumplist
filters
fayt
pathFields
1 Like

Thanks. Our elements with one indent are identical. But since it looks like not every preference of the huge preference dialog is contained in prefs.oxc, this approach may still be fruitful. Let's do the lines with two indents also. Again, replace every occurrence with nothing:

^(?!\t\t<\w+\b|\w+\b).*\r?\n|^\t\t<(?=\w+\b)|[ >].*

My element names with two indents are (sorted and deduped with VS Code command palette, which you don't have to do): actions, auto, auto_backup, bg_commands, code, command, dual, email, ext, fdb, fields, foldertabs, gridlines, hide, hideext, icon_command, icon_layout, initial_dual, layout, left, lister_title, log, max_threads, modes, mouse_hook_delay, name, named_color_bools, named_colors, named_dwords, pass, port, powermode, renamemacro, right, server, single, spacing_scheme, startup, std.filedisplay, std.foldertabs, std.foldertree, std.metapane, std.statusbar, std.toolbar, std.viewerpane, system_colors, system_colors_enabled, tab_new, text, tortoise_set, user, viewmodes, win_e_command, win_e_layout.

And while I'm at it, here's the regex for the elements with three indents:

^(?!\t\t\t<\w+\b|\w+\b).*\r?\n|^\t\t\t<(?=\w+\b)|[ >].*

My elements with three indents are: details, event, field, file, folder, frozen, lmb_alt, lmb_ctrl, lmb_normal, mmb_alt, mmb_ctrl, mmb_normal, mode, pathstring, pidl, power.

two indents

actions
auto
auto_backup
bg_commands
command
dual
email
ext
fields
gridlines
header
hide
hideext
icon_command
icon_layout
layout
left
lister_title
max_threads
modes
mouse_hook_delay
name
named_color_bools
named_colors
named_dwords
pass
port
powermode
presets
right
server
single
spacing_scheme
startup
std.filedisplay
std.foldertabs
std.foldertree
std.metapane
std.statusbar
std.toolbar
std.viewerpane
system_colors
system_colors_enabled
tab_dblclk
tab_new
text
tortoise_set
user
viewmodes
win_e_command
win_e_layout

three indents

details
event
field
file
folder
frozen
lmb_alt
lmb_ctrl
lmb_normal
mmb_ctrl
mmb_normal
mode
pathstring
power
preset
tree
1 Like

Thank you!

I looked at what I have that you don't have (not at what you have that I don't have).

With two indents, there are the elements findable via regex <(code|fdb|foldertabs|initial_dual|log|renamemacro)\b. Of those, <(code|fdb|foldertabs|log|renamemacro)\b were from element path prefs/fonts, so most probably irrelevant. The remaining element with path prefs/layout/initial_dual was removed when resetting the preference via dialog and didn't make a difference.

With three indents, the elements findable via regex <(mmb_alt|pidl)\b were what I had, but not you. Element path prefs/tree/actions/mmb_alt with a command (Go NEWTAB OPENINDUAL) inside it seems irrelevant. Element path prefs/layout/tab_new/pidl has a ?, followed by 36 characters of Base64 inside it. I don't know what it's for, but it looks irrelevant also, but I could be wrong.

BTW: Fully restarting DOpus doesn't make a difference. The problem persists. So, it's also not just some rare erroneous state it got into in a session.

I don't know if that's relevant, but, during development of the script add-in, I often used the function that's reachable via menu "Settings > Install Script..." to overwrite the previous installation without changing the version number. (If you try to reproduce, maybe change something insignificant like adding a space to make the file different.)

The XML nodes in prefs.oxc will be largely the same for everyone. They don't tell you what the configuration is. The data within the nodes is the configuration.

I've been able to reproduce this now; it happens because script commands by default are flagged as wanting both a source and destination path, and in that situation the command processor will swap the destination and source file displays around if a command is run against the destination.

(Same thing will happen with an internal command as long as it's one that uses both a source and destination, e.g. Copy).

We'll add a way to prevent this in the next beta, probably some flags when initialising script commands that let you tell it you don't want both a source and destination.

2 Likes

I have the generic command RunBareCommandFile, which runs the lines of the specified file using scriptCmdData.func.command. Wouldn't your solution mean that, without adding an additional command, I could only either keep the current bug or don't have the tab in scriptCmdData.func.command.desttab/scriptCmdData.func.desttab available in scripts? (scriptCmdData.func.sourcetab.lister.desttab isn't the same when a whole lister can be the destination, so a script also couldn't set it itself.)

It would be more desirable not having to specify per bare command file whether it needs a destination, because this is rather just an implementation detail. But if its unavoidable, it would be more desirable to be able to specify this on a subordinate level to a command, be it a RunBareCommandFile argument, using a double file extension of the bare command file, or using initial flag lines in the file itself. If this is not the most obvious way of solving this bug in the DOpus source code, would it be possible to defer the command processor potentially swapping around the destination and source file displays until the first Command is run (including the pre-filled one from scriptCmdData.func.command), i.e., doing this lazily? That way, the decision whether a destination is needed, can be done inside the command call handler, so I wouldn't be forced to implement different commands for it.

I'm not sure what you mean by "bare command file".

The way it works is the way it works, and it's worked this way long before we had commands added by scripts.

Some commands don't use either a source or destination, e.g. Help ABOUT.

Some commands only use a source, e.g. Select ALL.

Some commands use a source and destination, e.g. Copy.

The command itself defines what it uses/needs in terms of paths, and when it's run Opus checks those paths are available and sets the command up to use them.

All this change is doing is giving script commands the ability to define that too. But scripts, being scripts, will always be free to override and query what Listers/Tabs exist and choose which ones they target.

RunBareCommandFile runs files like .dcf files without the XML skeleton. They can have the extensions .std, .js, and .vbs, and contain bare code (i.e., no XML skeleton) just like in the Command Editor dialog. This done by manually building a Command from a bare command file.

Example of a bare command file example.js:

function OnClick(clickData) {
    DOpus.Output("Hello world!");
}

Since RunBareCommandFile can run scripts with varying needs (requiring destination or not), I was asking whether it's possible to solve this bug while avoiding forcing me to branch out RunBareCommandFile into two commands RunBareCommandFileWithSource and RunBareCommandFileWithSourceAndDest. If this would be possible for you, the script could state what it needs either through a double file extension like example.withdest.js, or through initial directives like that:

// Directive: provideDestination

function OnClick(clickData) {
    DOpus.Output("Hello world!");
}

RunBareCommandFile could then read that information and only send the destination into the Command when needed.

Of couse, RunBareCommandFile's implementation would then need a way to explicitly or implicitly cause/prevent the command processor actions you hinted at (that are the cause of this thread's bug). If you think of adding an option for custom commands that would be specified in OnAddCommands(), couldn't that option not just be a two-state, but a three-state option, allowing you to do the cause/prevent action on a case-by-case basis in the custom-command implementation?