Updated 2006-11-29 03:45:49

This is the commented version of RS's Simple Search and replace.

proc searchrep {t {replace 1}} {

# The procedure is called searchrep. A value should be returned in the # end?
    set w .sr

#
    if ![winfo exists $w] {

#
	toplevel $w

	wm title $w "Search"

# The title Search should appear ...
	grid [label $w.1 -text Find:] [entry $w.f -textvar Find] \
		[button $w.bn -text Next \
		-command [list searchrep'next $t]] -sticky ew
	bind $w.f <Return> [list $w.bn invoke]
	if $replace {
	    grid [label $w.2 -text Replace:] [entry $w.r -textvar Replace] \
		    [button $w.br -text Replace \
		    -command [list searchrep'rep1 $t]] -sticky ew
	    bind $w.r <Return> [list $w.br invoke]
	    grid x x [button $w.ba -text "Replace all" \
		    -command [list searchrep'all $t]] -sticky ew
	}
	grid x [checkbutton $w.i -text "Ignore case" -variable IgnoreCase] \
		[button $w.c -text Cancel -command "destroy $w"] -sticky ew
	grid $w.i -sticky w
	grid columnconfigure $w 1 -weight 1
	$t tag config hilite -background yellow
    } else {raise $w}
 }

#-- Find the next instance
 proc searchrep'next w {
     foreach {from to} [$w tag ranges hilite] {
	 $w tag remove hilite $from $to
     }
     set cmd [list $w search -count n -- $::Find insert+2c]
     if $::IgnoreCase {set cmd [linsert $cmd 2 -nocase]}
     set pos [eval $cmd]
     if {$pos ne ""} {
	 $w mark set insert $pos
	 $w see insert
	 $w tag add hilite $pos $pos+${n}c
     }
 }

#-- Replace the current instance, and find the next
 proc searchrep'rep1 w {
     if {[$w tag ranges hilite] ne ""} {
	 $w delete insert insert+[string length $::Find]c
	 $w insert insert $::Replace
	 searchrep'next $w
	 return 1
     } else {return 0}
 }

#-- Replace all
 proc searchrep'all w {
     set go 1
     while {$go} {set go [searchrep'rep1 $w]}
 }

#---------------- Test and demo:
 package require Tk
 pack [text .t]
 .t insert end "hello world, this is some text to test on"
 searchrep .t

Here's how to plug this functionality into e: a tiny editor plugin for eTcl:
 m+ $m Edit Search  {searchrep .t.t 0}
 m+ $m Edit Replace {searchrep .t.t}

For better looks, I changed the -sticky settings to "news" there (buttons come very low else). A deeper problem is that the dialog comes up at top left, and possibly covers the "hilited" search term. Other than reparenting it into a non-toplevel (like Pocket Word does), I have no good solution for that...

The solution is simple: don't use a dialog. Personally I like how Firefox does it, as a popup toolbar of sorts at the bottom of the window.

2006-03-18 HE Perfectly! I need an search dialog and the wiki has it just in time :-)

See also Searching in a text widget, Simple Search and Replace commented

Category Example | Arts and crafts of Tcl-Tk programming | Category Widget