Merge pull request #823 from reitermarkus/refactoring-tty

Refactor Tty.
This commit is contained in:
Markus Reiter 2016-10-02 05:36:50 +02:00 committed by GitHub
commit 8b06a01e5b
30 changed files with 238 additions and 176 deletions

View File

@ -16,7 +16,7 @@ def blacklisted?(name)
Homebrew provides pip via: `brew install python`. However you will then Homebrew provides pip via: `brew install python`. However you will then
have two Pythons installed on your Mac, so alternatively you can install have two Pythons installed on your Mac, so alternatively you can install
pip via the instructions at: pip via the instructions at:
https://pip.readthedocs.io/en/stable/installing/ #{Formatter.url("https://pip.readthedocs.io/en/stable/installing/")}
EOS EOS
when "pil" then <<-EOS.undent when "pil" then <<-EOS.undent
Instead of PIL, consider `pip install pillow` or `brew install Homebrew/python/pillow`. Instead of PIL, consider `pip install pillow` or `brew install Homebrew/python/pillow`.
@ -24,7 +24,7 @@ def blacklisted?(name)
when "macruby" then <<-EOS.undent when "macruby" then <<-EOS.undent
MacRuby is not packaged and is on an indefinite development hiatus. MacRuby is not packaged and is on an indefinite development hiatus.
You can read more about it at: You can read more about it at:
https://github.com/MacRuby/MacRuby #{Formatter.url("https://github.com/MacRuby/MacRuby")}
EOS EOS
when /(lib)?lzma/ when /(lib)?lzma/
"lzma is now part of the xz formula." "lzma is now part of the xz formula."
@ -50,7 +50,7 @@ def blacklisted?(name)
To install Clojure you should install Leiningen: To install Clojure you should install Leiningen:
brew install leiningen brew install leiningen
and then follow the tutorial: and then follow the tutorial:
https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md #{Formatter.url("https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md")}
EOS EOS
when "osmium" then <<-EOS.undent when "osmium" then <<-EOS.undent
The creator of Osmium requests that it not be packaged and that people The creator of Osmium requests that it not be packaged and that people
@ -65,8 +65,8 @@ def blacklisted?(name)
brew install typesafe-activator brew install typesafe-activator
You can read more about this change at: You can read more about this change at:
https://www.playframework.com/documentation/2.3.x/Migration23 #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Migration23")}
https://www.playframework.com/documentation/2.3.x/Highlights23 #{Formatter.url("https://www.playframework.com/documentation/2.3.x/Highlights23")}
EOS EOS
when "haskell-platform" then <<-EOS.undent when "haskell-platform" then <<-EOS.undent
We no longer package haskell-platform. Consider installing ghc We no longer package haskell-platform. Consider installing ghc

View File

@ -147,8 +147,8 @@ rescue Exception => e
Utils::Analytics.report_exception(e) Utils::Analytics.report_exception(e)
onoe e onoe e
if internal_cmd && defined?(OS::ISSUES_URL) if internal_cmd && defined?(OS::ISSUES_URL)
$stderr.puts "#{Tty.white}Please report this bug:" $stderr.puts "#{Tty.bold}Please report this bug:#{Tty.reset}"
$stderr.puts " #{Tty.em}#{OS::ISSUES_URL}#{Tty.reset}" $stderr.puts " #{Formatter.url(OS::ISSUES_URL)}"
end end
$stderr.puts e.backtrace $stderr.puts e.backtrace
exit 1 exit 1

View File

@ -79,13 +79,10 @@ module Hbc
load_specification artifact_spec load_specification artifact_spec
if target.exist? if target.exist?
target_abv = " (#{target.abv})" "#{printable_target} (#{target.abv})"
else else
warning = "Missing #{self.class.artifact_english_name}" Formatter.error(printable_target, label: "Missing #{self.class.artifact_english_name}")
warning = "#{Tty.red}#{warning}#{Tty.reset}: "
end end
"#{warning}#{printable_target}#{target_abv}"
end end
end end
end end

View File

