class SikulixRunner extends AbstractRunner {

  public static final String NAME = "Sikulix";
  public static final String TYPE = "directory/sikulix";

  private AbortableScriptRunnerWrapper wrapper = new AbortableScriptRunnerWrapper();

  @Override
  public boolean isSupported() {
    return true;
  }

  @Override
  public String getName() {
    return NAME;
  }

  @Override
  public String[] getExtensions() {
    return new String[0];
  }

  @Override
  public String getType() {
    return TYPE;
  }

  @Override
  public boolean canHandle(String identifier) {
    File file = new File(identifier);

    if (file.isDirectory()) {
      File innerScriptFile = Runner.getScriptFile(file);
      return null != innerScriptFile;
    }

    return false;
  }

  @Override
  protected int doRunScript(String scriptFolder, String[] scriptArgs, IRunner.Options options) {<FILL_FUNCTION_BODY>}

  public EffectiveRunner getEffectiveRunner(String scriptFileOrFolder) {
    File scriptFile = new File(scriptFileOrFolder);
    File innerScriptFile = Runner.getScriptFile(scriptFile);
    if (null != innerScriptFile) {
      String innerScriptFilePath = innerScriptFile.getAbsolutePath();
      return new EffectiveRunner(Runner.getRunner(innerScriptFilePath), innerScriptFilePath, true);
    }
    return new EffectiveRunner(null, null, false);
  }

  @Override
  public boolean isAbortSupported() {
    return wrapper.isAbortSupported();
  }

  @Override
  protected void doAbort() {
    wrapper.doAbort();
  }
}

    EffectiveRunner runnerAndFile = getEffectiveRunner(scriptFolder);
    IRunner runner = runnerAndFile.getRunner();
    String innerScriptFile = runnerAndFile.getScript();
    if (null != runner) {
      try {
        wrapper.setRunner(runner);
        return runner.runScript(innerScriptFile, scriptArgs, options);
      } finally {
        wrapper.clearRunner();
      }
    }
    return Runner.FILE_NOT_FOUND;
  
<methods>public non-sealed void <init>() ,public final void abort() ,public boolean canHandle(java.lang.String) ,public final boolean canHandleFileEnding(java.lang.String) ,public void checkAndSetConsole() ,public final void close() ,public boolean consoleChecked() ,public void consoleChecked(boolean) ,public final int evalScript(java.lang.String, org.sikuli.support.runner.IRunner.Options) ,public void execAfter(java.lang.String[]) ,public void execBefore(java.lang.String[]) ,public java.lang.String getDefaultExtension() ,public org.sikuli.support.runner.IRunner.EffectiveRunner getEffectiveRunner(java.lang.String) ,public java.lang.String[] getFileEndings() ,public final boolean hasExtension(java.lang.String) ,public final void init(java.lang.String[]) throws org.sikuli.script.SikuliXception,public boolean isAbortSupported() ,public final boolean isAborted() ,public final boolean isReady() ,public final boolean isRunning() ,public boolean isSupported() ,public final void redirect(java.io.PrintStream, java.io.PrintStream) ,public final void reset() ,public final void runLines(java.lang.String, org.sikuli.support.runner.IRunner.Options) ,public final int runScript(java.lang.String, java.lang.String[], org.sikuli.support.runner.IRunner.Options) ,public void setConsole(java.lang.Object) <variables>public static final int NOT_SUPPORTED,private static final java.util.concurrent.ScheduledExecutorService TIMEOUT_EXECUTOR,private static final java.lang.Object WORKER_LOCK,private boolean aborted,static ArrayList<java.lang.String> codeAfter,static ArrayList<java.lang.String> codeBefore,private java.lang.Object console,private boolean consoleChecked,private boolean ready,private boolean running,private static volatile java.lang.Thread worker