Version 3 of Simple search and replace

Updated 2006-03-17 23:13:12

Richard Suchenwirth 2006-03-17 - Here's a search (and replace) dialog implemented in a pretty minimal way, yet it feels usable to me. (Called with 0 as second argument, it skips the replace elements.)

http://mini.net/files/searchrep.jpg

You can tie it to a text widget (see demo code below), and, well, just try it for yourself... The "exported API" is the searchrep proc which you might bind to menu items or a key combination:

 proc searchrep {t {replace 1}} {
    set w .sr
    if ![winfo exists $w] {
        toplevel $w
        wm title $w "Search"
        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 

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


Category Example | Arts and crafts of Tcl-Tk programming