mirror of
https://github.com/chylex/IntelliJ-Rainbow-Brackets.git
synced 2025-05-08 21:34:06 +02:00
parent
ec78647a17
commit
2977a08009
README.md
src/main/kotlin/com/chylex/intellij/coloredbrackets
@ -5,3 +5,4 @@ This is a fork of the [🌈Rainbow Brackets](https://github.com/izhangzhihao/int
|
||||
## Key Changes
|
||||
|
||||
- Support for CLion and Rider
|
||||
- Fixed service initialization warnings reported by 2024.2+
|
||||
|
@ -11,11 +11,12 @@ import com.intellij.lang.LanguageExtension
|
||||
import com.intellij.lang.PairedBraceMatcher
|
||||
import com.intellij.psi.tree.IElementType
|
||||
|
||||
@Suppress("ConvertLambdaToReference")
|
||||
object BracePairs {
|
||||
|
||||
private val providers = LanguageExtension<BracePairProvider>("com.chylex.coloredbrackets.bracePairProvider")
|
||||
|
||||
private val bracePairs =
|
||||
private val bracePairs = lazy {
|
||||
Language.getRegisteredLanguages()
|
||||
.map { language ->
|
||||
if (language is CompositeLanguage) {
|
||||
@ -71,8 +72,9 @@ object BracePairs {
|
||||
language.displayName to braceMap
|
||||
}
|
||||
.toMap()
|
||||
}
|
||||
|
||||
fun getBracePairs(language: Language): MutableMap<String, MutableList<BracePair>>? = bracePairs[language.displayName]
|
||||
fun getBracePairs(language: Language): MutableMap<String, MutableList<BracePair>>? = bracePairs.value[language.displayName]
|
||||
|
||||
private fun getBraceTypeSetOf(language: Language): Set<IElementType> = getBracePairs(language)?.values?.flatten()?.map { listOf(it.leftBraceType, it.rightBraceType) }?.flatten()?.toSet() ?: emptySet()
|
||||
|
||||
|
@ -39,16 +39,21 @@ object RainbowHighlighter {
|
||||
private val squigglyBrackets: CharArray = charArrayOf('{', '}')
|
||||
private val angleBrackets: CharArray = charArrayOf('<', '>')
|
||||
|
||||
private val settings = RainbowSettings.instance
|
||||
private val settings
|
||||
get() = RainbowSettings.instance
|
||||
|
||||
private val roundBracketsRainbowColorKeys: Array<TextAttributesKey> =
|
||||
private val roundBracketsRainbowColorKeys = lazy {
|
||||
createRainbowAttributesKeys(KEY_ROUND_BRACKETS, settings.numberOfColors)
|
||||
private val squareBracketsRainbowColorKeys: Array<TextAttributesKey> =
|
||||
}
|
||||
private val squareBracketsRainbowColorKeys = lazy {
|
||||
createRainbowAttributesKeys(KEY_SQUARE_BRACKETS, settings.numberOfColors)
|
||||
private val squigglyBracketsRainbowColorKeys: Array<TextAttributesKey> =
|
||||
}
|
||||
private val squigglyBracketsRainbowColorKeys = lazy {
|
||||
createRainbowAttributesKeys(KEY_SQUIGGLY_BRACKETS, settings.numberOfColors)
|
||||
private val angleBracketsRainbowColorKeys: Array<TextAttributesKey> =
|
||||
}
|
||||
private val angleBracketsRainbowColorKeys = lazy {
|
||||
createRainbowAttributesKeys(KEY_ANGLE_BRACKETS, settings.numberOfColors)
|
||||
}
|
||||
|
||||
private val rainbowElement: HighlightInfoType = HighlightInfoType
|
||||
.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.CONSTANT)
|
||||
@ -68,10 +73,10 @@ object RainbowHighlighter {
|
||||
|
||||
fun getRainbowAttributesKeys(rainbowName: String): Array<TextAttributesKey> {
|
||||
return when (rainbowName) {
|
||||
NAME_ROUND_BRACKETS -> roundBracketsRainbowColorKeys
|
||||
NAME_SQUARE_BRACKETS -> squareBracketsRainbowColorKeys
|
||||
NAME_SQUIGGLY_BRACKETS -> squigglyBracketsRainbowColorKeys
|
||||
NAME_ANGLE_BRACKETS -> angleBracketsRainbowColorKeys
|
||||
NAME_ROUND_BRACKETS -> roundBracketsRainbowColorKeys.value
|
||||
NAME_SQUARE_BRACKETS -> squareBracketsRainbowColorKeys.value
|
||||
NAME_SQUIGGLY_BRACKETS -> squigglyBracketsRainbowColorKeys.value
|
||||
NAME_ANGLE_BRACKETS -> angleBracketsRainbowColorKeys.value
|
||||
else -> throw IllegalArgumentException("Unknown rainbow name: $rainbowName")
|
||||
}
|
||||
}
|
||||
|
@ -20,19 +20,20 @@ class RainbowifyBanner : EditorNotifications.Provider<EditorNotificationPanel>()
|
||||
override fun getKey(): Key<EditorNotificationPanel> = KEY
|
||||
|
||||
override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor, project: Project): EditorNotificationPanel? {
|
||||
val settings = RainbowSettings.instance
|
||||
|
||||
if (!RainbowSettings.instance.isRainbowEnabled) {
|
||||
if (RainbowSettings.instance.suppressDisabledCheck) return null
|
||||
if (!settings.isRainbowEnabled) {
|
||||
if (settings.suppressDisabledCheck) return null
|
||||
return EditorNotificationPanel().apply {
|
||||
text("Colored Brackets is now disabled")
|
||||
icon(AllIcons.General.GearPlain)
|
||||
createComponentActionLabel("got it, don't show again") {
|
||||
RainbowSettings.instance.suppressDisabledCheck = true
|
||||
settings.suppressDisabledCheck = true
|
||||
EditorNotifications.getInstance(project).updateAllNotifications()
|
||||
}
|
||||
|
||||
createComponentActionLabel("enable Colored Brackets") {
|
||||
RainbowSettings.instance.isRainbowEnabled = true
|
||||
settings.isRainbowEnabled = true
|
||||
EditorNotifications.getInstance(project).updateAllNotifications()
|
||||
}
|
||||
}
|
||||
@ -40,12 +41,12 @@ class RainbowifyBanner : EditorNotifications.Provider<EditorNotificationPanel>()
|
||||
|
||||
val psiFile = file.toPsiFile(project)
|
||||
if (psiFile != null && !checkForBigFile(psiFile)) {
|
||||
if (RainbowSettings.instance.suppressBigFileCheck) return null
|
||||
if (settings.suppressBigFileCheck) return null
|
||||
return EditorNotificationPanel().apply {
|
||||
text("Rainbowify is disabled for files > " + RainbowSettings.instance.bigFilesLinesThreshold + " lines")
|
||||
text("Rainbowify is disabled for files > " + settings.bigFilesLinesThreshold + " lines")
|
||||
icon(AllIcons.General.InspectionsEye)
|
||||
createComponentActionLabel("got it, don't show again") {
|
||||
RainbowSettings.instance.suppressBigFileCheck = true
|
||||
settings.suppressBigFileCheck = true
|
||||
EditorNotifications.getInstance(project).updateAllNotifications()
|
||||
}
|
||||
|
||||
@ -57,16 +58,16 @@ class RainbowifyBanner : EditorNotifications.Provider<EditorNotificationPanel>()
|
||||
}
|
||||
|
||||
if (
|
||||
RainbowSettings.instance.languageBlacklist.contains(file.fileType.name) ||
|
||||
RainbowSettings.instance.languageBlacklist.contains(memoizedFileExtension(file.name))
|
||||
settings.languageBlacklist.contains(file.fileType.name) ||
|
||||
settings.languageBlacklist.contains(memoizedFileExtension(file.name))
|
||||
) {
|
||||
if (RainbowSettings.instance.suppressBlackListCheck) return null
|
||||
if (settings.suppressBlackListCheck) return null
|
||||
return EditorNotificationPanel().apply {
|
||||
text("Rainbowify is disabled because the language/file extension is in the black list")
|
||||
icon(AllIcons.General.InspectionsEye)
|
||||
|
||||
createComponentActionLabel("got it, don't show again") {
|
||||
RainbowSettings.instance.suppressBlackListCheck = true
|
||||
settings.suppressBlackListCheck = true
|
||||
EditorNotifications.getInstance(project).updateAllNotifications()
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package com.chylex.intellij.coloredbrackets.action
|
||||
|
||||
import com.chylex.intellij.coloredbrackets.RainbowInfo
|
||||
import com.intellij.codeInsight.highlighting.HighlightManager
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
@ -19,6 +20,10 @@ import java.awt.event.KeyEvent
|
||||
|
||||
abstract class AbstractScopeHighlightingAction : AnAction() {
|
||||
|
||||
final override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.BGT
|
||||
}
|
||||
|
||||
final override fun update(e: AnActionEvent) {
|
||||
e.presentation.isEnabledAndVisible = e.editor.let { it != null && it !is TextComponentEditor }
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ class ScopeOutsideHighlightingRestrainAction : AbstractScopeHighlightingAction()
|
||||
val highlighters = LinkedList<RangeHighlighter>()
|
||||
|
||||
val startOffset = rainbowInfo.startOffset
|
||||
val hideByAnyKey = RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects
|
||||
|
||||
if (startOffset > 0) {
|
||||
highlightManager.addRangeHighlight(
|
||||
this,
|
||||
@ -33,7 +35,7 @@ class ScopeOutsideHighlightingRestrainAction : AbstractScopeHighlightingAction()
|
||||
startOffset,
|
||||
attributes, //create("ScopeOutsideHighlightingRestrainAction", attributes),
|
||||
false, //hideByTextChange
|
||||
RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects, //hideByAnyKey
|
||||
hideByAnyKey, //hideByAnyKey
|
||||
highlighters
|
||||
)
|
||||
}
|
||||
@ -47,7 +49,7 @@ class ScopeOutsideHighlightingRestrainAction : AbstractScopeHighlightingAction()
|
||||
lastOffset,
|
||||
attributes, //create("ScopeOutsideHighlightingRestrainAction", attributes),
|
||||
false, //hideByTextChange
|
||||
RainbowSettings.instance.pressAnyKeyToRemoveTheHighlightingEffects, //hideByAnyKey
|
||||
hideByAnyKey, //hideByAnyKey
|
||||
highlighters
|
||||
)
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
|
||||
class RainbowAnnotator : Annotator {
|
||||
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
||||
val settings = settings
|
||||
if (settings.isRainbowEnabled && element is LeafPsiElement) {
|
||||
if (!settings.applyColorsOfRoundForAllBrackets) {
|
||||
if (settings.isEnableRainbowRoundBrackets) annotateUtil(element, holder, "(", ")", NAME_ROUND_BRACKETS)
|
||||
@ -40,7 +41,8 @@ object RainbowUtils {
|
||||
private val leftBracketsSet = setOf("(", "[", "{", "<")
|
||||
private val rightBracketsSet = setOf(")", "]", "}", ">")
|
||||
|
||||
val settings = RainbowSettings.instance
|
||||
val settings
|
||||
get() = RainbowSettings.instance
|
||||
|
||||
private tailrec fun iterateChildren(
|
||||
LEFT: String,
|
||||
|
@ -5,7 +5,6 @@ import com.intellij.codeHighlighting.TextEditorHighlightingPass
|
||||
import com.intellij.codeInsight.highlighting.BraceMatchingUtil
|
||||
import com.intellij.codeInsight.highlighting.CodeBlockSupportHandler
|
||||
import com.intellij.ide.actions.ToggleZenModeAction
|
||||
import com.intellij.lang.Language
|
||||
import com.intellij.lang.LanguageParserDefinitions
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.IndentGuideDescriptor
|
||||
@ -231,7 +230,7 @@ class RainbowIndentsPass internal constructor(
|
||||
*/
|
||||
|
||||
private inner class IndentsCalculator {
|
||||
val myComments: MutableMap<Language, TokenSet> = HashMap()
|
||||
val myComments: MutableMap<String, TokenSet> = HashMap()
|
||||
val lineIndents = IntArray(document.lineCount) // negative value means the line is empty (or contains a comment) and indent
|
||||
|
||||
// (denoted by absolute value) was deduced from enclosing non-empty lines
|
||||
@ -317,7 +316,7 @@ class RainbowIndentsPass internal constructor(
|
||||
return false
|
||||
}
|
||||
val language = tokenType.language
|
||||
var comments: TokenSet? = myComments[language]
|
||||
var comments: TokenSet? = myComments[language.id]
|
||||
if (comments == null) {
|
||||
val definition = LanguageParserDefinitions.INSTANCE.forLanguage(language)
|
||||
if (definition != null) {
|
||||
@ -327,7 +326,7 @@ class RainbowIndentsPass internal constructor(
|
||||
return false
|
||||
}
|
||||
else {
|
||||
myComments[language] = comments
|
||||
myComments[language.id] = comments
|
||||
}
|
||||
}
|
||||
return comments.contains(tokenType)
|
||||
|
@ -16,18 +16,21 @@ class DefaultRainbowVisitor : RainbowHighlightVisitor() {
|
||||
|
||||
override fun visit(element: PsiElement) {
|
||||
val type = (element as? LeafPsiElement)?.elementType ?: return
|
||||
val matching = filterPairs(type, element) ?: return
|
||||
|
||||
val settings = RainbowSettings.instance
|
||||
val processor = Processor(settings)
|
||||
val matching = processor.filterPairs(type, element) ?: return
|
||||
|
||||
val pair =
|
||||
if (matching.size == 1) {
|
||||
matching[0]
|
||||
}
|
||||
else {
|
||||
matching.find { element.isValidBracket(it) }
|
||||
matching.find { processor.isValidBracket(element, it) }
|
||||
} ?: return
|
||||
|
||||
val level = element.getBracketLevel(pair)
|
||||
if (RainbowSettings.instance.isDoNOTRainbowifyTheFirstLevel) {
|
||||
val level = processor.getBracketLevel(element, pair)
|
||||
if (settings.isDoNOTRainbowifyTheFirstLevel) {
|
||||
if (level >= 1) {
|
||||
rainbowPairs(element, pair, level)
|
||||
}
|
||||
@ -45,9 +48,9 @@ class DefaultRainbowVisitor : RainbowHighlightVisitor() {
|
||||
element.setHighlightInfo(element.parent, level, startElement, endElement)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private class Processor(private val settings: RainbowSettings) {
|
||||
|
||||
private fun LeafPsiElement.getBracketLevel(pair: BracePair): Int = iterateBracketParents(parent, pair, -1)
|
||||
fun getBracketLevel(element: LeafPsiElement, pair: BracePair): Int = iterateBracketParents(element.parent, pair, -1)
|
||||
|
||||
private tailrec fun iterateBracketParents(element: PsiElement?, pair: BracePair, count: Int): Int {
|
||||
if (element == null || element is PsiFile) {
|
||||
@ -55,7 +58,7 @@ class DefaultRainbowVisitor : RainbowHighlightVisitor() {
|
||||
}
|
||||
|
||||
var nextCount = count
|
||||
if (!RainbowSettings.instance.cycleCountOnAllBrackets) {
|
||||
if (!settings.cycleCountOnAllBrackets) {
|
||||
if (element.haveBrackets(
|
||||
{ it.elementType() == pair.leftBraceType },
|
||||
{ it.elementType() == pair.rightBraceType })
|
||||
@ -109,7 +112,7 @@ class DefaultRainbowVisitor : RainbowHighlightVisitor() {
|
||||
}
|
||||
|
||||
//For https://github.com/izhangzhihao/intellij-rainbow-brackets/issues/830
|
||||
if (RainbowSettings.instance.doNOTRainbowifyTemplateString) {
|
||||
if (settings.doNOTRainbowifyTemplateString) {
|
||||
if (left?.prevSibling?.textMatches("$") == true) return false
|
||||
}
|
||||
|
||||
@ -120,18 +123,18 @@ class DefaultRainbowVisitor : RainbowHighlightVisitor() {
|
||||
return (this as? LeafPsiElement)?.elementType
|
||||
}
|
||||
|
||||
private fun LeafPsiElement.isValidBracket(pair: BracePair): Boolean {
|
||||
val pairType = when (elementType) {
|
||||
fun isValidBracket(element: LeafPsiElement, pair: BracePair): Boolean {
|
||||
val pairType = when (element.elementType) {
|
||||
pair.leftBraceType -> pair.rightBraceType
|
||||
pair.rightBraceType -> pair.leftBraceType
|
||||
else -> return false
|
||||
}
|
||||
|
||||
return if (pairType == pair.leftBraceType) {
|
||||
checkBracePair(this, parent.firstChild, pairType, PsiElement::getNextSibling)
|
||||
checkBracePair(element, element.parent.firstChild, pairType, PsiElement::getNextSibling)
|
||||
}
|
||||
else {
|
||||
checkBracePair(this, parent.lastChild, pairType, PsiElement::getPrevSibling)
|
||||
checkBracePair(element, element.parent.lastChild, pairType, PsiElement::getPrevSibling)
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,25 +156,25 @@ class DefaultRainbowVisitor : RainbowHighlightVisitor() {
|
||||
return false
|
||||
}
|
||||
|
||||
private fun filterPairs(type: IElementType, element: LeafPsiElement): List<BracePair>? {
|
||||
fun filterPairs(type: IElementType, element: LeafPsiElement): List<BracePair>? {
|
||||
val pairs = element.language.bracePairs ?: return null
|
||||
val filterBraceType = pairs[type.toString()]
|
||||
return when {
|
||||
filterBraceType.isNullOrEmpty() -> {
|
||||
filterBraceType.isNullOrEmpty() -> {
|
||||
null
|
||||
}
|
||||
// https://github.com/izhangzhihao/intellij-rainbow-brackets/issues/198
|
||||
element.javaClass.simpleName == "OCMacroForeignLeafElement" -> {
|
||||
element.javaClass.simpleName == "OCMacroForeignLeafElement" -> {
|
||||
null
|
||||
}
|
||||
|
||||
RainbowSettings.instance.isDoNOTRainbowifyBracketsWithoutContent -> {
|
||||
settings.isDoNOTRainbowifyBracketsWithoutContent -> {
|
||||
filterBraceType
|
||||
.filterNot { it.leftBraceType == type && element.nextSibling?.elementType() == it.rightBraceType }
|
||||
.filterNot { it.rightBraceType == type && element.prevSibling?.elementType() == it.leftBraceType }
|
||||
}
|
||||
|
||||
else -> {
|
||||
else -> {
|
||||
filterBraceType
|
||||
}
|
||||
}
|
||||
|
@ -21,10 +21,12 @@ abstract class RainbowHighlightVisitor : HighlightVisitor {
|
||||
private var highlightInfoHolder: HighlightInfoHolder? = null
|
||||
|
||||
override fun suitableForFile(file: PsiFile): Boolean {
|
||||
return RainbowSettings.instance.isRainbowEnabled &&
|
||||
val settings = RainbowSettings.instance
|
||||
|
||||
return settings.isRainbowEnabled &&
|
||||
checkForBigFile(file) &&
|
||||
!RainbowSettings.instance.languageBlacklist.contains(file.fileType.name) &&
|
||||
!RainbowSettings.instance.languageBlacklist.contains(memoizedFileExtension(file.name)) &&
|
||||
!settings.languageBlacklist.contains(file.fileType.name) &&
|
||||
!settings.languageBlacklist.contains(memoizedFileExtension(file.name)) &&
|
||||
fileIsNotHaskellOrIntelliJHaskellPluginNotEnabled(file.fileType.name)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user