pax_global_header00006660000000000000000000000064137474613660014533gustar00rootroot0000000000000052 comment=b292dfbbbe2eb8fbe6cbc3a7a10160f4486fbde8 ruby-console-1.10.1/000077500000000000000000000000001374746136600142345ustar00rootroot00000000000000ruby-console-1.10.1/.editorconfig000066400000000000000000000000641374746136600167110ustar00rootroot00000000000000root = true [*] indent_style = tab indent_size = 2 ruby-console-1.10.1/.github/000077500000000000000000000000001374746136600155745ustar00rootroot00000000000000ruby-console-1.10.1/.github/workflows/000077500000000000000000000000001374746136600176315ustar00rootroot00000000000000ruby-console-1.10.1/.github/workflows/development.yml000066400000000000000000000016341374746136600227020ustar00rootroot00000000000000name: Development on: [push, pull_request] jobs: test: runs-on: ${{matrix.os}}-latest continue-on-error: ${{matrix.experimental}} strategy: matrix: os: - ubuntu - macos ruby: - 2.5 - 2.6 - 2.7 experimental: [false] env: [""] include: - os: ubuntu ruby: truffleruby experimental: true - os: ubuntu ruby: jruby experimental: true - os: ubuntu ruby: head experimental: true steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} - name: Install dependencies run: ${{matrix.env}} bundle install - name: Run tests timeout-minutes: 5 run: ${{matrix.env}} bundle exec rspec ruby-console-1.10.1/.gitignore000066400000000000000000000001611374746136600162220ustar00rootroot00000000000000/.bundle/ /.yardoc /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ /gems.locked .rspec_status .covered.db ruby-console-1.10.1/.rspec000066400000000000000000000001001374746136600153400ustar00rootroot00000000000000--format documentation --color --require spec_helper --warnings ruby-console-1.10.1/README.md000066400000000000000000000037621374746136600155230ustar00rootroot00000000000000# Console Provides beautiful console logging for Ruby applications. Implements fast, buffered log output. [![Development Status](https://github.com/socketry/console/workflows/Development/badge.svg)](https://github.com/socketry/console/actions?workflow=Development) ## Features - Thread safe global logger with per-fiber context. - Carry along context with nested loggers. - Enable/disable log levels per-class. - Detailed logging of exceptions. - Beautiful logging to the terminal or structured logging using JSON. ## Usage Please see the [project documentation](https://socketry.github.io/console). ## Contributing We welcome contributions to this project. 1. Fork it. 2. Create your feature branch (`git checkout -b my-new-feature`). 3. Commit your changes (`git commit -am 'Add some feature'`). 4. Push to the branch (`git push origin my-new-feature`). 5. Create new Pull Request. ## License Released under the MIT license. Copyright, 2019, by [Samuel Williams](https://www.codeotaku.com). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ruby-console-1.10.1/bake.rb000066400000000000000000000002701374746136600154620ustar00rootroot00000000000000 def sample_progress_bar require_relative 'lib/console' measure = Console.logger.measure("Progress Bar", 10000) 10000.times do |i| sleep 0.001 measure.increment end end ruby-console-1.10.1/bake/000077500000000000000000000000001374746136600151365ustar00rootroot00000000000000ruby-console-1.10.1/bake/console.rb000066400000000000000000000004231374746136600171240ustar00rootroot00000000000000# frozen_string_literal: true # Increase the verbosity of the logger to info. def info require_relative '../lib/console' Console.logger.info! end # Increase the verbosity of the logger to debug. def debug require_relative '../lib/console' Console.logger.debug! end ruby-console-1.10.1/benchmark/000077500000000000000000000000001374746136600161665ustar00rootroot00000000000000ruby-console-1.10.1/benchmark/fiber_vs_thread.rb000077500000000000000000000042041374746136600216440ustar00rootroot00000000000000#!/usr/bin/env ruby # frozen_string_literal: true # Copyright, 2020, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'benchmark/ips' require 'fiber' # GC.disable puts RUBY_VERSION class Fiber attr_accessor :my_local end class MyObject attr_accessor :my_local end Benchmark.ips do |benchmark| benchmark.report("Hash\#[]=") do |count| hash = Hash.new while count > 0 hash[:my_local] = count count -= 1 end end benchmark.report("Thread\#[]=") do |count| thread = Thread.current while count > 0 thread[:my_local] = count count -= 1 end end benchmark.report("Thread\#thread_variable_set") do |count| thread = Thread.current while count > 0 thread.thread_variable_set(:my_local, count) count -= 1 end end benchmark.report("Fiber\#my_local=") do |count| fiber = Fiber.current while count > 0 fiber.my_local = count count -= 1 end end benchmark.report("MyObject\#my_local=") do |count| object = MyObject.new while count > 0 object.my_local = count count -= 1 end end benchmark.compare! end ruby-console-1.10.1/console.gemspec000066400000000000000000000012541374746136600172450ustar00rootroot00000000000000 require_relative "lib/console/version" Gem::Specification.new do |spec| spec.name = "console" spec.version = Console::VERSION spec.summary = "Beautiful logging for Ruby." spec.authors = ["Samuel Williams"] spec.license = "MIT" spec.homepage = "https://github.com/socketry/console" spec.files = Dir.glob('{bake,lib}/**/*', File::FNM_DOTMATCH, base: __dir__) spec.required_ruby_version = ">= 2.5" spec.add_dependency "fiber-local" spec.add_development_dependency "bake" spec.add_development_dependency "bundler" spec.add_development_dependency "covered" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "rspec", "~> 3.0" end ruby-console-1.10.1/gems.rb000066400000000000000000000003111374746136600155070ustar00rootroot00000000000000source "https://rubygems.org" # Specify your gem's dependencies in console.gemspec gemspec group :maintenance, optional: true do gem "bake-bundler" gem "bake-modernize" gem "utopia-project" end ruby-console-1.10.1/guides/000077500000000000000000000000001374746136600155145ustar00rootroot00000000000000ruby-console-1.10.1/guides/getting-started/000077500000000000000000000000001374746136600206215ustar00rootroot00000000000000ruby-console-1.10.1/guides/getting-started/README.md000066400000000000000000000110751374746136600221040ustar00rootroot00000000000000# Getting Started This guide explains how to use `console` for logging. ## Installation Add the gem to your project: ~~~ bash $ bundle add console ~~~ ## Core Concepts `console` has several core concepts: - A log message which consists of a set of arguments and options, which includes a timestamp, severity, and other structured data. - A {ruby Console::Logger} instance which is the main entry point for logging for a specific system and writes data to a given output formatter. - An output instance such as {ruby Console::XTerm}, {ruby Console::Serialized::Logger} which formats these log messages and writes them to a specific output device. - An event instance, such as {ruby Console::Event::Progress} or {ruby Console::Event::Spawn} which represents a structured event within a system, which can be formatted in a specific way. ## Basic Logging Out of the box, {ruby Console.logger} is a globally shared logger that outputs to the current terminal via `stderr`. ~~~ ruby require 'console' Console.logger.info("Hello World") ~~~
  0.0s     info: Hello World [pid=219113] [2020-08-08 12:21:26 +1200]
