Gtk::Text は良くできてると思うんですが、Emacs に慣れた身にはやはり 機能不足に感じます。ということで、まずは fill_paragraph を実装して みました。Alt-q で段落を指定幅に整形します。漢字コードは EUC にの み対応しています。ん〜、かなり長くなってしまいました。
module GtkTextFillParagraph
def initialize(*args)
super(*args)
@fill_column = 70
@kinsoku_list = [' ', '、', '。']
signal_connect('key-press-event') do |w, ev|
if ev.state == 8 and ev.keyval == ?q then
s, e = get_paragraph
str = get_chars s, e
delete_text s, e
insert_text fill_paragraph(str), s
end
end
end
attr :fill_column, true
def fill_paragraph(s)
prefix = /\A[\#^gt;]+ +/.match(s).to_s
col = 0
ret = ''
s = s.gsub(/^#{prefix}/, '').gsub(/([\200-\376])\n|\n([\200-\376])/n, '\\1\\2').gsub(/(\S)\s+/, '\\1 ')
s = prefix + s
s.scan(/[\041-\176]+|./).each do |c|
col2 = if c[0] < 0x80 then c.length elsif c[0] == 0x8e then 1 else 2 end
if col == 0 then
col = col2
elsif not @kinsoku_list.include? c and col + col2 > @fill_column then
ret << "\n#{prefix}"
col = prefix.length + col2
else
col += col2
end
ret << c
end
ret
end
private
def pos_byte(str, pos)
str =~ /\A.{#{pos}}/p
$&.length
end
def wclen(str)
str.split(//).length
end
def get_paragraph()
p = position
l = get_length
s = get_chars(0, -1)
p2 = pos_byte s, p
pre = if p2 == 0 then pre = ''
elsif s[0..p2-1] =~ /\n\n/p then pre = $' #'
else pre = s[0..p2-1]
end
aft = if s[p2..-1] =~ /\n\n/p then $` #`
else aft = s[p2..-1]
end
if pre[-1] == 0x0a and aft[0] == 0x0a then pre = aft = '' end
startp = p - wclen(pre)
endp = p + wclen(aft)
[startp, endp]
end
end
使用例
require 'gtk' class MyText < Gtk::Text include GtkTextFillParagraph end w = Gtk::Window::new t = MyText::new t.set_editable true w.add t w.show_all Gtk::main