what_weve_got_here_is_an_error_to_communicate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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