마우스로 더블 클릭하는 미니 사전

루비와 gtk로 만든 미니 사전입니다.
찾을 단어를 마우스로 더블 클릭하여(또는 드래그하여) 선택하면 마우스 위치에 사전이 뜹니다.
사전 소스는 구글 사전입니다.(파싱하기 제일 편한 것으로 ;;:wink:
[attachment=0:2r62it8x]minidict.png[/attachment:2r62it8x]

[code:2r62it8x]
#!/usr/bin/ruby1.9.1

coding: utf-8

version: 20100911

colyright: GPL v3

author: cogniti AT gmail.com

버그

@window.present 가 올라오지(raise) 못하는 경우가 있다.

require ‘gtk2’
require ‘gtkhtml2’
require ‘net/http’

Gtk::Window

@window = Gtk::Window.new("사전")
@window.signal_connect( "destroy" ) { Gtk.main_quit }
@window.set_default_size(300, 200)
@window.opacity=0.9
@window.decorated = false
@window.accept_focus = false
#@window.keep_above = true

@window.signal_connect(‘enter-notify-event’) do
@window.decorated = true
end

Gtk::ScrolledWindow

sw = Gtk::ScrolledWindow.new(nil, nil)
sw.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)

Gtk::HtmlView

@htmlview = Gtk::HtmlView.new
@htmlview.show

add

sw.add(@htmlview)
@window.add(sw)

show

@window.show_all

Gtk::HtmlDocument

@doc = Gtk::HtmlDocument.new
@doc.open_stream(‘text/html’)
@doc.write_stream(‘<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><html><body><h3>구글 사전을 이용한 영한사전입니다.<br/> 마우스로 단어를 더블 클릭(또는 드래그)하면 그 위치에 창이 뜨고 단어가 표시됩니다.</h3></body></html>’)
@doc.close_stream()
@htmlview.document = @doc

CLIPBOARD

@clipboard = Gtk::Clipboard.get(Gdk::Selection::PRIMARY) # 선택한 문자열

@clipboard.signal_connect(‘owner-change’) do
@q = @clipboard.wait_for_text # 선택한 문자열 읽어온다.
unless @q.nil?
# 마우스 포인터 위치 읽어 온다.
x = Gdk::Window.default_root_window.pointer[1]
y = Gdk::Window.default_root_window.pointer[2]
# 마우스 작업에 방해되지 않도록 +10 해준다.
@window.move(x+10, y+10)

	dict @q
	@window&#46;decorated = false
	@window&#46;present
end

end

def convert_to_html s
s.gsub!(/<?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?>/, "")
s.gsub!(/<DictionaryPage>/, "<html>")
s.gsub!(/</DictionaryPage>/, "</html>")

s&#46;gsub!(/&lt;AvailableLanguages \/&gt;/, &quot;&quot;)

s&#46;gsub!(/&lt;result&gt;/, &quot;&lt;body&gt;&quot;)
s&#46;gsub!(/&lt;\/result&gt;/, &quot;&lt;\/body&gt;&quot;)

s&#46;gsub!(/&lt;result \/&gt;/, &quot;&quot;)

s&#46;gsub!(/&lt;primary source_language=\&quot;0\&quot;&gt;/, &quot;&lt;dl&gt;&quot;)
s&#46;gsub!(/&lt;\/primary&gt;/, &quot;&lt;\/dl&gt;&quot;)

s&#46;gsub!(/&lt;related_phrase source_language=\&quot;0\&quot;&gt;/, &quot;&lt;!-- IGNORE&quot;)
s&#46;gsub!(/&lt;\/related_phrase&gt;/, &quot;IGNORE-- &gt;&quot;)

s&#46;gsub!(/&lt;term language=\&quot;0\&quot; type=\&quot;0\&quot;&gt;/, &quot;&quot;)
s&#46;gsub!(/&lt;term language=\&quot;9\&quot; type=\&quot;1\&quot;&gt;/, &quot;&quot;)
s&#46;gsub!(/&lt;\/term&gt;/, &quot;&quot;)

s&#46;gsub!(/&lt;text&gt;/, &quot;&lt;dd&gt;&quot;)
s&#46;gsub!(/&lt;\/text&gt;/, &quot;&lt;\/dd&gt;&quot;)

