/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/gui/CompleteWord.java
Java | 508 lines | 376 code | 71 blank | 61 comment | 68 complexity | 0cb899081f303b6e9305e5649baaddb6 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
- /*
- * CompleteWord.java - Complete word dialog
- * :tabSize=8:indentSize=8:noTabs=false:
- * :folding=explicit:collapseFolds=1:
- *
- * Copyright (C) 2000, 2001 Slava Pestov
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- package org.gjt.sp.jedit.gui;
- //{{{ Imports
- import java.awt.Component;
- import java.awt.Font;
- import java.awt.Point;
- import java.awt.event.KeyEvent;
- import java.util.HashSet;
- import java.util.Set;
- import java.util.TreeSet;
- import java.util.Arrays;
- import java.util.Collection;
- import javax.swing.DefaultListCellRenderer;
- import javax.swing.JList;
- import javax.swing.SwingUtilities;
- import org.gjt.sp.jedit.Buffer;
- import org.gjt.sp.jedit.EditPane;
- import org.gjt.sp.jedit.visitors.JEditVisitorAdapter;
- import org.gjt.sp.jedit.jEdit;
- import org.gjt.sp.jedit.MiscUtilities;
- import org.gjt.sp.jedit.TextUtilities;
- import org.gjt.sp.jedit.View;
- import org.gjt.sp.jedit.syntax.KeywordMap;
- import org.gjt.sp.jedit.textarea.JEditTextArea;
- import org.gjt.sp.util.StandardUtilities;
- //}}}
- /**
- * A completion popup class.
- */
- public class CompleteWord extends CompletionPopup
- {
- //{{{ completeWord() method
- public static void completeWord(View view)
- {
- JEditTextArea textArea = view.getTextArea();
- Buffer buffer = view.getBuffer();
- int caretLine = textArea.getCaretLine();
- int caret = textArea.getCaretPosition();
- if(!buffer.isEditable())
- {
- textArea.getToolkit().beep();
- return;
- }
- KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret);
- String noWordSep = getNonAlphaNumericWordChars(
- buffer,keywordMap);
- String word = getWordToComplete(buffer,caretLine,
- caret,noWordSep);
- if(word == null)
- {
- textArea.getToolkit().beep();
- return;
- }
- Completion[] completions = getCompletions(buffer,word,caret);
- if(completions.length == 0)
- {
- textArea.getToolkit().beep();
- }
- //{{{ if there is only one competion, insert in buffer
- else if(completions.length == 1)
- {
- Completion c = completions[0];
- if(c.text.equals(word))
- {
- textArea.getToolkit().beep();
- }
- else
- {
- textArea.replaceSelection(c.text.substring(
- word.length()));
- }
- } //}}}
- //{{{ show popup if > 1
- else
- {
- String longestPrefix = MiscUtilities.getLongestPrefix(
- completions,
- keywordMap != null
- ? keywordMap.getIgnoreCase()
- : false);
- if (word.length() < longestPrefix.length())
- {
- buffer.insert(caret,longestPrefix.substring(
- word.length()));
- }
- textArea.scrollToCaret(false);
- Point location = textArea.offsetToXY(
- caret - word.length());
- location.y += textArea.getPainter().getLineHeight();
- SwingUtilities.convertPointToScreen(location,
- textArea.getPainter());
- new CompleteWord(view,longestPrefix,
- completions,location,noWordSep);
- } //}}}
- } //}}}
- //{{{ CompleteWord constructor
- public CompleteWord(View view, String word, Completion[] completions,
- Point location, String noWordSep)
- {
- super(view, location);
- this.noWordSep = noWordSep;
- this.view = view;
- this.textArea = view.getTextArea();
- this.buffer = view.getBuffer();
- this.word = word;
- reset(new Words(completions), true);
- } //}}}
- //{{{ Private members
- //{{{ getNonAlphaNumericWordChars() method
- private static String getNonAlphaNumericWordChars(Buffer buffer,
- KeywordMap keywordMap)
- {
- // figure out what constitutes a word character and what
- // doesn't
- String noWordSep = buffer.getStringProperty("noWordSep");
- if(noWordSep == null)
- noWordSep = "";
- if(keywordMap != null)
- {
- String keywordNoWordSep = keywordMap.getNonAlphaNumericChars();
- if(keywordNoWordSep != null)
- noWordSep += keywordNoWordSep;
- }
- return noWordSep;
- } //}}}
- //{{{ getWordToComplete() method
- private static String getWordToComplete(Buffer buffer, int caretLine,
- int caret, String noWordSep)
- {
- CharSequence line = buffer.getLineSegment(caretLine);
- int dot = caret - buffer.getLineStartOffset(caretLine);
- if(dot == 0)
- return null;
- char ch = line.charAt(dot-1);
- if(!Character.isLetterOrDigit(ch)
- && noWordSep.indexOf(ch) == -1)
- {
- // attempting to expand non-word char
- return null;
- }
- int wordStart = TextUtilities.findWordStart(line,dot-1,noWordSep);
- CharSequence word = line.subSequence(wordStart,dot);
- if(word.length() == 0)
- return null;
- return word.toString();
- } //}}}
-
- //{{{ getVisibleBuffers() method
- private static Collection<Buffer> getVisibleBuffers()
- {
- final Set<Buffer> buffers = new HashSet<Buffer>();
- jEdit.visit(new JEditVisitorAdapter()
- {
- @Override
- public void visit(EditPane editPane)
- {
- buffers.add(editPane.getBuffer());
- }
- });
- return buffers;
- } //}}}
- //{{{ getCompletions() method
- private static Completion[] getCompletions(final Buffer buffer, final String word,
- final int caret)
- {
- // build a list of unique words in all buffers, or visible buffers,
- // depending on completeFromAllBuffers
- final Set<Completion> completions = new TreeSet<Completion>(new StandardUtilities
- .StringCompare<Completion>());
- // only complete current buffer's keyword map
- final KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret);
- final String noWordSep = getNonAlphaNumericWordChars(
- buffer,keywordMap);
-
- final Collection<Buffer> sourceBuffers =
- jEdit.getBooleanProperty("completeFromAllBuffers") ?
- Arrays.asList(jEdit.getBuffers()) :
- getVisibleBuffers();
- for (Buffer b : sourceBuffers)
- {
- // only complete current buffer's keyword map
- KeywordMap _keywordMap;
- if(b == buffer)
- _keywordMap = keywordMap;
- else
- _keywordMap = null;
- int offset = (b == buffer ? caret : 0);
- getCompletions(b,word,keywordMap,noWordSep,
- offset,completions);
- }
- Completion[] completionArray = completions
- .toArray(new Completion[completions.size()]);
- return completionArray;
- } //}}}
- //{{{ getCompletions() method
- private static void getCompletions(Buffer buffer, String word,
- KeywordMap keywordMap, String noWordSep, int caret,
- Set<Completion> completions)
- {
- int wordLen = word.length();
- //{{{ try to find matching keywords
- if(keywordMap != null)
- {
- String[] keywords = keywordMap.getKeywords();
- for(int i = 0; i < keywords.length; i++)
- {
- String _keyword = keywords[i];
- if(_keyword.regionMatches(keywordMap.getIgnoreCase(),
- 0,word,0,wordLen))
- {
- Completion keyword = new Completion(_keyword,true);
- if(!completions.contains(keyword))
- {
- completions.add(keyword);
- }
- }
- }
- } //}}}
- //{{{ loop through all lines of current buffer
- for(int i = 0; i < buffer.getLineCount(); i++)
- {
- CharSequence line = buffer.getLineSegment(i);
- int start = buffer.getLineStartOffset(i);
- // check for match at start of line
- if (StandardUtilities.startsWith(line, word) &&
- caret != start + word.length())
- {
- String _word = completeWord(line,0,noWordSep);
- Completion comp = new Completion(_word,false);
- // remove duplicates
- if(!completions.contains(comp))
- {
- completions.add(comp);
- }
- }
- // check for match inside line
- int len = line.length() - word.length();
- for(int j = 0; j < len; j++)
- {
- char c = line.charAt(j);
- if(!Character.isLetterOrDigit(c) && noWordSep.indexOf(c) == -1)
- {
- if (StandardUtilities.regionMatches(line,j + 1,word,0,wordLen)
- && caret != start + j + word.length() + 1)
- {
- String _word = completeWord(line,j + 1,noWordSep);
- Completion comp = new Completion(_word,false);
- // remove duplicates
- if(!completions.contains(comp))
- {
- completions.add(comp);
- }
- }
- }
- }
- } //}}}
- } //}}}
- //{{{ completeWord() method
- private static String completeWord(CharSequence line, int offset, String noWordSep)
- {
- // '+ 1' so that findWordEnd() doesn't pick up the space at the start
- int wordEnd = TextUtilities.findWordEnd(line,offset + 1,noWordSep);
- return line.subSequence(offset,wordEnd).toString();
- } //}}}
- //{{{ Instance variables
- private View view;
- private JEditTextArea textArea;
- private Buffer buffer;
- private String word;
- private String noWordSep;
- //}}}
- //{{{ Completion class
- private static class Completion
- {
- final String text;
- final boolean keyword;
- Completion(String text, boolean keyword)
- {
- this.text = text;
- this.keyword = keyword;
- }
- public String toString()
- {
- return text;
- }
- public int hashCode()
- {
- return text.hashCode();
- }
- public boolean equals(Object obj)
- {
- if(obj instanceof Completion)
- return ((Completion)obj).text.equals(text);
- else
- return false;
- }
- } //}}}
- //{{{ Words class
- private class Words implements Candidates
- {
- private final DefaultListCellRenderer renderer;
- private final Completion[] completions;
- public Words(Completion[] completions)
- {
- this.renderer = new DefaultListCellRenderer();
- this.completions = completions;
- }
- public int getSize()
- {
- return completions.length;
- }
- public boolean isValid()
- {
- return true;
- }
- public void complete(int index)
- {
- String insertion = completions[index].toString().substring(word.length());
- textArea.replaceSelection(insertion);
- }
- public Component getCellRenderer(JList list, int index,
- boolean isSelected, boolean cellHasFocus)
- {
- renderer.getListCellRendererComponent(list,
- null, index, isSelected, cellHasFocus);
- Completion comp = completions[index];
- String text = comp.text;
- Font font = list.getFont();
- if(index < 9)
- text = (index + 1) + ": " + text;
- else if(index == 9)
- text = "0: " + text;
- if(comp.keyword)
- font = font.deriveFont(Font.BOLD);
- renderer.setText(text);
- renderer.setFont(font);
- return renderer;
- }
- public String getDescription(int index)
- {
- return null;
- }
- } //}}}
- //{{{ resetWords() method
- private void resetWords(String newWord)
- {
- int caret = textArea.getCaretPosition();
- Completion[] completions = getCompletions(
- buffer,newWord,caret);
- if(completions.length > 0)
- {
- word = newWord;
- reset(new Words(completions), true);
- }
- else
- {
- dispose();
- }
- } //}}}
- //}}}
- //{{{ keyPressed() medhod
- protected void keyPressed(KeyEvent e)
- {
- if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE)
- {
- textArea.backspace();
- e.consume();
- if(word.length() == 1)
- {
- dispose();
- }
- else
- {
- resetWords(word.substring(0,word.length() - 1));
- }
- }
- } //}}}
- //{{{ keyTyped() medhod
- protected void keyTyped(KeyEvent e)
- {
- char ch = e.getKeyChar();
- if(Character.isDigit(ch))
- {
- int index = ch - '0';
- if(index == 0)
- index = 9;
- else
- index--;
- if(index < getCandidates().getSize())
- {
- setSelectedIndex(index);
- if(doSelectedCompletion())
- {
- e.consume();
- dispose();
- }
- return;
- }
- else
- /* fall through */;
- }
- // \t handled above
- if(ch != '\b' && ch != '\t')
- {
- /* eg, foo<C+b>, will insert foobar, */
- if(!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1)
- {
- doSelectedCompletion();
- textArea.userInput(ch);
- e.consume();
- dispose();
- return;
- }
- textArea.userInput(ch);
- e.consume();
- resetWords(word + ch);
- }
- } //}}}
- }