@ -57,12 +57,17 @@ module Hbc
def summarize_artifact(artifact_spec) def summarize_artifact(artifact_spec)
load_specification artifact_spec load_specification artifact_spec
return unless self.class.islink?(target) if self.class.islink?(target) && target.exist? && target.readlink.exist?
"#{printable_target} -> #{target.readlink} (#{target.readlink.abv})"
else
string = if self.class.islink?(target)
"#{printable_target} -> #{target.readlink}"
else
printable_target
end
link_description = "#{Tty.red}Broken Link#{Tty.reset}: " unless target.exist? Formatter.error(string, label: "Broken Link")
target_readlink_abv = " (#{target.readlink.abv})" if target.readlink.exist? end
"#{link_description}#{printable_target} -> #{target.readlink}#{target_readlink_abv}"
end end
end end
end end

View File

@ -28,11 +28,11 @@ module Hbc
def result def result
if errors? if errors?
"#{Tty.red}failed#{Tty.reset}" Formatter.error("failed")
elsif warnings? elsif warnings?
"#{Tty.yellow}warning#{Tty.reset}" Formatter.warning("warning")
else else
"#{Tty.green}passed#{Tty.reset}" Formatter.success("passed")
end end
end end
@ -40,11 +40,11 @@ module Hbc
summary = ["#{summary_header}: #{result}"] summary = ["#{summary_header}: #{result}"]
errors.each do |error| errors.each do |error|
summary << " #{Tty.red}-#{Tty.reset} #{error}" summary << " #{Formatter.error("-")} #{error}"
end end
warnings.each do |warning| warnings.each do |warning|
summary << " #{Tty.yellow}-#{Tty.reset} #{warning}" summary << " #{Formatter.warning("-")} #{warning}"
end end
summary.join("\n") summary.join("\n")

View File

@ -122,11 +122,11 @@ module Hbc
end end
def self.notfound_string def self.notfound_string
"#{Tty.red}Not Found - Unknown Error#{Tty.reset}" Formatter.error("Not Found - Unknown Error")
end end
def self.error_string(string = "Error") def self.error_string(string = "Error")
"#{Tty.red}(#{string})#{Tty.reset}" Formatter.error("(#{string})")
end end
def self.render_with_none(string) def self.render_with_none(string)

View File

@ -18,16 +18,16 @@ module Hbc
def self.info(cask) def self.info(cask)
puts "#{cask.token}: #{cask.version}" puts "#{cask.token}: #{cask.version}"
puts formatted_url(cask.homepage) if cask.homepage puts Formatter.url(cask.homepage) if cask.homepage
installation_info(cask) installation_info(cask)
puts "From: #{formatted_url(github_info(cask))}" if github_info(cask) puts "From: #{Formatter.url(github_info(cask))}" if github_info(cask)
name_info(cask) name_info(cask)
artifact_info(cask) artifact_info(cask)
Installer.print_caveats(cask) Installer.print_caveats(cask)
end end
def self.formatted_url(url) def self.formatted_url(url)
"#{Tty.em}#{url}#{Tty.reset}" "#{Tty.underline}#{url}#{Tty.reset}"
end end
def self.installation_info(cask) def self.installation_info(cask)
@ -37,7 +37,7 @@ module Hbc
puts versioned_staged_path.to_s puts versioned_staged_path.to_s
.concat(" (") .concat(" (")
.concat(versioned_staged_path.exist? ? versioned_staged_path.abv : "#{Tty.red}does not exist#{Tty.reset}") .concat(versioned_staged_path.exist? ? versioned_staged_path.abv : Formatter.error("does not exist"))
.concat(")") .concat(")")
end end
else else
@ -47,7 +47,7 @@ module Hbc
def self.name_info(cask) def self.name_info(cask)
ohai cask.name.size > 1 ? "Names" : "Name" ohai cask.name.size > 1 ? "Names" : "Name"
puts cask.name.empty? ? "#{Tty.red}None#{Tty.reset}" : cask.name puts cask.name.empty? ? Formatter.error("None") : cask.name
end end
def self.github_info(cask) def self.github_info(cask)

View File

@ -30,7 +30,7 @@ module Hbc
begin begin
Homebrew.install_gem_setup_path! "rubocop-cask", RUBOCOP_CASK_VERSION, "rubocop" Homebrew.install_gem_setup_path! "rubocop-cask", RUBOCOP_CASK_VERSION, "rubocop"
rescue SystemExit rescue SystemExit
raise CaskError, $stderr.string.chomp.sub("#{Tty.red}Error#{Tty.reset}: ", "") raise CaskError, Tty.strip_ansi($stderr.string).chomp.sub(/\AError: /, "")
end end
end end
end end

View File

