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 17127 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]
Few comments addressed
HippieCompletion-v2-M4.diff (text/plain), 19.23 KB, created by
Genady Beryozkin
on 2005-01-12 17:21:33 EST
(
hide
)
Description:
Few comments addressed
Filename:
MIME Type:
Creator:
Genady Beryozkin
Created:
2005-01-12 17:21:33 EST
Size:
19.23 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 12 Jan 2005 22:18:16 -0000 >@@ -152,6 +152,8 @@ > command.toggleOverwrite.name = Toggle Overwrite > command.toggleInsertMode.description = Toggle insert mode > command.toggleInsertMode.name = Toggle Insert Mode >+command.hippieCompletion.description = Context insensitive completion >+command.hippieCompletion.name = Hippie 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.60 >diff -u -r1.60 plugin.xml >--- plugin.xml 9 Dec 2004 10:31:30 -0000 1.60 >+++ plugin.xml 12 Jan 2005 22:18:17 -0000 >@@ -426,6 +426,19 @@ > categoryId="org.eclipse.ui.category.edit" > id="org.eclipse.ui.edit.text.toggleInsertMode"> > </command> >+ <command >+ name="%command.hippieCompletion.name" >+ description="%command.hippieCompletion.description" >+ categoryId="org.eclipse.ui.category.edit" >+ id="org.eclipse.ui.edit.text.hippieCompletion"> >+ </command> >+ <!-- TODO Keybinding --> >+ <keyBinding >+ commandId="org.eclipse.ui.edit.text.hippieCompletion" >+ contextId="org.eclipse.ui.textEditorScope" >+ keySequence="Alt+/" >+ keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration"> >+ </keyBinding> > > <keyBinding > commandId="org.eclipse.ui.edit.text.delete.line" >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.148 >diff -u -r1.148 AbstractTextEditor.java >--- src/org/eclipse/ui/texteditor/AbstractTextEditor.java 6 Dec 2004 09:35:07 -0000 1.148 >+++ src/org/eclipse/ui/texteditor/AbstractTextEditor.java 12 Jan 2005 22:18:20 -0000 >@@ -4272,6 +4272,11 @@ > action.setActionDefinitionId(ITextEditorActionDefinitionIds.TOGGLE_INSERT_MODE); > setAction(ITextEditorActionConstants.TOGGLE_INSERT_MODE, action); > >+ action = new HippieCompleteAction(EditorMessages.getResourceBundle(), "Editor.HippieCompletion.", this); //$NON-NLS-1$ >+ // TODO action.setHelpContextId(IAbstractTextEditorHelpContextIds.HIPPIE_COMPLETION_ACTION); >+ action.setActionDefinitionId(ITextEditorActionDefinitionIds.HIPPIE_COMPLETION); >+ setAction(ITextEditorActionConstants.HIPPIE_COMPLETION, action); >+ > PropertyDialogAction openProperties= new PropertyDialogAction( > getSite().getShell(), > new ISelectionProvider() { >@@ -4295,6 +4300,7 @@ > markAsContentDependentAction(ITextEditorActionConstants.FIND_PREVIOUS, true); > markAsContentDependentAction(ITextEditorActionConstants.FIND_INCREMENTAL, true); > markAsContentDependentAction(ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE, true); >+ markAsContentDependentAction(ITextEditorActionConstants.HIPPIE_COMPLETION, true); > > markAsSelectionDependentAction(ITextEditorActionConstants.CUT, true); > markAsSelectionDependentAction(ITextEditorActionConstants.COPY, 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.19 >diff -u -r1.19 ITextEditorActionConstants.java >--- src/org/eclipse/ui/texteditor/ITextEditorActionConstants.java 8 Dec 2004 15:06:02 -0000 1.19 >+++ src/org/eclipse/ui/texteditor/ITextEditorActionConstants.java 12 Jan 2005 22:18:20 -0000 >@@ -517,4 +517,11 @@ > * @since 3.1 > */ > static final String QUICKDIFF_TOGGLE= "QuickDiff.Toggle"; //$NON-NLS-1$ >+ >+ /** >+ * Name of the action for emacs style hippie completion. >+ * Value: <code>"HIPPIE_COMPLETION"</code> >+ * @since 3.1 >+ */ >+ static final String HIPPIE_COMPLETION= "HIPPIE_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.18 >diff -u -r1.18 ITextEditorActionDefinitionIds.java >--- src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java 8 Dec 2004 15:06:02 -0000 1.18 >+++ src/org/eclipse/ui/texteditor/ITextEditorActionDefinitionIds.java 12 Jan 2005 22:18:21 -0000 >@@ -485,4 +485,11 @@ > * @since 3.1 > */ > static final String LINENUMBER_TOGGLE= "org.eclipse.ui.editors.lineNumberToggle"; //$NON-NLS-1$ >+ >+ /** >+ * Action definition ID of the edit -> text complete action >+ * Value: <code>"org.eclipse.ui.edit.text.hippieCompletion"</code>). >+ * @since 3.1 >+ */ >+ public static final String HIPPIE_COMPLETION= "org.eclipse.ui.edit.text.hippieCompletion"; //$NON-NLS-1$ > } >Index: src/org/eclipse/ui/texteditor/HippieCompleteAction.java >=================================================================== >RCS file: src/org/eclipse/ui/texteditor/HippieCompleteAction.java >diff -N src/org/eclipse/ui/texteditor/HippieCompleteAction.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/ui/texteditor/HippieCompleteAction.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,412 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2005 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Common Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/cpl-v10.html >+ * >+ * Contributors: >+ * Genady Beryozkin, me@genady.org - initial API and implementation >+ * IBM Corporation - fixes and cleaning >+ *******************************************************************************/ >+package org.eclipse.ui.texteditor; >+ >+import java.util.ArrayList; >+import java.util.HashSet; >+import java.util.Iterator; >+import java.util.LinkedList; >+import java.util.ResourceBundle; >+ >+import org.eclipse.jface.text.BadLocationException; >+import org.eclipse.jface.text.DocumentEvent; >+import org.eclipse.jface.text.FindReplaceDocumentAdapter; >+import org.eclipse.jface.text.IDocument; >+import org.eclipse.jface.text.IDocumentListener; >+import org.eclipse.jface.text.IRegion; >+import org.eclipse.jface.text.ITextSelection; >+import org.eclipse.jface.viewers.ISelectionChangedListener; >+import org.eclipse.jface.viewers.ISelectionProvider; >+import org.eclipse.jface.viewers.SelectionChangedEvent; >+ >+import org.eclipse.ui.IEditorInput; >+import org.eclipse.ui.IEditorPart; >+import org.eclipse.ui.IEditorReference; >+ >+/** >+ * 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 HippieCompleteAction extends TextEditorAction { >+ >+ /** >+ * The document that will be manipulated >+ */ >+ private IDocument fDocument; >+ >+ /** >+ * The selection provider associated with the text editor. >+ */ >+ private ISelectionProvider fSelectionProvider; >+ >+ /** >+ * The completion state that is used to continue the iteration over suggestions >+ */ >+ private CompletionState fLastCompletion= null; >+ >+ /** >+ * Modification lock that will prevent invalidation of the completion state when the >+ * completion action modifies the document >+ */ >+ private boolean fModifyingLock= false; >+ >+ SelectionChangeListener fSelectionListener; >+ DocumentChangeListener fContentListener; >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.ui.texteditor.TextEditorAction#setEditor(org.eclipse.ui.texteditor.ITextEditor) >+ */ >+ public void setEditor(ITextEditor editor) { >+ super.setEditor(editor); >+ >+ fSelectionListener= new SelectionChangeListener(); >+ fContentListener= new DocumentChangeListener(); >+ } >+ >+ /** >+ * This class accompanies the {@link HippieCompleteAction#checkValidPosition()} method >+ * to invalidate completion state when the selection changes. >+ */ >+ class SelectionChangeListener implements ISelectionChangedListener { >+ public void selectionChanged(SelectionChangedEvent event) { >+ if (!fModifyingLock) { >+ fLastCompletion= null; >+ } >+ } >+ } >+ >+ /** >+ * Invalidate the completion state when the document contents changes not >+ * as the result of the completion action itself. This is needed since >+ * the {@link HippieCompleteAction#update()} method is only called when the >+ * {@link HippieCompleteAction#fModifyingLock} is already false. >+ */ >+ class DocumentChangeListener implements IDocumentListener { >+ public void documentAboutToBeChanged(DocumentEvent event) { >+ } >+ >+ public void documentChanged(DocumentEvent event) { >+ if (!fModifyingLock) { >+ fLastCompletion= null; >+ } >+ } >+ } >+ >+ /** >+ * Perform the next completion. >+ */ >+ private void completeNext() { >+ // we don't wish to receive events on our own changes >+ fModifyingLock= true; >+ >+ try { >+ fDocument.replace(fLastCompletion.startOffset, fLastCompletion.length, >+ fLastCompletion.suggestions[fLastCompletion.nextSuggestion]); >+ } catch (BadLocationException e) { >+ // we should never get here >+ throw new IllegalStateException(e.toString()); >+ } >+ >+ // advance the suggestion state >+ fLastCompletion.advance(); >+ >+ // move the cursor to the insertion point >+ ((AbstractTextEditor) getTextEditor()).getSourceViewer().setSelectedRange(fLastCompletion.startOffset+fLastCompletion.length, 0); >+ >+ // allow changes >+ fModifyingLock= 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 #fLastCompletion}. >+ */ >+ 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 HippieCompleteAction(ResourceBundle bundle, String prefix, ITextEditor editor) { >+ super(bundle, prefix, editor); >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.jface.action.Action#run() >+ */ >+ public void run() { >+ checkValidPosition(); >+ if (fLastCompletion != null) >+ { >+ completeNext(); >+ return; >+ } >+ String prefix= getCurrentPrefix(); >+ if (prefix == null) { >+ getTextEditor().getSite().getShell().getDisplay().beep(); >+ return; >+ } >+ String[] suggestions= getSuggestions(prefix); >+ >+ // if it is single empty suggestion >+ if (suggestions.length == 1) { >+ getTextEditor().getSite().getShell().getDisplay().beep(); >+ return; >+ } >+ fLastCompletion= new CompletionState(suggestions, >+ ((ITextSelection) getTextEditor().getSelectionProvider().getSelection()).getOffset()); >+ completeNext(); >+ } >+ >+ /** >+ * Invalidate the completion state if the cursor is not located at >+ * the expected position. >+ */ >+ private void checkValidPosition() { >+ if (fLastCompletion != null) { >+ if (fLastCompletion.startOffset + fLastCompletion.length != >+ ((ITextSelection)fSelectionProvider.getSelection()).getOffset()) { >+ fLastCompletion= null; >+ } >+ } >+ } >+ >+ >+ /** >+ * 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 prefix the prefix to search for >+ * @return the list of all possible suggestions in the currently open editors >+ */ >+ public String[] getSuggestions(String prefix) { >+ >+ // Change the order of open editors, to make the active editor >+ // to appear first. >+ IEditorReference editorsArray[]= getTextEditor().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(getTextEditor()); >+ editorsVector.add(0, getTextEditor()); >+ >+ // 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) { >+ // do nothing >+ // TODO log the exception >+ } >+ } >+ } >+ >+ makeUnique(suggestions); >+ >+ // add the empty suggestion >+ suggestions.add(""); //$NON-NLS-1$ >+ return (String[])suggestions.toArray(new String[0]); >+ } >+ >+ >+ /** >+ * Remove duplicate suggestions (excluding the prefix), leaving the closest to list head. >+ * @param suggestions a modifiable list of 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 an {@link ArrayList} of possible completions, excluding the common prefix >+ * @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); //$NON-NLS-1$ >+ >+ 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); //$NON-NLS-1$ >+ 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. >+ * @return the prefix at the current cursor position that will be used in the search for possible completions >+ */ >+ private String getCurrentPrefix() { >+ ITextSelection selection= (ITextSelection) getTextEditor().getSelectionProvider().getSelection(); >+ if (selection.getLength() > 0) { >+ return null; >+ } >+ int pos= selection.getOffset(); >+ String docText= fDocument.get(); >+ int prevNonAlpha= pos; >+ while (prevNonAlpha > 0 && >+ Character.isJavaIdentifierPart(docText.charAt(prevNonAlpha-1))) >+ { >+ prevNonAlpha--; >+ } >+ if (prevNonAlpha != pos) { >+ return docText.substring(prevNonAlpha, pos); >+ } >+ return null; >+ } >+ >+ /* (non-Javadoc) >+ * @see org.eclipse.ui.texteditor.TextEditorAction#update() >+ */ >+ public void update() { >+ super.update(); >+ if (fDocument != null) { >+ fDocument.removeDocumentListener(fContentListener); >+ } >+ if (fSelectionProvider != null) { >+ fSelectionProvider.removeSelectionChangedListener(fSelectionListener); >+ } >+ >+ ITextEditor editor= getTextEditor(); >+ IEditorInput input= editor.getEditorInput(); >+ >+ fSelectionProvider= editor.getSelectionProvider(); >+ fSelectionProvider.addSelectionChangedListener(fSelectionListener); >+ >+ IDocument oldDocument = fDocument; >+ fDocument= editor.getDocumentProvider().getDocument(input); >+ fDocument.addDocumentListener(fContentListener); >+ >+ if (fDocument != oldDocument) { >+ fLastCompletion = null; // invalidate completion state on editor reuse >+ } >+ } >+}
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