mirror of
https://github.com/processing/processing4.git
synced 2026-02-04 06:09:17 +01:00
Merge pull request #3227 from galsasson/master
TweakMode fix to issue #3208
This commit is contained in:
@@ -2739,10 +2739,11 @@ public class JavaEditor extends Editor {
|
||||
* Replace all numbers with variables and add code to initialize
|
||||
* these variables and handle update messages.
|
||||
*/
|
||||
//public boolean automateSketch(Sketch sketch, ArrayList<Handle> handles[])
|
||||
protected boolean automateSketch(Sketch sketch, List<List<Handle>> handles) {
|
||||
protected boolean automateSketch(Sketch sketch, SketchParser parser) {
|
||||
SketchCode[] code = sketch.getCode();
|
||||
|
||||
List<List<Handle>> handles = parser.allHandles;
|
||||
|
||||
if (code.length < 1) {
|
||||
return false;
|
||||
}
|
||||
@@ -2751,8 +2752,8 @@ public class JavaEditor extends Editor {
|
||||
return false;
|
||||
}
|
||||
|
||||
int setupStartPos = SketchParser.getSetupStart(baseCode[0]);
|
||||
if (setupStartPos < 0) {
|
||||
int setupEndPos = SketchParser.getSetupEnd(baseCode[0]);
|
||||
if (setupEndPos < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2794,7 +2795,7 @@ public class JavaEditor extends Editor {
|
||||
}
|
||||
code[tab].setProgram(c);
|
||||
}
|
||||
|
||||
|
||||
// add the main header to the code in the first tab
|
||||
String c = code[0].getProgram();
|
||||
|
||||
@@ -2849,8 +2850,8 @@ public class JavaEditor extends Editor {
|
||||
" tweakmode_initAllVars();\n"+
|
||||
" tweakmode_initCommunication();\n\n";
|
||||
|
||||
setupStartPos = SketchParser.getSetupStart(c);
|
||||
c = replaceString(c, setupStartPos, setupStartPos, addToSetup);
|
||||
setupEndPos = SketchParser.getSetupEnd(c);
|
||||
c = replaceString(c, setupEndPos, setupEndPos, addToSetup);
|
||||
|
||||
code[0].setProgram(header + c);
|
||||
|
||||
|
||||
@@ -167,7 +167,6 @@ public class JavaMode extends Mode {
|
||||
RunnerListener listener,
|
||||
final boolean present) throws SketchException {
|
||||
final JavaEditor editor = (JavaEditor)listener;
|
||||
boolean launchInteractive = false;
|
||||
|
||||
if (isSketchModified(sketch)) {
|
||||
editor.deactivateRun();
|
||||
@@ -193,7 +192,7 @@ public class JavaMode extends Mode {
|
||||
final SketchParser parser = new SketchParser(editor.baseCode, requiresTweak);
|
||||
|
||||
// add our code to the sketch
|
||||
launchInteractive = editor.automateSketch(sketch, parser.allHandles);
|
||||
final boolean launchInteractive = editor.automateSketch(sketch, parser);
|
||||
|
||||
build = new JavaBuild(sketch);
|
||||
appletClassName = build.build(false);
|
||||
@@ -204,8 +203,10 @@ public class JavaMode extends Mode {
|
||||
public void run() {
|
||||
runtime.launch(present); // this blocks until finished
|
||||
// next lines are executed when the sketch quits
|
||||
editor.initEditorCode(parser.allHandles, false);
|
||||
editor.stopInteractiveMode(parser.allHandles);
|
||||
if (launchInteractive) {
|
||||
editor.initEditorCode(parser.allHandles, false);
|
||||
editor.stopInteractiveMode(parser.allHandles);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
@@ -38,17 +38,37 @@ public class SketchParser {
|
||||
ArrayList<ColorMode> colorModes;
|
||||
|
||||
List<List<Range>> scientificNotations;
|
||||
|
||||
|
||||
|
||||
Range setupFunction;
|
||||
|
||||
List<List<Range>> commentBlocks;
|
||||
List<int[]> curlyScopes;
|
||||
|
||||
public SketchParser(String[] codeTabs, boolean requiresComment) {
|
||||
this.codeTabs = codeTabs;
|
||||
this.requiresComment = requiresComment;
|
||||
intVarCount=0;
|
||||
floatVarCount=0;
|
||||
|
||||
|
||||
// get all comment blocks
|
||||
commentBlocks = new ArrayList<>();
|
||||
for (String code : codeTabs) {
|
||||
commentBlocks.add(getCommentBlocks(code));
|
||||
}
|
||||
|
||||
// get setup function range (to ignore all numbers there)
|
||||
setupFunction = new Range(getSetupStart(codeTabs[0]), getSetupEnd(codeTabs[0]));
|
||||
|
||||
// build curly scope for every character in the code
|
||||
curlyScopes = new ArrayList<>();
|
||||
for (String code : codeTabs) {
|
||||
curlyScopes.add(getCurlyScopes(code));
|
||||
}
|
||||
|
||||
// get all scientific notation (to ignore them)
|
||||
scientificNotations = getAllScientificNotations();
|
||||
|
||||
// find, add, and sort all tweakable numbers in the sketch
|
||||
// find, add, and sort all tweak-able numbers in the sketch
|
||||
addAllNumbers();
|
||||
|
||||
// handle colors
|
||||
@@ -65,11 +85,11 @@ public class SketchParser {
|
||||
|
||||
|
||||
public void addAllNumbers() {
|
||||
//allHandles = new ArrayList[codeTabs.length]; // moved inside addAllDecimalNumbers
|
||||
allHandles = new ArrayList<>();
|
||||
|
||||
addAllDecimalNumbers();
|
||||
addAllHexNumbers();
|
||||
addAllWebColorNumbers();
|
||||
//for (int i=0; i<codeTabs.length; i++) {
|
||||
for (List<Handle> handle : allHandles) {
|
||||
//Collections.sort(allHandles[i], new HandleComparator());
|
||||
Collections.sort(handle, new HandleComparator());
|
||||
@@ -83,14 +103,11 @@ public class SketchParser {
|
||||
* list of all numbers in the sketch (excluding hexadecimals)
|
||||
*/
|
||||
private void addAllDecimalNumbers() {
|
||||
allHandles = new ArrayList<>();
|
||||
|
||||
// for every number found:
|
||||
// save its type (int/float), name, value and position in code.
|
||||
|
||||
Pattern p = Pattern.compile("[\\[\\{<>(),\\t\\s\\+\\-\\/\\*^%!|&=?:~]\\d+\\.?\\d*");
|
||||
for (int i = 0; i < codeTabs.length; i++) {
|
||||
//allHandles[i] = new ArrayList<Handle>();
|
||||
List<Handle> handles = new ArrayList<Handle>();
|
||||
allHandles.add(handles);
|
||||
|
||||
@@ -102,10 +119,15 @@ public class SketchParser {
|
||||
int start = m.start()+1;
|
||||
int end = m.end();
|
||||
|
||||
if (isInComment(start, codeTabs[i])) {
|
||||
if (isInRangeList(start, commentBlocks.get(i))) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setupFunction.contains(start)) {
|
||||
// ignore numbers in setup
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requiresComment) {
|
||||
// only add numbers that have the "// tweak" comment in their line
|
||||
@@ -150,7 +172,7 @@ public class SketchParser {
|
||||
continue;
|
||||
|
||||
// beware of the global assignment (bug from 26.07.2013)
|
||||
if (isGlobal(m.start(), c))
|
||||
if (isGlobal(m.start(), i))
|
||||
continue;
|
||||
|
||||
int line = countLines(c.substring(0, start)) - 1; // zero based
|
||||
@@ -189,10 +211,15 @@ public class SketchParser {
|
||||
int start = m.start()+1;
|
||||
int end = m.end();
|
||||
|
||||
if (isInComment(start, codeTabs[i])) {
|
||||
if (isInRangeList(start, commentBlocks.get(i))) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setupFunction.contains(start)) {
|
||||
// ignore number in setup
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requiresComment) {
|
||||
// only add numbers that have the "// tweak" comment in their line
|
||||
@@ -207,7 +234,7 @@ public class SketchParser {
|
||||
}
|
||||
|
||||
// beware of the global assignment (bug from 26.07.2013)
|
||||
if (isGlobal(m.start(), c)) {
|
||||
if (isGlobal(m.start(), i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -245,10 +272,15 @@ public class SketchParser {
|
||||
int start = m.start();
|
||||
int end = m.end();
|
||||
|
||||
if (isInComment(start, codeTabs[i])) {
|
||||
if (isInRangeList(start, commentBlocks.get(i))) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setupFunction.contains(start)) {
|
||||
// ignore number in setup
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requiresComment) {
|
||||
// only add numbers that have the "// tweak" comment in their line
|
||||
@@ -263,7 +295,7 @@ public class SketchParser {
|
||||
}
|
||||
|
||||
// beware of the global assignment (bug from 26.07.2013)
|
||||
if (isGlobal(m.start(), c)) {
|
||||
if (isGlobal(m.start(), i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -288,13 +320,14 @@ public class SketchParser {
|
||||
private ArrayList<ColorMode> findAllColorModes() {
|
||||
ArrayList<ColorMode> modes = new ArrayList<ColorMode>();
|
||||
|
||||
for (String tab : codeTabs) {
|
||||
for (int i=0; i<codeTabs.length; i++) {
|
||||
String tab = codeTabs[i];
|
||||
int index = -1;
|
||||
// search for a call to colorMode function
|
||||
while ((index = tab.indexOf("colorMode", index+1)) > -1) {
|
||||
// found colorMode at index
|
||||
|
||||
if (isInComment(index, tab)) {
|
||||
if (isInRangeList(index, commentBlocks.get(i))) {
|
||||
// ignore comments
|
||||
continue;
|
||||
}
|
||||
@@ -326,7 +359,6 @@ public class SketchParser {
|
||||
Pattern p = Pattern.compile("color\\(|color\\s\\(|fill[\\(\\s]|stroke[\\(\\s]|background[\\(\\s]|tint[\\(\\s]");
|
||||
|
||||
for (int i = 0; i < codeTabs.length; i++) {
|
||||
//colorBoxes[i] = new ArrayList<ColorControlBox>();
|
||||
List<ColorControlBox> colorBox = new ArrayList<ColorControlBox>();
|
||||
colorBoxes.add(colorBox);
|
||||
|
||||
@@ -344,10 +376,15 @@ public class SketchParser {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isInComment(m.start(), tab)) {
|
||||
if (isInRangeList(m.start(), commentBlocks.get(i))) {
|
||||
// ignore colors in a comment
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setupFunction.contains(m.start())) {
|
||||
// ignore number in setup
|
||||
continue;
|
||||
}
|
||||
|
||||
// look for handles inside the parenthesis
|
||||
for (Handle handle : allHandles.get(i)) {
|
||||
@@ -360,7 +397,7 @@ public class SketchParser {
|
||||
|
||||
if (colorHandles.size() > 0) {
|
||||
/* make sure there is no other stuff between '()' like variables.
|
||||
* substract all handle values from string inside parenthesis and
|
||||
* subtract all handle values from string inside parenthesis and
|
||||
* check there is no garbage left
|
||||
*/
|
||||
String insidePar = tab.substring(openPar+1, closePar);
|
||||
@@ -423,10 +460,15 @@ public class SketchParser {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isInComment(m.start(), tab)) {
|
||||
if (isInRangeList(m.start(), commentBlocks.get(i))) {
|
||||
// ignore colors in a comment
|
||||
continue;
|
||||
}
|
||||
|
||||
if (setupFunction.contains(m.start())) {
|
||||
// ignore number in setup
|
||||
continue;
|
||||
}
|
||||
|
||||
// put 'colorParamsEnd' after three parameters inside the parenthesis or at the close
|
||||
int colorParamsEnd = openPar;
|
||||
@@ -450,7 +492,7 @@ public class SketchParser {
|
||||
|
||||
if (colorHandles.size() > 0) {
|
||||
/* make sure there is no other stuff between '()' like variables.
|
||||
* substract all handle values from string inside parenthesis and
|
||||
* subtract all handle values from string inside parenthesis and
|
||||
* check there is no garbage left
|
||||
*/
|
||||
String insidePar = tab.substring(openPar+1, colorParamsEnd);
|
||||
@@ -542,18 +584,13 @@ public class SketchParser {
|
||||
|
||||
|
||||
private List<List<Range>> getAllScientificNotations() {
|
||||
//ArrayList<Range> notations[] = new ArrayList[codeTabs.length];
|
||||
List<List<Range>> notations = new ArrayList<>();
|
||||
|
||||
Pattern p = Pattern.compile("[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?[eE][+\\-]?\\d+");
|
||||
//for (int i = 0; i < codeTabs.length; i++) {
|
||||
for (String code : codeTabs) {
|
||||
List<Range> notation = new ArrayList<Range>();
|
||||
//notations[i] = new ArrayList<Range>();
|
||||
//Matcher m = p.matcher(codeTabs[i]);
|
||||
Matcher m = p.matcher(code);
|
||||
while (m.find()) {
|
||||
//notations[i].add(new Range(m.start(), m.end()));
|
||||
notation.add(new Range(m.start(), m.end()));
|
||||
}
|
||||
notations.add(notation);
|
||||
@@ -646,92 +683,128 @@ public class SketchParser {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an int array for every tab that represents the scope depth at each character
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static private int[] getCurlyScopes(String code)
|
||||
{
|
||||
List<Range> comments = getCommentBlocks(code);
|
||||
|
||||
int[] scopes = new int[code.length()];
|
||||
int curlyScope = 0;
|
||||
boolean arrayAssignmentMaybeCommingFlag = false;
|
||||
int arrayAssignmentCurlyScope = 0;
|
||||
for (int pos=0; pos<code.length(); pos++) {
|
||||
scopes[pos] = curlyScope;
|
||||
|
||||
if (isInRangeList(pos, comments)) {
|
||||
// we are inside a comment, ignore and move on
|
||||
continue;
|
||||
}
|
||||
|
||||
if (code.charAt(pos) == '{') {
|
||||
if (arrayAssignmentMaybeCommingFlag ||
|
||||
arrayAssignmentCurlyScope>0) {
|
||||
// this is an array assignment
|
||||
arrayAssignmentCurlyScope++;
|
||||
arrayAssignmentMaybeCommingFlag = false;
|
||||
}
|
||||
else {
|
||||
curlyScope++;
|
||||
}
|
||||
}
|
||||
else if (code.charAt(pos) == '}') {
|
||||
if (arrayAssignmentCurlyScope>0) {
|
||||
arrayAssignmentCurlyScope--;
|
||||
}
|
||||
else {
|
||||
curlyScope--;
|
||||
}
|
||||
}
|
||||
else if (code.charAt(pos) == '=') {
|
||||
arrayAssignmentMaybeCommingFlag = true;
|
||||
}
|
||||
else if (!isWhiteSpace(code.charAt(pos))) {
|
||||
arrayAssignmentMaybeCommingFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
return scopes;
|
||||
}
|
||||
|
||||
static private boolean isWhiteSpace(char c) {
|
||||
if (c == ' ' ||
|
||||
c == '\t' ||
|
||||
c == '\n' ||
|
||||
c == '\r') {
|
||||
return true;
|
||||
}
|
||||
|
||||
int[][] a = {{1,2},{3,4}};
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a global position?
|
||||
* @param pos position
|
||||
* @param code code
|
||||
* @param codeTabIndex index of the code in codeTabs
|
||||
* @return
|
||||
* true if the position 'pos' is in global scope in the code 'code'
|
||||
* true if the position 'pos' is in global scope in the code 'codeTabs[codeTabIndex]'
|
||||
*
|
||||
*/
|
||||
static private boolean isGlobal(int pos, String code) {
|
||||
int curlyScope = 0; // count '{-}'
|
||||
|
||||
for (int c=pos; c>=0; c--)
|
||||
{
|
||||
if (code.charAt(c) == '{') {
|
||||
// check if a function or an array assignment
|
||||
for (int cc=c; cc>=0; cc--) {
|
||||
if (code.charAt(cc)==')') {
|
||||
curlyScope++;
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==']') {
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==';') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (code.charAt(c) == '}') {
|
||||
// check if a function or an array assignment
|
||||
for (int cc=c; cc>=0; cc--) {
|
||||
if (code.charAt(cc)==')') {
|
||||
curlyScope--;
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==']') {
|
||||
break;
|
||||
}
|
||||
else if (code.charAt(cc)==';') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (curlyScope == 0) {
|
||||
// it is a global position
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
private boolean isGlobal(int pos, int codeTabIndex) {
|
||||
return (curlyScopes.get(codeTabIndex)[pos]==0);
|
||||
};
|
||||
|
||||
static private boolean isInComment(int pos, String code) {
|
||||
// look for one line comment
|
||||
int lineStart = getStartOfLine(pos, code);
|
||||
if (lineStart < 0) {
|
||||
return false;
|
||||
public static List<Range> getCommentBlocks(String code) {
|
||||
List<Range> commentBlocks = new ArrayList<Range>();
|
||||
|
||||
int lastBlockStart=0;
|
||||
boolean lookForEnd = false;
|
||||
for (int pos=0; pos<code.length()-1; pos++) {
|
||||
if (lookForEnd) {
|
||||
// we have a start, look for the end
|
||||
if (code.charAt(pos) == '*' && code.charAt(pos+1) == '/') {
|
||||
commentBlocks.add(new Range(lastBlockStart, pos+1));
|
||||
lookForEnd = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (code.charAt(pos) == '/' && code.charAt(pos+1) == '*') {
|
||||
// we found a block start
|
||||
lastBlockStart = pos;
|
||||
lookForEnd = true;
|
||||
}
|
||||
else if (code.charAt(pos) == '/' && code.charAt(pos+1) == '/') {
|
||||
// we found a line comment
|
||||
commentBlocks.add(new Range(pos, getEndOfLine(pos, code)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (code.substring(lineStart, pos).indexOf("//") != -1) {
|
||||
return true;
|
||||
|
||||
return commentBlocks;
|
||||
}
|
||||
|
||||
private static boolean isInRangeList(int pos, List<Range> rangeList) {
|
||||
for (Range r : rangeList) {
|
||||
if (r.contains(pos)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: look for block comments
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static private int getEndOfLine(int pos, String code) {
|
||||
return code.indexOf("\n", pos);
|
||||
}
|
||||
|
||||
|
||||
static private int getStartOfLine(int pos, String code) {
|
||||
while (pos >= 0) {
|
||||
if (code.charAt(pos) == '\n') {
|
||||
return pos+1;
|
||||
}
|
||||
pos--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** returns the object of the function starting at 'pos'
|
||||
/** returns the object name (what comes before the '.') of the function starting at 'pos'
|
||||
*
|
||||
* @param pos
|
||||
* @param code
|
||||
@@ -762,7 +835,7 @@ public class SketchParser {
|
||||
}
|
||||
|
||||
|
||||
static public int getSetupStart(String code) {
|
||||
public static int getSetupStart(String code) {
|
||||
Pattern p = Pattern.compile("void[\\s\\t\\r\\n]*setup[\\s\\t]*\\(\\)[\\s\\t\\r\\n]*\\{");
|
||||
Matcher m = p.matcher(code);
|
||||
|
||||
@@ -772,11 +845,44 @@ public class SketchParser {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// private String replaceString(String str, int start, int end, String put) {
|
||||
// return str.substring(0, start) + put + str.substring(end, str.length());
|
||||
// }
|
||||
|
||||
public static int getSetupEnd(String code) {
|
||||
List<Range> comments = getCommentBlocks(code);
|
||||
|
||||
int setupStart = getSetupStart(code);
|
||||
if (setupStart == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
System.out.println("setup start = " + setupStart);
|
||||
|
||||
// count brackets to look for setup end
|
||||
int bracketCount=1;
|
||||
int pos = setupStart;
|
||||
while (bracketCount>0 && pos<code.length()) {
|
||||
|
||||
if (isInRangeList(pos, comments)) {
|
||||
// in a comment, ignore and move on
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (code.charAt(pos) == '{') {
|
||||
bracketCount++;
|
||||
}
|
||||
else if (code.charAt(pos) == '}') {
|
||||
bracketCount--;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (bracketCount == 0) {
|
||||
return pos-1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static class Range {
|
||||
|
||||
Reference in New Issue
Block a user