Skip to content

Commit

Permalink
Allow any text for the heading
Browse files Browse the repository at this point in the history
This change allows any text to be included after `# Change Log` and
before the first release node. This closes #12 and also closes #10 by
making a single release AST impossible since the heading is now its
own node.
  • Loading branch information
Theodus authored and SeanTAllen committed Sep 15, 2017
1 parent 33513ac commit 00e0fe4
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 48 deletions.
31 changes: 15 additions & 16 deletions changelog.pony
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
use "peg"

class Changelog
let unreleased: (Release | None)
let released: Array[Release]
let heading: String
var unreleased: (Release | None)
embed released: Array[Release]

new create(ast: AST) ? =>
let children = ast.children.values()
released = Array[Release](ast.size())
if ast.size() > 0 then
released = Array[Release]

heading = (children.next()? as Token).string()
if ast.size() > 1 then
unreleased = try Release(children.next()? as AST)? end
for child in children do
released.push(Release(child as AST)?)
Expand All @@ -16,10 +19,7 @@ class Changelog
unreleased = None
end

new _create(unreleased': (Release | None), released': Array[Release]) =>
(unreleased, released) = (unreleased', released')

fun ref create_release(version: String, date: String): Changelog^ ? =>
fun ref create_release(version: String, date: String) ? =>
match unreleased
| let r: Release =>
r.heading = "## [" + version + "] - " + date
Expand All @@ -33,19 +33,18 @@ class Changelog
if (r.changed as Section).entries == "" then
r.changed = None
end

_create(None, released.>unshift(r))
else this
else
this
end

fun ref create_unreleased(): Changelog^ =>
if unreleased is None then _create(Release._unreleased(), released)
else this
fun ref create_unreleased() =>
if unreleased is None then
unreleased = Release._unreleased()
end

fun string(): String iso^ =>
let str = (recover String end)
.> append(_Util.changelog_heading())
.> append(heading)
.> append("\n")
if unreleased isnt None then str.append(unreleased.string()) end
for release in released.values() do
Expand Down Expand Up @@ -77,7 +76,7 @@ class Release
for section in [fixed; added; changed].values() do
match section
| let s: this->Section =>
str.>append(s.string()).>append("\n\n")
str .> append(s.string()) .> append("\n\n")
end
end
str
Expand Down
15 changes: 9 additions & 6 deletions changelog_parser.pony
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ use "peg"
primitive ChangelogParser
fun apply(): Parser val =>
recover
let heading = L(_Util.changelog_heading())
-heading * -L("\n").many1() * release(false).opt() * release().many()
head() * release(false).opt() * release().many()
end

fun head(): Parser val =>
recover
(not L("\n## [") * Unicode).many().term(THeading)
* -L("\n").opt()
end

fun release(released: Bool = true): Parser val =>
Expand Down Expand Up @@ -56,6 +61,8 @@ primitive ChangelogParser

fun digit(): Parser val => recover R('0', '9') end

primitive THeading is Label fun text(): String => "Heading"

trait val TSection is Label
primitive Fixed is TSection fun text(): String => "Fixed"
primitive Added is TSection fun text(): String => "Added"
Expand All @@ -65,7 +72,3 @@ primitive TRelease is Label fun text(): String => "Release"
primitive TVersion is Label fun text(): String => "Version"
primitive TDate is Label fun text(): String => "Date"
primitive TEntries is Label fun text(): String => "Entries"

primitive _Util
fun changelog_heading(): String =>
"# Change Log\n\nAll notable changes to the Pony compiler and standard library will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com/).\n"
6 changes: 3 additions & 3 deletions changelog_tool.pony
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ChangelogTool
let date = Date(Time.seconds()).format("%Y-%m-%d")
let changelog: String =
Changelog(_parse()?)?
.create_release(version, date)?
.> create_release(version, date)?
.string()
_edit_or_print(edit, changelog)
else
Expand All @@ -43,7 +43,7 @@ class ChangelogTool
try
let changelog: String =
Changelog(_parse()?)?
.create_unreleased()
.> create_unreleased()
.string()
_edit_or_print(edit, changelog)
else
Expand All @@ -66,7 +66,7 @@ class ChangelogTool
let source = Source(FilePath(_env.root as AmbientAuth, _filename)?)?
match recover val ChangelogParser().parse(source) end
| (_, let ast: AST) =>
//_env.out.print(recover val Printer(ast) end)
// _env.out.print(recover val Printer(ast) end)
ast
| (let offset: USize, let r: Parser val) =>
let e = recover val SyntaxError(source, offset, r) end
Expand Down
161 changes: 138 additions & 23 deletions tests/main.pony
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,10 @@ actor Main is TestList
test(_TestParseVersion)
test(_TestParseDate)
test(_TestParseEntries)
test(_TestParseHead)
test(_TestParseChangelog)
test(_TestSingleRelease)

class ParseTest
let _h: TestHelper
let _parser: Parser

new create(h: TestHelper, parser: Parser) =>
(_h, _parser) = (h, parser)

fun run(tests: Array[(String, String)]) =>
for (source, expected) in tests.values() do
_h.log("test: " + source)
let source' = Source.from_string(source)
match recover val _parser.parse(source') end
| (_, let r: (AST | Token | NotPresent)) =>
let result = recover val Printer(r) end
_h.assert_eq[String](expected, result)
| (let offset: USize, let r: Parser val) =>
let e = recover val SyntaxError(source', offset, r) end
_Logv(_h, PegFormatError.console(e))
_h.assert_eq[String](expected, "")
| (_, Skipped) => _h.log("skipped")
| (_, Lex) => _h.log("lex")
end
end

class iso _TestParseVersion is UnitTest
fun name(): String => "parse version"
Expand Down Expand Up @@ -83,6 +62,52 @@ class iso _TestParseEntries is UnitTest
"(Entries - Upgrade to LLVM 3.9.1 ([PR #1498](https://github.com/ponylang/ponyc/pull/1498)))\n" )
])

class iso _TestParseHead is UnitTest
fun name(): String => "parse heading"

fun apply(h: TestHelper) =>
ParseTest(h, ChangelogParser.head()).run(
[ ( """
# Change Log
All notable changes to the Pony compiler and standard library will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com/).
""",
"""
(Heading # Change Log
All notable changes to the Pony compiler and standard library will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com/).
)
""")
( """
# Change Log
Some other text
## [unreleased] - unreleased
""",
"""
(Heading # Change Log
Some other text
)
""" )
( """
# Change Log
Some other text that contains:
`## [unreleased] - unreleased`
## [unreleased] - unreleased
""",
"""
(Heading # Change Log
Some other text that contains:
`## [unreleased] - unreleased`
)
""" )
])

class iso _TestParseChangelog is UnitTest
fun name(): String => "parse CHANGELOG"

Expand Down Expand Up @@ -114,6 +139,96 @@ class iso _TestParseChangelog is UnitTest
h.fail()
end

class iso _TestSingleRelease is UnitTest
fun name(): String => "single release"

fun apply(h: TestHelper) ? =>
_OutputTest(h, ChangelogParser()).run(
"""
# Change Log
All notable changes to the Pony compiler and standard library will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com/).
## [unreleased] - unreleased
### Fixed
- Fix invalid separator in PONYPATH for Windows. ([PR #32](https://github.com/ponylang/pony-stable/pull/32))
### Added
### Changed
""",
"""
# Change Log
All notable changes to the Pony compiler and standard library will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com/).
## [0.0.0] - 0000-00-00
### Fixed
- Fix invalid separator in PONYPATH for Windows. ([PR #32](https://github.com/ponylang/pony-stable/pull/32))
""")?

class ParseTest
let _h: TestHelper
let _parser: Parser

new create(h: TestHelper, parser: Parser) =>
(_h, _parser) = (h, parser)

fun run(tests: Array[(String, String)]) =>
for (source, expected) in tests.values() do
_h.log("test: " + source)
let source' = Source.from_string(source)
match recover val _parser.parse(source') end
| (_, let r: (AST | Token | NotPresent)) =>
let result = recover val Printer(r) end
_h.assert_eq[String](expected, result)
| (let offset: USize, let r: Parser val) =>
let e = recover val SyntaxError(source', offset, r) end
_Logv(_h, PegFormatError.console(e))
_h.assert_eq[String](expected, "")
| (_, Skipped) => _h.log("skipped")
| (_, Lex) => _h.log("lex")
end
end

class _OutputTest
let _h: TestHelper
let _parser: Parser

new create(h: TestHelper, parser: Parser) =>
(_h, _parser) = (h, parser)

fun run(input: String, expected: String) ? =>
let source = Source.from_string(input)
match recover val _parser.parse(source) end
| (let n: USize, let r: (AST | Token | NotPresent)) =>
match r
| let ast: AST =>
let changelog =
Changelog(ast)? .> create_release("0.0.0", "0000-00-00")?
let output: String = changelog.string()
_h.log(recover val Printer(ast) end)
_h.log(output)
_h.assert_eq[String](expected, output)
else
_h.log(recover val Printer(r) end)
_h.fail()
end
| (let offset: USize, let r: Parser val) =>
let e = recover val SyntaxError(source, offset, r) end
_Logv(_h, PegFormatError.console(e))
_h.fail()
end

primitive _Logv
fun apply(h: TestHelper, bsi: ByteSeqIter) =>
let str = recover String end
Expand Down

0 comments on commit 00e0fe4

Please sign in to comment.