s&#46;gsub!(/&lt;PronunciationGroup type=\&quot;2\&quot;&gt;/, &quot;&quot;)
s&#46;gsub!(/&lt;\/PronunciationGroup&gt;/, &quot;&quot;)

s&#46;gsub!(/&lt;dd&gt;#{@q}&lt;\/dd&gt;/, &quot;&lt;dt&gt;#{@q}&lt;/dt&gt;&quot;)

if s&#46;strip! == &quot;&lt;html&gt;\n  \n  \n&lt;/html&gt;&quot;
	&quot;찾는 단어가 없습니다&#46;&quot;
else
	s
end

end

def dict q
# | ==> %7C
uri = "http://www.google.com/dictionary/feeds?client=ig&langpair=en%7Cko&q=#{q}&hl=ko"
begin
s = Net::HTTP.get URI.parse(uri)
@result = convert_to_html(s)
@doc.open_stream(‘text/html’)
@doc.write_stream(‘<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />’)
@doc.write_stream(@result)
@doc.close_stream
rescue => e
puts e.message
end
end

Gtk.main
[/code:2r62it8x]

질문 : 사전의 source 는 무슨 사전인가요?

구글 사전이 소스입니다.

[list:2zzjfutp]
[:2zzjfutp] 영단어가 아닌경우 검색하지 않게 했습니다.[/:m:2zzjfutp]
[:2zzjfutp] convert_to_html 를 줄였습니다.[/:m:2zzjfutp]
[:2zzjfutp] 그외, 루비 문법을 이용해 코드를 줄였습니다.[/:m:2zzjfutp][/list:u:2zzjfutp]

[code:2zzjfutp]#!/usr/bin/ruby1.9.1

coding: utf-8

version: 20100911

colyright: GPL v3

author: cogniti AT gmail.com

버그

window 가 올라오지(raise) 못하는 경우가 있다. @window.present

require ‘gtk2’
require ‘gtkhtml2’
require ‘net/http’
require ‘erb’

Gtk::Window

@window = Gtk::Window.new("사전")
@window.signal_connect( "destroy" ) { Gtk.main_quit }
@window.set_default_size(300, 200)
@window.opacity=0.9
@window.decorated = false
@window.accept_focus = false
#@window.keep_above = true

@window.signal_connect(‘enter-notify-event’) do
@window.decorated = true
end

Gtk::ScrolledWindow

sw = Gtk::ScrolledWindow.new(nil, nil)
sw.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)

Gtk::HtmlView

@htmlview = Gtk::HtmlView.new
@htmlview.show

add

sw.add(@htmlview)
@window.add(sw)

show

@window.show_all

Gtk::HtmlDocument

@doc = Gtk::HtmlDocument.new
def display html
@doc.open_stream(‘text/html’)
@doc.write_stream(‘<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />’)
@doc.write_stream(html)
@doc.close_stream()
end
display ‘<html><body><h3>구글 사전을 이용한 영한사전입니다.<br/> 마우스로 단어를 드래그하면 그 위치에 창이 뜨고 단어가 표시됩니다.</h3></body></html>’
@htmlview.document = @doc

CLIPBOARD

@clipboard = Gtk::Clipboard.get(Gdk::Selection::PRIMARY) # 선택한 문자열

@clipboard.signal_connect(‘owner-change’) do
@q = @clipboard.wait_for_text.strip # 선택한 문자열 읽어온다.
if @q =~ /^[a-z]+$/i
# 마우스 포인터 위치 읽어 온다.
_, x, y = Gdk::Window.default_root_window.pointer
# 마우스 작업에 방해되지 않도록 +10 해준다.
@window.move(x+10, y+10)

dict @q
@window&#46;decorated = false
@window&#46;present

end
end

def convert_to_html s
return "찾는 단어가 없습니다." unless s =~ /<text>/

s.gsub!(%r{<related_phrase.+?</related_phrase>}m, ‘’)
word, *dds = s.scan(%r{<text>(.+?)</text>}).map { |x| x[0] }
template = ERB.new <<-EOH
<html>
<body>
<dl>
<dt><%= word %></dt>
<% dds.each { |dd| %>
<dd><%= dd %></dd>
<% } %>
</dl>
</body>
</html>
EOH
template.result binding
end

