Last active
October 18, 2024 13:12
-
-
Save keplersj/8464003 to your computer and use it in GitHub Desktop.
Groovy syntax handling for Xcode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// groovy lang specs | |
( | |
/****************************************************************************/ | |
// MARK: Groovydoc | |
/****************************************************************************/ | |
{ | |
Identifier = "xcode.lang.groovy.comment.groovydoc.keyword"; | |
Syntax = { | |
StartChars = "@"; | |
Chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
Words = ( | |
"@author", | |
"@beaninfo", | |
"@deprecated", | |
"@docRoot", | |
"@exception", | |
"@inheritDoc", | |
"@link", | |
"@linkplain", | |
"@param", | |
"@return", | |
"@see", | |
"@serial", | |
"@serialData", | |
"@serialField", | |
"@since", | |
"@throws", | |
"@value", | |
"@version" | |
); | |
Type = "xcode.syntax.comment.doc.keyword"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.comment.groovydoc"; | |
Syntax = { | |
Start = "/**"; | |
End = "*/"; | |
Foldable = YES; | |
IncludeRules = ( "xcode.lang.groovy.comment.groovydoc.keyword", "xcode.lang.url", "xcode.lang.url.mail", "xcode.lang.comment.mark" ); | |
Type = "xcode.syntax.comment.doc"; | |
}; | |
}, | |
{ | |
// Handle the degenerate case of '/**/' comments. They look like the start of a groovyDoc comment, but they aren't. | |
Identifier = "xcode.lang.groovy.comment.degenerate"; | |
Syntax = { | |
StartChars = "/"; | |
Chars = "/*"; | |
Words = ( "/**/" ); | |
Type = "xcode.syntax.comment"; | |
}; | |
}, | |
/****************************************************************************/ | |
// MARK: Groovy Keywords | |
/****************************************************************************/ | |
{ | |
Identifier = "xcode.lang.groovy.identifier"; | |
Syntax = { | |
StartChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; | |
Chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; | |
Words = ( | |
"abstract", | |
"as", | |
"assert", | |
"break", | |
"case", | |
"catch", | |
"class", | |
"const", | |
"continue", | |
"def", | |
"default", | |
"do", | |
"else", | |
"extends", | |
"false", | |
"final", | |
"finally", | |
"for", | |
"goto", | |
"if", | |
"implements", | |
"import", | |
"instanceof", | |
"interface", | |
"native", | |
"new", | |
"null", | |
"package", | |
"println", | |
"private", | |
"property", | |
"protected", | |
"public", | |
"return", | |
"static", | |
"super", | |
"switch", | |
"synchronized", | |
"this", | |
"throw", | |
"throws", | |
"true", | |
"try", | |
"while" | |
); | |
AltKeywords = ( | |
"any", | |
"boolean", | |
"byte", | |
"char", | |
"double", | |
"float", | |
"int", | |
"long", | |
"short", | |
"void" | |
); | |
Type = "xcode.syntax.keyword"; | |
AltType = "xcode.syntax.identifier"; // non-keywords are identifiers | |
}; | |
}, | |
/****************************************************************************/ | |
// MARK: Groovy Top Level | |
/****************************************************************************/ | |
{ | |
Identifier = "xcode.lang.groovy"; | |
Description = "groovy Coloring"; | |
BasedOn = "xcode.lang.simpleColoring"; | |
IncludeInMenu = YES; | |
UsesCLikeIndentation = YES; | |
Name = "groovy"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
IncludeRules = ( // processed in order | |
"xcode.lang.groovy.package", | |
"xcode.lang.groovy.import", | |
"xcode.lang.groovy.class", | |
"xcode.lang.groovy.interface", | |
); | |
Type = "xcode.syntax.plain"; | |
}; | |
}, | |
/****************************************************************************/ | |
// MARK: Lexers | |
/****************************************************************************/ | |
// The following rule returns tokens to the other rules | |
{ | |
Identifier = "xcode.lang.groovy.lexer"; | |
Syntax = { | |
IncludeRules = ( | |
"xcode.lang.groovy.comment.degenerate", | |
"xcode.lang.groovy.comment.groovydoc", | |
"xcode.lang.comment", | |
"xcode.lang.comment.singleline", | |
"xcode.lang.string", | |
"xcode.lang.character", | |
"xcode.lang.completionplaceholder", | |
"xcode.lang.groovy.identifier", | |
"xcode.lang.number", | |
); | |
}; | |
}, | |
/****************************************************************************/ | |
// MARK: Classes/Interfaces | |
/****************************************************************************/ | |
{ | |
Identifier = "xcode.lang.groovy.class"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.class.declarator", | |
"xcode.lang.groovy.class.block", | |
); | |
Type = "xcode.syntax.definition.groovy.class"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.innerclass"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.method.declarator", | |
"xcode.lang.groovy.class.block", | |
); | |
Type = "xcode.syntax.definition.groovy.class"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.class.declarator"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"class", | |
"xcode.lang.groovy.class.name", | |
"xcode.lang.groovy.class.declarator.extends?", | |
"xcode.lang.groovy.class.declarator.implements?", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.class.name"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.identifier", | |
"xcode.lang.groovy.templateclause?", | |
); | |
Type = "xcode.syntax.name.partial"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.class.declarator.extends"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"extends", | |
"xcode.lang.groovy.qualifiedname", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.class.declarator.implements"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"implements", | |
"xcode.lang.groovy.qualifiedname", | |
"xcode.lang.groovy.classnames.list*", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.interface"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Foldable = YES; | |
Recursive = YES; | |
Rules = ( | |
"xcode.lang.groovy.interface.declarator", | |
"xcode.lang.groovy.interface.block", | |
); | |
Type = "xcode.syntax.declaration.groovy.interface"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.interface.declarator"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"interface", | |
"xcode.lang.groovy.class.name", | |
"xcode.lang.groovy.interface.declarator.extends?", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.interface.declarator.extends"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"extends", | |
"xcode.lang.groovy.qualifiedname", | |
"xcode.lang.groovy.classnames.list*", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.classnames.list"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
",", | |
"xcode.lang.groovy.qualifiedname", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.qualifiedname"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.identifier", | |
"xcode.lang.groovy.qualifiedname.more*", | |
"xcode.lang.groovy.templateclause?", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.templateclause"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Start = "<"; | |
End = ">"; | |
Recursive = YES; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.package.qualifiedname"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.identifier", | |
"xcode.lang.groovy.import.qualifiedname.more*", | |
); | |
Type = "xcode.syntax.groovy.package"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.import.qualifiedname"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.identifier", | |
"xcode.lang.groovy.import.qualifiedname.more*", | |
"*?", | |
); | |
Type = "xcode.syntax.groovy.import"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.import.qualifiedname.more"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
".", | |
"xcode.lang.groovy.identifier?", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.qualifiedname.more"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
".", | |
"xcode.lang.groovy.identifier", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.package"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"package", | |
"xcode.lang.groovy.package.qualifiedname", | |
";", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.import"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"import", | |
"xcode.lang.groovy.import.qualifiedname", | |
";", | |
); | |
}; | |
}, | |
/****************************************************************************/ | |
// MARK: Methods | |
/****************************************************************************/ | |
{ | |
Identifier = "xcode.lang.groovy.method.declaration"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.method.declarator", | |
"xcode.lang.groovy.method.declarator.throws?", | |
";", | |
); | |
Type = "xcode.syntax.declaration.method"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.method.definition"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.method.declarator", | |
"xcode.lang.groovy.method.declarator.throws?", | |
"xcode.lang.groovy.block", | |
); | |
Type = "xcode.syntax.definition.method"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.method.declarator"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"xcode.lang.groovy.identifier", | |
"xcode.lang.groovy.parenexpr", | |
); | |
Type = "xcode.syntax.name.partial"; | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.method.declarator.throws"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Rules = ( | |
"throws", | |
"xcode.lang.groovy.qualifiedname", | |
"xcode.lang.groovy.classnames.list*", | |
); | |
}; | |
}, | |
/****************************************************************************/ | |
// MARK: Blocks | |
/****************************************************************************/ | |
{ | |
Identifier = "xcode.lang.groovy.class.block"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Start = "{"; | |
End = "}"; | |
Foldable = YES; | |
Recursive = YES; | |
IncludeRules = ( | |
"xcode.lang.groovy.class", | |
"xcode.lang.groovy.interface", | |
"xcode.lang.groovy.method.definition", | |
"xcode.lang.groovy.method.declaration", | |
"xcode.lang.groovy.bracketexpr", | |
"xcode.lang.groovy.parenexpr", | |
"xcode.lang.groovy.initializer", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.interface.block"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Start = "{"; | |
End = "}"; | |
Foldable = YES; | |
Recursive = YES; | |
IncludeRules = ( | |
"xcode.lang.groovy.interface", | |
"xcode.lang.groovy.method.definition", | |
"xcode.lang.groovy.method.declaration", | |
"xcode.lang.groovy.bracketexpr", | |
"xcode.lang.groovy.parenexpr", | |
"xcode.lang.groovy.initializer", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.block"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Start = "{"; | |
End = "}"; | |
Foldable = YES; | |
Recursive = YES; | |
IncludeRules = ( | |
"xcode.lang.groovy.class", | |
"xcode.lang.groovy.interface", | |
"xcode.lang.groovy.bracketexpr", | |
"xcode.lang.groovy.parenexpr", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.parenexpr"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Start = "("; | |
End = ")"; | |
Recursive = YES; | |
IncludeRules = ( | |
"xcode.lang.groovy.bracketexpr", | |
"xcode.lang.groovy.block", | |
"xcode.lang.groovy.innerclass", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.bracketexpr"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Start = "["; | |
End = "]"; | |
Recursive = YES; | |
IncludeRules = ( | |
"xcode.lang.groovy.parenexpr", | |
); | |
}; | |
}, | |
{ | |
Identifier = "xcode.lang.groovy.initializer"; | |
Syntax = { | |
Tokenizer = "xcode.lang.groovy.lexer"; | |
Start = "="; | |
End = ";"; | |
Recursive = NO; | |
IncludeRules = ( | |
"xcode.lang.groovy.parenexpr", | |
"xcode.lang.groovy.bracketexpr", | |
); | |
}; | |
}, | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -e | |
# Assumes Xcode 4+. | |
XCODE_MAJOR_VERSION=`xcodebuild -version | awk 'NR == 1 {print substr($2,1,1)}'` | |
if [ "$XCODE_MAJOR_VERSION" -lt "4" ]; then | |
echo "Xcode 4+ not found." | |
exit 1 | |
fi | |
# DVTFOUNDATION_DIR may vary depending on Xcode setup. If Xcode has installed | |
# the `xcode-select` command, it will be determined automatically. Otherwise, | |
# change it to reflect your current Xcode setup. Find suitable path with e.g.: | |
# | |
# find / -type f -name 'DVTFoundation.xcplugindata' 2> /dev/null | |
# | |
# Example of DVTFOUNDATION_DIR's from "default" Xcode 4+ setups; | |
# | |
# Xcode 4.1: /Developer/Library/PrivateFrameworks/DVTFoundation.framework/Versions/A/Resources/ | |
# Xcode 4.3: /Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/ | |
# Defaults to Xcode 4.3's DVTFOUNDATION_DIR. Path is modified automatically if | |
# `xcode-select` command is available, as mentioned above. | |
DVTFOUNDATION_DIR="/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/" | |
if type "xcode-select" > /dev/null; then | |
DVTFOUNDATION_DIR=`xcode-select --print-path` | |
DVTFOUNDATION_DIR+="/.." | |
FRAMEWORK_NAME="DVTFoundation.framework" | |
DVTFOUNDATION_DIR=`find $DVTFOUNDATION_DIR -name $FRAMEWORK_NAME -print` | |
DVTFOUNDATION_DIR+="/Versions/A/Resources" | |
fi | |
PLUGINDATA_FILE="DVTFoundation.xcplugindata" | |
PLISTBUDDY=/usr/libexec/PlistBuddy | |
PLIST_FILE=tmp.plist | |
# Provide means of deleting the Go entry from the plugindata file. | |
if [ "$1" = "--delete-entry" ]; then | |
echo "Removing Go language specification entry." | |
$PLISTBUDDY -c "Delete :plug-in:extensions:Xcode.SourceCodeLanguage.Groovy" $DVTFOUNDATION_DIR/$PLUGINDATA_FILE | |
echo "Run 'sudo rm -rf /var/folders/*' and restart Xcode to update change immediately." | |
exit 0 | |
fi | |
GROOVY_LANG_ENTRY=" | |
<?xml version=\"1.0\" encoding=\"UTF-8\"?> | |
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> | |
<plist version=\"1.0\"> | |
<dict> | |
<key>Xcode.SourceCodeLanguage.Groovy</key> | |
<dict> | |
<key>conformsTo</key> | |
<array> | |
<dict> | |
<key>identifier</key> | |
<string>Xcode.SourceCodeLanguage.Generic</string> | |
</dict> | |
</array> | |
<key>documentationAbbreviation</key> | |
<string>groovy</string> | |
<key>fileDataType</key> | |
<array> | |
<dict> | |
<key>identifier</key> | |
<string>com.apple.xcode.groovy-source</string> | |
</dict> | |
</array> | |
<key>id</key> | |
<string>Xcode.SourceCodeLanguage.Groovy</string> | |
<key>languageName</key> | |
<string>Groovy</string> | |
<key>languageSpecification</key> | |
<string>xcode.lang.groovy</string> | |
<key>name</key> | |
<string>Groovy</string> | |
<key>point</key> | |
<string>Xcode.SourceCodeLanguage</string> | |
<key>version</key> | |
<string>0</string> | |
</dict> | |
</dict> | |
</plist> | |
" | |
echo "Backing up plugindata file (copied to $PLUGINDATA_FILE.bak)." | |
cp $DVTFOUNDATION_DIR/$PLUGINDATA_FILE $DVTFOUNDATION_DIR/$PLUGINDATA_FILE.bak | |
echo "Adding Go language specification entry." | |
echo $GROOVY_LANG_ENTRY > $PLIST_FILE | |
$PLISTBUDDY -c "Merge $PLIST_FILE plug-in:extensions" $DVTFOUNDATION_DIR/$PLUGINDATA_FILE | |
rm -f $PLIST_FILE | |
echo "Installing Groovy language specification file for Xcode." | |
cp Groovy.xclangspec $DVTFOUNDATION_DIR | |
echo "Run 'sudo rm -rf /var/folders/*' and restart Xcode to update change immediately." | |
echo "Syntax coloring must be manually selected from the Editor - Syntax Coloring menu in Xcode." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment