[sikuli] 209/385: my first test with JRuby
Gilles Filippini
pini at moszumanska.debian.org
Sun Jun 29 19:26:14 UTC 2014
This is an automated email from the git hooks/post-receive script.
pini pushed a commit to tag upstream/1.1.0_beta1
in repository sikuli.
commit a979c5392c3e993ff7a4cb33e4a7708f6312bcac
Author: Raimund Hocke <info at its-me-raiman.de>
Date: Thu Feb 13 16:33:30 2014 +0100
my first test with JRuby
---
JRuby/pom.xml | 8 +-
.../org/sikuli/scriptrunner/JRubyScriptRunner.java | 996 ++++++++++-----------
JRuby/src/main/resources/rukuli.rb | 10 +
JRuby/src/main/resources/rukuli/app.rb | 33 +
JRuby/src/main/resources/rukuli/clickable.rb | 278 ++++++
JRuby/src/main/resources/rukuli/config.rb | 67 ++
JRuby/src/main/resources/rukuli/exception.rb | 14 +
JRuby/src/main/resources/rukuli/key_code.rb | 21 +
JRuby/src/main/resources/rukuli/platform.rb | 12 +
JRuby/src/main/resources/rukuli/region.rb | 88 ++
JRuby/src/main/resources/rukuli/screen.rb | 20 +
JRuby/src/main/resources/rukuli/searchable.rb | 134 +++
JRuby/src/main/resources/rukuli/typeable.rb | 32 +
JRuby/src/main/resources/rukuli/version.rb | 3 +
JRuby/src/main/resources/sikulix.rb | 16 +
.../sikuli/scriptrunner/JythonScriptRunner.java | 11 +-
pom.xml | 2 +-
17 files changed, 1231 insertions(+), 514 deletions(-)
diff --git a/JRuby/pom.xml b/JRuby/pom.xml
index 9ca8612..fea6a4b 100755
--- a/JRuby/pom.xml
+++ b/JRuby/pom.xml
@@ -6,7 +6,7 @@
* Copyright 2010-2014, Sikuli.org
* Released under the MIT License.
*
- * xxx, RaiMan 2014
+ * Roman S Samarev, RaiMan 2014
-->
<parent>
@@ -25,9 +25,9 @@
<developers>
<developer>
- <id>xxx</id>
- <name>yyy</name>
- <email>zzz at web.de</email>
+ <id>RomanSSamarev</id>
+ <name>Roman S Samarev</name>
+ <email>samarev at acm.org</email>
</developer>
</developers>
diff --git a/JRuby/src/main/java/org/sikuli/scriptrunner/JRubyScriptRunner.java b/JRuby/src/main/java/org/sikuli/scriptrunner/JRubyScriptRunner.java
index 9597694..5cf5730 100644
--- a/JRuby/src/main/java/org/sikuli/scriptrunner/JRubyScriptRunner.java
+++ b/JRuby/src/main/java/org/sikuli/scriptrunner/JRubyScriptRunner.java
@@ -2,7 +2,7 @@
* Copyright 2010-2014, Sikuli.org
* Released under the MIT License.
*
- * WhoIsWho 2014
+ * Roman S Samarev 2014
*/
package org.sikuli.scriptrunner;
@@ -33,511 +33,507 @@ import org.jruby.javasupport.JavaEmbedUtils.EvalUnit;
import org.jruby.CompatVersion;
import org.jruby.embed.LocalContextScope;
import org.jruby.RubyInstanceConfig.CompileMode;
-import org.jruby.embed.PathType;
public class JRubyScriptRunner implements IScriptRunner {
- //<editor-fold defaultstate="collapsed" desc="new logging concept">
- private static final String me = "JRubyScriptRunner: ";
- private int lvl = 3;
-
- private void log(int level, String message, Object... args) {
- Debug.logx(level, level < 0 ? "error" : "debug",
- me + message, args);
- }
- //</editor-fold>
-
- /**
- * The ScriptingContainer instance
- */
- private static ScriptingContainer interpreter = null;
- private static int savedpathlen = 0;
- private static final String COMPILE_ONLY = "# COMPILE ONLY";
- /**
- * sys.argv for the jruby script
- */
- private static ArrayList<String> sysargv = null;
- /**
- * The header commands, that are executed before every script
- */
- private final static String SCRIPT_HEADER
- = "# coding: utf-8\n"
- + "require 'java'\n"
- + "require 'rukuli'\n"
- + "require 'sikulix'\n"
- + "Rukuli::Config.run do |config|\n"
- + " config.image_path = SIKULI_IMAGE_PATH + '/'\n"
- + " config.logging = true\n"
- + "end\n";
-
- private static ArrayList<String> codeBefore = null;
- private static ArrayList<String> codeAfter = null;
- /**
- * CommandLine args
- */
- private int errorLine;
- private int errorColumn;
- private String errorType;
- private String errorText;
- private int errorClass;
- private String errorTrace;
-
- private static final int PY_SYNTAX = 0;
- private static final int PY_RUNTIME = 1;
- private static final int PY_JAVA = 2;
- private static final int PY_UNKNOWN = -1;
-
- private static String sikuliLibPath;
-
- private static String timestampBuilt;
- private static final String tsb = "##--##Fri Jan 28 13:06:44 MSD 2014##--##";
-
- @Override
- public void init(String[] args) {
- //TODO classpath and other path handlings
- sikuliLibPath = new File(SikuliX.getJarPath(), "Lib").getAbsolutePath();
- if (!SikuliX.isRunningFromJar()
- || !sikuliLibPath.contains("sikuli-ide")
- || !sikuliLibPath.contains("sikuli-script")) {
- if (System.getProperty("ruby.path") == null) {
- System.setProperty("ruby.path", sikuliLibPath);
- log(lvl, "init: python.path hack: \n" + System.getProperty("ruby.path"));
- } else {
- String currentPath = System.getProperty("ruby.path");
- if (!FileManager.pathEquals(currentPath, sikuliLibPath)) {
- log(-1, "init: Not running from jar and Ruby path not empty: Sikuli might not work!\n"
- + "Current python.path: " + currentPath);
- }
- }
- }
- }
-
- @Override
- public int runScript(File scriptfile, File imagedirectory, String[] scriptArgs, String[] forIDE) {
- if (null == scriptfile) {
- //run the Ruby statements from argv (special for setup functional test)
- fillSysArgv(null, null);
- createScriptingContainer();
- interpreter.put("SIKULI_IMAGE_PATH",
- imagedirectory.getAbsolutePath());
- executeScriptHeader(new String[0]);
- SikuliX.displaySplash(null);
- return runRuby(null, scriptArgs, null);
- }
- scriptfile = new File(scriptfile.getAbsolutePath());
- fillSysArgv(scriptfile, scriptArgs);
- createScriptingContainer();
- interpreter.put("SIKULI_IMAGE_PATH",
- imagedirectory.getAbsolutePath());
- if (forIDE == null) {
- executeScriptHeader(new String[]{
- scriptfile.getParentFile().getAbsolutePath(),
- scriptfile.getParentFile().getParentFile().getAbsolutePath()});
- } else {
- executeScriptHeader(new String[]{
- forIDE[0]});
- }
- int exitCode = 0;
- SikuliX.displaySplashFirstTime(null);
- SikuliX.displaySplash(null);
- if (forIDE == null) {
- exitCode = runRuby(scriptfile, null,
- new String[]{scriptfile.getParentFile().getAbsolutePath()});
- } else {
- exitCode = runRuby(scriptfile, null, forIDE);
- }
- log(lvl + 1, "runScript: at exit: path:");
- for (Object p : interpreter.getLoadPaths()) {
- log(lvl + 1, "runScript: " + p.toString());
- }
- log(lvl + 1, "runScript: at exit: --- end ---");
- return exitCode;
- }
-
- @Override
- public int runTest(File scriptfile, File imagedirectory, String[] scriptArgs, String[] forIDE) {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
- }
-
- @Override
- public int runInteractive(String[] scriptArgs) {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
- }
-
- @Override
- public String getCommandLineHelp() {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
- }
-
- @Override
- public String getInteractiveHelp() {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
- }
-
- @Override
- public String getName() {
- return "jruby";
- }
-
- @Override
- public String[] getFileEndings() {
- return new String[]{"rb"};
- }
-
- @Override
- public String hasFileEnding(String ending) {
- for (String suf : getFileEndings()) {
- if (suf.equals(ending.toLowerCase())) {
- return suf;
- }
- }
- return null;
- }
-
- @Override
- public void close() {
- if (interpreter != null) {
- interpreter.clear();
- }
- }
-
- @Override
- public boolean doSomethingSpecial(String action, Object[] args) {
- if ("redirect".equals(action)) {
- doRedirect((PipedInputStream[]) args);
- return true;
- } else if ("convertSrcToHtml".equals(action)) {
- //convertSrcToHtml((String) args[0]);
- return true;
- } else if ("cleanBundle".equals(action)) {
- //cleanBundle((String) args[0]);
- return true;
- } else if ("createRegionForWith".equals(action)) {
- //args[0] = createRegionForWith(args[0]);
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public void execBefore(String[] stmts) {
- if (stmts == null) {
- codeBefore = null;
- return;
- }
- if (codeBefore == null) {
- codeBefore = new ArrayList<String>();
- }
- codeBefore.addAll(Arrays.asList(stmts));
- }
-
- @Override
- public void execAfter(String[] stmts) {
- if (stmts == null) {
- codeAfter = null;
- return;
- }
- if (codeAfter == null) {
- codeAfter = new ArrayList<String>();
- }
- codeAfter.addAll(Arrays.asList(stmts));
- }
-
- private int runRuby(File ruFile, String[] stmts, String[] scriptPaths) {
- int exitCode = 0;
- String stmt = "";
- boolean fromIDE = false;
- String filename = "<script>";
- try {
- if (null == ruFile) {
- log(lvl, "runRuby: running statements");
- StringBuilder buffer = new StringBuilder();
- for (String e : stmts) {
- buffer.append(e);
- }
- interpreter.setScriptFilename(filename);
- interpreter.runScriptlet(buffer.toString());
- } else {
- filename = ruFile.getAbsolutePath();
- if (scriptPaths != null) {
- FileReader script = new FileReader(ruFile.getAbsolutePath());
+ //<editor-fold defaultstate="collapsed" desc="new logging concept">
+ private static final String me = "JRubyScriptRunner: ";
+ private int lvl = 3;
+
+ private void log(int level, String message, Object... args) {
+ Debug.logx(level, level < 0 ? "error" : "debug",
+ me + message, args);
+ }
+ //</editor-fold>
+
+ /**
+ * The ScriptingContainer instance
+ */
+ private static ScriptingContainer interpreter = null;
+ private static int savedpathlen = 0;
+ private static final String COMPILE_ONLY = "# COMPILE ONLY";
+ /**
+ * sys.argv for the jruby script
+ */
+ private static ArrayList<String> sysargv = null;
+ /**
+ * The header commands, that are executed before every script
+ */
+ private final static String SCRIPT_HEADER
+ = "# coding: utf-8\n"
+ + "require 'java'\n"
+ + "require 'rukuli'\n"
+ + "require 'sikulix'\n"
+ + "Rukuli::Config.run do |config|\n"
+ + " config.image_path = SIKULI_IMAGE_PATH + '/'\n"
+ + " config.logging = true\n"
+ + "end\n";
+
+ private static ArrayList<String> codeBefore = null;
+ private static ArrayList<String> codeAfter = null;
+ /**
+ * CommandLine args
+ */
+ private int errorLine;
+ private int errorColumn;
+ private String errorType;
+ private String errorText;
+ private int errorClass;
+ private String errorTrace;
+
+ private static final int PY_SYNTAX = 0;
+ private static final int PY_RUNTIME = 1;
+ private static final int PY_JAVA = 2;
+ private static final int PY_UNKNOWN = -1;
+
+ private static String sikuliLibPath;
+
+ @Override
+ public void init(String[] args) {
+ //TODO classpath and other path handlings
+ sikuliLibPath = new File(SikuliX.getJarPath(), "Lib").getAbsolutePath();
+ if (!SikuliX.isRunningFromJar()
+ || !sikuliLibPath.contains("sikuli-ide")
+ || !sikuliLibPath.contains("sikuli-script")) {
+ if (System.getProperty("ruby.path") == null) {
+ System.setProperty("ruby.path", sikuliLibPath);
+ log(lvl, "init: python.path hack: \n" + System.getProperty("ruby.path"));
+ } else {
+ String currentPath = System.getProperty("ruby.path");
+ if (!FileManager.pathEquals(currentPath, sikuliLibPath)) {
+ log(-1, "init: Not running from jar and Ruby path not empty: Sikuli might not work!\n"
+ + "Current python.path: " + currentPath);
+ }
+ }
+ }
+ }
+
+ @Override
+ public int runScript(File scriptfile, File imagedirectory, String[] scriptArgs, String[] forIDE) {
+ if (null == scriptfile) {
+ //run the Ruby statements from argv (special for setup functional test)
+ fillSysArgv(null, null);
+ createScriptingContainer();
+ interpreter.put("SIKULI_IMAGE_PATH",
+ imagedirectory.getAbsolutePath());
+ executeScriptHeader(new String[0]);
+ SikuliX.displaySplash(null);
+ return runRuby(null, scriptArgs, null);
+ }
+ scriptfile = new File(scriptfile.getAbsolutePath());
+ fillSysArgv(scriptfile, scriptArgs);
+ createScriptingContainer();
+ interpreter.put("SIKULI_IMAGE_PATH",
+ imagedirectory.getAbsolutePath());
+ if (forIDE == null) {
+ executeScriptHeader(new String[]{
+ scriptfile.getParentFile().getAbsolutePath(),
+ scriptfile.getParentFile().getParentFile().getAbsolutePath()});
+ } else {
+ executeScriptHeader(new String[]{
+ forIDE[0]});
+ }
+ int exitCode = 0;
+ SikuliX.displaySplashFirstTime(null);
+ SikuliX.displaySplash(null);
+ if (forIDE == null) {
+ exitCode = runRuby(scriptfile, null,
+ new String[]{scriptfile.getParentFile().getAbsolutePath()});
+ } else {
+ exitCode = runRuby(scriptfile, null, forIDE);
+ }
+ log(lvl + 1, "runScript: at exit: path:");
+ for (Object p : interpreter.getLoadPaths()) {
+ log(lvl + 1, "runScript: " + p.toString());
+ }
+ log(lvl + 1, "runScript: at exit: --- end ---");
+ return exitCode;
+ }
+
+ @Override
+ public int runTest(File scriptfile, File imagedirectory, String[] scriptArgs, String[] forIDE) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public int runInteractive(String[] scriptArgs) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getCommandLineHelp() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getInteractiveHelp() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getName() {
+ return "jruby";
+ }
+
+ @Override
+ public String[] getFileEndings() {
+ return new String[]{"rb"};
+ }
+
+ @Override
+ public String hasFileEnding(String ending) {
+ for (String suf : getFileEndings()) {
+ if (suf.equals(ending.toLowerCase())) {
+ return suf;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void close() {
+ if (interpreter != null) {
+ interpreter.clear();
+ }
+ }
+
+ @Override
+ public boolean doSomethingSpecial(String action, Object[] args) {
+ if ("redirect".equals(action)) {
+ doRedirect((PipedInputStream[]) args);
+ return true;
+ } else if ("convertSrcToHtml".equals(action)) {
+ //convertSrcToHtml((String) args[0]);
+ return true;
+ } else if ("cleanBundle".equals(action)) {
+ //cleanBundle((String) args[0]);
+ return true;
+ } else if ("createRegionForWith".equals(action)) {
+ //args[0] = createRegionForWith(args[0]);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void execBefore(String[] stmts) {
+ if (stmts == null) {
+ codeBefore = null;
+ return;
+ }
+ if (codeBefore == null) {
+ codeBefore = new ArrayList<String>();
+ }
+ codeBefore.addAll(Arrays.asList(stmts));
+ }
+
+ @Override
+ public void execAfter(String[] stmts) {
+ if (stmts == null) {
+ codeAfter = null;
+ return;
+ }
+ if (codeAfter == null) {
+ codeAfter = new ArrayList<String>();
+ }
+ codeAfter.addAll(Arrays.asList(stmts));
+ }
+
+ private int runRuby(File ruFile, String[] stmts, String[] scriptPaths) {
+ int exitCode = 0;
+ String stmt = "";
+ boolean fromIDE = false;
+ String filename = "<script>";
+ try {
+ if (null == ruFile) {
+ log(lvl, "runRuby: running statements");
+ StringBuilder buffer = new StringBuilder();
+ for (String e : stmts) {
+ buffer.append(e);
+ }
+ interpreter.setScriptFilename(filename);
+ interpreter.runScriptlet(buffer.toString());
+ } else {
+ filename = ruFile.getAbsolutePath();
+ if (scriptPaths != null) {
+ FileReader script = new FileReader(ruFile.getAbsolutePath());
// TODO implement compile only !!!
- if (scriptPaths[0].toUpperCase().equals(COMPILE_ONLY)) {
- log(lvl, "runRuby: running COMPILE_ONLY");
- EvalUnit unit = interpreter.parse(script, filename);
- //unit.run();
- } else {
- if (scriptPaths.length > 1) {
- filename = FileManager.slashify(scriptPaths[0], true) +
- scriptPaths[1] + ".sikuli";
- log(lvl, "runRuby: running script from IDE: \n" + filename);
- fromIDE = true;
- } else {
- filename = scriptPaths[0];
- log(lvl, "runRuby: running script: \n" + filename);
- }
- interpreter.runScriptlet(script, filename);
- }
- } else {
- log(-1, "runRuby: invalid arguments");
- exitCode = -1;
- }
- }
- } catch (Exception e) {
- java.util.regex.Pattern p
- = java.util.regex.Pattern.compile("SystemExit: ([0-9]+)");
- Matcher matcher = p.matcher(e.toString());
+ if (scriptPaths[0].toUpperCase().equals(COMPILE_ONLY)) {
+ log(lvl, "runRuby: running COMPILE_ONLY");
+ EvalUnit unit = interpreter.parse(script, filename);
+ //unit.run();
+ } else {
+ if (scriptPaths.length > 1) {
+ filename = FileManager.slashify(scriptPaths[0], true)
+ + scriptPaths[1] + ".sikuli";
+ log(lvl, "runRuby: running script from IDE: \n" + filename);
+ fromIDE = true;
+ } else {
+ filename = scriptPaths[0];
+ log(lvl, "runRuby: running script: \n" + filename);
+ }
+ interpreter.runScriptlet(script, filename);
+ }
+ } else {
+ log(-1, "runRuby: invalid arguments");
+ exitCode = -1;
+ }
+ }
+ } catch (Exception e) {
+ java.util.regex.Pattern p
+ = java.util.regex.Pattern.compile("SystemExit: ([0-9]+)");
+ Matcher matcher = p.matcher(e.toString());
//TODO error stop I18N
- if (matcher.find()) {
- exitCode = Integer.parseInt(matcher.group(1));
- Debug.info("Exit code: " + exitCode);
- } else {
- //log(-1,_I("msgStopped"));
- if (null != ruFile) {
- exitCode = findErrorSource(e, filename, scriptPaths);
- } else {
- Debug.error("runRuby: Ruby exception: %s with %s", e.getMessage(), stmt);
- }
- if (fromIDE) {
- exitCode *= -1;
- } else {
- exitCode = 1;
- }
- }
- }
- return exitCode;
- }
-
- private int findErrorSource(Throwable thr, String filename, String[] forIDE) {
- String err = thr.getMessage();
-
- errorLine = -1;
- errorColumn = -1;
- errorClass = PY_UNKNOWN;
- errorType = "--UnKnown--";
- errorText = "--UnKnown--";
-
- String msg;
-
- if (err.startsWith("(SyntaxError)")) {
+ if (matcher.find()) {
+ exitCode = Integer.parseInt(matcher.group(1));
+ Debug.info("Exit code: " + exitCode);
+ } else {
+ //log(-1,_I("msgStopped"));
+ if (null != ruFile) {
+ exitCode = findErrorSource(e, filename, scriptPaths);
+ } else {
+ Debug.error("runRuby: Ruby exception: %s with %s", e.getMessage(), stmt);
+ }
+ if (fromIDE) {
+ exitCode *= -1;
+ } else {
+ exitCode = 1;
+ }
+ }
+ }
+ return exitCode;
+ }
+
+ private int findErrorSource(Throwable thr, String filename, String[] forIDE) {
+ String err = thr.getMessage();
+
+ errorLine = -1;
+ errorColumn = -1;
+ errorClass = PY_UNKNOWN;
+ errorType = "--UnKnown--";
+ errorText = "--UnKnown--";
+
+ String msg;
+
+ if (err.startsWith("(SyntaxError)")) {
//org.jruby.parser.ParserSyntaxException
- //(SyntaxError) /tmp/sikuli-3213678404470696048.rb:2: syntax error, unexpected tRCURLY
-
- Pattern pLineS = Pattern.compile("(?<=:)(.*):(.*)");
- java.util.regex.Matcher mLine = pLineS.matcher(err);
- if (mLine.find()) {
- log(lvl + 2, "SyntaxError error line: " + mLine.group(1));
- errorText = mLine.group(2) == null ? errorText : mLine.group(2);
- log(lvl + 2, "SyntaxError: " + errorText);
- errorLine = Integer.parseInt(mLine.group(1));
- errorColumn = -1;
- errorClass = PY_SYNTAX;
- errorType = "SyntaxError";
- }
- } else {
+ //(SyntaxError) /tmp/sikuli-3213678404470696048.rb:2: syntax error, unexpected tRCURLY
+
+ Pattern pLineS = Pattern.compile("(?<=:)(.*):(.*)");
+ java.util.regex.Matcher mLine = pLineS.matcher(err);
+ if (mLine.find()) {
+ log(lvl + 2, "SyntaxError error line: " + mLine.group(1));
+ errorText = mLine.group(2) == null ? errorText : mLine.group(2);
+ log(lvl + 2, "SyntaxError: " + errorText);
+ errorLine = Integer.parseInt(mLine.group(1));
+ errorColumn = -1;
+ errorClass = PY_SYNTAX;
+ errorType = "SyntaxError";
+ }
+ } else {
//if (err.startsWith("(NameError)")) {
- // org.jruby.embed.EvalFailedException
- //(NameError) undefined local variable or method `asdf' for main:Object
-
- Pattern type = Pattern.compile("(?<=\\()(\\w*)");
- java.util.regex.Matcher mLine = type.matcher(err);
- if (mLine.find()) {
- errorType = mLine.group(1);
- }
- Throwable cause = thr.getCause();
- //cause.printStackTrace();
- for (StackTraceElement line : cause.getStackTrace()) {
- if (line.getFileName().equals(filename)) {
- errorText = cause.getMessage();
- errorColumn = -1;
- errorLine = line.getLineNumber();
- errorClass = PY_RUNTIME;
- this.errorText = thr.getMessage();
-
- if (errorType.equals("Rukuli::ImageNotFound")) {
- errorType = "FindFailed";
- } else if (errorType.equals("RuntimeError")) {
- errorClass = PY_JAVA;
- }
- //errorType = "NameError";
- break;
- }
- }
- }
-
- msg = "script";
- if (forIDE != null) {
- msg += " [ " + forIDE[1] + " ]";
- }
- if (errorLine != -1) {
- //log(-1,_I("msgErrorLine", srcLine));
- msg += " stopped with error in line " + errorLine;
- if (errorColumn != -1) {
- msg += " at column " + errorColumn;
- }
- } else {
- msg += "] stopped with error at line --unknown--";
- }
-
- if (errorClass == PY_RUNTIME || errorClass == PY_SYNTAX) {
- Debug.error(msg);
- Debug.error(errorType + " ( " + errorText + " )");
- if (errorClass == PY_RUNTIME) {
- Throwable cause = thr.getCause();
- //cause.printStackTrace();
- StackTraceElement[] stack = cause.getStackTrace();
- /*StringWriter writer = new StringWriter();
- PrintWriter out = new PrintWriter(writer);
- cause.printStackTrace(out);
- errorTrace = writer.toString();*/
- StringBuilder builder = new StringBuilder();
- for (StackTraceElement line : stack) {
- builder.append(line.getLineNumber());
- builder.append(":\t");
- builder.append(line.getClassName());
- builder.append(" ( ");
- builder.append(line.getMethodName());
- builder.append(" )\t");
- builder.append(line.getFileName());
- builder.append('\n');
- }
- errorTrace = builder.toString();
- if (errorTrace.length() > 0) {
- Debug.error("--- Traceback --- error source first\n"
- + "line: class ( method ) file \n" + errorTrace
- + "[error] --- Traceback --- end --------------");
- log(lvl + 2, "--- Traceback --- error source first\n"
- + "line: class ( method ) file \n" + errorTrace
- + "[error] --- Traceback --- end --------------");
- }
- }
- } else if (errorClass == PY_JAVA) {
- } else {
- Debug.error(msg);
- Debug.error("Could not evaluate error source nor reason. Analyze StackTrace!");
- Debug.error(err);
- }
- return errorLine;
- }
-
- /**
- * Initializes the ScriptingContainer and creates an instance.
- */
- private void createScriptingContainer() {
+ // org.jruby.embed.EvalFailedException
+ //(NameError) undefined local variable or method `asdf' for main:Object
+
+ Pattern type = Pattern.compile("(?<=\\()(\\w*)");
+ java.util.regex.Matcher mLine = type.matcher(err);
+ if (mLine.find()) {
+ errorType = mLine.group(1);
+ }
+ Throwable cause = thr.getCause();
+ //cause.printStackTrace();
+ for (StackTraceElement line : cause.getStackTrace()) {
+ if (line.getFileName().equals(filename)) {
+ errorText = cause.getMessage();
+ errorColumn = -1;
+ errorLine = line.getLineNumber();
+ errorClass = PY_RUNTIME;
+ this.errorText = thr.getMessage();
+
+ if (errorType.equals("Rukuli::ImageNotFound")) {
+ errorType = "FindFailed";
+ } else if (errorType.equals("RuntimeError")) {
+ errorClass = PY_JAVA;
+ }
+ //errorType = "NameError";
+ break;
+ }
+ }
+ }
+
+ msg = "script";
+ if (forIDE != null) {
+ msg += " [ " + forIDE[1] + " ]";
+ }
+ if (errorLine != -1) {
+ //log(-1,_I("msgErrorLine", srcLine));
+ msg += " stopped with error in line " + errorLine;
+ if (errorColumn != -1) {
+ msg += " at column " + errorColumn;
+ }
+ } else {
+ msg += "] stopped with error at line --unknown--";
+ }
+
+ if (errorClass == PY_RUNTIME || errorClass == PY_SYNTAX) {
+ Debug.error(msg);
+ Debug.error(errorType + " ( " + errorText + " )");
+ if (errorClass == PY_RUNTIME) {
+ Throwable cause = thr.getCause();
+ //cause.printStackTrace();
+ StackTraceElement[] stack = cause.getStackTrace();
+ /*StringWriter writer = new StringWriter();
+ PrintWriter out = new PrintWriter(writer);
+ cause.printStackTrace(out);
+ errorTrace = writer.toString();*/
+ StringBuilder builder = new StringBuilder();
+ for (StackTraceElement line : stack) {
+ builder.append(line.getLineNumber());
+ builder.append(":\t");
+ builder.append(line.getClassName());
+ builder.append(" ( ");
+ builder.append(line.getMethodName());
+ builder.append(" )\t");
+ builder.append(line.getFileName());
+ builder.append('\n');
+ }
+ errorTrace = builder.toString();
+ if (errorTrace.length() > 0) {
+ Debug.error("--- Traceback --- error source first\n"
+ + "line: class ( method ) file \n" + errorTrace
+ + "[error] --- Traceback --- end --------------");
+ log(lvl + 2, "--- Traceback --- error source first\n"
+ + "line: class ( method ) file \n" + errorTrace
+ + "[error] --- Traceback --- end --------------");
+ }
+ }
+ } else if (errorClass == PY_JAVA) {
+ } else {
+ Debug.error(msg);
+ Debug.error("Could not evaluate error source nor reason. Analyze StackTrace!");
+ Debug.error(err);
+ }
+ return errorLine;
+ }
+
+ /**
+ * Initializes the ScriptingContainer and creates an instance.
+ */
+ private void createScriptingContainer() {
//TODO create a specific RubyPath (sys.path)
- if (interpreter == null) {
- //ScriptingContainer.initialize(System.getProperties(), null, sysargv.toArray(new String[0]));
-
- interpreter = new ScriptingContainer(
- LocalContextScope.THREADSAFE);
- interpreter.setCompatVersion(CompatVersion.RUBY2_0);
- interpreter.setCompileMode(CompileMode.JIT);
- }
- }
-
- public ScriptingContainer getScriptingContainer() {
- if (interpreter == null) {
- sysargv = new ArrayList<String>();
- sysargv.add("--???--");
- sysargv.addAll(Arrays.asList(Settings.getArgs()));
- createScriptingContainer();
- }
- return interpreter;
- }
-
- /**
- * Executes the defined header for the jython script.
- *
- * @param syspaths List of all syspath entries
- */
- private void executeScriptHeader(String[] syspaths) {
+ if (interpreter == null) {
+ //ScriptingContainer.initialize(System.getProperties(), null, sysargv.toArray(new String[0]));
+
+ interpreter = new ScriptingContainer(
+ LocalContextScope.THREADSAFE);
+ interpreter.setCompatVersion(CompatVersion.RUBY2_0);
+ interpreter.setCompileMode(CompileMode.JIT);
+ }
+ }
+
+ public ScriptingContainer getScriptingContainer() {
+ if (interpreter == null) {
+ sysargv = new ArrayList<String>();
+ sysargv.add("--???--");
+ sysargv.addAll(Arrays.asList(Settings.getArgs()));
+ createScriptingContainer();
+ }
+ return interpreter;
+ }
+
+ /**
+ * Executes the defined header for the jython script.
+ *
+ * @param syspaths List of all syspath entries
+ */
+ private void executeScriptHeader(String[] syspaths) {
// TODO implement compile only
- if (syspaths.length > 0 && syspaths[0].toUpperCase().equals(COMPILE_ONLY)) {
- return;
- }
- List<String> jypath = interpreter.getLoadPaths();
- if (!FileManager.pathEquals((String) jypath.get(0), sikuliLibPath)) {
- log(lvl, "executeScriptHeader: adding SikuliX Lib path to sys.path\n" + sikuliLibPath);
- int jypathLength = jypath.size();
- String[] jypathNew = new String[jypathLength + 1];
- jypathNew[0] = sikuliLibPath;
- for (int i = 0; i < jypathLength; i++) {
- log(lvl + 1, "executeScriptHeader: before: %d: %s", i, jypath.get(i));
- jypathNew[i + 1] = (String) jypath.get(i);
- }
- for (int i = 0; i < jypathLength; i++) {
- jypath.set(i, jypathNew[i]);
- }
- jypath.add(jypathNew[jypathNew.length - 1]);
- for (int i = 0; i < jypathNew.length; i++) {
- log(lvl + 1, "executeScriptHeader: after: %d: %s", i, jypath.get(i));
- }
- }
- if (savedpathlen == 0) {
- savedpathlen = interpreter.getLoadPaths().size();
- log(lvl + 1, "executeScriptHeader: saved sys.path: %d", savedpathlen);
- }
- while (interpreter.getLoadPaths().size() > savedpathlen) {
- interpreter.getLoadPaths().remove(savedpathlen);
- }
- log(lvl + 1, "executeScriptHeader: at entry: path:");
- for (Object p : interpreter.getLoadPaths()) {
- log(lvl + 1, p.toString());
- }
- log(lvl + 1, "executeScriptHeader: at entry: --- end ---");
- for (String syspath : syspaths) {
- jypath.add(FileManager.slashify(syspath, false));
- }
-
- interpreter.runScriptlet(SCRIPT_HEADER);
-
- if (codeBefore != null) {
- StringBuilder buffer = new StringBuilder();
- for (String line : codeBefore) {
- buffer.append(line);
- }
- interpreter.runScriptlet(buffer.toString());
- }
- }
-
- private boolean doRedirect(PipedInputStream[] pin) {
- ScriptingContainer interpreter = getScriptingContainer();
- try {
- PipedOutputStream pout = new PipedOutputStream(pin[0]);
- PrintStream ps = new PrintStream(pout, true);
- System.setOut(ps);
- interpreter.setOutput(ps);
- } catch (Exception e) {
- log(-1, "doRedirect: Couldn't redirect STDOUT\n%s", e.getMessage());
- return false;
- }
- try {
- PipedOutputStream pout = new PipedOutputStream(pin[1]);
- PrintStream ps = new PrintStream(pout, true);
- System.setErr(ps);
- interpreter.setError(ps);
- } catch (Exception e) {
- log(-1, "doRedirect: Couldn't redirect STDERR\n%s", e.getMessage());
- return false;
- }
- return true;
- }
-
- /**
- * Fills the sysargv list for the Ruby script
- *
- * @param filename The file containing the script: Has to be passed as first
- * parameter in Ruby
- * @param argv The parameters passed to Sikuli with --args
- */
- private void fillSysArgv(File filename, String[] argv) {
- sysargv = new ArrayList<String>();
- if (filename != null) {
- sysargv.add(filename.getAbsolutePath());
- }
- if (argv != null) {
- sysargv.addAll(Arrays.asList(argv));
- }
- }
-}
\ No newline at end of file
+ if (syspaths.length > 0 && syspaths[0].toUpperCase().equals(COMPILE_ONLY)) {
+ return;
+ }
+ List<String> jypath = interpreter.getLoadPaths();
+ if (!FileManager.pathEquals((String) jypath.get(0), sikuliLibPath)) {
+ log(lvl, "executeScriptHeader: adding SikuliX Lib path to sys.path\n" + sikuliLibPath);
+ int jypathLength = jypath.size();
+ String[] jypathNew = new String[jypathLength + 1];
+ jypathNew[0] = sikuliLibPath;
+ for (int i = 0; i < jypathLength; i++) {
+ log(lvl + 1, "executeScriptHeader: before: %d: %s", i, jypath.get(i));
+ jypathNew[i + 1] = (String) jypath.get(i);
+ }
+ for (int i = 0; i < jypathLength; i++) {
+ jypath.set(i, jypathNew[i]);
+ }
+ jypath.add(jypathNew[jypathNew.length - 1]);
+ for (int i = 0; i < jypathNew.length; i++) {
+ log(lvl + 1, "executeScriptHeader: after: %d: %s", i, jypath.get(i));
+ }
+ }
+ if (savedpathlen == 0) {
+ savedpathlen = interpreter.getLoadPaths().size();
+ log(lvl + 1, "executeScriptHeader: saved sys.path: %d", savedpathlen);
+ }
+ while (interpreter.getLoadPaths().size() > savedpathlen) {
+ interpreter.getLoadPaths().remove(savedpathlen);
+ }
+ log(lvl + 1, "executeScriptHeader: at entry: path:");
+ for (Object p : interpreter.getLoadPaths()) {
+ log(lvl + 1, p.toString());
+ }
+ log(lvl + 1, "executeScriptHeader: at entry: --- end ---");
+ for (String syspath : syspaths) {
+ jypath.add(FileManager.slashify(syspath, false));
+ }
+
+ interpreter.runScriptlet(SCRIPT_HEADER);
+
+ if (codeBefore != null) {
+ StringBuilder buffer = new StringBuilder();
+ for (String line : codeBefore) {
+ buffer.append(line);
+ }
+ interpreter.runScriptlet(buffer.toString());
+ }
+ }
+
+ private boolean doRedirect(PipedInputStream[] pin) {
+ ScriptingContainer interpreter = getScriptingContainer();
+ try {
+ PipedOutputStream pout = new PipedOutputStream(pin[0]);
+ PrintStream ps = new PrintStream(pout, true);
+ System.setOut(ps);
+ interpreter.setOutput(ps);
+ } catch (Exception e) {
+ log(-1, "doRedirect: Couldn't redirect STDOUT\n%s", e.getMessage());
+ return false;
+ }
+ try {
+ PipedOutputStream pout = new PipedOutputStream(pin[1]);
+ PrintStream ps = new PrintStream(pout, true);
+ System.setErr(ps);
+ interpreter.setError(ps);
+ } catch (Exception e) {
+ log(-1, "doRedirect: Couldn't redirect STDERR\n%s", e.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Fills the sysargv list for the Ruby script
+ *
+ * @param filename The file containing the script: Has to be passed as first
+ * parameter in Ruby
+ * @param argv The parameters passed to Sikuli with --args
+ */
+ private void fillSysArgv(File filename, String[] argv) {
+ sysargv = new ArrayList<String>();
+ if (filename != null) {
+ sysargv.add(filename.getAbsolutePath());
+ }
+ if (argv != null) {
+ sysargv.addAll(Arrays.asList(argv));
+ }
+ }
+}
diff --git a/JRuby/src/main/resources/rukuli.rb b/JRuby/src/main/resources/rukuli.rb
new file mode 100755
index 0000000..e0dbf97
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli.rb
@@ -0,0 +1,10 @@
+require "rukuli/platform"
+#require Rukuli::Platform.sikulix_path
+require "rukuli/version"
+
+require "rukuli/app"
+require "rukuli/exception"
+require "rukuli/region"
+require "rukuli/screen"
+require "rukuli/key_code"
+require "rukuli/config"
diff --git a/JRuby/src/main/resources/rukuli/app.rb b/JRuby/src/main/resources/rukuli/app.rb
new file mode 100755
index 0000000..d45b268
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/app.rb
@@ -0,0 +1,33 @@
+# An App object represents a running app on the system.
+#
+module Rukuli
+ class App
+
+ # Public: creates a new App instance
+ #
+ # app_name - String name of the app
+ #
+ # Examples
+ #
+ # App.new("TextEdit")
+ #
+ # Returns the newly initialized App
+ def initialize(app_name)
+ @java_obj = org.sikuli.script::App.new(app_name)
+ end
+
+ # Public: brings the App to focus
+ #
+ # Returns nothing
+ def focus
+ @java_obj.focus()
+ end
+
+ # Public: the Region instance representing the app's window
+ #
+ # Returns the newly initialized Region
+ def window
+ Region.new(@java_obj.window())
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/clickable.rb b/JRuby/src/main/resources/rukuli/clickable.rb
new file mode 100755
index 0000000..72c7d0e
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/clickable.rb
@@ -0,0 +1,278 @@
+# The Clickable module defines interaction with the mouse. It is included in
+# the Region class.
+#
+module Rukuli
+ module Clickable
+
+ # Public: Performs a single click on an image match or point (x, y)
+ #
+ # args - String representing filename of image to find and click
+ # args - Fixnum, Fixnum representing x and y coordinates within
+ # a Region (0,0) is the top left
+ #
+ # Examples
+ #
+ # region.click('smile.png')
+ # region.click(123, 432)
+ #
+ # Returns nothing
+ def click(*args)
+ case args.length
+ when 1 then click_image(args[0])
+ when 2 then click_point(args[0], args[1])
+ else raise ArgumentError
+ end
+ end
+
+ # Public: Performs a double click on an image match or point (x, y)
+ #
+ # args - String representing filename of image to find and click
+ # args - Fixnum, Fixnum representing x and y coordinates within
+ # a Region (0,0) is the top left
+ #
+ # Examples
+ #
+ # region.double_click('smile.png')
+ # region.double_click(123, 432)
+ #
+ # Returns nothing
+ def double_click(*args)
+ case args.length
+ when 1 then click_image(args[0], true)
+ when 2 then click_point(args[0], args[1], true)
+ else raise ArgumentError
+ end
+ end
+
+ # Public: Performs a click and hold on an image match or point (x, y)
+ #
+ # args - String representing filename of image to find and click
+ # args - Fixnum, Fixnum representing x and y coordinates within
+ # a Region (0,0) is the top left
+ # seconds - Fixnum representing the number of seconds to hold down
+ # before releasing
+ #
+ # Examples
+ #
+ # region.click_and_hold('smile.png', 2)
+ # region.click_and_hold(123, 432, 2)
+ #
+ # Returns nothing
+ def click_and_hold(seconds = 1, *args)
+ case args.length
+ when 1 then click_image_and_hold(args[0], seconds)
+ when 2 then click_point_and_hold(args[0], args[1], seconds)
+ else raise ArgumentError
+ end
+ end
+
+ # Public: Performs a mouse down, drag, and mouse up
+ #
+ # start_x - Fixnum representing the x of the mouse down
+ # start_y - Fixnum representing the y of the mouse down
+ # end_x - Fixnum representing the x of the mouse up
+ # end_y - Fixnum representing the y of the mouse up
+ #
+ # Examples
+ #
+ # region.drag_drop(20, 12, 23, 44)
+ #
+ # Returns nothing
+ def drag_drop(start_x, start_y, end_x, end_y)
+ @java_obj.dragDrop(
+ offset_location(start_x, start_y),
+ offset_location(end_x, end_y)
+ )
+ end
+
+ # Public: Simulates turning of the mouse wheel up
+ #
+ # steps - Fixnum representing the number of steps to turn the mouse wheel
+ #
+ # Examples
+ #
+ # region.wheel_up(10)
+ #
+ # Returns nothing
+ def wheel_up(steps = 1)
+ @java_obj.wheel(-1, steps)
+ end
+
+ # Public: Simulates turning of the mouse wheel down
+ #
+ # steps - Fixnum representing the number of steps to turn the mouse wheel
+ #
+ # Examples
+ #
+ # region.wheel_down(10)
+ #
+ # Returns nothing
+ def wheel_down(steps = 1)
+ @java_obj.wheel(1, steps)
+ end
+
+ # Public: Performs a hover on an image match or point (x, y)
+ #
+ # args - String representing filename of image to find and hover
+ # args - Fixnum, Fixnum representing x and y coordinates within
+ # a Region (0,0) is the top left
+ #
+ # Examples
+ #
+ # region.hover('smile.png')
+ # region.hover(123, 432)
+ #
+ # Returns nothing
+ def hover(*args)
+ case args.length
+ when 1 then hover_image(args[0])
+ when 2 then hover_point(args[0], args[1])
+ else raise ArgumentError
+ end
+ end
+
+ private
+
+ # Private: turns the mouse wheel
+ #
+ # direction - Fixnum represeting direction to turn wheel
+ # steps - the number of steps to turn the mouse wheel
+ #
+ # Returns nothing
+ def wheel(direction, steps)
+ @java_obj.wheel(direction, steps)
+ end
+
+ # Private: clicks on a matched Region based on an image based search
+ #
+ # filename - A String representation of the filename of the region to
+ # match against
+ # seconds - The length in seconds to hold the mouse
+ #
+ # Returns nothing
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def click_image_and_hold(filename, seconds)
+ begin
+ pattern = org.sikuli.script::Pattern.new(filename).similar(0.9)
+ @java_obj.hover(pattern)
+ @java_obj.mouseDown(java.awt.event.InputEvent::BUTTON1_MASK)
+ sleep(seconds.to_i)
+ @java_obj.mouseUp(0)
+ rescue NativeException => e
+ raise_exception e, filename
+ end
+ end
+
+ # Private: clicks on a point within the region
+ #
+ # filename - A String representation of the filename of the region to
+ # match against
+ #
+ # Returns nothing
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def click_point_and_hold(x, y, seconds)
+ begin
+ @java_obj.hover(location(x, y))
+ @java_obj.mouseDown(java.awt.event.InputEvent::BUTTON1_MASK)
+ sleep(seconds.to_i)
+ @java_obj.mouseUp(0)
+ rescue NativeException => e
+ raise_exception e, filename
+ end
+ end
+
+ # Private: clicks on a matched Region based on an image based search
+ #
+ # filename - A String representation of the filename of the region to
+ # match against
+ # is_double - (optional) Boolean determining if should be a double click
+ #
+ # Returns nothing
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def click_image(filename, is_double = false, and_hold = false)
+ begin
+ if is_double
+ @java_obj.doubleClick(filename, 0)
+ else
+ @java_obj.click(filename, 0)
+ end
+ rescue NativeException => e
+ raise_exception e, filename
+ end
+ end
+
+ # Private: clicks on a point relative to a Region's top left corner
+ #
+ # x - a Fixnum representing the x component of the point to click
+ # y - a Fixnum representing the y component of the point to click
+ # is_double - (optional) Boolean determining if should be a double click
+ #
+ # Returns nothing
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def click_point(x, y, is_double = false)
+ if is_double
+ @java_obj.doubleClick(offset_location(x, y))
+ else
+ @java_obj.click(offset_location(x, y))
+ end
+ end
+
+ # Private: hovers on a matched Region based on an image based search
+ #
+ # filename - A String representation of the filename of the region to
+ # match against
+ #
+ # Returns nothing
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def hover_image(filename)
+ begin
+ @java_obj.hover(filename)
+ rescue NativeException => e
+ raise_exception e, filename
+ end
+ end
+
+ # Private: hovers on a point relative to a Region's top left corner
+ #
+ # x - a Fixnum representing the x component of the point to hover
+ # y - a Fixnum representing the y component of the point to hover
+ #
+ # Returns nothing
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def hover_point(x, y)
+ @java_obj.hover(offset_location(x, y))
+ end
+
+ # Private: create a new instance of Location
+ #
+ # x - a Fixnum representing the x component of the point to hover
+ # y - a Fixnum representing the y component of the point to hover
+ #
+ # Return location class instance
+ def location(x, y)
+ org.sikuli.script::Location.new(x, y)
+ end
+
+ # Private: location with offset
+ #
+ # x - a Fixnum representing the x component of the point to hover
+ # y - a Fixnum representing the y component of the point to hover
+ #
+ # Return new location
+ def offset_location(x, y)
+ location(x, y).offset(x(), y())
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/config.rb b/JRuby/src/main/resources/rukuli/config.rb
new file mode 100755
index 0000000..16e6cdc
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/config.rb
@@ -0,0 +1,67 @@
+# Config variables for the Sikuli driver
+#
+module Rukuli
+ class Config
+ class << self
+
+ # Public: the Boolean representing whether or not to perform a 1 second
+ # highlight when an image is matched through Searchable#find,
+ # Searchable#find_all. Defaults to false.
+ attr_accessor :highlight_on_find
+
+ # Public: the absolute file path where Sikuli will look for images when
+ # a just a filename is passed to a search or click method
+ #
+ # Returns the String representation of the path
+ def image_path
+ java.lang.System.getProperty("SIKULI_IMAGE_PATH")
+ end
+
+ # Public: the setter for the absolute file path where Sikuli will search
+ # for images with given a filename as an image
+ #
+ # Examples
+ #
+ # Rukuli::Config.image_path = "/Users/andreanastacio/rukuli/images/"
+ #
+ # Returns nothing
+ def image_path=(path)
+ java.lang.System.setProperty("SIKULI_IMAGE_PATH", path)
+ end
+
+ # Public: turns stdout logging on and off for the Sikuli java classes.
+ # Defaults to true.
+ #
+ # Examples
+ #
+ # Rukuli::Config.logging = false
+ #
+ # Returns nothing
+ def logging=(boolean)
+ return unless [TrueClass, FalseClass].include? boolean.class
+ org.sikuli.basics::Settings.InfoLogs = boolean
+ org.sikuli.basics::Settings.ActionLogs = boolean
+ org.sikuli.basics::Settings.DebugLogs = boolean
+ end
+
+ # Public: convienence method for grouping the setting of config
+ # variables
+ #
+ # Examples
+ #
+ # Rukuli::Config.run do |config|
+ # config.logging = true
+ # config.image_path = "/User/andreanastacio/images"
+ # config.highlight_on_find = true
+ # end
+ #
+ # Returns nothing
+ def run(*args)
+ if block_given?
+ yield self
+ end
+ end
+
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/exception.rb b/JRuby/src/main/resources/rukuli/exception.rb
new file mode 100755
index 0000000..c6e1524
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/exception.rb
@@ -0,0 +1,14 @@
+# Exception classes for Sikuli image searching and matching
+#
+module Rukuli
+
+ # Thrown when Sikuli is unable to find a match within the region for the
+ # file given.
+ #
+ class ImageNotFound < StandardError; end
+
+ # Thrown when a filename is given that is not found on disk in the image
+ # path. Image path can be configured using Rukuli::Config.image_path
+ #
+ class FileDoesNotExist < StandardError; end
+end
diff --git a/JRuby/src/main/resources/rukuli/key_code.rb b/JRuby/src/main/resources/rukuli/key_code.rb
new file mode 100755
index 0000000..e882ca9
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/key_code.rb
@@ -0,0 +1,21 @@
+require 'java'
+java_import 'org.sikuli.script.Key'
+java_import 'org.sikuli.script.KeyModifier'
+
+#
+# These constants represent keyboard codes for interacting with the keyboard.
+# Keyboard interaction is defined in the Rukuli::Typeable module.
+#
+module Rukuli
+ KEY_CMD = KeyModifier::META
+ KEY_SHIFT = KeyModifier::SHIFT
+ KEY_CTRL = KeyModifier::CTRL
+ KEY_ALT = KeyModifier::ALT
+
+ KEY_BACKSPACE = Key::BACKSPACE
+ KEY_RETURN = Key::ENTER
+ LEFT_ARROW = Key::LEFT
+ RIGHT_ARROW = Key::RIGHT
+ UP_ARROW = Key::UP
+ DOWN_ARROW = Key::DOWN
+end
diff --git a/JRuby/src/main/resources/rukuli/platform.rb b/JRuby/src/main/resources/rukuli/platform.rb
new file mode 100755
index 0000000..7a33055
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/platform.rb
@@ -0,0 +1,12 @@
+module Rukuli
+ class Platform
+
+ def self.sikulix_path
+ path = "#{ENV['SIKULIX_HOME']}"
+ if ENV['SIKULIX_HOME'].nil?
+ raise LoadError, "Failed to load 'sikuli-java.jar'\nMake sure SIKULIX_HOME is set!"
+ end
+ path
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/region.rb b/JRuby/src/main/resources/rukuli/region.rb
new file mode 100755
index 0000000..f84df94
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/region.rb
@@ -0,0 +1,88 @@
+# A Region represents a rectangle on screen. Regions are the main point of
+# interaction for Sikuli actions. Regions can receive actions from the mouse,
+# keyboard, and image search.
+#
+require "rukuli/clickable"
+require "rukuli/typeable"
+require "rukuli/searchable"
+
+module Rukuli
+ class Region
+ include Clickable
+ include Typeable
+ include Searchable
+
+ # Public: creates a new Region object
+ #
+ # args - Array representing x (left bound), y (top), width, height
+ # 4 Fixnums left, top, width, height
+ # An instance of an org.sikuli.script::Region
+ #
+ # Examples
+ #
+ # Region.new([10, 10, 200, 300])
+ # Region.new(10, 10, 200, 300)
+ # Region.new(another_region)
+ #
+ # Returns the newly initialized object
+ def initialize(*args)
+ @java_obj = org.sikuli.script::Region.new(*args)
+ end
+
+ # Public: highlight the region with a ~ 5 pixel red border
+ #
+ # seconds - Fixnum length of time to show border
+ #
+ # Returns nothing
+ def highlight(seconds = 1)
+ @java_obj.java_send(:highlight, [Java::int], seconds)
+ end
+
+ # Public: the x component of the top, left corner of the Region
+ def x
+ @java_obj.x()
+ end
+
+ # Public: the y component of the top, left corner of the Region
+ def y
+ @java_obj.y()
+ end
+
+ # Public: the width in pixels of the Region
+ def width
+ @java_obj.w()
+ end
+
+ # Public: the height in pixels of the Region
+ def height
+ @java_obj.h()
+ end
+
+ # Public: provide access to all region methods provided by the SikuliScript API
+ # See http://sikuli.org/doc/java/edu/mit/csail/uid/Region.html
+ def method_missing method_name, *args, &block
+ @java_obj.send method_name, *args, &block
+ end
+
+ private
+
+ # Private: interpret a java NativeException and raises a more descriptive
+ # exception
+ #
+ # exception - The original java exception thrown by the sikuli java_obj
+ # filename - A string representing the filename to include in the
+ # exception message
+ #
+ # Returns nothing
+ def raise_exception(exception, filename)
+ message = exception.message
+ if message.start_with? "java.lang."
+ raise exception.message
+ elsif message.start_with? "org.sikuli.script.FindFailed"
+ raise Rukuli::FileDoesNotExist, "The file '#{filename}' does not exist."
+ else
+ raise Rukuli::ImageNotFound, "The image '#{filename}' did not match in this region."
+ end
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/screen.rb b/JRuby/src/main/resources/rukuli/screen.rb
new file mode 100755
index 0000000..a783800
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/screen.rb
@@ -0,0 +1,20 @@
+# A Screen object defines a special type of Rukuli::Region that represents
+# the entire screen.
+#
+# TODO: Test the Screen object with multiple monitors attached.
+#
+module Rukuli
+ class Screen < Region
+
+ # Public: creates a new Screen object
+ #
+ # Examples
+ #
+ # screen = Rukuli::Screen.new
+ #
+ # Returns the newly initialized Screen object
+ def initialize
+ @java_obj = org.sikuli.script::Screen.new()
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/searchable.rb b/JRuby/src/main/resources/rukuli/searchable.rb
new file mode 100755
index 0000000..11254fc
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/searchable.rb
@@ -0,0 +1,134 @@
+# The Rukuli::Searchable module is the heart of Sikuli. It defines the
+# wrapper around Sikuli's on screen image searching and matching capability
+# It is implemented by the Region class.
+#
+module Rukuli
+ module Searchable
+
+ # Public: search for an image within a Region
+ #
+ # filename - A String representation of the filename to match against
+ # similarity - A Float between 0 and 1 representing the threshold for
+ # matching an image. Passing 1 corresponds to a 100% pixel for pixel
+ # match. Defaults to 0.9 (90% match)
+ #
+ # Examples
+ #
+ # region.find('needle.png')
+ # region.find('needle.png', 0.5)
+ #
+ # Returns an instance of Region representing the best match
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def find(filename, similarity = 0.9)
+ begin
+ pattern = build_pattern(filename, similarity)
+ match = Region.new(@java_obj.find(pattern))
+ match.highlight if Rukuli::Config.highlight_on_find
+ match
+ rescue NativeException => e
+ raise_exception e, filename
+ end
+ end
+
+ # Public: search for an image within a region (does not raise ImageNotFound exceptions)
+ #
+ # filename - A String representation of the filename to match against
+ # similarity - A Float between 0 and 1 representing the threshold for
+ # matching an image. Passing 1 corresponds to a 100% pixel for pixel
+ # match. Defaults to 0.9 (90% match)
+ #
+ # Examples
+ #
+ # region.find!('needle.png')
+ # region.find!('needle.png', 0.5)
+ #
+ # Returns the match or nil if no match is found
+ def find!(filename, similarity = 0.9)
+ begin
+ find(filename, similarity)
+ rescue Rukuli::ImageNotFound => e
+ nil
+ end
+ end
+
+ # Public: search for an image within a Region and return all matches
+ #
+ # TODO: Sort return results so they are always returned in the same order
+ # (top left to bottom right)
+ #
+ # filename - A String representation of the filename to match against
+ # similarity - A Float between 0 and 1 representing the threshold for
+ # matching an image. Passing 1 corresponds to a 100% pixel for pixel
+ # match. Defaults to 0.9 (90% match)
+ #
+ # Examples
+ #
+ # region.find_all('needle.png')
+ # region.find_all('needle.png', 0.5)
+ #
+ # Returns an array of Region objects that match the given file and
+ # threshold
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def find_all(filename, similarity = 0.9)
+ begin
+ pattern = build_pattern(filename, similarity)
+ matches = @java_obj.findAll(pattern)
+ regions = matches.collect do |r|
+ match = Region.new(r)
+ match.highlight if Rukuli::Config.highlight_on_find
+ match
+ end
+ regions
+ rescue NativeException => e
+ raise_exception e, filename
+ end
+ end
+
+ # Public: wait for a match to appear within a region
+ #
+ # filename - A String representation of the filename to match against
+ # time - A Fixnum representing the amount of time to wait defaults
+ # to 2 seconds
+ # similarity - A Float between 0 and 1 representing the threshold for
+ # matching an image. Passing 1 corresponds to a 100% pixel for pixel
+ # match. Defaults to 0.9 (90% match)
+ #
+ # Examples
+ #
+ # region.wait('needle.png') # wait for needle.png to appear for up to 1 second
+ # region.wait('needle.png', 10) # wait for needle.png to appear for 10 seconds
+ #
+ # Returns nothing
+ #
+ # Throws Rukuli::FileNotFound if the file could not be found on the system
+ # Throws Rukuli::ImageNotMatched if no matches are found within the region
+ def wait(filename, time = 2, similarity = 0.9)
+ begin
+ pattern = build_pattern(filename, similarity)
+ match = Region.new(@java_obj.wait(pattern, time))
+ match.highlight if Rukuli::Config.highlight_on_find
+ match
+ rescue NativeException => e
+ raise_exception e, filename
+ end
+ end
+
+ private
+
+ # Private: builds a java Pattern to check
+ #
+ # filename - A String representation of the filename to match against
+ # similarity - A Float between 0 and 1 representing the threshold for
+ # matching an image. Passing 1 corresponds to a 100% pixel for pixel
+ # match. Defaults to 0.9 (90% match)
+ #
+ # Returns a org.sikuli.script::Pattern object to match against
+ def build_pattern(filename, similarity)
+ org.sikuli.script::Pattern.new(filename).similar(similarity)
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/typeable.rb b/JRuby/src/main/resources/rukuli/typeable.rb
new file mode 100755
index 0000000..02b7e6e
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/typeable.rb
@@ -0,0 +1,32 @@
+# Defines interactions with the keyboard. Implemented in the Region class.
+#
+module Rukuli
+ module Typeable
+
+ # Public: Types text as if it was being typed on the keyboard with an
+ # optional key modifier
+ #
+ # text - String representing text to be typed on keyboard
+ # modifier - (optional) Sikilu constant (defined in key_code.rb)
+ # representing key to hold while typing text
+ #
+ # Examples
+ #
+ # region.type("Hello World")
+ # region.type("s", Rukuli::KEY_CMD) # saves a file
+ #
+ # Returns nothing
+ def type(text, modifier = 0)
+ @java_obj.type(nil, text, modifier)
+ end
+
+ # Public: Types text then presses the return/enter key on the keyboard
+ #
+ # text - String
+ #
+ # Returns nothing
+ def enter(text)
+ @java_obj.type(text + Sikuli::KEY_RETURN)
+ end
+ end
+end
diff --git a/JRuby/src/main/resources/rukuli/version.rb b/JRuby/src/main/resources/rukuli/version.rb
new file mode 100755
index 0000000..17b5ca4
--- /dev/null
+++ b/JRuby/src/main/resources/rukuli/version.rb
@@ -0,0 +1,3 @@
+module Rukuli
+ VERSION = "1.0.0"
+end
diff --git a/JRuby/src/main/resources/sikulix.rb b/JRuby/src/main/resources/sikulix.rb
new file mode 100755
index 0000000..62820af
--- /dev/null
+++ b/JRuby/src/main/resources/sikulix.rb
@@ -0,0 +1,16 @@
+require_relative 'rukuli'
+include Rukuli
+
+$screen = Screen.new
+
+clickable = [:click, :double_click, :click_and_hold, :drag_drop,
+ :hover, :wheel_down, :wheel_up ]
+
+typeable = [:enter, :type]
+
+searchable = [:find, :find!, :find_all, :wait]
+
+(clickable + typeable + searchable).each do |name|
+ method = $screen.method (name)
+ Object.send(:define_method, name){ |*args| method.call *args }
+end
diff --git a/Jython/src/main/java/org/sikuli/scriptrunner/JythonScriptRunner.java b/Jython/src/main/java/org/sikuli/scriptrunner/JythonScriptRunner.java
index 8ff21bb..3251ca6 100644
--- a/Jython/src/main/java/org/sikuli/scriptrunner/JythonScriptRunner.java
+++ b/Jython/src/main/java/org/sikuli/scriptrunner/JythonScriptRunner.java
@@ -93,20 +93,13 @@ public class JythonScriptRunner implements IScriptRunner {
= FileManager.convertStreamToString(SikuliBundleCleaner);
private static String sikuliLibPath;
- private static String timestampBuilt;
- private static final String tsb = "##--##Tue Jan 21 15:53:09 CET 2014##--##";
- static {
- Debug.log(3, "SikuliX Jython Support Build: %s %s", Settings.getVersionShort(),
- SikuliX.makeTimestamp(tsb));
- }
-
/**
* {@inheritDoc}
*/
@Override
public void init(String[] param) {
sikuliLibPath = new File(SikuliX.getJarPath(), "Lib").getAbsolutePath();
- if (!SikuliX.isRunningFromJar()
+ if (!SikuliX.isRunningFromJar()
|| !sikuliLibPath.contains("sikuli-ide")
|| !sikuliLibPath.contains("sikuli-script")
) {
@@ -195,7 +188,7 @@ public class JythonScriptRunner implements IScriptRunner {
+ scr + "\"");
} else {
log(lvl, "runPython: running script: \n" + scriptPaths[0]);
- interpreter.exec("sys.argv[0] = \"" + scriptPaths[0] + "\"");
+ interpreter.exec("sys.argv[0] = \"" + scriptPaths[0] + "\"");
}
interpreter.execfile(pyFile.getAbsolutePath());
}
diff --git a/pom.xml b/pom.xml
index f7e0fb9..3d63283 100755
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
<developers>
<developer>
<id>RaiMan</id>
- <name>RaiMan</name>
+ <name>Raimund Hocke</name>
<email>rmhdevelop at me.com</email>
</developer>
</developers>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/sikuli.git
More information about the pkg-java-commits
mailing list