2013 年 12 月の履歴(もしくは日誌)


2013 年 12 月

12 月 31 日

rbenv install -l でずらずら長いリストが出て困る

Ruby 2.1.0 が出ましたね.ところで rbenv install で簡単にインストールできるにしても,rbenv install -l の長いリストで新しいバージョンが加わったかどうか確認するのは面倒では無いですか? で rbenv install -l で 1.8 系や 1.9 系の最新だけをリストして,さらに rbenv versions の結果と比較してインストールされているかどうか表示するとか,そんな感じのものを ruby で書いてみました.

$ rbversion
1.8.7-p375                               
1.9.3-p484           installed           
2.0.0-p353           installed           
2.1.0                installed           
jruby-1.7.9          installed           
maglev-1.0.0         maglev-2.0.0-dev    
rbx-2.2.1            installed           
ree-1.8.7-2012.02               

最初に動けば良いって感じで書いたら,こうなりました.

#!/usr/bin/env ruby
# rbenv versions でインストールされている ruby を確認し
# rbenv install -l でインストール可能なものと比較する.-dev とか -rc とか -preview は無視する
installed = Hash.new
`rbenv versions`.split("\n").each do |line| 
       line.sub!(/^\s*\*?\s*/,'')
       line.sub!(/\s*\(.*\)$/,'')
       if line =~ /([^-]*)-(.*)/
              #
  else
    line =~ /^(2\.\d+)\.(.*)/
       end
       if $1
              installed[$1] = $2
       else 
              installed[line] = ''
       end
end
rb = nil
v = nil
pline = nil
`rbenv install -l`.split("\n").map {|line| line.sub!(/^\s*\*?\s*/,''); line}.push('').each do |line|
       next if line == "Available versions:"
       if line =~ /([^-]*)-(.*)/
              #
       else
    line =~ /^(2\.\d+)\.(.*)/
  end
       vr = $2
       if $1
              l = $1
       else
              l = line
  end
  #p [line,l,vr]
       next if vr =~ /rc|dev|preview/
       if l != rb
              if v
                     print pline
      print "    " if pline !~ /-/
                     if installed[rb]
        #p [:test,v.to_f ,installed[rb].to_f ,v.to_f > installed[rb].to_f ]
                            case
                            when v.to_f > installed[rb].to_f 
                                   print " *new* (#{installed[rb]})"
                            when v == installed[rb]
                                   print "\tinstalled"
                            else
                                   print "\t(#{installed[rb]})"
                            end
                     end
                     print "\n"
              elsif rb 
                     print "#{rb}\n"
              end
              rb = l
       end
       v = vr
  pline = line
end

いろいろ駄目だなと自分でも思います.

そしてある記事を見ました.

これをみて Enumerable#chunk って便利そう.これを使って書き直したら良くなるかも! って思ったので書き直しました.

#!/usr/bin/env ruby
# rbenv versions でインストールされている ruby を確認し
# rbenv install -l でインストール可能なものと比較する.-dev とか -rc とか -preview は無視する
pr = lambda{|line| line=~/^((\d+\.\d)|(\w+))/;$1 }
installed = `rbenv versions`.each_line.
  map {|line| line.gsub(/(^\s*\*?\s*|\s*\(.*\)$)/,'').chomp}.
  compact.chunk(&pr).to_h
available = `rbenv install -l`.each_line.
  map {|line| next if line=~/(Available versions|-dev|-rc|-preview)/; line.strip}.
  compact.chunk(&pr).to_a
available.each {|a|
  i = installed[a.first] ? installed[a.first].last : ''
  puts "%-20s %-20s" % [a.last.last, i == a.last.last ? "installed" : i]
}

これが良いのかどうか分からないけど,短くなった.

ついでに Perl でも書いてみた.Perl で Enumerable#chunk みたいなのって何かあるのかなって調べてみたけど良くわからりませんでした.

#!/usr/bin/perl
use strict;
use warnings;
my %installed;
foreach my $line (split m/\n/, `plenv versions`) {
       next if $line =~ m/^system/;
       my $test = q{};
       $line =~ s/^\s*\*?\s*//g;
       $line =~ s/\([^\)]+\)//g;
       if ($line =~ m/((^\d+\.\d+)|(^[A-Za-z]+))/ ) {
              $test = "$1";
       }
       else {
              $test = 'unknown';
       }
       if (exists $installed{$test}) {
              push($installed{$test}, $line);
       }
       else {
              $installed{$test} = [$line];
       } 
}
my %available;
my @keys = ();
foreach my $line (split m/\n/, `plenv install -l`) {
       next if $line =~ m/(Available|-RC|-TRIAL)/;
       my $test = 'unknown';
       $line =~ s/^\s*\*?\s*//g;
       if ($line =~ m/((^\d+\.\d+)|(^[A-Za-z]+))/ ) {
              $test = "$1";
       }
       if (exists $available{$test}) {
              push($available{$test}, $line);
       }
       else {
              $available{$test} = [$line];
              push @keys, $test;
       } 
}
foreach my $k (@keys) {
       my $i = exists($installed{$k}) ? $installed{$k}[-1] : q{};
       $i = $i eq $available{$k}[-1] ? "installed" : $i;
       printf("%-10s %-20s\n", $available{$k}[-1],$i);
}

http://onohiroki.cycling.jp/tb/tb.cgi/weblog_d20131231n1 TrackBack