function OnInit(d){ /* This script relies on David Carpenter's excellent Everything search utility being installed and in use. It uses the associated command line interface module to pass user supplied search parameters to Everything. The resultant list of matching items is imported to Directory Opus as a collection. Sample button commands: 1. $es 2. $es "/profile\dropbox" file: dm:thismonth 3. $es "/mydocuments" file: dm:thisweek <*.jpg|*.png> 4. $es file: dm:thisyear monthly ext:xls;doc 5. $es file: dm:thisyear monthly ext:xls;doc -p 6. $es file: dm:thisyear monthly ext:xls;doc -w 7. $es -r v[23].[0-9].+xls __promptuser 8. $es "/appdata" ext:log __viewnewest 1. Will prompt the user to modify a default set of search arguments. Default arguments are set in Preferences. 2. For normal (non-regex) searches, aliases are resolved. This example will list all dropbox files modified this month. 3. Search keys can be grouped using <> brackets. This will list all JPG and PNG files in My Documents modified this week. 4. This will list all files modified this year which include the string "monthly" and an extension of XLS or DOC in the name. 5. This will list all files modified this year which include the string "monthly" and an extension of XLS or DOC anywhere in the filepath. 6. This will list all files modified this year which include the word "monthly" and an extension of XLS or DOC in the name. 7. Use the -r keyword to enable regex. In this example the __promptuser switch will prompt the user to modify the supplied regex. 8. This will list all LOG files in %APPDATA% and show the most recent log file in the viewer pane. See https://www.voidtools.com/support/everything/searching/ for all search options. See https://www.voidtools.com/downloads/ for Everything and es.exe downloads. Use the shift modifier to force a prompt. By default every successful search ovewrites an existing collection. Use the ctrl modifier to force append. */ d.name = "$es"; d.desc = "Use es.exe as a front end to Everything to generate a collection of matching items."; d.copyright = "aussieboykie"; d.version = "1.7"; d.default_enable = true; // v1.0 February 29th, 2016 // v1.1 March 1st, 2016 - Fix switchesonly routine loop to start from 0, not 1. // v1.2 March 2nd, 2016 - Fix resolution of tmp_cmd and tmp_out. // v1.2 March 2nd, 2016 - Replace switchesonly with generic allinset routine. // v1.3 March 8th, 2016 - Use /appdata instead of /homeroot for tmp_cmd and tmp_out. // v1.3 March 8th, 2016 - Protect against inadvertent deselection. // v1.3 March 8th, 2016 - Add __promptuser and __viewnewest switches and associated code. // v1.4 March 10th, 2016 - Add __update switch. // v1.4 March 10th, 2016 - Process switches case independently - e.g. __promptuser or PromptUser treated the same. // v1.4 March 10th, 2016 - Allow layout of collection columns via script configuration. // v1.4 March 10th, 2016 - Make temp file location configurable. Default to /temp if not configured. // v1.4 March 10th, 2016 - Extend placement default to disable all panels - e.g. tree, viewer, etc. // v1.4 March 10th, 2016 - Add default post DOpusRT delay and ability to adjust via script configuration. // v1.5 March 11th, 2016 - Fix missing comma before "norm" in def_placement. // v1.6 March 14th, 2016 - Use codepage 1252 in generated DOS command to handle non-ASCII characters in file names. // v1.6 March 14th, 2016 - Needed to remove /utf8 option from DOpusRT import as part of the same fix. // v1.6 March 14th, 2016 - See http://www.dostips.com/forum/viewtopic.php?f=3&t=3268 for an explanation. // v1.7 February 15th, 2017 - Repair invalid d.func.command.results.newtabs(0).tabs(0) statement (remove .tabs(0)) // v1.7 February 15th, 2017 - Add Code Page configuration option var cmd = d.AddCommand(); cmd.name = d.name; cmd.method = d.name; cmd.desc = d.desc; cmd.label = d.name; // Catch all for whatever arguments the user types. Not actually used for anything in this version. cmd.template = "__promptuser/s,__update/s,__viewnewest/s,m/m"; // Define defaults for things the user can configure via Preferences --> Scripts var cfg = new CfgHelper(d); var def_tracelevel = 1; // Default "other log" trace level. The bigger the number the more log messages. var def_espath = "/programfilesx86\\everything"; // Default path to search for es.exe var def_tmppath = "/temp"; // Default path for temp files var def_code_page = "1252"; var def_delay = 250; // Default delay in milliseconds var def_searchcriteria = 'file: dm:thisweek|dm:lastweek "/mydocuments"'; // Default search criteria // Where and how to open the Everything collection - default is a new lister with no panels var def_placement = "NEW=noviewpane,notree,nodual,noutilitypanel,nometapane,norm"; var def_columns = ""; // Default columns layout for collection var str = "Debug trace verbosity level - e.g. 1, 2, 3, etc."; str = str + "\n A higher value exposes more trace messages. Set to 0 to disable." cfg.add("def_tracelevel",def_tracelevel,str); str = "Where to look for es.exe executable."; cfg.add("def_espath",def_espath,str); str = "Where to write temp files."; cfg.add("def_tmppath",def_tmppath,str); str = "Default code page."; cfg.add("def_code_page",def_code_page,str); str = "Delay in milliseconds after DOpusRT /import."; cfg.add("def_delay",def_delay,str); str = "Default editable search criteria to be passed to Everything."; cfg.add("def_searchcriteria",def_searchcriteria,str); str = "Where and how to open the resultant Everything collection."; cfg.add("def_placement",def_placement,str); str = "Which columns to display in the Everything collection."; str = str + "\n If this field is left blank the user's default Collection format will be used." cfg.add("def_columns",def_columns,str); function CfgHelper(d){ // Based on original code by @tbone at http://resource.dopus.com/viewtopic.php?f=35&t=22979 this.d = d; this.name = null; if (d.config_desc==undefined) d.config_desc=DOpus.Create.Map(); this.add = function(name, val, description){ if (name==undefined) return this; // if name not supplied, exit immediately this.name=name; // needed later to add corresponding value(s) and/or description return this.addval(val).setdesc(description); } this.addvec = function(name){ if (name==undefined) return this; // if name not supplied, exit immediately this.name=name; // needed later to add corresponding value(s) and/or description return this.addval(DOpus.Create.Vector); // create an empty vector } this.addval = function(val){ if (this.name==undefined) return this; // need to add value to something if (typeof this.d.config[this.name]=="object") { if (val!=undefined) this.d.config[this.name].push_back(val); } else this.d.config[this.name]=(val==undefined)?false:val; // default value = FALSE return this; } this.setdesc = function(description){ if (this.name==undefined) return this; // need to add description to something d.config_desc(this.name)=(description==undefined)?null:description; return this } } } function $es(d){ d.func.command.deselect = false; // Output the supplied command line Trace("Original command line = " + d.cmdline,1); // If it's not already present, add a trim() method to the JScript String prototype if(!String.prototype.trim) String.prototype.trim = function(){return this.replace(/^\s+|\s+$/g,'');}; // First locate the Everything CLI (es.exe) which will be used to trigger an Everything search later var es_app = "es.exe"; var es_spec = findes(es_app); if (es_spec=="") abort("Unable to locate" + es_app); Trace("es.exe located in " + es_spec,1); var es_path = DOpus.FSUtil.getitem(es_spec).path; // Isolate any supplied arguments var n = d.cmdline.trim().indexOf(" "); var es_args = (n>=0) ? d.cmdline.trim().slice(n) : ""; // Deal with any Opus switches var promptuser = (d.func.args.got_arg.__promptuser) ? d.func.args.__promptuser : false; if (promptuser) es_args = es_args.replace(/ __promptuser/i,""); var update = (d.func.args.got_arg.__update) ? d.func.args.__update : false; if (update) es_args = es_args.replace(/ __update/i,""); var viewnewest = (d.func.args.got_arg.__viewnewest) ? d.func.args.__viewnewest : false; if (viewnewest) es_args = es_args.replace(/ __viewnewest/,""); // Determine if remaining arguments are regex arguments var searchcriteria = es_args.trim(); var s = " " + searchcriteria + " "; var isregex = (s.indexOf(" -r ")>=0); // Qualifiers may be used to force prompt (shift) and/or collection update (ctrl) var promptuser = ((promptuser) || (d.func.qualifiers.indexOf("shift")>=0)); var updatecoll = ((update) || (d.func.qualifiers.indexOf("ctrl")>=0)); Trace("promptuser = " + promptuser,1); Trace("updatecoll = " + updatecoll,1); // Populate or update es_args by means of a user prompt, if required if ((promptuser) || (es_args=="")) { if (isregex) searchcriteria = (searchcriteria=="") ? Script.config.def_regexcriteria.trim() : searchcriteria; else searchcriteria = (searchcriteria=="") ? Script.config.def_searchcriteria.trim() : searchcriteria; var dlg = DOpus.dlg; var dlgbutton = (updatecoll) ? 2 : 1; // Determine whether to replace collection or add to an existing collection dlg.buttons = "Replace|Append|Cancel"; dlg.defid = dlgbutton; dlg.max = 0; dlg.defvalue = searchcriteria; dlg.select = true; dlg.title = "Everything Search"; var str = "Specify search criteria:\n"; str = str + "\n-r Regular expression search."; str = str + "\n-i Case sensitive search."; str = str + "\n-w Whole word search."; str = str + "\n-p Full path search."; str = str + "\n-n Limit to first results."; dlg.message = str; // Prompt the user for search criteria dlgbutton = dlg.show; Trace("dlgbutton = " + dlgbutton,2); if (dlgbutton==0) return false; updatecoll = (dlgbutton==2) ? true : updatecoll; searchcriteria = dlg.input.trim(); } Trace("updatecoll = " + updatecoll,1); // Do nothing if only switches were provided if (allinset(searchcriteria,["-r","-i","-w","-p","-n","-s","-h","--help"])) return false;; Trace("Search Criteria = " + searchcriteria,1); // regex: is treated as a special case s = " " + searchcriteria + " "; isregex = (s.indexOf(" -r ")>=0); searchcriteria = (isregex) ? regex(searchcriteria) : normal(searchcriteria); Trace("Transformed search criteria = " + searchcriteria,1); // Prepare to execute search var a = d.cmdline.split(" "); s = a.shift(); var tmp_path = Script.config.def_tmppath; var code_page = Script.config.def_code_page; Trace("code_page = " + code_page,1); Trace("typeof code_page = " + typeof code_page,1); if (code_page=="") code_page = "1252"; tmp_path = (tmp_path=="") ? String(DOpus.FSUtil.Resolve("/temp")) : String(DOpus.FSUtil.Resolve(tmp_path)); Trace("tmp_path = " + tmp_path,2); var tmp_cmd = String(DOpus.FSUtil.Resolve(tmp_path + "\\" + s + ".cmd")); var tmp_out = String(DOpus.FSUtil.Resolve(tmp_path + "\\" + s + ".out")); // Execute search var tmp_size = runshell(es_app + " " + searchcriteria,es_path,tmp_cmd,tmp_out,code_page) // Test to see if the search generated any output if (tmp_size==0) return false; // Create or update the collection cmdstring = "/home\\dopusrt.exe /col import "; cmdstring = (updatecoll) ? cmdstring : cmdstring = cmdstring + "/clear "; cmdstring = cmdstring + "/create everything " + '"' + tmp_out + '"'; Trace("DOpusRT import command = " + cmdstring,3); d.func.command.runcommand(cmdstring); // Inject a short delay after the DOpusRT import // Without a delay GO is ok but the subsequent SELECT operation is unreliable var delay = (typeof Script.config.def_delay=="number") ? Script.config.def_delay : 500; DOpus.delay(delay); cmdstring = "Go Coll://Everything " + Script.config.def_placement + " USEQUALKEYS"; Trace("cmdstring = " + cmdstring,3); d.func.command.runcommand(cmdstring); if (0 characters cmdstring = cmdstring.replace(/\/g,'^>'); return cmdstring; } function regex(searchcriteria){ // Need to escape some characters for regex to work // Not sure if the following transformations cover all situations var a = searchcriteria.split(""); for (var i = 1; i < a.length; i++){ switch(a[i]) { case "|": a[i] = "^" + a[i]; break; case ">": a[i] = "^" + a[i]; break; case "<": a[i] = "^" + a[i]; break; case "^": a[i] = "^" + a[i]; break; default: } } return a.join(""); } function resolvealiases(str){ // Attempt to resolve any supplied aliases such as /mydocuments, /programfiles, etc. if (str.length==0) return str; // Nothing to do var a = str.split("/"); if (a.length==1) return str; // Nothing to do var n, s; Trace("str (1) = " + str,3,false,"resolvealiases") for (var i = 1; i < a.length; i++) { Trace("a[" + i + "] = " + a[i],4,false,"resolvealiases"); // Alias can be terminated by a space, or a single or double quote, or a backslash n = a[i].search(/[ '"\\]/); Trace("n = " + n,4,false,"resolvealiases"); // Isolate the alias s = (n<0)?a[i]:a[i].substr(0,n); Trace("s = " + s,4,false,"resolvealiases"); // Resolve the alias s = DOpus.FSUtil.Resolve("/" + s); Trace("s = " + s,4,false,"resolvealiases"); // Replace the alias with its resolved path a[i] = (n<0)?s:s + a[1].substring(n); Trace("a[i] = " + a[i],4,false,"resolvealiases"); } Trace("str (2) = " + a.join(""),3,false,"resolvealiases") return a.join(""); } function resolvedir(str){ return resolvespec(str,type="d"); } function resolvefile(str){ return resolvespec(str,type="f"); } function resolvespec(str,type){ var resolved = String(DOpus.FSUtil.Resolve(str)); if (resolved=="") return ""; if (!DOpus.FSUtil.Exists(resolved)) return ""; var item = DOpus.FSUtil.GetItem(resolved); switch(type){ case "d": Trace("Folder = " + resolved,4,false,"resolvespec"); return (item.is_dir)?resolved:""; case "f": Trace("File = " + resolved,4,false,"resolvespec"); return (!item.is_dir)?resolved:""; default: Trace("Item = " + resolved,4,false,"resolvespec"); return resolved; } } function runshell(doscmd,cd,tmp_cmd,tmp_out, code_page){ // Builds and executes a DOS command var fso = new ActiveXObject("Scripting.FileSystemObject"); Trace("tmp_cmd = " + tmp_cmd,2,false,"runshell"); var f = fso.CreateTextFile(tmp_cmd,true); var a =[]; a[a.length] = "pushd " + cd; a[a.length] = "chcp " + code_page; a[a.length] = doscmd + " > " + tmp_out; a[a.length] = "popd"; for (i = 0; i < a.length; i++) f.WriteLine(a[i]); f.Close(); var objWShell = new ActiveXObject("WScript.Shell"); objWShell.Run("cmd /c " + tmp_cmd, 0, true); // First check to see if the search generated any output return (DOpus.fsutil.exists(tmp_out)) ? DOpus.fsutil.getitem(tmp_out).size : 0; } function Trace(str,level,err,fn){ // Output supplied text if it is flagged as an error message or trace level is within current def_tracelevel limit. e.g. // Trace("This is an error message and will always print",1,true) // Trace("This will print if def_tracelevel is greater than zero") // Trace("This will print if def_tracelevel is greater than zero",1) // Trace("This will print if def_tracelevel is greater than one",2) var err = (err==undefined)?false:err; var level = (level==undefined)?1:level; var s = (err)?"error: ":"info(" + level + "): "; // Use (optional) fn to prefix message with calling function name. e.g. // Trace("Quick 'n Dirty",1,false,"qnd") ==> info(1): (qnd): Quick 'n Dirty s = (fn==undefined)?s:s + "(" + fn + "): " if (level<=Script.config.def_tracelevel || err) DOpus.Output(s + str,err); }