From 0bdc55c26ff8d6906fabfb15ab2b788ea8e434e4 Mon Sep 17 00:00:00 2001 From: Jens Date: Fri, 16 Feb 2018 17:58:12 +0100 Subject: [PATCH 1/5] [Stdlib, Spec-lib] Myst spec failures now includes path to the failure ``` require "stdlib/spec.mt" describe("Fish") do describe("#swim") do it("moves the fish forward")do assert(false) end end end ``` Will now print: ```text Fish #swim moves the fish forward Assertion failed. Expected: true Got: false ``` In red :D Also with this came a simple module `Color` with `#colored` which is what is used for printing red and green stuff here. To make that work, I added some lexing for escape codes (notably `\e`). --- src/myst/syntax/lexer.cr | 5 ++++ stdlib/colored.mt | 39 +++++++++++++++++++++++++++++++ stdlib/spec.mt | 6 +++++ stdlib/spec/describe_container.mt | 17 ++++++++++++++ stdlib/spec/single_spec.mt | 6 +++-- 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 stdlib/colored.mt create mode 100644 stdlib/spec/describe_container.mt diff --git a/src/myst/syntax/lexer.cr b/src/myst/syntax/lexer.cr index 62eead9..243182e 100644 --- a/src/myst/syntax/lexer.cr +++ b/src/myst/syntax/lexer.cr @@ -397,6 +397,11 @@ module Myst when "\\n" then '\n' when "\\\"" then '"' when "\\t" then '\t' + when "\\e" then '\e' + when "\\r" then '\r' + when "\\f" then '\f' + when "\\v" then '\v' + when "\\b" then '\b' when "\\0" then '\0' end end diff --git a/stdlib/colored.mt b/stdlib/colored.mt new file mode 100644 index 0000000..2e039f3 --- /dev/null +++ b/stdlib/colored.mt @@ -0,0 +1,39 @@ +defmodule Color + def ansi_from_symbol(sym) + when sym == :black + return ANSI_BLACK + when sym == :red + return ANSI_RED + when sym == :green + return ANSI_GREEN + when sym == :yellow + return ANSI_YELLOW + when sym == :blue + return ANSI_BLUE + when sym == :purple + return ANSI_PURPLE + when sym == :cyan + return ANSI_CYAN + when sym == :white + return ANSI_WHITE + else + raise ":\"<(sym)>\" is not a valid color" + end + end + + ANSI_RESET = "\e[0m" + + ANSI_BLACK = "\e[0;30m" + ANSI_RED = "\e[0;31m" + ANSI_GREEN = "\e[0;32m" + ANSI_YELLOW = "\e[0;33m" + ANSI_BLUE = "\e[0;34m" + ANSI_PURPLE = "\e[0;35m" + ANSI_CYAN = "\e[0;36m" + ANSI_WHITE = "\e[0;37m" + + def colored(string : String, sym) + color = ansi_from_symbol(sym) + "<(color)><(string)><(ANSI_RESET)>" + end +end diff --git a/stdlib/spec.mt b/stdlib/spec.mt index 32fb2fc..fe0951b 100644 --- a/stdlib/spec.mt +++ b/stdlib/spec.mt @@ -1,6 +1,8 @@ require "./spec/dsl.mt" require "./spec/errors.mt" require "./spec/single_spec.mt" +require "./spec/describe_container.mt" +require "./colored.mt" # Spec # @@ -24,6 +26,8 @@ require "./spec/single_spec.mt" # Calls). This should be addressed before too long, since it's a fairly common # use case, but a basic Spec library does not require it. defmodule Spec + describe_stack = [] + def it(name, &block) spec = %SingleSpec{name} spec.run{ block() } @@ -39,6 +43,8 @@ defmodule Spec def describe(name, &block) + describe_stack.push(%DescribeContainer{name}) block() + describe_stack.pop end end diff --git a/stdlib/spec/describe_container.mt b/stdlib/spec/describe_container.mt new file mode 100644 index 0000000..6ce2959 --- /dev/null +++ b/stdlib/spec/describe_container.mt @@ -0,0 +1,17 @@ +defmodule Spec + deftype DescribeContainer + def initialize(name : String) + @name = name + end + + def name; @name; end + + def get_path(current : String) + when !describe_stack.empty? + return describe_stack.pop.get_path("<(@name)> <(current)>") + else + "<(@name)> <(current)>" + end + end + end +end diff --git a/stdlib/spec/single_spec.mt b/stdlib/spec/single_spec.mt index 0708084..75bb867 100644 --- a/stdlib/spec/single_spec.mt +++ b/stdlib/spec/single_spec.mt @@ -9,9 +9,11 @@ defmodule Spec def run(&block) block() - STDOUT.print(".") + STDOUT.print(Color.colored(".", :green)) rescue failure - STDOUT.puts(failure) + STDOUT.puts("\n") + STDOUT.puts(Color.colored(" <(describe_stack.pop.get_path(@name))>", :red)) + STDOUT.puts(Color.colored(" <(failure)>", :red)) exit(1) end end From 7930b838ad06e07e9ea347e09a9ec631f590d3fe Mon Sep 17 00:00:00 2001 From: Jens Date: Fri, 16 Feb 2018 18:01:41 +0100 Subject: [PATCH 2/5] Completes the previous commit (Forgot to put some stuff in the previous) --- stdlib/colored.mt | 4 ++-- stdlib/spec.mt | 3 +++ stdlib/spec/single_spec.mt | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/stdlib/colored.mt b/stdlib/colored.mt index 2e039f3..b7ea0cb 100644 --- a/stdlib/colored.mt +++ b/stdlib/colored.mt @@ -32,8 +32,8 @@ defmodule Color ANSI_CYAN = "\e[0;36m" ANSI_WHITE = "\e[0;37m" - def colored(string : String, sym) + def colored(string, sym) color = ansi_from_symbol(sym) - "<(color)><(string)><(ANSI_RESET)>" + "<(color)><(string.to_s)><(ANSI_RESET)>" end end diff --git a/stdlib/spec.mt b/stdlib/spec.mt index fe0951b..b808a71 100644 --- a/stdlib/spec.mt +++ b/stdlib/spec.mt @@ -4,6 +4,8 @@ require "./spec/single_spec.mt" require "./spec/describe_container.mt" require "./colored.mt" +include Spec + # Spec # # A simple library for writing specs around Myst code. Specs are written using @@ -27,6 +29,7 @@ require "./colored.mt" # use case, but a basic Spec library does not require it. defmodule Spec describe_stack = [] + include DSL def it(name, &block) spec = %SingleSpec{name} diff --git a/stdlib/spec/single_spec.mt b/stdlib/spec/single_spec.mt index 75bb867..f154dde 100644 --- a/stdlib/spec/single_spec.mt +++ b/stdlib/spec/single_spec.mt @@ -14,6 +14,7 @@ defmodule Spec STDOUT.puts("\n") STDOUT.puts(Color.colored(" <(describe_stack.pop.get_path(@name))>", :red)) STDOUT.puts(Color.colored(" <(failure)>", :red)) + STDOUT.puts exit(1) end end From f9fa921c4dbea4f694960b364621a8e4f3062cc2 Mon Sep 17 00:00:00 2001 From: Jens Date: Fri, 16 Feb 2018 22:54:17 +0100 Subject: [PATCH 3/5] Added `List#first` and `List#last` --- stdlib/list.mt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/stdlib/list.mt b/stdlib/list.mt index ac0c4b0..4f9a605 100644 --- a/stdlib/list.mt +++ b/stdlib/list.mt @@ -9,6 +9,26 @@ deftype List "[" + join(",") + "]" end + def first + self[0] + end + + def first? + first + rescue + nil + end + + def last + self[self.size - 1] + end + + def last? + last + rescue + nil + end + # empty? -> bool # # Return `true` if the List contains 0 elements. Return `false` otherwise. From 568ad39e4b10e9585e0f16ba4c5aaad7eebf78e9 Mon Sep 17 00:00:00 2001 From: Jens Date: Fri, 16 Feb 2018 22:55:11 +0100 Subject: [PATCH 4/5] Added type restriction for `sym` in `Color#colored` --- stdlib/colored.mt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/colored.mt b/stdlib/colored.mt index b7ea0cb..581a1ec 100644 --- a/stdlib/colored.mt +++ b/stdlib/colored.mt @@ -32,8 +32,8 @@ defmodule Color ANSI_CYAN = "\e[0;36m" ANSI_WHITE = "\e[0;37m" - def colored(string, sym) + def colored(string, sym : Symbol) color = ansi_from_symbol(sym) - "<(color)><(string.to_s)><(ANSI_RESET)>" + "<(color)><(string)><(ANSI_RESET)>" end end From d78dca08b939595c7d990d2e72f2dfc4c8a36577 Mon Sep 17 00:00:00 2001 From: Jens Date: Fri, 16 Feb 2018 22:56:01 +0100 Subject: [PATCH 5/5] Made the spec-lib not tear itself down when an error occured... --- stdlib/spec/describe_container.mt | 6 +++--- stdlib/spec/single_spec.mt | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/stdlib/spec/describe_container.mt b/stdlib/spec/describe_container.mt index 6ce2959..e2a708a 100644 --- a/stdlib/spec/describe_container.mt +++ b/stdlib/spec/describe_container.mt @@ -6,9 +6,9 @@ defmodule Spec def name; @name; end - def get_path(current : String) - when !describe_stack.empty? - return describe_stack.pop.get_path("<(@name)> <(current)>") + def get_path(current : String, stack_index) + when !describe_stack.empty? && next_describe = describe_stack[stack_index] + return describe_stack[stack_index].get_path("<(@name)> <(current)>", stack_index - 1) else "<(@name)> <(current)>" end diff --git a/stdlib/spec/single_spec.mt b/stdlib/spec/single_spec.mt index f154dde..6de5e31 100644 --- a/stdlib/spec/single_spec.mt +++ b/stdlib/spec/single_spec.mt @@ -12,7 +12,15 @@ defmodule Spec STDOUT.print(Color.colored(".", :green)) rescue failure STDOUT.puts("\n") - STDOUT.puts(Color.colored(" <(describe_stack.pop.get_path(@name))>", :red)) + + last = describe_stack.last? + + when last + STDOUT.puts(Color.colored(" <(last.get_path(@name, describe_stack.size -1))>", :red)) + else + STDOUT.puts(Color.colored(" <(@name)>"), :red) + end + STDOUT.puts(Color.colored(" <(failure)>", :red)) STDOUT.puts exit(1)