#31 2009-03-11 22:00

krtek
Senior Member
From: Łódź (Poland)
Registered: 2008-02-21
Posts: 262

Re: ReNamer: Making of new manual

WARNING
With PascalScript you can achieve more than only renaming files. You can change a datestamp of the file (with SetFileTimeCreated and SetFileTimeModified functions), you can create (or replace!) a file (with FileWriteContent function)  or rename a file that is not even loaded to the filetable (with WideRenameFile function) and more. But be aware that any of actions performed by PascalScript (apart of changing the FileName variable) will be performed during Preview (and NOT Rename) operation. So be aware that you might do some harm to your files or filesystem, especially if AutoPreview is turned on.



Renaming files with PascalScript
There are two custom strings for you to use:
var FileName : WideString            (e.g. "file.txt")
const FilePath : WideString.         (e.g. "c:\temp\file.txt")

Renaming of files with PascalScript consist of changing the FileName variable*, eg. if you want to add 'VIP file ' as a prefix to the filename you would need such a script:

begin
  FileName:='VIP file ' + FileName;
end.

You might also move a file to a different folder, like that:

begin
  FileName:='c:\temp\'+FileName;
end.

or like that:

begin
  FileName:='NewSubfolder\' + FileName;
end.

This will move the file to the new subfolder of file's parent folder.
If FilePath constant would be 'c:\parent\file.txt', this script will contacenate two strings: 'c:\parent\' and 'NewSubfolder\file.txt' into 'c:\parent\NewSubfolder\file.txt'.
Just remember that there already is a '\' at the end of the path the FileName is appended to.

FilePath constant is provided only for reference. You may change it, but this will have no influence on renaming operation.


*Second (highly unrecommended for "everyday" use) way of renaming consist of using WideRenameFile function. This one allows you to rename files even if they are not loaded to ReNamer's filetable. Furthermore it rename files during Preview (and not Rename) so you can't even check what the result will be like.

Last edited by krtek (2009-03-11 22:03)


Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).

Offline

#32 2009-03-11 23:10

krtek
Senior Member
From: Łódź (Poland)
Registered: 2008-02-21
Posts: 262

Re: ReNamer: Making of new manual

Regex functions in PascalScript

function ReplaceRegEx(const Input, Find, Replace: WideString; const CaseSensitive, UseSubstitution: Boolean): WideString;

This is exact equivalent of RegEx rule.

Description of parameters:
Input - string to be processed by RegEx engine, eg. FileName
Find  - equivalent for the field 'Expression' from the RegEx rule dialog
Replace - well... 'Replace' from the RegEx rule dialog
CaseSensitive - True/False
UseSubstitution - determines whether use references in result or not. If it's set to True, function will change $1-$9 in 'Replace' string with the corresponding parts of 'Find' expression, eg. (.+). If it's set to False, function will print $1 as it is (eg. "My_Picture_$1" instead of "My_Picture_365") to the result string.



function MatchesRegEx(const Input, Find: WideString; const CaseSensitive: Boolean): TStringsArray;

MatchesRegEx function returns an array of full matches, which matched the entire expression (not the sub-patterns).

Parameters: as in ReplaceRegEx function.

Example:

const
  SAMPLE = 'one two three';
  REGEX = '\w';
var 
  I: integer;
  Message: WideString;
  Matches: TStringsArray;
begin
  Matches := MatchesRegEx(SAMPLE, REGEX, False);
  Message := 'FOUND '+IntToStr(Length(Matches))+' MATCHES:';
  for I:=0 to Length(Matches)-1 do
    Message := Message + #10 + Matches[i]; 
  WideShowMessage(Message);
end.

If you run that script you will find out that a full match was achieved three times by the regex in the sample text. It will return an array ['one', 'two', 'three'].



function SubMatchesRegEx(const Input, Find: WideString; const CaseSensitive: Boolean): TStringsArray;

This function is very similar to MatchesRegEx, but instead of returning full expression matches it will return an array of sub-expression matches for the first full expression match.  It can easily be combined with MatchesRegEx function, to allow users to find all global matches, and then parse those matches through SubMatchesRegEx function to find individual sub-expression matches of each global match.

Parameters: as in ReplaceRegEx function.

Example:

const
  SAMPLE = 'one two three';
  REGEX = '(.*) (.*) (.*)';
var 
  I: integer;
  Message: WideString;
  SubMatches: TStringsArray;
