こんにちは、越水です。

tktext.rbのTkTextに, Tcl/Tkの`text dump'コマンドが実装されていないよう
なので、下のようなコードを書いてみました。将来、dumpが実装されることが
あれば参考にしてください:

require 'tk'

class TkTextDump <TkText
  def _dump(type, *index)
    str = tk_send('dump', type, *index)
    result = []
    sel = nil
    i = 0
    while i < str.size
      # retrieve key
      idx = str.index(/ /, i)
      result.push str[i..(idx-1)]
      i = idx + 1
      
      # retrieve value
      case result[-1]
      when 'text'
	if str[i] == ?{
	  # text formed as {...}
	  val, i = _retrieve_breathed_text(str, i)
	  result.push val
	else
	  # text which may contain backslahes
	  val, i = _retrieve_backslashed_text(str, i)
	  result.push val
	end
      else
	idx = str.index(/ /, i)
	val = str[i..(idx-1)]
	case result[-1]
	when 'mark'
	  case val
	  when 'insert'
	    result.push TkTextMarkInsert.new(self)
	  when 'current'
	    result.push TkTextMarkCurrent.new(self)
	  else
	    result.push tk_tcl2rb val
	  end
	when 'tagon'
	  if val == 'sel'
	    if sel
	      result.push sel
	    else
	      result.push TkTextTagSel.new(self)
	    end
	  else
	    result.push tk_tcl2rb val
	  end
	when 'tagoff'
	    result.push tk_tcl2rb sel
	when 'window'
	  result.push tk_tcl2rb val
	end
	i = idx + 1
      end

      # retrieve index
      idx = str.index(/ /, i)
      if idx
	result.push str[i..(idx-1)]
	i = idx + 1
      else
	result.push str[i..-1]
	break
      end
    end
    
    kvis = []
    until result.empty?
      kvis.push [result.shift, result.shift, result.shift]
    end
    kvis  # result is [[key1, value1, index1], [key2, value2, index2], ...]
  end
  private :_dump

  def _retrieve_breathed_text(str, i)
    cnt = 0
    idx = i
    while idx < str.size
      case str[idx]
      when ?{
	cnt += 1
      when ?}
	cnt -= 1
	if cnt == 0
	  break
	end
      end
      idx += 1
    end
    return str[i+1..idx-1], idx + 2
  end
  private :_retrieve_breathed_text

  def _retrieve_backslashed_text(str, i)
    j = i
    idx = nil
    loop {
      idx = str.index(/ /, j)
      if str[idx-1] == ?\\
	j += 1
      else
	break
      end
    }
    val = str[i..(idx-1)]
    val.gsub!(/\\( |\{|\})/, '\1')
    return val, idx + 1
  end
  private :_retrieve_backslashed_text

  def dump_all(*index)
    _dump('-all', *index)
  end
  def dump_mark(*index)
    _dump('-mark', *index)
  end
  def dump_tag(*index)
    _dump('-tag', *index)
  end
  def dump_text(*index)
    _dump('-text', *index)
  end
  def dump_window(*index)
    _dump('-window', *index)
  end
end

txt = TkTextDump.new {
  insert 'end', '0123456789'
  pack
}
btn = TkButton.new {
  text 'Get'
  command {
    txt.dump_all('1.0', 'end').each {
      | key, value, index |
      if key == 'text'
	puts index + ': ' + value
      end
    }
  }
  pack
}
Tk.mainloop

# 越水 greentea / fa2.so-net.ne.jp