All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.languages.yaml.YamlCompletion Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.languages.yaml;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.ImageIcon;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import org.netbeans.modules.csl.api.CodeCompletionContext;
import org.netbeans.modules.csl.api.CodeCompletionHandler;
import org.netbeans.modules.csl.api.CodeCompletionHandler.QueryType;
import org.netbeans.modules.csl.api.CodeCompletionResult;
import org.netbeans.modules.csl.api.CompletionProposal;
import org.netbeans.modules.csl.api.ElementHandle;
import org.netbeans.modules.csl.api.ElementKind;
import org.netbeans.modules.csl.api.HtmlFormatter;
import org.netbeans.modules.csl.api.Modifier;
import org.netbeans.modules.csl.api.OffsetRange;
import org.netbeans.modules.csl.api.ParameterInfo;
import org.netbeans.modules.csl.spi.DefaultCompletionResult;
import org.netbeans.modules.csl.spi.ParserResult;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.ImageUtilities;

/**
 * YAML code completion.
 *
 * @author Tor Norbye
 */
public class YamlCompletion implements CodeCompletionHandler {

    private String refcard;
    // Based http://www.yaml.org/refcard.html
    private static final String[] YAML_KEYS =
            new String[]{
        "? ", "Key indicator.",
        ": ", "Value indicator.",
        "- ", "Nested series entry indicator.",
        ", ", "Separate in-line branch entries.",
        "[]", "Surround in-line series branch.",
        "{}", "Surround in-line keyed branch.",
        "'", "Surround in-line unescaped scalar",
        "\"", "Surround in-line escaped scalar",
        "|", "Block scalar indicator.",
        ">", "Folded scalar indicator.",
        "-", "Strip chomp modifier ('|-' or '>-').",
        "+", "Keep chomp modifier ('|+' or '>+').",
        //1-9  : Explicit indentation modifier ("|1", or '>2').
        //       # Modifiers can be combined ('|2-', '>+1').
        "&", "Anchor property.",
        "*", "Alias indicator.",
        //"none",  "Unspecified tag (automatically resolved by application).",
        "!", "Non-specific tag",
        "!foo", "Primary",
        "!!foo", "Secondary",
        "!h!foo", "Requires \"%TAG !h! \"",
        "!", "Verbatim tag (always means \"foo\").",
        "%", "Directive indicator.",
        "---", "Document header.",
        "...", "Document terminator.",
        "#", "Throwaway comment indicator.",
        "`@", "Both reserved for future use.",
        "=", "Default \"value\" mapping key.",
        "<<", "Merge keys from another mapping.",
        "!!map", "{ Hash table, dictionary, mapping }",
        "!!seq", "{ List, array, tuple, vector, sequence }",
        "!!str", "Unicode string",
        "!!set", "{ cherries, plums, apples }",
        "!!omap", "[ one: 1, two: 2 ]", //{ ~, null }              : Null (no value).
    //[ 1234, 0x4D2, 02333 ]   : [ Decimal int, Hexadecimal int, Octal int ]
    //[ 1_230.15, 12.3015e+02 ]: [ Fixed float, Exponential float ]
    //[ .inf, -.Inf, .NAN ]    : [ Infinity (float), Negative, Not a number ]
    };

    private boolean startsWith(String theString, String prefix, boolean caseSensitive) {
        if (prefix.length() == 0) {
            return true;
        }

        return caseSensitive ? theString.startsWith(prefix)
                : theString.toLowerCase().startsWith(prefix.toLowerCase());
    }

    @Override
    public CodeCompletionResult complete(CodeCompletionContext context) {
        List proposals = new ArrayList();

        boolean caseSensitive = context.isCaseSensitive();
        String prefix = context.getPrefix();
        if (prefix == null) {
            prefix = "";
        }
        int anchor = context.getCaretOffset();

        // Regular expression matching.  {
        for (int i = 0, n = YAML_KEYS.length; i < n; i += 2) {
            String word = YAML_KEYS[i];
            String desc = YAML_KEYS[i + 1];

            if (startsWith(word, prefix, caseSensitive)) {
                KeywordItem item = new KeywordItem(word, desc, anchor, Integer.toString(10000 + i));
                proposals.add(item);
            }
        }

        if (proposals.isEmpty()) {
            // Prefix isn't any of the chars -- so just add all
            for (int i = 0, n = YAML_KEYS.length; i < n; i += 2) {
                String word = YAML_KEYS[i];
                String desc = YAML_KEYS[i + 1];

                KeywordItem item = new KeywordItem(word, desc, anchor, Integer.toString(10000 + i));
                proposals.add(item);
            }
        }
        DefaultCompletionResult result = new DefaultCompletionResult(proposals, false);
        result.setFilterable(false);
        return result;
    }

