Skip to content

Commit

Permalink
Merge pull request #852 from guard/rework_logging
Browse files Browse the repository at this point in the history
Rework logging and UI configuration
  • Loading branch information
e2 committed Aug 6, 2016
2 parents 73453cd + 4a6cf6b commit 32af0bf
Show file tree
Hide file tree
Showing 18 changed files with 445 additions and 284 deletions.
5 changes: 1 addition & 4 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ inherit_from:
- vendor/hound/config/style_guides/ruby.yml
- .rubocop_todo.yml

# Rails cops
AllCops:
RunRailsCops: true

# Files you want to exclude
AllCops:
TargetRubyVersion: 2.2
Exclude:
- db/schema.rb
- tmp/aruba/Guardfile
Expand Down
35 changes: 34 additions & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2016-05-19 21:55:11 +0200 using RuboCop version 0.40.0.
# on 2016-08-06 16:49:52 +0200 using RuboCop version 0.42.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand All @@ -18,6 +18,16 @@ Lint/NestedMethodDefinition:
- 'lib/guard/commands/show.rb'
- 'lib/guard/jobs/pry_wrapper.rb'

# Offense count: 7
# Configuration parameters: Include.
# Include: app/**/*.rb, config/**/*.rb, lib/**/*.rb
Rails/Exit:
Exclude:
- 'lib/**/*.rake'
- 'lib/guard.rb'
- 'lib/guard/cli.rb'
- 'lib/tasks/releaser.rb'

# Offense count: 39
# Cop supports --auto-correct.
Style/MutableConstant:
Expand All @@ -38,6 +48,21 @@ Style/MutableConstant:
- 'lib/guard/ui/colors.rb'
- 'lib/guard/version.rb'

# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: predicate, comparison
Style/NumericPredicate:
Exclude:
- 'lib/guard/dsl_describer.rb'
- 'lib/guard/terminal.rb'

# Offense count: 1
# Cop supports --auto-correct.
Style/SpaceInsideArrayPercentLiteral:
Exclude:
- 'guard.gemspec'

# Offense count: 41
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
Expand All @@ -57,3 +82,11 @@ Style/SpaceInsideStringInterpolation:
- 'lib/guard/plugin_util.rb'
- 'lib/guard/runner.rb'
- 'lib/guard/ui.rb'

# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiterals:
Exclude:
- 'Rakefile'
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ end
#
group :test do
# Both guard-rspec and guard-cucumber are used by cucumber features
gem "guard-cucumber", require: false
gem "guard-cucumber", "~> 2.1", require: false
gem "guard-rspec", require: false

gem "codeclimate-test-reporter", require: nil
Expand Down
2 changes: 1 addition & 1 deletion config/Guardfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ group :specs, halt_on_fail: true do
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
end

