127 lines
2.4 KiB
Ruby
Raw Normal View History

2020-10-10 14:16:11 +02:00
# typed: true
# frozen_string_literal: true
2020-08-09 02:59:35 +02:00
# Various helper functions for interacting with TTYs.
#
# @api private
2016-08-26 16:04:47 +02:00
module Tty
2020-10-10 15:42:30 +02:00
include Kernel
extend T::Sig
2020-09-17 04:18:13 +05:30
@stream = $stdout
2016-08-26 16:04:47 +02:00
module_function
2020-10-10 15:42:30 +02:00
sig { params(stream: IO, _block: T.proc.params(arg0: IO).void).void }
def with(stream, &_block)
2020-09-17 04:18:13 +05:30
previous_stream = @stream
@stream = stream
yield stream
ensure
@stream = previous_stream
end
2020-10-10 15:42:30 +02:00
sig { params(string: String).returns(String) }
2016-08-26 16:04:47 +02:00
def strip_ansi(string)
string.gsub(/\033\[\d+(;\d+)*m/, "")
end
2020-10-10 15:42:30 +02:00
sig { returns(Integer) }
2016-08-26 16:04:47 +02:00
def width
@width ||= begin
2018-09-17 19:44:12 +02:00
_, width = `/bin/stty size 2>/dev/null`.split
width, = `/usr/bin/tput cols 2>/dev/null`.split if width.to_i.zero?
width ||= 80
width.to_i
end
2016-08-26 16:04:47 +02:00
end
2020-10-10 15:42:30 +02:00
sig { params(string: String).returns(String) }
2016-08-26 16:04:47 +02:00
def truncate(string)
2020-10-10 15:42:30 +02:00
(w = width).zero? ? string.to_s : (string.to_s[0, w - 4] || "")
2016-08-26 16:04:47 +02:00
end
COLOR_CODES = {
2018-11-02 17:18:07 +00:00
red: 31,
green: 32,
yellow: 33,
blue: 34,
2016-08-26 16:04:47 +02:00
magenta: 35,
2018-11-02 17:18:07 +00:00
cyan: 36,
2016-08-26 16:04:47 +02:00
default: 39,
}.freeze
STYLE_CODES = {
2018-11-02 17:18:07 +00:00
reset: 0,
bold: 1,
italic: 3,
underline: 4,
2016-08-26 16:04:47 +02:00
strikethrough: 9,
2018-11-02 17:18:07 +00:00
no_underline: 24,
2016-08-26 16:04:47 +02:00
}.freeze
SPECIAL_CODES = {
up: "1A",
down: "1B",
right: "1C",
left: "1D",
erase_line: "K",
erase_char: "P",
}.freeze
2016-08-26 16:04:47 +02:00
CODES = COLOR_CODES.merge(STYLE_CODES).freeze
2020-10-10 15:42:30 +02:00
sig { params(code: Integer).returns(T.self_type) }
2016-08-26 16:04:47 +02:00
def append_to_escape_sequence(code)
@escape_sequence ||= []
@escape_sequence << code
self
end
2020-10-10 15:42:30 +02:00
sig { returns(String) }
2016-08-26 16:04:47 +02:00
def current_escape_sequence
return "" if @escape_sequence.nil?
2018-09-17 02:45:00 +02:00
2016-08-26 16:04:47 +02:00
"\033[#{@escape_sequence.join(";")}m"
end
2020-10-10 15:42:30 +02:00
sig { void }
2016-08-26 16:04:47 +02:00
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
SPECIAL_CODES.each do |name, code|
define_singleton_method(name) do
if @stream.tty?
"\033[#{code}"
else
""
end
end
end
2020-10-10 15:42:30 +02:00
sig { returns(String) }
2016-08-26 16:04:47 +02:00
def to_s
2019-10-04 09:17:44 +02:00
return "" unless color?
2018-09-17 02:45:00 +02:00
2016-08-26 16:04:47 +02:00
current_escape_sequence
ensure
reset_escape_sequence!
end
2019-10-04 09:17:44 +02:00
2020-10-10 15:42:30 +02:00
sig { returns(T::Boolean) }
2019-10-04 09:17:44 +02:00
def color?
2020-04-05 15:44:50 +01:00
return false if Homebrew::EnvConfig.no_color?
return true if Homebrew::EnvConfig.color?
2019-10-04 09:17:44 +02:00
2020-09-17 04:18:13 +05:30
@stream.tty?
2019-10-04 09:17:44 +02:00
end
2016-08-26 16:04:47 +02:00
end