@ -102,12 +102,12 @@ module Hbc
A report has been made to Apple about this app. Their certificate will hopefully be revoked. A report has been made to Apple about this app. Their certificate will hopefully be revoked.
See the public report at See the public report at
https://openradar.appspot.com/#{radar_number} #{Formatter.url("https://openradar.appspot.com/#{radar_number}")}
If this report is accurate, please duplicate it at If this report is accurate, please duplicate it at
https://bugreport.apple.com/ #{Formatter.url("https://bugreport.apple.com/")}
If this report is a mistake, please let us know by opening an issue at If this report is a mistake, please let us know by opening an issue at
https://github.com/caskroom/homebrew-cask/issues/new #{Formatter.url("https://github.com/caskroom/homebrew-cask/issues/new")}
EOS EOS
end end

View File

@ -87,7 +87,7 @@ module Hbc
s = if MacOS.version >= :lion && !ENV["HOMEBREW_NO_EMOJI"] s = if MacOS.version >= :lion && !ENV["HOMEBREW_NO_EMOJI"]
(ENV["HOMEBREW_INSTALL_BADGE"] || "\xf0\x9f\x8d\xba") + " " (ENV["HOMEBREW_INSTALL_BADGE"] || "\xf0\x9f\x8d\xba") + " "
else else
"#{Tty.blue}==>#{Tty.reset} #{Tty.white}Success!#{Tty.reset} " Formatter.headline("Success! ", color: :blue)
end end
s << "#{@cask} was successfully installed!" s << "#{@cask} was successfully installed!"
end end

View File

@ -32,12 +32,7 @@ end
def odebug(title, *sput) def odebug(title, *sput)
return unless Hbc.respond_to?(:debug) return unless Hbc.respond_to?(:debug)
return unless Hbc.debug return unless Hbc.debug
puts Formatter.headline(title, color: :magenta)
width = Tty.width * 4 - 6
if $stdout.tty? && title.to_s.length > width
title = title.to_s[0, width - 3] + "..."
end
puts "#{Tty.magenta}==>#{Tty.reset} #{Tty.white}#{title}#{Tty.reset}"
puts sput unless sput.empty? puts sput unless sput.empty?
end end
@ -151,12 +146,10 @@ module Hbc
def self.error_message_with_suggestions def self.error_message_with_suggestions
<<-EOS.undent <<-EOS.undent
Most likely, this means you have an outdated version of Homebrew-Cask. Please run: Most likely, this means you have an outdated version of Homebrew-Cask. Please run:
#{UPDATE_CMD}
#{Tty.green}#{UPDATE_CMD} If this doesnt fix the problem, please report this bug:
#{Formatter.url(ISSUES_URL)}
#{Tty.reset}If this doesnt fix the problem, please report this bug:
#{Tty.em}#{ISSUES_URL}#{Tty.reset}
EOS EOS
end end

View File

@ -42,9 +42,9 @@ module Homebrew
next if out.nil? || out.empty? next if out.nil? || out.empty?
if first_warning if first_warning
$stderr.puts <<-EOS.undent $stderr.puts <<-EOS.undent
#{Tty.white}Please note that these warnings are just used to help the Homebrew maintainers #{Tty.bold}Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry and just ignore them. Thanks!#{Tty.reset} working fine: please don't worry and just ignore them. Thanks!#{Tty.reset}
EOS EOS
end end

View File

@ -79,9 +79,10 @@ module Homebrew
else else
help_lines.map do |line| help_lines.map do |line|
line.slice(2..-1) line.slice(2..-1)
.sub(/^ \* /, "#{Tty.highlight}brew#{Tty.reset} ") .sub(/^ \* /, "#{Tty.bold}brew#{Tty.reset} ")
.gsub(/`(.*?)`/, "#{Tty.highlight}\\1#{Tty.reset}") .gsub(/`(.*?)`/, "#{Tty.bold}\\1#{Tty.reset}")
.gsub(/<(.*?)>/, "#{Tty.em}\\1#{Tty.reset}") .gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
.gsub(/<(.*?)>/, "#{Tty.underline}\\1#{Tty.reset}")
.gsub("@hide_from_man_page", "") .gsub("@hide_from_man_page", "")
end.join.strip end.join.strip
end end

View File

