|
From: <mir...@us...> - 2007-03-13 15:28:40
|
Revision: 2141
http://svn.sourceforge.net/rubyeclipse/?rev=2141&view=rev
Author: mirkostocker
Date: 2007-03-13 08:28:37 -0700 (Tue, 13 Mar 2007)
Log Message:
-----------
Add the feature to automagically add 'end' after class, module, def and do statements. This feature was requested in the recent Ruby / Rails IDE Comparison blog post and I think it's really nice to have. But I'm not sure if I did the whole thing 'right' so it would be nice if someone (Chris?) could review it. And don't hesitate to remove it if you don't like it :)
Modified Paths:
--------------
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/SmartTypingConfigurationBlock.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java
trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java 2007-03-12 20:13:22 UTC (rev 2140)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.java 2007-03-13 15:28:37 UTC (rev 2141)
@@ -122,6 +122,7 @@
public static String RubyEditorPreferencePage_closeStrings;
public static String RubyEditorPreferencePage_closeBrackets;
public static String RubyEditorPreferencePage_closeBraces;
+ public static String RubyEditorPreferencePage_endStatements;
public static String ProblemSeveritiesPreferencePage_title;
public static String ProblemSeveritiesConfigurationBlock_needsbuild_title;
public static String ProblemSeveritiesConfigurationBlock_needsfullbuild_message;
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties 2007-03-12 20:13:22 UTC (rev 2140)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/PreferencesMessages.properties 2007-03-13 15:28:37 UTC (rev 2141)
@@ -128,6 +128,7 @@
RubyEditorPreferencePage_closeStrings= "Double" and 'single' quoted &strings
RubyEditorPreferencePage_closeBrackets= (Parentheses) and [square] brac&kets
RubyEditorPreferencePage_closeBraces= {B&races}
+RubyEditorPreferencePage_endStatements='class', 'module', 'def' and blocks ('... do') with 'end'
SmartTypingConfigurationBlock_autoclose_title=Automatically close
SmartTypingConfigurationBlock_annotationReporting_link=Also see the <a href="org.eclipse.ui.editors.preferencePages.Spelling">spell checking</a> preferences.
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/SmartTypingConfigurationBlock.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/SmartTypingConfigurationBlock.java 2007-03-12 20:13:22 UTC (rev 2140)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/preferences/SmartTypingConfigurationBlock.java 2007-03-13 15:28:37 UTC (rev 2141)
@@ -36,7 +36,8 @@
return new OverlayPreferenceStore.OverlayKey[] {
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_CLOSE_STRINGS),
new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_CLOSE_BRACKETS),
- new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_CLOSE_BRACES)
+ new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_CLOSE_BRACES),
+ new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_END_STATEMENTS)
};
}
@@ -82,6 +83,9 @@
label= PreferencesMessages.RubyEditorPreferencePage_closeBraces;
addCheckBox(composite, label, PreferenceConstants.EDITOR_CLOSE_BRACES, 0);
+
+ label= PreferencesMessages.RubyEditorPreferencePage_endStatements;
+ addCheckBox(composite, label, PreferenceConstants.EDITOR_END_STATEMENTS, 0);
}
}
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2007-03-12 20:13:22 UTC (rev 2140)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/internal/ui/rubyeditor/RubyEditor.java 2007-03-13 15:28:37 UTC (rev 2141)
@@ -4,6 +4,8 @@
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
@@ -125,6 +127,8 @@
private final static String CLOSE_BRACKETS= PreferenceConstants.EDITOR_CLOSE_BRACKETS;
/** Preference key for automatically closing braces */
private final static String CLOSE_BRACES= PreferenceConstants.EDITOR_CLOSE_BRACES;
+ /** Preference key for automatically 'end'ing statements */
+ private final static String END_STATEMENTS= PreferenceConstants.EDITOR_END_STATEMENTS;
/** Preference key for code formatter tab size */
private final static String CODE_FORMATTER_TAB_SIZE= DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE;
/** Preference key for inserting spaces rather than tabs */
@@ -174,6 +178,7 @@
private FoldingActionGroup fFoldingGroup;
private BracketInserter fBracketInserter = new BracketInserter();
+ private EndInserter fEndInserter = new EndInserter();
private CompositeActionGroup fActionGroups;
private CompositeActionGroup fContextMenuGroup;
@@ -307,10 +312,13 @@
boolean closeBrackets= preferenceStore.getBoolean(CLOSE_BRACKETS);
boolean closeBraces= preferenceStore.getBoolean(CLOSE_BRACES);
boolean closeStrings= preferenceStore.getBoolean(CLOSE_STRINGS);
+ boolean endStatements= preferenceStore.getBoolean(END_STATEMENTS);
fBracketInserter.setCloseBracketsEnabled(closeBrackets);
fBracketInserter.setCloseBracesEnabled(closeBraces);
fBracketInserter.setCloseStringsEnabled(closeStrings);
- ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
+ fEndInserter.setEndStatementsEnabled(endStatements);
+ ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);
+ ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fEndInserter);
}
}
@@ -616,10 +624,11 @@
*/
public void dispose() {
ISourceViewer sourceViewer= getSourceViewer();
- if (sourceViewer instanceof ITextViewerExtension)
+ if (sourceViewer instanceof ITextViewerExtension) {
((ITextViewerExtension) sourceViewer).removeVerifyKeyListener(fBracketInserter);
+ ((ITextViewerExtension) sourceViewer).removeVerifyKeyListener(fEndInserter);
+ }
-
if (fProjectionModelUpdater != null) {
fProjectionModelUpdater.uninstall();
fProjectionModelUpdater = null;
@@ -760,6 +769,11 @@
if (CLOSE_STRINGS.equals(property)) {
fBracketInserter.setCloseStringsEnabled(getPreferenceStore().getBoolean(property));
return;
+ }
+
+ if (END_STATEMENTS.equals(property)) {
+ fEndInserter.setEndStatementsEnabled(getPreferenceStore().getBoolean(property));
+ return;
}
AdaptedSourceViewer sourceViewer= (AdaptedSourceViewer) getSourceViewer();
@@ -1044,6 +1058,67 @@
}
+ private class EndInserter implements VerifyKeyListener {
+
+ /** Pattern to match lines with statements that can be completed with 'end' */
+ private final Pattern openBlockPattern =
+ Pattern.compile("(\\s*)" + // Capture the space before the statement, we need it to indent 'end'
+ "((def|class|module)\\s.*" + // Either we look for one of these statements
+ "|.*[\\S].*do[\\w|\\s]*)" + // or for an iterator, which needs at least one none-space character and 'do' with optional arguments.
+ "[^(end)]"); // And it should not contain end already.
+
+ private boolean endStatements;
+
+ public void verifyKey(VerifyEvent event) {
+ if (!event.doit || !endStatements) return;
+
+ switch (event.character) {
+ case '\n':
+ case '\r':
+ break;
+ default:
+ return;
+ }
+
+ final IDocument document = getSourceViewer().getDocument();
+ final int offset = getSourceViewer().getSelectedRange().x;
+ final int length = getSourceViewer().getSelectedRange().y;
+ try {
+ IRegion startLine = document.getLineInformationOfOffset(offset);
+ String lineContent = document.get(startLine.getOffset(), startLine.getLength());
+ Matcher matched = openBlockPattern.matcher(lineContent);
+ if(matched.matches()) {
+ String baseIndentation = matched.group(1); // 1 marks the spaces in front of the statement
+ String bodyIndentation = addOneIndentationLevel(baseIndentation);
+
+ String lineDelimiter = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, null);
+
+ String body = event.character + bodyIndentation + lineDelimiter + baseIndentation + "end";
+ document.replace(offset, length, body);
+ getSourceViewer().setSelectedRange(offset + bodyIndentation.length() + 1 /*for the newline char*/, 0);
+ event.doit = false;
+ }
+ } catch (BadLocationException e) {
+ RubyPlugin.log(e);
+ }
+ }
+
+ private String addOneIndentationLevel(String indentation) {
+ if(RubyCore.getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR).equals(RubyCore.SPACE)) {
+ for(int i = 0; i < Integer.parseInt(RubyCore.getOption(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE)); i++) {
+ indentation += ' ';
+ }
+ } else {
+ indentation += '\t';
+ }
+ return indentation;
+ }
+
+ public void setEndStatementsEnabled(boolean endStatements) {
+ this.endStatements = endStatements;
+ }
+ }
+
private class BracketInserter implements VerifyKeyListener, ILinkedModeListener {
private boolean fCloseBrackets = true;
Modified: trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java
===================================================================
--- trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java 2007-03-12 20:13:22 UTC (rev 2140)
+++ trunk/org.rubypeople.rdt.ui/src/org/rubypeople/rdt/ui/PreferenceConstants.java 2007-03-13 15:28:37 UTC (rev 2141)
@@ -557,6 +557,15 @@
* @since 2.1
*/
public final static String EDITOR_CLOSE_BRACES = "closeBraces"; //$NON-NLS-1$
+
+ /**
+ * A named preference that controls whether the 'end' should be inserted
+ * automatically.
+ * <p>
+ * Value is of type <code>Boolean</code>.
+ * </p>
+ */
+ public final static String EDITOR_END_STATEMENTS = "endStatements"; //$NON-NLS-1$
/**
* A named preference that controls whether occurrences are marked in the
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|