def dict q

| ==> %7C

uri = "http://www.google.com/dictionary/feeds?client=ig&langpair=en%7Cko&q=#{q}&hl=ko"
begin
s = Net::HTTP.get URI.parse(uri)
display convert_to_html(s)
rescue => e
puts e.message
end
end

Gtk.main
[/code:2zzjfutp]

xdeui님 regex 코드 개선 감사합니다.
딱 100줄 나오네요. ㅎㅎㅎ

개선한 것들

  • gtk 코드를 보기 좋게 개선했음.
  • @clipboard.signal_connect(‘owner-change’) 에서 검사 코드를 dict 로 보내버렸음.
  • uri 수정하기 편하도록 프로그램 상단부에 위치했음.(@dict_url)

할 일

  • 창이 수초 후에 자동으로 사라지게 하는 기능 추가하는 것과
  • 창이 뒤로 내려가고(lower), 가끔 앞으로 안 올라오는(raise) 버그만 해결하면 매우 편리하겠네요.
  • gtk를 더 공부해서 데스크탑의 Notification Area 에 넣어야겠습니다.

[code:3pffgmkc]
#!/usr/bin/ruby1.9.1

coding: utf-8

version: 201009111952

license: GPL v3

author: cogniti AT gmail.com

도와준 사람, xdeui님 감사합니다. def convert_to_html, def display

알려진 버그

@window.present 가 올라오지(raise) 못하는 경우가 있다.

line 같은 단어의 경우 세종류의 <dt>line</dt> tag 생성해야 함.

require ‘gtk2’
require ‘gtkhtml2’
require ‘net/http’
require ‘erb’

URI.parse 에러를 방지하기 위해 "|" ==> "%7C" 로 변경하였음.

평가 지연(lazy evaluation)을 위해 lambda 사용

@dict_uri = lambda {|q| "http://www.google.com/dictionary/feeds?client=ig&langpair=en%7Cko&q=#{q}&hl=ko"}

Gtk::HtmlDocument

@doc = Gtk::HtmlDocument.new
def display html
@doc.open_stream(‘text/html’)
@doc.write_stream(‘<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />’)
@doc.write_stream(html)
@doc.close_stream()
end
display ‘<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><html><body><h3>구글 사전을 이용한 영한사전입니다.<br/> 마우스로 단어를 더블 클릭(또는 드래그)하면 그 위치에 창이 뜨고 단어가 표시됩니다.</h3></body></html>’

Gtk::HtmlView

htmlview = Gtk::HtmlView.new
htmlview.show
htmlview.document = @doc

Gtk::ScrolledWindow

sw = Gtk::ScrolledWindow.new(nil, nil)
sw.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
sw.add(htmlview)

Gtk::Window

@window = Gtk::Window.new("사전")
@window.signal_connect("destroy") { Gtk.main_quit }
@window.signal_connect(‘enter-notify-event’) { @window.decorated = true }
@window.set_default_size(300, 200)
@window.opacity = 0.9 # 투명도
@window.decorated = false # 윈도우 장식
@window.accept_focus = false # 초점을 가지지 못하게 한다.
#@window.keep_above = true
@window.add(sw)
@window.show_all

CLIPBOARD

@clipboard = Gtk::Clipboard.get(Gdk::Selection::PRIMARY) # 선택한 문자열
@clipboard.signal_connect(‘owner-change’) do
@q = @clipboard.wait_for_text
dict @q
end

def convert_to_html s
return "찾는 단어가 없습니다." unless s =~ /<text>/

s&#46;gsub!(%r{&lt;related_phrase&#46;+?&lt;/related_phrase&gt;}m, '')
word, *dds = s&#46;scan(%r{&lt;text&gt;(&#46;+?)&lt;/text&gt;})&#46;map { |x| x&#91;0&#93; }
template = ERB&#46;new &lt;&lt;-EOH

<html>
<body>
<dl>
<dt><%= word %></dt>
<% dds.each { |dd| %>
<dd><%= dd %></dd>
<% } %>
</dl>
</body>
</html>
EOH
template.result binding
end