The method name `info` indicates the severity level of the log message. You can filter out severity levels, and by default, `debug` messages are filtered out. Here are some examples of the different log levels: ~~~ ruby require 'console' Console.logger.debug("The input voltage has stabilized.") Console.logger.info("Making a request to the machine.") Console.logger.warn("The machine has detected a temperature anomaly.") Console.logger.error("The machine was unable to complete the request!") Console.logger.fatal("Depressurisation detected, evacuate the area!") ~~~ From the terminal, you can control the log level using the `CONSOLE_LEVEL` environment variable. To log all messages including `debug`: ~~~ bash $ CONSOLE_LEVEL=debug ./machine ~~~ Alternatively to restrict log messages to warnings and above: ~~~ bash $ CONSOLE_LEVEL=warn ./machine ~~~ If otherwise unspecified, Ruby's standard `$DEBUG` and `$VERBOSE` global variables will be checked and adjust the log level appropriately. ## Subject Logging The first argument to the log statement becomes the implicit subject of the log message. ~~~ ruby require 'console' class Machine include Console def initialize(voltage) @voltage = voltage.floor logger.info(self, "The input voltage has stabilized.") end end Machine.new(5.5) ~~~ The given subject, in this case `self`, is used on the first line, along with associated metadata, while the message itself appears on subsequent lines:
  0.0s     info: Machine [oid=0x3c] [pid=219041] [2020-08-08 12:17:33 +1200]
               | The input voltage has stabilized.
If you want to disable log messages which come from this particular class, you can execute your command: ~~~ bash $ CONSOLE_FATAL=Machine ./machine ~~~ This will prevent any log message which has a subject of class `Machine` from logging messages of a severity less than `fatal`. ## Exception Logging If your code has an unhandled exception, you may wish to log it. In order to log a full backtrace, you must log the subject followed by the exception. ~~~ ruby require 'console' class Cache include Console def initialize @entries = {} end def fetch(key) @entries.fetch(key) rescue => error logger.failure(self, error) end end Cache.new.fetch(:foo) ~~~ This will produce the following output:
  0.0s    fatal: Cache [oid=0x3c] [pid=220776] [2020-08-08 14:10:00 +1200]
               |   KeyError: key not found: :foo
               |   → cache.rb:11 in 'fetch'
               |     cache.rb:11 in 'fetch'
               |     cache.rb:17 in '<main>'
