Skip to content

Commit

Permalink
Add UriLine
Browse files Browse the repository at this point in the history
  • Loading branch information
menees committed Oct 27, 2023
1 parent baca1f5 commit 4ed9561
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<IsPublishable>false</IsPublishable>

<!-- Make the assembly, file, and NuGet package versions the same. -->
<Version>0.8.6-beta</Version>
<Version>0.8.7-beta</Version>
<UseLocaMeneesLibraries>false</UseLocaMeneesLibraries>
<LocaMeneesLibrariesSrc/>
<BuildingInsideVisualStudio Condition="'$(BuildingInsideVisualStudio)' == ''">false</BuildingInsideVisualStudio>
Expand Down
4 changes: 4 additions & 0 deletions src/Menees.Chords/HeaderLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ internal HeaderLine(string text, IEnumerable<Entry>? annotations = null)
return result;
}

#endregion

#region Protected Methods

/// <summary>
/// Writes the header text in brackets.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/Menees.Chords/Parsers/DocumentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public sealed class DocumentParser
new Func<LineContext, Entry?>[]
{
// Add line parsers in order from most specific syntax to least specific syntax.
UriLine.TryParse,
HeaderLine.TryParse,
ChordProRemarkLine.TryParse, // This will parse #-prefixed lines before Comment.TryParse gets them.
Comment.TryParse,
Expand Down
5 changes: 5 additions & 0 deletions src/Menees.Chords/Transformers/ChordProTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ protected virtual IReadOnlyList<Entry> TransformEntries(IReadOnlyList<Entry> inp

break;

case UriLine uri:
this.Add(output, new ChordProRemarkLine("# " + uri.Text));
this.AddAnnotations(output, uri.Annotations);
break;

default:
this.Add(output, entry);
break;
Expand Down
85 changes: 85 additions & 0 deletions src/Menees.Chords/UriLine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
namespace Menees.Chords;

#region Using Directives

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Menees.Chords.Parsers;

#endregion

/// <summary>
/// A line that parses with <see cref="Uri.TryCreate(string, UriKind, out Uri)"/> as an absolute URI.
/// </summary>
public sealed class UriLine : TextEntry
{
#region Constructors

private UriLine(string line, Uri uri, IEnumerable<Entry>? annotations = null)
: base(line, annotations)
{
this.Uri = uri;
}

#endregion

#region Public Properties

/// <summary>
/// Gets the parsed <see cref="Uri"/> for the current line.
/// </summary>
public Uri Uri { get; }

#endregion

#region Public Methods

/// <summary>
/// Tries to parse a header line from the current context.
/// </summary>
/// <param name="context">The current parsing context.</param>
/// <returns>A new instance if <paramref name="context"/>'s line was parsed. Null otherwise.</returns>
public static UriLine? TryParse(LineContext context)
{
Conditions.RequireNonNull(context);

UriLine? result = null;

Lexer lexer = context.CreateLexer(out IReadOnlyList<Entry> annotations);
if (lexer.Read(skipLeadingWhiteSpace: true) && lexer.Token.Type == TokenType.Text)
{
// We have to pull the token text out here because we're about to move the lexer forward.
string uriText = lexer.Token.Text;

// Since annotations were removed earlier, make sure there's nothing else on the line.
// And make sure the header text isn't a chord. We won't look for specific header values
// since Ultimate Guitar has many header variations:
// Intro, Outro, Verse, Verse #, Chorus, Interlude, Bridge, Pre-Chorus, Solo, Solo #, Break, Post-Chorus, Pre-Verse
if ((!lexer.Read() || string.IsNullOrEmpty(lexer.ReadToEnd(skipTrailingWhiteSpace: true)))
&& Uri.TryCreate(uriText, UriKind.Absolute, out Uri? uri))
{
result = new(uriText, uri, annotations);
}
}

return result;
}

#endregion

#region Protected Methods

/// <summary>
/// Writes <see cref="Uri"/>.
/// </summary>
/// <param name="writer">Used to write output.</param>
protected override void WriteWithoutAnnotations(TextWriter writer)
{
Conditions.RequireNonNull(writer);
writer.Write(this.Uri);
}

#endregion
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Every Rose Has Its Thorn – Poison. Bpm: 72. Original ½ step down.

https://tabs.ultimate-guitar.com/tab/poison/every-rose-has-its-thorn-chords-130272

[Verse 1]
G Cadd9 G Cadd9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Every Rose Has Its Thorn
Poison
72 bpm
** Original ½ step down **

# https://tabs.ultimate-guitar.com/tab/poison/every-rose-has-its-thorn-chords-130272

[Verse 1]
G Cadd9 G Cadd9
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{artist: Poison}
{tempo: 72}
{comment: Original ½ step down}

# https://tabs.ultimate-guitar.com/tab/poison/every-rose-has-its-thorn-chords-130272

{start_of_verse: Verse 1}
[G] [Cadd9] [G] [Cadd9]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{artist: Poison}
{tempo: 72}
{comment: Original ½ step down}

# https://tabs.ultimate-guitar.com/tab/poison/every-rose-has-its-thorn-chords-130272

{start_of_verse: Verse 1}
[G] [Cadd9] [G] [Cadd9]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Menees.Chords.Transformers.Tests;
namespace Menees.Chords.Transformers;

[TestClass]
public class ChordOverLyricTransformerTests
Expand Down
54 changes: 54 additions & 0 deletions tests/Menees.Chords.Tests/UriLineTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
namespace Menees.Chords;

using Menees.Chords.Parsers;

[TestClass]
public class UriLineTests
{
[TestMethod]
public void TryParseValidTest()
{
Test("https://github.com/menees/Chords/commits/master");
Test(" https://learn.microsoft.com/en-us/dotnet/core/install/windows?tabs=net70 ");
Test("https://learn.microsoft.com/en-us/dotnet/core/install/windows?tabs=net70#install-with-windows-installer");
Test(@"C:\Windows\System32\aadtb.dll", "file:///C:/Windows/System32/aadtb.dll");
Test(
"https://learn.microsoft.com/en-us/dotnet/core/install/windows (install-with-windows-installer)",
"https://learn.microsoft.com/en-us/dotnet/core/install/windows",
"(install-with-windows-installer)");

static void Test(string text, string? uri = null, string? comment = null)
{
uri ??= text;
LineContext context = LineContextTests.Create(text);
UriLine line = UriLine.TryParse(context).ShouldNotBeNull(text);
line.Uri.ShouldBe(new Uri(uri));
if (comment is not null)
{
line.Annotations.Count.ShouldBe(1);
line.Annotations[0].ShouldBeOfType<Comment>().ToString().ShouldBe(comment);
if (text.EndsWith(comment))
{
text = text.Substring(0, text.Length - comment.Length);
}
}

line.Text.ShouldBe(text.Trim());
}
}

[TestMethod]
public void TryParseInvalidTest()
{
Test("Not a Uri");
Test("[A#]");
Test("Mesa/Boogie");

static void Test(string text)
{
LineContext context = LineContextTests.Create(text);
UriLine? line = UriLine.TryParse(context);
line.ShouldBeNull();
}
}
}

0 comments on commit 4ed9561

Please sign in to comment.