SHARE
TWEET

Untitled

a guest Oct 23rd, 2019 130 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # encoding: utf-8
  2.  
  3. if defined?(Encoding) then
  4.   Encoding.default_external = 'utf-8'
  5.   Encoding.default_internal = 'utf-8'
  6. else
  7.   $KCODE = 'utf-8'
  8. end
  9. ENV["LANG"] = 'en_US.UTF-8'
  10.  
  11. begin
  12.   # Compatibility stuff
  13.   unless IRB.conf[:AT_EXIT]
  14.     IRB.conf[:AT_EXIT] = []
  15.     Kernel.at_exit do
  16.       IRB.conf[:AT_EXIT].each do |hook|
  17.         hook.call
  18.       end
  19.     end
  20.   end
  21.  
  22.   ## Some stuff I commonly use
  23.   # Ok, I usually hate that and prefer plain requires, but due to begin/rescue for each of it, I'll do it this way
  24.   %w[
  25.     pp
  26.     awesome_print
  27.     yaml
  28.     enumerator
  29.     readline
  30.   ].each do |path|
  31.     begin
  32.       require path
  33.     rescue LoadError
  34.       warn "Failed to load #{path.inspect} in #{__FILE__}:#{__LINE__-2}" if $VERBOSE
  35.     end
  36.   end
  37.  
  38.  
  39.  
  40.   module IRBUtilities; module_function
  41.     MethodMethod          = Object.instance_method(:method)
  42.     MethodInstanceMethod  = Module.instance_method(:instance_method)
  43.     MethodIsA             = Object.instance_method(:is_a?)
  44.     MethodIsDescendant    = Module.instance_method(:<)
  45.  
  46.     def self._method(obj, *args, &block)
  47.       MethodMethod.bind(obj).call(*args, &block)
  48.     end
  49.  
  50.     def self._instance_method(obj, *args, &block)
  51.       MethodInstanceMethod.bind(obj).call(*args, &block)
  52.     end
  53.  
  54.     def self._is_a?(obj, klass)
  55.       MethodIsA.bind(obj).call(klass)
  56.     end
  57.  
  58.     def self._is_descendant?(obj, klass)
  59.       MethodIsDescendant.bind(obj).call(klass)
  60.     end
  61.  
  62.     def pretty_print_methods(obj, meths)
  63.       descs = meths.map { |n, m|
  64.         i = 0
  65.         params = m.parameters.map { |type, name|
  66.           case type
  67.             when :req then name || "arg#{i+=1}"
  68.             when :opt then "#{name || "arg#{i+=1}"}=?"
  69.             when :rest then "*#{name || "rest"}"
  70.             when :block then "&#{name || "block"}"
  71.             else "??"
  72.           end
  73.         }
  74.         ["  #{n}(#{params.join(", ")})", m.source_location ? m.source_location.join(':') : '[native]']
  75.       }
  76.       width = descs.map { |a,b| a.size }.max
  77.       descs.each do |a,b|
  78.         $stdout.printf "%-*s %s\n", width, a, b
  79.       end
  80.  
  81.       descs.size
  82.     end
  83.   end
  84.  
  85.  
  86.  
  87.   ## Load history
  88.   module IRBHistory
  89.     @history_file           = File.expand_path('~/.irb_session_history')
  90.     @max_sessions           = 20
  91.     @max_lines_per_session  = 1000
  92.     @max_lines              = 10000
  93.     @sessions               = {}
  94.     @history                = []
  95.     @current_history        = nil
  96.  
  97.     @current_wd             = File.expand_path('.')
  98.     @current_ruby           = "#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}-#{RUBY_VERSION}".gsub(/\s+/, '_')
  99.     @current_ppid           = Process.ppid
  100.     @current_key            = [@current_ppid, @current_wd, @current_ruby]
  101.  
  102.     class <<self
  103.       attr_reader :sessions, :history_file, :history, :current_history
  104.       attr_reader :max_sessions, :max_lines_per_session, :max_lines
  105.       attr_reader :current_wd, :current_ruby, :current_ppid, :current_key
  106.     end
  107.  
  108.     def self.push(line)
  109.       @current_history.push([Time.now.to_i, line])
  110.       @current_history.shift if @current_history.length > @max_lines
  111.     end
  112.  
  113.     def self.restore
  114.       read_history_log
  115.       restore_history
  116.       restore_readline_history
  117.     end
  118.  
  119.     def self.read_history_log
  120.       sessions          = {}
  121.       lost              = []
  122.  
  123.       current           = lost
  124.       if File.exist?(@history_file) then
  125.         File.foreach(@history_file).each_with_index do |line, line_no|
  126.           if /^\# session time=(\d+), ppid=(\d+), ruby=(\S+), cwd=(.*)$/ =~ line then
  127.             time, ppid, ruby, cwd = $1, $2, $3, $4
  128.             current.replace(current.first(@max_lines_per_session)) # truncate array
  129.             time        = time.to_i
  130.             ppid        = ppid.to_i
  131.             current     = []
  132.             session_key = [ppid, cwd, ruby]
  133.             sessions[session_key] = [time, current]
  134.           elsif /^(\d+) (.*)$/ =~ line then
  135.             time, code = $1, $2
  136.             current << [time.to_i, code]
  137.           else
  138.             warn "Malformed line #{line_no+1}: #{line.inspect}"
  139.           end
  140.         end
  141.         warn "#{lost.size} log lines without session" unless lost.empty?
  142.         current.replace(current.first(@max_lines_per_session)) # truncate array
  143.       end
  144.  
  145.       sessions[@current_key] ||= [Time.now.to_i, []]
  146.       sorted            = sessions.sort_by { |key, (time, lines)| time }
  147.       @sessions         = Hash[sorted.last(@max_sessions)]
  148.       @current_history  = @sessions[@current_key] ? @sessions[@current_key].last : []
  149.       nil
  150.     end
  151.  
  152.     def self.restore_history
  153.       @history  = []
  154.       @sessions.sort_by { |(ppid, cwd, ruby), (time, lines)|
  155.         [
  156.           ppid == @current_ppid ? 1 : 0,    # matching ppid later (latest means first in history)
  157.           cwd  == @current_wd ? 1 : 0,      # matching working directory later
  158.           time                              # newer ones later
  159.         ]
  160. #      }.select { |(ppid, cwd, ruby), (time, lines)|
  161. #        ruby == @current_ruby
  162.       }.each do |(ppid, cwd, ruby), (time, lines)|
  163.         @history.concat(lines)
  164.       end
  165.       @history.replace(@history.first(@max_lines)) # truncate
  166.     end
  167.  
  168.     def self.restore_readline_history
  169.       Readline::HISTORY.clear
  170.       Readline::HISTORY.push(*@history.map(&:last))
  171.     end
  172.  
  173.     def self.save
  174.       return unless @current_history
  175.       save_history = @current_history.first(@max_lines_per_session)
  176.       @sessions.replace({@current_key => [Time.now.to_i, save_history]}.merge(@sessions))
  177.       File.open(@history_file, 'a+:binary') do |fh|
  178.         fh.flock(File::LOCK_EX)
  179.         fh.truncate(0)
  180.         @sessions.each do |(ppid, cwd, ruby), (time, lines)|
  181.           fh.puts "\# session time=#{time}, ppid=#{ppid}, ruby=#{ruby}, cwd=#{cwd}"
  182.           lines.each do |line_time, line|
  183.             fh.puts("#{line_time} #{line}")
  184.           end
  185.         end
  186.       end
  187.     end
  188.  
  189.     # utility function
  190.     def self.sort_hash_by!(hash, &block)
  191.       hash.replace(Hash[hash.sort_by(&block)])
  192.     end
  193.   end
  194.  
  195.   if defined? Readline then
  196.     # Compat
  197.     unless Readline::HISTORY.respond_to? :clear
  198.       hist = Readline::HISTORY
  199.       def hist.clear
  200.         length.times do pop end
  201.       end
  202.     end
  203.     IRBHistory.restore
  204.     IRB.conf[:AT_EXIT] << proc { IRBHistory.save }
  205.  
  206.     module IRB
  207.       begin
  208.         require "readline"
  209.         ::NBSP = "\302\240"
  210.         require 'irb/completion'
  211.         class ReadlineInputMethod < InputMethod
  212.           def gets
  213.             if l = readline(@prompt, false)
  214.               l.gsub!(/\302\240/, "") # this line does the trick - it's for poor swiss people who have {|} on opt-<key> combo, which means that pressing opt too early or releasing it too late you generate a non-breaking space (opt-space) which causes a syntax error
  215.               HISTORY.push(l) unless l.empty?
  216.               IRBHistory.push(l)
  217.               @line[@line_no += 1] = "#{l}\n"
  218.             else
  219.               @eof = true
  220.               l
  221.             end
  222.           end
  223.         end
  224.         Readline.completion_append_character = ""
  225.       rescue LoadError
  226.       end
  227.     end
  228.   end
  229.  
  230.  
  231.  
  232.   ## A couple of core patches to make life in IRB a little bit nicer
  233.   alias q exit
  234.  
  235.   module OriginalInspect
  236.     def irb_inspect
  237.       inspect
  238.     end
  239.  
  240.     def self.wrap(klass)
  241.       klass.class_eval do
  242.         alias original_inspect inspect
  243.  
  244.         def inspect
  245.           r = original_inspect
  246.           r.extend OriginalInspect
  247.           r
  248.         end
  249.       end
  250.     end
  251.   end
  252.   class Object
  253.     def eigenclass
  254.       class<<self;self;end
  255.     end
  256.     def eigendef(*a,&b)
  257.       eigenclass.send(:define_method, *a, &b)
  258.     end
  259.     def __m
  260.       meths  = methods-Object.instance_methods
  261.       meths -= Enumerable.instance_methods if IRBUtilities._is_a?(self, Enumerable)
  262.  
  263.       meths.sort
  264.     end
  265.     if Method.method_defined? :parameters then
  266.       def __mx
  267.         IRBUtilities.pretty_print_methods(self, __m.map { |m| [m, IRBUtilities._method(self, m)] })
  268.       end
  269.     else
  270.       def __mx
  271.         warn "__mx requires Method#parameters"
  272.         __m
  273.       end
  274.     end
  275.     def i
  276.       $stdout.puts inspect
  277.       self
  278.     end
  279.     def ii
  280.       $stdout.puts pretty_inspect
  281.       self
  282.     end
  283.     def irb_inspect
  284.       original = inspect
  285.       if original.length > 100 then
  286.         $stdout.sprintf "#<%p %s>", self.class, instance_variables.join(" ")
  287.       else
  288.         original
  289.       end
  290.     rescue
  291.       "<<could not inspect object>>"
  292.     end
  293.   end
  294.   class Module
  295.     def __im
  296.       meths  = instance_methods-Object.instance_methods
  297.       meths -= Enumerable.instance_methods if IRBUtilities._is_descendant?(self, Enumerable)
  298.  
  299.       meths.sort
  300.     end
  301.     if Method.method_defined? :parameters then
  302.       def __imx
  303.         IRBUtilities.pretty_print_methods(self, __im.map { |m| [m, IRBUtilities._instance_method(self, m)] })
  304.       end
  305.     else
  306.       def __imx
  307.         warn "__imx requires Method#parameters"
  308.         __im
  309.       end
  310.     end
  311.     def __m
  312.       if self.equal?(Module)
  313.         super
  314.       else
  315.         meths  = methods-Module.methods
  316.         meths -= Enumerable.instance_methods if IRBUtilities._is_a?(self, Enumerable)
  317.  
  318.         meths.sort
  319.       end
  320.     end
  321.   end
  322.   class String
  323.     # Convenience method, see Regexp#show_match
  324.     def show_match(regex)
  325.       regex.show_match(self)
  326.     end
  327.  
  328.     OriginalInspect.wrap(self)
  329. #     def irb_inspect
  330. #       if length <= 100 then
  331. #         original_inspect
  332. #       else
  333. #         sub(/\A(.{89}).*(.{10})/m, '\1…\2').original_inspect
  334. #       end
  335. #     end
  336.   end
  337.   class Array
  338.     OriginalInspect.wrap(self)
  339.     def irb_inspect
  340.       if size <= 100 then
  341.         "[#{map(&:irb_inspect).join(', ')}]"
  342.       else
  343.         "[#{first(89).map(&:irb_inspect).join(', ')}, …, #{last(10).map(&:irb_inspect).join(', ')}]"
  344.       end
  345.     end
  346.   end
  347.   class Hash
  348.     OriginalInspect.wrap(self)
  349.     def irb_inspect
  350.       if size <= 100 then
  351.         "{#{map{|k,v| "#{k.irb_inspect} => #{v.irb_inspect}"}.join(', ')}}"
  352.       else
  353.         ary = to_a
  354.         "{#{ary.first(89).map{|k,v| "#{k.irb_inspect} => #{v.irb_inspect}"}.join(', ')}, …, " \
  355.         "#{ary.last(10).map{|k,v| "#{k.irb_inspect} => #{v.irb_inspect}"}.join(', ')}}"
  356.       end
  357.     end
  358.   end
  359.   module Enumerable
  360.     def __m
  361.       (methods-Object.methods-Enumerable.instance_methods).sort
  362.     end
  363.   end
  364.   module Kernel
  365.   module_function
  366.     # Prints memory and cpu footprint of the server (uses ps in a subshell,
  367.     # portability is therefore limited)
  368.     def print_resource_usage
  369.       ps_out = `ps -o vsz,rss,%cpu,%mem -p #{$$}`
  370.       vsz, rss, cpu, pmem = ps_out.scan(/\d+(?:[.,]\d+)?/).map { |e| e.gsub(/,/,'.').to_f } # ps on 10.5.1 outputs ',' instead of '.' for MEM%
  371.       virtual, real = (vsz-rss).div(1024), rss.div(1024)
  372.       $stdout.printf "%dMB real, %dMB virtual, %.1f%% CPU, %.1f%% MEM\n", real, virtual, cpu, pmem
  373.     end
  374.  
  375.     # Terminate the current process - the hard way
  376.     def t!
  377.       `kill -9 #{$$}`
  378.     end
  379.  
  380.     # write data to a file
  381.     def putf(content, path='~/Desktop/irb_dump.txt')
  382.       File.open(File.expand_path(path), 'w') { |fh| fh.write(content) }
  383.     end
  384.  
  385.     # tiny bench method
  386.     def bench(n=100, runs=10)
  387.       n = n.to_i
  388.       t = []
  389.       runs.times do
  390.         a = Time.now
  391.         for i in 1..n
  392.           yield
  393.         end
  394.         t << (Time.now-a)*1000/n
  395.       end
  396.       mean   = t.inject { |a,b| a+b }.quo(t.size)
  397.       stddev = t.map { |a| (a-mean)**2 }.inject { |a,b| a+b }.quo(t.size)**0.5
  398.       [mean, stddev]
  399.     end
  400.  
  401.     # tiny bench method with nice printing
  402.     def pbench(n=1, runs=5, &b)
  403.       m, s = *bench(n,runs,&b)
  404.       p    = (100.0*s)/m
  405.       $stdout.printf "ø %fms (%.1f%%)\n", m, p
  406.     end
  407.  
  408.     # tiny bench method with nice printing,
  409.     # runs multiple tests
  410.     def mbench(n, runs, benches)
  411.       label_width = benches.keys.max_by(&:length).length+1
  412.       measures    = []
  413.       benches.each do |label, b|
  414.         m, s     = *bench(n,runs,&b)
  415.         p        = (100.0*s)/m
  416.         measures << [label, m]
  417.         $stdout.printf "%-*s ø %fms (%.1f%%)\n", label_width, "#{label}:", m, p
  418.       end
  419.  
  420.       measures.sort_by! { |l,m| m }
  421.       rel = measures.first.last
  422.       $stdout.puts measures.map { |l,m| sprintf "%s: %.1f", l, m/rel }.join(', ')
  423.       nil
  424.     end
  425.  
  426.     module PasswordString
  427.       def inspect; "[PASSWORD]"; end
  428.       def to_s; "[PASSWORD]"; end
  429.       def dup; obj=super;obj.extend PasswordString; obj; end
  430.       def clone; obj=super;obj.extend PasswordString; obj; end
  431.     end
  432.  
  433.     def password
  434.       `stty -echo`
  435.       r = gets.chomp
  436.       r.extend PasswordString
  437.       r
  438.     ensure
  439.       `stty echo`
  440.     end
  441.     alias secret password
  442.  
  443.     # 1.9's p/pp return the arguments -> sucks in irb. let it return nil again.
  444.     def p(*args)
  445.       puts(args.map{|a|a.inspect})
  446.       nil
  447.     end
  448.     def pp(*args)
  449.       PP.pp(*args)
  450.       nil
  451.     end
  452.  
  453.     # Invoke an original method on an object that possibly overrides, fakes or removes it
  454.     # Example:
  455.     #   cm some_obj, :inspect, Object
  456.     #   Object.instance_method(:inspect).bind(some_obj).call # is what that does
  457.     def cm(obj, meth, klass=Object)
  458.       klass.instance_method(meth).bind(obj).call
  459.     end
  460.   end
  461.  
  462.   class Regexp
  463.     # Convenience method on Regexp so you can do
  464.     # /an/.show_match("banana") # => "b<<an>>ana"
  465.     def show_match(str)
  466.       self =~ str
  467.  
  468.       "#{$`}<<#{$&}>>#{$'}"
  469.     end
  470.   end
  471.  
  472.  
  473.   # Support methods for beedit
  474.   require 'shellwords'
  475.   module ::BBedit
  476.     def self.open(obj)
  477.       case obj
  478.         when ::String
  479.           `bbedit #{obj.shellescape}`
  480.         when ::Method, ::UnboundMethod
  481.           file, line = obj.source_location
  482.           if file && File.readable?(file) then
  483.             `bbedit #{file.shellescape}:#{line}`
  484.           else
  485.             "Can't open native method"
  486.           end
  487.       end
  488.     end
  489.   end
  490.   module ::Sublime
  491.     def self.open(obj)
  492.       case obj
  493.         when ::String
  494.           `subl #{obj.shellescape}`
  495.         when ::Method, ::UnboundMethod
  496.           file, line = obj.source_location
  497.           if file && File.readable?(file) then
  498.             `subl #{file.shellescape}:#{line}`
  499.           else
  500.             "Can't open native method"
  501.           end
  502.       end
  503.     end
  504.   end
  505.   class ::Method
  506.     def bbedit
  507.       BBedit.open(self)
  508.     end
  509.     def subl
  510.       Sublime.open(self)
  511.     end
  512.   end
  513.   class ::UnboundMethod
  514.     def bbedit
  515.       BBedit.open(self)
  516.     end
  517.     def subl
  518.       Sublime.open(self)
  519.     end
  520.   end
  521.   class ::Object
  522.     def bbedit(name)
  523.       method(name).bbedit
  524.     end
  525.     def subl(name)
  526.       method(name).subl
  527.     end
  528.   end
  529.  
  530.  
  531.  
  532.   ## Configure IRB
  533.   ruby                    = ENV["rvm_ruby_string"] || "#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'}-#{RUBY_VERSION}"
  534.   prompt                  = {
  535.     :PROMPT_I     => "\001\e[42m\002 \001\e[0m\002 #{ruby}:%03n:%i>> ",  # default prompt
  536.     :PROMPT_S     => "\001\e[42m\002 \001\e[0m\002 #{ruby}:%03n:%i%l> ", # known continuation
  537.     :PROMPT_C     => "\001\e[42m\002 \001\e[0m\002 #{ruby}:%03n:%i>> ",
  538.     :PROMPT_N     => "\001\e[42m\002 \001\e[0m\002 #{ruby}:%03n:%i*> ",  # unknown continuation
  539.     :RETURN       => "\001\e[42m\002 \001\e[0m\002 # => %s\n",
  540.   }
  541.   #IRB.conf[:INSPECT_MODE]     = "{ |obj| obj.irb_inspect }" # use that code to generate the reply-line
  542.   IRB.conf[:INSPECT_MODE]     = :inspect
  543.   IRB.conf.delete(:AUTO_INDENT) # irb checks for presence, not content... stupid
  544.   IRB.conf[:PROMPT][:APEIROS] = prompt
  545.   IRB.conf[:PROMPT_MODE]      = :APEIROS
  546.  
  547.   ## Load railsrc
  548.   if defined?(Rails) then
  549.     rails_rc = File.expand_path('~/.railsrc')
  550.     load rails_rc if File.exist?(rails_rc)
  551.   end
  552.  
  553. rescue => e
  554.   $stdout.puts e, *e.backtrace.first(5)
  555. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top