/// <summary> /// Gets a list of styles for a specific pattern context member. /// </summary> private List <IroStyle> GetPatternStyles(List <string> styleNames, IroPrecompileData data) { //Check that styles exist, and try to get the first one out. if (styleNames.Count == 0) { Error.Compile("No style was defined for a pattern. All styles must have patterns."); return(null); } //Get all the patterns out. var styles = new List <IroStyle>(); foreach (var style in styleNames) { //Get the styles form the style list. int index = data.Styles.FindIndex(x => x.Name == style); if (index == -1) { Error.Compile("A style '" + style + "' is referenced in a pattern, but it is not defined in the style map."); return(null); } styles.Add(data.Styles[index]); } //Make sure all the patterns have textmate scopes. if (styles.Where(x => x.PygmentsScope != null).Count() != styles.Count) { Error.Compile("One or more styles for a pattern does not have a Pygments scope defined."); return(null); } return(styles); }
/// <summary> /// Adds a context that has been queued to the builder. /// </summary> private void AddQueuedContext(string ctxName, InlinePushContextMember ilp, IroPrecompileData data, ref StringBuilder text) { //Begin this context. text.AppendLine("\"" + ctxName + "\": ["); //Get styles out for pop rule. var popStyles = GetPatternStyles(ilp.PopStyles, data); //Add the pop rule. text.AppendLine("{"); text.AppendLine("\"token\": \"" + popStyles[0].AceScope + "\","); text.AppendLine("\"regex\": \"" + ilp.PopData.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\","); text.AppendLine("\"next\": \"pop\""); text.AppendLine("},"); //Add all patterns for the ILP. foreach (var pattern in ilp.Patterns) { AddMember(pattern, ctxName, ref text, data); } //Add the default style. text.AppendLine("{"); text.AppendLine("defaultToken: \"text\""); text.AppendLine("}"); //End this context. text.AppendLine("],"); }
/// <summary> /// Turns Iro precompile data into a compiled Rouge target. /// </summary> public CompileResult Compile(IroPrecompileData data) { var text = new RubyStringMaker(); //Add the coding header and modules. text.AppendLine("# -*- coding: utf-8 -*- #"); text.AppendLine(); text.AppendLine("module Rouge"); text.TabIn(); text.AppendLine("module Lexers"); text.TabIn(); text.AppendLine("class " + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + " < RegexLexer"); text.TabIn(); //Add basic metadata. text.AppendLine("title \"" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "\""); text.AppendLine("tag '" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "'"); text.AppendLine("mimetypes 'text/x-" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "'"); string fileTypes = ""; foreach (var ext in data.FileExtensions) { fileTypes += "'*." + ext + "', "; } fileTypes = fileTypes.TrimEnd(',', ' '); text.AppendLine("filenames " + fileTypes); text.AppendLine(); //Check the main context exists. var mainCtx = data.Contexts.FirstOrDefault(x => x.Name == "main"); if (mainCtx == null) { Error.Compile("No context exists named 'main' to use as the root context. Add a 'main' context."); return(null); } AddContext(mainCtx, "root", data, ref text); //Add all the queued helpers. while (queuedContexts.Count != 0) { var item = queuedContexts.ElementAt(0); AddILPContext(item.Key.Item1, item.Key.Item2, item.Value, data, ref text); queuedContexts.Remove(item.Key); } //Close all the modules. text.TabOut(); text.AppendLine("end"); text.TabOut(); text.AppendLine("end"); text.TabOut(); text.AppendLine("end"); return(new CompileResult() { GeneratedFile = text.ToString(), Target = Target.Rouge }); }
/// <summary> /// Processes the currently queued contexts. /// </summary> private void ProcessQueuedContexts(IroPrecompileData data, ref StringBuilder text) { foreach (var context in queuedContexts) { AddContext(new IroContext(context.Key) { Members = context.Value }, data, ref text); } queuedContexts = new Dictionary <string, List <ContextMember> >(); }
/// <summary> /// Adds a single context to the text grammar. /// </summary> private void AddContext(IroContext context, IroPrecompileData data, ref StringBuilder text) { //Name of context, start of patterns. text.AppendLine("'" + context.Name + "': {"); text.AppendLine("'patterns': ["); //Loop over, add members. foreach (var member in context.Members) { AddMember(member, data, ref text); } text.AppendLine("]"); text.AppendLine("}"); }
//Adds a single context to the grammar string. private void AddContext(IroContext ctx, IroPrecompileData data, ref PyStringMaker text) { //Open the context. text.AppendLine("'" + ctx.Name + "' : ["); text.TabIn(); //Add context members. foreach (var member in ctx.Members) { AddContextMember(ctx.Name, member, data, ref text); } text.TrimEnd(',', ' '); text.TabOut(); text.AppendLine("],"); }
//Adds a single context to the text. private void AddContext(IroContext ctx, string name, IroPrecompileData data, ref RubyStringMaker text) { //Reset includes, create new state. includedThisRun = new List <string>(); text.AppendLine("state:" + name); text.TabIn(); //Loop over rules, add them. foreach (var member in ctx.Members) { AddContextMember(member, ctx.Name, data, ref text); } text.TabOut(); text.AppendLine("end"); }
/// <summary> /// Gets a list of styles for a specific pattern context member. /// </summary> private List <IroStyle> GetPatternStyles(List <string> styleNames, IroPrecompileData data) { //Check that styles exist, and try to get the first one out. if (styleNames.Count == 0) { Error.Compile("No style was defined for a pattern. All styles must have patterns."); return(null); } //Get all the patterns out. var styles = new List <IroStyle>(); foreach (var style in styleNames) { //Get the styles form the style list. int index = data.Styles.FindIndex(x => x.Name == style); if (index == -1) { Error.Compile("A style '" + style + "' is referenced in a pattern, but it is not defined in the style map."); return(null); } styles.Add(data.Styles[index]); } //Make sure all the patterns have textmate scopes. foreach (var style in styles) { if (style.AceScope == null) { //Missing ace, can inherit? if (style.TextmateScope == null) { Error.Compile("No Textmate or Atom scope is defined for style '" + style.Name + "'."); return(null); } style.AceScope = style.TextmateScope; } } return(styles); }
//Adds a single context to the compiling string. private void AddContext(IroContext thisCtx, string ctxName, IroPrecompileData data, ref StringBuilder text) { //Begin this context. text.AppendLine("\"" + ctxName + "\": ["); //Loop over the context, add all members. for (int i = 0; i < thisCtx.Members.Count; i++) { var member = thisCtx.Members[i]; AddMember(member, ctxName, ref text, data); } //Add the default member. text.AppendLine("{"); text.AppendLine("defaultToken: \"text\""); text.AppendLine("}"); //Close the context. text.AppendLine("],"); }
/// <summary> /// Compiles precompile data into an Atom Textmate file. /// </summary> public CompileResult Compile(IroPrecompileData data) { var text = new StringBuilder(); //Add the file extensions. text.AppendLine("'fileTypes': ["); foreach (var ext in data.FileExtensions) { text.AppendLine("'" + ext + "'"); } text.AppendLine("]"); //Name of the grammar. text.AppendLine("'name': '" + data.Name + "'"); //Template for including main. text.AppendLine("'patterns' : ["); text.AppendLine("{"); text.AppendLine("'include': '#main'"); text.AppendLine("}"); text.AppendLine("]"); //Root scope name. text.AppendLine("'scopeName': '" + data.Name + "'"); //UUID (if one exists). text.AppendLine("'uuid': '" + data.UUID + "'"); //Main repo for all patterns. text.AppendLine("'repository': {"); //Loop over contexts and add them. Make sure main is first. var mainCtx = data.Contexts.FirstOrDefault(x => x.Name == "main"); if (mainCtx == null) { Error.Compile("No main context exists to start the grammar with."); return(null); } //Add main. AddContext(mainCtx, data, ref text); ProcessQueuedContexts(data, ref text); //Loop over other contexts and add. foreach (var ctx in data.Contexts) { //Skip main, already processed. if (ctx.Name == "main") { continue; } AddContext(ctx, data, ref text); ProcessQueuedContexts(data, ref text); } //Close set, return. text.AppendLine("}"); return(new CompileResult() { GeneratedFile = FormatCScript(text.ToString()), Target = Target.Atom }); }
/// <summary> /// Compiles pre-compile data into a Pygments grammar file. /// </summary> public CompileResult Compile(IroPrecompileData data) { var text = new PyStringMaker(); //Header for imports and class naming. text.AppendLine("from pygments.lexer import RegexLexer, bygroups"); text.AppendLine("from pygments.token import *"); text.AppendLine("import re"); text.AppendLine("__all__ =['" + data.Name + "Lexer']"); text.AppendLine(); text.AppendLine("class " + data.Name + "Lexer(RegexLexer):"); text.TabIn(); //Name with capital first letter, aliases. text.AppendLine("name = '" + data.Name[0].ToString().ToUpper() + data.Name.Substring(1) + "'"); text.AppendLine("aliases = ['" + data.Name + "']"); //File names. string fNames = "["; foreach (var ext in data.FileExtensions) { fNames += "'" + ext + "', "; } fNames = fNames.TrimEnd(',', ' ') + "]"; text.AppendLine(fNames); //Template flags. text.AppendLine("flags = re.MULTILINE | re.UNICODE"); text.AppendLine(); //Open the tokens map. text.AppendLine("tokens = {"); text.TabIn(); //Get the root context and evaluate. var rootCtx = data.Contexts.FirstOrDefault(x => x.Name == "main"); if (rootCtx == null) { Error.Compile("No 'main' context exists to create the root grammar state from."); return(null); } AddContext(rootCtx, data, ref text); includedThisRun = new List <string>(); //Evaluate the rest of the contexts. foreach (var context in data.Contexts) { //Ignore main, already done. if (context.Name == "main") { continue; } //Add, reset includes. AddContext(context, data, ref text); includedThisRun = new List <string>(); } //Add queued contexts. for (int i = 0; i < queuedContexts.Count; i++) { var queued = queuedContexts.ElementAt(i); AddQueuedContext(queued.Key.Item2, queued.Key.Item1, queued.Value, data, ref text); } text.TabOut(); text.AppendLine("}"); return(new CompileResult() { GeneratedFile = text.ToString(), Target = Target.Pygments }); }
public CompileResult Compile(IroPrecompileData data) { throw new System.NotImplementedException(); }
/// <summary> /// Compiles a set of Iro precompile data into a generated file. /// </summary> public CompileResult Compile(IroPrecompileData data) { var text = new StringBuilder(); //Add the header. text.AppendLine("/*"); text.AppendLine("* To try in Ace editor, copy and paste into the mode creator"); text.AppendLine("*here : http://ace.c9.io/tool/mode_creator.html"); text.AppendLine("*/"); text.AppendLine(); text.AppendLine("define(function(require, exports, module) {"); text.AppendLine("\"use strict\";"); text.AppendLine("var oop = require(\"../lib/oop\");"); text.AppendLine("var TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;"); text.AppendLine("/* --------------------- START ----------------------------- */"); text.AppendLine("var MysampleHighlightRules = function() {"); text.AppendLine("this.$rules = { "); //Define the main ruleset. var mainCtx = data.Contexts.FirstOrDefault(x => x.Name == "main"); if (mainCtx == null) { Error.Compile("No 'main' context exists to create patterns from."); return(null); } //Add the main context. AddContext(mainCtx, "start", data, ref text); //Add all other contexts. foreach (var context in data.Contexts) { //Ignore main, already processed. if (context.Name == "main") { continue; } AddContext(context, context.Name, data, ref text); } //Add the queued contexts from inline pushes. while (queuedContexts.Count > 0) { AddQueuedContext(queuedContexts.First().Key, queuedContexts.First().Value, data, ref text); queuedContexts.Remove(queuedContexts.First().Key); } //Trim the trailing ",". text = text.TrimEnd(','); //Close the set. text.AppendLine("};"); text.AppendLine("this.normalizeRules();"); text.AppendLine("};"); //Footer. text.AppendLine("/* ------------------------ END ------------------------------ */"); text.AppendLine("oop.inherits(MysampleHighlightRules, TextHighlightRules);"); text.AppendLine("exports.MysampleHighlightRules = MysampleHighlightRules;"); text.AppendLine("});"); return(new CompileResult() { GeneratedFile = text.ToString(), Target = Target.Ace }); }
public CompileResult Compile(IroPrecompileData data) { string text = ""; //Loop over styles and remove weird proprietary Iro colour values (WhyYYYYY) foreach (var style in data.Styles) { ReplaceIroColours(ref style.Colour); ReplaceIroColours(ref style.BackgroundColour); } //Loop over styles, generate. foreach (var style in data.Styles) { //Name of the CSS class. if (!style.Name.StartsWith(".")) { Error.CompileWarning("When compiling for CSS, style names should start with a '.', prepending."); text += "."; } text += style.Name + " {"; //Body. if (style.Colour == null) { Error.Compile("When compiling for CSS, all styles must have a 'color' or 'colour' property."); return(null); } if (!validHexColour.IsMatch(style.Colour) && !validColours.Contains(style.Colour.ToLower())) { Error.Compile("Invalid colour name given for style '" + style.Name + "', must be a valid CSS colour or hexadecimal colour value."); return(null); } text += " color:" + style.Colour + "; "; //Is there a background colour? if (style.BackgroundColour != null) { //Valid? if (!validHexColour.IsMatch(style.Colour) && !validColours.Contains(style.Colour.ToLower())) { Error.Compile("Invalid background colour given for style '" + style.BackgroundColour + "', must be a valid CSS colour or hexadecimal colour value."); return(null); } text += "background-color: " + style.BackgroundColour + "; "; } //Font stylings.s if (style.Bold) { text += "font-weight: bold; "; } if (style.Italic) { text += "font-style: italic; "; } //Close the style! :) text += "}\r\n"; } //Done compiling, return target. return(new CompileResult() { Target = Target.CSS, GeneratedFile = text }); }
//Adds a single context member to the compiling string. private void AddMember(ContextMember member, string ctxName, ref StringBuilder text, IroPrecompileData data) { if (member.Type == ContextMemberType.Pattern) { //Normal pattern. var pattern = ((PatternContextMember)member); var patternStyles = GetPatternStyles(pattern.Styles, data); text.AppendLine("{"); text.AppendLine("\"token\": \"" + patternStyles[0].AceScope + "\","); //Replace normal '\' with '\\', since it's inside another string. text.AppendLine("\"regex\": \"" + pattern.Data.Replace("\\", "\\\\") + "\""); //Close pattern. text.AppendLine("},"); } else if (member.Type == ContextMemberType.InlinePush) { //Inline push pattern. var ilp = ((InlinePushContextMember)member); var ilpStyles = GetPatternStyles(ilp.Styles, data); //Get the push data. text.AppendLine("{"); text.AppendLine("\"token\": \"" + ilpStyles[0].AceScope + "\","); //Replace normal '\' with '\\', since it's inside another string. text.AppendLine("\"regex\": \"" + ilp.Data.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\","); //Queue an ILP context to be created later (if it's not already created). string pushCtxName; var ilpPushTuple = new Tuple <string, string>(ctxName, ilp.Data); if (!contextsCreated.ContainsKey(ilpPushTuple)) { pushCtxName = "helper_" + ShortId.Generate(7); //Queue and add to the "done" list. QueueILPContext(pushCtxName, ilp); contextsCreated.Add(ilpPushTuple, pushCtxName); } else { //Already created one for this regex. pushCtxName = contextsCreated[ilpPushTuple]; } text.AppendLine("\"push\": \"" + pushCtxName + "\""); //Close pattern. text.AppendLine("},"); } else if (member.Type == ContextMemberType.Include) { //Include. //Find the top-level context being included. var toInclude = data.Contexts.FirstOrDefault(x => x.Name == member.Data); if (toInclude == null) { Error.Compile("No context with name '" + member.Data + "' exists to include."); return; } //Make sure toInclude isn't this one. if (toInclude.Name == ctxName) { Error.CompileWarning("Recursive include loop detected, ignoring it."); return; } //Loop over all members in toInclude, include them. foreach (var memberInc in toInclude.Members) { AddMember(memberInc, toInclude.Name, ref text, data); } } }
private void AddContextMember(ContextMember member, string ctxName, IroPrecompileData data, ref RubyStringMaker text) { //What type is it? switch (member.Type) { case ContextMemberType.Pattern: //Normal pattern. var pattern = (PatternContextMember)member; string rule = "rule /"; rule += pattern.Data + "/"; //Get styles for pattern. Do they match up? var styles = GetPatternStyles(pattern.Styles, data); if (styles.Count > 1) { //Grouped. rule += " do"; text.AppendLine(rule); text.TabIn(); rule = "groups "; foreach (var style in styles) { rule += style.PygmentsScope.Replace(".", "::") + ", "; } rule = rule.TrimEnd(' ', ','); text.AppendLine(rule); text.TabOut(); text.AppendLine("end"); } else if (styles.Count != 0) { //Ungrouped. rule += ", " + styles[0].PygmentsScope.Replace(".", "::"); text.AppendLine(rule); } else { Error.Compile("No styles given for rule '" + pattern.Data + "'."); return; } break; case ContextMemberType.InlinePush: //Inline push pattern. var ilp = (InlinePushContextMember)member; string ruleIlp = "rule /" + ilp.Data + "/"; //Get styles for pattern. Do they match up? var pushStyles = GetPatternStyles(ilp.Styles, data); string helperName = "helper_" + ShortId.Generate(7); //Is the helper already made? var madeHelper = queuedContexts.FirstOrDefault(x => x.Key.Item1 == ctxName && x.Value.Data == ilp.Data); if (madeHelper.Key != null) { //Already made a helper, set the name. helperName = madeHelper.Key.Item2; } if (pushStyles.Count > 1) { //Grouped. ruleIlp += " do"; text.AppendLine(ruleIlp); text.TabIn(); ruleIlp = "groups "; foreach (var style in pushStyles) { ruleIlp += style.PygmentsScope.Replace(".", "::") + ", "; } ruleIlp = ruleIlp.TrimEnd(' ', ','); text.AppendLine(ruleIlp); //Add the push. ruleIlp = "push :" + helperName; //Tab out, end. text.TabOut(); text.AppendLine("end"); } else if (pushStyles.Count != 0) { //Ungrouped. ruleIlp += ", " + pushStyles[0].PygmentsScope.Replace(".", "::") + ", :" + helperName; text.AppendLine(ruleIlp); } else { Error.Compile("No styles given for rule '" + ilp.Data + "'."); return; } //Queue the push scope if not already pushed. if (madeHelper.Key == null) { QueueILPScope(ctxName, helperName, ilp); } break; case ContextMemberType.Include: //Get the context to include. var ctx = data.Contexts.FirstOrDefault(x => x.Name == member.Data); if (ctx == null) { Error.Compile("Context mentioned to include '" + member.Data + "' does not exist."); return; } //Skip? if (includedThisRun.Contains(member.Data)) { return; } //Include all members recursively with update list. includedThisRun.Add(member.Data); foreach (var mem in ctx.Members) { AddContextMember(mem, ctxName, data, ref text); } break; } }
//Adds an inline push context member. private void AddILPContext(string ctxName, string name, InlinePushContextMember mem, IroPrecompileData data, ref RubyStringMaker text) { //Create the rule, reset includes. includedThisRun = new List <string>(); text.AppendLine("state:" + name); text.TabIn(); //Add the pop rule. string popRule = "rule /" + mem.PopData + "/"; var styles = GetPatternStyles(mem.PopStyles, data); if (styles.Count > 1) { //Append. popRule += " do"; text.AppendLine(popRule); text.TabIn(); //Newline with groups. popRule = "groups "; foreach (var scope in styles) { popRule += scope.PygmentsScope.Replace(".", "::") + ", "; } popRule = popRule.TrimEnd(' ', ','); text.AppendLine(popRule); text.AppendLine("push :pop!"); text.TabOut(); text.AppendLine("end"); } else if (styles.Count == 1) { //Single style. popRule += ", " + styles[0].PygmentsScope.Replace(".", "::") + ", :pop!"; text.AppendLine(popRule); } else { Error.Compile("No pop styles included for pop rule '" + mem.PopData + "'."); return; } //Loop over rules, add them. foreach (var member in mem.Patterns) { AddContextMember(member, ctxName, data, ref text); } text.TabOut(); text.AppendLine("end"); }
//Adds a queued context to the text. private void AddQueuedContext(string name, string originalCtx, InlinePushContextMember ilp, IroPrecompileData data, ref PyStringMaker text) { //Open the context. text.AppendLine("'" + name + "' : ["); text.TabIn(); //Add the pop rule. var popStyles = GetPatternStyles(ilp.PopStyles, data); text.AppendLine("(u'" + ilp.PopData.Replace("\\", "\\\\") + "', byGroups(" + string.Join(", ", popStyles.Select(x => x.PygmentsScope)).TrimEnd(',', ' ') + "), '" + originalCtx + "')"); //Add context members. includedThisRun = new List <string>(); foreach (var member in ilp.Patterns) { AddContextMember(name, member, data, ref text); } text.TrimEnd(',', ' '); text.TabOut(); text.AppendLine("],"); }
/// <summary> /// Adds a single context member to the text. /// </summary> private void AddMember(ContextMember member, IroPrecompileData data, ref StringBuilder text) { if (member.Type == ContextMemberType.Pattern) { //Normal pattern. Get styles out. var pattern = ((PatternContextMember)member); var styles = GetPatternStyles(pattern.Styles, data); //Check if the groups match. if (!Compiler.GroupsMatch(pattern.Data, styles.Count)) { Error.Compile("Amount of capture groups does not line up with the amount of assigned styles."); return; } //Add to text. text.AppendLine("{"); //Make sure to replace backslashes and quotes. text.AppendLine("'match': '" + pattern.Data.Replace("\\", "\\\\").Replace("'", "\\'") + "'"); if (styles.Count > 1) { //Multiple styles. text.AppendLine("'captures': {"); for (int i = 0; i < styles.Count; i++) { //Numbered styles. text.AppendLine("'" + (i + 1) + "': {"); text.AppendLine("'name': '" + styles[i].TextmateScope + "." + data.Name + "'"); text.AppendLine("}"); } text.AppendLine("}"); } else { //Single style. text.AppendLine("'name': '" + styles[0].TextmateScope + "." + data.Name + "'"); } text.AppendLine("}"); } else if (member.Type == ContextMemberType.InlinePush) { //Inline push pattern. var ilp = ((InlinePushContextMember)member); var styles = GetPatternStyles(ilp.Styles, data); //Add starting styles. text.AppendLine("{"); text.AppendLine("'begin': '" + ilp.Data.Replace("\\", "\\\\").Replace("'", "\\'") + "'"); text.AppendLine("'beginCaptures': {"); for (int i = 0; i < styles.Count; i++) { text.AppendLine("'" + (i + 1) + "': {"); text.AppendLine("'name': '" + styles[i].TextmateScope + "." + data.Name + "'"); text.AppendLine("}"); } text.AppendLine("}"); //Is a default style assigned? int defaultStyleIndex = ilp.Patterns.FindIndex(x => x.Type == ContextMemberType.DefaultStyle); if (defaultStyleIndex != -1) { //Are other patterns defined? if (ilp.Patterns.FindIndex(x => x.Type == ContextMemberType.Pattern) != -1) { //Warn the user. Error.CompileWarning("You cannot define unique patterns when a 'default_style' attribute is applied. Ignoring them."); } //Get the style out. var style = GetPatternStyles(new List <string>() { ilp.Patterns[defaultStyleIndex].Data }, data); //Add default content name. text.AppendLine("'contentName': '" + style[0].TextmateScope + "." + data.Name + "'"); } else { //Actual patterns defined, not just default. //Begin patterns, capture all "pattern" sets and includes and queue them. text.AppendLine("'patterns': ["); //Include the queued context. if (ilp.Patterns.Count != 0) { string helperName = "helper_" + ShortId.Generate(7); text.AppendLine("{"); text.AppendLine("'include': '#" + helperName + "'"); text.AppendLine("}"); //Queue it. QueueContext(helperName, ilp.Patterns); } text.AppendLine("]"); } //Patterns done, pop condition & styles. var popStyles = GetPatternStyles(ilp.PopStyles, data); //Patterns match up with context groups? if (!Compiler.GroupsMatch(ilp.PopData, popStyles.Count)) { Error.Compile("Mismatch between capture groups and number of styles for pop with regex '" + ilp.PopData + "'."); return; } //Okay, add pop data. text.AppendLine("'end': '" + ilp.PopData.Replace("\\", "\\\\").Replace("'", "\\'") + "'"); text.AppendLine("'endCaptures': {"); for (int i = 0; i < popStyles.Count; i++) { text.AppendLine("'" + (i + 1) + "': {"); text.AppendLine("'name': '" + popStyles[i].TextmateScope + "." + data.Name + "'"); text.AppendLine("}"); } text.AppendLine("}"); //Close whole ILP. text.AppendLine("}"); } else if (member.Type == ContextMemberType.Include) { //Append an include. text.AppendLine("{"); text.AppendLine("'include': '#" + member.Data + "'"); text.AppendLine("}"); } }
private void AddContextMember(string ctxName, ContextMember member, IroPrecompileData data, ref PyStringMaker text) { //What's the context member type? string regTxt = ""; switch (member.Type) { //Normal pattern. case ContextMemberType.Pattern: var pat = (PatternContextMember)member; regTxt += "(u'" + pat.Data.Replace("\\", "\\\\") + "', bygroups("; //Get styles out. var styles = GetPatternStyles(pat.Styles, data); //Apply styles. foreach (var style in styles) { regTxt += style.PygmentsScope + ", "; } regTxt = regTxt.TrimEnd(',', ' '); //Close bygroups, end pattern. regTxt += ")),"; text.AppendLine(regTxt); return; //Inline push. case ContextMemberType.InlinePush: var ilp = (InlinePushContextMember)member; regTxt += "(u'" + ilp.Data.Replace("\\", "\\\\") + "', bygroups("; //Get push styles out. var pushStyles = GetPatternStyles(ilp.Styles, data); //Add and close bygroups scope. foreach (var style in pushStyles) { regTxt += style.PygmentsScope + ", "; } regTxt = regTxt.TrimEnd(',', ' '); regTxt += ")"; //Add the push scope with a random name. string helperName = "helper_" + ShortId.Generate(7); QueueContext(ctxName, helperName, ilp); regTxt += ", '" + helperName + "'),"; text.AppendLine(regTxt); return; //Include. case ContextMemberType.Include: //Get the context to include. var ctx = data.Contexts.FirstOrDefault(x => x.Name == member.Data); if (ctx == null) { Error.Compile("Context mentioned to include '" + member.Data + "' does not exist."); return; } //Skip? if (includedThisRun.Contains(member.Data)) { return; } //Include all members recursively with update list. includedThisRun.Add(member.Data); foreach (var mem in ctx.Members) { AddContextMember(ctxName, mem, data, ref text); } return; } }