Rename order with numbering

I've noticed something fishy with the order of renaming.

I've created a button to handle renaming and versioning my .SQL files for deployment order. Basically, I name the file something meaningful, put an integer in front of its name, select as many as I want to rename, and then let the hell break loose with the button. It renames the file by adding a "wider" integer (usually in the thousands) to the front and then a few things more. The problem emerged when I had to handle many files and changed the default ordering to 1: Type ascending, 2: Extension ascending, and 3: Name descending. For some folders, there might be 4th and 5th order rules, for others only those 3. The first two don't do much as there are always only .SQL files there (or at least selected).

Now, applying the numbering rename preset to the selection obviously wouldn't work anymore as it would rename the files in the reverse order, meaning the file I'd like to deploy first would get deployed the last instead. Not good. So I created another button and changed its function from

@set start = {dlgstringS|Start numbering at|1001}
rename PRESET="Add numbering" NUMBER {$start}
// the "few things more" part removed for the sake of simplicity

to

@set start = {dlgstringS|Start numbering at|1001}
@confirm Reverse order
Set SORTREVERSE=Toggle
@confirm Apply Rename Preset
rename PRESET="Add numbering" NUMBER {$start}
@confirm Restore order
Set SORTREVERSE=Toggle

At first, it was without the @confirms, I added those later so that I could watch what is happening (definitely not what I expected). If I ran each step separately (eg. from Opus CLI or using separate buttons), the results were correct. But when running it as a single batch using a single button, the ordering of the rename did not change as it should.

So, after clicking the second button, the files are still renamed as if their order wasn't reversed before renaming.

I've checked the description for SORTREVERSE and it says:

Reverses the sort order in the current file display. If the list is only sorted by one column, the direction of that column sort is reversed. If multiple columns are selected for sorting, their directions are not altered but the overall result is reversed as the final step in the sorting.

And indeed, when running it step by step, seemingly the order stayed as it was, order indicator was still showing arrow 1 up on Type, arrow 2 up on Ext, and arrow 3 down on Name. According to SORTREVERSE description that made sense: it really didn't change the order, it only reversed the result, so I thought the new ordering was only temporary. Except when I used the first button on this supposedly temporary ordered set of files, it yielded the expected (or unexpected in this case) results of renaming the files in the correct order.

It seems that when I click the button, the order of files the Rename function is working with is the one that was in effect at the time of the button being clicked and not the order which was in effect when the Rename function was executed, that is, the Rename function completely disregards the preceding changes in the order of the files. Check this short video here.

  • Could you confirm this being the case here?
  • If it is, is it a bug or is it intentional?
  • If it's intentional, is there a way to achieve my goal using a single button with multiple commands instead of moving each command/function to a separate button and having to click them in a certain order (which makes it not-so-quick-at-all-anymore)?

Buttons take a snapshot of the file list before they start running. There are some commands which will cause the snapshot to be re-evaluated, but in general the order is already defined before any of the commands in the button are run.

Also, changing the sort-order/direction by command will ask the lister to re-order the files, but won't necessarily wait for that to finish.

Changing sort-order (and selection) is something that a command should do if you want to see the files in a different order (or selection), but not something that a command should rely on if it wants to change the order that a subsequent command in the same button goes through the file list (unless there's no alternative).

For doing that kind of thing, scripting is the better method. That gives you full control over which files commands act on, and in which order.

As a quick example, this will open the Rename dialog with the selected files and folders in reverse order to how they're currently displayed:

function OnClick(clickData)
{
	var cmd = clickData.func.command;
	cmd.deselect = false;

	if (clickData.func.sourcetab.selected.count == 0)
	{
		return;
	}

	var vecSelected = DOpus.Create.Vector(clickData.func.sourcetab.selected);
	var vecReversed = DOpus.Create.Vector();

	while(!vecSelected.empty)
	{
		vecReversed.push_back(vecSelected.back());
		vecSelected.pop_back();
	}

	cmd.ClearFiles();
	cmd.SetFiles(vecReversed);
	cmd.RunCommand("Rename");
}

If you change the last line to run your rename command, it should do what you need.

2 Likes

Thanks for your quick reply, @Leo.

This snapshot is killing me :slight_smile: I figure one of the commands that make the snapshot to be re-evaluated is the Rename command itself. I guess that's why several consecutive Rename commands can operate on the same fileset. Or more precisely, not the same, because they get renamed after each step, but the same selection.

The original button has the following commands:

@set start = {dlgstringS|Start numbering at|0101}
// Set SORTREVERSE=Toggle
@confirm Wait for reverse
rename PRESET="Add numbering" NUMBER {$start}
rename PRESET="Version, V, auto"
rename PRESET="Remove missing version number"
rename PRESET="Remove sorting number"
//Set SORTREVERSE=Toggle

And those work (well, except for producing the wrong order in case the name is sorted reverse in the first place). Unfortunately, that does not seem to work when in script. I replaced

cmd.RunCommand("Rename");

with

cmd.RunCommand("@set start = {dlgstringS|Start numbering at|1001}" );
cmd.RunCommand("rename PRESET="Add numbering" NUMBER {$start}");
cmd.RunCommand("rename PRESET="Version, V, auto" ");
cmd.RunCommand("rename PRESET="Remove missing version number" ");
cmd.RunCommand("rename PRESET="Remove sorting number" ");

and at first it seemed to work. It asked for the value of the start variable and even renamed the files accordingly. Alas, after the first rename being successful, the second one failed, stating that the file it wants to rename cannot be found and it displayed the original name of the file. I've tried tricking it by adding

cmd.SetFiles(DOpus.Create.Vector(clickData.func.sourcetab.selected));

in front of the second Rename command

cmd.RunCommand("@set start = {dlgstringS|Start numbering at|1001}" );
cmd.RunCommand("rename PRESET="Add numbering" NUMBER {$start}");
cmd.SetFiles(DOpus.Create.Vector(clickData.func.sourcetab.selected));
cmd.RunCommand("rename PRESET="Version, V, auto" ");

I thought it would re-fetch the current selection of files, but it either did not or the selection was not updated yet to produce a new list with the new names, because it still failed with the same error.

Use cmd.AddLine("...") to add all the lines to the cmd object, then cmd.Run() to execute them as a batch.

1 Like

That actually worked, thank you very much, @Leo! But why? What's the difference between doing it one step at a time and doing it as a batch in script?

The Command object is given a list of files.

It's also given a list of one or more commands to run on those files.

If you run a single command and it renames some of the files, the file list the Command object has is now out of date. But it won't change; it's still the list you gave it, and it's still the file list that will be used if you run another command separately. (You could rebuilt the list, but it'd be a pain to work out where all the files had gone.)

On the other hand, if you run multiple commands at once as a batch, that is handled specially. The batch itself makes a copy of the file list and updates it when the Rename command is run, so that chaining multiple rename commands together works. But that copy of the file list doesn't change what's in the Command object; that stays the way you set it up, until you explicitly ask it to change. (As an example, you might want to rename a file to *.bak, then put another file in its place, then run something against the file which is now in the original's place.)

2 Likes

Awesome! It's also great having someone able and willing to explain the details! Thank you very much again, @Leo!

Have a nice day (or night or whatever it is where you are :wink: )!

2 Likes