1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/tk/lib/tk/itemconfig.rb: bug fix on 'itemconfiginfo' method, and

modify to make it easy to override 'itemconfiginfo' method.
* ext/tk/lib/tkextlib/tile/treeview.rb : support Tile 0.7.8.
* ext/tk/lib/tkextlib/version.rb : [new] add Tk::Tkextlib_RELEASE_DATE
  to get the information from scripts.
* ext/tk/lib/tk.rb: load 'tkextlib/version.rb', and update RELEASE_DATE.
* ext/tk/lib/tkextlib/SUPPORT_STATUS: update.
* ext/tk/sample/editable_listbox.rb: [new] the listbox with editable
  items. It's one of the example about usage of Place geometry manager.
* ext/tk/sample/tktextio.rb: improve the functions of TkTextIO class.
  Those are required by 'irbtkw.rbw'.
* ext/tk/sample/irbtkw.rbw: [new] IRB on Ruby/Tk. It doesn't need any
  real console. IRB works on a text widget without I/O blocking. That
  is, thread switching on IRB will work properly, even if on Windows.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11283 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagai 2006-11-06 06:56:37 +00:00
parent ced53248ff
commit 2ec88c167b
10 changed files with 1692 additions and 206 deletions

View file

@ -1,3 +1,28 @@
Mon Nov 6 15:41:55 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/tk/itemconfig.rb: ext/tk/lib/tk/itemconfig.rb: bug
fix on 'itemconfiginfo' method, and modify to make it easy to
override 'itemconfiginfo' method.
* ext/tk/lib/tkextlib/tile/treeview.rb : support Tile 0.7.8.
* ext/tk/lib/tkextlib/version.rb : [new] add Tk::Tkextlib_RELEASE_DATE
to get the information from scripts.
* ext/tk/lib/tk.rb: load 'tkextlib/version.rb', and update RELEASE_DATE
* ext/tk/lib/tkextlib/SUPPORT_STATUS: update.
* ext/tk/sample/editable_listbox.rb: [new] the listbox with editable
items. It's one of the example about usage of Place geometry manager.
* ext/tk/sample/tktextio.rb: improve the functions of TkTextIO class.
Those are required by 'irbtkw.rbw'.
* ext/tk/sample/irbtkw.rbw: [new] IRB on Ruby/Tk. It doesn't need any
real console. IRB works on a text widget without I/O blocking. That
is, thread switching on IRB will work properly, even if on Windows.
Mon Nov 6 00:42:05 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (arg_dup_check): vid may be nameless internal id.

View file

