Hatena::Groupkakisute

g5nの書き殴り

2007-12-13

コマンドラインで twitter から自分のタイムラインをとってくる

05:18 |  コマンドラインで twitter から自分のタイムラインをとってくる - g5nの書き殴り を含むブックマーク はてなブックマーク -  コマンドラインで twitter から自分のタイムラインをとってくる - g5nの書き殴り

時刻を知りたくてつくった。だいたい3時間まえとかいわれてもうれしくない。

twitteer-archive.rb

require "rubygems"
require "twitter"
require "date"

def getpass(prompt = "Password: ")
  begin
    STDERR.print prompt
    system "stty -echo"
    passwd = readline.chomp
  ensure
    system "stty echo"
  end
  STDERR.puts
  return passwd
end

STDERR.print("Login: ")
login = gets.chomp
passwd = getpass
twit = Twitter::Base.new(login, passwd)
twit.timeline(:user).reverse.each{|m|
  time = DateTime.parse(m.created_at).new_offset(Rational(9,24))
  text = m.text.gsub(/&#(\d+);/){[$1.to_i].pack("U*")}
  printf("%s %s\n", time.strftime("%H:%M"), text);
}

日本語のIMAPフォルダ名のデコード

16:38 |  日本語のIMAPフォルダ名のデコード - g5nの書き殴り を含むブックマーク はてなブックマーク -  日本語のIMAPフォルダ名のデコード - g5nの書き殴り

% ruby -r net/imap -e 'puts Net::IMAP.decode_utf7("&hAwwSAAK-")'

ここにいたる道筋

考えたことなかったので、最初 Courier imapd に依存してるかと思って次のようにぐぐった

  • courier imapd フォルダ名 日本語

そしたら次のヒントが検索結果に

フォルダ名の国際化はRFCで決まってるお

そこで rfc 2060 を見に行った。

% rfc 2060

どうも modified UTF-7 というらしい(5.1.3. Mailbox International Naming Convention)。

つぎに imap.rb を grep した。

% grep utf7 /usr/local/lib/ruby/1.8/net/imap.rb
    # mailbox names to and from utf7.
    def self.decode_utf7(s)
    def self.encode_utf7(s)
%

おお、Net::IMAP.decode_utf7 というのがあるよ。偉いよ shugo さん。

JasonGuabsJasonGuabs2017/01/25 04:19печать брошюр http://wkrolik.com.ua/products/katalog

2007-12-11

MeCabで分かたれるカタカナ語を探す

22:20 | MeCabで分かたれるカタカナ語を探す - g5nの書き殴り を含むブックマーク はてなブックマーク - MeCabで分かたれるカタカナ語を探す - g5nの書き殴り

namazu.cgi は検索時に wakati.c を使い、カタカナを分かたない。そのためインデックスされてる語と異なるので引っかからないことが多い。wakati.c にパッチをあてるという手もあるけど、Namazuアップグレードが面倒になるので、辞書登録がいいと判断。で、とりあえず、辞書登録すべき単語の候補を拾い上げるという作業が必要だったのでやってみた。

namazu-wakati-miss.rb

#! ruby -Ke

require "nkf"
require "MeCab"

mecab = MeCab::Tagger.new("-Owakati")

a = NKF.nkf("-Ew", "")
n = NKF.nkf("-Ew", "")
_ = NKF.nkf("-Ew", "")

words = Hash.new(0)
Dir["**/*.html"].each{|f|
  File.read(f).scan(/[#{a}-#{n}#{_}]+/u).each{|w|
    words[w] += 1
  }
}

words.keys.map{|w| NKF.nkf("-We", w)}.sort.each{|w|
  if w.size > 1 and words[NKF.nkf("-Ew", w)] > 2
    wakati = mecab.parse(w).strip
    puts(w != wakati ? "#{words[NKF.nkf("-Ew", w)]} #{w} [#{wakati}]" : w)
  end
}

こういうのを2分くらいで書ければいいんだがMeCabの使い方を調べてたら10分くらいかかった。

2007-12-10

rollover.js改

01:38 | rollover.js改 - g5nの書き殴り を含むブックマーク はてなブックマーク - rollover.js改 - g5nの書き殴り

rel 属性にロールオーバー用の画像を指定できたほうがいいという話が出たのでしてみた。

使い方

<head>
  <!-- ... -->
  <script type="text/javascript" src="prototype.js"></script>
  <script type="text/javascript" src="rollover.js"></script>
  <!-- ... -->
</head>
<body>
  <!-- ... -->

  <a class="rollover" rel="rollover[../img/over.gif]"><img src="../img/default.gif"></a>

  <!-- ... -->

rollover.js

var preloaded_images = $A();

function init_rollover()
{
  var toggle = function(img, original, another){
    return function(){
      if (img.src == original) {
        img.src = another;
      } else {
        img.src = original;
      }
    }
  };

  var preload = function(img, another){
    var holder = new Image();
    holder.src = another;
    preloaded_images.push(holder);
  };

  var buttons = $$('.rollover');

  buttons.each(function(button){
    var img = button.getElementsByTagName("img")[0];
    var rel = button.readAttribute("rel");
    if(img){
      var another = "";
      var original = img.src;
      if (rel && rel.match(/rollover\[(.*)\]/)) {
        another = RegExp.$1;
      } else {
        if (img.src.match(/_on\./)){
          another = img.src.sub(/_on\.(png|gif|jpg)$/, "_off.#{1}");
        } else {
          another = img.src.sub(/_off\.(png|gif|jpg)$/, "_on.#{1}");
        }
      };

      preload(img, another);
      button.onmouseover = toggle(img, original, another);
      button.onfocus = toggle(img, original, another);
      button.onmouseout = toggle(img, original, another);
      button.onblur = toggle(img, original, another);
    }
  });
}

Event.observe(window, "load", init_rollover, false);

2007-12-04

ヘディングのレベルだけ抜き出すワンライナー

21:11 |  ヘディングのレベルだけ抜き出すワンライナー - g5nの書き殴り を含むブックマーク はてなブックマーク -  ヘディングのレベルだけ抜き出すワンライナー - g5nの書き殴り

HTMLshift_jis で書かれてるとして。HTMLコメントの中にあるヘディングは無視するとして。

% ruby -Ks -e 'require "rubygems"; require "hpricot"; ARGV.map{|f| p [f, Hpricot(File.read(f)).search("h1,h2,h3,h4,h5,h6").map{|i| i.name[/\d/].to_i}]}' ./**/*.htm ./**/*.html

インデントしてみた。

#! ruby -Ks
require "rubygems"
require "hpricot"
ARGV.map{|f| 
  p [f, Hpricot(File.read(f)).search("h1,h2,h3,h4,h5,h6").map{|i| i.name[/\d/].to_i}]
}

detect-heading-gap.rb - ヘディングレベルのギャップを探す

21:51 |  detect-heading-gap.rb - ヘディングレベルのギャップを探す - g5nの書き殴り を含むブックマーク はてなブックマーク -  detect-heading-gap.rb - ヘディングレベルのギャップを探す - g5nの書き殴り

NGと判定される条件

  • h1 から始まらない
  • ヘディングレベルが直前より2以上大きいことがある
#! ruby -Ks
require "rubygems"
require "hpricot"
ng = []
ARGV.each{|f|
  heading = Hpricot(File.read(f)).search("h1,h2,h3,h4,h5,h6")
  result = "."
  prev = nil

  trace = []
  heading.each_with_index{|i,k|

    lv = i.name[/\d/].to_i
    case k
    when 0
      if lv != 1
        result = "X"
        trace << "x"
      end
    else
      if prev - lv > 1
        result = "X"
        trace << "x"
      end
    end
    trace << lv
    prev = lv
  }
  v = [result, f, trace.join(" ")].join(" ")
  puts v
  if result != "."
    ng << v
  end
}
if !ng.empty?
  puts "--"
  puts "NG: #{ng.size} files NG of #{ARGV.size}"
  put ng
else
  puts "--"
  puts "OK: All #{ARGV.size} files good"
end

2007-11-29

行の集合演算をするワンライナー

11:52 |  行の集合演算をするワンライナー - g5nの書き殴り を含むブックマーク はてなブックマーク -  行の集合演算をするワンライナー - g5nの書き殴り

a.txt にファイルパスのリストがあった。そのうち、疑わしいものを b.txt に入れて分かる人に投げたら、b.txt のうち c.txt の部分以外は不要という回答があった。さて、a.txt で生き残るのはどれか。ただし、見易さのために空行が含まれている。

行末をWindows形式にするのに nkf -Lw をつかった。

golfer がどう書くのか、あるいは同じことを MS Office しか使えない人がどうするのかは気になるところ。

% ruby -e '
    a,b,c = ARGV.map{|i| 
      File.read(i).scan(/\S+/)
    }; 
    puts a - (b - c)
  ' [a-c].txt | 
  sort | nkf -Lw > a-b+c.txt

なお、じっさいには、ファイルパスはあるウェブサイトの DocumentRoot からのパスであり、分かる人に b.txt を投げるときに確認しやすいように、a.txt の各行頭に http://example.com を付加したので、それを消すということをやった。

% ruby -e '
    a,b,c = ARGV.map{|i| 
      File.read(i).scan(/\S+/).map{|j| 
        j.sub("http://example.com", "")
      }
    };
    puts a - (b - c)
  ' [a-c].txt | 
  sort | nkf -Lw > a-d+n.txt

ここに書くとき、上のドメイン名の置き換えみたいなのがめんどくさいんだよなあ。これがなかったらコピペで終わるんだけど。