Skip to content

Instantly share code, notes, and snippets.

@takkkun
Created March 16, 2012 02:51
Show Gist options
  • Save takkkun/2048256 to your computer and use it in GitHub Desktop.
Save takkkun/2048256 to your computer and use it in GitHub Desktop.
alc.co.jp cli (enja, jaen)
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
require 'nokogiri'
require 'stringio'
require 'open-uri'
begin
require 'rainbow'
rescue LoadError
class String
def color(*args)
self
end
end
end
class Buffer < StringIO
WIDTH = `tput cols`.to_i
def print(body = '', indent = 0)
super format(body, indent)
end
def puts(body = '', indent = 0)
super format(body, indent)
end
private
def format(body, indent)
index = 0
lines = []
space = ''
while index < body.length
size = measure(body, index, WIDTH - space.size)
lines << space + body[index, size]
index += size
space = ' ' * indent if space.empty?
end
lines.join("\n")
end
def measure(string, index, length)
end_index = index
size = 0
while string[end_index] && size < length
size += charsize(string[end_index])
end_index += 1
end
end_index -= 1 if size >= length
end_index - index
end
def charsize(char)
char.ord < 256 ? 1 : 2
end
end
HEAD = ' ' * 2
LIST_HEAD = ' ' * 4 + '* '
abort 'Usage: alc (en-word|ja-word)'.color(:red) if ARGV.empty?
def lookup(query, buffer = Buffer.new)
content = open("http://eow.alc.co.jp/#{URI.encode query}/UTF-8/")
document = Nokogiri::HTML(content)
word = document.css('#resultsList > ul > li:nth-child(1)')
heading = word.css('span.midashi').first
if word.empty? || heading.text != query
variation = document.css('.sas > strong > a')
abort "alc: '#{query}' did not match any word.".color(:red) if variation.empty?
buffer.print("#{query} => ")
return lookup(variation.first.text, buffer)
end
detail = word.css('div').text
readings = [
/【発音】([^【]+)/ =~ detail ? $1.gsub(/、$/, '') : nil,
/【@】([^【]+)/ =~ detail ? $1.gsub(/、$/, '') : nil
].compact
buffer.print(heading.text.color(:green))
buffer.print(" (#{readings.join(', ')})") unless readings.empty?
buffer.puts()
elements = word.css('span.wordclass, ol, ul')
if elements.empty?
buffer.puts(HEAD + detail, HEAD.size)
else
elements.each do |element|
case element.name.downcase
when 'span'
buffer.puts(HEAD + element.text.color(:cyan), HEAD.size)
when 'ol', 'ul'
items = element.css('li').empty? ? [element] : element.children
items.each {|item| buffer.puts(LIST_HEAD + item, LIST_HEAD.size)}
end
end
end
buffer
end
puts lookup(ARGV.first.downcase).string
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment