console 0.5 → 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d6d335e8b78f82a73be6a3cf6ab279594277fe4fd492d82db5da34695643219e
4
+ data.tar.gz: 22dd7d9b66f54a1bd38e563158d5ff58148e9f744d06a4d391ef8ae01676bb9d
5
+ SHA512:
6
+ metadata.gz: 9c4947d01b98cf603d14444be28815d4e7b6d3e3b7627be3b6f1d4d4d56f97702e7b61827c7c966533d696b73b9a0138b5a74fb2388fec645b5619b2e741ad2e
7
+ data.tar.gz: 8ecfe1ee0c30bc99b2662f6095defde0e99c8594a8a49b9c513f14914b80f84c9bc7ee7e13064097ac225a2f9a7a132ebae6b8f31c610cecd4c58e4cbfb77cf7
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ dist: xenial
3
+ cache: bundler
4
+
5
+ matrix:
6
+ include:
7
+ - rvm: 2.3
8
+ - rvm: 2.4
9
+ - rvm: 2.5
10
+ - rvm: 2.6
11
+ - rvm: 2.6
12
+ env: COVERAGE=BriefSummary,Coveralls
13
+ - rvm: ruby-head
14
+ - rvm: jruby-head
15
+ - rvm: truffleruby
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in console.gemspec
6
+ gemspec
7
+
8
+ gem "pry"
@@ -0,0 +1,165 @@
1
+ # Console
2
+
3
+ Provides beautiful console logging for Ruby applications. Implements fast, buffered log output.
4
+
5
+ [![Build Status](https://travis-ci.com/socketry/console.svg)](http://travis-ci.com/socketry/console)
6
+ [![Coverage Status](https://coveralls.io/repos/socketry/console/badge.svg)](https://coveralls.io/r/socketry/console)
7
+
8
+ ## Motivation
9
+
10
+ When Ruby decided to reverse the order of exception backtraces, I finally gave up using the built in logging and decided restore sanity to the output of my programs once and for all!
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'console'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ ## Usage
25
+
26
+ As your code executes, it generates interesting events which you want to know about. The general approach is to use an `Console::Logger` which outputs text to the terminal. The text is generated by inspecting the console that occurred.
27
+
28
+ Capturing structured information allows it to be used in different ways. These events can be sent to a logger or some other system (e.g. web browser, syslog) and analysed in more detail.
29
+
30
+ ### Default Logger
31
+
32
+ Generally speaking, use `Console.logger` which is suitable for logging to the user's terminal.
33
+
34
+ ### Module Integration
35
+
36
+ ```ruby
37
+ require 'console'
38
+
39
+ # Set the log level:
40
+ Console.logger.debug!
41
+
42
+ module MyModule
43
+ extend Console
44
+
45
+ def self.test_logger
46
+ logger.debug "GOTO LINE 1."
47
+ logger.info "5 things your doctor won't tell you!"
48
+ logger.warn "Something didn't work as expected!"
49
+ logger.error "The matrix has two cats!"
50
+ end
51
+
52
+ test_logger
53
+ end
54
+ ```
55
+
56
+ ### Class Integration
57
+
58
+ ```ruby
59
+ require 'console'
60
+
61
+ # Set the log level:
62
+ Console.logger.debug!
63
+
64
+ class MyObject
65
+ include Console
66
+
67
+ def test_logger
68
+ logger.debug "GOTO LINE 1."
69
+ logger.info "5 things your doctor won't tell you!"
70
+ logger.warn "Something didn't work as expected!"
71
+ logger.error "The matrix has two cats!"
72
+ end
73
+ end
74
+
75
+ MyObject.new.test_logger
76
+ ```
77
+
78
+ ### Console Formatting
79
+
80
+ Console classes are used to wrap data which can generate structured log messages:
81
+
82
+ ```ruby
83
+ require 'console'
84
+
85
+ class MyConsole < Console::Generic
86
+ def format(output, terminal, verbose)
87
+ output.puts "My console text!"
88
+ end
89
+ end
90
+
91
+ Console.logger.info("My Console", MyConsole.new)
92
+ ```
93
+
94
+ #### Error Events
95
+
96
+ `Console::Error` represents an error and will log the message and backtrace recursively.
97
+
98
+ #### Shell Events
99
+
100
+ `Console::Shell` represents the execution of a shell command, and will log the environment, arguments and options used to execute it.
101
+
102
+ ### Multiple Loggers
103
+
104
+ ### Custom Log Levels
105
+
106
+ `Console::Filter` implements support for multiple log levels.
107
+
108
+ ```ruby
109
+ require 'console'
110
+
111
+ MyLogger = Console::Filter[noise: 0, stuff: 1, broken: 2]
112
+
113
+ logger = MyLogger.new(Console.logger, name: "Java")
114
+ logger.verbose! # log severity/name/pid etc.
115
+
116
+ logger.broken("It's so janky.")
117
+ ```
118
+
119
+ ### Multiple Outputs
120
+
121
+ ```ruby
122
+ require 'console/terminal'
123
+ require 'console/serialized/logger'
124
+ require 'console/logger'
125
+ require 'console/split'
126
+
127
+ terminal = Console::Terminal::Logger.new
128
+ file = Console::Serialized::Logger.new(File.open("/tmp/log.json", "w"))
129
+
130
+ logger = Console::Logger.new(Console::Split[terminal, file])
131
+
132
+ logger.info "I can go everywhere!"
133
+ ```
134
+
135
+ ## Contributing
136
+
137
+ 1. Fork it
138
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
139
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
140
+ 4. Push to the branch (`git push origin my-new-feature`)
141
+ 5. Create new Pull Request
142
+
143
+ ## License
144
+
145
+ Released under the MIT license.
146
+
147
+ Copyright, 2019, by [Samuel Williams](https://www.codeotaku.com).
148
+
149
+ Permission is hereby granted, free of charge, to any person obtaining a copy
150
+ of this software and associated documentation files (the "Software"), to deal
151
+ in the Software without restriction, including without limitation the rights
152
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
153
+ copies of the Software, and to permit persons to whom the Software is
154
+ furnished to do so, subject to the following conditions:
155
+
156
+ The above copyright notice and this permission notice shall be included in
157
+ all copies or substantial portions of the Software.
158
+
159
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
160
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
161
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
162
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
163
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
164
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
165
+ THE SOFTWARE.
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ task :console do
9
+ require 'pry'
10
+ require 'console'
11
+
12
+ binding.pry
13
+ end
@@ -0,0 +1,24 @@
1
+
2
+ require_relative "lib/console/version"
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "console"
6
+ spec.version = Console::VERSION
7
+ spec.authors = ["Samuel Williams"]
8
+ spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
+
10
+ spec.summary = "Beautiful logging for Ruby."
11
+ spec.homepage = "https://github.com/socketry/console"
12
+
13
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
14
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ end
16
+
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "covered"
21
+ spec.add_development_dependency "bundler"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+ end
@@ -0,0 +1,65 @@
1
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'console/logger'
22
+ require_relative 'console/terminal/logger'
23
+
24
+ module Console
25
+ class << self
26
+ attr_accessor :logger
27
+
28
+ LEVELS = {
29
+ 'debug' => Logger::DEBUG,
30
+ 'info' => Logger::INFO,
31
+ }
32
+
33
+ # Set the default log level based on `$DEBUG` and `$VERBOSE`.
34
+ # You can also specify CONSOLE_LOG_LEVEL=debug or CONSOLE_LOG_LEVEL=info in environment.
35
+ def default_log_level(env = ENV)
36
+ if level = env['CONSOLE_LOG_LEVEL']
37
+ LEVELS[level] || Logger.warn
38
+ elsif $DEBUG
39
+ Logger::DEBUG
40
+ elsif $VERBOSE
41
+ Logger::INFO
42
+ else
43
+ Logger::WARN
44
+ end
45
+ end
46
+ end
47
+
48
+ # Create the logger instance:
49
+ @logger = Logger.new(
50
+ Terminal::Logger.new($stderr),
51
+ level: self.default_log_level,
52
+ )
53
+
54
+ def logger= logger
55
+ @logger = logger
56
+ end
57
+
58
+ def logger
59
+ @logger || Console.logger
60
+ end
61
+
62
+ def self.extended(klass)
63
+ klass.instance_variable_set(:@logger, nil)
64
+ end
65
+ end
@@ -0,0 +1,40 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'stringio'
22
+
23
+ module Console
24
+ class Buffer < StringIO
25
+ def initialize(prefix = nil)
26
+ @prefix = prefix
27
+
28
+ super()
29
+ end
30
+
31
+ def puts(*args, prefix: @prefix)
32
+ args.each do |arg|
33
+ self.write(prefix) if prefix
34
+ super(arg)
35
+ end
36
+ end
37
+
38
+ alias << puts
39
+ end
40
+ end
@@ -0,0 +1,66 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'filter'
22
+
23
+ module Console
24
+ class Capture
25
+ def initialize
26
+ @events = []
27
+ end
28
+
29
+ attr :events
30
+
31
+ def last
32
+ @events.last
33
+ end
34
+
35
+ def verbose!(value = true)
36
+ end
37
+
38
+ def call(subject = nil, *arguments, severity: UNKNOWN, **options, &block)
39
+ message = {
40
+ time: Time.now.iso8601,
41
+ severity: severity,
42
+ **options,
43
+ }
44
+
45
+ if subject
46
+ message[:subject] = subject
47
+ end
48
+
49
+ if arguments.any?
50
+ message[:arguments] = arguments
51
+ end
52
+
53
+ if block_given?
54
+ if block.arity.zero?
55
+ message[:message] = yield
56
+ else
57
+ buffer = StringIO.new
58
+ yield buffer
59
+ message[:message] = buffer.string
60
+ end
61
+ end
62
+
63
+ @events << message
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,76 @@
1
+ # Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'generic'
22
+
23
+ module Console
24
+ class Error < Generic
25
+ def self.current_working_directory
26
+ Dir.getwd
27
+ rescue # e.g. Errno::EMFILE
28
+ nil
29
+ end
30
+
31
+ def self.for(exception)
32
+ self.new(exception, self.current_working_directory)
33
+ end
34
+
35
+ def initialize(exception, root = nil)
36
+ @exception = exception
37
+ @root = root
38
+ end
39
+
40
+ attr :exception
41
+ attr :root
42
+
43
+ def self.register(terminal)
44
+ terminal[:exception_title] ||= terminal.style(:red, nil, :bold)
45
+ terminal[:exception_detail] ||= terminal.style(:yellow)
46
+ terminal[:exception_backtrace] ||= terminal.style(:red)
47
+ end
48
+
49
+ def format(output, terminal, verbose)
50
+ format_exception(@exception, nil, output, terminal, verbose)
51
+ end
52
+
53
+ def format_exception(exception, prefix = nil, output, terminal, verbose)
54
+ lines = exception.message.lines.map(&:chomp)
55
+
56
+ output.puts " #{prefix}#{terminal[:exception_title]}#{exception.class}#{terminal.reset}: #{lines.shift}"
57
+
58
+ lines.each do |line|
59
+ output.puts " #{terminal[:exception_detail]}#{line}#{terminal.reset}"
60
+ end
61
+
62
+ exception.backtrace&.each_with_index do |line, index|
63
+ path, offset, message = line.split(":")
64
+
65
+ # Make the path a bit more readable
66
+ path.gsub!(/^#{@root}\//, "./") if @root
67
+
68
+ output.puts " #{index == 0 ? "→" : " "} #{terminal[:exception_backtrace]}#{path}:#{offset}#{terminal.reset} #{message}"
69
+ end
70
+
71
+ if exception.cause and verbose
72
+ format_exception(exception.cause, "Caused by ", output, terminal)
73
+ end
74
+ end
75
+ end
76
+ end