## Program Structure Generally, all programs should use the global `Console.logger` instance. The per-class `include Console` allows you to All programs should generally use the global `Console.logger` instance. Generally, individual classes should not be catching and logging exceptions. Generally, individual classes should not be catching and logging exceptions. It makes for simpler code if this is handled in a few places near the top of your program. Exceptions should collect enough information such that logging them produces a detailed backtrace leading to the failure.ruby-console-1.10.1/guides/getting-started/old.md000066400000000000000000000106351374746136600217260ustar00rootroot00000000000000## Motivation 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\! ## Installation Add this line to your application's Gemfile: ``` ruby gem 'console' ``` And then execute: $ bundle ## Usage 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. 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. ### Default Logger Generally speaking, use `Console.logger` which is suitable for logging to the user's terminal. ### Environment Variables #### `CONSOLE_LEVEL=debug` Control the default logger level. You can set it to any of the supported log levels: `debug`, `info`, `warn`, `error`, `fatal`. #### `CONSOLE_DEBUG=MyClass,MyModule::MyClass` Enable debug logging for the specified class names. You can specify one or more class names which will be resolved at runtime. ### Module Integration ``` ruby require 'console' # Set the log level: Console.logger.debug! module MyModule extend Console def self.test_logger logger.debug "GOTO LINE 1." logger.info "5 things your doctor won't tell you!" logger.warn "Something didn't work as expected!" logger.error "The matrix has two cats!" end test_logger end ``` ### Class Integration ``` ruby require 'console' # Set the log level: Console.logger.debug! class MyObject include Console def test_logger logger.debug "GOTO LINE 1." logger.info "5 things your doctor won't tell you!" logger.warn "Something didn't work as expected!" logger.error "The matrix has two cats!" end end MyObject.new.test_logger ``` ### Subject Logging The first argument to the log method is the subject. ``` ruby class Thing def call Console.logger.info(self) {"Something is going on"} end end ``` Using this approach, you can turn on and off specific subjects by using the class name: ``` ruby $ CONSOLE_DEBUG=Thing ./script.rb ``` This will conditionally enable all log statements which have a subject of class `Thing`. ### Console Formatting Console classes are used to wrap data which can generate structured log messages: ``` ruby require 'console' class MyConsole < Console::Generic def format(output, terminal, verbose) output.puts "My console text!" end end Console.logger.info("My Console", MyConsole.new) ``` #### Failure Events `Console::Event::Failure` represents an exception and will log the message and backtrace recursively. #### Spawn Events `Console::Event::Spawn` represents the execution of a command, and will log the environment, arguments and options used to execute it. ### Custom Log Levels `Console::Filter` implements support for multiple log levels. ``` ruby require 'console' MyLogger = Console::Filter[noise: 0, stuff: 1, broken: 2] # verbose: true - log severity/name/pid etc. logger = MyLogger.new(Console.logger, name: "Java", verbose: true) logger.broken("It's so janky.") ``` ### Multiple Outputs Use `Console::Split` to log to multiple destinations. ``` ruby require 'console/terminal' require 'console/serialized/logger' require 'console/logger' require 'console/split' terminal = Console::Terminal::Logger.new file = Console::Serialized::Logger.new(File.open("log.json", "a")) logger = Console::Logger.new(Console::Split[terminal, file]) logger.info "I can go everywhere!" ``` ### Custom Logger Output `Console::Logger` provides a default interface which is a drop in replacemnet for `Logger` and other similar implementations. The only method required for output is `#call(*arguments, **options, &block)`. ``` ruby require 'console/logger' output = proc do |*arguments, **options, &block| puts "arguments: #{arguments.inspect} options: #{options.inspect} block: #{block.call}" end logger = Console::Logger.new(output) logger.info("Hello World!", meta: "data") {"block"} # => arguments: ["Hello World!"] options: {:severity=>:info, :meta=>"data"} block: block ``` ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request ruby-console-1.10.1/lib/000077500000000000000000000000001374746136600150025ustar00rootroot00000000000000ruby-console-1.10.1/lib/console.rb000066400000000000000000000027251374746136600167770ustar00rootroot00000000000000# frozen_string_literal: true # # Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'console/logger' module Console def self.logger Logger.instance end def self.logger= instance Logger.instance= instance end def logger= logger @logger = logger end def logger @logger || Logger.instance end def self.extended(klass) klass.instance_variable_set(:@logger, nil) end end ruby-console-1.10.1/lib/console/000077500000000000000000000000001374746136600164445ustar00rootroot00000000000000ruby-console-1.10.1/lib/console/buffer.rb000066400000000000000000000026061374746136600202460ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'stringio' module Console class Buffer < StringIO def initialize(prefix = nil) @prefix = prefix super() end def puts(*args, prefix: @prefix) args.each do |arg| self.write(prefix) if prefix super(arg) end end alias << puts end end ruby-console-1.10.1/lib/console/capture.rb000066400000000000000000000036231374746136600204400ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'filter' module Console # A general sink which captures all events into a buffer. class Capture def initialize @buffer = [] end attr :buffer def last @buffer.last end def clear @buffer.clear end def verbose!(value = true) end def call(subject = nil, *arguments, severity: UNKNOWN, **options, &block) message = { time: ::Time.now.iso8601, severity: severity, **options, } if subject message[:subject] = subject end if arguments.any? message[:arguments] = arguments end if block_given? if block.arity.zero? message[:message] = yield else buffer = StringIO.new yield buffer message[:message] = buffer.string end end @buffer << message end end end ruby-console-1.10.1/lib/console/event.rb000066400000000000000000000023571374746136600201210ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'event/spawn' require_relative 'event/failure' require_relative 'event/metric' require_relative 'event/progress' ruby-console-1.10.1/lib/console/event/000077500000000000000000000000001374746136600175655ustar00rootroot00000000000000ruby-console-1.10.1/lib/console/event/failure.rb000066400000000000000000000054021374746136600215420ustar00rootroot00000000000000# frozen_string_literals: true # # Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'generic' module Console module Event class Failure < Generic def self.current_working_directory Dir.getwd rescue # e.g. Errno::EMFILE nil end def self.for(exception) self.new(exception, self.current_working_directory) end def initialize(exception, root = nil) @exception = exception @root = root end attr :exception attr :root def self.register(terminal) terminal[:exception_title] ||= terminal.style(:red, nil, :bold) terminal[:exception_detail] ||= terminal.style(:yellow) terminal[:exception_backtrace] ||= terminal.style(:red) end def to_h {exception: @exception, root: @root} end def format(output, terminal, verbose) format_exception(@exception, nil, output, terminal, verbose) end def format_exception(exception, prefix, output, terminal, verbose) lines = exception.message.lines.map(&:chomp) output.puts " #{prefix}#{terminal[:exception_title]}#{exception.class}#{terminal.reset}: #{lines.shift}" lines.each do |line| output.puts " #{terminal[:exception_detail]}#{line}#{terminal.reset}" end exception.backtrace&.each_with_index do |line, index| path, offset, message = line.split(":") # Make the path a bit more readable path.gsub!(/^#{@root}\//, "./") if @root output.puts " #{index == 0 ? "→" : " "} #{terminal[:exception_backtrace]}#{path}:#{offset}#{terminal.reset} #{message}" end if exception.cause format_exception(exception.cause, "Caused by ", output, terminal, verbose) end end end end end ruby-console-1.10.1/lib/console/event/generic.rb000066400000000000000000000024641374746136600215340ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. module Console module Event class Generic def self.register(terminal) end def to_h end def as_json to_h end def format(buffer, terminal) end end end end ruby-console-1.10.1/lib/console/event/metric.rb000066400000000000000000000031361374746136600214000ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'generic' module Console module Event class Metric < Generic def self.[](**parameters) parameters.map(&self.method(:new)) end def initialize(name, value, **tags) @name = name @value = value @tags = tags end attr :name attr :value attr :tags def to_h {name: @name, value: @value, tags: @tags} end def format(output, terminal, verbose) output.puts "#{@name}=#{@value} #{@tags.inspect}" end end end end ruby-console-1.10.1/lib/console/event/progress.rb000066400000000000000000000042061374746136600217600ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'generic' module Console module Event class Progress < Generic BLOCK = [ " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█", ] def initialize(current, total) @current = current @total = total end attr :current attr :total def value @current.to_f / @total.to_f end def bar(value = self.value, width = 70) blocks = width * value full_blocks = blocks.floor partial_block = ((blocks - full_blocks) * BLOCK.size).floor if partial_block.zero? BLOCK.last * full_blocks else "#{BLOCK.last * full_blocks}#{BLOCK[partial_block]}" end.ljust(width) end def self.register(terminal) terminal[:progress_bar] ||= terminal.style(:blue, :white) end def to_h {current: @current, total: @total} end def format(output, terminal, verbose) output.puts "#{terminal[:progress_bar]}#{self.bar}#{terminal.reset} #{sprintf('%6.2f', self.value * 100)}%" end end end end ruby-console-1.10.1/lib/console/event/spawn.rb000066400000000000000000000045021374746136600212430ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'generic' module Console module Event class Spawn < Generic def self.for(*arguments, **options) # Extract out the command environment: if arguments.first.is_a?(Hash) self.new(*arguments, **options) else self.new(nil, arguments, **options) end end def initialize(environment, *arguments, **options) @environment = environment @arguments = arguments @options = options end attr :environment attr :arguments attr :options def chdir_string(options) if options and chdir = options[:chdir] " in #{chdir}" end end def self.register(terminal) terminal[:shell_command] ||= terminal.style(:blue, nil, :bold) end def to_h {environment: @environment, arguments: @arguments, options: @options} end def format(output, terminal, verbose) arguments = @arguments.flatten.collect(&:to_s) output.puts " #{terminal[:shell_command]}#{arguments.join(' ')}#{terminal.reset}#{chdir_string(options)}" if verbose and @environment @environment.each do |key, value| output.puts " export #{key}=#{value}" end end end end end # Deprecated. Shell = Event::Spawn end ruby-console-1.10.1/lib/console/filter.rb000066400000000000000000000073041374746136600202620ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'buffer' module Console UNKNOWN = 'unknown' class Filter def self.[] **levels klass = Class.new(self) klass.instance_exec do const_set(:LEVELS, levels) const_set(:MINIMUM_LEVEL, levels.values.min) const_set(:MAXIMUM_LEVEL, levels.values.max) levels.each do |name, level| const_set(name.to_s.upcase, level) define_method(name) do |subject = nil, *arguments, **options, &block| if self.enabled?(subject, level) self.call(subject, *arguments, severity: name, **options, **@options, &block) end end define_method("#{name}!") do @level = level end define_method("#{name}?") do @level <= level end end end return klass end def initialize(output, verbose: true, level: self.class::DEFAULT_LEVEL, enabled: nil, **options) @output = output @verbose = verbose @level = level @subjects = {} @options = options if enabled enabled.each{|name| enable(name)} end end def with(level: @level, verbose: @verbose, **options) dup.tap do |logger| logger.level = level logger.verbose! if verbose logger.options = @options.merge(options) end end attr_accessor :output attr :verbose attr :level attr :subjects attr_accessor :options def level= level if level.is_a? Symbol @level = self.class::LEVELS[level] else @level = level end end def verbose!(value = true) @verbose = value @output.verbose!(value) end def off! @level = self.class::MAXIMUM_LEVEL + 1 end def all! @level = -1 end # You can enable and disable logging for classes. This function checks if logging for a given subject is enabled. # @param subject [Object] the subject to check. def enabled?(subject, level = self.class::MINIMUM_LEVEL) if specific_level = @subjects[subject.class] return level >= specific_level end if level >= @level return true end end # Enable specific log level for the given class. # @param name [String, Class] The class to enable. def enable(subject, level = self.class::MINIMUM_LEVEL) unless subject.is_a?(Class) subject = subject.class end @subjects[subject] = level end # Disable specific logging for the specific class. # @param name [String, Class] The class to disable. def disable(subject) unless subject.is_a? Class subject = subject.class end @subjects.delete(subject) end def call(*arguments, **options, &block) @output.call(*arguments, **options, &block) end end end ruby-console-1.10.1/lib/console/logger.rb000066400000000000000000000052771374746136600202630ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'filter' require_relative 'progress' require_relative 'resolver' require_relative 'terminal/logger' require 'fiber/local' module Console class Logger < Filter[debug: 0, info: 1, warn: 2, error: 3, fatal: 4] extend Fiber::Local # Set the default log level based on `$DEBUG` and `$VERBOSE`. # You can also specify CONSOLE_LEVEL=debug or CONSOLE_LEVEL=info in environment. # https://mislav.net/2011/06/ruby-verbose-mode/ has more details about how it all fits together. def self.default_log_level(env = ENV) if level = (env['CONSOLE_LEVEL'] || env['CONSOLE_LOG_LEVEL']) LEVELS[level.to_sym] || level.to_i elsif $DEBUG DEBUG elsif $VERBOSE.nil? WARN else INFO end end # Controls verbose output using `$VERBOSE`. def self.verbose?(env = ENV) !$VERBOSE.nil? || env['CONSOLE_VERBOSE'] end def self.default_logger(output, verbose: self.verbose?, level: self.default_log_level) terminal = Terminal::Logger.new(output, verbose: verbose) logger = self.new(terminal, verbose: verbose, level: level) resolver = Resolver.default_resolver(logger) return logger end def self.local self.default_logger($stderr) end DEFAULT_LEVEL = 1 def initialize(output, **options) super(output, **options) end def progress(subject, total, **options) Progress.new(self, subject, total, **options) end # @deprecated Please use {progress}. alias measure progress def failure(subject, exception, *arguments, &block) fatal(subject, *arguments, Event::Failure.new(exception), &block) end end end ruby-console-1.10.1/lib/console/progress.rb000066400000000000000000000064071374746136600206440ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'event/progress' module Console class Progress def self.now Process.clock_gettime(Process::CLOCK_MONOTONIC) end def initialize(output, subject, total = 0, minimum_output_duration: 1.0) @output = output @subject = subject @start_time = Progress.now @last_output_time = nil @minimum_output_duration = 0.1 @current = 0 @total = total end attr :subject attr :current attr :total def duration Progress.now - @start_time end def progress @current.to_f / @total.to_f end def remaining @total - @current end def average_duration if @current > 0 duration / @current end end def estimated_remaining_time if average_duration = self.average_duration average_duration * remaining end end def increment(amount = 1) @current += amount if output? @output.info(@subject, self) {Event::Progress.new(@current, @total)} @last_output_time = Progress.now end return self end def resize(total) @total = total @output.info(@subject, self) {Event::Progress.new(@current, @total)} @last_output_time = Progress.now return self end def mark(*arguments) @output.info(@subject, *arguments) end def to_s if estimated_remaining_time = self.estimated_remaining_time "#{@current}/#{@total} completed in #{formatted_duration(self.duration)}, #{formatted_duration(estimated_remaining_time)} remaining." else "#{@current}/#{@total} completed, waiting for estimate..." end end private def duration_since_last_output if @last_output_time Progress.now - @last_output_time end end def output? if duration = duration_since_last_output return duration > @minimum_output_duration else return true end end def formatted_duration(duration) if duration < 60.0 return "#{duration.round(2)}s" end duration /= 60.0 if duration < 60.0 return "#{duration.round}m" end duration /= 60.0 if duration < 60.0 return "#{duration.round(1)}h" end duration /= 24.0 return "#{duration.round(1)}d" end end end ruby-console-1.10.1/lib/console/resolver.rb000066400000000000000000000057001374746136600206340ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'filter' module Console class Resolver # You can change the log level for different classes using CONSOLE_ env vars. # # e.g. `CONSOLE_WARN=Acorn,Banana CONSOLE_DEBUG=Cat` will set the log level for the classes Acorn and Banana to `warn` and Cat to `debug`. This overrides the default log level. # # @parameter logger [Logger] A logger instance to set the logging levels on. # @parameter env [Hash] The environment to read levels from. # # @returns [Nil] If there were no custom logging levels specified in the environment. # @returns [Resolver] If there were custom logging levels, then the created resolver is returned. def self.default_resolver(logger, env = ENV) # Find all CONSOLE_ variables from environment: levels = Logger::LEVELS .map{|label, level| [level, env["CONSOLE_#{label.upcase}"]&.split(',')]} .to_h .compact # If we have any levels, then create a class resolver, and each time a class is resolved, set the log level for that class to the specified level: if levels.any? resolver = Resolver.new levels.each do |level, names| resolver.bind(names) do |klass| logger.enable(klass, level) end end return resolver end end def initialize @names = {} @trace_point = TracePoint.new(:class, &self.method(:resolve)) end def bind(names, &block) names.each do |name| if klass = Object.const_get(name) rescue nil yield klass else @names[name] = block end end if @names.any? @trace_point.enable else @trace_point.disable end end def waiting? @trace_point.enabled? end def resolve(trace_point) if block = @names.delete(trace_point.self.to_s) block.call(trace_point.self) end if @names.empty? @trace_point.disable end end end end ruby-console-1.10.1/lib/console/serialized/000077500000000000000000000000001374746136600205775ustar00rootroot00000000000000ruby-console-1.10.1/lib/console/serialized/logger.rb000066400000000000000000000041551374746136600224100ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative '../buffer' require_relative '../filter' require 'time' require 'json' module Console module Serialized class Logger def initialize(io = $stderr, format: JSON) @io = io @start = Time.now @format = format end attr :io attr :start attr :format def verbose!(value = true) end def call(subject = nil, *arguments, severity: UNKNOWN, **options, &block) record = { time: Time.now.iso8601, severity: severity, class: subject.class, oid: subject.object_id, pid: Process.pid, } if subject record[:subject] = subject end if arguments.any? record[:arguments] = arguments end if options.any? record[:options] = options end if block_given? if block.arity.zero? record[:message] = yield else buffer = StringIO.new yield buffer record[:message] = buffer.string end end @io.puts(@format.dump(record)) end end end end ruby-console-1.10.1/lib/console/split.rb000066400000000000000000000030021374746136600201170ustar00rootroot00000000000000 # Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. module Console class Split def self.[] *outputs self.new(outputs) end def initialize(outputs) @outputs = outputs end def verbose!(value = true) @outputs.each{|output| output.verbose!(value)} end def call(level, subject = nil, *arguments, **options, &block) @outputs.each do |output| output.call(level, subject, *arguments, **options, &block) end end end end ruby-console-1.10.1/lib/console/terminal.rb000066400000000000000000000022201374746136600206000ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative 'terminal/logger' ruby-console-1.10.1/lib/console/terminal/000077500000000000000000000000001374746136600202575ustar00rootroot00000000000000ruby-console-1.10.1/lib/console/terminal/logger.rb000066400000000000000000000132121374746136600220620ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require_relative '../buffer' require_relative '../event' require_relative 'text' require_relative 'xterm' require 'json' module Console module Terminal # This, and all related methods, is considered private. CONSOLE_START_AT = 'CONSOLE_START_AT' # Exports CONSOLE_START which can be used to synchronize the start times of all child processes when they log using delta time. def self.start_at!(environment = ENV) if time_string = environment[CONSOLE_START_AT] start_at = Time.parse(time_string) rescue nil end unless start_at start_at = Time.now environment[CONSOLE_START_AT] = start_at.to_s end return start_at end def self.for(io) if io.isatty XTerm.new(io) else Text.new(io) end end class Logger def initialize(io = $stderr, verbose: nil, start_at: Terminal.start_at!, **options) @io = io @start_at = start_at @terminal = Terminal.for(io) if verbose.nil? @verbose = !@terminal.colors? else @verbose = verbose end @terminal[:logger_prefix] ||= @terminal.style(nil, nil, nil) @terminal[:logger_suffix] ||= @terminal.style(:white, nil, :faint) @terminal[:subject] ||= @terminal.style(nil, nil, :bold) @terminal[:debug] = @terminal.style(:cyan) @terminal[:info] = @terminal.style(:green) @terminal[:warn] = @terminal.style(:yellow) @terminal[:error] = @terminal.style(:red) @terminal[:fatal] = @terminal[:error] self.register_defaults(@terminal) end attr :io attr_accessor :verbose attr :start attr :terminal def verbose!(value = true) @verbose = value end def register_defaults(terminal) Event.constants.each do |constant| klass = Event.const_get(constant) klass.register(terminal) end end UNKNOWN = 'unknown' def call(subject = nil, *arguments, name: nil, severity: UNKNOWN, **options, &block) prefix = build_prefix(name || severity.to_s) indent = " " * prefix.size buffer = Buffer.new("#{indent}| ") if subject format_subject(severity, prefix, subject, buffer) end if options&.any? format_options(options, buffer) end arguments.each do |argument| format_argument(argument, buffer) end if block_given? if block.arity.zero? format_argument(yield, buffer) else yield(buffer, @terminal) end end @io.write buffer.string end protected def format_options(options, output) format_value(options.to_json, output) end def format_argument(argument, output) case argument when Exception Event::Failure.new(argument).format(output, @terminal, @verbose) when Event::Generic argument.format(output, @terminal, @verbose) else format_value(argument, output) end end def format_subject(severity, prefix, subject, buffer) if subject.is_a?(String) format_string_subject(severity, prefix, subject, buffer) elsif subject.is_a?(Module) format_string_subject(severity, prefix, subject.to_s, buffer) else format_object_subject(severity, prefix, subject, buffer) end end def format_object_subject(severity, prefix, subject, output) prefix_style = @terminal[severity] if @verbose suffix = " #{@terminal[:logger_suffix]}[oid=0x#{subject.object_id.to_s(16)}] [pid=#{Process.pid}] [#{Time.now}]#{@terminal.reset}" end prefix = "#{prefix_style}#{prefix}:#{@terminal.reset} " output.puts "#{@terminal[:subject]}#{subject.class}#{@terminal.reset}#{suffix}", prefix: prefix end def format_string_subject(severity, prefix, subject, output) prefix_style = @terminal[severity] if @verbose suffix = " #{@terminal[:logger_suffix]}[pid=#{Process.pid}] [#{Time.now}]#{@terminal.reset}" end prefix = "#{prefix_style}#{prefix}:#{@terminal.reset} " output.puts "#{@terminal[:subject]}#{subject}#{@terminal.reset}#{suffix}", prefix: prefix end def format_value(value, output) string = value.to_s string.each_line do |line| output.puts "#{line}" end end def time_offset_prefix offset = Time.now - @start_at minutes = (offset/60).floor seconds = (offset - (minutes*60)) if minutes > 0 "#{minutes}m#{seconds.floor}s" else "#{seconds.round(2)}s" end.rjust(6) end def build_prefix(name) if @verbose "#{time_offset_prefix} #{name.rjust(8)}" else time_offset_prefix end end end end end ruby-console-1.10.1/lib/console/terminal/text.rb000066400000000000000000000052151374746136600215730ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'io/console' module Console # Styled terminal output. module Terminal class Text def initialize(output) @output = output @styles = {reset: self.reset} end def [] key @styles[key] end def []= key, value @styles[key] = value end def colors? false end def style(foreground, background = nil, *attributes) end def reset end def write(*arguments, style: nil) if style and prefix = self[style] @output.write(prefix) @output.write(*arguments) @output.write(self.reset) else @output.write(*arguments) end end def puts(*arguments, style: nil) if style and prefix = self[style] @output.write(prefix) @output.puts(*arguments) @output.write(self.reset) else @output.puts(*arguments) end end # Print out the given arguments. # When the argument is a symbol, look up the style and inject it into the output stream. # When the argument is a proc/lambda, call it with self as the argument. # When the argument is anything else, write it directly to the output. def print(*arguments) arguments.each do |argument| case argument when Symbol @output.write(self[argument]) when Proc argument.call(self) else @output.write(argument) end end end # Print out the arguments as per {#print}, followed by the reset sequence and a newline. def print_line(*arguments) print(*arguments) @output.puts(self.reset) end end end end ruby-console-1.10.1/lib/console/terminal/xterm.rb000066400000000000000000000040411374746136600217420ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'io/console' require_relative 'text' module Console # Styled terminal output. module Terminal class XTerm < Text COLORS = { black: 0, red: 1, green: 2, yellow: 3, blue: 4, magenta: 5, cyan: 6, white: 7, default: 9, } ATTRIBUTES = { normal: 0, bold: 1, bright: 1, faint: 2, italic: 3, underline: 4, blink: 5, reverse: 7, hidden: 8, } def colors? true end def size @output.winsize end def style(foreground, background = nil, *attributes) tokens = [] if foreground tokens << 30 + COLORS.fetch(foreground) end if background tokens << 40 + COLORS.fetch(background) end attributes.each do |attribute| tokens << ATTRIBUTES.fetch(attribute){attribute.to_i} end return "\e[#{tokens.join(';')}m" end def reset "\e[0m" end end end end ruby-console-1.10.1/lib/console/version.rb000066400000000000000000000022241374746136600204560ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. module Console VERSION = "1.10.1" end ruby-console-1.10.1/spec/000077500000000000000000000000001374746136600151665ustar00rootroot00000000000000ruby-console-1.10.1/spec/console/000077500000000000000000000000001374746136600166305ustar00rootroot00000000000000ruby-console-1.10.1/spec/console/capture_spec.rb000066400000000000000000000026761374746136600216450ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console/capture' RSpec.describe Console::Capture do subject {described_class.new} let(:logger) {Console::Logger.new(subject)} describe '#buffer' do it 'can access log buffer' do logger.info("Hello World!") last = subject.last expect(last).to include(severity: :info, subject: "Hello World!") end end end ruby-console-1.10.1/spec/console/console_spec.rb000066400000000000000000000044241374746136600216350ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console' require_relative 'my_module' RSpec.describe Console do context MyModule do let(:io) {StringIO.new} let(:logger) {Console::Logger.new(Console::Terminal::Logger.new(io))} it "should log some messages" do MyModule.logger = logger MyModule.test_logger expect(io.string).to_not include("GOTO LINE 1") expect(io.string).to include("There be the dragons!") end it "should show debug messages" do MyModule.logger = logger MyModule.logger.debug! MyModule.test_logger expect(io.string).to include("GOTO LINE 1") end it "should log nested exceptions" do MyModule.logger = logger MyModule.logger.verbose! MyModule.log_error expect(io.string).to include("Caused by ArgumentError: It broken!") expect(MyModule.logger.debug?).to be == false expect(MyModule.logger.info?).to be == true end end describe '#logger' do let!(:original_logger) {described_class.logger} after do described_class.logger = original_logger end it 'sets and returns a logger' do logger = double(:logger) described_class.logger = logger expect(described_class.logger).to be(logger) end end end ruby-console-1.10.1/spec/console/event/000077500000000000000000000000001374746136600177515ustar00rootroot00000000000000ruby-console-1.10.1/spec/console/event/metric_spec.rb000066400000000000000000000026741374746136600226040ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console' require 'console/capture' RSpec.describe Console::Event::Metric do let(:output) {Console::Capture.new} let(:logger) {Console::Logger.new(output)} let(:event) {described_class.new(:x, 10)} it "can log event" do logger.info(self, event) expect(output.last).to include( arguments: [event], ) end end ruby-console-1.10.1/spec/console/logger_spec.rb000066400000000000000000000100501374746136600214420ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console/logger' require 'console/capture' RSpec.describe Console::Logger do let(:output) {Console::Capture.new} subject{described_class.new(output)} let(:message) {"Hello World"} describe '#with' do let(:nested) {subject.with(name: "nested", level: :debug)} it "should change level" do expect(nested.level).to be == 0 end it "should change name" do expect(nested.options[:name]).to be == "nested" end it "logs message with name" do nested.error(message) expect(output.last).to include( name: "nested", subject: message, ) end end context "with level" do let(:level) {0} subject{described_class.new(output, level: level)} it "should have specified log level" do expect(subject.level).to be == level end end context "default log level" do it "logs info" do expect(output).to receive(:call).with(message, severity: :info) subject.info(message) end it "doesn't log debug" do expect(output).to_not receive(:call) subject.debug(message) end end described_class::LEVELS.each do |name, level| it "can log #{name} messages" do expect(output).to receive(:call).with(message, severity: name) subject.level = level subject.send(name, message) end end describe '#enable' do let(:object) {Object.new} it "can enable specific subjects" do subject.warn! subject.enable(object) expect(subject).to be_enabled(object) expect(output).to receive(:call).with(object, message, severity: :debug) subject.debug(object, message) end end describe "#off!" do before do subject.off! end described_class::LEVELS.each do |name, level| it "doesn't log #{name} messages" do expect(output).to_not receive(:call) subject.send(name, message) expect(subject.send("#{name}?")).to be == false end end end describe "#all!" do before do subject.all! end described_class::LEVELS.each do |name, level| it "can log #{name} messages" do expect(output).to receive(:call).with(message, severity: name) subject.send(name, message) expect(subject.send("#{name}?")).to be == true end end end describe '.default_log_level' do let!(:debug) {$DEBUG} after {$DEBUG = debug} let!(:verbose) {$VERBOSE} after {$VERBOSE = verbose} it 'should set default log level' do $DEBUG = false $VERBOSE = 0 expect(Console::Logger.default_log_level).to be == Console::Logger::INFO end it 'should set default log level based on $DEBUG' do $DEBUG = true expect(Console::Logger.default_log_level).to be == Console::Logger::DEBUG end it 'should set default log level based on $VERBOSE' do $DEBUG = false $VERBOSE = true expect(Console::Logger.default_log_level).to be == Console::Logger::INFO end it 'can get log level from ENV' do expect(Console::Logger.default_log_level({'CONSOLE_LEVEL' => 'debug'})).to be == Console::Logger::DEBUG end end end ruby-console-1.10.1/spec/console/my_module.rb000066400000000000000000000020011374746136600211400ustar00rootroot00000000000000 module MyModule extend Console def self.argument_error raise ArgumentError, "It broken!" end def self.nested_error argument_error rescue raise RuntimeError, "Magic smoke escaped!" end def self.log_error self.nested_error rescue logger.error(self, $!) end def self.test_logger logger.debug "1: GOTO LINE 2", "2: GOTO LINE 1" logger.info "Dear maintainer:" do |buffer| buffer.puts "Once you are done trying to 'optimize' this routine, and have realized what a terrible mistake that was, please increment the following counter as a warning to the next guy:" buffer.puts "total_hours_wasted_here = 42" end logger.warn "Something didn't work as expected!" logger.error "There be the dragons!", (raise RuntimeError, "Bits have been rotated incorrectly!" rescue $!) logger.info(self) {Console::Shell.for({LDFLAGS: "-lm"}, "gcc", "-o", "stuff.o", "stuff.c", chdir: "/tmp/compile")} logger.info(Object.new) {"Where would we be without Object.new?"} end test_logger end ruby-console-1.10.1/spec/console/progress_spec.rb000066400000000000000000000030461374746136600220360ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console' require 'console/progress' RSpec.describe Console::Progress do describe '#increment' do it 'can create new measurement' do measure = Console.logger.measure("My Measurement", 100) expect(measure.current).to be 0 expect(measure.total).to be 100 expect(measure.subject).to be == "My Measurement" expect(Console.logger).to receive(:info).and_call_original measure.increment(50) end end end ruby-console-1.10.1/spec/console/resolver_spec.rb000066400000000000000000000045631374746136600220400ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console/resolver' RSpec.describe Console::Resolver do it "triggers when class is defined" do resolved = false subject.bind(["Console::Resolver::Foobar"]) do |klass| resolved = true end expect(subject).to be_waiting class Console::Resolver::Foobar end expect(subject).to_not be_waiting expect(resolved).to be true end it "triggers immediately if class is already defined" do resolved = false subject.bind(["Console::Resolver"]) do |klass| resolved = true end expect(subject).to_not be_waiting expect(resolved).to be true end describe '.default_resolver' do let(:logger) {Console.logger} it 'has no resolver if not required by environment' do expect(Console::Resolver.default_resolver(logger)).to be_nil end it 'can set custom log levels from environment' do expect(Console::Resolver.default_resolver(logger, {'CONSOLE_WARN' => 'Acorn,Banana', 'CONSOLE_DEBUG' => 'Cat'})).to be_a Console::Resolver class Acorn; end class Banana; end class Cat; end expect(Console.logger.subjects[Acorn]).to be == Console::Logger::WARN expect(Console.logger.subjects[Banana]).to be == Console::Logger::WARN expect(Console.logger.subjects[Cat]).to be == Console::Logger::DEBUG end end end ruby-console-1.10.1/spec/console/serialized/000077500000000000000000000000001374746136600207635ustar00rootroot00000000000000ruby-console-1.10.1/spec/console/serialized/logger_spec.rb000066400000000000000000000033531374746136600236050ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console/serialized/logger' RSpec.describe Console::Serialized::Logger do let(:io) {StringIO.new} subject{described_class.new(io)} let(:message) {"Hello World"} let(:record) {JSON.parse(io.string, symbolize_names: true)} it "can log to buffer" do subject.call do |buffer| buffer << message end expect(record).to include :message expect(record[:message]).to be == message end it "can log options" do subject.call(name: "request-id") record = JSON.parse(io.string, symbolize_names: true) expect(record).to include(:options) expect(record[:options]).to be == {name: "request-id"} end end ruby-console-1.10.1/spec/console/terminal/000077500000000000000000000000001374746136600204435ustar00rootroot00000000000000ruby-console-1.10.1/spec/console/terminal/logger_spec.rb000066400000000000000000000026361374746136600232700ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console/terminal/logger' RSpec.describe Console::Terminal::Logger do let(:io) {StringIO.new} subject{described_class.new(io)} let(:message) {"Hello World"} it "can log to buffer" do subject.call do |buffer| buffer << message end expect(io.string).to include message end end ruby-console-1.10.1/spec/console/terminal/xterm_spec.rb000066400000000000000000000045521374746136600231470ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console/terminal/xterm' RSpec.describe Console::Terminal::XTerm do let(:io) {StringIO.new} subject{described_class.new(io)} it "can generate simple style" do expect(subject.style(:blue)).to be == "\e[34m" end it "can generate complex style" do expect(subject.style(:blue, nil, :underline, :bold)).to be == "\e[34;4;1m" end it "can write text with specified style" do subject[:bold] = subject.style(nil, nil, :bold) subject.write("Hello World", style: :bold) expect(io.string).to be == "\e[1mHello World\e[0m" end it "can puts text with specified style" do subject[:bold] = subject.style(nil, nil, :bold) subject.puts("Hello World", style: :bold) expect(io.string.split(/\r?\n/)).to be == ["\e[1mHello World", "\e[0m"] end describe '#print' do it "can print using the specified style" do subject[:bold] = subject.style(nil, nil, :bold) subject.print(:bold, "Hello World") expect(io.string).to be == "\e[1mHello World" end end describe '#print_line' do it "can print a line using the specified style" do subject[:bold] = subject.style(nil, nil, :bold) subject.print_line(:bold, "Hello World") expect(io.string.split(/\r?\n/)).to be == ["\e[1mHello World\e[0m"] end end end ruby-console-1.10.1/spec/console_spec.rb000066400000000000000000000023521374746136600201710ustar00rootroot00000000000000# Copyright, 2019, by Samuel G. D. Williams. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'console' RSpec.describe Console do it "has a version number" do expect(Console::VERSION).not_to be nil end end ruby-console-1.10.1/spec/spec_helper.rb000066400000000000000000000005521374746136600200060ustar00rootroot00000000000000 require 'bundler/setup' require 'covered/rspec' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! config.expect_with :rspec do |c| c.syntax = :expect end end