mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-10-10 08:09:39 +00:00
support: basic idea plugin
This commit is contained in:
@ -0,0 +1,26 @@
|
||||
package gay.pizza.pork.intellij
|
||||
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import javax.swing.Icon
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
object PorkFileType : LanguageFileType(PorkLanguage) {
|
||||
override fun getName(): @NonNls String {
|
||||
return "Pork File"
|
||||
}
|
||||
|
||||
override fun getDescription(): @NlsContexts.Label String {
|
||||
return "Pork file"
|
||||
}
|
||||
|
||||
override fun getDefaultExtension(): @NlsSafe String {
|
||||
return "pork"
|
||||
}
|
||||
|
||||
override fun getIcon(): Icon {
|
||||
return PorkIcon
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package gay.pizza.pork.intellij
|
||||
|
||||
import com.intellij.openapi.util.IconLoader.getIcon
|
||||
import javax.swing.Icon
|
||||
|
||||
val PorkIcon: Icon = getIcon("/icons/pork.png", PorkLanguage::class.java)
|
@ -0,0 +1,5 @@
|
||||
package gay.pizza.pork.intellij
|
||||
|
||||
import com.intellij.lang.Language
|
||||
|
||||
object PorkLanguage : Language("Pork")
|
@ -0,0 +1,96 @@
|
||||
package gay.pizza.pork.intellij
|
||||
|
||||
import com.intellij.lexer.LexerBase
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import gay.pizza.pork.parser.*
|
||||
import com.intellij.psi.TokenType as PsiTokenType
|
||||
|
||||
class PorkLexer : LexerBase() {
|
||||
private val log: Logger = Logger.getInstance(PorkLexer::class.java)
|
||||
|
||||
private lateinit var source: StringCharSource
|
||||
private lateinit var tokenizer: Tokenizer
|
||||
private var internalTokenStart: Int = 0
|
||||
private var internalTokenEnd: Int = 0
|
||||
private var internalState: Int = 0
|
||||
private var currentTokenType: IElementType? = null
|
||||
|
||||
override fun start(buffer: CharSequence, startOffset: Int, endOffset: Int, initialState: Int) {
|
||||
source = StringCharSource(
|
||||
input = buffer,
|
||||
startIndex = startOffset,
|
||||
endIndex = endOffset
|
||||
)
|
||||
tokenizer = Tokenizer(source)
|
||||
internalState = initialState
|
||||
internalTokenStart = startOffset
|
||||
internalTokenEnd = startOffset
|
||||
currentTokenType = null
|
||||
advance()
|
||||
}
|
||||
|
||||
override fun getState(): Int {
|
||||
return internalState
|
||||
}
|
||||
|
||||
override fun getTokenType(): IElementType? {
|
||||
return currentTokenType
|
||||
}
|
||||
|
||||
override fun getTokenStart(): Int {
|
||||
return internalTokenStart
|
||||
}
|
||||
|
||||
override fun getTokenEnd(): Int {
|
||||
return internalTokenEnd
|
||||
}
|
||||
|
||||
override fun advance() {
|
||||
internalTokenStart = internalTokenEnd
|
||||
if (internalTokenStart == bufferEnd) {
|
||||
currentTokenType = null
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val currentToken = tokenizer.next()
|
||||
currentTokenType = tokenAsElement(currentToken)
|
||||
internalTokenStart = currentToken.start
|
||||
internalTokenEnd = currentToken.start + currentToken.text.length
|
||||
} catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
} catch (e: Throwable) {
|
||||
currentTokenType = PsiTokenType.BAD_CHARACTER
|
||||
internalTokenEnd = bufferEnd
|
||||
log.warn(Tokenizer::class.java.name, e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBufferSequence(): CharSequence {
|
||||
return source.input
|
||||
}
|
||||
|
||||
override fun getBufferEnd(): Int {
|
||||
return source.endIndex
|
||||
}
|
||||
|
||||
private fun tokenAsElement(token: Token): IElementType = when {
|
||||
token.type.family == TokenFamily.KeywordFamily ->
|
||||
PorkTokenTypes.Keyword
|
||||
token.type.family == TokenFamily.SymbolFamily ->
|
||||
PorkTokenTypes.Symbol
|
||||
token.type.family == TokenFamily.OperatorFamily ->
|
||||
PorkTokenTypes.Operator
|
||||
token.type.family == TokenFamily.StringLiteralFamily ->
|
||||
PorkTokenTypes.String
|
||||
token.type.family == TokenFamily.NumericLiteralFamily ->
|
||||
PorkTokenTypes.Number
|
||||
token.type == TokenType.Whitespace ->
|
||||
PorkTokenTypes.Whitespace
|
||||
else -> PsiTokenType.CODE_FRAGMENT
|
||||
}
|
||||
|
||||
override fun toString(): String = "Lexer(start=$internalTokenStart, end=$internalTokenEnd)"
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package gay.pizza.pork.intellij
|
||||
|
||||
import com.intellij.lexer.Lexer
|
||||
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase
|
||||
import com.intellij.psi.tree.IElementType
|
||||
|
||||
object PorkSyntaxHighlighter : SyntaxHighlighter {
|
||||
override fun getHighlightingLexer(): Lexer {
|
||||
return PorkLexer()
|
||||
}
|
||||
|
||||
override fun getTokenHighlights(tokenType: IElementType?): Array<TextAttributesKey> {
|
||||
if (tokenType == null) return emptyArray()
|
||||
val attributes = when (tokenType) {
|
||||
PorkTokenTypes.Keyword ->
|
||||
TextAttributesKey.createTextAttributesKey(
|
||||
"PORK.KEYWORD",
|
||||
DefaultLanguageHighlighterColors.KEYWORD
|
||||
)
|
||||
PorkTokenTypes.Symbol ->
|
||||
TextAttributesKey.createTextAttributesKey(
|
||||
"PORK.SYMBOL",
|
||||
DefaultLanguageHighlighterColors.LOCAL_VARIABLE
|
||||
)
|
||||
PorkTokenTypes.Operator ->
|
||||
TextAttributesKey.createTextAttributesKey(
|
||||
"PORK.OPERATOR",
|
||||
DefaultLanguageHighlighterColors.OPERATION_SIGN
|
||||
)
|
||||
PorkTokenTypes.String ->
|
||||
TextAttributesKey.createTextAttributesKey(
|
||||
"PORK.STRING",
|
||||
DefaultLanguageHighlighterColors.STRING
|
||||
)
|
||||
PorkTokenTypes.Number ->
|
||||
TextAttributesKey.createTextAttributesKey(
|
||||
"PORK.NUMBER",
|
||||
DefaultLanguageHighlighterColors.NUMBER
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
return if (attributes == null)
|
||||
emptyArray()
|
||||
else SyntaxHighlighterBase.pack(attributes)
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package gay.pizza.pork.intellij
|
||||
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
class PorkSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
|
||||
override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?): SyntaxHighlighter {
|
||||
return PorkSyntaxHighlighter
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package gay.pizza.pork.intellij
|
||||
|
||||
import com.intellij.psi.TokenType
|
||||
import com.intellij.psi.tree.IElementType
|
||||
|
||||
object PorkTokenTypes {
|
||||
val Whitespace = TokenType.WHITE_SPACE
|
||||
val Keyword = IElementType("keyword", PorkLanguage)
|
||||
val Symbol = IElementType("symbol", PorkLanguage)
|
||||
val Operator = IElementType("operator", PorkLanguage)
|
||||
val String = IElementType("string", PorkLanguage)
|
||||
val Number = IElementType("number", PorkLanguage)
|
||||
}
|
Reference in New Issue
Block a user