Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 14942 Details for
Bug 11668
Add emacs-style "Alt-/" hippie auto completion
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
First patch
patch.txt (text/plain), 16.80 KB, created by
Genady Beryozkin
on 2004-09-30 17:13:23 EDT
(
hide
)
Description:
First patch
Filename:
MIME Type:
Creator:
Genady Beryozkin
Created:
2004-09-30 17:13:23 EDT
Size:
16.80 KB
patch
obsolete
>Index: plugin.properties >=================================================================== >RCS file: /home/eclipse/org.eclipse.ui.workbench.texteditor/plugin.properties,v >retrieving revision 1.26 >diff -u -r1.26 plugin.properties >--- plugin.properties 23 Jun 2004 19:41:45 -0000 1.26 >+++ plugin.properties 30 Sep 2004 21:01:52 -0000 >@@ -152,6 +152,8 @@ > command.toggleOverwrite.name = Toggle Overwrite > command.toggleInsertMode.description = Toggle insert mode > command.toggleInsertMode.name = Toggle Insert Mode >+command.emacsCompletion.description = Context insensitive completion >+command.emacsCompletion.name = Text Completion > command.windowEnd.description = Go to the end of the window > command.windowEnd.name = Window End > command.windowStart.description = Go to the start of the window >Index: plugin.xml >=================================================================== >RCS file: /home/eclipse/org.eclipse.ui.workbench.texteditor/plugin.xml,v >retrieving revision 1.52.2.1 >diff -u -r1.52.2.1 plugin.xml >--- plugin.xml 4 Aug 2004 08:32:00 -0000 1.52.2.1 >+++ plugin.xml 30 Sep 2004 21:01:52 -0000 >@@ -425,6 +425,12 @@ > categoryId="org.eclipse.ui.category.edit" > id="org.eclipse.ui.edit.text.toggleInsertMode"> > </command> >+ <command >+ name="%command.emacsCompletion.name" >+ description="%command.emacsCompletion.description" >+ categoryId="org.eclipse.ui.category.edit" >+ id="org.eclipse.ui.edit.text.emacsCompletion"> >+ </command> > > <keyBinding > commandId="org.eclipse.ui.edit.text.delete.line" >@@ -788,6 +794,12 @@ > commandId="org.eclipse.ui.edit.text.toggleInsertMode" > contextId="org.eclipse.ui.textEditorScope" > keySequence="Ctrl+Shift+Insert" >+ keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration"> >+ </keyBinding> >+ <keyBinding >+ commandId="org.eclipse.ui.edit.text.emacsCompletion" >+ contextId="org.eclipse.ui.textEditorScope" >+ keySequence="Alt+/" > keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration"> > </keyBinding> > <keyBinding >Index: src/org/eclipse/ui/texteditor/AbstractTextEditor.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/AbstractTextEditor.java,v >retrieving revision 1.138.2.1 >diff -u -r1.138.2.1 AbstractTextEditor.java >--- src/org/eclipse/ui/texteditor/AbstractTextEditor.java 1 Sep 2004 07:47:32 -0000 1.138.2.1 >+++ src/org/eclipse/ui/texteditor/AbstractTextEditor.java 30 Sep 2004 21:01:56 -0000 >@@ -4209,6 +4209,12 @@ > action.setHelpContextId(IAbstractTextEditorHelpContextIds.TOGGLE_INSERT_MODE_ACTION); > action.setActionDefinitionId(ITextEditorActionDefinitionIds.TOGGLE_INSERT_MODE); > setAction(ITextEditorActionConstants.TOGGLE_INSERT_MODE, action); >+ >+ action = new EmacsCompleteAction(EditorMessages.getResourceBundle(), "Editor.EmacsCompletion.", this); //$NON-NLS-1$ >+ // TODO action.setHelpContextId(IAbstractTextEditorHelpContextIds.EMACS_COMPLETION_ACTION); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.EMACS_COMPLETION); >+ setAction(ITextEditorActionConstants.EMACS_COMPLETION, action); >+ > > markAsContentDependentAction(ITextEditorActionConstants.UNDO, true); > markAsContentDependentAction(ITextEditorActionConstants.REDO, true); >@@ -4217,6 +4223,7 @@ > markAsContentDependentAction(ITextEditorActionConstants.FIND_PREVIOUS, true); > markAsContentDependentAction(ITextEditorActionConstants.FIND_INCREMENTAL, true); > markAsContentDependentAction(ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE, true); >+ markAsContentDependentAction(ITextEditorActionConstants.EMACS_COMPLETION, true); > > markAsSelectionDependentAction(ITextEditorActionConstants.CUT, true); > markAsSelectionDependentAction(ITextEditorActionConstants.COPY, true); >@@ -4226,6 +4233,7 @@ > markAsSelectionDependentAction(ITextEditorActionConstants.SHIFT_RIGHT_TAB, true); > markAsSelectionDependentAction(ITextEditorActionConstants.UPPER_CASE, true); > markAsSelectionDependentAction(ITextEditorActionConstants.LOWER_CASE, true); >+ markAsSelectionDependentAction(ITextEditorActionConstants.EMACS_COMPLETION, true); > > markAsPropertyDependentAction(ITextEditorActionConstants.UNDO, true); > markAsPropertyDependentAction(ITextEditorActionConstants.REDO, true); >Index: src/org/eclipse/ui/texteditor/ITextEditorActionConstants.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/ITextEditorActionConstants.java,v >retrieving revision 1.15 >diff -u -r1.15 ITextEditorActionConstants.java >--- src/org/eclipse/ui/texteditor/ITextEditorActionConstants.java 23 Jun 2004 19:41:45 -0000 1.15 >+++ src/org/eclipse/ui/texteditor/ITextEditorActionConstants.java 30 Sep 2004 21:01:56 -0000 >@@ -415,4 +415,11 @@ > * @since 3.0 > */ > static final String TOGGLE_INSERT_MODE= "TOGGLE_INSERT_MODE"; //$NON-NLS-1$ >+ >+ /** >+ * Name of the action for emacs style completion. >+ * Value: <code>"EMACS_COMPLETION"</code> >+ * @since 3.1 >+ */ >+ static final String EMACS_COMPLETION= "EMACS_COMPLETION"; //$NON-NLS-1$ > } >Index: src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java >=================================================================== >RCS file: /home/eclipse/org.eclipse.ui.workbench.texteditor/src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java,v >retrieving revision 1.15 >diff -u -r1.15 ITextEditorActionDefinitionIds.java >--- src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java 23 Jun 2004 19:41:45 -0000 1.15 >+++ src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java 30 Sep 2004 21:01:56 -0000 >@@ -447,4 +447,11 @@ > * @since 3.0 > */ > public static final String TOGGLE_INSERT_MODE= "org.eclipse.ui.edit.text.toggleInsertMode"; //$NON-NLS-1$ >+ >+ /** >+ * Action definition ID of the edit -> text complete action >+ * Value: <code>"org.eclipse.ui.edit.text.emacsCompletion"</code>). >+ * @since 3.1 >+ */ >+ public static final String EMACS_COMPLETION= "org.eclipse.ui.edit.text.emacsCompletion"; //$NON-NLS-1$ > } >Index: src/org/eclipse/ui/texteditor/EmacsCompleteAction.java >=================================================================== >RCS file: src/org/eclipse/ui/texteditor/EmacsCompleteAction.java >diff -N src/org/eclipse/ui/texteditor/EmacsCompleteAction.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/ui/texteditor/EmacsCompleteAction.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,341 @@ >+package org.eclipse.ui.texteditor; >+ >+import java.util.*; >+ >+import org.eclipse.jface.text.*; >+import org.eclipse.jface.viewers.ISelectionChangedListener; >+import org.eclipse.jface.viewers.SelectionChangedEvent; >+import org.eclipse.ui.*; >+ >+/** >+ * This class implements the emacs style completion action. >+ * Completion action is a stateful action, as the user may invoke >+ * it several times in a row in order to scroll the possible completions. >+ * >+ * >+ * TODO: Work on backward suggestions >+ * TODO: Sort by editor type >+ * TODO: Provide history option >+ * >+ * @author Genady Beryozkin, me@genady.org >+ */ >+public class EmacsCompleteAction extends TextEditorAction { >+ >+ private IDocument doc; >+ private ITextEditor editor; >+ >+ /** >+ * The completion state to continue >+ * the iteration over suggestions >+ */ >+ private CompletionState lastCompletion = null; >+ >+ private boolean modifyingLock = false; >+ >+ SelectionChangeListener selectionListener; >+ DocumentChangeListerner contentListener; >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.ui.texteditor.TextEditorAction#setEditor(org.eclipse.ui.texteditor.ITextEditor) >+ */ >+ public void setEditor(ITextEditor editor) { >+ super.setEditor(editor); >+ >+ if (this.editor != null) { >+ this.editor.getSelectionProvider().removeSelectionChangedListener(selectionListener); >+ doc.removeDocumentListener(contentListener); >+ } >+ this.editor = editor; >+ >+ selectionListener = new SelectionChangeListener(); >+ contentListener = new DocumentChangeListerner(); >+ >+ IEditorInput input = editor.getEditorInput(); >+ doc = editor.getDocumentProvider().getDocument(input); >+ editor.getSelectionProvider().addSelectionChangedListener(selectionListener); >+ doc.addDocumentListener(contentListener); >+ } >+ >+ class SelectionChangeListener implements ISelectionChangedListener { >+ public void selectionChanged(SelectionChangedEvent event) { >+ if (!modifyingLock) { >+ lastCompletion = null; >+ } >+ } >+ } >+ >+ class DocumentChangeListerner implements IDocumentListener { >+ public void documentAboutToBeChanged(DocumentEvent event) { >+ } >+ >+ public void documentChanged(DocumentEvent event) { >+ if (!modifyingLock) { >+ lastCompletion = null; >+ } >+ } >+ } >+ >+ /** >+ * Perform the next completion. >+ */ >+ private void completeNext() { >+ // we don't wish to receive events on our own changes >+ modifyingLock = true; >+ >+ try { >+ doc.replace(lastCompletion.startOffset, lastCompletion.length, >+ lastCompletion.suggestions[lastCompletion.nextSuggestion]); >+ } catch (BadLocationException e) { >+ // we should never get here >+ throw new IllegalStateException(e.toString()); >+ } >+ >+ // advance the suggestion state >+ lastCompletion.advance(); >+ >+ // move the cursor to the insertion point >+ getTextEditor().getSelectionProvider(). >+ setSelection(new TextSelection(lastCompletion.startOffset+lastCompletion.length, 0)); >+ >+ // allow changes >+ modifyingLock = false; >+ } >+ >+ >+ /** >+ * This class represents the state of the last completion process. >+ * Each time the user moves to a new position and calls this action >+ * an instance of this inner classs is created and saved in >+ * {@link #lastCompletion}. >+ */ >+ private static class CompletionState { >+ >+ /** The list of suggestions that was computed when the completion >+ * action was first invoked >+ */ >+ final String[] suggestions; >+ >+ /** The caret position at which we insert the suggestions */ >+ final int startOffset; >+ >+ /** The length of the last suggestion string */ >+ int length; >+ >+ /** The index of next suggestion (index into the suggestion array) */ >+ int nextSuggestion; >+ >+ CompletionState(String[] suggestions, int startOffset) { >+ this.suggestions = suggestions; >+ this.startOffset = startOffset; >+ length = 0; >+ nextSuggestion = 0; >+ } >+ >+ public void advance() { >+ length = suggestions[nextSuggestion].length(); >+ nextSuggestion = (nextSuggestion + 1) % suggestions.length; >+ } >+ } >+ >+ /** >+ * @param bundle the resource bundle >+ * @param prefix a prefix to be prepended to the various resource keys >+ * (described in <code>ResourceAction</code> constructor), or >+ * <code>null</code> if none >+ * @param editor the text editor >+ */ >+ protected EmacsCompleteAction(ResourceBundle bundle, String prefix, ITextEditor editor) { >+ super(bundle, prefix, editor); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.jface.action.Action#run() >+ */ >+ public void run() { >+ if (lastCompletion != null) >+ { >+ completeNext(); >+ return; >+ } >+ String prefix = getCurrentPrefix(); >+ if (prefix == null) { >+ editor.getSite().getShell().getDisplay().beep(); >+ return; >+ } >+ String[] suggestions = getSuggestions(prefix); >+ >+ // if it is single empty suggestion >+ if (suggestions.length == 1) { >+ editor.getSite().getShell().getDisplay().beep(); >+ return; >+ } >+ lastCompletion = new CompletionState(suggestions, >+ ((ITextSelection)editor.getSelectionProvider().getSelection()).getOffset()); >+ completeNext(); >+ editor.setHighlightRange(lastCompletion.startOffset, lastCompletion.length, false); >+ editor.showHighlightRangeOnly(true); >+ //editor. >+ } >+ >+ >+ /** >+ * Create the array of suggestions. It scan all open text editors >+ * and prefers suggestion from the currently open editor. >+ * It also addes the empty suggestion at the end. >+ * >+ * @param currEditor The current editor >+ */ >+ public String[] getSuggestions(String prefix) { >+ >+ // Change the order of open editors, to make the active editor >+ // to appear first. >+ IEditorReference editorsArray[] = editor.getSite().getWorkbenchWindow().getActivePage().getEditorReferences(); >+ ArrayList editorsVector = new ArrayList(); >+ for (int i = 0; i < editorsArray.length; i++) { >+ IEditorPart realEditor = editorsArray[i].getEditor(false); >+ if (realEditor != null) { >+ editorsVector.add(realEditor); >+ } >+ } >+ editorsVector.remove(editor); >+ editorsVector.add(0, editor); >+ >+ // collect the suggestions from all open text editors >+ LinkedList suggestions = new LinkedList(); >+ for (int i = 0; i < editorsVector.size(); i++) { >+ if (editorsVector.get(i) instanceof ITextEditor) { >+ ITextEditor textEditor = (ITextEditor) editorsVector.get(i); >+ IEditorInput input = textEditor.getEditorInput(); >+ IDocument doc = textEditor.getDocumentProvider().getDocument(input); >+ >+ try { >+ suggestions.addAll(getForwardSuggestions(doc, prefix)); >+ } catch (BadLocationException e) { >+ // TODO Auto-generated catch block >+ e.printStackTrace(); >+ } >+ } >+ } >+ >+ makeUnique(suggestions); >+ >+ suggestions.add(""); // empty suggestion >+ return (String[])suggestions.toArray(new String[0]); >+ } >+ >+ >+ /** >+ * Remove duplicate suggestions, leaving the closest to list head. >+ * @param suggestions >+ */ >+ private void makeUnique(LinkedList suggestions) { >+ HashSet seenAlready = new HashSet(); >+ >+ for (Iterator i = suggestions.iterator(); i.hasNext();) { >+ String suggestion = (String) i.next(); >+ if (seenAlready.contains(suggestion)) { >+ i.remove(); >+ } else { >+ seenAlready.add(suggestion); >+ } >+ } >+ } >+ >+ /** >+ * Copied from {@link FindReplaceDocumentAdapter}. >+ * >+ * Converts a non-regex string to a pattern >+ * that can be used with the regex search engine. >+ * >+ * @param string the non-regex pattern >+ * @return the string converted to a regex pattern >+ */ >+ private static String asRegPattern(String string) { >+ StringBuffer out= new StringBuffer(string.length()); >+ boolean quoting= false; >+ >+ for (int i= 0, length= string.length(); i < length; i++) { >+ char ch= string.charAt(i); >+ if (ch == '\\') { >+ if (quoting) { >+ out.append("\\E"); //$NON-NLS-1$ >+ quoting= false; >+ } >+ out.append("\\\\"); //$NON-NLS-1$ >+ continue; >+ } >+ if (!quoting) { >+ out.append("\\Q"); //$NON-NLS-1$ >+ quoting= true; >+ } >+ out.append(ch); >+ } >+ if (quoting) >+ out.append("\\E"); //$NON-NLS-1$ >+ >+ return out.toString(); >+ } >+ >+ >+ /** >+ * Return the list of completion suggestions the correspond to the provided >+ * prefix >+ * >+ * @param document >+ * @param prefix >+ * @return >+ * @throws BadLocationException >+ */ >+ private static ArrayList getForwardSuggestions(IDocument document, String prefix) throws BadLocationException { >+ ArrayList res = new ArrayList(); >+ >+ FindReplaceDocumentAdapter searcher = new >+ FindReplaceDocumentAdapter(document); >+ >+ // search only at word boundaries >+ String searchPattern = "\\b" + asRegPattern(prefix); >+ >+ IRegion reg = searcher.find(0, searchPattern, true, true, false, true); >+ while (reg != null) { >+ // try to complete to a word >+ IRegion word = searcher.find(reg.getOffset(), "\\w+", true, true, false, true); >+ if (word.getLength() > reg.getLength() ) { // empty suggestion will be added later >+ String found = document.get(word.getOffset(), word.getLength()); >+ res.add(found.substring(prefix.length())); >+ } >+ int nextPos = word.getOffset() + word.getLength(); >+ if (nextPos >= document.getLength() ) { >+ break; >+ } >+ reg = searcher.find(nextPos, searchPattern, true, true, false, true); >+ } >+ >+ return res; >+ } >+ >+ /** >+ * Return the part of a word before the caret. >+ * If the caret is not at a middle/end of a word, >+ * returns null. >+ */ >+ public String getCurrentPrefix() { >+ ITextSelection selection = (ITextSelection)editor.getSelectionProvider().getSelection(); >+ if (selection.getLength() > 0) { >+ return null; >+ } >+ int pos = selection.getOffset(); >+ String docText = doc.get(); >+ int prevNonAlpha = pos; >+ while (prevNonAlpha > 0 && >+ Character.isJavaIdentifierPart(docText.charAt(prevNonAlpha-1))) >+ { >+ prevNonAlpha--; >+ } >+ if (prevNonAlpha != pos) { >+ return docText.substring(prevNonAlpha, pos); >+ } else { >+ return null; >+ } >+ >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 11668
:
806
|
14942
|
17032
|
17127
|
17183
|
17184
|
17243
|
17310