begin
  SubMatches := SubMatchesRegEx(SAMPLE, REGEX, False);
  Message := 'FOUND '+IntToStr(Length(SubMatches))+' REFFERENCES:';
  for I:=0 to Length(SubMatches)-1 do
    Message := Message + #10 + SubMatches[i]; 
  WideShowMessage(Message);
end.

It will return an array ['one', 'two', 'three'].
SubMatches[0] stands for $1 in RegEx rule
SubMatches[1] stands for $2 in RegEx rule and so on...


SubMatchesRegEx function is very useful when you need to compensate for lack of possibility to change case of the replace part in RegEx rule.

The script below should be linked from here but should be in the second part.

Changing case according to RegEx.

Short description of script controls:
This script will change case of every submatch of REGEX (every part of regex taken in parenthesis'()') to one selected in CHANGE_CASE. It will omit words that will be placed in TO_SKIP string (delimited with DELIMITER). You may also choose if search should be CASE_SENSITIVE.
To avoid randomness script expects a REGEX that will match entire filename (extention is skipped by the script). If the whole filename weren't matched with the regex script will show a warning message and ask if user want to rename the file anyway.

The script was written to change case of surnames in filenames of mp3 with such a pattern:
Eddy Wata - I Love My People.mp3 ---> Eddy WATA - I Love My People.mp3
Geo Da Silva - Feelin' So Good (Long Mix).mp3 ---> Geo Da SILVA - Feelin' So Good (Long Mix).mp3
David Guetta Feat. Chris Willis - Love Is Gone (Original Mix).mp3 ---> David GUETTA Feat. Chris WILLIS - Love Is Gone (Original Mix).mp3

But it can do a lot more. It can change case of any part of filename if only you can write regex that will match that part as a submatch.

const

//SCRIPT CONTROLS:

//Legend:
//1. UPPERCASE
//2. lowercase
//3. First letter capital
CHANGE_CASE = 1;

REGEX = '.+\s(\w+)\s(Feat\.|ft\.|&|And|Featuring)\s\w+\s(\w+) - .+|.+\s(\w+)\s-\s.+';


TO_SKIP = 'Feat.|ft.|&|And|Featuring';      //Here you can put words that you want to be skipped by script.
                                            //The case convertion won't be applied to them.
                                            //Seperate them with DELIMITER
                                            //And remember that you need to make them explicit. Remove any escape signs.
                                            //They need to be strings already matched by regex, so Feat. instead of Feat\.

DELIMITER = '|';                      //Delimiter of words in TO_SKIP string


CASE_SENSITIVE = False;      //Should searching with regex be case sensitive? Default: False

//END OF SCRIPT CONTROLS




var
  Matches, SubPatterns : TStringsArray;
  TempFilename, FileNameNoEXT : WideString;
  start_pos, end_pos, i, j : Integer;
  Initialized, TimeToExit, NeedSkipping, NotAFullMatch : Boolean;
  Skip : TStringsArray;
  Answer : WideString;
  


procedure Initialize;
begin
  Skip:=WideSplitString(TO_SKIP, DELIMITER);
  Answer:='Type just word BREAK in here to exit the script';
end;



begin
  
if not TimeToExit then
begin

  if not Initialized then Initialize;

  TempFilename:='';
  end_pos:=0;
  start_pos:=1;
  SetLength(SubPatterns,0);
  SetLength(Matches,0);
  NotAFullMatch:=false;
  FileNameNoEXT:=WideStripExtension(FileName);
  
  
  Matches:=MatchesRegEx(FileNameNoEXT, REGEX, CASE_SENSITIVE);
  if Length(Matches) <= 0 then exit;
  if Matches[0] <> FileNameNoEXT then NotAFullMatch:=true;
  SubPatterns:=SubMatchesRegEx(Matches[0],REGEX,CASE_SENSITIVE);
  if Length(SubPatterns) <=0 then exit;
  
  for i:=0 to Length(SubPatterns)-1 do
    if SubPatterns[i]<>'' then
    begin
      NeedSkipping:=false;
      end_pos:=WidePos(SubPatterns[i], Matches[0])-1;
      TempFileName:=TempFileName+WideCopy(Matches[0], start_pos, end_pos-start_pos+1);
      start_pos:=end_pos+Length(SubPatterns[i])+1;
      
      for j:=0 to Length(Skip)-1 do
        if WideSameText(SubPatterns[i],Skip[j]) then NeedSkipping:=true;

      if not NeedSkipping then 
        case CHANGE_CASE of
          1 : TempFilename:=TempFileName+WideUpperCase(SubPatterns[i]);
          2 : TempFilename:=TempFileName+WideLowerCase(SubPatterns[i]);
          3 : TempFilename:=TempFileName+WideUpperCase(SubPatterns[i][1])+WideLowerCase(WideCopy(SubPatterns[i], 2, Length(SubPatterns[i])-1));
        else
          begin  
            ShowMessage('The value of CHANGE_CASE constant is invalid. Check legend for info.');
            TimeToExit:=True;
            break;
          end;
        end
      else
        TempFilename:=TempFileName+SubPatterns[i];


    end;
  if start_pos < Length(FileNameNoEXT) then
    TempFilename:=TempFileName+WideCopy(FileNameNoEXT, start_pos, Length(FileNameNoEXT)-start_pos+1);
 
 if NotAFullMatch then
   if not WideInputQuery('RegEx didn''t match the full filename.', 'Old filename:'+#10+FileName+#10+#10+'Proposed new filename: '+#10+TempFileName+WideExtractFileExt(FileName)+#10+#10+'What should we do?'#10+#10+'Pressing OK button = Rename that file'+#10+'Pressing Cancek button = Skip that file'+#10+'Type ''break'' in the text field to exit the script'+#10, Answer) then
     exit
   else if WideSameText(WideLowerCase(Answer),'break') then 
       begin
         TimeToExit:=True;
         exit;
       end
   else
       Answer:='Type just word BREAK in here to exit the script';
 
     
 FileName:=TempFileName+WideExtractFileExt(FileName);

end
else exit;
 
end.

Last edited by krtek (2009-03-15 09:45)


Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).

