Created
October 10, 2016 06:46
-
-
Save zhaocai/fe976e635bd5751f57917e18e21e62d5 to your computer and use it in GitHub Desktop.
Everything in XYplorer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* CUSTOMIZATIONS | |
------------------------------------------------------------------------------------------------- | |
$path: the path of the folder containing the es.exe executable, with a final | |
slash. | |
$paper: the base name of the paper folder containing the search results, without | |
extension; | |
$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". | |
$ipc: if set to TRUE the availability of Everything via IPC is tested, i.e. the | |
script checks whether es.exe can successfully communicate with Everything and | |
obtain search results, and starts Everything service and client if not. | |
$diacritics: if set to TRUE it matches diacritical marks, therefore a ≠ à. This | |
behaviour can be temporarily overridden with the custom switch "-d". | |
$loc_aware: if set to TRUE it limits the scope of search to the current location | |
and all its subfolders. This behaviour can be temporarily overridden with the | |
custom switch "-l". | |
Note: the custom switches above must be placed at the very start of the query in | |
order to be recognized, and the last letter must be followed by a blank space. | |
They can be compounded and order doesn't matter, so "-dl " = "-ld ". However | |
each letter must not be repeated, so "-ll " is not valid syntax. | |
$unicode: if set to TRUE it tells es.exe to always output the search results to | |
an output file. If set to FALSE instead (default), the script will try to read | |
the search results from memory first, but if it finds question marks (the sign | |
of the presence of unrecognized Unicode characters) it will trigger the search a | |
second time, effectively falling back to a TRUE status of the parameter and | |
roughly doubling the execution time. Useful for people who rarely deal with CJK | |
characters and can thus gain some speed, especially on low-end machines. | |
*/ | |
$path = "%ProgramW6432%\Everything\"; //"<xypath>\..\Everything\" | |
$paper = "Everything"; //"Everything in XYplorer" | |
$mode = "Total"; //"Smart" | |
$ipc = FALSE; //FALSE | |
$loc_aware = FALSE; //TRUE | |
$diacritics = TRUE; //TRUE | |
$unicode = TRUE; //FALSE | |
/* Main | |
------------------------------------------------------------------------------------------------- | |
First of all a test is made to make sure that es.exe can obtain results from | |
Everything. A simple call is made: cmd /c es * -n 1 This asks for just one file, | |
with no conditions at all on its name. This is easier than matching against the | |
four possible error messages provided by es.exe, i.e. (according to its source | |
code) | |
Everything IPC service not running. Everything IPC | |
window not found, IPC unavailable. failed to register | |
IPCTEST window class failed to create IPCTEST window | |
Then the output obtained via runret() is matched against a very simple | |
expression consisting of any capital letter of the Latin alphabet followed by a | |
colon and then anything. This is because Everything could return just "C:", | |
perfectly valid path for the system drive. If nothing can be matched it means | |
either Everything database is empty or there is some problem with the IPC | |
interface. Both can be usually solved by simply starting Everything service and | |
Everything client, and so the script will take care of both, repeating the steps | |
if necessary until it gets one result. | |
After that, the $query variable is declared global: doing so a search query can | |
be fed from an external source, for example a call via an alias. A special | |
boolean variable is declared as well, that will help during the validation of | |
the search query. | |
The user is asked to enter the search query if not done before, then custom | |
switches are searched for. The approach consists in isolating whatever matches | |
the regular expression "^-[dl]* " first, and then counting the occurences of | |
each letter in it. If a letter is found more than once the whole match is | |
dismissed, i.e. it is not considered a switch or a composition of switches. | |
Otherwise it is kept in memory and removed from the query. If what remains of | |
the query is not an empty, then the query itself is valid and the script can go | |
on (remember that an empty query tells Everything to list its full database, | |
which is usually huge and causes a system slowdown). While an approach with | |
foreach() loops might be deemed as overkill for just two letters, it can be | |
expanded very easily in the future (linear complexity), should more switches be | |
needed. | |
The custom switches can now perform their action. Their overriding action | |
against the parameters defined on top is calculated with a XOR operation. To | |
confine a search to the current path, this is appended to the query as: | |
"Shall we dance" AND path:"G:\Movies" | |
The current path is retrived via <curpath>. If it contains the string "paper:" | |
it means a paper folder is currently browsed: no standard path can be obtained, | |
so location-awareness is disabled and the search will be system-wide. Otherwise | |
the current path is processed to resolve all the junctions in it (because | |
Everything works with the real paths). Diacritics can be matched simply by | |
enclosing the query like this: | |
diacritics:(háček façade Pokémon) | |
Parentheses are not mandatory, but they can never hurt so there they are. | |
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. | |
There are two possibilities: the search results will either contain or not | |
Unicode characters. | |
The first case is the cleanest one, since search results can be retrieved | |
directly from memory via runret(). This mode is enabled when $unicode is set to | |
FALSE (as per user choice) AND there are no Unicode characters in the query (the | |
reason is pretty obvious). This is the best-guess scenario possible for a | |
"disk-less" execution, however there could still be Unicode characters in the | |
results. | |
If this is the case, the codepage of the console must be changed to 65001 | |
(UTF-8) with the chcp command. 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 ( && ) and the results will be written on disk to an | |
output file ( >> ). Cases for which this type of execution is necessary are: - | |
questions mark, which are the sign of the presence of Unicode characters, were | |
found with the "disk-less" approach; - the $results variable is empty, either | |
because the user set $unicode to TRUE, effectively skipping the faster execution | |
above, or because Unicode characters were found in the query, again effectively | |
skipping the faster execution. | |
The console will write to disk a list of matches encoded in UTF-8 without BOM. | |
However the absence of a BOM causes the generation of 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). | |
Now the paper folder can be opened. If another, non-paper tab is focused, a new | |
tab will be opened, otherwise the current tab is overwritten. Finally, the | |
status bar will show the search query as Everything would have seen it, i.e. | |
with no special character escapings. | |
And that's all, folks. | |
*/ | |
/*IPC TEST.######################################################################################## | |
-------------------------------------------------------------------------------------------------*/ | |
if ($ipc) { | |
while (runret("cmd /c es * -n 1", "$path") UnLike "[A-Z]:*") { | |
if (confirm("Everything in XYplorer can't work properly because Everything service and client are not running.<crlf 2>Click OK to start Everything service (a UAC prompt will appear) and client now.")) { //translatable | |
$time = 7; | |
run "cmd /c start """" /separate /wait Everything -svc", "$path", 2, 0; | |
while ($time > 5) { | |
status "Everything in XYplorer is starting Everything service, please wait $time seconds…", , "progress"; //translatable | |
wait 10; | |
$time = $time - 0.01; | |
}; | |
run "Everything -startup", "$path", 0, 0; | |
while ($time <= 5 AND $time >= 0) { | |
status "Everything in XYplorer is starting Everything client, please wait $time second". ($time == 1) ? "" : "s" ."…", , "progress"; //translatable | |
wait 10; | |
$time = $time - 0.01; | |
}; | |
} else { | |
end TRUE; | |
}; | |
}; | |
}; | |
/*QUERY DECLARATION AND VALIDATION.################################################################ | |
-------------------------------------------------------------------------------------------------*/ | |
global $query; set $valid; | |
while (NOT $valid) { | |
while ($query == "") { | |
$query = trim(input("Everything in XYplorer", "Type your search query as you would in Everything", "Everything is awesome… [it's a movie quote ツ]", "s")); //translatable | |
}; | |
$start = now("yyyy-mm-dd hh:nn:ss.ffff"); | |
$switches = formatlist(regexmatches("$query", "^-[ld]* "), "p", "<crlf>"); | |
if ("$switches" != "") { | |
foreach ($switch, "l|d") { | |
if (gettokenindex("$switch", "$switches", "<crlf>", "c") > 1) { | |
$switches = ""; | |
break; | |
}; | |
}; | |
}; | |
$query = trim(substr("$query", strlen(replace("$switches", "<crlf>")))); | |
$valid = ($query == "") ? FALSE : TRUE ; | |
}; | |
/*TRANSLATION OF CUSTOM SWITCHES.################################################################## | |
-------------------------------------------------------------------------------------------------*/ | |
$current_path = ("<curpath>" Like "*paper:*") ? "*" : property("#ResolveJunctionsAll", "<curpath>"); | |
$query = ($loc_aware XOR ($switches Like "*l*")) ? "$query AND path:""$current_path""" : "$query"; | |
$query = ($diacritics XOR ($switches Like "*d*")) ? "diacritics:$query" : "$query"; | |
/*ESCAPING OF MINUS SIGNS AND OTHER PARTICULAR CHARACTERS.######################################### | |
-------------------------------------------------------------------------------------------------*/ | |
if ("$mode" == "Smart") { | |
$cl = regexreplace("$query", '\B-(?!([riwps]|n (?!\D))\b)', '"-"'); | |
} elseif ("$mode" == "Total") { | |
$cl = replace("$query", '-', '"-"'); | |
}; | |
$cl = replacelist("$cl", '< > & | ^ "', '^< ^> ^& ^| ^^ \"', " "); | |
$middle = now("yyyy-mm-dd hh:nn:ss.ffff"); | |
/*NON-UNICODE, "DISK-LESS" METHOD.################################################################# | |
-------------------------------------------------------------------------------------------------*/ | |
if (NOT $unicode AND NOT isunicode("$cl")) { | |
$results = runret("cmd /c es.exe $cl", "$path"); | |
}; | |
/*UNICODE METHOD WITH OUTPUT REDIRECTION.########################################################## | |
-------------------------------------------------------------------------------------------------*/ | |
if ($unicode OR ($results Like "*[?]*") OR NOT isset($results)) { | |
writefile("<xypaper>\$paper.txt", hexdump("EFBBBF", , "ri"), , "b"); | |
run "cmd /c chcp 65001 && es.exe $cl >> ""<xypaper>\$paper.txt""", "$path", 2, 0; | |
unset $results; | |
}; | |
/*RESULTS PRESENTATION.############################################################################ | |
-------------------------------------------------------------------------------------------------*/ | |
$finish = now("yyyy-mm-dd hh:nn:ss.ffff"); | |
if (tab("get", "path") != "paper:$paper") { | |
tab("new"); | |
}; | |
paperfolder("paper:$paper", "$results", , isset($results) ? "n" : "" . "l"); | |
status "Everything in XYplorer [". datediff("$start", "$middle", "us")/1000 . "+" . datediff("$middle", "$finish", "us")/1000 ." ms]: $query"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Search string X Y works ok
Search string X Y Z does not