3 people like it.

Release Notes parser

See: https://github.com/fsharp/FAKE/issues/171 This is a parser for RELEASE_NOTES.md files for F# projects. Handles both simple and more complex file formats described in the link above.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
open System
open System.IO
open System.Text.RegularExpressions

// set paths here
let dir = @"..\dev\FSharpScripts\fsharp_comunity_code_sprint\"
let simple_notes = dir + @"RELEASE_NOTES_simple.md"
let complex_notes = dir + @"RELEASE_NOTES_complex.md"

let nugetRegex = Regex(@"([0-9]+.)+[0-9]+(-[a-zA-Z]+)?")    // e.g: match "4.1.22-beta"
let assemblyRegex = Regex(@"([0-9]+.)+[0-9]+")              // e.g: match "0.13.2"

/// Parse simple release notes sequence
let parseSimpleReleaseNotes (text:seq<string>) =
    let lastLine = text |> Seq.last
    let assemblyVersion, nugetVersion = assemblyRegex.Match(lastLine), nugetRegex.Match(lastLine)
    if not assemblyVersion.Success then 
        failwith "Unable to parse valid Assembly version from release notes."
    let notes = lastLine.Substring(nugetVersion.Index + nugetVersion.Length).Trim([|' '; '-'|]);
    assemblyVersion.Value, nugetVersion.Value, [notes]

/// Parse "complex" release notes text sequence
let parseComplexReleaseNotes (text:seq<string>) =
    let indexOfLastBlock = // index of last block that begings with {#}+
        text
        |> Seq.fold (fun (index, ctr) str ->
            if String.IsNullOrEmpty(str) then (index, ctr + 1)
            elif str.Trim().[0] = '#' then (index + ctr, 1) 
            else (index, ctr + 1)) (0, 0)
        |> fst
    let lastBlock = text |> Seq.skip indexOfLastBlock
    let blockHeader = lastBlock |> Seq.head
    let notes =
        lastBlock
        |> Seq.skip 1
        |> Seq.map (fun str -> str.Trim([|' '; '*'|]))
        |> Seq.toList
    let assemblyVersion, nugetVersion = assemblyRegex.Match(blockHeader), nugetRegex.Match(blockHeader)
    if not assemblyVersion.Success then
        failwith "Unable to parse valid Assembly version from release notes."
    assemblyVersion.Value, nugetVersion.Value, notes
    

/// Parse a Release Notes File - Either simple or "complex" format
/// See: https://github.com/fsharp/FAKE/issues/171
/// <param name="filePath">The path to the release notes file</param>
/// <returns> (assembly_version, nuget_version, [release_notes]) </returns>
let parseReleaseNotes filePath =
    let text = // read file and trim leading & trailing blank lines
        let data = File.ReadLines(filePath) 
        let num_real_lines =
            data
            |> Seq.fold (fun (line_count, blank_count) str ->
                if String.IsNullOrEmpty(str.Trim()) then
                    line_count, blank_count + 1 
                else line_count + 1 + blank_count, 0) (0, 0)
            |> fst
        data
        |> Seq.take num_real_lines // drop trailing empty lines
        |> Seq.skipWhile (fun str -> String.IsNullOrWhiteSpace(str.Trim())) // drop leading empty lines
    
    if text |> Seq.isEmpty then failwith "Empty Realease file."

    let (|Simple|Complex|Invalid|) c  =
        match c with
        |'*' -> Simple
        |'#' -> Complex
        |_ -> Invalid
    let firstNonEmptyChar = (text |> Seq.head).Trim([|'-'; ' '|]).[0]
    match firstNonEmptyChar with
    |Simple -> parseSimpleReleaseNotes text   // parse simple release notes type
    |Complex -> parseComplexReleaseNotes text  // parse complex release notes type
    |Invalid -> failwith "Invalid Release Notes format."
namespace System
namespace System.IO
namespace System.Text
namespace System.Text.RegularExpressions
val dir : string

Full name: Script.dir
val simple_notes : string

Full name: Script.simple_notes
val complex_notes : string

Full name: Script.complex_notes
val nugetRegex : Regex

Full name: Script.nugetRegex
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
Regex(pattern: string) : unit
Regex(pattern: string, options: RegexOptions) : unit
val assemblyRegex : Regex

Full name: Script.assemblyRegex
val parseSimpleReleaseNotes : text:seq<string> -> string * string * string list

Full name: Script.parseSimpleReleaseNotes


 Parse simple release notes sequence
val text : seq<string>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val lastLine : string
module Seq

from Microsoft.FSharp.Collections
val last : source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.last
val assemblyVersion : Match
val nugetVersion : Match
Regex.Match(input: string) : Match
Regex.Match(input: string, startat: int) : Match
Regex.Match(input: string, beginning: int, length: int) : Match
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
property Group.Success: bool
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
val notes : string
String.Substring(startIndex: int) : string
String.Substring(startIndex: int, length: int) : string
property Capture.Index: int
property Capture.Length: int
property Capture.Value: string
val parseComplexReleaseNotes : text:seq<string> -> string * string * string list

Full name: Script.parseComplexReleaseNotes


 Parse "complex" release notes text sequence
val indexOfLastBlock : int
val fold : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> 'State

Full name: Microsoft.FSharp.Collections.Seq.fold
val index : int
val ctr : int
val str : string
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
String.IsNullOrEmpty(value: string) : bool
String.Trim() : string
String.Trim([<ParamArray>] trimChars: char []) : string
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val lastBlock : seq<string>
val skip : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.skip
val blockHeader : string
val head : source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.head
val notes : string list
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
val parseReleaseNotes : filePath:string -> string * string * string list

Full name: Script.parseReleaseNotes


 Parse a Release Notes File - Either simple or "complex" format
 See: https://github.com/fsharp/FAKE/issues/171
 <param name="filePath">The path to the release notes file</param>
 <returns> (assembly_version, nuget_version, [release_notes]) </returns>
val filePath : string
val data : Collections.Generic.IEnumerable<string>
type File =
  static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
  static member AppendAllText : path:string * contents:string -> unit + 1 overload
  static member AppendText : path:string -> StreamWriter
  static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
  static member Create : path:string -> FileStream + 3 overloads
  static member CreateText : path:string -> StreamWriter
  static member Decrypt : path:string -> unit
  static member Delete : path:string -> unit
  static member Encrypt : path:string -> unit
  static member Exists : path:string -> bool
  ...

Full name: System.IO.File
File.ReadLines(path: string) : Collections.Generic.IEnumerable<string>
File.ReadLines(path: string, encoding: Text.Encoding) : Collections.Generic.IEnumerable<string>
val num_real_lines : int
val line_count : int
val blank_count : int
val take : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.take
val skipWhile : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.skipWhile
String.IsNullOrWhiteSpace(value: string) : bool
val isEmpty : source:seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.isEmpty
val c : char
val firstNonEmptyChar : char
active recognizer Simple: char -> Choice<unit,unit,unit>
active recognizer Complex: char -> Choice<unit,unit,unit>
active recognizer Invalid: char -> Choice<unit,unit,unit>
Raw view Test code New version

More information

Link:http://fssnip.net/ku
Posted:10 years ago
Author:Alpha Diallo
Tags: fake , f# community code sprint