ReplaceList question

Please check the FAQ (https://www.xyplorer.com/faq.php) before posting a question...
Post Reply
klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

ReplaceList question

Post by klownboy »

An issue with SC replacelist is driving me nuts. I've simplified and cut down this portion of the script as an example. There's actually a foreach loop which will provide the replacement for each value. Each list generated is correct - no issues there.

Code: Select all

  $XY_TB_buttons = "Add Tags [tagsadd]|Address Bar Go [go]|All Drives (Group) [{drives_all}]|Auto-Refresh [autorefresh]|Available Drives (Group) [{drives_avl}]|Back [back]|Backup To [backupto]|Branch View [flatview]|Browse Network [browsenetwork]|Calculate Folder Sizes [calcfosi]|CD-ROM Drives (Group) [{drives_cdr}]|Checkbox Selection [cbx]|Close Tab [closetab]|Command Prompt [dosbox]|Computer [myco]|Configuration [conf]|Copy [copy]|Copy Path or Name [copypath]|Copy to Other Pane [dpcopyto]|Copy To... [copyto]|Customize Keyboard [cks]|Cut [cut]|Delete [del]|Details View [viewdetails]|Disconnect Mapped Drive [netunmap]|Drives [drives]|Dual Pane [dp]";
    echo  $XY_TB_buttons;
    $XY_TB_buttons_short = "";
      foreach ($button, $XY_TB_buttons, "|") {
	  	 $button_name = trim(gettoken($button, 2, "["), "]", "R");
	      $XY_TB_buttons_short = $XY_TB_buttons_short . $button_name . "|";
     }
   $XY_TB_buttons_short = trim( $XY_TB_buttons_short, "|" "R");
    echo "short<crlf>$XY_TB_buttons_short";

	    $XY_TB_buttons_desc = "";
    foreach ($button, $XY_TB_buttons, "|") {
	  	 $button_name = gettoken($button, 1, "[", "t");
	     $XY_TB_buttons_desc = $XY_TB_buttons_desc . $button_name . "|";
    }
                 $XY_TB_buttons_desc = trim( $XY_TB_buttons_desc, "|" "R");
	echo "Desc<crlf>$XY_TB_buttons_desc"; step;

   $TB_button_desc = replacelist ("copypath", $XY_TB_buttons_short, $XY_TB_buttons_desc, "|"); echo $TB_button_desc;
   $TB_button_desc = replacelist ("autorefresh", $XY_TB_buttons_short, $XY_TB_buttons_desc, "|"); echo $TB_button_desc;
   unstep;
The replacelist for "copypath" always comes out "Copy path" and it should be "Copy Path or Name" whereas "autorefresh" replacement gives the correct result of "Auto-refresh". The vast majority of the replacement results are correct. I believe it's due to the repetition of the word "copy" in the lists. Is this a bug or can I get around the issue some how? Thanks.
Last edited by klownboy on 28 May 2015 01:33, edited 1 time in total.

bdeshi
Posts: 4256
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612
Contact:

Re: ReplaceList failure

Post by bdeshi »

replacelist tries to match and replace from left [1]. Furthermore, any part of the inputstring that has matched is excluded from consequent search/replacements [2].

The first search-pattern that is found in "copypath" is 'copy', because this is listed before 'copypath' itself in $XY_TB_buttons_short. [pt1]
Since a match was found, no further search is done for this pattern, and this is replaced with "Copy" from $TM_TB_buttons_desc.

Then for the next patterns this part of the string is skipped [pt2] and all searches are done against 'path'. So you're left with 'Copypath'.

This could be remedied by listing search/replace patterns with largest strings at left. Or since both patternlists are sorted in the same order, just use a token-based replacement.

Code: Select all

  //$TB_button_desc = replacelist ("copypath", $XY_TB_buttons_short, $XY_TB_buttons_desc, "|"); echo $TB_button_desc;
  $TB_button_desc = gettoken($XY_TB_buttons_desc, gettokenindex('copypath', $XY_TB_buttons_short, '|', 'i'), '|'); echo $TB_button_desc;
  //$TB_button_desc = replacelist ("autorefresh", $XY_TB_buttons_short, $XY_TB_buttons_desc, "|"); echo $TB_button_desc;
  $TB_button_desc = gettoken($XY_TB_buttons_desc, gettokenindex('autorefresh', $XY_TB_buttons_short, '|', 'i'), '|'); echo $TB_button_desc;
An argument can be made that replacelist should always search the whole string for each pattern, but I think that will only create more complexity, as you might be replacing already replaced parts, or parts of replaced parts, or smaller parts... again and again. :whistle:

ed. :ninja: checksyntax
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList failure

Post by klownboy »

Thanks Sammay for your help and the explanations. I just woke up and haven't tried your suggestion but I will.
SammaySarkar wrote:An argument can be made that replacelist should always search the whole string for each pattern, but I think that will only create more complexity, as you might be replacing already replaced parts, or parts of replaced parts, or smaller parts...
I would say yes, this is a valid condern. Why shouldn't SC replacelist be looking for the complete match that is clearly within the confines of the defined separator "|". Maybe Don could have a parameter which would look for a match of the complete string, which in most cases, I think users would want as a default actually.

Yes, as a work around in this case, since the 2 other lists are derived directly from the master list and have the same sort order as you said, the use of gettokenindex is a great idea. :appl: I wouldn't like having to rearrange listings to make something like this work - not such a good idea. :(
Thanks,
Ken

admin
Site Admin
Posts: 66347
Joined: 22 May 2004 16:48
Location: Win8.1, Win10, Win11, all @100%
Contact:

Re: ReplaceList failure

Post by admin »

See help for ReplaceList:
"Replaces substrings by list."

Not:
"Replaces strings by list."

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList question

Post by klownboy »

admin wrote:See help for ReplaceList:"Replaces substrings by list."Not:"Replaces strings by list."
Help is always the first thing I check though I didn't catch on to this point. Though it's a shame a string couldn't be covered some way in SC replacelist or similar such that if you have a situation like |Copy Path or Name| it would look for the exact match of that string contained within the "|" separator and not be tricked by one word similarity. Thanks Don.

admin
Site Admin
Posts: 66347
Joined: 22 May 2004 16:48
Location: Win8.1, Win10, Win11, all @100%
Contact:

Re: ReplaceList question

Post by admin »

Yes, in the meantime I added that as an option. Next beta...

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList question

Post by klownboy »

Thanks Don this will come in handy. I tried the enhanced SC ReplaceList with a scope of 2 on the example script in the first post and in the full vTB (Vertical Toolbar) script which uses it in 3 different places and it works great. Thanks again. :tup: :appl:

Edit: Right now I'm using SC ReplaceList to replace each string in a foreach loop situation. I have to do some testing, but I think especially now with this change, I may be able to accomplish all the replacements at once instead of individually in a foreach loop...which would be cool.

admin
Site Admin
Posts: 66347
Joined: 22 May 2004 16:48
Location: Win8.1, Win10, Win11, all @100%
Contact:

Re: ReplaceList question

Post by admin »

That should work. Let me know if it does not.

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList question

Post by klownboy »

Hi Don, as I said above it works fine for a one string replacement, but I'm finding if I have a list of strings using scope "2", it returns the strings again with no replacement done. Hopefully, I haven't screwed up the syntax. Try this script portion to test...

Code: Select all

   $XY_TB_buttons = "Add Tags [tagsadd]|Address Bar Go [go]|All Drives (Group) [{drives_all}]|Auto-Refresh [autorefresh]|Available Drives (Group) [{drives_avl}]|Back [back]|Backup To [backupto]|Branch View [flatview]|Browse Network [browsenetwork]|Calculate Folder Sizes [calcfosi]|CD-ROM Drives (Group) [{drives_cdr}]|Checkbox Selection [cbx]|Close Tab [closetab]|Command Prompt [dosbox]|Computer [myco]|Configuration [conf]|Copy [copy]|Copy Path or Name [copypath]|Copy to Other Pane [dpcopyto]|Copy To... [copyto]|Customize Keyboard [cks]|Cut [cut]|Delete [del]|Details View [viewdetails]|Disconnect Mapped Drive [netunmap]|Drives [drives]|Dual Pane [dp]|Edit Files in Clipboard [clip]|Enable Background Processing [bfop]|Enable Color Filters [cofi]|Enable Custom File Icons [cfi]|Exit without Saving [exitnosave]|Favorite Files [favfiles]|Favorite Folders [favs]|Find by Label [findlabel]|Find by Tags [tagsfind]|Find Files [find]|Floating Preview [fp]|Folder View Settings [fvs]|Forward [fore]|Full Screen Preview [previewfull]|Go to Last Target [lasttarget]|Go to Previous Location [goprev]|Hard Drives (Group) [{drives_fix}]|Hide Folders in List [showfolders]|Home [home]|Hotlist [hotlist]|Labels [labels]|Last or Min Size Info Panel [panellast]|List Management [lstmgmt]|List View [viewlist]|Lock Tab [locktab]|Manage Commands [udc]|Manual Sorting [mansort]|Map Network Drive [netmap]|Max or Min Size Info Panel [panelmax]|Metadata [meta]|Mini Tree [minitree]|Move to Other Pane [dpmoveto]|Move To... [moveto]|Network Drives (Group) [{drives_net}]|New Folder [newfolder]|New Tab [newtab]|Nuke [nuke]|Open With [openwith]|Paper Folders [paper]|Paste [paste]|Preview [preview]|Properties [shellprops]|Properties Tab [props]|Queue File Operations [queue]|Quick File View [qfv]|Quick Search [qns]|Recent File Operations [rfo]|Recent Locations [mru]|Redo [redo]|Refresh [refresh]|Remove Tags [tagsrmv]|Rename [rename]|Save Settings [savesett]|Select All [select]|Set Tags [tagsset]|Show Catalog [cat]|Show Grid [grid]|Show Hidden Items [showhidden]|Show Info Panel [panelshow]|Show Navigation Panel [hidenav]|Show System Items [showsystem]|Show Tree [treeshow]|Sort By [sort]|Step Mode [steps]|Sticky Selection [sticky]|Stop [stop]|Suspend Auto-Refresh [refreshsus]|Sync Browse [syncbrowse]|Sync Scroll [syncscroll]|Tab List [tablist]|Tabsets [tabsets]|Thumbnails View [viewthumbs]|Toggle Active Pane [dp12]|Toggle Instant Color Filter [icf]|Toggle Visual Filter [visualfilter]|Toggle Wide Info Panel [hightree]|Tree Path Tracing [tpt]|Type Stats and Filter [tsf]|Undo [undo]|Up [up]|Use Custom Copy [cucopy]|Views [views]|Wipe [wipe]|Zoom In [zoomin]|Zoom Out [zoomout]";
    echo  $XY_TB_buttons;
    $XY_TB_buttons_short = "";
      foreach ($button, $XY_TB_buttons, "|") {
	  	 $button_name = trim(gettoken($button, 2, "["), "]", "R");
	      $XY_TB_buttons_short = $XY_TB_buttons_short . $button_name . "|";
     }
   $XY_TB_buttons_short = trim( $XY_TB_buttons_short, "|" "R");
    echo "Short name<crlf>$XY_TB_buttons_short";

	  $XY_TB_buttons_desc = "";
    foreach ($button, $XY_TB_buttons, "|") {
	  	 $button_name = gettoken($button, 1, "[", "t");
	     $XY_TB_buttons_desc = $XY_TB_buttons_desc . $button_name . "|";
    }
                 $XY_TB_buttons_desc = trim( $XY_TB_buttons_desc, "|" "R");
	echo "Descriptive name<crlf>$XY_TB_buttons_desc"; step;

  $actual_list = "cbx|fvs|previewfull|home|hotlist|openwith|preview|qfv|qns|savesett|cat|grid|hidenav|syncbrowse|visualfilter|tsf|undo|views";
  $TB_button_desc = replacelist ("$actual_list", "$XY_TB_buttons_short", "$XY_TB_buttons_desc", "|", 0, 2); echo $TB_button_desc;  //this doesn't work
   $TB_button_desc = replacelist ("fvs|home", "$XY_TB_buttons_short", "$XY_TB_buttons_desc", "|", 0, 2); echo $TB_button_desc;   //this doesn't work
  $TB_button_desc = replacelist ("copypath", "$XY_TB_buttons_short", "$XY_TB_buttons_desc", "|", 0, 2); echo $TB_button_desc;    //this works
   $TB_button_short_list = replacelist ("Add Tags|Address Bar Go|Auto-Refresh|Hard Drives (Group)|Hide Folders in List", "$XY_TB_buttons_desc", "$XY_TB_buttons_short", "|", 0, 1); echo $TB_button_short_list;  //this works with scope "1" but not with scope "2".

Update 1: It looks like it works fine for this particular case if I use scope "1" for "whole words" since when replacing in this direction, XY is looking for only single word strings in the "search list" even though there are multiple words in the "replacelist". In another situation I have to reverse this going from the long descriptive name (more than one word) to get the short single word name which I would assume in that case I would have to use "scope "2". I'll follow-up later on that.
Update 2: I tested going in the reverse direction from the long (more than one word description names) to the replacement single words and I would have thought that scope "2" would be necessary, but it doesn't work and yet again scope "1" does work. Isn't that a bit strange especially working in this direction (i.e., multi-words strings and multi-words search list)? Is scope "1" working like scope "2" should? I added that example to the above script using scope "1" where I thought "2" would be necessary. Is it acceptable to have a the replacelist "string" be multiple strings separated by a separator...well, I suppose it must be since it seems to work in scope "1".

admin
Site Admin
Posts: 66347
Joined: 22 May 2004 16:48
Location: Win8.1, Win10, Win11, all @100%
Contact:

Re: ReplaceList question

Post by admin »

Sorry, no time to step through that code. Can you somehow isolate the issue?

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList question

Post by klownboy »

Don, sorry about the length of the script piece, but you wouldn't have to step through it to see what's happening. I had some echo's placed in there which would give you the results. Anyway, I'm not sure it is a problem just unexpected results between scope "1" and "2" (i.e., the reverse of expected - I did not get the results expected using scope "2" where there was multiple words involved in each string, yet I received the proper results using scope "1"). It didn't seem right.

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList question

Post by klownboy »

ReplaceList using scope "1" and "2" check a bit easier to see results with a multiple strings...

Code: Select all

   text replacelist("Hello you|Taxi Cab color|Taxi Driver - Sam|Taxi Co|car type|Hello, Taxi Driver!|nice car","model|Hello you|Taxi cab color|Taxi Driver - Sam|Taxi Co|French bread|car type|Hello, Taxi Driver!|nice car", "Nissan|goodbye|yellow|Sam|BMW Cabs|Corn bread|350Z|Hello Sam|great car!", "|", 0,1);  //then try "2"
   //scope "1" - yields good result -  goodbye|yellow|Sam|BMW Cabs|350Z|Hello Sam|great car!    
   //scope "2" - no replacement occurs -  Hello you|Taxi Cab color|Taxi Driver - Sam|Taxi Co|car type|Hello, Taxi Driver!|nice car

PeterH
Posts: 2827
Joined: 21 Nov 2005 20:39
Location: DE W11Pro 24H2, 1920*1200*100% 3840*2160*150%

Re: ReplaceList question

Post by PeterH »

(Think you could have done it still a bit shorter?)

Just to start: I think the first operand is just a string, the | shouldn't have a meaning here. (I.e | are just like any other characters in this string.)
But at chance the | are word separators here, as blank and others are. So option=1 can work. But should also work if you replace all | of the 1st operand with blanks.
But it seems a bit of strange when you work with option=1="test words", and then test for groups of words. Strange, but might be OK.

And for option=2 I understand that the whole first operand must fit a compare? If yes, then this can't fit in any way, as no token in operand2 is identical to the whole operand1.

Am I right, or misunderstanding?

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList question

Post by klownboy »

PeterH wrote:Think you could have done it still a bit shorter?
Yeah, I over did it again...sorry. This was a silly example, but the original use is shown in the looooonger post above that.

It boils down to this...
When there was just "one" string, whether it was one word or multiple words, the new change to replacelist with scope "2" worked fine as in the first post (i.e., the change resulted in that replacelist example working). After reporting that to Don, I then mentioned to Don in a later post that I had a situation where I was using this in a foreach loop to replace each string one at a time and I was wondering if I could use it to replace all the strings at once without the foreach loop. Of course the strings requiring replacement were separated by the same separator used in the searchlist and replacelist. Bottom line is, Don thought it should work and said, let me know if it doesn't (I don't know if he realized how I was separating the individual strings). Well, it actually does work when using scope "1", but not scope "2". Now it's stating to make sense, but initially that's what surprised me. As you mentioned, I think it is recognizing the "|" as separators and the contents between the separators are being treated as a single word (i.e., scope "1" and not as a group of words as in scope "2").
PeterH wrote:And for option=2 I understand that the whole first operand must fit a compare? If yes, then this can't fit in any way, as no token in operand2 is identical to the whole operand1.
When you refer to the whole first operand, I assume you are referring to everything in the "string" section of SC replacelist (e.g., "Taxi Cab color|Taxi Driver - Sam|Taxi Co|car type"). Which is saying you can't have multiple multi-word strings (with separators between them) which need to be replaced using scope "2". Is that correct? Maybe Don needs to give his thoughts too. :wink: Thanks.

klownboy
Posts: 4462
Joined: 28 Feb 2012 19:27
Location: Windows 11, 25H2 Build 26200.8737 at 100% 2560x1440

Re: ReplaceList question

Post by klownboy »

Don, out of curiosity only (no need to test), does the logic in my previous post make sense to you, concerning why scope "1" works when the enhanced SC replacelist has a "string" containing both single and multiple words separated by "|" whereas scope "2" does not?

Edit: Quick test: these replacements work fine using scope "1" so I suppose, it works as you intended. :whistle: :appl:

Code: Select all

     $list1 = "can not do|not excited|no way|hotdog bun";
     $list2 = "can do|very excited|way|hamburger roll";
     $my_list1 = "can not do|no way";
     $my_list2 = "not excited|hotdog bun";
     $new_list1 = replacelist ($my_list1, $list1, $list2, "|", 0, 1); echo $new_list1;  //correct  - can do|way
     $new_list2 = replacelist ($my_list2, $list1, $list2, "|", 0, 1); echo $new_list2;  //correct  - very excited|hamburger roll

Post Reply