Project creation

This commit is contained in:
perceux 2009-05-07 18:53:34 +00:00
commit 59d35f425a
36 changed files with 1914 additions and 0 deletions

7
RegExcite/.classpath Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="com.google.gwt.eclipse.core.GWT_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="war/WEB-INF/classes"/>
</classpath>

29
RegExcite/.project Normal file
View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>RegExcite</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
<nature>com.google.gdt.eclipse.core.webAppNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module rename-to='regexcite'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Other module inherits -->
<!-- Specify the app entry point class. -->
<entry-point class='org.dreamsoft.regexcite.client.RegExcite'/>
</module>

View file

@ -0,0 +1,73 @@
package org.dreamsoft.regexcite.client;
import org.dreamsoft.regexcite.client.ui.AnalysePanel;
import org.dreamsoft.regexcite.client.ui.FramePanel;
import org.dreamsoft.regexcite.client.ui.ReplacePanel;
import org.dreamsoft.regexcite.client.ui.SearchPanel;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.user.client.ui.DecoratedTabPanel;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class RegExcite implements EntryPoint {
SearchPanel searchPanel = new SearchPanel();
ReplacePanel replacePanel = new ReplacePanel();
AnalysePanel analysePanel = new AnalysePanel();
FramePanel regexpressoPanel = new FramePanel("regexpresso", "regexpresso/regexpresso.html");
FramePanel helpPanel = new FramePanel("doc", "doc/index.html");
/**
* This is the entry point method.
*/
public void onModuleLoad() {
DecoratedTabPanel tabPanel = new DecoratedTabPanel();
tabPanel.add(searchPanel, "Search");
tabPanel.add(replacePanel, "Replace");
tabPanel.add(analysePanel, "Analyse");
tabPanel.add(regexpressoPanel, "Regexpresso");
tabPanel.add(helpPanel, "Help");
tabPanel.selectTab(1);
tabPanel.setAnimationEnabled(true);
tabPanel.setHeight("100%");
tabPanel.setWidth("100%");
tabPanel.getDeckPanel().setSize("100%", "100%");
// Lazy load for big panels!
tabPanel.addBeforeSelectionHandler(new BeforeSelectionHandler<Integer>() {
public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
int tabIndex = event.getItem();
switch (tabIndex) {
case 0:
searchPanel.showPanel();
break;
case 1:
break;
case 2:
analysePanel.showPanel();
break;
default:
break;
}
}
});
RootPanel.get("content").add(tabPanel);
// Test value
analysePanel.initTest();
searchPanel.initTest();
replacePanel.initTest();
}
}

View file

@ -0,0 +1,174 @@
package org.dreamsoft.regexcite.client.ui;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalSplitPanel;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.TreeListener;
import com.google.gwt.user.client.ui.VerticalPanel;
public class AnalysePanel extends VerticalPanel {
public final TextBox regexpTextBox = new TextBox();
final Tree regexpTree = new Tree();
final HTML nodeInfoHtml = new HTML();
final TreeItem root = regexpTree.addItem(regexpTextBox.getText());
final Command executeCommand = new Command() {
public void execute() {
root.removeItems();
try {
parse(root, regexpTextBox.getText());
} catch (Exception e) {
}
root.setState(true, false);
regexpTree.addItem(root.getChild(0));
if (regexpTree.getItemCount() > 1)
regexpTree.removeItem(regexpTree.getItem(0));
if (regexpTree.getItemCount() > 0) {
detailItem(regexpTree.getItem(0));
}
}
};
private boolean initialized;
private void detailItem(TreeItem item) {
NodeInfo ni = (NodeInfo) item.getUserObject();
if (ni != null) {
try {
// Decoupage pour placer un span!
String resultString = regexpTextBox.getText();
String s1 = resultString.substring(0, ni.startIndex);
String s2 = resultString.substring(ni.startIndex, ni.endIndex);
String s3 = resultString.substring(ni.endIndex, resultString.length());
// TODO Utiliser DOM.createElement(...) ??
resultString = s1 + "<span>" + s2 + "</span>" + s3;
resultString += "<hr>" + ni.toString();
nodeInfoHtml.setHTML("<pre>" + resultString + "</pre>");
// FIXME ca marche pas!!
regexpTextBox.setFocus(true);
regexpTextBox.setSelectionRange(ni.startIndex, ni.endIndex - ni.startIndex);
} catch (Exception e) {
Window.alert(e.getMessage());
}
}
}
public AnalysePanel() {
super();
}
public void showPanel() {
if (!initialized) {
initialized = true;
regexpTextBox.setWidth("100%");
regexpTree.setAnimationEnabled(true);
regexpTree.addStyleName("smallcar");
regexpTree.setSize("100%", "100%");
nodeInfoHtml.addStyleName("result");
SimplePanel spanel = new SimplePanel();
spanel.setWidget(nodeInfoHtml);
spanel.setWidth("100%");
SimplePanel spanel2 = new SimplePanel();
spanel2.setWidget(regexpTree);
spanel2.setWidth("100%");
KeyboardListenerAdapter CRListener = new CarriageReturnListenerAdapter(executeCommand);
regexpTextBox.addKeyboardListener(CRListener);
HorizontalSplitPanel hspanel = new HorizontalSplitPanel();
hspanel.setRightWidget(spanel);
hspanel.setLeftWidget(spanel2);
regexpTree.addTreeListener(new TreeListener() {
public void onTreeItemSelected(TreeItem item) {
detailItem(item);
}
public void onTreeItemStateChanged(TreeItem item) {
}
});
add(regexpTextBox);
setCellVerticalAlignment(regexpTextBox, ALIGN_TOP);
add(hspanel);
setCellVerticalAlignment(hspanel, ALIGN_TOP);
setCellHeight(hspanel, "100%");
setSize("100%", "100%");
hspanel.setSplitPosition("33%");
}
executeCommand.execute();
}
public static class NodeInfo {
int startIndex;
int endIndex;
String name;
boolean conbineable;
NodeInfo(int startIndex, int endIndex, String name, boolean conbineable) {
this.conbineable = conbineable;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.name = name;
}
@Override
public String toString() {
String result = "";
result += "<br>startIndex = " + this.startIndex;
result += "<br>endIndex = " + this.endIndex;
result += "<br>name = " + this.name;
result += "<br>conbineable = " + this.conbineable;
return result;
}
}
public static NodeInfo createNodeInfo(int startIndex, int endIndex, String name, boolean conbineable) {
return new NodeInfo(startIndex, endIndex, name, conbineable);
}
public native TreeItem parse(TreeItem treeItem, String re)/*-{
var buildTree = function(node, parentNode) {
if(node != null){
var nodeName = ((node.value==null)?node.nodeName:node.value);
var tmpNode = parentNode.@com.google.gwt.user.client.ui.TreeItem::addItem(Ljava/lang/String;)(nodeName);
for(var i in node.children){
buildTree(node.children[i], tmpNode);
}
tmpNode.@com.google.gwt.user.client.ui.TreeItem::setState(Z)(true);
if (undefined != node.startIndex) {
var tmpObj = @org.dreamsoft.regexcite.client.ui.AnalysePanel::createNodeInfo(IILjava/lang/String;Z)(node.startIndex,node.endIndex,node.nodeName,node.combineable);
tmpNode.@com.google.gwt.user.client.ui.TreeItem::setUserObject(Ljava/lang/Object;)(tmpObj);
}
}
}
var state = $wnd.PatternJS.parse(re);
var v = state.getAST();
buildTree(v, treeItem);
return treeItem;
}-*/;
public void initTest() {
regexpTextBox.setText("([ae]+)|([lc]+)|\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b");
executeCommand.execute();
}
}

View file

@ -0,0 +1,27 @@
package org.dreamsoft.regexcite.client.ui;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.Widget;
public class CarriageReturnListenerAdapter extends KeyboardListenerAdapter {
private Command command;
public CarriageReturnListenerAdapter(Command command) {
this.command = command;
}
public void onKeyPress(Widget sender, char keyCode, int modifiers) {
if (keyCode == KEY_ENTER) {
onCarriageReturnPress(sender, modifiers);
}
super.onKeyPress(sender, keyCode, modifiers);
}
protected void onCarriageReturnPress(Widget sender, int modifiers) {
if (command != null) {
command.execute();
}
}
}

View file

@ -0,0 +1,15 @@
package org.dreamsoft.regexcite.client.ui;
import com.google.gwt.user.client.ui.NamedFrame;
import com.google.gwt.user.client.ui.SimplePanel;
public class FramePanel extends SimplePanel {
public FramePanel(String id, String url) {
super();
NamedFrame nf = new NamedFrame(id);
nf.setUrl(url);
nf.setSize("100%", "100%");
setWidget(nf);
setSize("100%", "100%");
}
}

View file

@ -0,0 +1,154 @@
package org.dreamsoft.regexcite.client.ui;
import org.dreamsoft.regexcite.client.util.regex.Pattern;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ToggleButton;
/**
* Create the search panel
*/
public class ReplacePanel extends DockPanel {
private ResultPanel errorPanel = new ResultPanel();
final SelectableTextArea textArea = new SelectableTextArea();
final TextBox regexpTextBox = new TextBox();
final TextBox replaceTextBox = new TextBox();
final ToggleButton autoExec = new ToggleButton("Execute");
final ToggleButton showSplit = new ToggleButton("Split");
final ToggleButton showHighlight = new ToggleButton("Highlight");
final ToggleButton showFirstMatch = new ToggleButton("Match");
public ReplacePanel() {
final Command executeCommand = new Command() {
public void execute() {
try {
String resultString = getInputText();
if (showHighlight.isDown()) {
// FIXME CSS ??
String startHTML = "<span style='background-color: #DBFF00;'>";
String endHTML = "</span>";
String bound = "";
for (int i = 0; i < 15; i++) {
Integer.toHexString(Random.nextInt(255));
}
String start = "s" + bound + "s";
String end = "e" + bound + "e";
resultString = resultString.replaceAll(regexpTextBox.getText(), start + replaceTextBox.getText() + end);
resultString = escapeHTML(resultString);
resultString = resultString.replaceAll(start, startHTML);
resultString = resultString.replaceAll(end, endHTML);
textArea.setInnerHTML(resultString.replaceAll("\n", "<br>"));
} else {
//
}
resultString = "";
if (showFirstMatch.isDown()) {
resultString += "<hr>";
Pattern p = new Pattern(regexpTextBox.getText(), Pattern.MULTILINE | Pattern.GLOBAL);
String result[] = p.match(getInputText());
for (int i = 0; i < result.length; i++) {
String string = result[i];
resultString += "<br> match(" + i + ") = " + string;
}
}
if (showSplit.isDown()) {
resultString += "<hr>";
Pattern p = new Pattern(regexpTextBox.getText(), Pattern.MULTILINE);
String result[] = p.split(getInputText());
for (int i = 0; i < result.length; i++) {
String string = result[i];
resultString += "<br> split(" + i + ") = " + string;
}
}
errorPanel.setHTML(resultString);
} catch (Exception e) {
errorPanel.setError(e.getLocalizedMessage());
}
}
};
KeyboardListenerAdapter CRListener = new CarriageReturnListenerAdapter(executeCommand);
regexpTextBox.addKeyboardListener(CRListener);
replaceTextBox.addKeyboardListener(CRListener);
regexpTextBox.setWidth("100%");
final Timer autoSearchTimer = new Timer() {
public void run() {
if (autoExec.isDown()) {
executeCommand.execute();
}
}
};
autoExec.setDown(true);
showHighlight.setDown(true);
regexpTextBox.setWidth("100%");
textArea.setSize("100%", "100%");
textArea.addStyleName("result");
HorizontalPanel hpanel = new HorizontalPanel();
hpanel.setSpacing(2);
hpanel.add(regexpTextBox);
hpanel.add(replaceTextBox);
hpanel.add(autoExec);
hpanel.add(showHighlight);
hpanel.add(showFirstMatch);
hpanel.add(showSplit);
hpanel.setSize("100%", "100%");
add(hpanel, DockPanel.NORTH);
setCellHeight(hpanel, "1%");
add(textArea, DockPanel.CENTER);
setCellHeight(textArea, "98%");
add(errorPanel, DockPanel.SOUTH);
setCellHeight(errorPanel, "1%");
setSize("100%", "100%");
autoSearchTimer.scheduleRepeating(1000);
}
protected String escapeHTML(String text) {
String result = text;
String replace[][] = { { "\\&", "&amp;" }, { "\\\"", "&quot;" }, { "\\ ", "&nbsp;" }, { "\\<", "&lt;" }, { "\\>", "&gt;" }, { "\\'", "&#39;" } };
for (int i = 0; i < replace.length; i++) {
String[] repl = replace[i];
result = result.replaceAll(repl[0], repl[1]);
}
return result;
}
protected String getInputText() {
return textArea.getText();
}
public void initTest() {
regexpTextBox.setText("([ae]+)|([lc]+)|\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b");
replaceTextBox.setText("$&");
textArea.setText("One of the welcome developments in GWT 1.5 was the inclusion of some decent looking CSS themes -- standard. chrome and dark."
+ "How can you use them in your GWT app? Just include one of the following lines in your apps .xml file:");
autoExec.setDown(false);
}
}

View file

@ -0,0 +1,21 @@
package org.dreamsoft.regexcite.client.ui;
import com.google.gwt.user.client.ui.HTML;
/**
* Create a result panel
*/
public class ResultPanel extends HTML {
public ResultPanel() {
setStyleName("result");
setSize("100%", "100%");
}
public void setHTML(String html) {
super.setHTML("<pre>" + html + "</pre>");
}
public void setError(String error) {
super.setHTML("<pre class='error'>" + error + "</pre>");
}
}

View file

@ -0,0 +1,144 @@
package org.dreamsoft.regexcite.client.ui;
import org.dreamsoft.regexcite.client.util.regex.Pattern;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.VerticalSplitPanel;
/**
* Create the search panel
*/
public class SearchPanel extends DockPanel {
ResultPanel resultPanel = new ResultPanel();
final TextArea textArea = new TextArea();
final TextBox regexpTextBox = new TextBox();
final TextBox replaceTextBox = new TextBox();
final ToggleButton autoExec = new ToggleButton("Execute");
final ToggleButton showSplit = new ToggleButton("Split");
final ToggleButton showHighlight = new ToggleButton("Highlight");
final ToggleButton showFirstMatch = new ToggleButton("Match");
private VerticalSplitPanel vspanel = new VerticalSplitPanel();
private boolean initialized;
public SearchPanel() {
super();
setSize("100%", "100%");
}
protected String getInputText() {
return textArea.getText();
}
public void initTest() {
regexpTextBox.setText("([ae]+)|([lc]+)|\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b");
replaceTextBox.setText("$0");
textArea.setText("One of the welcome developments in GWT 1.5 was the inclusion of some decent looking CSS themes -- standard. chrome and dark."
+ "How can you use them in your GWT app? Just include one of the following lines in your apps .xml file:");
autoExec.setDown(false);
}
public void showPanel() {
if (!initialized) {
initialized = true;
final Command executeCommand = new Command() {
public void execute() {
try {
String replaceString = replaceTextBox.getText();
if (showHighlight.isDown()) {
replaceString = "<span>" + replaceTextBox.getText() + "</span>";
}
String resultString = getInputText().replaceAll(regexpTextBox.getText(), replaceString);
if (showFirstMatch.isDown()) {
resultString += "<hr>";
Pattern p = new Pattern(regexpTextBox.getText(), Pattern.GLOBAL | Pattern.MULTILINE);
String result[] = p.match(getInputText());
for (int i = 0; i < result.length; i++) {
String string = result[i];
resultString += "<br> match(" + i + ") = " + string;
}
}
if (showSplit.isDown()) {
resultString += "<hr>";
Pattern p = new Pattern(regexpTextBox.getText(), Pattern.GLOBAL | Pattern.MULTILINE);
String result[] = p.split(getInputText());
for (int i = 0; i < result.length; i++) {
String string = result[i];
resultString += "<br> split(" + i + ") = " + string;
}
}
resultPanel.setHTML(resultString);
} catch (Exception e) {
resultPanel.setError(e.getLocalizedMessage());
}
}
};
final Timer autoSearchTimer = new Timer() {
public void run() {
if (autoExec.isDown()) {
executeCommand.execute();
}
}
};
KeyboardListenerAdapter CRListener = new CarriageReturnListenerAdapter(executeCommand);
regexpTextBox.addKeyboardListener(CRListener);
replaceTextBox.addKeyboardListener(CRListener);
regexpTextBox.setWidth("100%");
autoExec.setDown(true);
showHighlight.setDown(true);
regexpTextBox.setWidth("100%");
textArea.setSize("100%", "100%");
HorizontalPanel hpanel = new HorizontalPanel();
hpanel.setSpacing(2);
hpanel.add(regexpTextBox);
hpanel.add(replaceTextBox);
hpanel.add(autoExec);
hpanel.add(showHighlight);
hpanel.add(showFirstMatch);
hpanel.add(showSplit);
hpanel.setSize("100%", "100%");
vspanel.setWidth("100%");
vspanel.setHeight("100%");
vspanel.setTopWidget(textArea);
vspanel.setBottomWidget(resultPanel);
add(hpanel, DockPanel.NORTH);
add(vspanel, DockPanel.CENTER);
setCellHeight(vspanel, "100%");
vspanel.setSplitPosition("40%");
autoSearchTimer.scheduleRepeating(1000);
}
// FIXME Why the split position change when help tab is selected?
vspanel.setSplitPosition("200px");
}
}

View file

@ -0,0 +1,49 @@
package org.dreamsoft.regexcite.client.ui;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.RichTextArea;
public class SelectableTextArea extends RichTextArea {
Element elem;
public void setInnerHTML(String html) {
elem = getElement();
_setInnerHTML(html);
}
native void _setInnerHTML(String html) /*-{
var elem = this.@org.dreamsoft.regexcite.client.ui.SelectableTextArea::elem;
var w = elem.contentWindow;
var d = w.document;
d.body.innerHTML = html;
}-*/;
public void moveSelectionRange(int start, int end) {
elem = getElement();
_moveSelectionRange(start, end);
}
// FIXME buggy method, is there no way to select a part of a text with this fucking firefox?
native void _moveSelectionRange(int startRelativeIndex, int endRelativeIndex) /*-{
var elem = this.@org.dreamsoft.regexcite.client.ui.SelectableTextArea::elem;
var w = elem.contentWindow;
var d = w.document;
if (typeof w.getSelection != 'undefined') {
var selectio = w.getSelection();
selectio.removeAllRanges();
var range = d.createRange();
var base = d.body;
range.selectNode(base);
// alert(base.selectionStart + "," + base.selectionEnd);
selectio.addRange(range);
}
else if (typeof d.selection != 'undefined') {
d.selection.empty();
var textRange = d.selection.createRange();
textRange.moveStart('character', startRelativeIndex);
textRange.moveEnd('character', endRelativeIndex);
textRange.select();
}
}-*/;
}

View file

