How Expect sees function keys

Run this:

    puts "Type any characters, then <Return>."

    expect {
        ? {
            set result $expect_out(0,string)
            if {[string compare \n $result]} {
                scan $result %c value
                if {$value==27} {
                    puts "You just typed Esc (decimal ASCII 27)."
                } {
                    puts "You just typed '$result' (decimal ASCII $value)."
                }
            }
            exp_continue
        }
    }

Example output: type "a<CR>", see decimal 97; type "<F1><CR>", see the sequence

27-91-49-(49,50)-126 [explain] Win 95


Also see "keysyms", CWIND, and "How to send escape characters through Expect".


Csan The original code did not handle the Esc $result properly - it ate the second ' character in the output. I added a branch to handle that case.

I also extended the output to include the octal and hexadecimal values - useful for further re-use of the $result - see further on. Another addition was to save the resulting character (sequence) to keyseq.dat, which can be imported into another text editor. I find this addition very useful while using 'joe' editor...

2008-08-06: new version, with corrected output (cosmetic changes, prettier output, correct text), switched to string equal and also handling the Enter-only case

The new version of the script (I called it keyseqs.exp):

 #!/usr/bin/expect

 set timeout 10
 set outfile ./keyseq.dat

 set prompt "Type any characters followed by <Return>, wait for $timeout seconds or press Ctrl-C
 The resulting character sequence will be written to $outfile

 Type here:
 "

 set showheader 1
 set seqsize 0
 puts $prompt

 expect {
   ? {
     set result $expect_out(0,string)
     if {![string equal \n $result]} {
       if {[catch {eof $fd}]} {
         set fd [open $outfile w]
       }
       scan $result %c dvalue

       set show $result
       if {$dvalue==27} {
           set show Esc
       }
       if {$showheader} {
         puts "\nWhat you have just entered I can see as the following byte sequence:\n"
         set showheader 0
       }
       puts "'$show'\t(ASCII octal [format %4s [format %#o $dvalue]], decimal [format %3s $dvalue], hexadecimal [format %x $dvalue])"

       puts -nonewline $fd $result
       incr seqsize
     } {
       if {$seqsize==0} {
         puts "You only typed Enter. $outfile is empty."
         set seqsize 0
       }
       if {![catch {eof $fd}]} {
         close $fd
         puts "\n$outfile created.\n-+----\n$prompt"
         set showheader 1
       }
     }
     exp_continue
   }
 }

Example output (I typed PageUp):

 # ./keyseqs.exp
 Type any characters followed by <Return>, wait for 10 seconds or press Ctrl-C
 The resulting character sequence will be written to ./keyseq.dat

 Type here:

 ^[[5~

 What you have just entered I can see as the following byte sequence:

 'Esc'   (ASCII octal  033, decimal  27, hexadecimal 1b)
 '['     (ASCII octal 0133, decimal  91, hexadecimal 5b)
 '5'     (ASCII octal  065, decimal  53, hexadecimal 35)
 '~'     (ASCII octal 0176, decimal 126, hexadecimal 7e)

 ./keyseq.dat created.
 -+----
 Type any characters followed by <Return>, wait for 10 seconds or press Ctrl-C
 The resulting character sequence will be written to ./keyseq.dat

 Type here:

 #

LV says: "Believe it or not, there is no set standard for what function keys generate. In fact the same function key could generate different values (for different applications) on some systems." That is to say, on some terminals or terminal emulators, one actually can program the value to be returned by the function key. Sometimes this can be done via software. Sometimes, as in the case of xterm, it can also be done via the X option database (app-defaults, etc.). I've been in situations where people had the function keys on their xterms generate an escape sequence for some applications, and commands in other windows, etc.