Merge remote-tracking branch 'upstream/master'

This commit is contained in:
GlenCFL
2017-12-07 14:16:47 -05:00
115 changed files with 2927 additions and 1252 deletions

View File

@@ -35,9 +35,8 @@
<HintPath>..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Castle.Windsor, Version=3.3.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Windsor.3.3.0\lib\net45\Castle.Windsor.dll</HintPath>
<Private>True</Private>
<Reference Include="Castle.Windsor, Version=3.4.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
<HintPath>..\packages\Castle.Windsor.3.4.0\lib\net45\Castle.Windsor.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="System" />

View File

@@ -29,64 +29,70 @@ namespace Filtration.Parser.Services
_blockGroupHierarchyBuilder = blockGroupHierarchyBuilder;
}
// Converts a string into an ItemFilterCommentBlock maintaining newlines and spaces but removing # characters
public IItemFilterCommentBlock TranslateStringToItemFilterCommentBlock(string inputString, IItemFilterScript parentItemFilterScript)
{
var itemFilterCommentBlock = new ItemFilterCommentBlock(parentItemFilterScript);
foreach (var line in new LineReader(() => new StringReader(inputString)))
{
var trimmedLine = line.TrimStart(' ').TrimStart('#');
itemFilterCommentBlock.Comment += trimmedLine + Environment.NewLine;
}
itemFilterCommentBlock.Comment = itemFilterCommentBlock.Comment.TrimEnd('\r', '\n');
return itemFilterCommentBlock;
}
// This method converts a string into a ItemFilterBlock. This is used for pasting ItemFilterBlocks
// and reading ItemFilterScripts from a file.
public IItemFilterBlock TranslateStringToItemFilterBlock(string inputString, ThemeComponentCollection masterComponentCollection)
public IItemFilterBlock TranslateStringToItemFilterBlock(string inputString, IItemFilterScript parentItemFilterScript, bool initialiseBlockGroupHierarchyBuilder = false)
{
_masterComponentCollection = masterComponentCollection;
var block = new ItemFilterBlock();
if (initialiseBlockGroupHierarchyBuilder)
{
_blockGroupHierarchyBuilder.Initialise(parentItemFilterScript.ItemFilterBlockGroups.First());
}
_masterComponentCollection = parentItemFilterScript.ItemFilterScriptSettings.ThemeComponentCollection;
var block = new ItemFilterBlock(parentItemFilterScript);
var showHideFound = false;
foreach (var line in new LineReader(() => new StringReader(inputString)))
{
if (line.StartsWith(@"# Section:"))
{
var section = new ItemFilterSection
{
Description = line.Substring(line.IndexOf(":", StringComparison.Ordinal) + 1).Trim()
};
return section;
}
if (line.StartsWith(@"#") && !showHideFound)
{
block.Description = line.TrimStart('#').TrimStart(' ');
continue;
}
var adjustedLine = line.Replace("#", " # ");
var trimmedLine = adjustedLine.TrimStart(' ').TrimEnd(' ');
var trimmedLine = line.Trim();
var spaceOrEndOfLinePos = trimmedLine.IndexOf(" ", StringComparison.Ordinal) > 0 ? trimmedLine.IndexOf(" ", StringComparison.Ordinal) : trimmedLine.Length;
var lineOption = trimmedLine.Substring(0, spaceOrEndOfLinePos);
switch (lineOption)
{
case "Show":
showHideFound = true;
block.Action = BlockAction.Show;
block.Enabled = true;
AddBlockGroupToBlock(block, trimmedLine);
break;
case "Hide":
showHideFound = true;
block.Action = BlockAction.Hide;
block.Enabled = true;
AddBlockGroupToBlock(block, trimmedLine);
break;
case "ShowDisabled":
showHideFound = true;
block.Action = BlockAction.Show;
block.Enabled = false;
AddBlockGroupToBlock(block, trimmedLine);
break;
case "HideDisabled":
{
showHideFound = true;
block.Action = BlockAction.Hide;
block.Enabled = false;
AddBlockGroupToBlock(block, trimmedLine);
block.Action = lineOption.StartsWith("Show") ? BlockAction.Show : BlockAction.Hide;
block.Enabled = !lineOption.EndsWith("Disabled");
// If block groups are enabled for this script, the comment after Show/Hide is parsed as a block
// group hierarchy, if block groups are disabled it is preserved as a simple text comment.
if (parentItemFilterScript.ItemFilterScriptSettings.BlockGroupsEnabled)
{
AddBlockGroupToBlock(block, trimmedLine);
}
else
{
block.ActionBlockItem.Comment = GetTextAfterFirstComment(trimmedLine);
}
break;
}
case "ItemLevel":
{
AddNumericFilterPredicateItemToBlockItems<ItemLevelBlockItem>(block, trimmedLine);
@@ -417,11 +423,11 @@ namespace Filtration.Parser.Services
private void AddBlockGroupToBlock(IItemFilterBlock block, string inputString)
{
var blockGroupStart = inputString.IndexOf("#", StringComparison.Ordinal);
if (blockGroupStart <= 0) return;
var blockGroupText = GetTextAfterFirstComment(inputString);
var blockGroups = blockGroupText.Split(new[] { " - " }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Trim())
.ToList();
var blockGroupText = inputString.Substring(blockGroupStart + 1);
var blockGroups = blockGroupText.Split('-').ToList();
if (blockGroups.Count(b => !string.IsNullOrEmpty(b.Trim())) > 0)
{
block.BlockGroup = _blockGroupHierarchyBuilder.IntegrateStringListIntoBlockGroupHierarchy(blockGroups);
@@ -429,6 +435,14 @@ namespace Filtration.Parser.Services
}
}
private static string GetTextAfterFirstComment(string inputString)
{
var blockGroupStart = inputString.IndexOf("#", StringComparison.Ordinal);
if (blockGroupStart <= 0) return string.Empty;
return inputString.Substring(blockGroupStart + 1);
}
private static Color GetColorFromString(string inputString)
{
var argbValues = Regex.Matches(inputString, @"\s+(\d+)");
@@ -455,15 +469,31 @@ namespace Filtration.Parser.Services
return new Color();
}
public string TranslateItemFilterBlockBaseToString(IItemFilterBlockBase itemFilterBlockBase)
{
var itemFilterBlock = itemFilterBlockBase as IItemFilterBlock;
if (itemFilterBlock != null) return TranslateItemFilterBlockToString(itemFilterBlock);
var itemFilterCommentBlock = itemFilterBlockBase as IItemFilterCommentBlock;
if (itemFilterCommentBlock != null) return TranslateItemFilterCommentBlockToString(itemFilterCommentBlock);
throw new InvalidOperationException("Unable to translate unknown ItemFilterBlock type");
}
// TODO: Private
public string TranslateItemFilterCommentBlockToString(IItemFilterCommentBlock itemFilterCommentBlock)
{
// TODO: Handle multi-line
// TODO: Tests
// TODO: # Section: text?
return $"#{itemFilterCommentBlock.Comment}";
}
// This method converts an ItemFilterBlock object into a string. This is used for copying a ItemFilterBlock
// to the clipboard, and when saving a ItemFilterScript.
// TODO: Private
public string TranslateItemFilterBlockToString(IItemFilterBlock block)
{
if (block.GetType() == typeof (ItemFilterSection))
{
return "# Section: " + block.Description;
}
var outputString = string.Empty;
if (!block.Enabled)
@@ -482,6 +512,10 @@ namespace Filtration.Parser.Services
{
outputString += " # " + block.BlockGroup;
}
else if (!string.IsNullOrEmpty(block.ActionBlockItem?.Comment))
{
outputString += " #" + block.ActionBlockItem.Comment;
}
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var blockItem in block.BlockItems.Where(b => b.GetType() != typeof(ActionBlockItem)).OrderBy(b => b.SortOrder))

View File

@@ -2,27 +2,53 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Filtration.Common.Utilities;
using Filtration.ObjectModel;
using Filtration.ObjectModel.Factories;
using Filtration.Parser.Interface.Services;
using Filtration.Properties;
namespace Filtration.Parser.Services
{
internal class ItemFilterBlockBoundary
{
public ItemFilterBlockBoundary(int startLine, ItemFilterBlockBoundaryType itemFilterBlockBoundaryType)
{
StartLine = startLine;
BoundaryType = itemFilterBlockBoundaryType;
}
public int StartLine { get; set; }
public ItemFilterBlockBoundaryType BoundaryType { get; set; }
}
internal enum ItemFilterBlockBoundaryType
{
ScriptDescription,
ItemFilterBlock,
CommentBlock
}
internal class ItemFilterScriptTranslator : IItemFilterScriptTranslator
{
private readonly IItemFilterBlockTranslator _blockTranslator;
private readonly IItemFilterScriptFactory _itemFilterScriptFactory;
private readonly IBlockGroupHierarchyBuilder _blockGroupHierarchyBuilder;
public ItemFilterScriptTranslator(IItemFilterBlockTranslator blockTranslator,
IBlockGroupHierarchyBuilder blockGroupHierarchyBuilder)
public ItemFilterScriptTranslator(IBlockGroupHierarchyBuilder blockGroupHierarchyBuilder,
IItemFilterBlockTranslator blockTranslator,
IItemFilterScriptFactory itemFilterScriptFactory)
{
_blockTranslator = blockTranslator;
_blockGroupHierarchyBuilder = blockGroupHierarchyBuilder;
_blockTranslator = blockTranslator;
_itemFilterScriptFactory = itemFilterScriptFactory;
}
public string PreprocessDisabledBlocks(string inputString)
public static string PreprocessDisabledBlocks(string inputString)
{
bool inDisabledBlock = false;
var showHideFound = false;
@@ -82,9 +108,9 @@ namespace Filtration.Parser.Services
return lines.Aggregate((c, n) => c + Environment.NewLine + n);
}
public ItemFilterScript TranslateStringToItemFilterScript(string inputString)
public IItemFilterScript TranslateStringToItemFilterScript(string inputString)
{
var script = new ItemFilterScript();
var script = _itemFilterScriptFactory.Create();
_blockGroupHierarchyBuilder.Initialise(script.ItemFilterBlockGroups.First());
inputString = inputString.Replace("\t", "");
@@ -98,12 +124,12 @@ namespace Filtration.Parser.Services
var lines = Regex.Split(inputString, "\r\n|\r|\n");
// Process the script header
for (var i = 0; i < conditionBoundaries.First.Value; i++)
for (var i = 0; i < conditionBoundaries.Skip(1).First().StartLine; i++)
{
if (lines[i].StartsWith("#"))
{
script.Description += lines[i].Substring(1).Trim(' ') + Environment.NewLine;
}
}
}
if (!string.IsNullOrEmpty(script.Description))
@@ -115,47 +141,94 @@ namespace Filtration.Parser.Services
// and add that object to the ItemFilterBlocks list
for (var boundary = conditionBoundaries.First; boundary != null; boundary = boundary.Next)
{
var begin = boundary.Value;
var end = boundary.Next?.Value ?? lines.Length;
if (boundary.Value.BoundaryType == ItemFilterBlockBoundaryType.ScriptDescription)
{
continue;
}
var begin = boundary.Value.StartLine;
var end = boundary.Next?.Value.StartLine ?? lines.Length;
var block = new string[end - begin];
Array.Copy(lines, begin, block, 0, end - begin);
var blockString = string.Join("\r\n", block);
script.ItemFilterBlocks.Add(_blockTranslator.TranslateStringToItemFilterBlock(blockString, script.ThemeComponents));
if (boundary.Value.BoundaryType == ItemFilterBlockBoundaryType.ItemFilterBlock)
{
script.ItemFilterBlocks.Add(_blockTranslator.TranslateStringToItemFilterBlock(blockString, script));
}
else
{
script.ItemFilterBlocks.Add(_blockTranslator.TranslateStringToItemFilterCommentBlock(blockString, script));
}
}
_blockGroupHierarchyBuilder.Cleanup();
return script;
}
private static LinkedList<int> IdentifyBlockBoundaries(string inputString)
private static LinkedList<ItemFilterBlockBoundary> IdentifyBlockBoundaries(string inputString)
{
var blockBoundaries = new LinkedList<int>();
var blockBoundaries = new LinkedList<ItemFilterBlockBoundary>();
var previousLine = string.Empty;
var currentLine = 0;
var currentLine = -1;
var currentItemFilterBlockBoundary = new ItemFilterBlockBoundary(0, ItemFilterBlockBoundaryType.ScriptDescription);
foreach (var line in new LineReader(() => new StringReader(inputString)))
{
currentLine++;
var trimmedLine = line.TrimStart(' ').TrimEnd(' ');
if (trimmedLine.StartsWith("Show") || trimmedLine.StartsWith("Hide") ||
trimmedLine.StartsWith("# Section:"))
var trimmedLine = line.Trim(' ');
if (string.IsNullOrWhiteSpace(trimmedLine))
{
previousLine = line;
continue;
}
// A line starting with a comment when we're inside a ItemFilterBlock boundary represents the end of that block
// as ItemFilterBlocks cannot have comment lines after the block description
if (trimmedLine.StartsWith("#") && currentItemFilterBlockBoundary.BoundaryType == ItemFilterBlockBoundaryType.ItemFilterBlock)
{
blockBoundaries.AddLast(currentItemFilterBlockBoundary);
currentItemFilterBlockBoundary = new ItemFilterBlockBoundary(currentLine, ItemFilterBlockBoundaryType.CommentBlock);
}
// A line starting with a comment where the previous line was null represents the start of a new comment (unless we're on the first
// line in which case it's not a new comment).
else if (trimmedLine.StartsWith("#") && string.IsNullOrWhiteSpace(previousLine) && currentItemFilterBlockBoundary.BoundaryType != ItemFilterBlockBoundaryType.ScriptDescription)
{
if (blockBoundaries.Count > 0)
{
blockBoundaries.AddLast(currentItemFilterBlockBoundary);
}
currentItemFilterBlockBoundary = new ItemFilterBlockBoundary(currentLine, ItemFilterBlockBoundaryType.CommentBlock);
}
else if (trimmedLine.StartsWith("Show") || trimmedLine.StartsWith("Hide"))
{
// If the line previous to the Show or Hide line is a comment then we should include that in the block
// as it represents the block description.
// currentLine > 2 caters for an edge case where the script description is a single line and the first
// block has no description. This prevents the script description from being assigned to the first block's description.
blockBoundaries.AddLast(previousLine.StartsWith("#") && !previousLine.StartsWith("# Section:") &&
currentLine > 2
? currentLine - 2
: currentLine - 1);
if (!(currentItemFilterBlockBoundary.StartLine == currentLine - 1 && currentItemFilterBlockBoundary.BoundaryType == ItemFilterBlockBoundaryType.CommentBlock))
{
blockBoundaries.AddLast(currentItemFilterBlockBoundary);
}
currentItemFilterBlockBoundary = new ItemFilterBlockBoundary(previousLine.StartsWith("#") && currentLine > 2 ? currentLine - 1 : currentLine,
ItemFilterBlockBoundaryType.ItemFilterBlock);
}
previousLine = line;
}
if (blockBoundaries.Last.Value != currentItemFilterBlockBoundary)
{
blockBoundaries.AddLast(currentItemFilterBlockBoundary);
}
return blockBoundaries;
}
public string TranslateItemFilterScriptToString(ItemFilterScript script)
public string TranslateItemFilterScriptToString(IItemFilterScript script)
{
var outputString = string.Empty;
@@ -178,7 +251,7 @@ namespace Filtration.Parser.Services
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var block in script.ItemFilterBlocks)
{
outputString += _blockTranslator.TranslateItemFilterBlockToString(block) + Environment.NewLine;
outputString += _blockTranslator.TranslateItemFilterBlockToString(block as ItemFilterBlock) + Environment.NewLine;
if (Settings.Default.ExtraLineBetweenBlocks)
{

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Castle.Core" version="3.3.3" targetFramework="net461" />
<package id="Castle.Windsor" version="3.3.0" targetFramework="net461" />
<package id="Castle.Windsor" version="3.4.0" targetFramework="net461" />
</packages>