Page 2 of 2

Re: Help with a reference to regex group

Posted: 12 Dec 2019 12:36
by John_C
Thanks a lot. This is what I have created:

Code: Select all

::foreach($item, <clipboard>, <crlf>, 'e') {
    $i = 1;
    $filename = regexmatches($item, '[^\\]+$');
    $itemwithnewpath = <curpath> . '\' . $filename; // it is assumed that the script is launched on Ctrl-V
    while (true) {
        if exists($itemwithnewpath) {
            $i++;
            $item = regexreplace($item, '#\d+') . '#' . format($i, '0');
        } else {
            copyas $item, <curpath>;
            break;
        }
    }
}
I believe the code it terrible, but I already spent about 8 hours trying to write something that should work. In addition that it is terrible, it simply doesn't work: XY says that there is nothing to copy or it can't be copied.

Re: Help with a reference to regex group

Posted: 12 Dec 2019 13:06
by highend
Before you reach the while loop, your $itemwithnewpath doesn't even contain the affix.
So what's the use of testing for existence of that item? Ofc it (should) exist, you've copied it to the clipboard before...

And inside the while loop in the exists() clause you're working with $item =
You are checking for $itemwithnewpath, so you need to assign it to that variable as well, not to $item

E.g. in the else case you don't even use the [itemlist] parameter for copyas (which is $item (without the path) here!)
In your case it would copy the selected items! Even multiple ones...

The most important commands when developing a .xys script are:

Code: Select all

step:
unstep;
and for (if you use it): https://docs.microsoft.com/en-us/sysinternals/downloads/debugview
sysdebug;
So step through the script, eliminate each logic error (and there are plenty, sorry)...

Ofc I have a working version of what you are trying to do. But the things you profit the most from is: The errors you make on your own.
When you've finished this script I'll post mine as a reference (mine should work with all kind of affixes, while you're trying to make it to work only with the one you're currently using). No, this is not some kind of punishment! You're trying and trust me, you'll get a lot better at scripting when you're able to solve this little puzzle...

Re: Help with a reference to regex group

Posted: 13 Dec 2019 06:52
by John_C
I came up to the following,

Code: Select all

::foreach($item, <clipboard>, <crlf>, 'e') {
    $i = 1;
    while (true) {
        $filename = regexmatches($item, '[^\\]+$');
        $itemwithnewpath = <curpath> . '\' . $filename;
        if exists($itemwithnewpath) {
            $i++;
            $itemwithnewpath = regexreplace($item, '#\d+') . '#' . format($i, '0');
            msg $itemwithnewpath;
        } else {
            copyas $filename, <curpath>, $item;
            break;
        }
    }
}
and tried to fix it for a long time in different ways, but have not succeeded yet.

Re: Help with a reference to regex group

Posted: 13 Dec 2019 07:26
by highend
Does your second $itemwithnewpath = regexreplace($item, '#\d+') . '#' . format($i, '0'); assignment
lead to the expected name of the file? You're capturing at least one up to unlimited digits. Which sense does it make when you format it back to a single number (a 02 in the affix would be trimmed down to a 2 here), when you don't count the length of the digits you've captured?

Your first assignment for $itemwithnewpath = doesn't even contain an affix. So how should a
regexreplace() for #<some digits> work if there is no #<some digits>?

Without the $exts = <grab everything after the first dot> like in the former scripts, you won't
get the correct name...

viewtopic.php?p=175102#p175102
layed out the logic to do this kind of stuff, even with the necessary commands...

Re: Help with a reference to regex group

Posted: 13 Dec 2019 08:40
by highend
I'm not around till sunday afternoon, so:

Code: Select all