def dict q
return if q.nil?
q.strip!

if q =~ /^&#91;a-z&#93;+$/i # 영단어만 통과
	begin
		s = Net&#58;&#58;HTTP&#46;get URI&#46;parse(@dict_uri&#46;call q)
		display convert_to_html(s)
	rescue =&gt; e
		puts e&#46;message
	end
	# 마우스 포인터 위치 읽어 온다&#46;
	_, x, y = Gdk&#58;&#58;Window&#46;default_root_window&#46;pointer
	# 마우스 작업에 방해되지 않도록 +10 해준다&#46;
	@window&#46;move(x+10, y+10)
	@window&#46;decorated = false
	@window&#46;present
end

end

Gtk.main
[/code:3pffgmkc]

후~ 재미있게 사시는군요. :P
그런데 이거 실행은 어떻게 합니까?
/usr/bin 같은데 저장해 놓고
터미널에서
sh 파일이름 하면 되나요?
그것도 아닌 것 같구요. :roll:

소스파일 이름을 minidict.rb 라 할 때

[code:1pyuiaze]
$ ruby1.9.1 minidict.rb
또는
$ ruby minidict.rb
또는
$ chmod +x minidict.rb

다음처럼 하면 소스코드에서 첫 줄(shebang line, #!/usr/bin/ruby1.9.1)에 적어놓은 해석기(ruby1.9.1)가 소스를 실행합니다.

$ ./minidict
[/code:1pyuiaze]

ruby 가 안 깔려 있다면 루비를 설치해야 합니다.
다음처럼 하면 아마 1.8.x 버전이 설치될 겁니다.
아직 ruby1.9.x 용 ruby-gnome2 패키지가 없습니다.

[code:1pyuiaze]
sudo install ruby
sudo install libgtkhtml2-ruby
[/code:1pyuiaze]
만약 libgtkhtml2-ruby 설치가 안 되면 http://www.cogno.org/node/91 여기를 보고 컴파일하여 설치합니다. 해당 링크에서는 ruby1.9.1 버전을 기준으로 설명합니다.

가끔 창이 올라오지 않는 문제 해결했습니다.

[code:2advtadn]
@window.keep_above = true # 추가된 부분
@window.present # 창을 화면으로 올려준다.
@window.keep_above = false # 추가된 부분
[/code:2advtadn]

위에 실행방법 있습니다.
.rb 파일이 올라가지 않아서 .txt 확장자로 올려니,
파일명을 .rb 로 바꾸어준 후 실행하세요.

[code:2advtadn]mv minidict.txt minidict.rb[/code:2advtadn]

[list:25gh5myg]
[:25gh5myg] 알려진버그 수정 (line)[/:m:25gh5myg]
[:25gh5myg] Tab -> 2 spaces[/:m:25gh5myg][/list:u:25gh5myg]

[code:25gh5myg]#!/usr/bin/ruby1.9.1

coding: utf-8

version: 20100912

license: GPL v3

author: cogniti AT gmail.com

require ‘gtk2’
require ‘gtkhtml2’
require ‘net/http’
require ‘erb’

URI.parse 에러를 방지하기 위해 "|" ==> "%7C" 로 변경하였음.

평가 지연(lazy evaluation)을 위해 lambda 사용

def dict_uri q
"http://www.google.com/dictionary/feeds?client=ig&langpair=en%7Cko&q=#{q}&hl=ko"
end

Gtk::HtmlDocument

@doc = Gtk::HtmlDocument.new
def display html
@doc.open_stream(‘text/html’)
@doc.write_stream(‘<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />’)
@doc.write_stream(html)
@doc.close_stream()
end
display ‘<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><html><body><h3>구글 사전을 이용한 영한사전입니다.<br/> 마우스로 단어를 더블 클릭(또는 드래그)하면 그 위치에 창이 뜨고 단어가 표시됩니다.</h3></body></html>’

Gtk::HtmlView

htmlview = Gtk::HtmlView.new
htmlview.show
htmlview.document = @doc

Gtk::ScrolledWindow

sw = Gtk::ScrolledWindow.new(nil, nil)
sw.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC)
sw.add(htmlview)

Gtk::Window