@ -117,7 +117,7 @@ module Homebrew
puts "#{f.full_name}: #{specs * ", "}#{" [#{attrs * ", "}]" unless attrs.empty?}" puts "#{f.full_name}: #{specs * ", "}#{" [#{attrs * ", "}]" unless attrs.empty?}"
puts f.desc if f.desc puts f.desc if f.desc
puts "#{Tty.em}#{f.homepage}#{Tty.reset}" if f.homepage puts Formatter.url(f.homepage) if f.homepage
conflicts = f.conflicts.map(&:name).sort! conflicts = f.conflicts.map(&:name).sort!
puts "Conflicts with: #{conflicts*", "}" unless conflicts.empty? puts "Conflicts with: #{conflicts*", "}" unless conflicts.empty?
@ -133,7 +133,7 @@ module Homebrew
end end
end end
puts "From: #{Tty.em}#{github_info(f)}#{Tty.reset}" puts "From: #{Formatter.url(github_info(f))}"
unless f.deps.empty? unless f.deps.empty?
ohai "Dependencies" ohai "Dependencies"

View File

@ -282,13 +282,13 @@ module Homebrew
EOS EOS
rescue => e rescue => e
ofail <<-EOS.undent ofail <<-EOS.undent
#{Tty.white}Failed to migrate HOMEBREW_REPOSITORY to #{new_homebrew_repository}! #{Tty.bold}Failed to migrate HOMEBREW_REPOSITORY to #{new_homebrew_repository}!#{Tty.reset}
The error was: The error was:
#{e} #{e}
Please try to resolve this error yourself and then run `brew update` again to Please try to resolve this error yourself and then run `brew update` again to
complete the migration. If you need help please +1 an existing error or comment complete the migration. If you need help please +1 an existing error or comment
with your new error in issue: with your new error in issue:
#{Tty.em}https://github.com/Homebrew/brew/issues/987#{Tty.reset} #{Formatter.url("https://github.com/Homebrew/brew/issues/987")}
EOS EOS
$stderr.puts e.backtrace $stderr.puts e.backtrace
end end

View File

@ -15,3 +15,4 @@ require "compat/dependency_collector"
require "compat/language/haskell" require "compat/language/haskell"
require "compat/xcode" require "compat/xcode"
require "compat/software_spec" require "compat/software_spec"
require "compat/utils"

View File

@ -8,3 +8,11 @@ def shell_profile
else "~/.bash_profile" else "~/.bash_profile"
end end
end end
module Tty
module_function
def white
reset.bold
end
end

View File

@ -111,7 +111,7 @@ module Debrew
begin begin
puts e.backtrace.first.to_s puts e.backtrace.first.to_s
puts "#{Tty.red}#{e.class.name}#{Tty.reset}: #{e}" puts Formatter.error(e, label: e.class.name)
loop do loop do
Menu.choose do |menu| Menu.choose do |menu|

View File

@ -119,12 +119,12 @@ class Descriptions
# Take search results -- a hash mapping formula names to descriptions -- and # Take search results -- a hash mapping formula names to descriptions -- and
# print them. # print them.
def print def print
blank = "#{Tty.yellow}[no description]#{Tty.reset}" blank = Formatter.warning("[no description]")
@descriptions.keys.sort.each do |full_name| @descriptions.keys.sort.each do |full_name|
short_name = short_names[full_name] short_name = short_names[full_name]
printed_name = short_name_counts[short_name] == 1 ? short_name : full_name printed_name = short_name_counts[short_name] == 1 ? short_name : full_name
description = @descriptions[full_name] || blank description = @descriptions[full_name] || blank
puts "#{Tty.white}#{printed_name}:#{Tty.reset} #{description}" puts "#{Tty.bold}#{printed_name}:#{Tty.reset} #{description}"
end end
end end

View File

@ -54,7 +54,7 @@ module Homebrew
return if @put_filenames.include? filename return if @put_filenames.include? filename
puts "#{Tty.red}#{filename}#{Tty.reset}" puts Formatter.error(filename.to_s)
@put_filenames << filename @put_filenames << filename
end end
@ -93,7 +93,7 @@ module Homebrew
next unless ARGV.verbose? && !text_matches.empty? next unless ARGV.verbose? && !text_matches.empty?
print_filename.call(string, file) print_filename.call(string, file)
text_matches.first(MAXIMUM_STRING_MATCHES).each do |match, offset| text_matches.first(MAXIMUM_STRING_MATCHES).each do |match, offset|
puts " #{Tty.gray}-->#{Tty.reset} match '#{match}' at offset #{Tty.em}0x#{offset}#{Tty.reset}" puts " #{Tty.gray}-->#{Tty.reset} match '#{match}' at offset #{Tty.bold}0x#{offset}#{Tty.reset}"
end end
if text_matches.size > MAXIMUM_STRING_MATCHES if text_matches.size > MAXIMUM_STRING_MATCHES

View File

@ -473,7 +473,7 @@ module Homebrew
If you have trouble downloading packages with Homebrew, then maybe this If you have trouble downloading packages with Homebrew, then maybe this
is the problem? If the following command doesn't work, then try removing is the problem? If the following command doesn't work, then try removing
your curlrc: your curlrc:
curl https://github.com curl #{Formatter.url("https://github.com")}
EOS EOS
end end
@ -610,7 +610,7 @@ module Homebrew
Setting DYLD_INSERT_LIBRARIES can cause Go builds to fail. Setting DYLD_INSERT_LIBRARIES can cause Go builds to fail.
Having this set is common if you use this software: Having this set is common if you use this software:
http://asepsis.binaryage.com/ #{Formatter.url("http://asepsis.binaryage.com/")}
EOS EOS
end end
@ -752,7 +752,7 @@ module Homebrew
Without a correctly configured origin, Homebrew won't update Without a correctly configured origin, Homebrew won't update
properly. You can solve this by adding the Homebrew remote: properly. You can solve this by adding the Homebrew remote:
cd #{HOMEBREW_REPOSITORY} cd #{HOMEBREW_REPOSITORY}
git remote add origin https://github.com/Homebrew/brew.git git remote add origin #{Formatter.url("https://github.com/Homebrew/brew.git")}
EOS EOS
elsif origin !~ %r{Homebrew/brew(\.git)?$} elsif origin !~ %r{Homebrew/brew(\.git)?$}
<<-EOS.undent <<-EOS.undent
@ -764,7 +764,7 @@ module Homebrew
Unless you have compelling reasons, consider setting the Unless you have compelling reasons, consider setting the
origin remote to point at the main repository, located at: origin remote to point at the main repository, located at:
https://github.com/Homebrew/brew.git #{Formatter.url("https://github.com/Homebrew/brew.git")}
EOS EOS
end end
end end
@ -956,8 +956,8 @@ module Homebrew
<<-EOS.undent <<-EOS.undent
A .pydistutils.cfg file was found in $HOME, which may cause Python A .pydistutils.cfg file was found in $HOME, which may cause Python
builds to fail. See: builds to fail. See:
https://bugs.python.org/issue6138 #{Formatter.url("https://bugs.python.org/issue6138")}
https://bugs.python.org/issue4655 #{Formatter.url("https://bugs.python.org/issue4655")}
EOS EOS
end end

View File

@ -318,7 +318,7 @@ class BuildError < RuntimeError
def dump def dump
if !ARGV.verbose? if !ARGV.verbose?
puts puts
puts "#{Tty.red}READ THIS#{Tty.reset}: #{Tty.em}#{OS::ISSUES_URL}#{Tty.reset}" puts Formatter.error(Formatter.url(OS::ISSUES_URL), label: "READ THIS")
if formula.tap if formula.tap
case formula.tap.name case formula.tap.name
when "homebrew/boneyard" when "homebrew/boneyard"
@ -327,7 +327,7 @@ class BuildError < RuntimeError
else else
if issues_url = formula.tap.issues_url if issues_url = formula.tap.issues_url
puts "If reporting this issue please do so at (not Homebrew/brew):" puts "If reporting this issue please do so at (not Homebrew/brew):"
puts " #{issues_url}" puts " #{Formatter.url(issues_url)}"
end end
end end
end end

View File

@ -214,7 +214,7 @@ class FormulaInstaller
opoo "#{formula.full_name}: #{old_flag} was deprecated; using #{new_flag} instead!" opoo "#{formula.full_name}: #{old_flag} was deprecated; using #{new_flag} instead!"
end end
oh1 "Installing #{Tty.green}#{formula.full_name}#{Tty.reset}" if show_header? oh1 "Installing #{Formatter.identifier(formula.full_name)}" if show_header?
if formula.tap && !formula.tap.private? if formula.tap && !formula.tap.private?
options = [] options = []
@ -426,7 +426,7 @@ class FormulaInstaller
if deps.empty? && only_deps? if deps.empty? && only_deps?
puts "All dependencies for #{formula.full_name} are satisfied." puts "All dependencies for #{formula.full_name} are satisfied."
elsif !deps.empty? elsif !deps.empty?
oh1 "Installing dependencies for #{formula.full_name}: #{Tty.green}#{deps.map(&:first)*", "}#{Tty.reset}", oh1 "Installing dependencies for #{formula.full_name}: #{deps.map(&:first).map(&Formatter.method(:identifier)).join(", ")}",
truncate: false truncate: false
deps.each { |dep, options| install_dependency(dep, options) } deps.each { |dep, options| install_dependency(dep, options) }
end end
@ -476,7 +476,7 @@ class FormulaInstaller
fi.verbose = verbose? && !quieter? fi.verbose = verbose? && !quieter?
fi.debug = debug? fi.debug = debug?
fi.prelude fi.prelude
oh1 "Installing #{formula.full_name} dependency: #{Tty.green}#{dep.name}#{Tty.reset}" oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}"
fi.install fi.install
fi.finish fi.finish
rescue Exception rescue Exception

