what_weve_got_here_is_an_error_to_communicate 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +2 -0
  6. data/Rakefile +6 -0
  7. data/Readme.md +34 -0
  8. data/acceptance +29 -0
  9. data/experiments/formatting/5_potential_structure_dsls.rb +88 -0
  10. data/experiments/formatting/half_thoughtout_dsl_for_toplevel_structure_of_argument_error.rb +43 -0
  11. data/experiments/formatting/haml_like_structure.rb +139 -0
  12. data/experiments/formatting/other_structures +156 -0
  13. data/lib/error_to_communicate.rb +3 -0
  14. data/lib/error_to_communicate/at_exit.rb +11 -0
  15. data/lib/error_to_communicate/config.rb +32 -0
  16. data/lib/error_to_communicate/exception_info.rb +41 -0
  17. data/lib/error_to_communicate/format.rb +132 -0
  18. data/lib/error_to_communicate/format/terminal_helpers.rb +97 -0
  19. data/lib/error_to_communicate/parse/backtrace.rb +34 -0
  20. data/lib/error_to_communicate/parse/exception.rb +21 -0
  21. data/lib/error_to_communicate/parse/no_method_error.rb +27 -0
  22. data/lib/error_to_communicate/parse/registry.rb +30 -0
  23. data/lib/error_to_communicate/parse/wrong_number_of_arguments.rb +35 -0
  24. data/lib/error_to_communicate/rspec_formatter.rb +46 -0
  25. data/lib/error_to_communicate/version.rb +3 -0
  26. data/lib/what_weve_got_here_is_an_error_to_communicate.rb +3 -0
  27. data/screenshot.png +0 -0
  28. data/spec/acceptance/argument_error_spec.rb +55 -0
  29. data/spec/acceptance/exception_spec.rb +29 -0
  30. data/spec/acceptance/no_error_spec.rb +44 -0
  31. data/spec/acceptance/no_methood_error_spec.rb +50 -0
  32. data/spec/acceptance/spec_helper.rb +41 -0
  33. data/spec/parse/backtrace_spec.rb +101 -0
  34. data/spec/parse/exception_spec.rb +14 -0
  35. data/spec/parse/no_method_error_spec.rb +23 -0
  36. data/spec/parse/registered_parsers_spec.rb +68 -0
  37. data/spec/parse/spec_helper.rb +23 -0
  38. data/spec/parse/wrong_number_of_arguments_spec.rb +77 -0
  39. data/spec/rspec_formatter_spec.rb +95 -0
  40. data/spec/spec_helper.rb +20 -0
  41. data/what_weve_got_here_is_an_error_to_communicate.gemspec +19 -0
  42. metadata +168 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6d8b74cd9d659e3218cc9ecad4a0fdbba80b6d07
4
+ data.tar.gz: eadb2da5ec5d00795c54b93bf8efd7e0304b017d
5
+ SHA512:
6
+ metadata.gz: e060fb388519b4492109c8e31d1f723b6b3cdb939650b6a709348778cbf771f0cbd5f75ec7a866945d140308c58330c5436d464cd01254fea9c4272f4b87c126
7
+ data.tar.gz: 2df113222792975b9e4bdc07dbdb2190e1f4f67b1ef5b5daa6b13d2fbfaa675755abc92818e873c00e737efdacd84dd38f8790cb49ccac72d72ef23f12fefaa9
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ # Where our acceptance tests render
2
+ proving_grounds
3
+
4
+ # Libs shouldn't lock down deps
5
+ Gemfile.lock
6
+
7
+ # Thoughts and shit
8
+ notes
9
+
10
+ # the rubygems we compile and distribute
11
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --fail-fast
3
+ --require error_to_communicate/rspec_formatter
4
+ --format WhatWeveGotHereIsAnErrorToCommunicate::RSpecFormatter
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ matrix:
7
+ fast_finish: true
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env rake
2
+ require File.join('rspec', 'core', 'rake_task')
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/Readme.md ADDED
@@ -0,0 +1,34 @@
1
+ [![Build Status](https://travis-ci.org/JoshCheek/what-we-ve-got-here-is-an-error-to-communicate.svg?branch=master)](https://travis-ci.org/JoshCheek/what-we-ve-got-here-is-an-error-to-communicate)
2
+
3
+ What if error messages were compelling to read?
4
+ -----------------------------------------------
5
+
6
+ Blog explaining the code is [here](http://blog.turing.io/2015/01/18/what-we-ve-got-here-is-an-error-to-communicate/).
7
+ (or will be once it's merged).
8
+
9
+ A screenshot of the code rendering an `ArgumentError`.
10
+
11
+ ![screenshot](https://s3.amazonaws.com/josh.cheek/images/scratch/better-reuby-commandline-errors.png)
12
+
13
+ This is a proof of concept
14
+ --------------------------
15
+
16
+ This isn't fit for real-world use.
17
+ If there is resonance in the community, I'll probably try to make it a real gem.
18
+ I'll have some time to do that during my next braeak in late march 2015.
19
+
20
+ Inspirations:
21
+ -------------
22
+
23
+ * I think initially this was inspired by Sarah Gray's talk at Software Craftsmanship North America:
24
+ [Visualizing Enumerable: Own Abstract Concepts Through Physicalization](https://vimeo.com/54860297)
25
+ * Got to thinking about it again with Kerri Miller, conversing at DCamp,
26
+ and then at Ruby Conf, she created [chatty_exceptions](https://github.com/kerrizor/chatty_exceptions)
27
+ which is in this same domain.
28
+ * Charlie Sommerville's [better_errors](https://rubygems.org/gems/better_errors)
29
+ gem gives you a nice interface like this for Rails.
30
+
31
+ License
32
+ --------
33
+
34
+ [<img src="http://www.wtfpl.net/wp-content/uploads/2012/12/wtfpl.svg" width="15" height="15" alt="WTFPL" /> Do what the fuck you want to.](http://www.wtfpl.net/)
data/acceptance ADDED
@@ -0,0 +1,29 @@
1
+ No error:
2
+ Given a file that doesn't error
3
+ No exception is printed
4
+ It exits with 0
5
+
6
+ Argument Error:
7
+ Given a file with three lines in the backtrace that explodes on the third
8
+ displaying the error:
9
+ It prints the exception class
10
+ It prints the message (reworded to be more obvious)
11
+ heuristic:
12
+ It displays the most recent line of code and the next 5
13
+ It displays the second most recent of the backtrace, and 5 lines of code before / after
14
+ backtrace:
15
+ It displays each line of the backtrace
16
+ It includes the code from that line
17
+
18
+ NoMethod Error:
19
+ Given a file with three lines in the backtrace that explodes on the third
20
+ displaying the error:
21
+ It prints the exception class
22
+ It prints the message (reworded to be more obvious) #<Object> has no method called #<method name>
23
+ heuristic:
24
+ It displays the line of the backtrace with the NoMethodError, and 5 lines of code before / after #This is where it blew up
25
+ It displays the second most recent of the backtrace, and 5 lines of code before / after #This is where the called started
26
+ backtrace:
27
+ It displays each line of the backtrace
28
+ It includes the code from that line
29
+
@@ -0,0 +1,88 @@
1
+ # a bunch of different options for what the DSL could look like
2
+
3
+ def display_location(attributes)
4
+ formatter = attributes.fetch :formatter
5
+ location = attributes.fetch :location
6
+ path = Pathname.new location.path
7
+ line_index = location.linenum - 1
8
+ highlight = attributes.fetch :highlight, location.label # currently ignoring this, b/c we can't highlight into the middle of the syntax highlighted output
9
+ end_index = bound_num min: 0, num: line_index+attributes.fetch(:context).end
10
+ start_index = bound_num min: 0, num: line_index+attributes.fetch(:context).begin
11
+ annotation = attributes.fetch :annotation, ''
12
+ message_offset = line_index - start_index
13
+ emphasize_path = attributes.fetch(:emphasisis) == :path
14
+ raw_code = path.exist? && File.read(path).lines[start_index..end_index].join("")
15
+
16
+ # explicitly call begin to make the next call a node, call .end to leave
17
+ formatter
18
+ .begin.group(:path_with_code)
19
+ .begin.group(:path, emphasize_path&&:emphasize)
20
+ .text(:dir, path_to_dir(@cwd, path, '/'))
21
+ .text(:filename, path.basename)
22
+ .text(:separator, ":")
23
+ .text(:line_number, location.linenum)
24
+ .end
25
+ .begin.code(raw_code || "Can't find code")
26
+ .strip_indentation(true)
27
+ .language(:ruby)
28
+ .starting_linenum(start_index.next)
29
+ .if(raw_code).annotate(:error, annotate, line: message_offset)
30
+ .end
31
+ .end
32
+
33
+ # leaves get !, use .end to end a node
34
+ formatter
35
+ .group(:path_with_code)
36
+ .group(:path, emphasize_path&&:emphasize)
37
+ .text!(:dir, path_to_dir(@cwd, path, '/'))
38
+ .text!(:filename, path.basename)
39
+ .text!(:separator, ":")
40
+ .text!(:line_number, location.linenum)
41
+ .end
42
+ .code(raw_code || "Can't find code")
43
+ .strip_indentation!
44
+ .language!(:ruby)
45
+ .starting_linenum!(start_index.next)
46
+ .if(raw_code)
47
+ .annotate!(:error, annotate, line: message_offset)
48
+ .end
49
+ .end
50
+ .end
51
+
52
+ # nodes get !
53
+ formatter
54
+ .group!(:path_with_code)
55
+ .group!(:path, emphasize_path&&:emphasize)
56
+ .text(:dir, path_to_dir(@cwd, path, '/'))
57
+ .text(:filename, path.basename)
58
+ .text(:separator, ":")
59
+ .text(:line_number, location.linenum)
60
+ .end
61
+ .code!(raw_code || "Can't find code")
62
+ .strip_indentation
63
+ .language(:ruby)
64
+ .starting_linenum(start_index.next)
65
+ .if!(raw_code)
66
+ .annotate(:error, annotate, line: message_offset)
67
+ .end
68
+ .end
69
+ .end
70
+
71
+ # swapping self
72
+ formatter.eval prototype: self do
73
+ group :path_with_code do
74
+ group :path, emphasize_path&&:emphasize do
75
+ text :dir, path_to_dir(@cwd, path, '/')
76
+ text :filename, path.basename
77
+ text :separator, ":"
78
+ text :line_number, location.linenum
79
+ end
80
+ code raw_code||"Can't find code" do
81
+ language :ruby
82
+ strip_indentation
83
+ starting_linenum start_index.next
84
+ annotate :error, annotate, line: message_offset if raw_code
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,43 @@
1
+ SemanticStructure
2
+ .dsl
3
+ .partition
4
+ .header
5
+ .title!(@info.classname)
6
+ .subtext(:error)
7
+ .text!(@info.explanation)
8
+ .deemphasize
9
+ .text!(:context, '(expected ')
10
+ .text!(:stands_out, @info.num_expected)
11
+ .text!(:context, ', sent ')
12
+ .text!(:stands_out, @info.num_received)
13
+ .text!(:context, ')')
14
+ .end
15
+ .end
16
+ .end
17
+ }
18
+ .partition { |heuristic|
19
+ heuristic = display_location formatter: heuristic,
20
+ annotation: "expected #{@info.num_expected}",
21
+ location: @info.backtrace[0],
22
+ highlight: @info.backtrace[0].label,
23
+ context: 0..5,
24
+ emphasisis: :code
25
+
26
+ heuristic = display_location formatter: heuristic
27
+ annotation: "SENT #{info.num_received}",
28
+ location: info.backtrace[1],
29
+ highlight: info.backtrace[0].label,
30
+ context: -5..5,
31
+ emphasisis: :code
32
+ heuristic
33
+ }
34
+ .partition { |fmt|
35
+ info.backtrace.reduce(fmt) do |formatter, location|
36
+ display_location formatter: formatter,
37
+ location: location,
38
+ highlight: location.succ.label,
39
+ context: 0..0,
40
+ emphasisis: :path
41
+ end
42
+ }
43
+ end
@@ -0,0 +1,139 @@
1
+ # hypothetical way to render http://blog.turing.io/images/article_images/error_to_communicate/proof_of_concept-e2d4c91d.png
2
+ # Seems like it would take a lot of work, though, and I'm not totally sure how to map it to HTML/CSS
3
+
4
+ # ===== KEY =====
5
+ defn: - a tree definition named "defn"
6
+ defn:< - a tree definition named "defn" with one child, a node named "defn"
7
+ node - a node named "node"
8
+ if a leaf, then its children may be provided as text
9
+ or zero or more of any kind of node
10
+ *node - zero or more nodes named "node"
11
+ $ref - node named "ref" whose children come from a structure definition named "ref"
12
+ ?node - zero or one nodes named "node"
13
+ .class - a boolean attribute on the containing node (ie a css class)
14
+ node.class - node has the boolean attribute "attr"
15
+
16
+ # ===== TEMPLATE =====
17
+ main:
18
+ error_type
19
+ class
20
+ explanation
21
+ heuristic
22
+ backtrace
23
+ *$codeview
24
+
25
+ wrong_number_of_arguments:
26
+ $codeview
27
+ $codeview
28
+
29
+ codeview:
30
+ path
31
+ ?.emphasize
32
+ dir
33
+ file
34
+ ?line_num
35
+ code
36
+ *codeline
37
+ ?.emphasize
38
+ ?linenum
39
+ line
40
+ ?annotation
41
+
42
+ message:<
43
+ details:<
44
+ standout:<
45
+
46
+ # ===== STYLE =====
47
+
48
+ error_type {
49
+ display: block;
50
+ border-top: 2px solid white;
51
+ border-bottom: 2px solid white;
52
+ }
53
+ error_type class {
54
+ color: #fff;
55
+ border-right: 1px solid white;
56
+ }
57
+ error_type explanation message { color: #F00 }
58
+ error_type explanation details { color: #A00 }
59
+ error_type explanation standout { color: #FFF }
60
+
61
+ path { display: block; }
62
+ path.emphasize { text-decoration: underline; }
63
+ path dir { color: #088; }
64
+ path file { color: #08C; }
65
+ path line_num { color: #04C; }
66
+
67
+ # should be grayed out if not emphasize
68
+ code { display: block; }
69
+ code codeline { display: block; }
70
+ code linenum { linenum: #04C; }
71
+ code line { }
72
+ code annotation {
73
+ background-color: #F00;
74
+ color: #FFF;
75
+ text-transform: uppercase;
76
+ }
77
+
78
+
79
+ # ===== DATA =====
80
+ bt0 = backtrace[0]
81
+ bt2 = backtrace[1]
82
+ main: {
83
+ error_type: {
84
+ class: 'ArgumentError',
85
+ explanation: [
86
+ {message: 'wrong number of arguments'},
87
+ {details: [
88
+ '(sent ',
89
+ {standout: 3},
90
+ ' expected ',
91
+ {standout: 2},
92
+ ')',
93
+ ]}
94
+ ]
95
+ },
96
+ heuristic: [
97
+ {codeview: {
98
+ path: {
99
+ dir: File.dirname(bt0.path),
100
+ file: File.basename(bt0.path),
101
+ linenum: bt0.linenum,
102
+ },
103
+ code: File.read(bt0.path)[bt0.linenum, 5].map.with_index(bt0.linenum) { |line, linenum|
104
+ { emphasize: true,
105
+ linenum: linenum,
106
+ line: line,
107
+ annotation: ('Expected 2' if linenum == bt0.linenum),
108
+ }
109
+ },
110
+ }},
111
+ {codeview: {
112
+ path: {
113
+ dir: File.dirname(bt1.path),
114
+ file: File.basename(bt1.path),
115
+ linenum: bt1.linenum,
116
+ },
117
+ code: File.read(bt1.path)[bt1.linenum, 5].map.with_index(bt1.linenum) { |line, linenum|
118
+ { emphasize: true,
119
+ linenum: linenum,
120
+ line: line,
121
+ annotation: ('Sent 3' if linenum == bt1.linenum)
122
+ }
123
+ },
124
+ }},
125
+ ],
126
+ backtrace: backtrace.map { |location|
127
+ { path: {
128
+ emphasize: true,
129
+ dir: File.dirname(location.path),
130
+ file: File.basename(location.path),
131
+ linenum: location.linenum,
132
+ },
133
+ code: {
134
+ linenum: location.linenum,
135
+ line: File.read(location.path).lines[location.linenum-1],
136
+ }
137
+ }
138
+ }
139
+ }
@@ -0,0 +1,156 @@
1
+ Hypothesis: Everything can be made from the following elements and styling
2
+ stack (vertical list)
3
+ flow (horizontal list)
4
+ grid (basically a table -- overlaid stacks and flows?)
5
+ text (an element containing only text)
6
+
7
+ Shoes:
8
+ (I'm omitting the methods that seem like they manipulate styles)
9
+ http://shoesrb.com/manual/Hello.html
10
+ layout
11
+ stack
12
+ flow
13
+ window
14
+ generic
15
+ image
16
+ video
17
+ background
18
+ banner
19
+ caption
20
+ code
21
+ dialog
22
+ inscription
23
+ form
24
+ list_box
25
+ button
26
+ check
27
+ edit_box
28
+ edit_line
29
+ radio
30
+ shapes
31
+ arc
32
+ arrow
33
+ cap
34
+ line
35
+ oval
36
+ rect
37
+ shape
38
+ star
39
+ text
40
+ para
41
+ strong
42
+ title
43
+ em
44
+ link
45
+ ins
46
+ span
47
+ sub
48
+ subtitle
49
+ sup
50
+ del
51
+
52
+ HTML:
53
+ http://www.w3.org/wiki/HTML/Elements
54
+ limited to just the ones I was already aware of, or seem useful
55
+ I've rearranged them a little bit
56
+ metadata
57
+ head
58
+ title
59
+ link
60
+ meta
61
+ sections
62
+ body
63
+ section
64
+ nav
65
+ article
66
+ aside
67
+ h1 - h6
68
+ header
69
+ footer
70
+ grouping
71
+ hr
72
+ pre
73
+ blockquote
74
+ ol/ul/dl/li/dt/dd
75
+ figure
76
+ figcaption
77
+ div
78
+ main
79
+ text
80
+ p
81
+ center
82
+ a
83
+ acronym
84
+ abbr
85
+ br
86
+ cite
87
+ code
88
+ em
89
+ mark
90
+ q
91
+ span
92
+ small
93
+ spacer
94
+ strike
95
+ strong
96
+ sub/sup
97
+ time
98
+ wbr <-- line break opportunity (who knew!)
99
+ ins
100
+ del
101
+ embedded content
102
+ img
103
+ iframe
104
+ embed
105
+ object
106
+ param
107
+ video
108
+ audio
109
+ source
110
+ track
111
+ canvas
112
+ map
113
+ area
114
+ math
115
+ svg
116
+ applet
117
+ frame
118
+ frameset
119
+ noframes
120
+ bgsound
121
+ noembed
122
+ plaintext
123
+ tables
124
+ table
125
+ caption
126
+ colgroup
127
+ col
128
+ tbody
129
+ thead
130
+ tfoot
131
+ tr
132
+ td
133
+ th
134
+ forms
135
+ form
136
+ fieldset
137
+ legend
138
+ label
139
+ input
140
+ button
141
+ select
142
+ datalist
143
+ optgroup
144
+ option
145
+ textarea
146
+ keygen
147
+ output
148
+ progress
149
+ meter
150
+ interactive
151
+ details
152
+ summary
153
+ command
154
+ menu
155
+ other
156
+ script