@window = Gtk::Window.new("사전")
@window.signal_connect("destroy") { Gtk.main_quit }
@window.signal_connect(‘enter-notify-event’) { @window.decorated = true }
@window.set_default_size(300, 200)
@window.opacity = 0.9 # 투명도
@window.decorated = false # 윈도우 장식
@window.accept_focus = false # 초점을 가지지 못하게 한다.
@window.add(sw)
@window.show_all

CLIPBOARD

clipboard = Gtk::Clipboard.get(Gdk::Selection::PRIMARY) # 선택한 문자열
clipboard.signal_connect(‘owner-change’) do |clipboard|
dict clipboard.wait_for_text
end

def convert_to_html s
return "찾는 단어가 없습니다." unless s =~ /<primary/

primaries = s.scan(%r{<primary.+?</primary>}m)
dls = primaries.map { |primary| primary_to_dl primary }.join
<<-EOH
<html>
<body>
#{dls}
</body>
</html>
EOH
end

TEMPLATE = ERB.new <<EOH
<dl>
<dt><%= word %></dt>
<% dds.each { |dd| %>
<dd><%= dd %></dd>
<% } %>
</dl>
EOH
def primary_to_dl s
s.gsub!(%r{<related_phrase.+?</related_phrase>}m, ‘’)
word, *dds = s.scan(%r{<text>(.+?)</text>}).map { |x| x[0] }
TEMPLATE.result binding
end

def dict q
return if q.nil?
q.strip!
return unless q =~ /^[a-z]+$/i # 영단어만 통과
begin
s = Net::HTTP.get URI.parse(dict_uri q)
display convert_to_html(s)
rescue => e
puts e.message
end

마우스 포인터 위치 읽어 온다.

_, x, y = Gdk::Window.default_root_window.pointer

마우스 작업에 방해되지 않도록 +10 해준다.

@window.move(x+10, y+10)
@window.decorated = false
@window.keep_above = true
@window.present # 창을 화면으로 올려준다.
@window.keep_above = false
end

Gtk.main
[/code:25gh5myg]

[RubyKR] 에서 보고 넘어왔습니다.
stardict 은 약간 무거워서 시스템이 버거워 했는데
stardict 을 지워야 할지 고민 좀 해봐야할 것 같네요.
간결한게 감사합니다.

추후 여유가 있을 때 안정화, 리펙토링, 기능 추가할 생각입니다.

[size=150:26vsrs4c][b:26vsrs4c]minidict-htmlview.txt[/b:26vsrs4c][/size:26vsrs4c]
실행방법 참고
mv minidict-htmlview.txt minidict.rb

viewtopic.php?p=64653#p64653

바뀐 점

  • def display –> display_html 이름 바꿈
  • 마우스 드래그할 때 발생하는 과도한 owner-change 이벤트 무시
  • 사전 서버로 과도한 접속 방지와 프로그램의 응답성을 개선하기 위함
  • BUTTON_MOTION_MASK 를 체크해야 되는데 방법을 몰라서 0.5초 이내에 발생한 이벤트 무시

[size=150:26vsrs4c][b:26vsrs4c]minidict-textview.txt[/b:26vsrs4c][/size:26vsrs4c]

실행방법

ruby1.8.x, 1.9.x 모두에서 작동합니다.
ruby, libgtk2-ruby 가 안 깔려 있다면 루비를 설치해야 합니다.

$ sudo install ruby
$ sudo install libgtk2-ruby

.rb 파일이 올라가지 않아서 .txt 확장자로 올려니,
파일명을 .rb 로 바꾸어준 후 실행하세요.

$ mv minidict-textview.txt minidict.rb
$ ruby minidict.rb
또는
$ chmod +x minidict.rb
$ ./minidict

바뀐 점

  • Gtk::HtmlDocument –> Gtk::TextBuffer 교체
  • Gtk::HtmlView –> Gtk::TextView 교체
  • def display –> display_txt 교체
  • 마우스 드래그할 때 발생하는 과도한 owner-change 이벤트 무시
  • 사전 서버로 과도한 접속 방지와 프로그램의 응답성을 개선하기 위함
  • BUTTON_MOTION_MASK 를 체크해야 되는데 방법을 몰라서 0.5초 이내에 발생한 이벤트 무시

