Project creation
7
trunk/RegExcite/.classpath
Normal 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
trunk/RegExcite/.project
Normal 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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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%");
|
||||
}
|
||||
}
|
||||
|
|
@ -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[][] = { { "\\&", "&" }, { "\\\"", """ }, { "\\ ", " " }, { "\\<", "<" }, { "\\>", ">" }, { "\\'", "'" } };
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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>");
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}-*/;
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
1
trunk/RegExcite/war/RegEx3Compressed.js
Normal file
27
trunk/RegExcite/war/RegExcite.css
Normal 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;
|
||||
}
|
||||
24
trunk/RegExcite/war/RegExcite.html
Normal 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%"> <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>
|
||||
BIN
trunk/RegExcite/war/WEB-INF/lib/gwt-servlet.jar
Normal file
15
trunk/RegExcite/war/WEB-INF/web.xml
Normal 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>
|
||||
10
trunk/RegExcite/war/doc/index.html
Normal 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>
|
||||
BIN
trunk/RegExcite/war/images/error.gif
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
trunk/RegExcite/war/regexpresso/IE-22x22.png
Normal file
|
After Width: | Height: | Size: 161 B |
BIN
trunk/RegExcite/war/regexpresso/IE-sidebar.png
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
trunk/RegExcite/war/regexpresso/Moz-22x22.png
Normal file
|
After Width: | Height: | Size: 232 B |
30
trunk/RegExcite/war/regexpresso/NS-sidebar.js
Normal 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.');
|
||||
}
|
||||
BIN
trunk/RegExcite/war/regexpresso/NS-sidebar.png
Normal file
|
After Width: | Height: | Size: 704 B |
BIN
trunk/RegExcite/war/regexpresso/Opera-22x22.png
Normal file
|
After Width: | Height: | Size: 234 B |
BIN
trunk/RegExcite/war/regexpresso/Opera-sidebar.png
Normal file
|
After Width: | Height: | Size: 726 B |
348
trunk/RegExcite/war/regexpresso/index.html
Normal 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&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">∅</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=&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=...&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>
|
||||
BIN
trunk/RegExcite/war/regexpresso/main-22x22.png
Normal file
|
After Width: | Height: | Size: 131 B |
BIN
trunk/RegExcite/war/regexpresso/menu-left.png
Normal file
|
After Width: | Height: | Size: 116 B |
BIN
trunk/RegExcite/war/regexpresso/menu-right.png
Normal file
|
After Width: | Height: | Size: 114 B |
BIN
trunk/RegExcite/war/regexpresso/menu.png
Normal file
|
After Width: | Height: | Size: 588 B |
BIN
trunk/RegExcite/war/regexpresso/new-22x22.png
Normal file
|
After Width: | Height: | Size: 137 B |
BIN
trunk/RegExcite/war/regexpresso/new-47x50.png
Normal file
|
After Width: | Height: | Size: 330 B |
7
trunk/RegExcite/war/regexpresso/noempty.css
Normal 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; }
|
||||
20
trunk/RegExcite/war/regexpresso/presto.css
Normal 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; }
|
||||
520
trunk/RegExcite/war/regexpresso/regexpresso.html
Normal 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 = [
|
||||
["\\&","&"],
|
||||
["\\\"","""],
|
||||
["\\ "," "],
|
||||
["\\<","<"],
|
||||
["\\>",">"],
|
||||
["\\'","'"]
|
||||
];
|
||||
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+'®ex='+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="∅">
|
||||
<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>
|
||||