package ctagsinterface.jedit; import java.awt.Component; import java.awt.Point; import java.util.Vector; import javax.swing.DefaultListCellRenderer; import javax.swing.JList; import javax.swing.SwingUtilities; import org.gjt.sp.jedit.Buffer; import org.gjt.sp.jedit.View; import org.gjt.sp.jedit.gui.CompletionPopup.Candidates; import org.gjt.sp.jedit.textarea.JEditTextArea; import org.gjt.sp.jedit.textarea.TextAreaPainter; import superabbrevs.SuperAbbrevs; import ctagsinterface.index.TagIndex; import ctagsinterface.main.CtagsInterfacePlugin; import ctagsinterface.main.KindIconProvider; import ctagsinterface.main.Tag; import ctagsinterface.main.LanguageMap; import ctagsinterface.options.GeneralOptionPane; public class TagCompletion { private View view; private String prefix; public static void complete(View view, String prefix) { final TagCompletion completion = new TagCompletion(view, prefix); final Vector<Tag> tags = completion.getCompletions(); if (tags == null || tags.isEmpty()) return; if (tags.size() > 1) { JEditTextArea ta = view.getTextArea(); int caret = ta.getCaretPosition(); Point location = ta.offsetToXY(caret - prefix.length()); TextAreaPainter painter = ta.getPainter(); location.y += painter.getFontMetrics().getHeight(); SwingUtilities.convertPointToScreen(location, painter); TagCompletionPopup popup = new TagCompletionPopup(view, location); TagCandidates candidates = completion.new TagCandidates(tags, popup); popup.reset(candidates, true); } else completion.complete(tags.get(0)); } class TagCandidates implements Candidates { private Vector<Tag> tags; private Vector<Tag> shownTags; private DefaultListCellRenderer renderer; private TagCompletionPopup popup; @SuppressWarnings("serial") public TagCandidates(final Vector<Tag> tags, TagCompletionPopup popup) { shownTags = this.tags = tags; this.popup = popup; renderer = new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Tag tag = shownTags.get(index); if (isSelected) TagCandidates.this.popup.setSelectedTag(tag); super.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); String kind = tag.getKind(); if (kind == null) kind = ""; setIcon(KindIconProvider.getIcon(kind)); String prefix = (index <= 9) ? index + ": " : ""; setText(prefix + getCompletionString(tag)); return this; } }; } public int indexForKey(char ch) { if (Character.isDigit(ch)) return ch - '0'; return (-1); } public void narrow(char c) { if (c == '\b') prefix = prefix.substring(0, prefix.length() - 1); else prefix = prefix + c; shownTags = new Vector<Tag>(); for (Tag t: tags) { if (t.getName().startsWith(prefix)) shownTags.add(t); } popup.reset(this, true); } public void complete(int index) { TagCompletion.this.complete(shownTags.get(index)); } public Component getCellRenderer(JList list, int index, boolean isSelected, boolean cellHasFocus) { return renderer.getListCellRendererComponent(list, null, index, isSelected, cellHasFocus); } public String getDescription(int index) { return null; } public int getSize() { return shownTags.size(); } public boolean isValid() { return true; } } public TagCompletion(View view, String prefix) { this.view = view; this.prefix = prefix; } public String getLanguage(View view) { LanguageMap langMap = CtagsInterfacePlugin.getLangMap(); String language = langMap.getLanguage(view); return language; } public String getCompletionString(Tag tag) { StringBuffer sb = new StringBuffer(); sb.append(tag.getName()); String signature = tag.getExtension("signature"); if (signature != null && signature.length() > 0) sb.append(signature); String namespace = tag.getNamespace(); if (namespace != null && namespace.length() > 0) sb.append(" - " + namespace); return sb.toString(); } public Vector<Tag> getCompletions() { String q = TagIndex._NAME_FLD + ":" + prefix + "*"; return CtagsInterfacePlugin.runScopedQuery(view, q); } public String createAbbrev(String signature) { StringBuffer sb = new StringBuffer(); boolean startParam = false; for (int i = 0; i < signature.length(); i++) { char c = signature.charAt(i); switch (c) { case ',': sb.append("}"); // fall through case '(': startParam = true; sb.append(c); break; case ')': if (! startParam) // Case of 'f()' - no parameters sb.append("}"); sb.append(c); break; case ' ': case '\t': case '\n': sb.append(c); break; default: if (startParam) { startParam = false; sb.append("${"); sb.append(i + 1); sb.append(":"); } sb.append(c); break; } } return sb.toString(); } public void complete(Tag tag) { Buffer b = view.getBuffer(); String s = tag.getName(); b.insert(view.getTextArea().getCaretPosition(), s.substring(prefix.length())); // Check if a parametrized abbreviation is needed String sig = tag.getExtension("signature"); if (sig == null || sig.length() == 0) return; String abbrev = createAbbrev(sig); SuperAbbrevs.expandAbbrev(view, abbrev, null); } }