ReadChar

pmarin. ReadChar is an implementation of the classic getc and putbak functions.
For more info see the page 255 of Software Tools by Kernighan and Plauger.
The code is part of Muddy Scheme


package require TclOO
package require struct::stack

oo::class create ReadChar {

        constructor {{chan stdin}} {
                my variable ch 
                my variable buf
                set ch $chan
                set buf [struct::stack]
        }
        
        method getc {} {
                my variable ch
                my variable buf
                if  {[$buf size]} {
                        return [$buf pop]
                } else {
                        if {![eof $ch]} {
                                return [read $ch 1] 
                        } else {
                                return "eof"        
                        }
                }
        }
        
        method eof {} {
                my variable ch
                my variable buf
                if { ![$buf size] && [eof $ch] } {
                        return 1 
                } else {
                        return 0 
                }
        }
        
        method peek {} {
                my variable ch 
                my variable buf

                if  {[$buf size]} {
                        return [$buf peek]
                } else {
                        if {![eof $ch]} {
                                set c [read $ch 1]
                                $buf push $c 
                                return $c
                        } else {
                                return "eof"        
                        }
                }

        }

        method putbak str {
                my variable buf
                if { [string length $str] > 0 } {
                        if { [string length $str] == 1 } {
                                $buf push $str
                        } else {
                                foreach i [split [string reverse $str] {}] {
                                        $buf push $i        
                                }
                        }
                }
        }

        destructor  {
                my variable ch 
                my variable buf
                $buf destroy
                close $ch
        }
}

Comments

It is rare that It is not already implemented in the core libraries... Am I missing something?

DCP: Never ever needed to read or write a single char in Tcl in the last 10-15 years!
pmarin: Even the C Standard Library comes with getc and ungetc (stdio.h)!


LVwikignome - 2010-01-20 12:54:00

So, what would an example of using the above code look like? Is it a true getc, in that the application using the above code will get a single character at a time, without a newline needing to be typed?

(2010-1-20) pmarin. It is like getc and ungetc functions in C. Tcl I/O can't return characters to the buffer, or not? :

# An implementation of cat 
# cat.tcl

ReadChar create rchar ; # by default use stdin
while { ![rchar eof] } {
   puts -nonewline [rchar getc] 
}

Another example:

> ReadChar create rchar
::rchar
> rchar putbak "hello wolrd"
> puts [rchar peek]
h
> puts [rchar getc]
h
> puts [rchar getc]
e 
> puts "[rchar getc][rchar getc][rchar getc]"
llo
> rchar destroy

> set a [rchar getc]
123
1
> 23

I am using this class in the reader of Muddy Scheme


LVwikignome - 2010-01-20 14:27:55

so ReadChar getc returns 1 character. However, the character is only provided to ReadChar after the user has typed text in and hit return.

If you want a single character, to process as it is typed, you will first need to put the keyboard into raw mode.