/*EVERYTHING IN XYPLORER — Rev. 0.92 / 2014/07/08.#########--- Original script by Marco ---######## The code is divided into logical sections, each one identified by a line in the form "/*TITLE.###…" . Below that line a comment section like this one is found, which summarizes what happens below. -------------------------------------------------------------------------------------------------*/ /*ES.EXE SYNTAX.################################################################################### -r Search the database using a basic POSIX regular expression. -i Does a case sensitive search. -w Does a whole word search. -p Does a full path search. -h --help Display this help. -n Limit the amount of results shown to . -s Sort by full path. -d Search with diacritics, or without diacritics if they're enabled by default (see below) // Flux Note: a query containing a minus preceded by a blank (or in first position) and not followed by any of the letters above always produces the help, and no search results. -------------------------------------------------------------------------------------------------*/ "Find|:find|1 : Find"/*############################################################################ This is the main script of Everything in Xyplorer. -------------------------------------------------------------------------------------------------*/ /*CUSTOMIZATIONS.################################################################################## Here three parameters can be customized: $path: the path of the folder containing the es.exe executable, with a final slash. The default assumes - reasonably - that XYplorer and Everything, being both portable, reside in the same root folder; $paper: the name of the paper folder containing the search results. The default generates a unique name for each search (unless the user name is Flash…); $mode: controls how the minus sign, which introduces switches in es.exe, is treated/escaped. Three modes are available. Total: Everything in Xyplorer will behave as if it was a window of Everything. The minus sign will ALWAYS be escaped with double quotes, thus the functionality provided by es.exe switches won't be available, however the search syntax will absolutely be the same of that of the graphical user interface of Everything; Smart: Everything in Xyplorer will behave as an "advanced" interface to es.exe. The minus sign will be escaped with double quotes AS LONG AS it is not introducing a switch, EXCEPT for -h, --help and -n when NOT followed by a blank and one or more digits. This mode allows the use of switches, keeping at the same time the syntax of search queries involving actual hypens identical to the one used by Everything. In order for it to work properly, non-ambiguous syntax must be entered, i.e. if you really want to look for an item named "-p" (without quotes) then you must quote it. The odds of such kind of queries are low so the attention required for such corner cases is a more than acceptable tradeoff for the smartness provided by this mode. Also known as "The best of the two worlds…™"; None: the minus sign will NEVER be escaped, giving full control on how each minus is passed to the command line. Remember: proper escaping consists of double quotes for a "text" minus, while a "switch" minus shall not be modified. Whatever mode is entered that doesn't match "Total" or "Smart" is treated as "None". -------------------------------------------------------------------------------------------------*/ $path = "\..\Everything\"; //"\..\Everything\" // Flux: Replaced "#" with "_" in paper name (for easier purge with "Like" operator) $paper = "Everything in XYplorer_".now("yyyymmddhhmmss").".txt"; //"Everything in XYplorer#".now("yyyymmddhhmmss").".txt" $mode = "Smart"; //"Smart" $diacritics = 0; // [0/1] Enable or disable diacritics by default. Inverted by using switch "-d" // Flux /*GO!############################################################################################## Despite being the core part, the following code is quite simple. First of all, the user is asked to enter the search query. This will be stored in two variables, $query and $id. The former will undergo all the text manipulations, the latter won't be touched instead, because it needs to preserve the user input exactly for later. Then the minus sign is escaped according to the mode set above. Susbsequently, other special characters are escaped, namely the ones that can be used as search modifiers in Everything or in a normal regular expression and that are known to be "problematic" in a command line. Further info on http://forum.voidtools.com/viewtopic.php?f=5&t=1970&sid=2590f752481d94429e91191e55b6a261 and http://www.robvanderwoude.com/escapechars.php Once a "command line-friendly" query is obtained, the proper command can be run. In order to deal with Unicode the codepage of the console must be changed to 65001 (UTF-8) with the chcp command. Fortunately this change is temporary, so this is a portable/stealth solution that doesn't alter the system. The call to es.exe can simply be concatenated ( && ). Unfortunately though, the console still won't be able to display CJK characters, so runret() isn't a border-less solution, and the old-school redirection (appending, actually) to an output file ( >> ) is the only way. The console will write to disk a list of matches encoded in UTF-8 without BOM. For some unknown reasons (read: bug?) currently under investigation, XYplorer can preview correctly a BOM-less UTF-8 text file but, as soon as it processes it as a paper folder, it will generate gibberish in place of CJK characters. Therefore a little trick is required: the BOM of the future paper folder file is written beforehand. In order to be immune to variations in system encoding/locale/codepage, the BOM is provided to the writefile() function as a conversion from hex values (0xEF 0xBB 0xBF). After the invisible console window has done its job (synchronously) XYplorer will open the paper folder with the desired search results in a new tab. The status bar will show the search query that generated the results on screen, and the same query will be attached to the paper folder as a comment, for future reference. That's all, folks. -------------------------------------------------------------------------------------------------*/ // // To register the search Alias, enter the following line in the AddressBar and press Enter: // @?=::global $PRE_query; $PRE_query="<@1>"; load "\Extras\Everything in XYplorer.xys", "Find"; // // Then to search, type in AddressBar: "@? " followed by your query, e.g. "@? FindMe" // // ------------------------------------------------------------------------->>> Manage query // Flux global $PRE_query; set $CurrentPath; // ------------------------------------------------------<> If script launched from Alias in AddressBar if $PRE_query { if ($PRE_query UnLike "\*") { // Limit search to current path (or previous path searching again from paper tab) $CurrentPath = ( UnLike "paper:*")? "" : gettoken(tab("get", "name"), 1, "?"); $CurrentPath = '"'.$CurrentPath.'"'; } else { //----------------- // Search everywhere $PRE_query = trim($PRE_query, "\ "); } // ------------------------------------------------------<> If script launched manually // Marco } else { $PRE_query = input("Everything in XYplorer", "Type your search query as you would in Everything", "Everything is awesome… [it's a movie quote ツ]", "s"); } // ------------------------------------------------------<> Manage diacritics (e.g. "@? élite -d") $DiaQuery = regexreplace($PRE_query, "(^| +)-d(?=( |$))"); if ($DiaQuery != $PRE_query) { $PRE_query = $DiaQuery; $diacritics--; } $diacritics = abs($diacritics)? "diacritics:" : ""; // ------------------------------------------------------<> Manage switches $switches = trim(regexmatches($PRE_query, "((^| )-[riwps]+(?=( |$)))+")); $QueryTerms = trim(replace($PRE_query, $switches))." "; // ------------------------------------------------------<> Rebuild query $query = $CurrentPath." ".$diacritics.$QueryTerms.$switches; // -------------------------------------------------------------------------<<< // ------------------------------------------------------------------------->>> Marco $id = "$query"; if ("$mode" == "Smart") { $query = regexreplace("$query", '\B-(?!([riwps]|n (?!\D))\b)', '"-"'); } elseif ("$mode" == "Total") { $query = replace("$query", '-', '"-"'); }; // Flux: Removed escaping of "quotes", used when limiting search to current folder $query = replacelist("$query", '< > & | ^', '^< ^> ^& ^| ^^', " "); /* writefile("\$paper", hexdump("EFBBBF", , "ri"), , "b"); run "cmd /c chcp 65001 && es $query >> ""\$paper""", "$path", 2, 0; tab("new", "paper:$paper"); tag "$id", "\$paper", 2; status "$paper [$id]"; */ // -------------------------------------------------------------------------<<< // ------------------------------------------------------------------------->>> Flux $results = runret("cmd /c es $query", "$path"); if $results { // ------------------------------------------------------<> Wrong use of switches if ($results Like "-*") { msg "Wrong use of switches. ";// TODO list switches // ------------------------------------------------------<> Display results } elseif ($results UnLike "Everything*") { tab("new"); paperfolder("\$paper", $results, , "nls"); tab("rename", replace($CurrentPath."? ".$QueryTerms, '"')); if (get("View") != 0) {#302;} // setcolumns("Path.200, Name.350", 4); // Maybe useless with newer XY status "$query"; // ------------------------------------------------------<> Everything.exe was not loaded } else { run """$path\Everything.exe""", , 0, 0; // run """$path\Everything.exe"" -svc", , 0, 0; // Service, may be needed under...? status "... Loading Everything, please wait ..."; wait 5000; // Give Everything some headroom to start rebuilding its db msg "Everything was not loaded. Please restart the query. "; } // ------------------------------------------------------<> Nothing found } else { msg "$CurrentPath $PRE_query Not found. "; } // ------------------------------------------------------<> Automatically purge obsolete (not opened) papers foreach ($EverythingPaper, replace(listfolder(, gettoken($paper, 1, "_"), 5), ".txt")) { if ((get("tabs")."|".get("tabs", , "i")) UnLike "*$EverythingPaper*") { delete 0, 0, "\".$EverythingPaper.".txt"; } } // -------------------------------------------------------------------------<<< "Purge|:del : Purge"/*############################################################################# The purpose of this subscript is to delete all the paper folders generated by Everything in Xyplorer. -------------------------------------------------------------------------------------------------*/ /*CUSTOMIZATIONS.################################################################################## Here only one parameter can be customized: $regex: a regular expression matching the name of the paper folder(s). It must match the structure of $paper defined above AND match an entire full path! -------------------------------------------------------------------------------------------------*/ $regex = "^.*?Everything in XYplorer#\d{14}\.txt$"; //"^.*?Everything in XYplorer#\d{14}\.txt$" /*GO!############################################################################################## A simple one-liner. A (non-recursive) folder report of is generated, and then only the items (files) matching the regular expression above are passed to the delete command. Deletion is performed without any warning and without using the Recycle Bin. -------------------------------------------------------------------------------------------------*/ delete 0, 0, regexmatches(folderreport("items", "r", ""), "$regex");