зеркало из https://github.com/github/ruby.git
* 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:
Родитель
ced53248ff
Коммит
2ec88c167b
25
ChangeLog
25
ChangeLog
|
@ -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>
|
Mon Nov 6 00:42:05 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||||
|
|
||||||
* parse.y (arg_dup_check): vid may be nameless internal id.
|
* parse.y (arg_dup_check): vid may be nameless internal id.
|
||||||
|
|
|
@ -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>
|
2006-10-04 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||||
|
|
||||||
* lib/tkextlib/tile.rb, lib/tkextlib/tile/* : support Tile 0.7.6.
|
* lib/tkextlib/tile.rb, lib/tkextlib/tile/* : support Tile 0.7.6.
|
||||||
|
|
|
@ -4597,7 +4597,7 @@ end
|
||||||
#Tk.freeze
|
#Tk.freeze
|
||||||
|
|
||||||
module Tk
|
module Tk
|
||||||
RELEASE_DATE = '2006-09-01'.freeze
|
RELEASE_DATE = '2006-11-06'.freeze
|
||||||
|
|
||||||
autoload :AUTO_PATH, 'tk/variable'
|
autoload :AUTO_PATH, 'tk/variable'
|
||||||
autoload :TCL_PACKAGE_PATH, 'tk/variable'
|
autoload :TCL_PACKAGE_PATH, 'tk/variable'
|
||||||
|
@ -4609,6 +4609,7 @@ end
|
||||||
|
|
||||||
# call setup script for Tk extension libraries (base configuration)
|
# call setup script for Tk extension libraries (base configuration)
|
||||||
begin
|
begin
|
||||||
|
require 'tkextlib/version.rb'
|
||||||
require 'tkextlib/setup.rb'
|
require 'tkextlib/setup.rb'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
# ignore
|
# ignore
|
||||||
|
|
|
@ -289,7 +289,7 @@ module TkItemConfigMethod
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def itemconfiginfo(tagOrId, slot = nil)
|
def __itemconfiginfo_core(tagOrId, slot = nil)
|
||||||
if TkComm::GET_CONFIGINFO_AS_ARRAY
|
if TkComm::GET_CONFIGINFO_AS_ARRAY
|
||||||
if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
|
if (slot && slot.to_s =~ /^(|latin|ascii|kanji)(#{__item_font_optkeys(tagid(tagOrId)).join('|')})$/)
|
||||||
fontkey = $2
|
fontkey = $2
|
||||||
|
@ -594,7 +594,7 @@ module TkItemConfigMethod
|
||||||
if v.empty?
|
if v.empty?
|
||||||
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
|
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = nil
|
||||||
else
|
else
|
||||||
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new
|
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = TkVarAccess.new(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1020,13 +1020,18 @@ module TkItemConfigMethod
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
private :__itemconfiginfo_core
|
||||||
|
|
||||||
|
def itemconfiginfo(tagOrId, slot = nil)
|
||||||
|
__itemconfiginfo_core(tagOrId, slot)
|
||||||
|
end
|
||||||
|
|
||||||
def current_itemconfiginfo(tagOrId, slot = nil)
|
def current_itemconfiginfo(tagOrId, slot = nil)
|
||||||
if TkComm::GET_CONFIGINFO_AS_ARRAY
|
if TkComm::GET_CONFIGINFO_AS_ARRAY
|
||||||
if slot
|
if slot
|
||||||
org_slot = slot
|
org_slot = slot
|
||||||
begin
|
begin
|
||||||
conf = itemconfiginfo(tagOrId, slot)
|
conf = __itemconfiginfo_core(tagOrId, slot)
|
||||||
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|
||||||
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
|
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
|
||||||
return {conf[0] => conf[-1]}
|
return {conf[0] => conf[-1]}
|
||||||
|
@ -1037,7 +1042,7 @@ module TkItemConfigMethod
|
||||||
"there is a configure alias loop about '#{org_slot}'"
|
"there is a configure alias loop about '#{org_slot}'"
|
||||||
else
|
else
|
||||||
ret = {}
|
ret = {}
|
||||||
itemconfiginfo(tagOrId).each{|conf|
|
__itemconfiginfo_core(tagOrId).each{|conf|
|
||||||
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|
||||||
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
|
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
|
||||||
ret[conf[0]] = conf[-1]
|
ret[conf[0]] = conf[-1]
|
||||||
|
@ -1047,7 +1052,7 @@ module TkItemConfigMethod
|
||||||
end
|
end
|
||||||
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
|
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
|
||||||
ret = {}
|
ret = {}
|
||||||
itemconfiginfo(slot).each{|key, conf|
|
itemconfiginfo(tagOrId, slot).each{|key, conf|
|
||||||
ret[key] = conf[-1] if conf.kind_of?(Array)
|
ret[key] = conf[-1] if conf.kind_of?(Array)
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
[ current support status of Tcl/Tk extensions ]
|
[ 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
|
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
|
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)
|
TkTreeCtrl CVS/Hd(2005-12-02)
|
||||||
http://sourceforge.net/projects/tktreectrl ==> treectrl
|
http://sourceforge.net/projects/tktreectrl ==> treectrl
|
||||||
|
|
||||||
Tile CVS/Hd(2006-10-01)
|
Tile 0.7.8
|
||||||
http://sourceforge.net/projects/tktable ==> tile
|
http://sourceforge.net/projects/tktable ==> tile
|
||||||
|
|
||||||
|
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,6 @@
|
||||||
|
#
|
||||||
|
# release date of tkextlib
|
||||||
|
#
|
||||||
|
module Tk
|
||||||
|
Tkextlib_RELEASE_DATE = '2006-11-06'.freeze
|
||||||
|
end
|
|
@ -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
|
|
@ -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
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
#
|
#
|
||||||
# sample class of handling I/O stream on a TkText widget
|
# TkTextIO class :: handling I/O stream on a TkText widget
|
||||||
# by Hidetoshi NAGAI
|
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
|
||||||
#
|
#
|
||||||
# NOTE: TkTextIO supports 'character' (not 'byte') access only.
|
# NOTE: TkTextIO supports 'character' (not 'byte') access only.
|
||||||
# So, for example, TkTextIO#getc returns a character, TkTextIO#pos
|
# So, for example, TkTextIO#getc returns a character, TkTextIO#pos
|
||||||
|
@ -14,68 +14,375 @@
|
||||||
# TkTextIO.
|
# TkTextIO.
|
||||||
#
|
#
|
||||||
require 'tk'
|
require 'tk'
|
||||||
|
require 'tk/text'
|
||||||
|
require 'tk/textmark'
|
||||||
|
require 'thread'
|
||||||
|
|
||||||
class TkTextIO < TkText
|
class TkTextIO < TkText
|
||||||
def create_self(keys)
|
# keep safe level
|
||||||
mode = nil
|
@@create_queues = proc{ [Queue.new, Mutex.new, Queue.new, Mutex.new] }
|
||||||
ovwt = false
|
|
||||||
text = nil
|
|
||||||
wrap = 'char'
|
|
||||||
show = :pos
|
|
||||||
|
|
||||||
if keys.kind_of?(Hash)
|
OPT_DEFAULTS = {
|
||||||
mode = keys.delete('mode')
|
'mode' => nil,
|
||||||
ovwt = keys.delete('overwrite')
|
'overwrite' => false,
|
||||||
text = keys.delete('text')
|
'text' => nil,
|
||||||
show = keys.delete('show') if keys.has_key?('show')
|
'show' => :pos,
|
||||||
wrap = keys.delete('wrap') || 'char'
|
'wrap' => 'char',
|
||||||
end
|
'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)
|
super(keys)
|
||||||
|
|
||||||
self['wrap'] = wrap
|
@count_var = TkVariable.new
|
||||||
insert('1.0', text)
|
|
||||||
|
|
||||||
@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
|
@txtpos.gravity = :left
|
||||||
|
|
||||||
self.show_mode = show
|
|
||||||
|
|
||||||
@sync = true
|
|
||||||
@overwrite = (ovwt)? true: false
|
|
||||||
|
|
||||||
@lineno = 0
|
@lineno = 0
|
||||||
@line_offset = 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+'
|
@open = {:r => true, :w => true} # default is 'r+'
|
||||||
|
|
||||||
case mode
|
@console_mode = false
|
||||||
when 'r'
|
@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
|
@open[:r] = true; @open[:w] = nil
|
||||||
|
|
||||||
when 'r+'
|
when 'r+', 'rb+', 'r+b'
|
||||||
@open[:r] = true; @open[:w] = true
|
@open[:r] = true; @open[:w] = true
|
||||||
|
|
||||||
when 'w'
|
when 'w', 'wb'
|
||||||
@open[:r] = nil; @open[:w] = true
|
@open[:r] = nil; @open[:w] = true
|
||||||
self.value=''
|
self.value=''
|
||||||
|
|
||||||
when 'w+'
|
when 'w+', 'wb+', 'w+b'
|
||||||
@open[:r] = true; @open[:w] = true
|
@open[:r] = true; @open[:w] = true
|
||||||
self.value=''
|
self.value=''
|
||||||
|
|
||||||
when 'a'
|
when 'a', 'ab'
|
||||||
@open[:r] = nil; @open[:w] = true
|
@open[:r] = nil; @open[:w] = true
|
||||||
@txtpos = TkTextMark.new(self, 'end - 1 char')
|
@txtpos.set('end - 1 char')
|
||||||
@txtpos.gravity = :right
|
@txtpos.gravity = :right
|
||||||
|
|
||||||
when 'a+'
|
when 'a+', 'ab+', 'a+b'
|
||||||
@open[:r] = true; @open[:w] = true
|
@open[:r] = true; @open[:w] = true
|
||||||
@txtpos = TkTextMark.new(self, 'end - 1 char')
|
@txtpos.set('end - 1 char')
|
||||||
@txtpos.gravity = :right
|
@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
|
||||||
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)
|
def <<(obj)
|
||||||
_write(obj)
|
_write(obj)
|
||||||
|
@ -107,14 +414,15 @@ class TkTextIO < TkText
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def closed?
|
def closed?(dir=nil)
|
||||||
close_read? && close_write?
|
case dir
|
||||||
end
|
when :r, 'r'
|
||||||
def closed_read?
|
!@open[:r]
|
||||||
!@open[:r]
|
when :w, 'w'
|
||||||
end
|
!@open[:w]
|
||||||
def closed_write?
|
else
|
||||||
!@open[:w]
|
!@open[:r] && !@open[:w]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def _check_readable
|
def _check_readable
|
||||||
|
@ -129,7 +437,7 @@ class TkTextIO < TkText
|
||||||
|
|
||||||
def each_line(rs = $/)
|
def each_line(rs = $/)
|
||||||
_check_readable
|
_check_readable
|
||||||
while(s = gets)
|
while(s = self.gets(rs))
|
||||||
yield(s)
|
yield(s)
|
||||||
end
|
end
|
||||||
self
|
self
|
||||||
|
@ -138,7 +446,7 @@ class TkTextIO < TkText
|
||||||
|
|
||||||
def each_char
|
def each_char
|
||||||
_check_readable
|
_check_readable
|
||||||
while(c = getc)
|
while(c = self.getc)
|
||||||
yield(c)
|
yield(c)
|
||||||
end
|
end
|
||||||
self
|
self
|
||||||
|
@ -151,7 +459,7 @@ class TkTextIO < TkText
|
||||||
alias eof eof?
|
alias eof eof?
|
||||||
|
|
||||||
def fcntl(*args)
|
def fcntl(*args)
|
||||||
fail NotImplementedError, 'fcntl is not implemented on TkTextIO'
|
fail NotImplementedError, "fcntl is not implemented on #{self.class}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def fsync
|
def fsync
|
||||||
|
@ -163,11 +471,19 @@ class TkTextIO < TkText
|
||||||
end
|
end
|
||||||
|
|
||||||
def flush
|
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
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def getc
|
def getc
|
||||||
|
return _block_read(1) if @console_mode
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
return nil if eof?
|
return nil if eof?
|
||||||
c = get(@txtpos)
|
c = get(@txtpos)
|
||||||
|
@ -177,8 +493,10 @@ class TkTextIO < TkText
|
||||||
end
|
end
|
||||||
|
|
||||||
def gets(rs = $/)
|
def gets(rs = $/)
|
||||||
|
return _block_read(rs) if @console_mode
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
return nil if eof?
|
return nil if eof?
|
||||||
_readline(rs)
|
_readline(rs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -233,7 +551,6 @@ class TkTextIO < TkText
|
||||||
alias tell pos
|
alias tell pos
|
||||||
|
|
||||||
def pos=(idx)
|
def pos=(idx)
|
||||||
# @txtpos.set((idx.kind_of?(Numeric))? "1.0 + #{idx} char": idx)
|
|
||||||
seek(idx, IO::SEEK_SET)
|
seek(idx, IO::SEEK_SET)
|
||||||
idx
|
idx
|
||||||
end
|
end
|
||||||
|
@ -306,6 +623,8 @@ class TkTextIO < TkText
|
||||||
private :_read
|
private :_read
|
||||||
|
|
||||||
def read(len=nil, buf=nil)
|
def read(len=nil, buf=nil)
|
||||||
|
return _block_read(len, buf) if @console_mode
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
if len
|
if len
|
||||||
return "" if len == 0
|
return "" if len == 0
|
||||||
|
@ -321,6 +640,8 @@ class TkTextIO < TkText
|
||||||
end
|
end
|
||||||
|
|
||||||
def readchar
|
def readchar
|
||||||
|
return _block_read(1) if @console_mode
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
fail EOFError if eof?
|
fail EOFError if eof?
|
||||||
c = get(@txtpos)
|
c = get(@txtpos)
|
||||||
|
@ -334,6 +655,7 @@ class TkTextIO < TkText
|
||||||
s = get(@txtpos, 'end - 1 char')
|
s = get(@txtpos, 'end - 1 char')
|
||||||
@txtpos.set('end - 1 char')
|
@txtpos.set('end - 1 char')
|
||||||
elsif rs == ''
|
elsif rs == ''
|
||||||
|
@count_var.value # make it global
|
||||||
idx = tksearch_with_count([:regexp], @count_var,
|
idx = tksearch_with_count([:regexp], @count_var,
|
||||||
"\n(\n)+", @txtpos, 'end - 1 char')
|
"\n(\n)+", @txtpos, 'end - 1 char')
|
||||||
if idx
|
if idx
|
||||||
|
@ -345,6 +667,7 @@ class TkTextIO < TkText
|
||||||
@txtpos.set('end - 1 char')
|
@txtpos.set('end - 1 char')
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@count_var.value # make it global
|
||||||
idx = tksearch_with_count(@count_var, rs, @txtpos, 'end - 1 char')
|
idx = tksearch_with_count(@count_var, rs, @txtpos, 'end - 1 char')
|
||||||
if idx
|
if idx
|
||||||
s = get(@txtpos, "#{idx} + #{@count_var.value} char")
|
s = get(@txtpos, "#{idx} + #{@count_var.value} char")
|
||||||
|
@ -363,12 +686,22 @@ class TkTextIO < TkText
|
||||||
private :_readline
|
private :_readline
|
||||||
|
|
||||||
def readline(rs = $/)
|
def readline(rs = $/)
|
||||||
|
return _block_readline(rs) if @console_mode
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
fail EOFError if eof?
|
fail EOFError if eof?
|
||||||
_readline(rs)
|
_readline(rs)
|
||||||
end
|
end
|
||||||
|
|
||||||
def readlines(rs = $/)
|
def readlines(rs = $/)
|
||||||
|
if @console_mode
|
||||||
|
lines = []
|
||||||
|
while (line = _block_readline(rs))
|
||||||
|
lines << line
|
||||||
|
end
|
||||||
|
return lines
|
||||||
|
end
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
lines = []
|
lines = []
|
||||||
until(eof?)
|
until(eof?)
|
||||||
|
@ -379,7 +712,11 @@ class TkTextIO < TkText
|
||||||
end
|
end
|
||||||
|
|
||||||
def readpartial(maxlen, buf=nil)
|
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
|
_check_readable
|
||||||
|
fail EOFError if eof?
|
||||||
s = _read(maxlen)
|
s = _read(maxlen)
|
||||||
buf.replace(s) if buf.kind_of?(String)
|
buf.replace(s) if buf.kind_of?(String)
|
||||||
s
|
s
|
||||||
|
@ -471,6 +808,8 @@ class TkTextIO < TkText
|
||||||
end
|
end
|
||||||
|
|
||||||
def sysread(len, buf=nil)
|
def sysread(len, buf=nil)
|
||||||
|
return _block_read(len, buf) if @console_mode
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
fail EOFError if eof?
|
fail EOFError if eof?
|
||||||
s = _read(len)
|
s = _read(len)
|
||||||
|
@ -492,6 +831,13 @@ class TkTextIO < TkText
|
||||||
end
|
end
|
||||||
|
|
||||||
def ungetc(c)
|
def ungetc(c)
|
||||||
|
if @console_mode
|
||||||
|
@read_buf_mutex.synchronize {
|
||||||
|
@read_buffer[0,0] = c.chr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
_check_readable
|
_check_readable
|
||||||
c = c.chr if c.kind_of?(Fixnum)
|
c = c.chr if c.kind_of?(Fixnum)
|
||||||
if compare(@txtpos, '>', '1.0')
|
if compare(@txtpos, '>', '1.0')
|
||||||
|
@ -506,8 +852,10 @@ class TkTextIO < TkText
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
def _write(obj)
|
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))
|
n = number(tk_call('string', 'length', s))
|
||||||
delete(@txtpos, @txtpos + "#{n} char") if @overwrite
|
delete(@txtpos, @txtpos + "#{n} char") if @overwrite
|
||||||
self.insert(@txtpos, s)
|
self.insert(@txtpos, s)
|
||||||
|
@ -518,6 +866,37 @@ class TkTextIO < TkText
|
||||||
n
|
n
|
||||||
end
|
end
|
||||||
private :_write
|
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)
|
def write(obj)
|
||||||
_check_writable
|
_check_writable
|
||||||
|
@ -529,13 +908,19 @@ end
|
||||||
# TEST
|
# TEST
|
||||||
####################
|
####################
|
||||||
if __FILE__ == $0
|
if __FILE__ == $0
|
||||||
|
ev_loop = Thread.new{Tk.mainloop}
|
||||||
|
|
||||||
f = TkFrame.new.pack
|
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"){
|
: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)
|
pack(:side=>:left, :fill=>:both, :expand=>true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tk.update
|
||||||
|
|
||||||
$stdin = tio
|
$stdin = tio
|
||||||
$stdout = tio
|
$stdout = tio
|
||||||
$stderr = tio
|
$stderr = tio
|
||||||
|
@ -599,5 +984,67 @@ if __FILE__ == $0
|
||||||
|
|
||||||
tio.seek(0, IO::SEEK_END)
|
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
|
end
|
||||||
|
|
Загрузка…
Ссылка в новой задаче