View File

@ -153,7 +153,7 @@ class Migrator
end end
begin begin
oh1 "Migrating #{Tty.green}#{oldname}#{Tty.white} to #{Tty.green}#{newname}#{Tty.reset}" oh1 "Migrating #{Formatter.identifier(oldname)} to #{Formatter.identifier(newname)}"
lock lock
unlink_oldname unlink_oldname
move_to_new_directory move_to_new_directory
@ -200,7 +200,7 @@ class Migrator
end end
def unlink_oldname def unlink_oldname
oh1 "Unlinking #{Tty.green}#{oldname}#{Tty.reset}" oh1 "Unlinking #{Formatter.identifier(oldname)}"
old_cellar.subdirs.each do |d| old_cellar.subdirs.each do |d|
keg = Keg.new(d) keg = Keg.new(d)
keg.unlink keg.unlink
@ -208,7 +208,7 @@ class Migrator
end end
def link_newname def link_newname
oh1 "Linking #{Tty.green}#{newname}#{Tty.reset}" oh1 "Linking #{Formatter.identifier(newname)}"
new_keg = Keg.new(new_linked_keg_record) new_keg = Keg.new(new_linked_keg_record)
# If old_keg wasn't linked then we just optlink a keg. # If old_keg wasn't linked then we just optlink a keg.

