ProcessResult Apply(IEnumerable<SnippetGroup> availableSnippets, TextWriter writer, IndexReader reader) { var snippets = availableSnippets.ToList(); var missingSnippets = new List<MissingSnippet>(); var usedSnippets = new List<SnippetGroup>(); string line; while ((line = reader.ReadLine()) != null) { string key; if (!keyReader(line, out key)) { writer.WriteLine(line); continue; } writer.WriteLine("<!-- snippet: {0} -->", key); var snippetGroup = snippets.FirstOrDefault(x => x.Key == key); if (snippetGroup == null) { var missingSnippet = new MissingSnippet(key: key, line: reader.Index); missingSnippets.Add(missingSnippet); var message = $"** Could not find key '{key}' **"; writer.WriteLine(message); continue; } AppendGroup(snippetGroup, writer); if (usedSnippets.All(x => x.Key != snippetGroup.Key)) { usedSnippets.Add(snippetGroup); } } return new ProcessResult(missingSnippets: missingSnippets, usedSnippets: usedSnippets); }
/// <summary> /// Read <see cref="ReadSnippet"/> from a <see cref="TextReader"/>. /// </summary> /// <param name="textReader">The <see cref="TextReader"/> to read from.</param> /// <param name="source">Used to infer the version. Usually this will be the path to a file or a url.</param> public ReadSnippets FromReader(TextReader textReader, string source = null) { Guard.AgainstNull(textReader, "textReader"); using (var reader = new IndexReader(textReader)) { return GetSnippetsFromFile(reader, source); } }
ReadSnippets ProcessFile(string file) { using (var textReader = File.OpenText(file)) using (var stringReader = new IndexReader(textReader)) { return GetSnippetsFromFile(stringReader, file); } }
/// <summary> /// Apply <paramref name="snippets"/> to <paramref name="textReader"/>. /// </summary> public ProcessResult Apply(IEnumerable<SnippetGroup> snippets, TextReader textReader, TextWriter writer) { Guard.AgainstNull(snippets, "snippets"); Guard.AgainstNull(textReader, "textReader"); Guard.AgainstNull(writer, "writer"); using (var reader = new IndexReader(textReader)) { return Apply(snippets, writer, reader); } }
ReadSnippets GetSnippetsFromFile(IndexReader stringReader, string file) { var errors = new List<ReadSnippetError>(); var snippets = new List<ReadSnippet>(); var language = GetLanguageFromFile(file); var loopState = new LoopState(); while (true) { var line = stringReader.ReadLine(); if (line == null) { if (loopState.IsInSnippet) { errors.Add(new ReadSnippetError( message: "Snippet was not closed", file: file, line: loopState.StartLine.Value + 1, key: loopState.CurrentKey, version: null)); } break; } var trimmedLine = line.Trim().Replace(" ", " ").ToLowerInvariant(); if (loopState.IsInSnippet) { if (!loopState.EndFunc(trimmedLine)) { loopState.SnippetLines.Add(line); continue; } TryAddSnippet(stringReader, file, loopState, language, errors, snippets); loopState.Reset(); continue; } IsStart(stringReader, trimmedLine, loopState); } return new ReadSnippets(snippets, errors); }
void TryAddSnippet(IndexReader stringReader, string file, LoopState loopState, string language, List<ReadSnippetError> errors, List<ReadSnippet> snippets) { VersionRange parsedVersion; var startRow = loopState.StartLine.Value + 1; if (!TryParseVersion(file, loopState, out parsedVersion)) { errors.Add(new ReadSnippetError( message : "Could not extract version", file : file, line : startRow, key : loopState.CurrentKey, version:null)); return; } var value = ConvertLinesToValue(loopState.SnippetLines); if (value.IndexOfAny(invalidCharacters) > -1) { var joinedInvalidChars = "'" + string.Join("', '", invalidCharacters) + "'"; errors.Add(new ReadSnippetError( message: $"Snippet contains invalid characters ({joinedInvalidChars}). This was probably caused by you copying code from MS Word or Outlook. Dont do that.", file: file, line: startRow, key: loopState.CurrentKey, version: parsedVersion)); } var snippet = new ReadSnippet( startLine : startRow, endLine : stringReader.Index, key : loopState.CurrentKey.ToLowerInvariant(), version : parsedVersion, value : value, file : file, language: language.ToLowerInvariant()); snippets.Add(snippet); }
static void IsStart(IndexReader stringReader, string trimmedLine, LoopState loopState) { string version; string currentKey; if (IsStartCode(trimmedLine, out currentKey, out version)) { loopState.EndFunc = IsEndCode; loopState.CurrentKey = currentKey; loopState.IsInSnippet = true; loopState.Version = version; loopState.StartLine = stringReader.Index; loopState.SnippetLines = new List<string>(); return; } if (IsStartRegion(trimmedLine, out currentKey, out version)) { loopState.EndFunc = IsEndRegion; loopState.CurrentKey = currentKey; loopState.IsInSnippet = true; loopState.Version = version; loopState.StartLine = stringReader.Index; loopState.SnippetLines = new List<string>(); } }