Offline

#33 2009-03-15 07:36

narayan
Senior Member
Registered: 2009-02-08
Posts: 471

Re: ReNamer: Making of new manual

I am re-writing the Pascal script part of the manual now.

I will need to include some implementation-related information, which is not provided in the basic Pascal script tutorial (www.taoyue.com/tutorials/pascal/contents.html).

A few mini tutorials (with examples) will be necessary if we want a new user to pick up the scripting smoothly, without groping in the dark for missing links.

In other words, the mission statement for the Pascal Script manual is-

A newbie who has read the taoyue tutorial should be able to find all the building blocks and concepts necessary to write practical scripts in ReNamer without having to search elsewhere.

To start with, please provide mini tutorials (suitable for beginners) for the following topics:

1. ReNamer supports User-defined procedures and functions.

So how would a user collect, organize and store UDFs, so that they can be called any time he wants? Secondly, given an end-purpose, how should he search for the right UDF? (He cannot possibly open each of the UDFs and look inside. He also cannot rely on the UDF's name alone to guess what it does. So there has to be an efficient search method.)

2. ReNamer can import external functions from DLLs. How are these extracted? Are they extracted once and then onwards stored like any other UDF? Or are they extracted on-the-fly from the DLLs? Is there a difference in handling of these functions and the "stand-alone" UDFs?

3. The FilePath constant holds the original path of the file, and is provided for the direct file access. If this is a constant, how do you move the file to a different folder (or a new folder that is created on-the-fly based on metadata)?

N.B I am looking for ready material that I can copy and paste in the manual straightaway, without having to figure out some things myself. Thanks!

Last edited by narayan (2009-03-15 09:00)

Offline

#34 2009-03-15 09:40

krtek
Senior Member
From: Łódź (Poland)
Registered: 2008-02-21
Posts: 262

Re: ReNamer: Making of new manual

narayan wrote:

3. The FilePath constant holds the original path of the file, and is provided for the direct file access. If this is a constant, how do you move the file to a different folder (or a new folder that is created on-the-fly based on metadata)?

As I wrote in Renaming files with PascalScript you need to change FileName variable to do that.

Ps. I've tried to write mini tutorials (or mini manuals) on what was important to me when I was making my first steps with PascalScript.
Tell me if they're OK with your vision of the manual.


Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).

Offline

#35 2009-03-15 13:39

narayan
Senior Member
Registered: 2009-02-08
Posts: 471

Re: ReNamer: Making of new manual

Would that move or copy the file?

Let us see your mini tutorials! Or if they are already shared here at the forum, then I will need links please!

So far, I have explained all the variables, functions and procedures that were listed in the original manual. (There are some places where someone will need to add explanation.)

Then I will add the 3 topics mentioned before; plus these tutorials you mentioned.

Offline

#36 2009-03-15 14:55

narayan
Senior Member
Registered: 2009-02-08
Posts: 471

Re: ReNamer: Making of new manual

From a post in this thread, a doubt:

This one allows you to rename files even if they are not loaded to ReNamer's filetable. Furthermore it rename files during Preview (and not Rename) so you can't even check what the result will be like.