::$affix = getkey('PostfixNum', 'General');
    foreach($item, <clp>, <crlf>, 'e') {
        // Get the digit(s) from the used affix
        $cntNumAffix = regexmatches($affix, '\d+');

        // How many digits do we have? (e.g. 2 in " [01]")
        $lenNumAffix = strlen($cntNumAffix);

        // Base file (everything up to but not including the first dot)
        $baseFile = regexmatches(gpc($item, 'file'), '^[^.]+');

        // Keep everything after the first dot
        $exts = regexreplace($item, '^[^.]+\.?');

        // Generate destination file name (without path!)
        $dstFile = $baseFile . $affix . '.' . $exts;

        while (true) {
            // If the destination file does NOT exist
            if (exists(<curpath> . '\' . $dstFile) != 1) {
                copyas $dstFile, , $item;
                break;
            }

            // Destination file DOES already exist
            // Increase the digits of the affix by one
            $cntNumAffix++;

            // Create the new, formatted affix number
            $incAffix = format($cntNumAffix, strrepeat('0', $lenNumAffix));

            // Replace the digits with the incremented one(s)
            $affix = regexreplace($affix, '\d+', $incAffix);

            // This is the new (counted up) destination file name (again, no path!)
            $dstFile = $baseFile . $affix . '.' . $exts;
        }
    }

/*
Testdata:
Base file name: "file.user.js"
Used affix    : " [01]"
    file.user.js => file [01].user.js
    file.user.js => file [02].user.js
    file.user.js => file [03].user.js

Used affix    : "#2"
    file.user.js => file#2.user.js
    file.user.js => file#3.user.js
    file.user.js => file#4.user.js

The script will fill holes if they exist.
    file#2.user.js
    file#4.user.js

On the next run "file#3.user.js" would be created.
*/

Re: Help with a reference to regex group

Posted: 15 Dec 2019 07:43
by John_C
Highend, thanks a lot, again. I'm sure that I couldn't do this on my own.

I have made the following changes:

1. When you copy the file to the directory that doesn't have the file with such the name - the file is copied without the affix.

2. Now you can copy files without extensions (e.g. README) and directories.

To make it work for files without extensions and for directories, it was necessary (besides other changes, of course) to change != 1 to == 0 (actually, to == False, just a matter of personal style, I suppose). I'm wondering for what reason you decided to use != instead.

There are two issues that I don't understand how to fix:

1. When you copy the file to the directory that already have the file with the such name - the file is simply copied instead of asking the user.

2. When you copy multiple files, the copy window is created/closed for each file separately.

I have tried to fix the second issue in the following way: a) inside the foreach loop, instead of copying, create a string, b) perform the copying based on this string after the loop. But I have not succeeded with it and not sure that it possible at all. These attempts are not reflected in the version that I post below.

Of course, I don't expect that you should expend your own time with further improvements. It's a user forum, not a paid coding service.

Code: Select all

$affix = getkey('PostfixNum', 'General');

foreach($item, <clp>, <crlf>, 'e') {
    // Get the digit(s) from the used affix
    $cntNumAffix = regexmatches($affix, '\d+');

    // How many digits do we have? (e.g. 2 in '01')
    $lenNumAffix = strlen($cntNumAffix);

    // Base file (everything up to but not including the first dot)
    $baseFile = regexmatches(gpc($item, 'file'), '^[^.]+');

    // Keep everything after the first dot
    $exts = regexreplace($item, '^[^.]+\.?');

    // Generate destination file name (without path!)
    if ($exts != '') {
        //msg 1;
        $dstFile1 = $baseFile . '.' . $exts;
        $dstFile2 = $baseFile . '.' . $exts . $affix . '.' . regexreplace($exts, '^.+(#\d+|@[\d-]+)\.');
    } else {
        //msg 2;
        $dstFile1 = $baseFile;
        $dstFile2 = $baseFile . $affix;
    }

    while (true) {
        // If the destination file does NOT exist
        if (exists(<curpath> . '\' . $dstFile1) == False) {
            if ($exts != '') {
                //msg 3;
                copyas $baseFile . '.' . $exts,, $item;
            } else {
                //msg 4;
                copyas $baseFile,, $item;
            }
            break;
        }
        if (exists(<curpath> . '\' . $dstFile2) == False) {
            if ($exts != '') {
                //msg 5;
                copyas $baseFile . '.' . $exts . $affix . '.' . regexreplace($exts, '^.+(#\d+|@[\d-]+)\.'),, $item;
            } else {
                //msg 6;
                copyas $baseFile . $affix,, $item;
            }
            break;
        }

        // Destination file DOES already exist
        // Increase the digits of the affix by one
        $cntNumAffix++;

        // Create the new, formatted affix number
        $incAffix = format($cntNumAffix, strrepeat('0', $lenNumAffix));

        // Replace the digits with the incremented one(s)
        $affix = regexreplace($affix, '\d+', $incAffix);

        // This is the new (counted up) destination file name (again, no path!)
        $dstFile2 = $baseFile . '.' . $exts . $affix . '.' . regexreplace($exts, '^.+(#\d+|@[\d-]+)\.');
    }
}
Tested with:

Code: Select all

Increment affix: #2
Date affix: @<date yyyy-mm-dd-hh-nn>