@ -1,3 +1,11 @@
2006-11-06 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* lib/tkextlib/version.rb: keep release date of tkextlib on
"Tk::Tkextlib_RELEASE_DATE".
* lib/tkextlib/tile/treeview.rb : support Tile 0.7.8.
Now, you can handle tree items as objects.
2006-10-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* lib/tkextlib/tile.rb, lib/tkextlib/tile/* : support Tile 0.7.6.

View file

@ -4597,7 +4597,7 @@ end
#Tk.freeze
module Tk
RELEASE_DATE = '2006-09-01'.freeze
RELEASE_DATE = '2006-11-06'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'
@ -4609,6 +4609,7 @@ end
# call setup script for Tk extension libraries (base configuration)
begin
require 'tkextlib/version.rb'
require 'tkextlib/setup.rb'
rescue LoadError
# ignore

View file

@ -289,7 +289,7 @@ module TkItemConfigMethod
self
end
def itemconfiginfo(tagOrId, slot = nil)
def __itemconfiginfo_core(tagOrId, slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
fontkey = $2
@ -594,7 +594,7 @@ module TkItemConfigMethod
if v.empty?
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
else
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
end
end
@ -1020,13 +1020,18 @@ module TkItemConfigMethod
end
end
end
private :__itemconfiginfo_core
def itemconfiginfo(tagOrId, slot = nil)
__itemconfiginfo_core(tagOrId, slot)
end
def current_itemconfiginfo(tagOrId, slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if slot
org_slot = slot
begin
conf = itemconfiginfo(tagOrId, slot)
conf = __itemconfiginfo_core(tagOrId, slot)
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
return {conf[0] => conf[-1]}
@ -1037,7 +1042,7 @@ module TkItemConfigMethod
"there is a configure alias loop about '#{org_slot}'"
else
ret = {}
itemconfiginfo(tagOrId).each{|conf|
__itemconfiginfo_core(tagOrId).each{|conf|
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
ret[conf[0]] = conf[-1]
@ -1047,7 +1052,7 @@ module TkItemConfigMethod
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
ret = {}
itemconfiginfo(slot).each{|key, conf|
itemconfiginfo(tagOrId, slot).each{|key, conf|
ret[key] = conf[-1] if conf.kind_of?(Array)
}
ret

View file

@ -1,7 +1,7 @@
[ current support status of Tcl/Tk extensions ]
*******<<< RELEASE_DATE of the libraries : 2006/10/04 >>>*******
*** RELEASE_DATE of the libraries => see 'tkextlib/version.rb' ***
The following list shows *CURRENT* status when this file was modifyed
at last. If you want to add other Tcl/Tk extensions to the planed list
@ -83,7 +83,7 @@ BLT 2.4z http://sourceforge.net/projects/blt
TkTreeCtrl CVS/Hd(2005-12-02)
http://sourceforge.net/projects/tktreectrl ==> treectrl
Tile CVS/Hd(2006-10-01)
Tile 0.7.8
http://sourceforge.net/projects/tktable ==> tile

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
#
# release date of tkextlib
#
module Tk
Tkextlib_RELEASE_DATE = '2006-11-06'.freeze
end

View file

@ -0,0 +1,69 @@
#
# Editable_TkListbox class
#
# When "DoubleClick-1" on a listbox item, the entry box is opend on the
# item. And when hit "Return" key on the entry box after modifying the
# text, the entry box is closed and the item is changed. Or when hit
# "Escape" key, the entry box is closed without modification.
#
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
#
require 'tk'
class Editable_TkListbox < TkListbox
def _ebox_placer(coord_y)
idx = self.nearest(coord_y)
x, y, w, h = self.bbox(idx)
@ebox.place(:x => 0, :relwidth => 1.0,
:y => y - self.selectborderwidth,
:height => h + 2 * self.selectborderwidth)
@ebox.pos = idx
@ebox.value = self.listvariable.list[idx]
@ebox.focus
end
private :_ebox_placer
def create_self(keys)
super(keys)
unless self.listvariable
self.listvariable = TkVariable.new(self.get(0, :end))
end
@ebox = TkEntry.new(self){
@pos = -1
def self.pos; @pos; end
def self.pos=(idx); @pos = idx; end
}
@ebox.bind('Return'){
list = self.listvariable.list
list[@ebox.pos] = @ebox.value
self.listvariable.value = list
@ebox.place_forget
@ebox.pos = -1
}
@ebox.bind('Escape'){
@ebox.place_forget
@ebox.pos = -1
}
self.bind('Double-1', '%y'){|y| _ebox_placer(y) }
end
end
if $0 == __FILE__
scr = TkScrollbar.new.pack(:side=>:right, :fill=>:y)
lbox1 = Editable_TkListbox.new.pack(:side=>:left)
lbox2 = Editable_TkListbox.new.pack(:side=>:left)
scr.assign(lbox1, lbox2)
lbox1.insert(:end, *%w(a b c d e f g h i j k l m n))
lbox2.insert(:end, 0,1,2,3,4,5,6,7,8,9,0,1,2,3)
Tk.mainloop
end

119
ext/tk/sample/irbtkw.rbw Normal file
View file

@ -0,0 +1,119 @@
#!/usr/bin/env ruby
#
# irbtkw.rb : IRB console with Ruby/Tk
#
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
#
release = '2006/11/06'
require 'tk'
begin
require 'tktextio'
rescue LoadError
require File.join(File.dirname(File.expand_path(__FILE__)), 'tktextio.rb')
end
require 'irb'
# console setup
top = TkToplevel.new(:title=>'IRB console')
top.protocol(:WM_DELETE_WINDOW){ Tk.exit }
console = TkTextIO.new(top, :mode=>:console,
:width=>80).pack(:side=>:left,
:expand=>true, :fill=>:both)
console.yscrollbar(TkScrollbar.new(top, :width=>10).pack(:before=>console,
:side=>:right,
:expand=>false,
:fill=>:y))
ev_loop = Thread.new{Tk.mainloop}
# window position control
root = Tk.root
r_x = root.winfo_rootx
r_y = root.winfo_rooty
r_w = root.winfo_width
t_x = top.winfo_rootx
t_y = top.winfo_rooty
t_w = top.winfo_width
delta = 10
ratio = 0.8
s_w = (ratio * root.winfo_screenwidth).to_i
if r_x < t_x
r_x, t_x = t_x, r_x
end
if t_x + t_w + r_w + delta < s_w
r_x = t_x + t_w + delta
elsif t_w + r_w + delta < s_w
r_x = s_w - r_w
t_x = r_x - t_w
else
r_x = s_w - r_w
t_x = 0
end
root.geometry("+#{r_x}+#{r_y}")
top.geometry("+#{t_x}+#{t_y}")
root.raise
console.focus
# I/O setup
$stdin = console
$stdout = console
$stderr = console
# dummy for rubyw.exe on Windows
def STDIN.tty?
true
end
# IRB setup
IRB.init_config(nil)
IRB.conf[:USE_READLINE] = false
IRB.init_error
irb = IRB::Irb.new
IRB.conf[:MAIN_CONTEXT] = irb.context
class IRB::StdioInputMethod
def gets
prompt = "\n" << @prompt
$stdin.instance_eval{
flush
@prompt = prompt
_set_console_line
@prompt = nil
_see_pos
}
@line[@line_no += 1] = $stdin.gets
end
end
# IRB start
$stdout.print("*** IRB console on Ruby/Tk (#{release}) ")
irb_thread = Thread.new{
catch(:IRB_EXIT){
loop {
begin
irb.eval_input
rescue Exception
end
}
}
}
console.bind('Control-c'){
console.insert('end', "^C\n")
irb_thread.raise RubyLex::TerminateLineInput
}
irb_thread.join
# exit
Tk.exit

View file

@ -1,7 +1,7 @@
#!/usr/bin/env ruby
#
# sample class of handling I/O stream on a TkText widget
# by Hidetoshi NAGAI
# TkTextIO class :: handling I/O stream on a TkText widget
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
#
# NOTE: TkTextIO supports 'character' (not 'byte') access only.
# So, for example, TkTextIO#getc returns a character, TkTextIO#pos
@ -14,68 +14,375 @@
# TkTextIO.
#
require 'tk'
require 'tk/text'
require 'tk/textmark'
require 'thread'
class TkTextIO < TkText
def create_self(keys)
mode = nil
ovwt = false
text = nil
wrap = 'char'
show = :pos
# keep safe level
@@create_queues = proc{ [Queue.new, Mutex.new, Queue.new, Mutex.new] }
if keys.kind_of?(Hash)
mode = keys.delete('mode')
ovwt = keys.delete('overwrite')
text = keys.delete('text')
show = keys.delete('show') if keys.has_key?('show')
wrap = keys.delete('wrap') || 'char'
end
OPT_DEFAULTS = {
'mode' => nil,
'overwrite' => false,
'text' => nil,
'show' => :pos,
'wrap' => 'char',
'sync' => true,
'prompt' => nil,
'prompt_cmd' => nil,
'hist_size' => 1000,
}
def create_self(keys)
opts = _get_io_params((keys.kind_of?(Hash))? keys: {})
super(keys)
self['wrap'] = wrap
insert('1.0', text)
@count_var = TkVariable.new
@txtpos = TkTextMark.new(self, '1.0')
@write_buffer = ''
@read_buffer = ''
@buf_size = 0
@buf_max = 1024
@write_buf_queue, @write_buf_mutex,
@read_buf_queue, @read_buf_mutex = @@create_queues.call
@idle_flush = TkTimer.new(:idle, 1, proc{ @flusher.run rescue nil })
@timer_flush = TkTimer.new(250, -1, proc{ @flusher.run rescue nil })
@flusher = Thread.new{ loop { Thread.stop; flush() } }
@receiver = Thread.new{
begin
loop {
str = @write_buf_queue.deq
@write_buf_mutex.synchronize { @write_buffer << str }
@idle_flush.start
}
ensure
@flusher.kill
end
}
@timer_flush.start
_setup_io(opts)
end
private :create_self
def destroy
@flusher.kill rescue nil
@idle_flush.stop rescue nil
@timer_flush.stop rescue nil
@receiver.kill rescue nil
super()
end
####################################
def _get_io_params(keys)
opts = {}
self.class.const_get(:OPT_DEFAULTS).each{|k, v|
if keys.has_key?(k)
opts[k] = keys.delete(k)
else
opts[k] = v
end
}
opts
end
def _setup_io(opts)
unless defined? @txtpos
@txtpos = TkTextMark.new(self, '1.0')
else
@txtpos.set('1.0')
end
@txtpos.gravity = :left
self.show_mode = show
@sync = true
@overwrite = (ovwt)? true: false
@lineno = 0
@line_offset = 0
@count_var = TkVariable.new
@hist_max = opts['hist_size']
@hist_index = 0
@history = Array.new(@hist_max)
@history[0] = ''
self['wrap'] = wrap
self.show_mode = opts['show']
self.value = opts['text'] if opts['text']
@overwrite = (opts['overwrite'])? true: false
@sync = opts['sync']
@prompt = opts['prompt']
@prompt_cmd = opts['prompt_cmd']
@open = {:r => true, :w => true} # default is 'r+'
case mode
when 'r'
@console_mode = false
@end_of_stream = false
@console_buffer = nil
case opts['mode']
when nil
# do nothing
when :console, 'console'
@console_mode = true
# @console_buffer = TkTextIO.new(:mode=>'r')
@console_buffer = self.class.new(:mode=>'r')
self.show_mode = :insert
when 'r', 'rb'
@open[:r] = true; @open[:w] = nil
when 'r+'
when 'r+', 'rb+', 'r+b'
@open[:r] = true; @open[:w] = true
when 'w'
when 'w', 'wb'
@open[:r] = nil; @open[:w] = true
self.value=''
when 'w+'
when 'w+', 'wb+', 'w+b'
@open[:r] = true; @open[:w] = true
self.value=''
when 'a'
when 'a', 'ab'
@open[:r] = nil; @open[:w] = true
@txtpos = TkTextMark.new(self, 'end - 1 char')
@txtpos.set('end - 1 char')
@txtpos.gravity = :right
when 'a+'
when 'a+', 'ab+', 'a+b'
@open[:r] = true; @open[:w] = true
@txtpos = TkTextMark.new(self, 'end - 1 char')
@txtpos.set('end - 1 char')
@txtpos.gravity = :right
else
fail ArgumentError, "unknown mode `#{opts['mode']}'"
end
unless defined? @ins_head
@ins_head = TkTextMark.new(self, 'insert')
@ins_head.gravity = :left
end
unless defined? @ins_tail
@ins_tail = TkTextMark.new(self, 'insert')
@ins_tail.gravity = :right
end
unless defined? @tmp_mark
@tmp_mark = TkTextMark.new(self, 'insert')
@tmp_mark.gravity = :left
end
if @console_mode
_set_console_line
_setup_console_bindings
end
end
private :_get_io_params, :_setup_io
def _set_console_line
@tmp_mark.set(@ins_tail)
mark_set('insert', 'end')
prompt = ''
prompt << @prompt_cmd.call if @prompt_cmd
prompt << @prompt if @prompt
insert(@tmp_mark, prompt)
@ins_head.set(@ins_tail)
@ins_tail.set('insert')
@txtpos.set(@tmp_mark)
_see_pos
end
def _replace_console_line(str)
self.delete(@ins_head, @ins_tail)
self.insert(@ins_head, str)
end
def _get_console_line
@tmp_mark.set(@ins_tail)
s = self.get(@ins_head, @tmp_mark)
_set_console_line
s
end
private :_set_console_line, :_replace_console_line, :_get_console_line
def _cb_up
@history[@hist_index].replace(self.get(@ins_head, @ins_tail))
@hist_index += 1
@hist_index -= 1 if @hist_index >= @hist_max || !@history[@hist_index]
_replace_console_line(@history[@hist_index]) if @history[@hist_index]
Tk.callback_break
end
def _cb_down
@history[@hist_index].replace(self.get(@ins_head, @ins_tail))
@hist_index -= 1
@hist_index = 0 if @hist_index < 0
_replace_console_line(@history[@hist_index]) if @history[@hist_index]
Tk.callback_break
end
def _cb_left
if @console_mode && compare('insert', '<=', @ins_head)
mark_set('insert', @ins_head)
Tk.callback_break
end
end
def _cb_backspace
if @console_mode && compare('insert', '<=', @ins_head)
Tk.callback_break
end
end
def _cb_ctrl_a
if @console_mode
mark_set('insert', @ins_head)
Tk.callback_break
end
end
private :_cb_up, :_cb_down, :_cb_left, :_cb_backspace, :_cb_ctrl_a
def _setup_console_bindings
@bindtag = TkBindTag.new
tags = self.bindtags
tags[tags.index(self)+1, 0] = @bindtag
self.bindtags = tags
@bindtag.bind('Return'){
insert('end - 1 char', "\n")
if (str = _get_console_line)
@read_buf_queue.push(str)
@history[0].replace(str.chomp)
@history.pop
@history.unshift('')
@hist_index = 0
end
Tk.update
Tk.callback_break
}
@bindtag.bind('Alt-Return'){
Tk.callback_continue
}
@bindtag.bind('FocusIn'){
if @console_mode
mark_set('insert', @ins_tail)
Tk.callback_break
end
}
ins_mark = TkTextMark.new(self, 'insert')
@bindtag.bind('ButtonPress'){
if @console_mode
ins_mark.set('insert')
end
}
@bindtag.bind('ButtonRelease-1'){
if @console_mode && compare('insert', '<=', @ins_head)
mark_set('insert', ins_mark)
Tk.callback_break
end
}
@bindtag.bind('ButtonRelease-2', '%x %y'){|x, y|
if @console_mode
# paste a text at 'insert' only
x1, y1, x2, y2 = bbox(ins_mark)
unless x == x1 && y == y1
Tk.event_generate(self, 'ButtonRelease-2', :x=>x1, :y=>y1)
Tk.callback_break
end
end
}
@bindtag.bind('Up'){ _cb_up }
@bindtag.bind('Control-p'){ _cb_up }
@bindtag.bind('Down'){ _cb_down }
@bindtag.bind('Control-n'){ _cb_down }
@bindtag.bind('Left'){ _cb_left }
@bindtag.bind('Control-b'){ _cb_left }
@bindtag.bind('BackSpace'){ _cb_backspace }
@bindtag.bind('Control-h'){ _cb_backspace }
@bindtag.bind('Home'){ _cb_ctrl_a }
@bindtag.bind('Control-a'){ _cb_ctrl_a }
end
private :_setup_console_bindings
def _block_read(size = nil, ret = '', block_mode = true)
return '' if size == 0
return nil if ! @read_buf_queue && @read_buffer.empty?
ret = '' unless ret.kind_of?(String)
ret.replace('') unless ret.empty?
if block_mode == nil # partial
if @read_buffer.empty?
ret << @read_buffer.slice!(0..-1)
return ret
end
end
if size.kind_of?(Numeric)
loop{
@read_buf_mutex.synchronize {
buf_len = @read_buffer.length
if buf_len >= size
ret << @read_buffer.slice!(0, size)
return ret
else
ret << @read_buffer.slice!(0..-1)
size -= buf_len
return ret unless @read_buf_queue
end
}
@read_buffer << @read_buf_queue.pop
}
else # readline
rs = (size)? size: $/
rs = rs.to_s if rs.kind_of?(Regexp)
loop{
@read_buf_mutex.synchronize {
if (str = @read_buffer.slice!(/\A(.*)(#{rs})/m))
ret << str
return ret
else
ret << @read_buffer.slice!(0..-1)
return ret unless @read_buf_queue
end
}
@read_buffer << @read_buf_queue.pop
}
end
end
def _block_write
###### currently, not support
end
private :_block_read, :_block_write
####################################
def <<(obj)
_write(obj)
@ -107,14 +414,15 @@ class TkTextIO < TkText
nil
end
def closed?
close_read? && close_write?
end
def closed_read?
!@open[:r]
end
def closed_write?
!@open[:w]
def closed?(dir=nil)
case dir
when :r, 'r'
!@open[:r]
when :w, 'w'
!@open[:w]
else
!@open[:r] && !@open[:w]
end
end
def _check_readable
@ -129,7 +437,7 @@ class TkTextIO < TkText
def each_line(rs = $/)
_check_readable
while(s = gets)
while(s = self.gets(rs))
yield(s)
end
self
@ -138,7 +446,7 @@ class TkTextIO < TkText
def each_char
_check_readable
while(c = getc)
while(c = self.getc)
yield(c)
end
self
@ -151,7 +459,7 @@ class TkTextIO < TkText
alias eof eof?
def fcntl(*args)
fail NotImplementedError, 'fcntl is not implemented on TkTextIO'
fail NotImplementedError, "fcntl is not implemented on #{self.class}"
end
def fsync
@ -163,11 +471,19 @@ class TkTextIO < TkText
end
def flush
Tk.update if @open[:w] && @sync
Thread.pass
if @open[:w] || ! @write_buffer.empty?
@write_buf_mutex.synchronize {
_sync_write_buf(@write_buffer)
@write_buffer[0..-1] = ''
}
end
self
end
def getc
return _block_read(1) if @console_mode
_check_readable
return nil if eof?
c = get(@txtpos)
@ -177,8 +493,10 @@ class TkTextIO < TkText
end
def gets(rs = $/)
return _block_read(rs) if @console_mode
_check_readable
return nil if eof?
return nil if eof?
_readline(rs)
end
@ -233,7 +551,6 @@ class TkTextIO < TkText
alias tell pos
def pos=(idx)
# @txtpos.set((idx.kind_of?(Numeric))? "1.0 + #{idx} char": idx)
seek(idx, IO::SEEK_SET)
idx
end
@ -306,6 +623,8 @@ class TkTextIO < TkText
private :_read
def read(len=nil, buf=nil)
return _block_read(len, buf) if @console_mode
_check_readable
if len
return "" if len == 0
@ -321,6 +640,8 @@ class TkTextIO < TkText
end
def readchar
return _block_read(1) if @console_mode
_check_readable
fail EOFError if eof?
c = get(@txtpos)
@ -334,6 +655,7 @@ class TkTextIO < TkText
s = get(@txtpos, 'end - 1 char')
@txtpos.set('end - 1 char')
elsif rs == ''
@count_var.value # make it global
idx = tksearch_with_count([:regexp], @count_var,
"\n(\n)+", @txtpos, 'end - 1 char')
if idx
@ -345,6 +667,7 @@ class TkTextIO < TkText
@txtpos.set('end - 1 char')
end
else
@count_var.value # make it global
idx = tksearch_with_count(@count_var, rs, @txtpos, 'end - 1 char')
if idx
s = get(@txtpos, "#{idx} + #{@count_var.value} char")
@ -363,12 +686,22 @@ class TkTextIO < TkText
private :_readline
def readline(rs = $/)
return _block_readline(rs) if @console_mode
_check_readable
fail EOFError if eof?
_readline(rs)
end
def readlines(rs = $/)
if @console_mode
lines = []
while (line = _block_readline(rs))
lines << line
end
return lines
end
_check_readable
lines = []
until(eof?)
@ -379,7 +712,11 @@ class TkTextIO < TkText
end
def readpartial(maxlen, buf=nil)
#return @console_buffer.readpartial(maxlen, buf) if @console_mode
return _block_read(maxlen, buf, nil) if @console_mode
_check_readable
fail EOFError if eof?
s = _read(maxlen)
buf.replace(s) if buf.kind_of?(String)
s
@ -471,6 +808,8 @@ class TkTextIO < TkText
end
def sysread(len, buf=nil)
return _block_read(len, buf) if @console_mode
_check_readable
fail EOFError if eof?
s = _read(len)
@ -492,6 +831,13 @@ class TkTextIO < TkText
end
def ungetc(c)
if @console_mode
@read_buf_mutex.synchronize {
@read_buffer[0,0] = c.chr
}
return nil
end
_check_readable
c = c.chr if c.kind_of?(Fixnum)
if compare(@txtpos, '>', '1.0')
@ -506,8 +852,10 @@ class TkTextIO < TkText
nil
end
=begin
def _write(obj)
s = _get_eval_string(obj)
#s = _get_eval_string(obj)
s = (obj.kind_of?(String))? obj: obj.to_s
n = number(tk_call('string', 'length', s))
delete(@txtpos, @txtpos + "#{n} char") if @overwrite
self.insert(@txtpos, s)
@ -518,6 +866,37 @@ class TkTextIO < TkText
n
end
private :_write
=end
#=begin
def _sync_write_buf(s)
if (n = number(tk_call('string', 'length', s))) > 0
delete(@txtpos, @txtpos + "#{n} char") if @overwrite
self.insert(@txtpos, s)
#Tk.update
@txtpos.set(@txtpos + "#{n} char")
@txtpos.set('end - 1 char') if compare(@txtpos, '>=', :end)
@ins_head.set(@txtpos) if compare(@txtpos, '>', @ins_head)
_see_pos
end
self
end
private :_sync_write_buf
def _write(obj)
s = (obj.kind_of?(String))? obj: obj.to_s
n = number(tk_call('string', 'length', s))
@write_buf_queue.enq(s)
if @sync
Thread.pass
Tk.update
end
n
end
private :_write
#=end
def write(obj)
_check_writable
@ -529,13 +908,19 @@ end
# TEST
####################
if __FILE__ == $0
ev_loop = Thread.new{Tk.mainloop}
f = TkFrame.new.pack
tio = TkTextIO.new(f, :show=>:pos,
#tio = TkTextIO.new(f, :show=>:nil,
#tio = TkTextIO.new(f, :show=>:pos,
tio = TkTextIO.new(f, :show=>:insert,
:text=>">>> This is an initial text line. <<<\n\n"){
yscrollbar(TkScrollbar.new(f).pack(:side=>:right, :fill=>:y))
# yscrollbar(TkScrollbar.new(f).pack(:side=>:right, :fill=>:y))
pack(:side=>:left, :fill=>:both, :expand=>true)
}
Tk.update
$stdin = tio
$stdout = tio
$stderr = tio
@ -599,5 +984,67 @@ if __FILE__ == $0
tio.seek(0, IO::SEEK_END)
Tk.mainloop
STDOUT.print("tio.sync == #{tio.sync}\n")
# tio.sync = false
# STDOUT.print("tio.sync == #{tio.sync}\n")
(0..10).each{|i|
STDOUT.print("#{i}\n")
s = ''
(0..1000).each{ s << '*' }
print(s)
}
print("\n")
print("\n=========================================================\n\n")
s = ''
timer = TkTimer.new(:idle, -1, proc{
#STDOUT.print("idle call\n")
unless s.empty?
print(s)
s = ''
end
}).start
(0..10).each{|i|
STDOUT.print("#{i}\n")
(0..1000).each{ s << '*' }
}
# timer.stop
until s.empty?
sleep 0.1
end
timer.stop
=begin
tio.sync = false
print("\n")
#(0..10000).each{ putc('*') }
(0..10).each{|i|
STDOUT.print("#{i}\n")
(0..1000).each{ putc('*') }
}
(0..10).each{|i|
STDOUT.print("#{i}\n")
s = ''
(0..1000).each{ s << '*' }
print(s)
}
=end
num = 0
# io = TkTextIO.new(:mode=>:console, :prompt=>'').pack
#=begin
io = TkTextIO.new(:mode=>:console,
:prompt_cmd=>proc{
s = "[#{num}]"
num += 1
s
},
:prompt=>'-> ').pack
#=end
Thread.new{loop{sleep 2; io.puts 'hoge'}}
Thread.new{loop{p io.gets}}
ev_loop.join
end