What is the pattern here? When do all scripts show a Preview, and when do they act only on the actual renaming operation? How will the user know whether the previewed names are correctly being previewed?

Last edited by narayan (2009-03-15 15:31)

Offline

#37 2009-03-15 20:14

krtek
Senior Member
From: Łódź (Poland)
Registered: 2008-02-21
Posts: 262

Re: ReNamer: Making of new manual

narayan wrote:

Let us see your mini tutorials! Or if they are already shared here at the forum, then I will need links please!

Hmm... I've posted my minimanuals earlier in this thread. They're called Initialization of variables and breaking the execution of the script, Renaming files with PascalScript, Regex functions in PascalScript tongue

narayan wrote:

Would that move or copy the file?

It will move the file. I'm not sure if ReNamer can actually copy files. It's covered in Renaming files with PascalScript.

narayan wrote:

What is the pattern here? When do all scripts show a Preview, and when do they act only on the actual renaming operation?

I guess that my WARNING wasn't clear enough. I'll try to rephrase it in few secs.
ReNamer's philosophy is simple:
1. Preview. It fills filetable with New Names (and New Paths). Now you can check if everything is fine. You may also make individual adjustments (by edditing new name [F2]). If everything is ready you go to the second step.
2. Rename. After you press Rename button ReNamer replaces old names of files in filetable with new names (and old paths with new paths). That's all. No magic. Simple move 'old path\old name' to 'new path\new name' for all the files in the filetable.

On the first step (Preview) we play with filename only (not touching the file itself).  We play only with string that is the address of the file (eg. 'e:\test\test.txt'). We can change it according to rules. Then check if all is ok and press ReName.
In PascalScript rule this string is represented by FileName variable. Whatever you do to the FileName variable you won't touch the file itself. Only the string that represents it's filename. And when script exits (for that single file - don't forget that rules are executed for every file separately) New Name cell that respond to that file in filetable is filled with the content of the FileName variable. Still nothing has happened to the file. It will be actually renamed only when you press Rename.

And that's the normal usage of PascalScript. Anything apart from changing FileName variable is potentially dangerous. But I guess all the functions that have access to the operating system have it written in their names, eg. SetFileTimeModified or FileWriteContent...

And there's rewritten warning...

WARNING
With PascalScript you can achieve more than only renaming files. You can change a datestamp of the file (with SetFileTimeCreated and SetFileTimeModified functions), you can create (or replace!) a file (with FileWriteContent function)  or rename a file that is not even loaded to the filetable (with WideRenameFile function) and more.
But be aware that all scripts (exactly as other rules) are executed during Preview (and NOT Rename) operation. But scripts, in contrast to other rules, might (it depend on functions used) access your operating system directly. So be aware that you might do some harm to your files or filesystem, especially if AutoPreview is turned on.
The ONLY product of PascalScript that doesn't affect your files until Rename operation is the content of the FILENAME variable. "New Name" (and "New Path") fields of filetable are replaced with this variable content. After Preview you may check if you like them and if you do - press Rename. Only then the actual renaming of the files will take place.



narayan wrote:

How will the user know whether the previewed names are correctly being previewed?

I've never used WideRenameFile function before and I had to do a small testing of it. The answer is: if you use WideRenameFile function, you won't know if names are previed correctly until you press ReName. To be more precise: if you use that function, you can't be sure that files you've loaded to the filetable are still in their old paths. Using that function is like moving files with Windows Explorer AFTER they were loaded to ReNamer's filetable. ReNamer can't find these files anymore, so it won't rename them (at least with names built by Preview) and it will give you a warning:
"x file(s) failed to rename!".
Furthermore, Undo won't work for files renamed with WideRenameFile.

You may test it yourself with that simple script.

Const
TEST_FILE = 'e:\test\test.txt';

var
NewTestFile: Widestring;

begin
 NewTestFile:=WideExtractFilePath(TEST_FILE)+WideExtractBaseName(TEST_FILE)+'2'+WideExtractFileExt(TEST_FILE);
 if WideRenameFile(TEST_FILE, NewTestFile) then ShowMessage('File "'+TEST_FILE+'" renamed to '+NewTestFile);
 FileName:='old_'+FileName;
end.

Just change TEST_FILE const to some appropriate path. Script will try to append '2' to this file's name using WideRenameFile and will add 'old_' prefix to all the filenames in filetable.
If you add your TEST_FILE to ReNamer's filetable as well it will fail to be renamed to 'old_test.txt' (because it will be renamed to test2.txt earlier).

Last edited by krtek (2009-03-15 20:34)


Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).

Offline

#38 2009-03-15 23:31

krtek
Senior Member
From: Łódź (Poland)
Registered: 2008-02-21
Posts: 262

Re: ReNamer: Making of new manual

I think I've learned enough about WideRenameFile function to write its description.


function WideRenameFile(const OldName, NewName: WideString): Boolean;

WARNING: This is not the intended way to rename files with PascalScript. This function might be dangerous to your filesystem. It's not recommended to use it unless you're completely sure what you are doing.
If you wan't to rename files in normal way - just change the content of the FileName variable.

Description:
WideRenameFile function is completely independent from ReNamer's files table, which means it has nothing in common with the file (FileName) currently processed by script.
It is similar to DOS command 'move'. This function tries to rename (or move) given file (OldName) into the location given by NewName parameter. It returns TRUE If it succeeds, FALSE - if it wasn't able to rename/move the file.

Parameters:
OldName - file with a path that should be renamed
NewName - new filename with the path

Known issues:

  • If the folder you want to move file into doesn't exist, it WON'T create that folder. So you need to create the folder prior to moving the file. This behaviour is different from normal moving operation with ReNamer, which force creation of the folder if it doesn't exist.

  • If you give only a filename without a path as a NewName parameter (eg. 'test.txt') file will be renamed/moved to the current system folder (usually ReNamer's folder).

  • There have to be at least one file in files table in order for Preview to take place. So script below won't do it's job until there will be at least one marked file in the files table.

begin
WideRenameFile('c:\test\test.txt', 'c:\test\test2.txt');
end.
  • If you use WideRenameFile function to rename a file that is loaded into the files table, ReNamer won't be able to rename that file according to the set of rules established by you, because it won't be able to find the file in it's path.

  • Undo won't work for files renamed with WideRenameFile. Undo works according to the files table and WideRenameFile has nothing in common with it.

Last edited by krtek (2009-03-16 09:39)


Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).

Offline

#39 2009-03-16 02:47

narayan
Senior Member
Registered: 2009-02-08
Posts: 471

Re: ReNamer: Making of new manual

Absolutely fantastic, krtek!

I have already incorporated your inputs in the scripts section of the manual (and added examples/explanation); so I was hoping for some more "mini-tutorials for the absolute beginners".

I want to start off the introduction with a few actual mini examples (with explanation), so the newbies can feel right at home with scripting. In other words, just imagine a user who has freshly read the http://www.taoyue.com/tutorials/pascal/contents.html tutorial; but has no idea where to begin in ReNamer. This imaginary character needs to take the first few faltering steps with the help of our mini tutorial. So just words of advise and caution won't do- He would need some actual code snippets that are not too fancy for his newly developing knowledge.

What you have shared lately is for a bit advanced user (finer aspects of certain functions). But again, that will be needed too!

BTW your three-liners were absolutely priceless- They illustrated how exactly ReNamer can work as a file-manager PLUS file-renamer.  Thus your newly worded warning will be easy to illustrate.

Using that function is like moving files with Windows Explorer AFTER they were loaded to ReNamer's filetable. ReNamer can't find these files anymore, so it won't rename them (at least with names built by Preview) and it will give you a warning: "x file(s) failed to rename!".

I have noticed something related to what you mentioned: If you load a file in ReNamer and then rename/move/delete it externally, the ReNamer does not detect the change OR give a warning that the originally loaded file is missing now. I don't know if that's technically feasible, though.

Offline

#40 2009-03-16 09:38

krtek
Senior Member
From: Łódź (Poland)
Registered: 2008-02-21
Posts: 262

Re: ReNamer: Making of new manual

In my opinion this introductional mini tutorial should go like that:
1. Renaming files with PascalScript (but without the warning and without any info about existance of WideRenameFile function)
2. Initialization of variables and just a link to How to break the script execution which should be somewhere in the main part of manual
3. Basic File Name Utilities as WideExtraxtBaseName and WideExtractFileExt + concatenating of strings
4. Unicode Character Handling Routines like WideCharUpper and IsWideCharUpper...
5. Some Basic Conversion Routines as IntToStr and StrToInt
6. Interactive dialog like ShowMessage and WideInputQuery...

What do you think?


Regular Expressions are not as hard to understand as you may think. Check ReNamer's manual or nice Regular Expressions tutorial for more info and start to use full power of applications that use them (like ReNamer, Mp3Tag and so on).

Offline

Board footer

Powered by FluxBB