-fg color foreground color. -bg color background color. -style effect text style.where "color" is one of: black, red, green, yellow, blue, magenta, cyan or whiteand "effect" is one of: none, bright, dim, underline, blink or reverseMore than one match may be specified.Example, color the line containing "foo" red and underline the word "bar": cgrep '^.*foo.*$' -fg red 'bar' -style underlineSee Also: ANSI color controlCode:
#! /usr/bin/env tclsh proc ESC {} {return \033} proc ANSI {args} { # Support list and args conventions: if {[llength $args] == 1 && [llength [lindex $args 0]] > 1} { set args [lindex $args 0] } set ret "\033\[" foreach {op val} $args { switch -- $op { -style {} -bg {append ret 4} -fg {append ret 3} } switch -- $val { black {append ret "0;"} red {append ret "1;"} green {append ret "2;"} yellow {append ret "3;"} blue {append ret "4;"} magenta {append ret "5;"} cyan {append ret "6;"} white {append ret "7;"} none {append ret "0;"} bright {append ret "1;"} dim {append ret "2;"} underline {append ret "4;"} blink {append ret "5;"} reverse {append ret "7;"} } } set ret [string trim $ret ";"] return ${ret}m } fconfigure stdin -buffering none fconfigure stdout -buffering none -translation binary if {$argv == ""} { set title "cgrep:" append title "[ANSI -fg green -bg black] C" append title "[ANSI -fg red]o" append title "[ANSI -fg yellow]l" append title "[ANSI -fg cyan]o" append title "[ANSI -fg white]r " append title "[ANSI -style none]your text!" puts $title puts {usage: cgrep regexp option option ... Where regexp is a regular expression to match and option describes how to color the matched text. The options are one or more of: -fg color foreground color. -bg color background color. -style effect text style. where "color" is one of: black, red, green, yellow, blue, magenta, cyan or white and "effect" is one of: none, bright, dim, underline, blink or reverse More than one match may be specified. Example, color the line containing "foo" red and underline the word "bar": cgrep '^.*foo.*$' -fg red 'bar' -style underline } exit } # Support named patterns: if {([llength $argv] == 1) && [file exists ~/.cgrep]} { set f [open ~/.cgrep] set data [read $f] close $f foreach {name patterns} $data { if {$name == [lindex $argv 0]} { set argv $patterns break } } } proc shift {ls} { upvar 1 $ls LIST if {[llength $LIST]} { set ret [lindex $LIST 0] set LIST [lreplace $LIST 0 0] return $ret } else { error "Ran out of list elements." } } proc unshift {ls val} { upvar 1 $ls LIST set LIST [concat [list $val] $LIST] } proc process_args {argv} { set ret [list] while {[llength $argv]} { set re [shift argv] set format [list] while {[llength $argv]} { set op [shift argv] switch -exact -- $op { -fg - -bg - -style { set x [shift argv] if {[string match -* $x]} { unshift argv $x unshift argv $op break } lappend format $op $x } default { unshift argv $op break } } } lappend ret $re $format } return $ret } proc merge_color {current new} { array set c {-bg {} -fg {} -style {}} array set n {-bg {} -fg {} -style {}} foreach {style arr} {current c new n} { array set $arr [set $style] } foreach x {-bg -fg -style} { if {$n($x) == ""} { if {$c($x) != ""} { set n($x) $c($x) } else { unset n($x) } } } return [array get n] } proc get_matches {line formatting} { set ret [list] foreach {re color} $formatting { set matches [regexp -inline -all -indices -- $re $line] foreach m $matches { foreach {start end} $m {incr end; break} lappend ret [list $start start $color] lappend ret [list $end end $color] } } return $ret } proc resequence {formatting} { set ret [list] set cstack [list] foreach x [lsort -dictionary $formatting] { foreach {mark type color} $x break switch -- $type { start { unshift cstack $color set color [merge_color [lindex $cstack 0] $color] # unshift cstack $color set clist [list $color] } end { shift cstack set clist {{-style none}} lappend clist [lindex $cstack 0] } } lappend ret $mark $clist } return $ret } proc render_line {line formatting} { set n 0 set ret "" foreach {mark colors} $formatting { append ret [string range $line $n [expr {$mark-1}]] foreach color $colors { append ret [ANSI $color] #append ret "{$color}" } set n $mark } append ret [string range $line $n end] append ret [ANSI {-style none}] #append ret "{-none}" return $ret } proc main {argv} { set args [process_args $argv] while {[gets stdin line] >= 0} { puts [render_line $line [resequence [get_matches $line $args]]] } } main $argv
Jorge - 2013-05-11 03:32:47I think the very last line should read:
main $argv(I may be wrong)I tried the following and it works great:
tclsh cgrep.tcl '^proc.*{$' -fg red '^proc' -style underline < cgrep.tclthanks for sharing!slebetman - 2014-08-20@Jorge: Thanks for that bug report. Sorry it took me a long time to notice :)