View File

@ -44,7 +44,7 @@ class XcodeRequirement < Requirement
EOS EOS
else else
message + <<-EOS.undent message + <<-EOS.undent
Xcode can be installed from https://developer.apple.com/xcode/downloads/ Xcode can be installed from #{Formatter.url("https://developer.apple.com/xcode/downloads/")}
EOS EOS
end end
end end

View File

@ -5,8 +5,11 @@ require "utils/shell"
class TtyTests < Homebrew::TestCase class TtyTests < Homebrew::TestCase
def test_strip_ansi def test_strip_ansi
assert_equal "hello", assert_equal "hello", Tty.strip_ansi("\033\[36;7mhello\033\[0m")
Tty.strip_ansi("\033\[36;7mhello\033\[0m") end
def test_width
assert_kind_of Integer, Tty.width
end end
def test_truncate def test_truncate
@ -21,15 +24,26 @@ class TtyTests < Homebrew::TestCase
def test_no_tty_formatting def test_no_tty_formatting
$stdout.stubs(:tty?).returns false $stdout.stubs(:tty?).returns false
assert_nil Tty.blue assert_equal "", Tty.to_s
assert_nil Tty.white assert_equal "", Tty.red.to_s
assert_nil Tty.red assert_equal "", Tty.green.to_s
assert_nil Tty.green assert_equal "", Tty.yellow.to_s
assert_nil Tty.gray assert_equal "", Tty.blue.to_s
assert_nil Tty.yellow assert_equal "", Tty.magenta.to_s
assert_nil Tty.reset assert_equal "", Tty.cyan.to_s
assert_nil Tty.em assert_equal "", Tty.default.to_s
assert_nil Tty.highlight end
def test_formatting
$stdout.stubs(:tty?).returns(true)
assert_equal "", Tty.to_s
assert_equal "\033[31m", Tty.red.to_s
assert_equal "\033[32m", Tty.green.to_s
assert_equal "\033[33m", Tty.yellow.to_s
assert_equal "\033[34m", Tty.blue.to_s
assert_equal "\033[35m", Tty.magenta.to_s
assert_equal "\033[36m", Tty.cyan.to_s
assert_equal "\033[39m", Tty.default.to_s
end end
end end

