LoginSignup
5
6

More than 5 years have passed since last update.

pryでまあまあ簡単に複数行の履歴のコピー、編集を行う

Posted at

不便

pry上で、ちょっと前に定義したメソッドを書き変えたいみたいなことがあった時、履歴を辿っていっても一行ずつしか遡れなくて不便だと思います。

例えば

[1] pry(main)> def foo
[1] pry(main)*   puts "hoge"
[1] pry(main)* end

とやってた時に履歴は ['def foo', 'puts "hoge"', 'end' ] と入ってるだけでまとめて扱えない、というか扱う方法知らない。コピーするにしてもプロンプトが邪魔だったりする。

便利

https://github.com/ToQoz/ruby-anything を入れて、~/.pryrcにこんな感じで書いておく。

begin
  require 'ruby-anything'
rescue LoadError => err
  puts "Failed to load ruby-anything."
end

def pbcopy(str)
  IO.popen('pbcopy', 'r+') { |io| io.print str }
  output.puts ">>> Copy to clipboard >>>\n#{str}"
end

Pry::Commands.create_command "copy_from_history" do
  group "Clipboard"
  description "Copy to clipboard from pry's history"

  banner <<-'BANNER'
    Usage:   copy_from_history [--head|--tail]
             copy_from_history --head N
             copy_from_history --tail N

    Copy to clipboard form history with anything interface.
  BANNER

  def options(opt)
    opt.on :H, :head,   "Select from the first N hisotry", :optional_argument => true, :as => Integer
    opt.on :T, :tail,   "Select from the last N hisotry",  :optional_argument => true, :as => Integer
  end

  def process
    history = Pry.history.to_a[0..-2]
    range = case
      when opts.present?(:head)
        0..opts[:head]
      when opts.present?(:tail)
        (-opts[:tail])..-1
      else
        -100..-1
      end
    range = (-history.size)..range.max if range.min < 0 && -range.min > history.size

    history = history[range].map.with_index { |v, i| "#{i}: #{v}" }

    min = _anything_(history).to_i
    max = _anything_(history[min..range.max]).to_i

    pbcopy history[min..max].map { |h| h.sub(/^\d*:\s/, '') }.join("\n")
  end
end
Pry::Commands.alias_command 'cp_hist', 'copy_from_history'

Pryのコマンド追加、Pry::Commands.create_commandでコマンド定義してるけど、オプション取ったりしないときは、Pry::Commands.block_commandで定義するのがシンプルで良いと思う。

https://github.com/pry/pry/wiki/Custom-commands が詳しい。

で、Pry立ち上げて、

pry(main)[1]> copy_hist --tail 50
# --- anythingっぽい感じでcopyを開始する行を選択 ---
>
0: puts "hoge"
1: def foo           # これを選択
2:   puts "hoge"
3: end
4: exit
5: copy_from_history
# --- 1を選択 ---

# 再度anythingっぽいのが立ち上がってきて、copyする最後の行を選択
>
0: def foo
1:   puts "hoge"
2: end                # これを選択
3: exit
4: copy_from_history
# --- 2を選択 ---

>>> Copy to clipboard >>>
def foo
  puts "hoge"
end
def foo
  puts "hoge"
end

がclipboardに入ったので、普通にpasteして、

[2] pry(main)> def foo
[2] pry(main)*   puts "hoge"
[2] pry(main)*   end

# エディタを開いて編集したり
[2] pry(main)> def foo
[2] pry(main)*   puts "hoge"
[2] pry(main)*   edit

# 何行目を消すとかもっと簡単な編集ならこんな感じで
# 詳しい https://github.com/pry/pry/wiki/User-Input
[2] pry(main)> def foo
[2] pry(main)*   puts "hoge"
[2] pry(main)*   amend-line 2 !
1: def foo
[2] pry(main)* end
=> nil

Macじゃないければ、pbcopyのところ適当にいじれば使えると思います。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6