here.rb
hyuki さんが id:hyuki:20060601#here で、公開されている here.pl を ruby に移植してみました。自分の記憶力と迂闊さを考慮して、ちょっと余分に機能を付け足しています。
もしよかったらお使いください。
無保証、無サポート。
使い方
- 必要なもの: Windows, ruby実行環境
- 下準備
- 下にある here.rb のコードをコピーして "here.rb" と名前を付けて保存する。
- "here.bat" という名前で下に示した内容(ディレクトリは自分の here.rb が置いてある場所に適宜変更)のバッチファイルを作り、path の通ったディレクトリに置く。*1
- here.rb が生成するバッチファイルを置くためのディレクトリを作り、そこに path を通す。*2 here.bat を置いてあるディレクトリに here という名前のディレクトリを作ると覚えやすいと思われる。
- here.rb 内の定数 Batch_dir の値を上で新たに作った生成バッチファイル置き場のディレクトリに書き換える。
here.bat
@echo off ruby -Ks c:\rb_cmd\here.rb %*
- here.rb の動作
- 基本的には here.pl と同じ。コマンドプロンプト上で任意のディレクトリで here hoge と打ち込むと、Batch_dir で指定されたディレクトリに、現在いるディレクトリに戻ってくるためのバッチファイル hoge.bat が生成される。その Batch_dir で指定されたディレクトリに path が通っていれば、以降 hoge と打ち込めばそのディレクトリへ移動する。
- 同じ名前のファイルが既にあった場合、上書きしてよいか尋ねてくるので、y/n で許可/キャンセルを行なう。
- here.rb は存在すれば第2引数も取る事ができ "here hoge テスト用" などとすれば、バッチファイルに覚書用のコメントを入れることができる。
- 引数無しで実行すると、現在あるファイルの一覧を表示する。
- オプション -p str (str は任意の文字列)で str で始まるファイルの一覧を表示する。同様に -d str で str で始まる名前のディレクトリを指すファイルの一覧を表示する。
- 表示は我が家用に作ってあるため、改行が乱れて見にくくなる事があるかもしれません。その場合 here.rb 中の Visible, Project_code_width 等の定数の値を適当な大きさに書き換えて下さい。
(「続きを読む」以下に here.rb 本体のコードがあります)
here.rb
# # here.rb # here.pl の ruby への移植版 # require "optparse" # ↓自分のバッチファイル生成場所に変更して下さい。 # path を通すのを忘れないで下さい。 Batch_dir = "c:/bat/here/" # command line option 解析部 options = Hash.new parser = OptionParser.new parser.banner = "Usage:\there.rb project-code [note]\n\there.rb option [str]" parser.separator("") parser.on("-p [str]", "\"str\"で始まる procect-code を持つバッチの一覧を表示"){|arg| options[:p] = arg } parser.on("-d [str]", "\"str\"で始まるディレクトリを指すバッチの一覧を表示"){|arg| options[:d] = arg } parser.parse! # このスクリプトの主目的機能。 # 引数の 0 番目の要素の値を名前とするバッチファイルを作る。 # 引数に 1 番目の要素があれば、バッチファイルにコメントとして書き込む。 def make_bat( args ) chdir = Dir.pwd File.open(Batch_dir + args[0] + ".bat", "w"){|file| file.puts("@echo off") file.puts("REM here_note: #{args[1]}") if args[1] file.puts("pushd #{chdir.gsub!(/\//, "\\")}") } end def dialogue( args ) unless File.exist?(filename = Batch_dir + args[0] + ".bat") make_bat(args) else print "同じ project-code が存在します。\n\n" puts "#{filename}" overlap_pr = Projects.new([Projects.parse_info(filename)]) overlap_pr.show_self begin print "上書きしますか? [y/n] " ans = $stdin.gets.chomp! end until ans == "y" || ans == "n" case ans when "y" make_bat(args) puts "上書きしました。" overlap_pr = Projects.new([Projects.parse_info(filename)]) overlap_pr.show_self exit when "n" puts "中止しました。" exit end end end # here.rb 用バッチファイルの集まりを表すクラス class Projects def initialize( ary ) @list = ary.dup end def collect_project_code( str ) pr_list = @list.find_all{|project| /^#{str}.*/ =~ project[:project_code]} Projects.new(pr_list.sort_by{|project| project[:project_code]}) end def collect_destination_dir( str ) pr_list = @list.find_all{|project| /^#{str}.*/ =~ File.basename(project[:destination_dir])} Projects.new(pr_list.sort_by{|project| project[:destination_dir]}) end # Project_code_width: プロジェクトコードの表示幅。 Project_code_width = 10 # Visible: 表示するには長すぎるパス名を切り詰めるための定数。 # パス名の頭と尻尾がそれぞれこの数字分出力される。 Visible = 23 def show_self #scale_len = 8; scale = "" #1.upto(scale_len){|i| scale << (" "*9 + i.to_s)} # #puts "#{scale}" #puts "1234567890" * scale_len display_len = 2 * Visible + 5 @list.each{|pr| pr_code = pr[:project_code] d_d_name = pr[:destination_dir] if d_d_name.length > display_len last = d_d_name.length name_head = d_d_name[0...Visible] snip_str = d_d_name[Visible...-(Visible)] name_tail = d_d_name[-Visible...last] # ディレクトリの深さが分かるように、省略されたパス名の中の"\"数を数える。 if 0 < b_slash = snip_str.count("\\") d_d_name = name_head + "[..#{b_slash.to_s}]" + name_tail else d_d_name = name_head + "....." + name_tail end end note = pr[:note] ? "# " + pr[:note] : "" display_str = pr_code.ljust(Project_code_width) + d_d_name.ljust(display_len + 2) + note puts "#{display_str}" } end # 以下 2つのクラスメソッドで here.rb 用バッチファイルから、 # project-code, そのバッチが指す行き先のディレクトリ, 覚え書き # の情報を取り出し、Projects のインスタンスを生成する。 def Projects.list_from_dir( dir ) list = [] Dir.glob(dir + "*.bat"){|file_name| list << Projects.parse_info(file_name) } return Projects.new(list) end def Projects.parse_info( file_name ) info = {:project_code => File.basename(file_name, ".bat")} File.open(file_name){|file| file.readlines.each{|line| case line when /pushd\s*/ info[:destination_dir] = $'.chomp! when /REM\shere_note:\s*/i info[:note] = $'.chomp! end } } return info end end if options.empty? if ARGV.empty? Projects.list_from_dir(Batch_dir).show_self #puts parser.help else dialogue(ARGV) end else pj_list = Projects.list_from_dir(Batch_dir) if options.has_key?(:p) pj_ini_chr = options[:p] || "" pj_list.collect_project_code(pj_ini_chr).show_self else dest_ini_chr = options[:d] || "" pj_list.collect_destination_dir(dest_ini_chr).show_self end end