@ -0,0 +1,201 @@
package org.dreamsoft.regexcite.client.util.regex;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.JavaScriptObject;
/**
* <p>
* Implementation of the
* {@link org.dreamsoft.regexcite.client.util.regex.Pattern} class with a
* wrapper aroung the Javascript <a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Regular_Expressions"
* >RegExp</a> object. As most of the methods delegate to the JavaScript RegExp
* object, certain differences in the declaration and behaviour of regular
* expressions must be expected.
* </p>
* <p>
* Please note that neither the
* {@link org.dreamsoft.regexcite.client.util.regex.Pattern#compile(String)}
* method nor instances are supported. For the later, consider using
* {@link Pattern#match(String)}.
* </p>
*
* @author George Georgovassilis
*
*/
public class Pattern {
/**
* m Treat the string as multiple lines.
*/
public final static int MULTILINE = 1;
/**
* i Do case-insensitive pattern matching.
*/
public final static int CASE_INSENSITIVE = 2;
/**
* g Do global pattern matching.
*/
public final static int GLOBAL = 4;
/**
* s Treat the string as a single line.
*/
public final static int SINGLE_LINE = 8;
/**
* x Ignore whitespace within a pattern.
*/
public final static int IGNORE_WHITESPACE = 16;
@SuppressWarnings("unused")
private JavaScriptObject regExp;
private static JavaScriptObject createExpression(String pattern, int flags) {
String sFlags = "";
if ((flags & MULTILINE) != 0)
sFlags += "m";
if ((flags & CASE_INSENSITIVE) != 0)
sFlags += "i";
if ((flags & GLOBAL) != 0)
sFlags += "g";
if ((flags & SINGLE_LINE) != 0)
sFlags += "s";
if ((flags & IGNORE_WHITESPACE) != 0)
sFlags += "x";
return _createExpression(pattern, sFlags);
}
private static native JavaScriptObject _createExpression(String pattern, String flags)/*-{
return new RegExp(pattern, flags);
}-*/;
private native void _match(String text, List<?> matches)/*-{
var result = text.match(this.@org.dreamsoft.regexcite.client.util.regex.Pattern::regExp);
if (result == null) return;
for (var i=0;i<result.length;i++)
matches.@java.util.ArrayList::add(Ljava/lang/Object;)(result[i]);
}-*/;
public native int getLastIndex()/*-{
var result = this.@org.dreamsoft.regexcite.client.util.regex.Pattern::regExp.lastIndex;
return (typeof result!='undefined')?result:-1;
}-*/;
public native static String getLastMatch()/*-{
var result = RegExp.lastMatch;
return (typeof result!='undefined')?result:null;
}-*/;
public native static String getLeftContext()/*-{
var result = RegExp.leftContext;
return (typeof result!='undefined')?result:null;
}-*/;
public native static String getRightContext()/*-{
var result = RegExp.rightContext;
return (typeof result!='undefined')?result:null;
}-*/;
/**
* Escape a provided string so that it will be interpreted as a literal in
* regular expressions. The current implementation does escape each
* character even if not neccessary, generating verbose literals.
*
* @param input
* @return
*/
public static String quote(String input) {
String output = "";
for (int i = 0; i < input.length(); i++) {
output += "\\" + input.charAt(i);
}
return output;
}
/**
* Class constructor
*
* @param pattern
* Regular expression
*/
public Pattern(String pattern) {
this(pattern, 0);
}
/**
* Class constructor
*
* @param pattern
* Regular expression
* @param flags
*/
public Pattern(String pattern, int flags) {
regExp = createExpression(pattern, flags);
}
/**
* This method is borrowed from the JavaScript RegExp object. It parses a
* string and returns as an array any assignments to parenthesis groups in
* the pattern's regular expression
*
* @param text
* @return Array of strings following java's Pattern convention for groups:
* Group 0 is the entire input string and the remaining groups are
* the matched parenthesis. In case nothing was matched an empty
* array is returned.
*/
public String[] match(String text) {
List<?> matches = new ArrayList<Object>();
_match(text, matches);
String arr[] = new String[matches.size()];
for (int i = 0; i < matches.size(); i++)
arr[i] = matches.get(i).toString();
return arr;
}
/**
* Determines wether a provided text matches the regular expression
*
* @param text
* @return
*/
public native boolean test(String text)/*-{
return this.@org.dreamsoft.regexcite.client.util.regex.Pattern::regExp.test(text);
}-*/;
/**
* Returns the regular expression for this pattern
*
* @return
*/
public native String getSource()/*-{
var result = this.@org.dreamsoft.regexcite.client.util.regex.Pattern::regExp.source;
return (typeof result!='undefined')?result:null;
}-*/;
private native void _split(String input, List<?> results)/*-{
var parts = input.split(this.@org.dreamsoft.regexcite.client.util.regex.Pattern::regExp);
for (var i=0;i<parts.length;i++)
results.@java.util.ArrayList::add(Ljava/lang/Object;)(parts[i] );
}-*/;
/**
* Split an input string by the pattern's regular expression
*
* @param input
* @return Array of strings
*/
public String[] split(String input) {
List<?> results = new ArrayList<Object>();
_split(input, results);
String[] parts = new String[results.size()];
for (int i = 0; i < results.size(); i++)
parts[i] = (String) results.get(i);
return parts;
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,27 @@
.result {
word-wrap: break-word;
border: 0px solid black;
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
.result * span, .result * * span, span.hl {
background-color: #DBFF00;
word-wrap: break-word;
min-width: 2px;
min-height: 10px;
}
textarea {
word-wrap: break-word;
overflow: visible;
}
.error {
color: red;
background-image: url(images/error.gif);
background-repeat: no-repeat;
padding-left: 50px;
}
.smallcar * {
font-size: xx-small;
}

View file

@ -0,0 +1,24 @@
<html>
<head>
<title>RegExcite</title>
<script language="javascript" src="RegEx3Compressed.js"></script>
<script type="text/javascript" language="javascript" src="regexcite/regexcite.nocache.js"></script>
<link type="text/css" rel="stylesheet" href="RegExcite.css">
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<table width="100%" height="100%" cellpadding="0" cellspacing="0">
<tr>
<td height="0.5%">&nbsp;&nbsp;<b>RegEx</b><sub style='color: red;'>Cite</sub></td>
</tr>
<tr>
<td height="99%" valign="top">
<div id="content"></div>
</td>
</tr>
<tr>
<td height="0.5%" align="right">Dreamsoft<sup>TM</sup></td>
</tr>
</table>
</body>
</html>

Binary file not shown.

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>RegExcite.html</welcome-file>
</welcome-file-list>
<!-- Servlets -->
</web-app>

View file

@ -0,0 +1,10 @@
<h3>RegExcite</h3>
<br>perform a regular expression using Javascript.
<br>
<ul>
<ol>
<li> Enter a regular expression in the textbox</li>
<li> Enter a text in the textarea</li>
<li> Click on 'Search'</li>
</ol>
</ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

View file

@ -0,0 +1,30 @@
/**
Adds a page to the Netscape sidebar.
@see http://www.softwareadjuvant.com/class/introtoxml/toolscd/disk1/EditorBrowsers/Mozilla.org/
@param sbTitle::String
The default title of the panel
@param sbLoc::String
The absolute (!) URL of the page to load
*/
function netscape_addPanel( sbTitle, sbLoc )
{
//alert("netscape_addPanel("+sbTitle+","+sbLoc+")");
// hack: bc 2002-01-04 work around http://bugzilla.mozilla.org/show_bug.cgi?id=99808
// @todo : what if an error happens after the user called this method ? Is this handler registered globally or only inside this function ?
window.onerror = function()
{ alert("An error has occured during the sidebar installation. Please make sure your sidebar panel is open and then retry."); };
if ((typeof window.sidebar == "object") && (typeof window.sidebar.addPanel == "function"))
{
// this does not work if sbLoc is a local or relative URL. shit.
/// @param 1 title of the panel
/// @param 2 absolute location of the page embed into the panel
/// @param 3 URL to customize (?) the panel
window.sidebar.addPanel(sbTitle,sbLoc,"");
}
else
alert('This link is intended to work only with Netscape Gecko-based browsers such as Netscape 7.x.');
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

View file

@ -0,0 +1,348 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="description" content="A regular expressions quick tester">
<meta name="author" content="cbonar@users.berlios.de">
<meta name="robots" content="index">
<meta name="keywords" content="regexpresso regular expressions expression sidebar javavascript tester evaluator">
<link rel="stylesheet" type="text/css" href="presto.css">
<script type="text/javascript" src="NS-sidebar.js"></script>
<title>RegExpresso's page</title>
</head>
<body>
<div>
<a href="http://developer.berlios.de"><img align="right" src="http://developer.berlios.de/bslogo.php?group_id=3235&type=1" width="124" height="32" border="0" alt="BerliOS Logo"></a>
<span class="author"><a href="mailto:cbonar@users.berlios.de" class="author">cbonar@users.berlios.de</a></span>
</div>
<hr>
<h1>RegEx<span class="presto">presso</span><br><small>Regular expressions, quick and dirty !</small></h1>
<div>
<h2>Index</h2>
<ul>
<li><a href="#introduction">Introduction</a>
<li><a href="#notations">Notations used in this document</a>
<li><a href="#requirements">Browser requirements / specifications</a>
<li><a href="#bugs">Known bugs and limitations</a>
<li><a href="#quickstart">Quick start</a>
<li><a href="#syntax">Regular expressions syntax</a>
<li><a href="#menu">Menu</a>
<li><a href="#params">Parameters</a>
<li><a href="#local" class="outdated">Local installation</a>
<li><a href="#license">Copyright and source</a>
<li><a href="#tips">Tips
<ul>
<li>How to remove the empty matches from the view ?
<li>RegExpresso executes when loading if both <var>regex</var> and <var>subject</var> are given in the URL.
<li>Local installation
</ul></a>
<li><a href="#links">Links</a>
</ul>
</div>
<div><a name="introduction"></a>
<h2>Introduction</h2>
<p>This tool is mainly for programmers. It helps testing a regular expression before using it in some code.
There's not as many features as in professional tools, since it is intended only to quickly test a short regular expression.
Depending on your computer's capacities, the size of the subject to parse and the complexity of the regular expression,
it may take more or less of your microprocessor's time to process the expression.
Be sure to use reasonably-sized expressions and reasonable amounts of text.
</p>
</div>
<div><a name="notations"></a>
<h2>Notations used in this document</h2>
<ul>
<li><span class="regex">A regular expression</span>
<li><span class="outdated">Outdated / not accurate content</span>
<li><span class="url">A URL</span>
<li><var>Any kind of variable / named parameter</var>
</ul>
</div>
<div><a name="requirements"></a>
<h2>Browser requirements / specifications</h2>
<ul>
<li>The regular expressions flavour is the one of Javascript 1.2, which is similar to Perl's one.<br>
<li>Javascript 1.5 is needed (because of exception handling).
<li>DOM Level 2 support
<li>CSS 2 compatible
<li>
A fast computer, since there are some intensive calculations.<br>
For instance, I have found Konqueror requiring several explicit confirmations to continue executing the script
because it was too slow (heavy load) on a Pentium III 450 MHz with 128 MB SDRAM. Of course, there was a large amount of data.
I will probably set up some kind of benchmark to have a better idea of the power needed.
</ul>
<p>Some successful platforms :
<ul>
<li>Windows XP
<ul>
<li>Internet Explorer 6 SP2
<li>Firefox 1.0.1
<li>Mozilla 1.7.3
<li>Opera 7.54
</ul>
<li>Windows 2000
<ul>
<li>Internet Explorer 6 SP1
<li>Netscape 7.2
<li>Firefox 0.9.1
<li>Opera 7.54
</ul>
<li>GNU/Linux 2.6 (Mandrake 10.0)
<ul>
<li>Konqueror 3.2.0
<li>Mozilla 1.6
</ul>
</ul>
</div>
<div><a name="bugs"></a>
<h2>Known bugs and limitations</h2>
<ul>
<li>The Javascript RegExp class has some limitations as stated in the following article : <a href="http://www.webreference.com/js/column5/modifiers.html">http://www.webreference.com/js/column5/modifiers.html</a>
<li>Needs to be tested with other browsers, especially Safari.
<li>Behaviour of the menu's buttons depends greatly on the context of the tool : is it in the sidebar, the main window or a separate window ?
</ul>
</div>
<div><a name="quickstart"></a>
<h2>Quick start</h2>
<p>
<a href="javascript:void(open('http://regexpresso.berlios.de/regexpresso.html','_search'));" title="Bookmark this link to open it in Internet Explorer's search pane"><img src="IE-sidebar.png" alt="Internet Explorer sidebar" title="Bookmark this link to open it in Internet Explorer's sidebar"></a>
<a href="javascript:netscape_addPanel('Regular expressions evaluator','http://regexpresso.berlios.de/regexpresso.html');" title="Add to Netscape/Mozilla sidebar"><img src="NS-sidebar.png" alt="Add to Netscape/Mozilla sidebar"></a>
<a href="regexpresso.html" rel="sidebar" title="RegExpBar"><img src="Opera-sidebar.png" alt="Add to Opera sidebar" title="Add to Opera sidebar"></a>
<a href="javascript:void(open('regexpresso.html','_blank','width=240,height=640,scrollbars=yes,resizable=yes,dependent=yes'));" title="Test this tool online"><img src="new-47x50.png" width="48px"></a>
</p>
<ol>
<li>Open the tool's web page or add it to your browser's sidebar by clicking on one of the above links / pictures
<li>Paste the text to parse in the top text area
<li>Type a regular expression in the middle field
<li>Validate by either clicking on the button or typing Enter
<li>The matches are shown in the bottom of the page
<li>For instance : copy and paste this page's content into the text field, and type the following pattern : <span class="regex">/\be\w*\b/i</span> to match all word beginning with a 'e' or a 'E'
</ol>
</div>
<div><a name="syntax"></a>
<h2>Regular expressions syntax</h2>
<p>The regular expression you are awaited to type in the middle field follows Perl's regular expressions syntax.
That means : <span class="regex">command/options/modifiers</span>. Two commands are supported : "match" (<code>m//</code> operator) and "replace" (<code>s///</code> operator).
<ul>
<li>To obtain the matches of a regular expression, type : <span class="regex">m/pattern/modifiers</span> or <span class="regex">/pattern/modifiers</span>,
<li>To obtain the result of a substitution, type : <span class="regex">s/pattern/replace/modifiers</span>.
</ul>
where :
<ul>
<li><var>pattern</var> is <a href="http://www.regular-expressions.info/reference.html">the regular expression pattern</a>
<li><var>modifiers</var> is <a href="http://www.webreference.com/js/column5/modifiers.html">a sequence of characters in {'g','i'}</a>
<li><var>replace</var> is <a href="http://www.webreference.com/js/column5/substitute.html">a substitution pattern</a>
</ul>
</p>
</div>
<div><a name="menu"></a>
<h2>Menu</h2>
<p><img src="menu.png"></p>
<p>There is an auto-hiding menu at the top of the window that proposes different ways to open RegExpresso's window.</p>
<ul>
<li><img src="IE-22x22.png"> : Opens RegExpresso in Internet Explorer's search pane.
If you bookmark this link, it will open in the search pane every time you call it.
<li><img src="Moz-22x22.png"> : Adds RegExpresso as a new panel to the sidebar of Netscape/Mozilla familly browsers.
<li><img src="Opera-22x22.png"> : Adds RegExpresso as a new panel to the sidebar of Opera. This also works with Firefox.
<li><img src="new-22x22.png"> : Opens a new RegExpresso window, sized like a toolbar. The current content of the fields is lost.
<li><img src="main-22x22.png"> : Opens the current RegExpresso (keeps the fields values) in the "_main" target.
With Netscape/Mozilla and Internet Explorer, the "_main" target corresponds to the current browser's window.
With other browsers, this should be a new blank window, except if there is already a frame/window named "_main".
This is intended to be used only from the sidebar.
Since this is a standard link, and since it is updated every time the form is validated,
one can bookmark it, or open it using the contextual menus provided by the browser, which may bring more control.
</ul>
</div>
<div><a name="params"></a>
<h2>Parameters</h2>
<p>RegExpresso uses two kind of parameters :
<ul>
<li>standard form fields
<li>URL parameters
</ul>
While the formers can be altered by the user simply by typing some text in the web page,
the latters require the user to add them directly to the URL used to call the tool.
Indeed, those parameters are not frequently used, and it would have been wasting space to include them in the form.
Additionally, the form parameters can be passed in the URL the same way, so one can bookmark the full URL with parameters
to retrieve a given configuration of the tool.
</p>
<p>In the following tables, the "short name" is the name to use in the URL for this parameter.
For instance : <span class="url">http://regexpresso.berlios.de/regexpresso.html?highlight=on&amp;stylesheet=http://toto.com/mystyle.css</span>
would lead to an instance of the tool with "highlight" checked and a custom stylesheet located at <span class="url">http://toto.com/mystyle.css</span>.
</p>
<p><table>
<caption>Parameters accessed via the web form.<br></caption>
<thead>
<tr><th>Short name</th><th>Description</th><th>Examples / values</th></tr>
</thead>
<tbody>
<tr>
<td><var>subject</var></td>
<td>A text area where to put the text the regular expression will parse.</td>
<td>Any text will do it.</td>
</tr>
<tr>
<td><var>regex</var></td>
<td>The regular expression, using the Perl syntax (<a href="http://www.webreference.com/js/column5/modifiers.html">Javascript restrictions</a> applied).</td>
<td><span class="regex">/\b\w*(e)/i</span> will match all words ending with 'e' or 'E'</td>
</tr>
<tr>
<td><var>highlight</var></td>
<td>Switch the 'highlight' mode, where matches are highligthed and printed at their normal place in the subject,
so we don't loose the surrounding context.
In normal mode (highlight is unchecked), the matches are displayed one after another, line by line.
</td>
<td>checked/"on" = highlight mode ; unchecked/""(empty) = normal mode</td>
</tr>
<tr>
<td><var>backref</var></td>
<td>When using capturing parentheses in the regular expression,
there may be one or more "sub-matches" for every match.
This option tells whether or not to show them.
</td>
<td>checked/"on" = show back references ; unchecked/""(empty) = don't show</td>
</tr>
</tbody>
</table></p>
<p><table>
<caption>Parameters given in the URL only</caption>
<thead>
<tr><th>Short name</th><th>Description</th><th>Examples / values</th></tr>
</thead>
<tbody>
<tr>
<td><var>stylesheet</var></td>
<td>An URL to a stylesheet of type "text/css" to add to the tool.
Since this is CSS, this stylesheet can override the style attributes already defined in the default one embedded in RegExpresso.
</td>
<td>Any valid URL to a CSS stylesheet will do it.</td>
</tr>
<tr>
<td><var>empty</var></td>
<td>In highlight mode, empty matches are replaced by the "empty set" character :
<span class="unicode">&empty;</span> (may not be correctly rendered here).
This parameter can be set to change this default character.
</td>
<td>Any character or string (preferably encoded in UTF-8).</td>
</tr>
</tbody>
</table></p>
</div>
<div><a name="license"></a>
<h2>Copyright and source</h2>
<p><div class="license">Placed in public domain by cbonar@users.berlios.de, 2005. Share and enjoy!<br>
See <a href="http://developer.berlios.de/register/publicdomain.txt">http://developer.berlios.de/register/publicdomain.txt</a> for more info on this license.</div>
</p>
<p>Basically, that means you can copy, modify and distribute this tool without any restrictions.
By the way, I would be happy to hear of any usage of RegExpresso :).
Any comment should be directed to the address located at the top of this page.<br>
If you look at the source of RegExpresso's page, you will find that the page has most of its comments stripped, in order to reduce its size by some kilo-octets for faster loading.
You can have a look at the full original code as well as the whole project at <a href="http://developer.berlios.de/projects/regexpresso">http://developer.berlios.de/projects/regexpresso</a>.
</p>
</div>
<div><a name="tips"></a>
<h2>Tips</h2>
<h3>How to remove all empty matches from the view ?</h3>
<p>The short answer : call this URL : <a href="http://regexpresso.berlios.de/regexpresso.html?empty=&stylesheet=http://regexpresso.berlios.de/noempty.css">http://regexpresso.berlios.de/regexpresso.html?empty=&amp;stylesheet=http://regexpresso.berlios.de/noempty.css</a>.
</p>
<p>Now, the explanation.
<ul>
<li>You must first empty the filler string by setting it to an empty string in the URL calling RegExpresso.
Here is a sample URL : <span class="url">http://regexpresso.berlios.de/regexpresso.html?empty=</span>.<br>
<li>With most browsers, you will still have the borders printed at the place of the empty match.
To remove them as well, you must provide RegExpresso a custom stylesheet with borders removed for the empty matches.
Once again, this is done by using the a parameter of the URL, like : <span class="url">http://regexpresso.berlios.de/regexpresso.html?stylesheet=http://myhost/my.css</span>.
You can find such a stylesheet at <a href="http://regexpresso.berlios.de/noempty.css">http://regexpresso.berlios.de/noempty.css</a>.</ul>
</p>
<h3>RegExpresso executes when loading if both <var>regex</var> and <var>subject</var> are given in the URL.</h3>
<p>So you can use such URLs to remember or show the result of a regular expression without no user intervention at all.
</p>
<div class="outdated"><a name="local"></a>
<h3>Local installation</h3>
<p>You can download the files for local use, but there are limits :
<ul>
<li>Opera : buttons "open in main window" and "open a new window" won't work because the URL contains parameters ("?param1=...&amp;param2=...")
that Opera cannot understand on local files ("file://" protocol).
<li>Firefox : button "open a new window" won't work from the sidebar because it is loaded from the context of the main window,
which will not permit to open local files due to security reasons.
<li>With some other browser that may use relative URL in the case of local files,
there may be security locks that prohibit opening such an URL from the sidebar, depending on the context of the current main window.
</ul>
</p>
</div>
</div>
<div><a name="links"></a>
<h2>Links</h2>
<a href="http://www.regular-expressions.info/javascript.html">An introduction to regular expressions</a><br>
<a href="http://www.webreference.com/js/column5/index.html">A comprehensive article about Javascript regular expressions</a><br>
<a href="http://developer.berlios.de/projects/regexpresso">The project at BerliOS</a><br>
<a href="http://developer.berlios.de/docman/display_doc.php?docid=758&group_id=3235">More on sidebars in multiple browsers</a><br>
<a href="http://www.pcre.org/">PCRE "Perl Compatible Regular Expressions", used by KDE and Safari</a><br>
<a href="http://developer.apple.com/darwin/projects/webcore/">WebCore, the Safari framework</a><br>
</div>
<br><br><br><hr>last update : 20050302
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

View file

@ -0,0 +1,7 @@
/*
Hide empty matches.
The older way was to remove the content by setting a parameter on the URL and to use border:none.
visibility:hidden was another solution but still affects the layout so we still had to remove the content by another way.
Finally, the solution to move the matches outside of the view is not very refined, but works fine.
*/
.match_empty, .backref_empty, .highlight_empty { position:absolute; top:-50px; }

View file

@ -0,0 +1,20 @@
body { background-color:white; font-family:arial,verdana; font-size:smaller; }
h1 { font-family:arial,verdana,courier; font-size:large; font-weight:bold; }
h1 small { color:gray; font-style:italic; }
.presto { font-style:italic; color:red; }
td, th { border:solid black 1px; }
caption { font-size:large; font-weight:bold; }
.url { font-weight:bold; background-color:#E0E0E0; }
var { font-weight:bold; }
var:before, var:after { content:"\""; }
.author { text-decoration:none; }
span.author:before { content:"<"; }
span.author:after { content:">"; }
table { border-collapse:collapse; }
.regex { background-color:#DBFF00; border:none; border-top:solid black 1px; border-bottom:solid black 1px; }
.outdated { margin-top:20pt; background-color:#DBB6B6; }
.outdated:before { font-weight:bold; color:#DBB6B6; background-color:black; content:"OUTDATED" }
img { border:none; }
.unicode { font-family:"Lucida sans Unicode"; }
.license { background-color:#E0E0E0; }
code { background-color:#E0E0E0; }

View file

@ -0,0 +1,520 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Language" content="en">
<meta name="author" content="cbonar@users.berlios.de">
<meta name="date" content="20050227">
<meta name="copyright" content="Placed in public domain by cbonar@users.berlios.de, 2005. Share and enjoy! See http://www.sourceforge.net/register/publicdomain.txt for more info on this license.">
<meta name="robots" content="noindex,nofollow">
<meta name="description" content="A quick regular expressions tester">
<meta name="keywords" content="regexpresso regular expressions expression sidebar javavascript tester evaluator">
<title>RegExpresso</title>
<!--
Embedded, default, standalone style
-->
<style type="text/css">
<!--
body { background-color:#EEEEEE; }
div { margin-top:4px; margin-bottom:4px; }
table { empty-cells:show; }
.title { font-family:arial,verdana,courier; font-size:larger; font-weight:bold; }
.presto { font-style:italic; color:red; }
.error { color:red; }
.warning { background-color:red; color:white; font-weight:bold; padding:2pt; }
#subject, #regex, #output { width:100%; }
.button { width:auto; text-align:center; }
.options { font-size:small; }
.match, .match_empty { border:solid red 1px; background-color:#ffffe1; }
.backref, .backref_empty { border:solid gray 1px; background-color:#FFFFE1; }
.desc_again { font-style:italic; }
.regex { background:#FFFFE1; font-weight:bold; padding-left:.2em; padding-right:.2em; border:dotted #000000 1px; }
span.menu { position:fixed; top:-15px; left:0; }
span.menu:hover, span.menu#hover { top:0; }
img.menu { border:none; border-bottom:solid gray 1px; border-top:solid white 1px; }
img.menu:hover, img.menu#hover { cursor:pointer; }
a.doc { text-decoration:none; }
.highlight { background-color:#DBFF00; border:dotted #999999 1px; }
.highlight_empty { background-color:yellow; border:dotted #999999 1px; }
.highlight_backref { background-color:white; border:none; border-left:dotted #999999 1px; }
.highlight_backref:before { content:"("; }
.highlight_backref:after { content:")"; }
.highlight_empty, .match_empty, .backref_empty { font-family:"Lucida sans Unicode"; font-size:xx-small; }
-->
</style>
<!--[if IE]>
<style type="text/css">
span.menu { position:absolute; top:expression(document.body.scrollTop-15); }
span.menu#hover { top:expression(document.body.scrollTop); }
</style>
<![endif]-->
<!--
Compatibility section.
Maybe should we check at the beginning of every function...
I personally prefer not to restrict the user... after all he has been warned.
However, this could become necessary if not all functions require the same compatibility level.
-->
<noscript type="text/javascript">
<div class="warning">
WARNING : Your browser does not support Javascript or it is disabled.
You need it to be enabled to use this tool.
</div>
</noscript>
<script type="text/javascript">
<!--
var is_compatible = true;
if ( ! window.RegExp )
{
is_compatible = false;
document.write("\
<div class='warning'>\
WARNING : It seems that your browser does not support Javascript 1.5 regular expressions.\
You won't be able to run this tool.\
</div>\
");
}
function ie_version()
{
var ua = window.navigator.userAgent
// Dans le cas d'un autre navigateur, renvoie 0
var msie = ua.indexOf ( "MSIE " )
if ( msie > 0 )
return parseInt (ua.substring (msie+5, ua.indexOf (".", msie )));
else
return 0;
}
function netscape_addPanel(sbTitle,sbLoc)
{
// @todo : what if an error happens after the user called this method ? Is this handler registered globally or only inside this function ?
window.onerror = function()
{ alert("An error has occured during the sidebar installation. Please make sure your sidebar panel is open and then retry."); };
if ((typeof window.sidebar == "object") && (typeof window.sidebar.addPanel == "function"))
window.sidebar.addPanel (sbTitle,sbLoc,"");
else
alert('This link is intended to work only with Netscape Gecko-based browsers such as Netscape 7.x.');
}
// -->
</script>
<script type="text/javascript">
<!--
function myEscape( text )
{
return escape(text).replace(/\+/g,"%2B");
}
function Loop( values )
{
this.index = 0;
this.values = values;
this.next = function() { return this.values[ (this.index++) % this.values.length ]; }
}
function createSimpleRow( cell )
{
var tr = document.createElement("tr");
tr.appendChild(cell);
return tr;
}
function createSimpleElement( dom_type, css_class, dom_child )
{
var el = document.createElement(dom_type);
if ( css_class != null )
{
el.setAttribute("class",css_class);
el.setAttribute("className",css_class);// see DOM2 : this attribute has been renamed
}
if ( dom_child != null )
el.appendChild(dom_child);
return el;
}
function getParam( name )
{
if ( window.RegExp )
{
var result = new RegExp("\\??"+name+"=([^&]*)&?","i").exec(window.location.search);
if ( result != null && result[1] != null )
// with text/plain, the '+' signs will be converted to spaces, even if they were real '+'
return unescape(result[1].replace(/\+/g," "));
else
return null;
}
else
return null;
}
// -->
</script>
<script type="text/javascript">
<!--
var alt_style = getParam("stylesheet");
if ( alt_style != null && alt_style != "" )
document.write("<link rel='stylesheet' type='text/css' title='user style' href='"+alt_style+"'>");
// -->
</script>
<script type="text/javascript">
<!--
function createReportLink( text )
{
var url = "mailto:cbonar@users.berlios.de";
url += "?subject=" + myEscape("regexpresso error");
url += "&body=regex=" + myEscape(document.form.regex);
url += "%0D%0Asubject=" + myEscape(document.form.subject);
url += "%0D%0Ahighlight=" + document.form.highlight;
url += "%0D%0Abackref=" + document.form.backref;
url += "%0D%0Aempty=" + myEscape(document.form.empty);
url += "%0D%0Astylesheet=" + myEscape(document.form.stylesheet);
url += "%0D%0Auser-agent=" + myEscape(navigator.userAgent);
var anchor = createSimpleElement("a","error",document.createTextNode(text));
anchor.setAttribute("href",url);
return anchor;
}
function createReport( subject, user_entry )
{
var div = createSimpleElement("div","error",document.createTextNode("Unattended error. You can send a "));
div.appendChild( createReportLink("mail report") );
return div;
}
// even if the result is exactly the same
var desc_again = new Loop(["desc","desc_again"]);
function match( output, subject, regexp, highlight, backref, empty )
{
// computes the matches
var results = regexp.exec(subject);
var desc_class = desc_again.next();
if ( results == null )
output.appendChild( createSimpleElement("div",desc_class,document.createTextNode("No match.")) );
else if ( highlight )
{
output.appendChild( createSimpleElement("div",desc_class,document.createTextNode("Result :")) );
var dom_results = output.appendChild( createSimpleElement("div","match",null) );
}
else
var dom_results = output.appendChild( createSimpleElement("div","results",null) );
// match_index is the index of the match of the original subject
for ( match_index=0, text_before_index=0 ; results!=null && match_index<subject.length ; )
{
match_index += results.index;
if ( highlight )
{
var text_before = subject.substring(text_before_index,match_index);
if ( text_before.length > 0 )
dom_results.appendChild( document.createTextNode(text_before) );
if ( results[0].length > 0 )
var dom_highlight = createSimpleElement( "span", "highlight", document.createTextNode(results[0]) );
else
// again, due to IE, we must declare a separate CSS class
var dom_highlight = createSimpleElement( "span", "highlight_empty", document.createTextNode(empty) );
dom_results.appendChild(dom_highlight);
}
else
{
dom_results.appendChild( createSimpleElement("div",desc_class,document.createTextNode("Matched at char. "+match_index+" :")) );
var dom_match = createSimpleElement( "span", "match", document.createTextNode(results[0]) );
// @todo visual tooltips are limited in length, if the match is too big, cut it
var index_context_before = Math.max(0,match_index-10);
var index_context_after = Math.min(match_index+results[0].length+10,subject.length);
var context_before = subject.substring(index_context_before,match_index);// what's before
var context_after = subject.substring(Math.min(match_index+results[0].length,subject.length),index_context_after);// what's after
var tooltip = "char. " + match_index + " : ";
if ( index_context_before > 0 )
tooltip += "...";
tooltip += context_before + "*" + results[0] + "*" + context_after;
if ( index_context_after < subject.length-1 )
tooltip += "...";
dom_match.setAttribute("title",tooltip);
dom_results.appendChild(dom_match);
}
if ( backref && results.length>1 )
{
if ( ! highlight )
dom_results.appendChild( createSimpleElement("div",desc_class,document.createTextNode("Backreferences :")) );
for ( r=1 ; r<results.length ; r++ )
{
var patched_result = ( results[r] == undefined ? "" : results[r] );// this happens when the match is empty
if ( highlight )
dom_highlight.appendChild( createSimpleElement("span","highlight_backref",document.createTextNode(patched_result)) );
else
{
dom_results.appendChild( createSimpleElement("span","backref",document.createTextNode(patched_result)) );
dom_results.appendChild( document.createElement("br") );
}
}
}
text_before_index = match_index + results[0].length;
if ( results[0].length > 0 )
match_index += results[0].length;
else
match_index++;
results = regexp.exec( subject.substring(match_index,subject.length) );// continue on the remaining part of the subject
if ( highlight && results == null )
{
var text_after = subject.substring(match_index,subject.length);
if ( text_after.length > 0 )
dom_results.appendChild(document.createTextNode(text_after));
}
}
}
function genHTMLBound( string, max_length )
{
var chars = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
if ( max_length == undefined )
max_length = 20;
for( tries=0 ; tries<16 ; tries++ )
{
var size = 4 + Math.round(Math.random()*(max_length-4)); // the bound's length also is randomized every new try
var bound = "";
for ( c=0 ; c<size ; c++ )
bound += chars[Math.round(Math.random()*(chars.length-1))];// add a random character to the bound
if ( string.indexOf(bound) < 0 )
{
return bound;
}
}
return null;// failed
}
function escapeHTML( string )
{
var char_ent = [
["\\&","&amp;"],
["\\\"","&quot;"],
["\\ ","&nbsp;"],
["\\<","&lt;"],
["\\>","&gt;"],
["\\'","&#39;"]
];
var escaped = string;
for ( e=0 ; e<char_ent.length ; e++ )
escaped = escaped.replace( new RegExp(char_ent[e][0],"g"), char_ent[e][1] );
return escaped;
}
function replace( output, subject, regexp, replace_string, highlight )
{
output.appendChild( createSimpleElement( "div", createSimpleElement("td","results",document.createTextNode("Result :",desc_again.next()))) );
// it will be use without modification if not in highlight mode
var results = subject.replace(regexp,replace_string);
if ( highlight )
{
// this is why we need to know what's inside the previously computed result
var start = genHTMLBound(results,6);
var end = genHTMLBound(start+results,6);
if ( start != null && end != null )
{
results = subject.replace(regexp,start+replace_string+end);
results = escapeHTML(results);
results = results.replace(new RegExp(start,"g"),"<span class='highlight'>");
results = results.replace(new RegExp(end,"g"),"</span>");
var dom_results = output.appendChild( createSimpleElement("div","match",null) );
dom_results.innerHTML = results;
}
else
{
alert("Could not find a bounding string to highlight.\nYou could retry, but this is probably due to a too big amount of data.\nYou should better not use highlighting.");
output.appendChild( createSimpleElement("div","match",document.createTextNode(results)) );// falling back to not-highlighted
}
}
else
output.appendChild( createSimpleElement("div","match",document.createTextNode(results)) );
}
function parseURL()
{
var param_subject = getParam("subject");
if ( param_subject != null )
document.form.subject.value = param_subject;
var param_regex = getParam("regex");
if ( param_regex != null )
document.form.regex.value = param_regex;
var param_highlight = getParam("highlight");
if ( param_highlight != null )
document.form.highlight.checked = param_highlight == "on";
var param_backref = getParam("backref");
if ( param_backref != null )
document.form.backref.checked = param_backref == "on";
var param_empty = getParam("empty");
if ( param_empty != null )
document.form.empty.value = param_empty;
var param_stylesheet = getParam("stylesheet");
if ( param_stylesheet != null )
document.form.stylesheet.value = param_stylesheet;
if ( param_subject != null && param_regex != null )
go(param_subject,param_regex,"output");
}
function newLocation()
{
// and this property revealed to be the one of the main window (at least with Firefox).
if ( !!document.getElementById )
{
var param_subject = myEscape(document.getElementById('subject').value);
var param_regex = myEscape(document.getElementById('regex').value);
var param_highlight = document.getElementById('highlight').checked ? "on" : "";
var param_backref = document.getElementById('backref').checked ? "on" : "";
var param_empty = myEscape(document.getElementById("empty").value);
var param_stylesheet = myEscape(document.getElementById("stylesheet").value);
var url = document.location.pathname+'?subject='+param_subject+'&regex='+param_regex+'&highlight='+param_highlight+'&backref='+param_backref+"&empty="+param_empty+"&stylesheet="+param_stylesheet;
}
else
var url = document.location.href;
return url;
}
function go( subject, perl_regex, output )
{
// every time a new result is displayed, the url to the new window is updated
// Opera can't open local files with parameters
document.getElementById("toMain").setAttribute("href",newLocation());
var dom_output = document.getElementById(output);
while ( dom_output.childNodes.length > 0 )
dom_output.removeChild(dom_output.firstChild);
var slashes = perl_regex.replace(/\\\\/g,"").replace(/\\\//,"").split("/").length-1;
// the user can omit the first slash
if ( slashes == 1 && perl_regex.charAt(0) != "/" )
perl_regex = "/" + perl_regex;
else if ( slashes < 2 )
perl_regex = "/" + perl_regex + "/";
else if ( new RegExp("s/.*/[^/]*","i").test(perl_regex) && slashes < 3 )
perl_regex = perl_regex + "/";
var full_regex = dom_output.appendChild( createSimpleElement("span","regex",document.createTextNode(perl_regex)) );
full_regex.setAttribute("title","The full regular expression");
try
{
var action = perl_regex.match(/([ms]?)\//)[1];// we can do that because we previously added (possibly) missing slashes
switch( action )
{
case "s":
var user_pattern = new RegExp("s/(.*)/(.*)/([^/]*)","i").exec(perl_regex);
if ( user_pattern != null )
{
var pattern = user_pattern[1];
var replace_string = user_pattern[2];
var modifiers = user_pattern[3];
var regex = new RegExp(pattern,modifiers);
replace( dom_output, subject, regex, replace_string, document.form.highlight.checked );
}
else
dom_output.appendChild( createReport() );
break;
case "m":
case "":
var user_pattern = new RegExp("m?/(.*)/([^/]*)","i").exec(perl_regex);
if ( user_pattern != null )
{
var pattern = user_pattern[1];
var modifiers = user_pattern[2];
var regex = new RegExp(pattern,modifiers);
match( dom_output, subject, regex, document.form.highlight.checked, document.form.backref.checked, document.form.empty.value );
}
else
dom_output.appendChild( createReport() );
break;
}
}
catch ( e )
{
// @see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/js56jslrfJScriptErrorsTOC.asp
if ( ie_version() > 0 )
{
switch ( e.number & 0xFFFF )
{
case 5017:// Syntax error in regular expression
case 5018:// Unexpected quantifier
case 5019:// Expected ']' in regular expression
case 5020:// Expected ')' in regular expression
case 5021:// Invalid range in character set
dom_output.appendChild( createSimpleElement("pre","error",document.createTextNode(e.description)) );
break;
default:
throw e;
break;
}
}
else if ( e instanceof SyntaxError )
dom_output.appendChild( createSimpleElement("pre","error",document.createTextNode(e.message)) );
else
throw e;
}
return false;
}
// -->
</script>
</head>
<body onLoad="javascript:parseURL();">
<!--
Top menu with links to open this page in different ways.
This is a shame to be forced to add the boundary pictures in the HTML because of the non-CSS aware browsers, but I had no real choice :[
More : IE just pops up the 'alt' attribute of the <img/> rather than the 'title' of <a/> (although it supports it).
Please tell me why it's so vital to IE to display the 'alt' attribute of a picture when it is already displayed !!!?
There is a fucking 'longdesc' URL attribute for that purpose ! Don't tell me it's because 'title' is not W3C, that would make me laugh.
Well, now I think I'll have to consider using Javascript or another CSS method to display a popup menu... }:|
Also, I had to concatenate the elements without any blanks between because there is no simple way (or I haven't found)
to ignores the non-significative blanks between the tags.
The biggest issue for me is that I cannot include HTML comments within the block :{
The netscape_addPanel function does not work from the sidebar (at least with Firefox),
but *hopefully* this does not make sense to use it from the sidebar.
There are links to add this page to the sidebar of different browsers in the more convenient way I could afford.
There is also a link that opens this page with the current fields values in a new window.
Finally, there is a link that opens the results in the main (bigger) window, while in sidebar mode.
-->
<span class="menu" onMouseOver="this.id='hover'" onMouseOut="this.id=''"
><img src="menu-left.png" alt="left boundary"
><a href="javascript:void(open(document.location.href,'_search'));"
><img class="menu" src="IE-22x22.png" alt="Internet Explorer logo" title="Open in Internet Explorer's search pane (bookmark this link)"
></a><img class="menu" src="Moz-22x22.png" alt="Mozilla logo" title="Add to Netscape/Mozilla sidebar"
onMouseOver="this.id='hover'" onMouseOut="this.id=''"
onClick="javascript:netscape_addPanel('Regular expressions evaluator',document.location.href);"
><a href="regexpresso.html" rel="sidebar"
><img class="menu" src="Opera-22x22.png" alt="Opera logo" title="Add to Opera sidebar"
></a><img class="menu" src="new-22x22.png" alt="'new window' icon" title="Open a new window"
onMouseOver="this.id='hover'" onMouseOut="this.id=''"
onClick="javascript:window.open(document.location.pathname,'_blank','width=240,height=640,scrollbars=yes,resizable=yes');"
><a id="toMain" target="_main" href="regexpresso.html"
><img class="menu" src="main-22x22.png" alt="'to Main window' icon" title="Open the results in the main window"
></a
><img src="menu-right.png" alt="right boundary"></span>
<div class="title">RegEx<span class="presto">presso</span></div>
<form name="form" id="form" onSubmit="javascript:return go(this.subject.value,this.regex.value,'output');" enctype="UTF-8">
<input type="hidden" id="empty" name="empty" value="&empty;">
<input type="hidden" id="stylesheet" name="stylesheet" value="">
<div class="input"><textarea name="subject" id="subject" rows="10" cols="20" onFocus="javascript:this.select();" title="The text ('subject') to evaluate">[Paste here the text to evaluate]</textarea></div>
<div class="input"><input type="text" name="regex" id="regex" value="/\b\w*(e)/i" onFocus="javascript:this.select();" title="'[m]/pattern/[modifiers]' or 's/pattern/replace/[modifiers]'"></div>
<table class="options">
<tr title="Highlight matches inside the subject"><td onClick="javascript:document.form.highlight.click();">Highlight matches :</td><td><input align="right" type="checkbox" id="highlight" name="highlight" title="Highlight matches inside the subject"></td></tr>
<tr><td onClick="javascript:document.form.backref.click();">Show backreferences :</td><td><input align="right" type="checkbox" id="backref" name="backref" title="Show backreferences captured by the parentheses" checked></td><tr>
</table>
<div class="submit"><input name="submit" id="submit" type="submit" value="EVALUATE"></div>
</form>
<div class="output" name="output" id="output">
</div>
<hr>
<div class="doc" title="External resources">
[<a class="doc" target="_main" href="http://www.regular-expressions.info/javascript.html">Introduction to regular expressions</a>]<br>
[<a class="doc" target="_main" href="http://www.webreference.com/js/column5/index.html">A comprehensive article</a>]<br>
[<a class="doc" target="_main" href="http://regexpresso.berlios.de/">About this tool</a>]<br>
<br>
<a align="right" target="_main" href="http://developer.berlios.de"><img src="http://developer.berlios.de/bslogo.php?group_id=3235&type=1" width="124" height="32" border="0" alt="BerliOS Logo"></a><br>
</div>
</body>
</html>