View File

@ -1,6 +1,7 @@
require "pathname" require "pathname"
require "emoji" require "emoji"
require "exceptions" require "exceptions"
require "utils/formatter"
require "utils/hash" require "utils/hash"
require "utils/json" require "utils/json"
require "utils/inreplace" require "utils/inreplace"
@ -10,85 +11,11 @@ require "utils/git"
require "utils/analytics" require "utils/analytics"
require "utils/github" require "utils/github"
require "utils/curl" require "utils/curl"
require "utils/tty"
class Tty
class << self
def strip_ansi(string)
string.gsub(/\033\[\d+(;\d+)*m/, "")
end
def blue
bold 34
end
def white
bold 39
end
def magenta
bold 35
end
def red
underline 31
end
def yellow
underline 33
end
def reset
escape 0
end
def em
underline 39
end
def green
bold 32
end
def gray
bold 30
end
def highlight
bold 39
end
def width
`/usr/bin/tput cols`.strip.to_i
end
def truncate(str)
w = width
w > 10 ? str.to_s[0, w - 4] : str
end
private
def color(n)
escape "0;#{n}"
end
def bold(n)
escape "1;#{n}"
end
def underline(n)
escape "4;#{n}"
end
def escape(n)
"\033[#{n}m" if $stdout.tty?
end
end
end
def ohai(title, *sput) def ohai(title, *sput)
title = Tty.truncate(title) if $stdout.tty? && !ARGV.verbose? title = Tty.truncate(title) if $stdout.tty? && !ARGV.verbose?
puts "#{Tty.blue}==>#{Tty.white} #{title}#{Tty.reset}" puts Formatter.headline(title, color: :blue)
puts sput puts sput
end end
@ -96,16 +23,16 @@ def oh1(title, options = {})
if $stdout.tty? && !ARGV.verbose? && options.fetch(:truncate, :auto) == :auto if $stdout.tty? && !ARGV.verbose? && options.fetch(:truncate, :auto) == :auto
title = Tty.truncate(title) title = Tty.truncate(title)
end end
puts "#{Tty.green}==>#{Tty.white} #{title}#{Tty.reset}" puts Formatter.headline(title, color: :green)
end end
# Print a warning (do this rarely) # Print a warning (do this rarely)
def opoo(warning) def opoo(message)
$stderr.puts "#{Tty.yellow}Warning#{Tty.reset}: #{warning}" $stderr.puts Formatter.warning(message, label: "Warning")
end end
def onoe(error) def onoe(message)
$stderr.puts "#{Tty.red}Error#{Tty.reset}: #{error}" $stderr.puts Formatter.error(message, label: "Error")
end end
def ofail(error) def ofail(error)
@ -171,9 +98,9 @@ def pretty_installed(f)
if !$stdout.tty? if !$stdout.tty?
f.to_s f.to_s
elsif Emoji.enabled? elsif Emoji.enabled?
"#{Tty.highlight}#{f} #{Tty.green}#{Emoji.tick}#{Tty.reset}" "#{Tty.bold}#{f} #{Formatter.success(Emoji.tick)}#{Tty.reset}"
else else
"#{Tty.highlight}#{Tty.green}#{f} (installed)#{Tty.reset}" Formatter.success("#{Tty.bold}#{f} (installed)#{Tty.reset}")
end end
end end
@ -181,9 +108,9 @@ def pretty_uninstalled(f)
if !$stdout.tty? if !$stdout.tty?
f.to_s f.to_s
elsif Emoji.enabled? elsif Emoji.enabled?
"#{f} #{Tty.red}#{Emoji.cross}#{Tty.reset}" "#{Tty.bold}#{f} #{Formatter.error(Emoji.cross)}#{Tty.reset}"
else else
"#{Tty.red}#{f} (uninstalled)#{Tty.reset}" Formatter.error("#{Tty.bold}#{f} (uninstalled)#{Tty.reset}")
end end
end end

View File

@ -0,0 +1,52 @@
require "utils/tty"
module Formatter
module_function
def arrow(string, color: nil)
prefix("==>", string, color)
end
def headline(string, color: nil)
arrow("#{Tty.bold}#{string}#{Tty.reset}", color: color)
end
def identifier(string)
"#{Tty.green}#{string}#{Tty.reset}"
end
def success(string, label: nil)
label(label, string, :green)
end
def warning(string, label: nil)
label(label, string, :yellow)
end
def error(string, label: nil)
label(label, string, :red)
end
def url(string)
"#{Tty.underline}#{string}#{Tty.no_underline}"
end
def label(label, string, color)
label = "#{label}:" unless label.nil?
prefix(label, string, color)
end
private_class_method :label
def prefix(prefix, string, color)
if prefix.nil? && color.nil?
string
elsif prefix.nil?
"#{Tty.send(color)}#{string}#{Tty.reset}"
elsif color.nil?
"#{prefix} #{string}"
else
"#{Tty.send(color)}#{prefix}#{Tty.reset} #{string}"
end
end
private_class_method :prefix
end

View File

@ -14,7 +14,7 @@ module GitHub
super <<-EOS.undent super <<-EOS.undent
GitHub API Error: #{error} GitHub API Error: #{error}
Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token: Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token:
#{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset} #{Formatter.url("https://github.com/settings/tokens/new?scopes=&description=Homebrew")}
and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token" and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
EOS EOS
end end
@ -30,7 +30,7 @@ module GitHub
if ENV["HOMEBREW_GITHUB_API_TOKEN"] if ENV["HOMEBREW_GITHUB_API_TOKEN"]
message << <<-EOS.undent message << <<-EOS.undent
HOMEBREW_GITHUB_API_TOKEN may be invalid or expired; check: HOMEBREW_GITHUB_API_TOKEN may be invalid or expired; check:
#{Tty.em}https://github.com/settings/tokens#{Tty.reset} #{Formatter.url("https://github.com/settings/tokens")}
EOS EOS
else else
message << <<-EOS.undent message << <<-EOS.undent
@ -38,7 +38,7 @@ module GitHub
Clear them with: Clear them with:
printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase
Or create a personal access token: Or create a personal access token:
#{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset} #{Formatter.url("https://github.com/settings/tokens/new?scopes=&description=Homebrew")}
and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token" and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
EOS EOS
end end
@ -106,14 +106,14 @@ module GitHub
onoe <<-EOS.undent onoe <<-EOS.undent
Your macOS keychain GitHub credentials do not have sufficient scope! Your macOS keychain GitHub credentials do not have sufficient scope!
Scopes they have: #{credentials_scopes} Scopes they have: #{credentials_scopes}
Create a personal access token: https://github.com/settings/tokens Create a personal access token: #{Formatter.url("https://github.com/settings/tokens")}
and then set HOMEBREW_GITHUB_API_TOKEN as the authentication method instead. and then set HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
EOS EOS
when :environment when :environment
onoe <<-EOS.undent onoe <<-EOS.undent
Your HOMEBREW_GITHUB_API_TOKEN does not have sufficient scope! Your HOMEBREW_GITHUB_API_TOKEN does not have sufficient scope!
Scopes it has: #{credentials_scopes} Scopes it has: #{credentials_scopes}
Create a new personal access token: https://github.com/settings/tokens Create a new personal access token: #{Formatter.url("https://github.com/settings/tokens")}
and then set the new HOMEBREW_GITHUB_API_TOKEN as the authentication method instead. and then set the new HOMEBREW_GITHUB_API_TOKEN as the authentication method instead.
EOS EOS
end end

View File

@ -0,0 +1,64 @@
module Tty
module_function
def strip_ansi(string)
string.gsub(/\033\[\d+(;\d+)*m/, "")
end
def width
`/usr/bin/tput cols`.strip.to_i
end
def truncate(string)
(w = width).zero? ? string.to_s : string.to_s[0, w - 4]
end
COLOR_CODES = {
red: 31,
green: 32,
yellow: 33,
blue: 34,
magenta: 35,
cyan: 36,
default: 39,
}.freeze
STYLE_CODES = {
reset: 0,
bold: 1,
italic: 3,
underline: 4,
strikethrough: 9,
no_underline: 24,
}.freeze
CODES = COLOR_CODES.merge(STYLE_CODES).freeze
def append_to_escape_sequence(code)
@escape_sequence ||= []
@escape_sequence << code
self
end
def current_escape_sequence
return "" if @escape_sequence.nil?
"\033[#{@escape_sequence.join(";")}m"
end
def reset_escape_sequence!
@escape_sequence = nil
end
CODES.each do |name, code|
define_singleton_method(name) do
append_to_escape_sequence(code)
end
end
def to_s
return "" unless $stdout.tty?
current_escape_sequence
ensure
reset_escape_sequence!
end
end