1# search.rb 2# 3# This demonstration script creates a collection of widgets that 4# allow you to load a file into a text widget, then perform searches 5# on that file. 6# 7# Text Search widget demo (called by 'widget') 8# 9 10# textLoadFile -- 11# This method below loads a file into a text widget, discarding 12# the previous contents of the widget. Tags for the old widget are 13# not affected, however. 14# 15# Arguments: 16# w - The window into which to load the file. Must be a 17# text widget. 18# file - The name of the file to load. Must be readable. 19 20def textLoadFile(w,file) 21 w.delete('1.0', 'end') 22 f = open(file, 'r') 23 while(!f.eof?) 24 w.insert('end', f.read(1000)) 25 end 26 f.close 27end 28 29# textSearch -- 30# Search for all instances of a given string in a text widget and 31# apply a given tag to each instance found. 32# 33# Arguments: 34# w - The window in which to search. Must be a text widget. 35# string - The string to search for. The search is done using 36# exact matching only; no special characters. 37# tag - Tag to apply to each instance of a matching string. 38 39def textSearch(w, string, tag) 40 tag.remove('0.0', 'end') 41 return if string == "" 42 cur = '1.0' 43 loop { 44 cur, len = w.search_with_length(string, cur, 'end') 45 break if cur == "" 46 tag.add(cur, "#{cur} + #{len} char") 47 cur = w.index("#{cur} + #{len} char") 48 } 49end 50 51# textToggle -- 52# This method is invoked repeatedly to invoke two commands at 53# periodic intervals. It normally reschedules itself after each 54# execution but if an error occurs (e.g. because the window was 55# deleted) then it doesn't reschedule itself. 56# 57# Arguments: 58# cmd1 - Command to execute when method is called. 59# sleep1 - Ms to sleep after executing cmd1 before executing cmd2. 60# cmd2 - Command to execute in the *next* invocation of this method. 61# sleep2 - Ms to sleep after executing cmd2 before executing cmd1 again. 62 63def textToggle(cmd1,sleep1,cmd2,sleep2) 64 sleep_list = [sleep2, sleep1] 65 TkAfter.new(proc{sleep = sleep_list.shift; sleep_list.push(sleep); sleep}, 66 -1, cmd1, cmd2).start(sleep1) 67end 68 69# toplevel widget 70if defined?($search_demo) && $search_demo 71 $search_demo.destroy 72 $search_demo = nil 73end 74 75# demo toplevel widget 76$search_demo = TkToplevel.new {|w| 77 title("Text Demonstration - Search and Highlight") 78 iconname("search") 79 positionWindow(w) 80} 81 82base_frame = TkFrame.new($search_demo).pack(:fill=>:both, :expand=>true) 83 84# frame 85$search_buttons = TkFrame.new(base_frame) {|frame| 86 TkButton.new(frame) { 87 text 'Dismiss' 88 command proc{ 89 tmppath = $search_demo 90 $search_demo = nil 91 tmppath.destroy 92 } 93 }.pack('side'=>'left', 'expand'=>'yes') 94 95 TkButton.new(frame) { 96 text 'Show Code' 97 command proc{showCode 'search'} 98 }.pack('side'=>'left', 'expand'=>'yes') 99} 100$search_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m') 101 102# frame 103TkFrame.new(base_frame) {|f| 104 TkLabel.new(f, 'text'=>'File name:', 105 'width'=>13, 'anchor'=>'w').pack('side'=>'left') 106 $search_fileName = TkVariable.new 107 TkEntry.new(f, 'width'=>40, 108 'textvariable'=>$search_fileName) { 109 pack('side'=>'left') 110 bind('Return', proc{textLoadFile($search_text, $search_fileName.value) 111 $search_string_entry.focus}) 112 focus 113 } 114 TkButton.new(f, 'text'=>'Load File', 115 'command'=>proc{textLoadFile($search_text, 116 $search_fileName.value)})\ 117 .pack('side'=>'left', 'pady'=>5, 'padx'=>10) 118}.pack('side'=>'top', 'fill'=>'x') 119 120TkFrame.new(base_frame) {|f| 121 TkLabel.new(f, 'text'=>'Search string:', 122 'width'=>13, 'anchor'=>'w').pack('side'=>'left') 123 $search_searchString = TkVariable.new 124 $search_string_entry = TkEntry.new(f, 'width'=>40, 125 'textvariable'=>$search_searchString) { 126 pack('side'=>'left') 127 bind('Return', proc{textSearch($search_text, $search_searchString.value, 128 $search_Tag)}) 129 } 130 TkButton.new(f, 'text'=>'Highlight', 131 'command'=>proc{textSearch($search_text, 132 $search_searchString.value, 133 $search_Tag)}) { 134 pack('side'=>'left', 'pady'=>5, 'padx'=>10) 135 } 136}.pack('side'=>'top', 'fill'=>'x') 137 138$search_text = TkText.new(base_frame, 'setgrid'=>true, 'wrap'=>'word') {|t| 139 $search_Tag = TkTextTag.new(t) 140 TkScrollbar.new(base_frame, 'command'=>proc{|*args| t.yview(*args)}) {|sc| 141 t.yscrollcommand(proc{|first,last| sc.set first,last}) 142 pack('side'=>'right', 'fill'=>'y') 143 } 144 pack('expand'=>'yes', 'fill'=>'both') 145} 146 147# Set up display styles for text highlighting. 148 149if TkWinfo.depth($search_demo) > 1 150 textToggle(proc{ 151 $search_Tag.configure('background'=>'#ce5555', 152 'foreground'=>'white') 153 }, 154 800, 155 proc{ 156 $search_Tag.configure('background'=>'', 'foreground'=>'') 157 }, 158 200 ) 159else 160 textToggle(proc{ 161 $search_Tag.configure('background'=>'black', 162 'foreground'=>'white') 163 }, 164 800, 165 proc{ 166 $search_Tag.configure('background'=>'', 'foreground'=>'') 167 }, 168 200 ) 169end 170$search_text.insert('1.0', "\ 171This window demonstrates how to use the tagging facilities in text \ 172widgets to implement a searching mechanism. First, type a file name \ 173in the top entry, then type <Return> or click on \"Load File\". Then \ 174type a string in the lower entry and type <Return> or click on \ 175\"Load File\". This will cause all of the instances of the string to \ 176be tagged with the tag \"search\", and it will arrange for the tag\'s \ 177display attributes to change to make all of the strings blink.") 178$search_text.insert('end', "\ 179The current directory to load a file is \"#{Dir.pwd}\".\ 180") 181$search_text.set_insert '0.0' 182 183$search_fileName.value = '' 184$search_searchString.value = '' 185 186$search_text.width = 60 187$search_text.height = 20 188