あ伊藤です.「めざせサイン本」大会(ちがう?)に参加ということで...

TeX の makeindex と同じことをするプログラム idx2ind です.

利点:
  目次のスタイルが選べる.

欠点:
  階層的な目次に(まだ)対応していない.

--_
ITO  Akinori at YAMAGATA UNIVERSITY
伊藤 彰則       山形     大学

#!/usr/local/bin/ruby

# remove DAKUTEN
DAKU_TBL = {
  "が" => "か",
  "ぎ" => "き",
  "ぐ" => "く",
  "げ" => "け",
  "ご" => "こ",
  "ざ" => "さ",
  "じ" => "し",
  "ず" => "す",
  "ぜ" => "せ",
  "ぞ" => "そ",
  "だ" => "た",
  "ぢ" => "ち",
  "づ" => "つ",
  "で" => "て",
  "ど" => "と",
  "ば" => "は",
  "び" => "ひ",
  "ぶ" => "ふ",
  "べ" => "へ",
  "ぼ" => "ほ",
  "ぱ" => "は",
  "ぴ" => "ひ",
  "ぷ" => "ふ",
  "ぺ" => "へ",
  "ぽ" => "ほ",
}

def remove_daku(s)
  res = []
  i = 0
  while i < s.size
    if s[i] < 128 then # single byte char
      res.push s[i,1]
      i += 1
    else
      wc = s[i,2]
      if DAKU_TBL.key?(wc) then
        res.push DAKU_TBL[wc]
      else
        res.push wc
      end
      i += 2
    end
  end
  res.join('')
end

def print_item_for_letter(keywords,letter,style)
  print "\\hfil {\\Large\\dg\\bf #{letter}}\\hfill\n"
  h = keywords[letter]
  for yomi in h.keys.sort
    z = h[yomi]
    for keyword in z.keys
      case style
      when :plain
        print "\\item ",keyword,",",z[keyword].sort.join(","),"\n"
      when :dotfill
        print "\\item ",keyword,"\\dotfill ",z[keyword].sort.join(","),"\n"
      when :fill
        print "\\item ",keyword,"\\hfill ",z[keyword].sort.join(","),"\n"
      end
    end
  end
end

#----------------------------MAIN-------------------------
# command line argument: idx2ind filename[.idx]

style = :plain
while /^-/ =~ ARGV[0]
  case ARGV[0]
  when "-plain" then
    style = :plain
  when "-dotfill" then
    style = :dotfill
  when "-fill" then
    style = :fill
  else
    STDERR.print "usage: idx2ind [options] filename[.idx]\n"
    STDERR.print "options: -plain      item page,page style (default)\n"
    STDERR.print "         -dotfill    item ...... page,page style\n"
    STDERR.print "         -fill       item        page,page style\n"
    exit(1)
  end
  ARGV.shift
end

keywords = {}
SYMBOL = "記号"

while gets
  keyword = nil
  page = nil
  if /\\indexentry\{(.*)\}\{(.*)\}/ then
    keyword = $1
    page = $2
  else
    next
  end
  keyword_yomi = nil
  if keyword =~ /.@/ then
    keyword_yomi,keyword = keyword.split(/@/)
  else
    keyword_yomi = keyword
  end
  first_char = keyword_yomi[0]
  first_letter = nil
  if 32 <= first_char && first_char <= 126 then
    # 1-byte character
    first_letter = keyword_yomi[0,1].upcase
    unless first_letter =~ /[A-Z]/ then
      # symbol
      first_letter = SYMBOL
    end
  else
    # 2-byte character
    first_letter = remove_daku(keyword_yomi[0,2])
  end
  keyword_yomi = remove_daku(keyword_yomi.upcase)
  h = nil
  if keywords.key?(first_letter) then
    h = keywords[first_letter]
  else
    h = {}
    keywords[first_letter] = h
  end
  if h.key?(keyword_yomi) then
    z = h[keyword_yomi]
    if z.key?(keyword) then
      z[keyword].push(page)
    else
      h[keyword_yomi] = {keyword => [page]}
    end
  else
    h[keyword_yomi] = {keyword => [page]}
  end
end

print "\\begin{theindex}\n"
first = TRUE
if keywords.key?(SYMBOL) then
  print_item_for_letter(keywords,SYMBOL,style)
  first = FALSE
  keywords.delete(SYMBOL)
end
for letter in keywords.keys.sort {
     |a,b| 
     x = (a[0] <=> b[0])
     if x == 0 then a <=> b else x end
  }
  if first then
    first = FALSE
  else
    print "\\indexspace\n"
  end
  print_item_for_letter(keywords,letter,style)
end
print "\\end{theindex}\n"