524 lines
16 KiB
C#
524 lines
16 KiB
C#
using System;
|
|
using AppKit;
|
|
using Foundation;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Cauldron.Macos.SourceWriter;
|
|
|
|
[Register("LanguageDescriptor")]
|
|
public class LanguageDescriptor : NSObject
|
|
{
|
|
#region Computed Properties
|
|
|
|
/// <summary>Gets the language identifier.</summary>
|
|
/// <value>The language identifier.</value>
|
|
public virtual string LanguageIdentifier { get => "Default"; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the language separators that can be used to define a "word" in the given
|
|
/// language.
|
|
/// </summary>
|
|
/// <value>The language separators.</value>
|
|
public virtual char[] LanguageSeparators { get; set; } = new char[] { '.' };
|
|
|
|
/// <summary>
|
|
/// Gets the escape character for the given language.
|
|
/// </summary>
|
|
/// <value>The escape character.</value>
|
|
public virtual char EscapeCharacter { get => '\\'; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the collection of <see cref="KeywordDescriptor"/> used to define
|
|
/// the keywords for this language.
|
|
/// </summary>
|
|
/// <value>The keywords.</value>
|
|
public Dictionary<string, KeywordDescriptor> Keywords { get; set; }
|
|
= new Dictionary<string, KeywordDescriptor>();
|
|
|
|
/// <summary>
|
|
/// Gets or sets the collection of <see cref="FormatDescriptor"/> formats used to syntax
|
|
/// highlight this language.
|
|
/// </summary>
|
|
/// <value>The formats.</value>
|
|
public List<FormatDescriptor> Formats { get; set; } = new List<FormatDescriptor>();
|
|
|
|
/// <summary>
|
|
/// Gets or sets the collection of <see cref="LanguageClosure"/> used to auto complete to
|
|
/// closure of text such as (), [], "" or ''.
|
|
/// </summary>
|
|
/// <value>The closures.</value>
|
|
public List<LanguageClosure> Closures { get; set; } = new List<LanguageClosure>();
|
|
|
|
/// <summary>
|
|
/// Gets or sets the formatting commands that can be added to the user interface for the user to
|
|
/// select and apply to a selection of text in the editor.
|
|
/// </summary>
|
|
/// <value>The <see cref="LanguageFormatCommand"/> items.</value>
|
|
public List<LanguageFormatCommand> FormattingCommands { get; set; }
|
|
= new List<LanguageFormatCommand>();
|
|
|
|
/// <summary>Gets or sets the color of generic keywords.</summary>
|
|
/// <value>The <c>NSColor</c> of the keyword.</value>
|
|
[Export("KeywordColor")]
|
|
public NSColor KeywordColor
|
|
{
|
|
get => LoadColor("KeywordColor", NSColor.SystemTeal);
|
|
set
|
|
{
|
|
WillChangeValue("KeywordColor");
|
|
SaveColor("KeywordColor", value, true);
|
|
DidChangeValue("KeywordColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of generic keyword type.</summary>
|
|
/// <value>The <c>NSColor</c> of the type.</value>
|
|
[Export("TypeColor")]
|
|
public NSColor TypeColor
|
|
{
|
|
get => LoadColor("TypeColor", NSColor.SystemTeal);
|
|
set
|
|
{
|
|
WillChangeValue("TypeColor");
|
|
SaveColor("TypeColor", value, true);
|
|
DidChangeValue("TypeColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a value type keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the value type.</value>
|
|
[Export("ValueTypeColor")]
|
|
public NSColor ValueTypeColor
|
|
{
|
|
get => LoadColor("ValueTypeColor", NSColor.SystemBlue);
|
|
set
|
|
{
|
|
WillChangeValue("ValueTypeColor");
|
|
SaveColor("ValueTypeColor", value, true);
|
|
DidChangeValue("ValueTypeColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a reference type keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the reference type.</value>
|
|
[Export("ReferenceTypeColor")]
|
|
public NSColor ReferenceTypeColor
|
|
{
|
|
get => LoadColor("ReferenceTypeColor", NSColor.SystemCyan);
|
|
set
|
|
{
|
|
WillChangeValue("ReferenceTypeColor");
|
|
SaveColor("ReferenceTypeColor", value, true);
|
|
DidChangeValue("ReferenceTypeColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a access modifier keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the access modifier.</value>
|
|
[Export("AccessModifierColor")]
|
|
public NSColor AccessModifierColor
|
|
{
|
|
get => LoadColor("AccessModifierColor", NSColor.SystemTeal);
|
|
set
|
|
{
|
|
WillChangeValue("AccessModifierColor");
|
|
SaveColor("AccessModifierColor", value, true);
|
|
DidChangeValue("AccessModifierColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a generic modifier keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the modifier.</value>
|
|
[Export("ModifierColor")]
|
|
public NSColor ModifierColor
|
|
{
|
|
get => LoadColor("ModifierColor", NSColor.SystemTeal);
|
|
set
|
|
{
|
|
WillChangeValue("ModifierColor");
|
|
SaveColor("ModifierColor", value, true);
|
|
DidChangeValue("ModifierColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a selection statement keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the selection statement.</value>
|
|
[Export("SelectionStatementColor")]
|
|
public NSColor SelectionStatementColor
|
|
{
|
|
get => LoadColor("SelectionStatementColor", NSColor.SystemBrown);
|
|
set
|
|
{
|
|
WillChangeValue("SelectionStatementColor");
|
|
SaveColor("SelectionStatementColor", value, true);
|
|
DidChangeValue("SelectionStatementColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a iteration statement keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the iteration statement.</value>
|
|
[Export("IterationStatementColor")]
|
|
public NSColor IterationStatementColor
|
|
{
|
|
get => LoadColor("IterationStatementColor", NSColor.SystemRed);
|
|
set
|
|
{
|
|
WillChangeValue("IterationStatementColor");
|
|
SaveColor("IterationStatementColor", value, true);
|
|
DidChangeValue("IterationStatementColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a jump statement keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the jump statement.</value>
|
|
[Export("JumpStatementColor")]
|
|
public NSColor JumpStatementColor
|
|
{
|
|
get => LoadColor("JumpStatementColor", NSColor.SystemYellow);
|
|
set
|
|
{
|
|
WillChangeValue("JumpStatementColor");
|
|
SaveColor("JumpStatementColor", value, true);
|
|
DidChangeValue("JumpStatementColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a exception handling keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the exception handling.</value>
|
|
[Export("ExceptionHandlingColor")]
|
|
public NSColor ExceptionHandlingColor
|
|
{
|
|
get => LoadColor("ExceptionHandlingColor", NSColor.SystemRed);
|
|
set
|
|
{
|
|
WillChangeValue("ExceptionHandlingColor");
|
|
SaveColor("ExceptionHandlingColor", value, true);
|
|
DidChangeValue("ExceptionHandlingColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a generic statement keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the statement.</value>
|
|
[Export("StatementColor")]
|
|
public NSColor StatementColor
|
|
{
|
|
get => LoadColor("StatementColor", NSColor.SystemPink);
|
|
set
|
|
{
|
|
WillChangeValue("StatementColor");
|
|
SaveColor("StatementColor", value, true);
|
|
DidChangeValue("StatementColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a method parameter keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the method parameter.</value>
|
|
[Export("MethodParameterColor")]
|
|
public NSColor MethodParameterColor
|
|
{
|
|
get => LoadColor("MethodParameterColor", NSColor.SystemTeal);
|
|
set
|
|
{
|
|
WillChangeValue("MethodParameterColor");
|
|
SaveColor("MethodParameterColor", value, true);
|
|
DidChangeValue("MethodParameterColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a namespace keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the namespace.</value>
|
|
[Export("NamespaceColor")]
|
|
public NSColor NamespaceColor
|
|
{
|
|
get => LoadColor("NamespaceColor", NSColor.SystemTeal);
|
|
set
|
|
{
|
|
WillChangeValue("NamespaceColor");
|
|
SaveColor("NamespaceColor", value, true);
|
|
DidChangeValue("NamespaceColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a operator keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the operator keyword.</value>
|
|
[Export("OperatorKeywordColor")]
|
|
public NSColor OperatorKeywordColor
|
|
{
|
|
get => LoadColor("OperatorKeywordColor", NSColor.SystemPurple);
|
|
set
|
|
{
|
|
WillChangeValue("OperatorKeywordColor");
|
|
SaveColor("OperatorKeywordColor", value, true);
|
|
DidChangeValue("OperatorKeywordColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a conversion keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the conversion keyword.</value>
|
|
[Export("ConversionKeywordColor")]
|
|
public NSColor ConversionKeywordColor
|
|
{
|
|
get => LoadColor("ConversionKeywordColor", NSColor.SystemPurple);
|
|
set
|
|
{
|
|
WillChangeValue("ConversionKeywordColor");
|
|
SaveColor("ConversionKeywordColor", value, true);
|
|
DidChangeValue("ConversionKeywordColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a access keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the access keyword.</value>
|
|
[Export("AccessKeywordColor")]
|
|
public NSColor AccessKeywordColor
|
|
{
|
|
get => LoadColor("AccessKeywordColor", NSColor.SystemPurple);
|
|
set
|
|
{
|
|
WillChangeValue("AccessKeywordColor");
|
|
SaveColor("AccessKeywordColor", value, true);
|
|
DidChangeValue("AccessKeywordColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a literal keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the literal keyword.</value>
|
|
[Export("LiteralKeywordColor")]
|
|
public NSColor LiteralKeywordColor
|
|
{
|
|
get => LoadColor("LiteralKeywordColor", NSColor.SystemPurple);
|
|
set
|
|
{
|
|
WillChangeValue("LiteralKeywordColor");
|
|
SaveColor("LiteralKeywordColor", value, true);
|
|
DidChangeValue("LiteralKeywordColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a contextual keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the contextual keyword.</value>
|
|
[Export("ContextualKeywordColor")]
|
|
public NSColor ContextualKeywordColor
|
|
{
|
|
get => LoadColor("ContextualKeywordColor", NSColor.SystemGreen);
|
|
set
|
|
{
|
|
WillChangeValue("ContextualKeywordColor");
|
|
SaveColor("ContextualKeywordColor", value, true);
|
|
DidChangeValue("ContextualKeywordColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a query keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the query keyword.</value>
|
|
[Export("QueryKeywordColor")]
|
|
public NSColor QueryKeywordColor
|
|
{
|
|
get => LoadColor("QueryKeywordColor", NSColor.SystemOrange);
|
|
set
|
|
{
|
|
WillChangeValue("QueryKeywordColor");
|
|
SaveColor("QueryKeywordColor", value, true);
|
|
DidChangeValue("QueryKeywordColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a preprocessor directive keyword.</summary>
|
|
/// <value>The <c>NSColor</c> of the preprocessor directive.</value>
|
|
[Export("PreprocessorDirectiveColor")]
|
|
public NSColor PreprocessorDirectiveColor
|
|
{
|
|
get => LoadColor("PreprocessorDirectiveColor", NSColor.SystemPurple);
|
|
set
|
|
{
|
|
WillChangeValue("PreprocessorDirectiveColor");
|
|
SaveColor("PreprocessorDirectiveColor", value, true);
|
|
DidChangeValue("PreprocessorDirectiveColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a comment.</summary>
|
|
/// <value>The <c>NSColor</c> of the comment.</value>
|
|
[Export("CommentColor")]
|
|
public NSColor CommentColor
|
|
{
|
|
get => LoadColor("CommentColor", NSColor.SystemGray);
|
|
set
|
|
{
|
|
WillChangeValue("CommentColor");
|
|
SaveColor("CommentColor", value, true);
|
|
DidChangeValue("CommentColor");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the color of a string literal.</summary>
|
|
/// <value>The <c>NSColor</c> of the string literal.</value>
|
|
[Export("StringLiteralColor")]
|
|
public NSColor StringLiteralColor
|
|
{
|
|
get => LoadColor("StringLiteralColor", NSColor.SystemOrange);
|
|
set
|
|
{
|
|
WillChangeValue("StringLiteralColor");
|
|
SaveColor("StringLiteralColor", value, true);
|
|
DidChangeValue("StringLiteralColor");
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="AppKit.TextKit.Formatter.LanguageDescriptor"/> class.
|
|
/// </summary>
|
|
public LanguageDescriptor()
|
|
{
|
|
}
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>Define this instance.</summary>
|
|
public virtual void Define()
|
|
{
|
|
// Initialize
|
|
this.Keywords.Clear();
|
|
this.Formats.Clear();
|
|
this.Closures.Clear();
|
|
this.FormattingCommands.Clear();
|
|
|
|
// Define the default set of closures
|
|
this.Closures.Add(new LanguageClosure('(', ')'));
|
|
this.Closures.Add(new LanguageClosure('[', ']'));
|
|
this.Closures.Add(new LanguageClosure('<', '>'));
|
|
this.Closures.Add(new LanguageClosure('{', '}'));
|
|
this.Closures.Add(new LanguageClosure('"'));
|
|
}
|
|
|
|
/// <summary>Formats the passed in string of text for previewing.</summary>
|
|
/// <returns>The string formatted for preview.</returns>
|
|
/// <param name="text">Text.</param>
|
|
public virtual string FormatForPreview(string text)
|
|
{
|
|
return text;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets all of the <see cref="FormatDescriptor"/> for this language to their default states
|
|
/// of unmatched and inactive.
|
|
/// </summary>
|
|
/// <remarks>This should only be called ba a <see cref="LanguageFormatter"/>.</remarks>
|
|
public virtual void ClearFormats()
|
|
{
|
|
// Clear the process state of all formats
|
|
foreach (FormatDescriptor format in Formats)
|
|
{
|
|
format.CharIndex = 0;
|
|
format.Active = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts the given color into a web style hex string in the form #RRBBGG or optionally
|
|
/// #RRBBGGAA.
|
|
/// </summary>
|
|
/// <returns>The web hex string representing the given color.</returns>
|
|
/// <param name="color">The <c>NSColor</c> to convert.</param>
|
|
/// <param name="withAlpha">
|
|
/// If set to <c>true</c> with the alpha (transparency) of the color will be included.
|
|
/// </param>
|
|
public static string NSColorToHexString(NSColor color, bool withAlpha)
|
|
{
|
|
// Break color into pieces
|
|
color.GetRgba(out nfloat red, out nfloat green, out nfloat blue, out nfloat alpha);
|
|
|
|
// Adjust to byte
|
|
alpha *= 255;
|
|
red *= 255;
|
|
green *= 255;
|
|
blue *= 255;
|
|
|
|
//With the alpha value?
|
|
if (withAlpha)
|
|
{
|
|
return string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}",
|
|
(int)alpha, (int)red, (int)green, (int)blue);
|
|
}
|
|
else
|
|
{
|
|
return string.Format("#{0:X2}{1:X2}{2:X2}", (int)red, (int)green, (int)blue);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a web formatted hex string in the form #RRGGBB or #RRGGBBAA into a color.
|
|
/// </summary>
|
|
/// <returns>The <c>NSColor</c> represented by the hex string.</returns>
|
|
/// <param name="hexValue">The web formatted hex string in the form #RRGGBB or #RRGGBBAA.</param>
|
|
public static NSColor NSColorFromHexString(string hexValue)
|
|
{
|
|
string colorString = hexValue.Replace("#", "");
|
|
float red, green, blue, alpha;
|
|
|
|
// Convert color based on length
|
|
switch (colorString.Length)
|
|
{
|
|
case 3: // #RGB
|
|
red = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(0, 1)), 16) / 255f;
|
|
green = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(1, 1)), 16) / 255f;
|
|
blue = Convert.ToInt32(string.Format("{0}{0}", colorString.Substring(2, 1)), 16) / 255f;
|
|
return NSColor.FromRgba(red, green, blue, 1.0f);
|
|
case 6: // #RRGGBB
|
|
red = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f;
|
|
green = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f;
|
|
blue = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f;
|
|
return NSColor.FromRgba(red, green, blue, 1.0f);
|
|
case 8: // #AARRGGBB
|
|
alpha = Convert.ToInt32(colorString.Substring(0, 2), 16) / 255f;
|
|
red = Convert.ToInt32(colorString.Substring(2, 2), 16) / 255f;
|
|
green = Convert.ToInt32(colorString.Substring(4, 2), 16) / 255f;
|
|
blue = Convert.ToInt32(colorString.Substring(6, 2), 16) / 255f;
|
|
return NSColor.FromRgba(red, green, blue, alpha);
|
|
default:
|
|
throw new ArgumentOutOfRangeException(string.Format("Invalid color value '{0}'. "
|
|
+ "It should be a hex value of the form #RBG, #RRGGBB or #AARRGGBB", hexValue));
|
|
}
|
|
}
|
|
|
|
/// <summary>Loads the requested color from system-wide user defaults.</summary>
|
|
/// <returns>The <c>NSColor</c> for the given key or the default value if the key
|
|
/// cannot be found in the user defaults.</returns>
|
|
/// <param name="key">The user default key for the color.</param>
|
|
/// <param name="defaultValue">The default <c>NSColor</c> value.</param>
|
|
public NSColor LoadColor(string key, NSColor defaultValue)
|
|
{
|
|
// Attempt to read color, add the language ID to make unique
|
|
string hex = NSUserDefaults.StandardUserDefaults.StringForKey(LanguageIdentifier + key);
|
|
|
|
// Take action based on value
|
|
if (hex == null)
|
|
{
|
|
return defaultValue;
|
|
}
|
|
else
|
|
{
|
|
return NSColorFromHexString(hex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves the given color to the systwm-wide user defaults with the give keyword.
|
|
/// </summary>
|
|
/// <param name="color">The <c>NSColor</c> to save to the user defaults.</param>
|
|
/// <param name="key">The user default key to assign the color to.</param>
|
|
/// <param name="sync">If set to <c>true</c> sync changes to preferences.</param>
|
|
public void SaveColor(string key, NSColor color, bool sync)
|
|
{
|
|
// Save to default, add the language ID to make unique
|
|
NSUserDefaults.StandardUserDefaults.SetString(NSColorToHexString(color, true), LanguageIdentifier + key);
|
|
if (sync) NSUserDefaults.StandardUserDefaults.Synchronize();
|
|
}
|
|
|
|
#endregion
|
|
}
|