/* * Copyright 2012 Volodymyr Kyrychenko * * Licensed 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 com.haskforce.features; /* * Adaptation of ErlangBinaryTypedHandler.java from 2012. */ import com.haskforce.psi.HaskellFile; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.editorActions.TypedHandlerDelegate; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.codeInsight.highlighting.BraceMatcher; import com.intellij.codeInsight.highlighting.BraceMatchingUtil; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.tree.IElementType; import com.intellij.util.text.CharArrayCharSequence; import org.jetbrains.annotations.NotNull; /** * Automatically closes multiline Haskell comments. */ public class HaskellTypedHandler extends TypedHandlerDelegate { @Override public Result charTyped(char c, Project project, @NotNull Editor editor, @NotNull PsiFile file) { if (!(file instanceof HaskellFile)) return super.charTyped(c, project, editor, file); if ((c != '{' && c != '-' && c != '#') || !CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) { return Result.CONTINUE; } insertMatchedEndComment(project, editor, file, c); return Result.CONTINUE; } /** * this is almost complete c'n'p from TypedHandler, * This code should be generalized into BraceMatchingUtil to support custom matching braces for plugin developers * * @see com.intellij.codeInsight.editorActions.TypedHandler * @see BraceMatchingUtil */ private static void insertMatchedEndComment(Project project, Editor editor, PsiFile file, char c) { if (!(file instanceof HaskellFile)) return; PsiDocumentManager.getInstance(project).commitAllDocuments(); FileType fileType = file.getFileType(); int offset = editor.getCaretModel().getOffset(); HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset); boolean atEndOfDocument = offset == editor.getDocument().getTextLength(); if (!atEndOfDocument) iterator.retreat(); if (iterator.atEnd()) return; BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator); if (iterator.atEnd()) return; IElementType braceTokenType = iterator.getTokenType(); final CharSequence fileText = editor.getDocument().getCharsSequence(); if (!braceMatcher.isLBraceToken(iterator, fileText, fileType)) return; if (!iterator.atEnd()) { iterator.advance(); if (!iterator.atEnd()) { if (!BraceMatchingUtil.isPairedBracesAllowedBeforeTypeInFileType(braceTokenType, iterator.getTokenType(), fileType)) { return; } if (BraceMatchingUtil.isLBraceToken(iterator, fileText, fileType)) { return; } } iterator.retreat(); } int lparenOffset = BraceMatchingUtil.findLeftmostLParen(iterator, braceTokenType, fileText, fileType); if (lparenOffset < 0) lparenOffset = 0; iterator = ((EditorEx) editor).getHighlighter().createIterator(lparenOffset); if (!BraceMatchingUtil.matchBrace(fileText, fileType, iterator, true, true)) { // Some other mechanism has put the closing '}' in the document already. editor.getDocument().insertString(offset, new CharArrayCharSequence(c)); } } }