Run a script when opening a directory if a file exists in that directory

I've recently discovered File Types feature.

It seems like a good place to place a dopus script (which I'm quite novice at) that allows me to run a powershell/python script by passing the path of the folder that I'm clicking onto to it.

Default action/script is just

go

which traverses into the folder.
I want to run a script before/after it.

@async myscript {sourcepath} 
go

and possibly only run the command if a file exists in that folder. Kinda like how autorun files used to work.

@ifexists:{dirImClickingInto}/afile.ext
@async myscript {dirImClickingInto}
@end ?
go

I tried using {sourcepath} and {file} arguments, but {sourcepath} gives me the parent folder.

How can I achieve such a task? Does using File Type scripts even make sense?

Oh, ok, if I run the script after I go into the folder, {sourcepath} gives me the correct path.

I would leave the file type double-click as it was, and instead use the OnAfterFolderChange scripting event.

1 Like

Oh that's really cool. I'll look into it :+1:
Thanks a lot

I've managed to build the script. I used WScript Shell to run the command, but I'm having trouble getting the script window to stay open. It closes even if the script is waiting for an input from stdin. Any pointers?

// autorun.js

// Called by Directory Opus to initialize the script
function OnInit(initData) {
	initData.name = "autorun";
	initData.version = "1.0";
	initData.copyright = "(c) 2020 923044";
	//	initData.url = "https://resource.dopus.com/c/buttons-scripts/16";
	initData.desc = "";
	initData.default_enable = true;
	initData.min_version = "12.0";
}

/**
 * Dump given string to Directory Opus console
  */
function log(what) {
	DOpus.Output(what);
}

/**
 * A clone of Array.map
  */
function map(collection, mapper) {
	var items = [];
	var iter = new Enumerator(collection);
	while (!iter.atEnd()) {
		var item = iter.item();
		if (mapper !== undefined) {
			item = mapper(item);
		}
		items.push(item);
		iter.moveNext()
	}

	return items;
}

/**
 * Filter elements by regex
 * @param items {string[]} array of items
 * @param pattern {RegExp} pattern
  */
function filterByRegex(items, pattern) {

	var filtered = [];
	for (var index = 0; index < items.length; index++) {
		var item = items[index];
		if (pattern.test(item)) {
			filtered.push(item);
		}
	}
	return filtered;
}

/**
 * A clone of Array.join
  */
function join(array, glue) {
	var joined = "";
	for (var i = 0; i < array.length; i++) {
		var item = array[i];
		joined += item;
		if (i < array.length) {
			joined += glue;
		}
	}

	return joined;
}

/** 
 * @param path {string} path to script
 * @param opts {{cwd?: string, args?: string[]}}
*/
function runScript(path, opts) {
	var cwd = (opts || {}).cwd;
	var shell = new ActiveXObject("WScript.Shell");
	if (cwd !== undefined) {
		shell.CurrentDirectory = cwd;
	}
	var args = opts.args || [];
	argsStr = join(map(args, function (it) { return '"' + it + '"' }), " ");

	if (/\.py/.test(path)) {
		shell.Exec('python.exe ' + path + " " + argsStr);
	}
	if (/\.ps1/.test(path)) {
		shell.Exec('powershell.exe -file ' + path + " " + argsStr);
	}
}

/**
 * @param e {OnAfterFolderChange} event
  */
function logEvent(e) {
	var action = e.action;
	var path = e.tab.path + "";
	var files = map(e.tab.files, function (it) { return it.name });
	var autoruns = filterByRegex(files, /^\.autorun/);

	var payload = {
		path: path,
		autoruns: autoruns,
		action: action,
		files: files,
	}

	log(JSON.stringify(payload, null, 4));
}

// Called after a new folder is read in a tab
function OnAfterFolderChange(e) {
	var path = e.tab.path + "";
	var files = map(e.tab.files, function (it) { return it.name });
	var autoruns = filterByRegex(files, /^\.autorun/);
	if (autoruns.length) {
		runScript(autoruns[0], { args: [path], cwd: path });
	}
}

here's a simple autorun script I have

# .autorun.py
import sys
import json

with open('log.txt', 'wt') as f:
    f.write(json.dumps(sys.argv))

input('asdasd')

which outputs passed arguments to a file:

# log.txt
[".autorun.py", "D:\\_dev\\aspnetcore\\OrchardCore\\src"]

Opus provides a Command object which you can use to run things, including the option of running them in a command prompt (MS-DOS batch mode), which may solve things.

I love this program :heartpulse::

/** 
 * @param path {string} path to script
 * @param opts {{cwd?: string, args?: string[]}}
*/
function runScriptDopus(path, opts) {
	opts = opts || {}
	var args = opts.args || [];

	var cmd = DOpus.Create().Command();
	cmd.SetType('msdos');
	// cmd.SetModifier('leavedoswindowopen');
	if (opts.cwd !== undefined) {
		cmd.SetSource(opts.cwd);
	}

	argsStr = join(map(args, function (it) { return '"' + it + '"' }), " ");
	if (/\.py/.test(path)) {
		cmd.AddLine('python ' + path + " " + argsStr);
	}
	if (/\.ps1/.test(path)) {
		cmd.AddLine('powershell.exe -file ' + path + " " + argsStr);
	}

	cmd.Run();
}

function OnAfterFolderChange(e) {
	var path = e.tab.path + "";
	var files = map(e.tab.files, function (it) { return it.name });
	var autoruns = filterByRegex(files, /^\.autorun/);
	if (autoruns.length) {
		runScriptDopus(autoruns[0], { args: [path], cwd: path });
	}
}

I wish I could use an IDE to explore what's available to me, or it had a more modern JS support.

Any chance something like QuickJS can be integrated to Directory Opus?