Last active
November 7, 2023 06:39
-
-
Save brand-it/5299e7b9d923caa8d204e2dcf31afdc6 to your computer and use it in GitHub Desktop.
.irbrc with a bunch of stuff I found useful. This is all sort of hacky but that kinda of the point. Do what you want take what you need. no need to be perfect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
MAX_COLUMNS_FOR_TABLE = 15 unless defined?(MAX_COLUMNS_FOR_TABLE) | |
DEFAULT_EDITOR = 'code' unless defined?(DEFAULT_EDITOR) | |
class PrettyString < String | |
# https://no-color.org/ | |
NO_COLOR = ENV.key?('NO_COLOR') || `tput colors`.chomp.to_i < 8 unless defined?(NO_COLOR) | |
unless defined?(ANSI_COLORS) | |
ANSI_COLORS = { | |
red: 31, | |
green: 32, | |
yellow: 33, | |
blue: 34, | |
magenta: 35 | |
}.freeze | |
end | |
ANSI_COLORS.each do |name, code| | |
define_method(name) { NO_COLOR ? self : "\e[#{code}m#{self}\e[0m" } | |
end | |
end | |
class PrintTable | |
attr_reader :data | |
def initialize(data) | |
@data = data | |
end | |
def print | |
return false if fields.size <= 1 || fields.length > MAX_COLUMNS_FOR_TABLE || total_width > IO.console.winsize[1] | |
puts border | |
puts title_row | |
puts border | |
data_to_a.each do |item| | |
puts '| ' + fields.map { |f| format("%-#{max_len[f]}s", read_attribute(item, f)) }.join(' | ') + ' |' | |
end | |
puts border | |
puts "#{data_to_a.length} rows in set\n" | |
true | |
rescue StandardError => e | |
puts e.message | |
puts e.backtrace.join("\n") | |
false | |
end | |
private | |
# Calulate the total lenght of the table | |
def total_width | |
fields.map { |f| max_len[f] }.sum + fields.length * 3 + 1 | |
end | |
def attributes_keys(data = self.data) | |
@attributes_keys ||= if data.respond_to?(:attributes_keys) | |
data.attributes_keys | |
elsif data.respond_to?(:keys) | |
data.keys | |
elsif data.respond_to?(:attributes) && data.attributes.respond_to?(:keys) | |
data.attributes.keys | |
elsif data.respond_to?(:members) | |
data.members | |
end | |
end | |
def data_to_a | |
if data.class == Array || data.class == Enumerable | |
data | |
else | |
[data] | |
end | |
end | |
def border | |
'+-' + fields.map { |f| '-' * max_len[f] }.join('-+-') + '-+' | |
end | |
def title_row | |
'| ' + fields.map { |f| format("%-#{max_len[f]}s", PrettyString.new(f.to_s).yellow) }.join(' | ') + ' |' | |
end | |
def max_len | |
return @max_len if @max_len | |
@max_len = Hash[*fields.map { |f| [f, f.to_s.length] }.flatten] | |
data_to_a.each do |item| | |
fields.each do |field| | |
len = read_attribute(item, field).length | |
@max_len[field] = len if len > @max_len[field] | |
end | |
end | |
@max_len | |
end | |
def fields | |
@fields ||= attributes_keys || [] | |
end | |
def read_attribute(item, attribute) | |
if item.respond_to?(:read_attribute) | |
item.read_attribute(attribute).to_s | |
elsif item.respond_to?(attribute.to_sym, false) | |
item.public_send(attribute.to_sym).to_s | |
elsif item.is_a?(Hash) | |
item[attribute.to_sym].to_s || item[attribute.to_s].to_s | |
else | |
raise "Can't read attribute #{attribute} from #{item.class}" | |
end | |
end | |
end | |
puts PrettyString.new('loading .irbrc...').blue | |
require 'tempfile' | |
# /Users/brandit/.asdf/installs/ruby/3.2.1/lib/ruby/gems/3.2.0/gems/actioncable-7.0.4.2/lib | |
def require_custom(gem_name, require_name = nil) | |
@libs ||= Dir["#{File.expand_path("~/.asdf/installs/ruby/#{RUBY_VERSION}")}/**/lib"].sort | |
gems = @libs.select { _1.include?(gem_name) } | |
if gems.any? | |
gems.each { $LOAD_PATH.unshift(_1.gsub("/lib/#{gem_name}", '/lib')) } | |
puts PrettyString.new("require #{require_name || gem_name}").green | |
require require_name || gem_name | |
end | |
rescue LoadError => e | |
puts PrettyString.new(e.message).red | |
end | |
require_custom 'awesome_print' | |
require_custom 'benchmark', 'benchmark/ips' | |
require_custom 'rbzip2' | |
require_custom 'memoist' | |
require_custom 'kalibera' | |
require_custom 'json' | |
# require_custom 'hirb' | |
IRB.conf[:PROMPT][:CUSTOM_PROMPT] = { | |
PROMPT_I: "#{PrettyString.new('[%n]').green} #{PrettyString.new(Dir.pwd).blue}> ", | |
PROMPT_N: "#{PrettyString.new('[%n]').green} #{PrettyString.new(Dir.pwd).blue}> ", | |
PROMPT_S: "#{PrettyString.new('[%n]').green} #{PrettyString.new(Dir.pwd).blue}> ", | |
PROMPT_C: "#{PrettyString.new('[%n]').green} #{PrettyString.new(Dir.pwd).blue}> ", | |
RETURN: "=> %s\n" | |
} | |
if defined?(Rails) | |
env = Rails.env | |
env_color = if env.acceptance? | |
PrettyString.new(env).green | |
elsif env.staging? | |
PrettyString.new(env).yellow | |
elsif env.production? | |
PrettyString.new(env).red | |
else | |
PrettyString.new(env).blue | |
end | |
IRB.conf[:PROMPT][:RAILS_APP] = { | |
PROMPT_I: "#{PrettyString.new('[%n]').green} #{Rails.application.class.module_parent_name} (#{env_color}) > ", | |
PROMPT_N: "#{PrettyString.new('[%n]').green} #{Rails.application.class.module_parent_name} (#{env_color}) > ", | |
PROMPT_S: "#{PrettyString.new('[%n]').green} #{Rails.application.class.module_parent_name} (#{env_color}) > ", | |
PROMPT_C: "#{PrettyString.new('[%n]').green} #{Rails.application.class.module_parent_name} (#{env_color}) > ", | |
RETURN: "=> %s\n" | |
} | |
IRB.conf[:PROMPT_MODE] = :RAILS_APP | |
else | |
IRB.conf[:PROMPT_MODE] = :CUSTOM_PROMPT | |
end | |
IRB.conf[:BACK_TRACE_LIMIT] = 20 | |
# ActiveRecord::Base.logger.level = 1 if defined?(ActiveRecord) | |
IRB.conf[:SAVE_HISTORY] = 1000 | |
# IRB.conf[:USE_AUTOCOMPLETE] = false # can be slow rather use tab or lm | |
# Overriding Object class | |
class Object | |
def types | |
self.class.ancestors.select { |a| a.to_s =~ /^[A-Z]/ }.sort_by(&:to_s) | |
end | |
def named | |
respond_to?(:name) ? name : self.class | |
end | |
# Easily print methods local to an object's class | |
def lm(scan = nil) | |
sorted_methods = (methods - Object.instance_methods).sort | |
scan ? sorted_methods.select { |m| m.to_s.include?(scan.to_s) } : sorted_methods | |
end | |
# look up source location of a method | |
def sl(method_name) | |
method(method_name).source_location | |
rescue StandardError | |
"#{method_name} not found" | |
end | |
# open particular method in vs code | |
def ocode(method_name) | |
file, line = sl(method_name) | |
if file && line | |
`#{DEFAULT_EDITOR} -g '#{file}:#{line}'` | |
else | |
"'#{method_name}' not found :( Try #{named}.lm to see available methods" | |
end | |
end | |
# display method source in rails console | |
def ds(method_name) | |
method(method_name).source.display | |
end | |
# open json object in VS Code Editor | |
def oj | |
file = Tempfile.new([named.to_s, '.json']) | |
file.write(JSON.pretty_generate(as_json)) | |
file.close | |
system("#{DEFAULT_EDITOR} #{file.path}") | |
rescue NoMethodError => e | |
puts PrettyString.new("Can't open #{named} because it doesn't respond to #as_json").red | |
end | |
end | |
# history command | |
def hist(count = 0) | |
# Get history into an array | |
history_array = Reline::HISTORY.to_a | |
# if count is > 0 we'll use it. | |
# otherwise set it to 0 | |
count = count.positive? ? count : 0 | |
if count.positive? | |
from = history_array.length - count | |
history_array = history_array[from..] | |
end | |
history_array | |
end | |
# copy a string to the clipboard | |
def cp(string) | |
`echo "#{string}" | pbcopy` | |
puts 'copied in clipboard' | |
end | |
# reloads the irb console can be useful for debugging .irbrc | |
def reload_irb | |
load File.expand_path('~/.irbrc') | |
# will reload rails env if you are running ./script/console | |
reload! if @script_console_running | |
puts 'Console Reloaded!' | |
end | |
# opens irbrc in vscode | |
def edit_irb | |
`#{DEFAULT_EDITOR} ~/.irbrc` if system('code') | |
end | |
def hirb_on | |
Hirb.enable | |
end | |
def hirb_off | |
Hirb.disable | |
end | |
def disable_active_record_logging | |
ActiveRecord::Base.logger.level = 1 | |
end | |
def enable_active_record_logging | |
ActiveRecord::Base.logger.level = 0 | |
end | |
def bm | |
# From http://blog.evanweaver.com/articles/2006/12/13/benchmark/ | |
# Call benchmark { } with any block and you get the wallclock runtime | |
# as well as a percent change + or - from the last run | |
cur = Time.zone.now | |
result = yield | |
print "#{cur = Time.zone.now - cur} seconds" | |
begin | |
puts " (#{(cur / $last_benchmark * 100).to_i - 100}% change)" | |
rescue StandardError | |
puts '' | |
end | |
$last_benchmark = cur | |
result | |
end | |
module IRB | |
class Irb | |
def output_value(omit = false) # :nodoc: | |
PrintTable.new(@context.last_value).print || original_output_value(omit) | |
end | |
# pulled this code from irb source to override the output_value method | |
# https://github.com/ruby/irb/blob/457502a7468399ba3a176e5769c63a49c0e69e95/lib/irb.rb#L824 | |
def original_output_value(omit = false) # :nodoc: | |
str = @context.inspect_last_value | |
multiline_p = str.include?("\n") | |
if omit | |
winwidth = @context.io.winsize.last | |
if multiline_p | |
first_line = str.split("\n").first | |
result = @context.newline_before_multiline_output? ? (@context.return_format % first_line) : first_line | |
output_width = Reline::Unicode.calculate_width(result, true) | |
diff_size = output_width - Reline::Unicode.calculate_width(first_line, true) | |
if diff_size.positive? && (output_width > winwidth) | |
lines, = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3) | |
str = '%s...' % lines.first | |
str += "\e[0m" if Color.colorable? | |
multiline_p = false | |
else | |
str = str.gsub(/(\A.*?\n).*/m, '\\1...') | |
str += "\e[0m" if Color.colorable? | |
end | |
else | |
output_width = Reline::Unicode.calculate_width(@context.return_format % str, true) | |
diff_size = output_width - Reline::Unicode.calculate_width(str, true) | |
if diff_size.positive? && (output_width > winwidth) | |
lines, = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3) | |
str = '%s...' % lines.first | |
str += "\e[0m" if Color.colorable? | |
end | |
end | |
end | |
if multiline_p && @context.newline_before_multiline_output? | |
printf @context.return_format, "\n#{str}" | |
else | |
printf @context.return_format, str | |
end | |
end | |
end | |
end | |
# exit using `q` | |
alias q exit | |
# all available methods explaination | |
def ll | |
puts '=============================================================================================================' | |
puts 'Welcome to console. Here are few list of pre-defined methods you can use.' | |
puts '=============================================================================================================' | |
puts 'bm(&block) ------------> benchmarking for block passed as an argument e.g bm { Lead.all.pluck(:stage);0 }' | |
puts 'cp(str) ---------------> copy string in clipboard e.g cp(lead.name)' | |
puts 'edit_gemfile ----------> edit gemfile' | |
puts 'edit_irb --------------> edit irbrc file' | |
puts 'hist(n) ---------------> command history e.g hist(10)' | |
puts 'obj.dispsoc(:method) --> display method source in rails console e.g lead.dispsoc(:name)' | |
puts 'obj.ocode(:method) ----> open method in vs code e.g lead.ocode(:name)' | |
puts 'obj.oj ----------------> open object json in vs code e.g lead.oo' | |
puts 'obj.sl(:method) -------> source location e.g lead.sl(:name)' | |
puts 'obj.types -------------> list of all types' | |
puts 'reload_irb ------------> reload irb console' | |
puts '=============================================================================================================' | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment