spirit_hands 2.0.8-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.gitignore +17 -0
- data/.pryrc +1 -0
- data/.ruby-gemset +1 -0
- data/CHANGELOG.md +147 -0
- data/CONTRIBUTING.md +18 -0
- data/CONTRIBUTORS.md +10 -0
- data/Gemfile +3 -0
- data/LICENSE.md +22 -0
- data/README.md +138 -0
- data/Rakefile +127 -0
- data/gem-public_cert.pem +32 -0
- data/lib/spirit_hands/hirb/fixes/enabled.rb +36 -0
- data/lib/spirit_hands/hirb/fixes/pager.rb +144 -0
- data/lib/spirit_hands/hirb/fixes/util.rb +19 -0
- data/lib/spirit_hands/hirb/fixes/view.rb +10 -0
- data/lib/spirit_hands/hirb/fixes.rb +5 -0
- data/lib/spirit_hands/hirb.rb +2 -0
- data/lib/spirit_hands/mattr_accessor_with_default.rb +44 -0
- data/lib/spirit_hands/melody.rb +24 -0
- data/lib/spirit_hands/options/color.rb +10 -0
- data/lib/spirit_hands/options/hirb.rb +34 -0
- data/lib/spirit_hands/options/less/colorize.rb +41 -0
- data/lib/spirit_hands/options/less/show_raw_unicode.rb +36 -0
- data/lib/spirit_hands/options/less.rb +2 -0
- data/lib/spirit_hands/options.rb +59 -0
- data/lib/spirit_hands/print.rb +75 -0
- data/lib/spirit_hands/prompt/base/render.rb +231 -0
- data/lib/spirit_hands/prompt/base.rb +24 -0
- data/lib/spirit_hands/prompt/main.rb +18 -0
- data/lib/spirit_hands/prompt/multiline.rb +17 -0
- data/lib/spirit_hands/prompt.rb +12 -0
- data/lib/spirit_hands/railtie.rb +7 -0
- data/lib/spirit_hands/terminal.rb +16 -0
- data/lib/spirit_hands/version.rb +3 -0
- data/lib/spirit_hands.rb +21 -0
- data/spirit_hands.gemspec +42 -0
- data.tar.gz.sig +0 -0
- metadata +239 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
# Fixes pager_command
|
2
|
+
require 'hirb'
|
3
|
+
require 'shellwords'
|
4
|
+
|
5
|
+
module Hirb
|
6
|
+
# This class provides class methods for paging and an object which can conditionally page given a terminal size that is exceeded.
|
7
|
+
class Pager
|
8
|
+
class << self
|
9
|
+
# Pages using a configured or detected shell command.
|
10
|
+
def command_pager(output, options={})
|
11
|
+
if valid_pager_command?(pc = options[:pager_command])
|
12
|
+
basic_pager(output, pc)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Exposed to allow user-custom, external-driven formatting
|
17
|
+
def basic_pager(output, override_pager_command=nil)
|
18
|
+
pc = basic_pager_command(override_pager_command)
|
19
|
+
pager = IO.popen(pc, "w")
|
20
|
+
begin
|
21
|
+
save_stdout = STDOUT.clone
|
22
|
+
STDOUT.reopen(pager)
|
23
|
+
STDOUT.puts output
|
24
|
+
rescue Errno::EPIPE
|
25
|
+
ensure
|
26
|
+
STDOUT.reopen(save_stdout)
|
27
|
+
save_stdout.close
|
28
|
+
pager.close
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def pager_command=(*commands) #:nodoc:
|
33
|
+
@pager_command = pager_command_select(*commands)
|
34
|
+
end
|
35
|
+
|
36
|
+
def pager_command #:nodoc:
|
37
|
+
@pager_command || pager_command_select
|
38
|
+
end
|
39
|
+
|
40
|
+
# Pages with a ruby-only pager which either pages or quits.
|
41
|
+
def default_pager(output, options={})
|
42
|
+
pager = new(options[:width], options[:height])
|
43
|
+
while pager.activated_by?(output, options[:inspect])
|
44
|
+
puts pager.slice!(output, options[:inspect])
|
45
|
+
return unless continue_paging?
|
46
|
+
end
|
47
|
+
puts output
|
48
|
+
puts "=== Pager finished. ==="
|
49
|
+
end
|
50
|
+
|
51
|
+
def page(string, inspect_mode, pgr_cmd, width, height)
|
52
|
+
if valid_pager_command?(pgr_cmd)
|
53
|
+
command_pager(string, :pager_command=>pgr_cmd)
|
54
|
+
else
|
55
|
+
default_pager(string, :width=>width, :height=>height, :inspect=>inspect_mode)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
#:stopdoc:
|
62
|
+
def valid_pager_command?(cmd)
|
63
|
+
cmd && Util.command_exists?(cmd.shellsplit[0])
|
64
|
+
end
|
65
|
+
|
66
|
+
# Default pager commands to try
|
67
|
+
def pager_command_fallbacks #:nodoc:
|
68
|
+
candidates = %w[less more pager cat]
|
69
|
+
candidates.unshift ENV['PAGER'] if ENV['PAGER']
|
70
|
+
candidates
|
71
|
+
end
|
72
|
+
|
73
|
+
# Pick the first valid command from commands
|
74
|
+
def pager_command_select(*commands)
|
75
|
+
commands += pager_command_fallbacks
|
76
|
+
commands.flatten.compact.uniq.find { |c| valid_pager_command? c }
|
77
|
+
end
|
78
|
+
|
79
|
+
# Actual command basic_pager needs to perform
|
80
|
+
def basic_pager_command(override_pager_command)
|
81
|
+
if valid_pager_command?(override_pager_command)
|
82
|
+
override_pager_command
|
83
|
+
else
|
84
|
+
pager_command
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def continue_paging?
|
89
|
+
puts "=== Press enter/return to continue or q to quit: ==="
|
90
|
+
!$stdin.gets.chomp[/q/i]
|
91
|
+
end
|
92
|
+
#:startdoc:
|
93
|
+
end # class methods
|
94
|
+
|
95
|
+
attr_reader :width, :height, :options
|
96
|
+
|
97
|
+
def initialize(width, height, options={})
|
98
|
+
resize(width, height)
|
99
|
+
@options = options
|
100
|
+
end
|
101
|
+
|
102
|
+
def pager_command
|
103
|
+
options[:pager_command] || self.class.pager_command
|
104
|
+
end
|
105
|
+
|
106
|
+
# Pages given string using configured pager.
|
107
|
+
def page(string, inspect_mode)
|
108
|
+
self.class.page(string, inspect_mode, pager_command, @width, @height)
|
109
|
+
end
|
110
|
+
|
111
|
+
def slice!(output, inspect_mode=false) #:nodoc:
|
112
|
+
effective_height = @height - 2 # takes into account pager prompt
|
113
|
+
if inspect_mode
|
114
|
+
sliced_output = String.slice(output, 0, @width * effective_height)
|
115
|
+
output.replace String.slice(output, char_count(sliced_output), String.size(output))
|
116
|
+
sliced_output
|
117
|
+
else
|
118
|
+
# could use output.scan(/[^\n]*\n?/) instead of split
|
119
|
+
sliced_output = output.split("\n").slice(0, effective_height).join("\n")
|
120
|
+
output.replace output.split("\n").slice(effective_height..-1).join("\n")
|
121
|
+
sliced_output
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Determines if string should be paged based on configured width and height.
|
126
|
+
def activated_by?(string_to_page, inspect_mode=false)
|
127
|
+
inspect_mode ? (String.size(string_to_page) > @height * @width) : (string_to_page.count("\n") > @height)
|
128
|
+
end
|
129
|
+
|
130
|
+
if String.method_defined? :chars
|
131
|
+
def char_count(string) #:nodoc:
|
132
|
+
string.chars.count
|
133
|
+
end
|
134
|
+
else
|
135
|
+
def char_count(string) #:nodoc:
|
136
|
+
String.size(string)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def resize(width, height) #:nodoc:
|
141
|
+
@width, @height = View.determine_terminal_size(width, height)
|
142
|
+
end
|
143
|
+
end # Pager
|
144
|
+
end # Hirb
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'hirb'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
class << Hirb::Util
|
5
|
+
# Determines if a shell command exists by searching for it in ENV['PATH'].
|
6
|
+
# (Fixed version)
|
7
|
+
def command_exists?(command)
|
8
|
+
if c = Pathname.new(command)
|
9
|
+
return true if c.absolute? && c.exist?
|
10
|
+
end
|
11
|
+
executable_file_exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
12
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).any? do |d|
|
13
|
+
executable_file_exts.any? do |ext|
|
14
|
+
f = File.expand_path(command + ext, d)
|
15
|
+
File.executable?(f) && !File.directory?(f)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end # Hirb::Util.self
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Integrate Hirb + SpiritHands print output (AwesomePrint / inspect)
|
2
|
+
require 'hirb'
|
3
|
+
require 'spirit_hands'
|
4
|
+
|
5
|
+
class << Hirb::View
|
6
|
+
def view_or_page_output(str)
|
7
|
+
view_output(str) ||
|
8
|
+
page_output(::SpiritHands::Print.pretty(str), true)
|
9
|
+
end
|
10
|
+
end # Hirb::View.self
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Module
|
2
|
+
def mattr_accessor_with_default(property, default = nil, &block)
|
3
|
+
if block_given?
|
4
|
+
if default
|
5
|
+
raise ArgumentError, 'Must specify only one of +default+ or &block'
|
6
|
+
end
|
7
|
+
default = block
|
8
|
+
end
|
9
|
+
|
10
|
+
getter = property.to_sym
|
11
|
+
setter = "#{property}=".to_sym
|
12
|
+
class_var = "@@#{property}".to_sym
|
13
|
+
|
14
|
+
# self.property=
|
15
|
+
define_singleton_method(setter) do |value|
|
16
|
+
if value.nil?
|
17
|
+
remove_class_variable(class_var)
|
18
|
+
else
|
19
|
+
class_variable_set(class_var, value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# self.property
|
24
|
+
if default.respond_to?(:call) # default is callable
|
25
|
+
define_singleton_method(getter) do
|
26
|
+
if class_variable_defined?(class_var)
|
27
|
+
class_variable_get(class_var)
|
28
|
+
else
|
29
|
+
default.()
|
30
|
+
end
|
31
|
+
end
|
32
|
+
else # default is literal object
|
33
|
+
default_value_name = "DEFAULT_#{property}".upcase.to_sym
|
34
|
+
const_set(default_value_name, default)
|
35
|
+
define_singleton_method(getter) do
|
36
|
+
if class_variable_defined?(class_var)
|
37
|
+
class_variable_get(class_var)
|
38
|
+
else
|
39
|
+
const_get(default_value_name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end # Module
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
3
|
+
class << SpiritHands
|
4
|
+
# This modifies pry to play our tune
|
5
|
+
def melody!(app = nil)
|
6
|
+
return false if @installed
|
7
|
+
@installed = true
|
8
|
+
|
9
|
+
SpiritHands.app = app unless app.nil?
|
10
|
+
setup_less_colorize
|
11
|
+
setup_less_show_raw_unicode
|
12
|
+
setup_hirb
|
13
|
+
|
14
|
+
# Use awesome_print for output, but keep pry's pager. If Hirb is
|
15
|
+
# enabled, try printing with it first.
|
16
|
+
::SpiritHands::Print.install!
|
17
|
+
|
18
|
+
# Friendlier prompt - line number, app name, nesting levels look like
|
19
|
+
# directory paths.
|
20
|
+
#
|
21
|
+
# Configuration (like Pry.color) can be changed later or even during console usage.
|
22
|
+
::SpiritHands::Prompt.install!
|
23
|
+
end
|
24
|
+
end # SpiritHands.self
|
@@ -0,0 +1,34 @@
|
|
1
|
+
autoload :Hirb, 'spirit_hands/hirb'
|
2
|
+
|
3
|
+
module SpiritHands
|
4
|
+
class << self
|
5
|
+
# Is hirb enabled?
|
6
|
+
def hirb
|
7
|
+
::Hirb.enabled?
|
8
|
+
end
|
9
|
+
|
10
|
+
# Set whether hirb is enabled (default: true)
|
11
|
+
def hirb=(h)
|
12
|
+
h = DEFAULT_HIRB if h.nil?
|
13
|
+
if hirb != h
|
14
|
+
if h
|
15
|
+
::Hirb.enable
|
16
|
+
else
|
17
|
+
::Hirb.disable
|
18
|
+
end
|
19
|
+
end
|
20
|
+
@hirb = !!h
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def setup_hirb
|
26
|
+
self.hirb = nil unless @hirb
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
DEFAULT_HIRB = true
|
31
|
+
|
32
|
+
# Whether to use hirb/unicode when hirb is enabled (default: true)
|
33
|
+
mattr_accessor_with_default :hirb_unicode, true
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module SpiritHands
|
4
|
+
DEFAULT_LESS_COLORIZE = true
|
5
|
+
LESS_R_LONG = '--RAW-CONTROL-CHARS'.freeze
|
6
|
+
LESS_R = /\A(.*-[^-R]*)R(.*)\z/.freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Allow less to display colorized output (default: true)
|
11
|
+
# (If, set updates LESS env var)
|
12
|
+
def less_colorize
|
13
|
+
ENV['LESS'].to_s.shellsplit.any? { |arg| arg == LESS_R_LONG || arg =~ LESS_R }
|
14
|
+
end
|
15
|
+
|
16
|
+
# true: add -R to LESS env var (default)
|
17
|
+
# false: remove -R from LESS env var
|
18
|
+
# nil: set to default (true)
|
19
|
+
def less_colorize=(n)
|
20
|
+
n = DEFAULT_LESS_COLORIZE if n.nil?
|
21
|
+
|
22
|
+
args = ENV['LESS'].to_s.shellsplit.map do |arg|
|
23
|
+
next if arg == LESS_R_LONG
|
24
|
+
if arg =~ LESS_R
|
25
|
+
arg = $1 + $2
|
26
|
+
end
|
27
|
+
arg unless arg.empty?
|
28
|
+
end
|
29
|
+
args << '-R' if n
|
30
|
+
new_less = args.collect.to_a.shelljoin
|
31
|
+
ENV['LESS'] = new_less.empty? ? nil : new_less
|
32
|
+
@less_colorize = !!n
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def setup_less_colorize
|
38
|
+
self.less_colorize = nil unless @less_colorize
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module SpiritHands
|
4
|
+
DEFAULT_LESS_SHOW_RAW_UNICODE = true
|
5
|
+
LESS_SHOW_RAW_BINFMT = '*n%c'.freeze
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Allow less to display colorized output (default: true)
|
9
|
+
# (If, set updates LESS env var)
|
10
|
+
def less_show_raw_unicode
|
11
|
+
ENV['LESSUTFBINFMT'] == LESS_SHOW_RAW_BINFMT
|
12
|
+
end
|
13
|
+
|
14
|
+
# true: set LESSUTFBINFMT to %*c
|
15
|
+
# false: unset LESSUTFBINFMT
|
16
|
+
# String: set custom LESSUTFBINFMT
|
17
|
+
# nil: set default(true)
|
18
|
+
def less_show_raw_unicode=(n)
|
19
|
+
n = DEFAULT_LESS_SHOW_RAW_UNICODE if n.nil?
|
20
|
+
ENV['LESSUTFBINFMT'] = if n.is_a?(String)
|
21
|
+
n
|
22
|
+
elsif n
|
23
|
+
LESS_SHOW_RAW_BINFMT
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
@less_show_raw_unicode = !!n
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def setup_less_show_raw_unicode
|
33
|
+
self.less_show_raw_unicode = nil unless @less_show_raw_unicode
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'readline'
|
3
|
+
require 'spirit_hands/mattr_accessor_with_default'
|
4
|
+
require 'spirit_hands/options/color'
|
5
|
+
require 'spirit_hands/options/less'
|
6
|
+
require 'spirit_hands/options/hirb'
|
7
|
+
|
8
|
+
module SpiritHands
|
9
|
+
### Options ###
|
10
|
+
|
11
|
+
# When printing values, start with this (default: '=> ')
|
12
|
+
mattr_accessor_with_default :value_prompt, '=> '
|
13
|
+
|
14
|
+
# Spaces to indent value (default: 2 spaces)
|
15
|
+
mattr_accessor_with_default :value_indent, 2
|
16
|
+
|
17
|
+
# Name of the app, which can be displayed to <app/> tag in prompt
|
18
|
+
mattr_accessor_with_default :app, -> {
|
19
|
+
if defined?(::Rails)
|
20
|
+
::Rails.application
|
21
|
+
else
|
22
|
+
# Trumpet emoji or pry
|
23
|
+
(Terminal.unicode?) ? "\u{1F3BA}" : 'pry'
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
# <color>...</color>
|
28
|
+
# <bold>...</color>
|
29
|
+
# <cmd/> command number
|
30
|
+
# <app/> SpiritHands.app, which can be String or a Rails Applicatino object
|
31
|
+
# <sep/> SpiritHands.prompt_separator
|
32
|
+
#
|
33
|
+
# Use \ to escape literal <, so in a Ruby string constant, "\\<"
|
34
|
+
#
|
35
|
+
mattr_accessor_with_default :prompt,
|
36
|
+
'<b>[<cmd/>]</b> <blue><app/></blue><tgt/> <red><sep/></red> '
|
37
|
+
|
38
|
+
# Color the prompt?
|
39
|
+
#
|
40
|
+
# A different setting than Pry.color since some may like colored output, but a
|
41
|
+
# plain prompt.
|
42
|
+
#
|
43
|
+
# Default: 'true' for GNU readline or rb-readline which correctly count line
|
44
|
+
# widths with color codes when using \001 and \002 hints. 'false' for
|
45
|
+
# libedit-based wrapper (standard on OS X unless ruby is explicitly compiled
|
46
|
+
# otherwise).
|
47
|
+
mattr_accessor_with_default :colored_prompt, -> { ::Readline::VERSION !~ /EditLine/ }
|
48
|
+
|
49
|
+
# Separator between application name and input in the prompt.
|
50
|
+
#
|
51
|
+
# Default: right angle quote (chevron) or >
|
52
|
+
#
|
53
|
+
mattr_accessor_with_default :prompt_separator, -> {
|
54
|
+
(Terminal.unicode?) ? "\u{BB}" : '>'
|
55
|
+
}
|
56
|
+
|
57
|
+
# Enable or disable AwesomePrint (default: true)
|
58
|
+
mattr_accessor_with_default :awesome_print, true
|
59
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module SpiritHands
|
2
|
+
module Print
|
3
|
+
class << self
|
4
|
+
PRINT_FUNCTION = ->(_output, value, _pry_) do
|
5
|
+
::SpiritHands::Print.print(_output, value, _pry_)
|
6
|
+
end
|
7
|
+
|
8
|
+
def install!
|
9
|
+
::Pry.config.print = PRINT_FUNCTION
|
10
|
+
end
|
11
|
+
|
12
|
+
def pretty(value)
|
13
|
+
if ::SpiritHands.awesome_print
|
14
|
+
require 'awesome_print' unless defined?(AwesomePrint)
|
15
|
+
opts = { :indent => ::SpiritHands.value_indent }
|
16
|
+
opts[:plain] = true if !SpiritHands.color
|
17
|
+
value.ai(opts)
|
18
|
+
else
|
19
|
+
value.inspect
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def hirb_unicode_enabled?
|
24
|
+
::Hirb::Formatter.dynamic_config.keys.any? do |key|
|
25
|
+
if opts = ::Hirb::Formatter.dynamic_config[key][:options]
|
26
|
+
opts && opts[:unicode]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def print(_output, value, _pry_)
|
32
|
+
if ::Hirb.enabled?
|
33
|
+
setup_hirb_unicode
|
34
|
+
return if ::Hirb::View.view_or_page_output(value)
|
35
|
+
end
|
36
|
+
_pry_.pager.open do |pager|
|
37
|
+
pager.print ::SpiritHands.value_prompt
|
38
|
+
pager.puts pretty(value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def hirb_unicode_enable
|
45
|
+
return false unless ::SpiritHands::Terminal.unicode?
|
46
|
+
require 'hirb/unicode'
|
47
|
+
|
48
|
+
::Hirb::Formatter.dynamic_config.keys.each do |key|
|
49
|
+
::Hirb::Formatter.dynamic_config[key][:options] ||= {}
|
50
|
+
::Hirb::Formatter.dynamic_config[key][:options][:unicode] = true
|
51
|
+
end
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def hirb_unicode_disable
|
56
|
+
::Hirb::Formatter.dynamic_config.keys.each do |key|
|
57
|
+
::Hirb::Formatter.dynamic_config[key][:options] ||= {}
|
58
|
+
::Hirb::Formatter.dynamic_config[key][:options][:unicode] = false
|
59
|
+
end
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup_hirb_unicode
|
64
|
+
if hirb_unicode_enabled? != SpiritHands.hirb_unicode
|
65
|
+
if SpiritHands.hirb_unicode
|
66
|
+
hirb_unicode_enable
|
67
|
+
else
|
68
|
+
hirb_unicode_disable
|
69
|
+
end
|
70
|
+
end
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
end # self
|
74
|
+
end # Print
|
75
|
+
end # SpiritHands
|