[b:26vsrs4c]따라서 사전창에 있는 내용을 복사한 후 다른 창에 붙여넣기할 수 있습니다.[/b:26vsrs4c]
이것 때문에 HtmlView 을 TextView 로 교체했습니다.

dbm이나 pstore 써서 사전쿼리 결과를 저장하고 있는건 어떤가요?

pstore 보다는 범용적인 (g)dbm으로 저장하는 거 찬성입니다.
그렇게 하면 서버 부하(load)를 낮추거나 인터넷이 안 되는 도서관 등에서 복습할 때 도움이 될 것 같습니다.

단, 저장된 db 배포 금지 조항, 보증 안 함(no warranty) 조항, 쿼리 결과에 powered by google 같은 조항 들어가면 법적으로 큰 문제는 생기지 않을 것 같습니다. 구글 크롬 확장으로 나온 사전도 있으니까요.
참고 링크 https://chrome.google.com/extensions/de … mcjbcpofhd

그리고 복수형 명사, 또는 동사 3인칭 등의 경우를 고려해야 합니다.
예를 들어 기본명+s 의 형태로 query 날리면 결과가 오는 단어가 있고 오지 않는 단어가 있습니다.
그 문제는 http://english.rubyforge.org/ 이걸로 해결이 될 것 같습니다만, 해당 gem을 테스트 해보지는 않았습니다.

DB 저장은 단순한 기능이지만, 시간이 좀 걸릴 듯 합니다.
일도 해야 되고, 공부도 해야 되고, 자이언트도 봐야 되니…ㅋㅋㅋ

http://english.rubyforge.org/

[quote="cogniti":3krkhlba]http://english.rubyforge.org/ 를 간단히 테스트 해봤는데 적용하기는 어려울 것 같습니다.
gdbm을 이용하여 저장 기능 추가했습니다.
사용하는데 큰 불편은 없을 것 같습니다.
오늘 자이언트는 정말 재미있었습니다. ㅋㅋㅋ

바뀐 점

  • gdbm을 사용하여 cache.db에 저장
  • MiniDictView 로 GUI를 분리[/quote:3krkhlba]
    우선 새로 바뀐 gdbm때문에 libgdbm-ruby1.8 패키지를 추가로 설치해줘야 하는군요.
    그리고 제 경우 실행하면 자꾸 이런 에러메시지와 함께 죽습니다.

[code:3krkhlba]./minidict.rb:53: warning: multiple values for a block parameter (2 for 1)
from ./minidict.rb:142
./minidict.rb:54: undefined method wait_for_text' for #&lt;Array&#58;0xb74db284&gt; from &#46;/minidict&#46;rb&#58;142&#58;in call’
from ./minidict.rb:142:in `main’
from ./minidict.rb:142
[/code:3krkhlba]

바뀐 점

  • 1.8.x 에서 안 되는 버그 수정
  • UI 개선
  • 20100916 버전에서 0.5초 체크 오류 수정

github에 넣었습니다.

http://github.com/cogniti/minidict

안되네요… :oops:

ruby 1.8 설치했구요.
죽 따라 했지요.

다운로드한 폴더에서
$ ruby minidict.rb 했더니
minidict.rb:11:in `require’: no such file to load – gdbm (LoadError)
from minidict.rb:11
이런 에러 메세지가 나오구요.

$ sudo chmod +x minidict.rb
$ ./minidict
했는데
bash: ./minidict: No such file or directory
이런 에러 메세지가 나옵니다.

뭐가 문제일까요?

실행방법입니다.

http://github.com/cogniti/minidict/blob/master/README

libgdbm-ruby 까지 설치하니까 됩니다.
사전이 귀엽네요.

사용해 보니
간단하게 보이게 하려고 하는 목적인지
아니면 다른 이유에서인지
구글 영한 사전의 원본과는 다르네요.
품사 표시도 없어서
원본이 더 알아보기가 편합니다.

터미널에서 실행하는게 귀찮아서 패널에 추가해 놨습니다.
이 글타래 보고 ruby 에 관심이 많아졌는데
한글 자료가 많이 없네요.

잘 쓸께요~ :P