| /*=============================================================================# |
| # Copyright (c) 2015, 2018 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.docmlet.wikitext.commonmark.ui; |
| |
| import java.util.Locale; |
| |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| |
| import org.eclipse.statet.docmlet.wikitext.commonmark.core.ParseHelper; |
| import org.eclipse.statet.docmlet.wikitext.core.markup.IMarkupLanguage; |
| import org.eclipse.statet.docmlet.wikitext.ui.sourceediting.IMarkupCompletionExtension; |
| import org.eclipse.statet.ltk.ui.sourceediting.assist.AssistInvocationContext; |
| |
| |
| 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 startOffset= endOffset; |
| while (startOffset > 0) { |
| final char c= document.getChar(--startOffset); |
| if (Character.isLetterOrDigit(c) || c == '-' || c == '_' || c == ':' || c == '.') { |
| continue; |
| } |
| if (c == '#' && startOffset > 0 && document.getChar(startOffset - 1) != '\\') { |
| startOffset++; |
| return new CompletionType(document.get(startOffset, endOffset - startOffset)); |
| } |
| 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 startOffset= endOffset; |
| final int lookupBound= Math.max(startOffset - 1000, 0); |
| while (startOffset > lookupBound) { |
| final char c= document.getChar(--startOffset); |
| if (c == '[' && !isEscaped(document, startOffset)) { |
| startOffset= forwardBlank(document, ++startOffset, endOffset); |
| final String sourcePrefix= document.get(startOffset, endOffset - startOffset); |
| 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); |
| } |
| |
| } |