guard "cucumber", keep_failed: true, all_on_start: false, cli: '--profile guard' do
guard "cucumber", keep_failed: true, all_on_start: false, cmd_additional_args: '--profile guard' do
watch(%r{^features/.+\.feature$})
watch(%r{^features/support/.+$}) { "features" }
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) do |m|
Expand Down
2 changes: 1 addition & 1 deletion features/api.feature
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Feature: using Guard API
"""
Given I run `bundle exec rake`
Then the output should match /\[bar\] foo/
Then the output should match /bar\nfoo/
5 changes: 4 additions & 1 deletion features/support/env.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@

set_environment_variable(
"GUARD_NOTIFIERS",
"---\n- :name: :terminal_title\n :options: {}\n"
"---\n"\
"- :name: :file\n"\
" :options:\n"\
" :path: '/dev/stdout'\n"
)
end

Expand Down
5 changes: 5 additions & 0 deletions lib/guard/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ class Options < Thor::CoreExt::HashWithIndifferentAccess
def initialize(opts = {}, default_opts = {})
super(default_opts.merge(opts || {}))
end

# workaround for: https://github.com/erikhuda/thor/issues/504
def fetch(name)
super(name.to_s)
end
end
end
2 changes: 1 addition & 1 deletion lib/guard/plugin_util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def plugin_class(options = {})
def add_to_guardfile
klass = plugin_class # call here to avoid failing later

require "guard/guardfile/evaluator"
require_relative "guardfile/evaluator"
# TODO: move this to Generator?
options = Guard.state.session.evaluator_options
evaluator = Guardfile::Evaluator.new(options)
Expand Down
10 changes: 6 additions & 4 deletions lib/guard/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ def run_on_changes(modified, added, removed)
def _supervise(plugin, task, *args)
catch self.class.stopping_symbol_for(plugin) do
plugin.hook("#{ task }_begin", *args)
begin
result = plugin.send(task, *args)
rescue Interrupt
throw(:task_has_failed)
result = UI.options.with_progname(plugin.class.name) do
begin
plugin.send(task, *args)
rescue Interrupt
throw(:task_has_failed)
end
end
plugin.hook("#{ task }_end", result)
result
Expand Down
47 changes: 23 additions & 24 deletions lib/guard/ui.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
require "guard/ui/colors"
require "guard/ui/config"

require "guard/terminal"
require "guard/options"
require "forwardable"

# TODO: rework this class from the bottom-up
# - remove dependency on Session and Scope
# - extract into a separate gem
# - change UI to class

module Guard
# The UI class helps to format messages for the user. Everything that is
Expand All @@ -23,13 +24,11 @@ class << self
# Get the Guard::UI logger instance
#
def logger
@logger ||= begin
require "lumberjack"
Lumberjack::Logger.new(
options.fetch('device') { $stderr },
options
)
end
@logger ||=
begin
require "lumberjack"
Lumberjack::Logger.new(options.device, options.logger_config)
end
end

# Since logger is global, for Aruba in-process to properly
Expand All @@ -45,11 +44,7 @@ def reset_logger
# @return [Hash] the logger options
#
def options
@options ||= Options.new(
level: :info,
template: ":time - :severity - :message",
time_format: "%H:%M:%S"
)
@options ||= Config.new
end

# Set the logger options
Expand All @@ -61,12 +56,14 @@ def options
#
# TODO: deprecate?
def options=(options)
@options = Options.new(options)
@options = Config.new(options)
end

# Assigns a log level
extend Forwardable
def_delegator :logger, :level=
def level=(new_level)
options.logger_config.level = new_level
@logger.level = new_level if @logger
end

# Show an info message.
#
Expand Down Expand Up @@ -176,9 +173,9 @@ def action_with_scopes(action, scope)
# @yieldparam [String] param the calling plugin name
#
def _filter(plugin)
only = options[:only]
except = options[:except]
plugin ||= calling_plugin_name
only = options.only
except = options.except
plugin ||= _calling_plugin_name

match = !(only || except)
match ||= (only && only.match(plugin))
Expand All @@ -191,9 +188,9 @@ def _filter(plugin)
def _filtered_logger_message(message, method, color_name, options = {})
message = color(message, color_name) if color_name

_filter(options[:plugin]) do |plugin|
_filter(options[:plugin]) do
reset_line if options[:reset]
logger.send(method, message, plugin)
logger.send(method, message)
end
end

Expand All @@ -203,9 +200,11 @@ def _filtered_logger_message(message, method, color_name, options = {})
# @param [Integer] depth the stack depth
# @return [String] the Guard plugin name
#
def calling_plugin_name(depth = 2)
name = %r{(guard\/[a-z_]*)(/[a-z_]*)?.rb:}i.match(caller[depth])
return "Guard" unless name
def _calling_plugin_name
name = caller.lazy.map do |line|
%r{(?<!guard\/lib)\/(guard\/[a-z_]*)(/[a-z_]*)?.rb:}i.match(line)
end.reject(&:nil?).take(1).force.first
return "Guard" unless name || (name && name[1] == "guard/lib")
name[1].split("/").map do |part|
part.split(/[^a-z0-9]/i).map(&:capitalize).join
end.join("::")
Expand Down
70 changes: 70 additions & 0 deletions lib/guard/ui/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require "guard/options"
require "guard/ui/logger"

module Guard
module UI
class Config < Guard::Options
DEFAULTS = {
only: nil,
except: nil,

# nil (will be whatever $stderr is later) or LumberJack device, e.g.
# $stderr or 'foo.log'
device: nil,
}.freeze

DEPRECATED_OPTS = %w(template time_format level progname).freeze

attr_reader :logger_config

def initialize(options = {})
opts = Guard::Options.new(options, DEFAULTS)

# migrate old options stored in UI config directly
deprecated_logger_opts = {}
DEPRECATED_OPTS.each do |option|
if opts.key?(option)
deprecated_logger_opts[option.to_sym] = opts.delete(option)
end
end

@logger_config = Logger::Config.new(deprecated_logger_opts)
super(opts.to_hash)
end

def device
# Use strings to work around Thor's indifferent Hash's bug
fetch("device") || $stderr
end

def only
fetch("only")
end

def except
fetch("except")
end

def [](name)
name = name.to_s

# TODO: remove in Guard 3.x
return logger_config[name] if DEPRECATED_OPTS.include?(name)
return device if name == "device"

# let Thor's Hash handle anything else
super(name.to_s)
end

def with_progname(name)
if Guard::UI.logger.respond_to?(:set_progname)
Guard::UI.logger.set_progname(name) do
yield if block_given?
end
elsif block_given?
yield
end
end
end
end
end
30 changes: 30 additions & 0 deletions lib/guard/ui/logger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require "guard/options"

module Guard
module UI
class Logger
class Config < Guard::Options
DEFAULTS = {
progname: "Guard",
level: :info,
template: ":time - :severity - :message",
time_format: "%H:%M:%S",
flush_seconds: 0,

# Other LumberJack device-specific options
# max_size: "5M",
# buffer_size: 0,
# additional_lines: nil,
}.freeze

def initialize(options = {})
super(options, DEFAULTS)
end

def level=(value)
self["level"] = value
end
end
end
end
end
Loading

0 comments on commit 32af0bf

Please sign in to comment.