    @Override
    public String document(ParserResult info, ElementHandle element) {
        if (refcard == null) {
            refcard = ""; // NOI18N
            // TODO: I18N
            InputStream is = null;
            StringBuilder sb = new StringBuilder();

            try {
                InputStream stream = YamlCompletion.class.getResourceAsStream("refcard.html");
                if (stream != null) {
                    is = new BufferedInputStream(stream);
                    while (true) {
                        int c = is.read();

                        if (c == -1) {
                            break;
                        }

                        sb.append((char) c);
                    }
                }
                if (sb.length() > 0) {
                    refcard = sb.toString();
                }
            } catch (IOException ie) {
                Exceptions.printStackTrace(ie);
            } finally {
                try {
                    if (is != null) {
                        is.close();
                    }
                } catch (IOException ie) {
                    Exceptions.printStackTrace(ie);
                }
            }
        }

        return refcard.length() > 0 ? refcard : null;
    }

    @Override
    public ElementHandle resolveLink(String link, ElementHandle originalHandle) {
        return null;
    }

    @Override
    public String getPrefix(ParserResult info, int caretOffset, boolean upToOffset) {
        if (caretOffset > 0) {
            try {
                Document doc = ((YamlParserResult) info).getSnapshot().getSource().getDocument(false);
                if (doc != null) {
                    return doc.getText(caretOffset - 1, 1);
                } else {
                    return null;
                }
            } catch (BadLocationException ex) {
                Exceptions.printStackTrace(ex);
            }
        }

        return null;
    }

    @Override
    public QueryType getAutoQuery(JTextComponent component, String typedText) {
        return QueryType.NONE;
    }

    @Override
    public String resolveTemplateVariable(String variable, ParserResult info, int caretOffset, String name, Map parameters) {
        return null;
    }

    @Override
    public Set getApplicableTemplates(Document doc, int selectionBegin, int selectionEnd) {
        return Collections.emptySet();
    }

    @Override
    public ParameterInfo parameters(ParserResult info, int caretOffset, CompletionProposal proposal) {
        return ParameterInfo.NONE;
    }
    private static ImageIcon keywordIcon;

    private static class KeywordItem implements CompletionProposal, ElementHandle {

        private int anchor;
        private static final String YAML_KEYWORD = "org/netbeans/modules/languages/yaml/yaml_files_16.png"; //NOI18N
        private final String keyword;
        private final String description;
        private final String sort;

        KeywordItem(String keyword, String description, int anchor, String sort) {
            this.keyword = keyword;
            this.description = description;
            this.anchor = anchor;
            this.sort = sort;
        }

        @Override
        public String getName() {
            return keyword;
        }

        @Override
        public ElementKind getKind() {
            return ElementKind.KEYWORD;
        }

        @Override
        public String getRhsHtml(HtmlFormatter formatter) {
            if (description != null) {
                //formatter.appendText(description);
                formatter.appendHtml(description);

                return formatter.getText();
            } else {
                return null;
            }
        }

        @Override
        public ImageIcon getIcon() {
            if (keywordIcon == null) {
                keywordIcon = ImageUtilities.loadImageIcon(YAML_KEYWORD, false);
            }

            return keywordIcon;
        }

        @Override
        public Set getModifiers() {
            return Collections.emptySet();
        }

        @Override
        public ElementHandle getElement() {
            // For completion documentation
            return this;
        }

        @Override
        public boolean isSmart() {
            return false;
        }

        @Override
        public int getAnchorOffset() {
            return anchor;
        }

        @Override
        public String getInsertPrefix() {
            return keyword;
        }

        @Override
        public String getSortText() {
            return sort;
        }

        @Override
        public String getLhsHtml(HtmlFormatter formatter) {
            formatter.name(ElementKind.KEYWORD, true);
            formatter.appendText(getName());
            formatter.name(ElementKind.KEYWORD, false);

            return formatter.getText();
        }

        @Override
        public String getCustomInsertTemplate() {
            return null;
        }

        @Override
        public FileObject getFileObject() {
            return null;
        }

        @Override
        public String getMimeType() {
            return YamlLanguage.MIME_TYPE;
        }

        @Override
        public String getIn() {
            return null;
        }

        @Override
        public boolean signatureEquals(ElementHandle handle) {
            return false;
        }

        @Override
        public int getSortPrioOverride() {
            return 0;
        }

        @Override
        public OffsetRange getOffsetRange(ParserResult result) {
            // FIXME parsing API
            return OffsetRange.NONE;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy