/*=============================================================================# # Copyright (c) 2015-2016 Stephan Wahlbrink (WalWare.de) and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at # http://www.eclipse.org/legal/epl-v10.html # # Contributors: # Stephan Wahlbrink - initial API and implementation #=============================================================================*/ package de.walware.docmlet.wikitext.commonmark.ui; import java.util.Locale; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import de.walware.ecommons.ltk.ui.sourceediting.assist.AssistInvocationContext; import de.walware.docmlet.wikitext.commonmark.core.ParseHelper; import de.walware.docmlet.wikitext.core.markup.IMarkupLanguage; import de.walware.docmlet.wikitext.ui.sourceediting.IMarkupCompletionExtension; public class CommonmarkCompletionExtension implements IMarkupCompletionExtension { private final ParseHelper helper= new ParseHelper(); public CommonmarkCompletionExtension() { } @Override public CompletionType getLinkAnchorLabel(final AssistInvocationContext context, final IMarkupLanguage markupLanguage) { try { final IDocument document= context.getDocument(); final int endOffset= context.getOffset(); int beginOffset= endOffset; while (beginOffset > 0) { final char c= document.getChar(--beginOffset); if (Character.isLetterOrDigit(c) || c == '-' || c == '_' || c == ':' || c == '.') { continue; } if (c == '#' && beginOffset > 0 && document.getChar(beginOffset - 1) != '\\') { beginOffset++; return new CompletionType(document.get(beginOffset, endOffset - beginOffset)); } break; } } catch (final BadLocationException e) {} return null; } @Override public CompletionType getLinkRefLabel(final AssistInvocationContext context, final IMarkupLanguage markupLanguage) { try { final IDocument document= context.getDocument(); final int endOffset= context.getInvocationOffset(); int beginOffset= endOffset; final int lookupBound= Math.max(beginOffset - 1000, 0); while (beginOffset > lookupBound) { final char c= document.getChar(--beginOffset); if (c == '[' && !isEscaped(document, beginOffset)) { beginOffset= forwardBlank(document, ++beginOffset, endOffset); final String sourcePrefix= document.get(beginOffset, endOffset - beginOffset); final String lookupPrefix= normalizeLabel(sourcePrefix); return new CompletionType(sourcePrefix, lookupPrefix); } if (c != '\n' || c != '\r') { continue; } break; } } catch (final BadLocationException e) {} return null; } private boolean isEscaped(final IDocument document, int offset) throws BadLocationException { int count= 0; while (offset > 0) { if (document.getChar(--offset) == '\\') { count++; } else { break; } } return (count % 2) == 1; } private int forwardBlank(final IDocument document, int offset, final int endOffset) throws BadLocationException { while (offset < endOffset) { final char c= document.getChar(offset); if (c == ' ' || c == '\t') { offset++; continue; } break; } return offset; } private String normalizeLabel(String label) { if (label.isEmpty()) { return ""; } label= this.helper.collapseWhitespace(label); if (label.isEmpty()) { return ""; } return label.toLowerCase(Locale.ROOT); } }