LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 01-28-2007, 05:01 AM   #1
sadarax
Member
 
Registered: Sep 2005
Distribution: Ubuntu
Posts: 249

Rep: Reputation: 30
Bash case with arrow keys (and DEL, BACKSPACE,etc)


I am trying to write a bash script using 'case' but I cannot figure out what the escape sequence would be for the arrow keys. Also, getting the escape sequence for the delete and backspace keys would be useful too. I know that \d is supposed to be delete, but it is not detecting properly....
 
Old 01-28-2007, 06:29 AM   #2
unSpawn
Moderator
 
Registered: May 2001
Posts: 27,451
Blog Entries: 54

Rep: Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893
If you don't mind me asking, is there any specific reason why you (are forced to) focus on using those keys?
 
Old 01-28-2007, 06:36 AM   #3
sadarax
Member
 
Registered: Sep 2005
Distribution: Ubuntu
Posts: 249

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by unSpawn
If you don't mind me asking, is there any specific reason why you (are forced to) focus on using those keys?
Sure, I am writing a bash script that grabs a single key, and throws the input to a 'case' select system. It would be nice to be able to assign actions when someone uses the arrow keys, but that is not the real reason I want to know how to accommodate the arrow keys. Currently with my code, either the script crashes or quits (not quite sure) when I use arrow keys, the DEL key. Also I cannot seem to assign control keys like "CTRL+C" to close the script. Without being able to specify an action, the script just keeps running.
 
Old 01-28-2007, 09:05 AM   #4
unSpawn
Moderator
 
Registered: May 2001
Posts: 27,451
Blog Entries: 54

Rep: Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893Reputation: 2893
Hmm. Similar to OSD stuff, right? To start with the last, CTRL+C can't be assigned since it sends a signal. The "best" ways to handle that within a script is to use "trap" since you can assign anything to that like a function to clean up before you go. Crashing is always interesting :-] Did you try to run your script with "set -xe" below the shebang line and look at the output? As far as the keys thing is concerned there are scripts (here on LQ too IIRC) that read single char input but in what way you can use it, I don't know. The problem is you probably will have to intercept settings (maybe using a custom inputrc) to make the keys emit something you can use. To give you an idea see: http://www.ibb.net/~anne/keyboard/troubleshooting.html.
 
Old 12-16-2009, 11:30 AM   #5
StuartRothrock
LQ Newbie
 
Registered: Nov 2009
Posts: 7

Rep: Reputation: 0
Smile

This is a belated response - but maybe it can help someone else searching for a solution. Here is an example how to capture most keys and map them in the same file.

#!/bin/bash4 #(i copied bashV4 from F11 since it has associative arrays)
while IFS='^B' read -sn1 a # ^B is Control B
do
k=`perl -e "printf('%d',ord('$a'));"`
if (( k == 27 )) ; then
while IFS='' read -sn1 -t1 c
do
l=`perl -e "printf('%d',ord('$c'));"`
k="$k $l"
grep "^$k 0 " $0 > /dev/null
if (( $? == 0 )) ; then
break
fi
done
fi
echo $k
grep "^$k 0 " $0
done
# never gets here
exit

27 79 70 0 end
27 79 72 0 home
27 79 81 0 f2
27 79 82 0 f3
27 79 83 0 f4
27 91 49 53 126 0 f5
27 91 49 55 126 0 f6
27 91 49 56 126 0 f7
27 91 49 57 126 0 f8
27 91 50 48 126 0 f9
27 91 50 49 126 0 f10
27 91 50 52 126 0 f12
27 91 50 126 0 insert
27 91 51 126 0 delete
27 91 49 126 0 home
27 91 52 126 0 end
27 91 53 126 0 pageUp
27 91 54 126 0 pageDown
27 91 65 0 up
27 91 66 0 down
27 91 67 0 right
27 91 68 0 left
27 91 49 59 53 67 0 ctl-right
27 91 49 59 53 68 0 ctl-left
27 91 49 59 53 65 0 ctl-up
27 91 49 59 53 66 0 ctl-down
27 91 69 0 keypad-five
9 0 tab
33 0 bang
35 0 pound
36 0 dollarSign
37 0 percent
38 0 ampersand
40 0 openParen

Last edited by StuartRothrock; 12-16-2009 at 11:32 AM. Reason: tried to keep indentation...
 
Old 12-18-2011, 05:35 AM   #6
dethrophes
LQ Newbie
 
Registered: Nov 2011
Posts: 5

Rep: Reputation: Disabled
A more complete solution

for anybody who like me ended up here looking for this solution.

this solution should manage just about any key combination.
Note alot of the keys may/will be mapped to X, window manager, terminal, etc...

Only real proble is detecting Escape,ctrl-[,ctrl-O as they are part of the sequences of the other keys.
so for example with this implementation pressing Escape 2 within a second will return ctrl-[ instead of Escape.




Code:
	

SpecialKeyCodes="
0027 0000 0;ctrl-alt-Enter
0027 0001 0;ctrl-alt-a
0027 0002 0;ctrl-alt-b
0027 0003 0;ctrl-alt-c
0027 0004 0;ctrl-alt-d
0027 0005 0;ctrl-alt-e
0027 0006 0;ctrl-alt-f
0027 0007 0;ctrl-alt-g
0027 0008 0;ctrl-alt-h
0027 0009 0;ctrl-alt-i
0027 0010 0;ctrl-alt-j
0027 0011 0;ctrl-alt-k
0027 0012 0;ctrl-alt-l
0027 0013 0;ctrl-alt-m
0027 0014 0;ctrl-alt-n
0027 0015 0;ctrl-alt-o
0027 0016 0;ctrl-alt-p
0027 0017 0;ctrl-alt-q
0027 0018 0;ctrl-alt-r
0027 0019 0;ctrl-alt-s
0027 0020 0;ctrl-alt-t
0027 0021 0;ctrl-alt-u
0027 0022 0;ctrl-alt-v
0027 0023 0;ctrl-alt-w
0027 0024 0;ctrl-alt-x
0027 0025 0;ctrl-alt-y
0027 0026 0;ctrl-alt-z
0027 0027 0;ctrl-alt-[; Escape
0027 0029 0;ctrl-alt-]
0027 0029 0;ctrl-alt-}
0027 0030 0;ctrl-alt-^
0027 0031 0;ctrl-alt-_
0027 0032 0;ctrl-alt-space;		 	Space

0027 0079 0049 0059 0050 0070 0;shift-end
0027 0079 0049 0059 0050 0072 0;shift-home
0027 0079 0049 0059 0050 0080 0;shift-f1
0027 0079 0049 0059 0050 0081 0;shift-f2
0027 0079 0049 0059 0050 0082 0;shift-f3
0027 0079 0049 0059 0050 0083 0;shift-f4
0027 0079 0049 0059 0051 0070 0;alt-end
0027 0079 0049 0059 0051 0072 0;alt-home
0027 0079 0049 0059 0051 0080 0;alt-f1
0027 0079 0049 0059 0051 0081 0;alt-f2
0027 0079 0049 0059 0051 0082 0;alt-f3
0027 0079 0049 0059 0051 0083 0;alt-f4
0027 0079 0049 0059 0052 0070 0;alt-shift-end
0027 0079 0049 0059 0052 0072 0;alt-shift-home
0027 0079 0049 0059 0052 0080 0;alt-shift-f1
0027 0079 0049 0059 0052 0081 0;alt-shift-f2
0027 0079 0049 0059 0052 0082 0;alt-shift-f3
0027 0079 0049 0059 0052 0083 0;alt-shift-f4
0027 0079 0049 0059 0053 0070 0;ctrl-end
0027 0079 0049 0059 0053 0072 0;ctrl-home
0027 0079 0049 0059 0053 0080 0;ctrl-f1
0027 0079 0049 0059 0053 0081 0;ctrl-f2
0027 0079 0049 0059 0053 0082 0;ctrl-f3
0027 0079 0049 0059 0053 0083 0;ctrl-f4
0027 0079 0049 0059 0054 0070 0;ctrl-shift-end
0027 0079 0049 0059 0054 0072 0;ctrl-shift-home
0027 0079 0049 0059 0054 0080 0;ctrl-shift-f1
0027 0079 0049 0059 0054 0081 0;ctrl-shift-f2
0027 0079 0049 0059 0054 0082 0;ctrl-shift-f3
0027 0079 0049 0059 0054 0083 0;ctrl-shift-f4
0027 0079 0049 0059 0055 0070 0;ctrl-alt-end
0027 0079 0049 0059 0055 0072 0;ctrl-alt-home
0027 0079 0049 0059 0055 0080 0;ctrl-alt-f1
0027 0079 0049 0059 0055 0081 0;ctrl-alt-f2
0027 0079 0049 0059 0055 0082 0;ctrl-alt-f3
0027 0079 0049 0059 0055 0083 0;ctrl-alt-f4
0027 0079 0049 0059 0056 0070 0;ctrl-alt-shift-end
0027 0079 0049 0059 0056 0072 0;ctrl-alt-shift-home
0027 0079 0049 0059 0056 0080 0;ctrl-alt-shift-f1
0027 0079 0049 0059 0056 0081 0;ctrl-alt-shift-f2
0027 0079 0049 0059 0056 0082 0;ctrl-alt-shift-f3
0027 0079 0049 0059 0056 0083 0;ctrl-alt-shift-f4
0027 0079 0070 0;end
0027 0079 0072 0;home
0027 0079 0080 0;f1
0027 0079 0081 0;f2
0027 0079 0082 0;f3
0027 0079 0083 0;f4

0027 0091 0049 0053 0059 0050 0126 0;shift-f5
0027 0091 0049 0053 0059 0051 0126 0;alt-f5
0027 0091 0049 0053 0059 0052 0126 0;alt-shift-f5
0027 0091 0049 0053 0059 0053 0126 0;ctrl-f5
0027 0091 0049 0053 0059 0054 0126 0;ctrl-shift-f5
0027 0091 0049 0053 0059 0055 0126 0;ctrl-alt-f5
0027 0091 0049 0053 0059 0056 0126 0;ctrl-alt-shift-f5
0027 0091 0049 0053 0126 0;f5
0027 0091 0049 0055 0059 0050 0126 0;shift-f6
0027 0091 0049 0055 0059 0051 0126 0;alt-f6
0027 0091 0049 0055 0059 0052 0126 0;alt-shift-f6
0027 0091 0049 0055 0059 0053 0126 0;ctrl-f6
0027 0091 0049 0055 0059 0054 0126 0;ctrl-shift-f6
0027 0091 0049 0055 0059 0055 0126 0;ctrl-alt-f6
0027 0091 0049 0055 0059 0056 0126 0;ctrl-alt-shift-f6
0027 0091 0049 0055 0126 0;f6
0027 0091 0049 0056 0059 0050 0126 0;shift-f7
0027 0091 0049 0056 0059 0051 0126 0;alt-f7
0027 0091 0049 0056 0059 0052 0126 0;alt-shift-f7
0027 0091 0049 0056 0059 0053 0126 0;ctrl-f7
0027 0091 0049 0056 0059 0054 0126 0;ctrl-shift-f7
0027 0091 0049 0056 0059 0055 0126 0;ctrl-alt-f7
0027 0091 0049 0056 0059 0056 0126 0;ctrl-alt-shift-f7
0027 0091 0049 0056 0126 0;f7
0027 0091 0049 0057 0059 0050 0126 0;shift-f8
0027 0091 0049 0057 0059 0051 0126 0;alt-f8
0027 0091 0049 0057 0059 0052 0126 0;alt-shift-f8
0027 0091 0049 0057 0059 0053 0126 0;ctrl-f8
0027 0091 0049 0057 0059 0054 0126 0;ctrl-shift-f8
0027 0091 0049 0057 0059 0055 0126 0;ctrl-alt-f8
0027 0091 0049 0057 0059 0056 0126 0;ctrl-alt-shift-f8
0027 0091 0049 0057 0126 0;f8
0027 0091 0049 0059 0050 0065 0;shift-up
0027 0091 0049 0059 0050 0066 0;shift-down
0027 0091 0049 0059 0050 0067 0;shift-right
0027 0091 0049 0059 0050 0068 0;shift-left
0027 0091 0049 0059 0050 0069 0;shift-keypad-five
#0027 0091 0049 0059 0050 0126 0;shift-home
0027 0091 0049 0059 0051 0065 0;alt-up
0027 0091 0049 0059 0051 0066 0;alt-down
0027 0091 0049 0059 0051 0067 0;alt-right
0027 0091 0049 0059 0051 0068 0;alt-left
0027 0091 0049 0059 0051 0069 0;alt-keypad-five
#0027 0091 0049 0059 0051 0126 0;alt-home
0027 0091 0049 0059 0052 0065 0;alt-shift-up
0027 0091 0049 0059 0052 0066 0;alt-shift-down
0027 0091 0049 0059 0052 0067 0;alt-shift-right
0027 0091 0049 0059 0052 0068 0;alt-shift-left
0027 0091 0049 0059 0052 0069 0;alt-shift-keypad-five
#0027 0091 0049 0059 0052 0126 0;alt-shift-home
0027 0091 0049 0059 0053 0065 0;ctrl-up
0027 0091 0049 0059 0053 0066 0;ctrl-down
0027 0091 0049 0059 0053 0067 0;ctrl-right
0027 0091 0049 0059 0053 0068 0;ctrl-left
0027 0091 0049 0059 0053 0069 0;ctrl-keypad-five
#0027 0091 0049 0059 0053 0126 0;ctrl-home
0027 0091 0049 0059 0054 0065 0;ctrl-shift-up
0027 0091 0049 0059 0054 0066 0;ctrl-shift-down
0027 0091 0049 0059 0054 0067 0;ctrl-shift-right
0027 0091 0049 0059 0054 0068 0;ctrl-shift-left
0027 0091 0049 0059 0054 0069 0;ctrl-shift-keypad-five
#0027 0091 0049 0059 0054 0126 0;ctrl-shift-home
0027 0091 0049 0059 0055 0065 0;ctrl-alt-up
0027 0091 0049 0059 0055 0066 0;ctrl-alt-down
0027 0091 0049 0059 0055 0067 0;ctrl-alt-right
0027 0091 0049 0059 0055 0068 0;ctrl-alt-left
0027 0091 0049 0059 0055 0069 0;ctrl-alt-keypad-five
#0027 0091 0049 0059 0055 0126 0;ctrl-alt-home
0027 0091 0049 0059 0056 0065 0;ctrl-alt-shift-up
0027 0091 0049 0059 0056 0066 0;ctrl-alt-shift-down
0027 0091 0049 0059 0056 0067 0;ctrl-alt-shift-right
0027 0091 0049 0059 0056 0068 0;ctrl-alt-shift-left
0027 0091 0049 0059 0056 0069 0;ctrl-alt-shift-keypad-five
#0027 0091 0049 0059 0056 0126 0;ctrl-alt-shift-home
0027 0091 0049 0126 0;home
0027 0091 0050 0048 0059 0050 0126 0;shift-f9
0027 0091 0050 0048 0059 0051 0126 0;alt-f9
0027 0091 0050 0048 0059 0052 0126 0;alt-shift-f9
0027 0091 0050 0048 0059 0053 0126 0;ctrl-f9
0027 0091 0050 0048 0059 0054 0126 0;ctrl-shift-f9
0027 0091 0050 0048 0059 0055 0126 0;ctrl-alt-f9
0027 0091 0050 0048 0059 0056 0126 0;ctrl-alt-shift-f9
0027 0091 0050 0048 0126 0;f9
0027 0091 0050 0049 0059 0050 0126 0;shift-f10
0027 0091 0050 0049 0059 0051 0126 0;alt-f10
0027 0091 0050 0049 0059 0052 0126 0;alt-shift-f10
0027 0091 0050 0049 0059 0053 0126 0;ctrl-f10
0027 0091 0050 0049 0059 0054 0126 0;ctrl-shift-f10
0027 0091 0050 0049 0059 0055 0126 0;ctrl-alt-f10
0027 0091 0050 0049 0059 0056 0126 0;ctrl-alt-shift-f10
0027 0091 0050 0049 0126 0;f10
0027 0091 0050 0051 0059 0050 0126 0;shift-f11
0027 0091 0050 0051 0059 0051 0126 0;alt-f11
0027 0091 0050 0051 0059 0052 0126 0;alt-shift-f11
0027 0091 0050 0051 0059 0053 0126 0;ctrl-f11
0027 0091 0050 0051 0059 0054 0126 0;ctrl-shift-f11
0027 0091 0050 0051 0059 0055 0126 0;ctrl-alt-f11
0027 0091 0050 0051 0059 0056 0126 0;ctrl-alt-shift-f11
0027 0091 0050 0051 0126 0;f11
0027 0091 0050 0052 0059 0050 0126 0;shift-f12
0027 0091 0050 0052 0059 0051 0126 0;alt-f12
0027 0091 0050 0052 0059 0052 0126 0;alt-shift-f12
0027 0091 0050 0052 0059 0053 0126 0;ctrl-f12
0027 0091 0050 0052 0059 0054 0126 0;ctrl-shift-f12
0027 0091 0050 0052 0059 0055 0126 0;ctrl-alt-f12
0027 0091 0050 0052 0059 0056 0126 0;ctrl-alt-shift-f12
0027 0091 0050 0052 0126 0;f12
0027 0091 0050 0059 0050 0126 0;shift-insert
0027 0091 0050 0059 0051 0126 0;alt-insert
0027 0091 0050 0059 0052 0126 0;alt-shift-insert
0027 0091 0050 0059 0053 0126 0;ctrl-insert
0027 0091 0050 0059 0054 0126 0;ctrl-shift-insert
0027 0091 0050 0059 0055 0126 0;ctrl-alt-insert
0027 0091 0050 0059 0056 0126 0;ctrl-alt-shift-insert
0027 0091 0050 0126 0;insert
0027 0091 0051 0059 0050 0126 0;shift-delete
0027 0091 0051 0059 0051 0126 0;alt-delete
0027 0091 0051 0059 0052 0126 0;alt-shift-delete
0027 0091 0051 0059 0053 0126 0;ctrl-delete
0027 0091 0051 0059 0054 0126 0;ctrl-shift-delete
0027 0091 0051 0059 0055 0126 0;ctrl-alt-delete
0027 0091 0051 0059 0056 0126 0;ctrl-alt-shift-delete
0027 0091 0051 0126 0;delete
#0027 0091 0052 0059 0050 0126 0;shift-end
#0027 0091 0052 0059 0051 0126 0;alt-end
#0027 0091 0052 0059 0052 0126 0;alt-shift-end
#0027 0091 0052 0059 0053 0126 0;ctrl-end
#0027 0091 0052 0059 0054 0126 0;ctrl-shift-end
#0027 0091 0052 0059 0055 0126 0;ctrl-alt-end
#0027 0091 0052 0059 0056 0126 0;ctrl-alt-shift-end
0027 0091 0052 0126 0;end
0027 0091 0053 0059 0050 0126 0;shift-pageUp
0027 0091 0053 0059 0051 0126 0;alt-pageUp
0027 0091 0053 0059 0052 0126 0;alt-shift-pageUp
0027 0091 0053 0059 0053 0126 0;ctrl-pageUp
0027 0091 0053 0059 0054 0126 0;ctrl-shift-pageUp
0027 0091 0053 0059 0055 0126 0;ctrl-alt-pageUp
0027 0091 0053 0059 0056 0126 0;ctrl-alt-shift-pageUp
0027 0091 0053 0126 0;pageUp
0027 0091 0054 0059 0050 0126 0;shift-pageDown
0027 0091 0054 0059 0051 0126 0;alt-pageDown
0027 0091 0054 0059 0052 0126 0;alt-shift-pageDown
0027 0091 0054 0059 0053 0126 0;ctrl-pageDown
0027 0091 0054 0059 0054 0126 0;ctrl-shift-pageDown
0027 0091 0054 0059 0055 0126 0;ctrl-alt-pageDown
0027 0091 0054 0059 0056 0126 0;ctrl-alt-shift-pageDown
0027 0091 0054 0126 0;pageDown
0027 0091 0065 0;up
0027 0091 0066 0;down
0027 0091 0067 0;right
0027 0091 0068 0;left
0027 0091 0069 0;keypad-five
0027 0091 0090 0;shift-Horizontal-Tab

0027 0127 0;alt-delete;	Delete

"

ControlCharacters=(
	[0x00]="Enter"			# "Null character"
	[0x01]="Start-of-Header"
	[0x02]="Start-of-Text"
	[0x03]="End-of-Text"
	[0x04]="End-of-Transmission"
	[0x05]="Enquiry"
	[0x06]="Acknowledgment"
	[0x07]="Bell"
	[0x08]="Backspace"
	[0x09]="Horizontal-Tab"
	[0x0A]="Line-feed"
	[0x0B]="Vertical-Tab"
	[0x0C]="Form-feed"
	[0x0D]="Carriage-return"
	[0x0E]="Shift-Out"
	[0x0F]="Shift-In"
	[0x10]="Data-Link-Escape"
	[0x11]="XON"
	[0x12]="Device-Control-2"
	[0x13]="XOFF"
	[0x14]="Device-Control-4"
	[0x15]="Negative-Acknowledgement"
	[0x16]="Synchronous-idle"
	[0x17]="End-of-Transmission-Block"
	[0x18]="Cancel"
	[0x19]="End-of-Medium"
	[0x1A]="Substitute"
	[0x1B]="Escape"
	[0x1C]="File-Separator"
	[0x1D]="Group-Separator"
	[0x1E]="Record-Separator"
	[0x1F]="Unit-Separator"
	[0x7F]="Delete"
)

	function read1 {
		IFS='' read  -sn1 "${@}" scancode
	}
	function read2 {
		# Captues Ctrl-C 
		stty -echo raw
		scancode=$(dd bs=1 count=1 2>/dev/null || true )
		stty echo -raw
	}
	function ReadKey {
		local scancode 
		local scancode_f
		local d
		if read1; then
			d=$(printf '%04d' "'${scancode}")
			case "${scancode}" in
				[^[:cntrl:]])
					echo "${scancode}"
					;;
				$'\e')
					local -i icnt=1
					local oscancode Match=
					scancode_f="${d}"
					while read1 -t1 && [ ${icnt} -lt 9 ]; do
						let icnt+=1
						scancode_f="${scancode_f} $(printf '%04d' "'${scancode}")"
						if  [ ${icnt} -eq 2 ] ; then
							case "${scancode}" in
								[[O]) continue;;
								[^[:cntrl:]]) Match="alt-${scancode}"; break ;;
							esac
						fi
						Match="$(echo "${SpecialKeyCodes}" | grep "^${scancode_f} 0;")"
						if [ -n "${Match:-}" ]; then
							Match="${Match#*;}"
							Match="${Match%;*}"
							break
						fi
						oscancode="${scancode}"
					done
					if [ -z "${Match}" ]; then
						case "${scancode_f}" in
							'0027') Match="Escape" ;;
							'0027 0079') Match="alt-O" ;;
							'0027 0091') Match="alt-[" ;;
						esac
					fi
					if [ -n "${Match}" ]; then
						echo "${Match}"
					else
						# print any unrecognised codes
						echo "${scancode_f} 0;"
					fi
					;;
				*)
					d=$(printf '%d' "'${scancode}")
					if [ -n "${ControlCharacters[${d}]:-}" ]; then
						echo "${ControlCharacters[${d}]}"
					else
						# print any unrecognised control characters
						printf 'Unknown %02x\n' "'${scancode}"
					fi
					;;
			esac
		fi
	}
	function HandleKey {
		local Key
		while true; do
			key="$(ReadKey )"
			case "${key}" in
				Carriage-return|Enter) 
					break
					;;
				*)
					echo "${key}"
					;;
			esac
		done
	}
HandleKey

Last edited by dethrophes; 12-19-2011 at 07:16 AM. Reason: Put the code in a code block
 
Old 12-18-2011, 08:44 AM   #7
StuartRothrock
LQ Newbie
 
Registered: Nov 2009
Posts: 7

Rep: Reputation: 0
Run it and it exits without a keypress or anything. Some inherent characteristics of this site's HTML may have eaten some of the characters.
 
Old 12-19-2011, 07:11 AM   #8
dethrophes
LQ Newbie
 
Registered: Nov 2011
Posts: 5

Rep: Reputation: Disabled
just call the function at the end of the file. Like this.

Code:
	SpecialKeyCodes="
0027 0000 0;ctrl-alt-Enter
0027 0001 0;ctrl-alt-a
0027 0002 0;ctrl-alt-b
0027 0003 0;ctrl-alt-c
0027 0004 0;ctrl-alt-d
0027 0005 0;ctrl-alt-e
0027 0006 0;ctrl-alt-f
0027 0007 0;ctrl-alt-g
0027 0008 0;ctrl-alt-h
0027 0009 0;ctrl-alt-i
0027 0010 0;ctrl-alt-j
0027 0011 0;ctrl-alt-k
0027 0012 0;ctrl-alt-l
0027 0013 0;ctrl-alt-m
0027 0014 0;ctrl-alt-n
0027 0015 0;ctrl-alt-o
0027 0016 0;ctrl-alt-p
0027 0017 0;ctrl-alt-q
0027 0018 0;ctrl-alt-r
0027 0019 0;ctrl-alt-s
0027 0020 0;ctrl-alt-t
0027 0021 0;ctrl-alt-u
0027 0022 0;ctrl-alt-v
0027 0023 0;ctrl-alt-w
0027 0024 0;ctrl-alt-x
0027 0025 0;ctrl-alt-y
0027 0026 0;ctrl-alt-z
0027 0027 0;ctrl-alt-[; Escape
0027 0029 0;ctrl-alt-]
0027 0029 0;ctrl-alt-}
0027 0030 0;ctrl-alt-^
0027 0031 0;ctrl-alt-_
0027 0032 0;ctrl-alt-space;		 	Space

0027 0079 0049 0059 0050 0070 0;shift-end
0027 0079 0049 0059 0050 0072 0;shift-home
0027 0079 0049 0059 0050 0080 0;shift-f1
0027 0079 0049 0059 0050 0081 0;shift-f2
0027 0079 0049 0059 0050 0082 0;shift-f3
0027 0079 0049 0059 0050 0083 0;shift-f4
0027 0079 0049 0059 0051 0070 0;alt-end
0027 0079 0049 0059 0051 0072 0;alt-home
0027 0079 0049 0059 0051 0080 0;alt-f1
0027 0079 0049 0059 0051 0081 0;alt-f2
0027 0079 0049 0059 0051 0082 0;alt-f3
0027 0079 0049 0059 0051 0083 0;alt-f4
0027 0079 0049 0059 0052 0070 0;alt-shift-end
0027 0079 0049 0059 0052 0072 0;alt-shift-home
0027 0079 0049 0059 0052 0080 0;alt-shift-f1
0027 0079 0049 0059 0052 0081 0;alt-shift-f2
0027 0079 0049 0059 0052 0082 0;alt-shift-f3
0027 0079 0049 0059 0052 0083 0;alt-shift-f4
0027 0079 0049 0059 0053 0070 0;ctrl-end
0027 0079 0049 0059 0053 0072 0;ctrl-home
0027 0079 0049 0059 0053 0080 0;ctrl-f1
0027 0079 0049 0059 0053 0081 0;ctrl-f2
0027 0079 0049 0059 0053 0082 0;ctrl-f3
0027 0079 0049 0059 0053 0083 0;ctrl-f4
0027 0079 0049 0059 0054 0070 0;ctrl-shift-end
0027 0079 0049 0059 0054 0072 0;ctrl-shift-home
0027 0079 0049 0059 0054 0080 0;ctrl-shift-f1
0027 0079 0049 0059 0054 0081 0;ctrl-shift-f2
0027 0079 0049 0059 0054 0082 0;ctrl-shift-f3
0027 0079 0049 0059 0054 0083 0;ctrl-shift-f4
0027 0079 0049 0059 0055 0070 0;ctrl-alt-end
0027 0079 0049 0059 0055 0072 0;ctrl-alt-home
0027 0079 0049 0059 0055 0080 0;ctrl-alt-f1
0027 0079 0049 0059 0055 0081 0;ctrl-alt-f2
0027 0079 0049 0059 0055 0082 0;ctrl-alt-f3
0027 0079 0049 0059 0055 0083 0;ctrl-alt-f4
0027 0079 0049 0059 0056 0070 0;ctrl-alt-shift-end
0027 0079 0049 0059 0056 0072 0;ctrl-alt-shift-home
0027 0079 0049 0059 0056 0080 0;ctrl-alt-shift-f1
0027 0079 0049 0059 0056 0081 0;ctrl-alt-shift-f2
0027 0079 0049 0059 0056 0082 0;ctrl-alt-shift-f3
0027 0079 0049 0059 0056 0083 0;ctrl-alt-shift-f4
0027 0079 0070 0;end
0027 0079 0072 0;home
0027 0079 0080 0;f1
0027 0079 0081 0;f2
0027 0079 0082 0;f3
0027 0079 0083 0;f4

0027 0091 0049 0053 0059 0050 0126 0;shift-f5
0027 0091 0049 0053 0059 0051 0126 0;alt-f5
0027 0091 0049 0053 0059 0052 0126 0;alt-shift-f5
0027 0091 0049 0053 0059 0053 0126 0;ctrl-f5
0027 0091 0049 0053 0059 0054 0126 0;ctrl-shift-f5
0027 0091 0049 0053 0059 0055 0126 0;ctrl-alt-f5
0027 0091 0049 0053 0059 0056 0126 0;ctrl-alt-shift-f5
0027 0091 0049 0053 0126 0;f5
0027 0091 0049 0055 0059 0050 0126 0;shift-f6
0027 0091 0049 0055 0059 0051 0126 0;alt-f6
0027 0091 0049 0055 0059 0052 0126 0;alt-shift-f6
0027 0091 0049 0055 0059 0053 0126 0;ctrl-f6
0027 0091 0049 0055 0059 0054 0126 0;ctrl-shift-f6
0027 0091 0049 0055 0059 0055 0126 0;ctrl-alt-f6
0027 0091 0049 0055 0059 0056 0126 0;ctrl-alt-shift-f6
0027 0091 0049 0055 0126 0;f6
0027 0091 0049 0056 0059 0050 0126 0;shift-f7
0027 0091 0049 0056 0059 0051 0126 0;alt-f7
0027 0091 0049 0056 0059 0052 0126 0;alt-shift-f7
0027 0091 0049 0056 0059 0053 0126 0;ctrl-f7
0027 0091 0049 0056 0059 0054 0126 0;ctrl-shift-f7
0027 0091 0049 0056 0059 0055 0126 0;ctrl-alt-f7
0027 0091 0049 0056 0059 0056 0126 0;ctrl-alt-shift-f7
0027 0091 0049 0056 0126 0;f7
0027 0091 0049 0057 0059 0050 0126 0;shift-f8
0027 0091 0049 0057 0059 0051 0126 0;alt-f8
0027 0091 0049 0057 0059 0052 0126 0;alt-shift-f8
0027 0091 0049 0057 0059 0053 0126 0;ctrl-f8
0027 0091 0049 0057 0059 0054 0126 0;ctrl-shift-f8
0027 0091 0049 0057 0059 0055 0126 0;ctrl-alt-f8
0027 0091 0049 0057 0059 0056 0126 0;ctrl-alt-shift-f8
0027 0091 0049 0057 0126 0;f8
0027 0091 0049 0059 0050 0065 0;shift-up
0027 0091 0049 0059 0050 0066 0;shift-down
0027 0091 0049 0059 0050 0067 0;shift-right
0027 0091 0049 0059 0050 0068 0;shift-left
0027 0091 0049 0059 0050 0069 0;shift-keypad-five
#0027 0091 0049 0059 0050 0126 0;shift-home
0027 0091 0049 0059 0051 0065 0;alt-up
0027 0091 0049 0059 0051 0066 0;alt-down
0027 0091 0049 0059 0051 0067 0;alt-right
0027 0091 0049 0059 0051 0068 0;alt-left
0027 0091 0049 0059 0051 0069 0;alt-keypad-five
#0027 0091 0049 0059 0051 0126 0;alt-home
0027 0091 0049 0059 0052 0065 0;alt-shift-up
0027 0091 0049 0059 0052 0066 0;alt-shift-down
0027 0091 0049 0059 0052 0067 0;alt-shift-right
0027 0091 0049 0059 0052 0068 0;alt-shift-left
0027 0091 0049 0059 0052 0069 0;alt-shift-keypad-five
#0027 0091 0049 0059 0052 0126 0;alt-shift-home
0027 0091 0049 0059 0053 0065 0;ctrl-up
0027 0091 0049 0059 0053 0066 0;ctrl-down
0027 0091 0049 0059 0053 0067 0;ctrl-right
0027 0091 0049 0059 0053 0068 0;ctrl-left
0027 0091 0049 0059 0053 0069 0;ctrl-keypad-five
#0027 0091 0049 0059 0053 0126 0;ctrl-home
0027 0091 0049 0059 0054 0065 0;ctrl-shift-up
0027 0091 0049 0059 0054 0066 0;ctrl-shift-down
0027 0091 0049 0059 0054 0067 0;ctrl-shift-right
0027 0091 0049 0059 0054 0068 0;ctrl-shift-left
0027 0091 0049 0059 0054 0069 0;ctrl-shift-keypad-five
#0027 0091 0049 0059 0054 0126 0;ctrl-shift-home
0027 0091 0049 0059 0055 0065 0;ctrl-alt-up
0027 0091 0049 0059 0055 0066 0;ctrl-alt-down
0027 0091 0049 0059 0055 0067 0;ctrl-alt-right
0027 0091 0049 0059 0055 0068 0;ctrl-alt-left
0027 0091 0049 0059 0055 0069 0;ctrl-alt-keypad-five
#0027 0091 0049 0059 0055 0126 0;ctrl-alt-home
0027 0091 0049 0059 0056 0065 0;ctrl-alt-shift-up
0027 0091 0049 0059 0056 0066 0;ctrl-alt-shift-down
0027 0091 0049 0059 0056 0067 0;ctrl-alt-shift-right
0027 0091 0049 0059 0056 0068 0;ctrl-alt-shift-left
0027 0091 0049 0059 0056 0069 0;ctrl-alt-shift-keypad-five
#0027 0091 0049 0059 0056 0126 0;ctrl-alt-shift-home
0027 0091 0049 0126 0;home
0027 0091 0050 0048 0059 0050 0126 0;shift-f9
0027 0091 0050 0048 0059 0051 0126 0;alt-f9
0027 0091 0050 0048 0059 0052 0126 0;alt-shift-f9
0027 0091 0050 0048 0059 0053 0126 0;ctrl-f9
0027 0091 0050 0048 0059 0054 0126 0;ctrl-shift-f9
0027 0091 0050 0048 0059 0055 0126 0;ctrl-alt-f9
0027 0091 0050 0048 0059 0056 0126 0;ctrl-alt-shift-f9
0027 0091 0050 0048 0126 0;f9
0027 0091 0050 0049 0059 0050 0126 0;shift-f10
0027 0091 0050 0049 0059 0051 0126 0;alt-f10
0027 0091 0050 0049 0059 0052 0126 0;alt-shift-f10
0027 0091 0050 0049 0059 0053 0126 0;ctrl-f10
0027 0091 0050 0049 0059 0054 0126 0;ctrl-shift-f10
0027 0091 0050 0049 0059 0055 0126 0;ctrl-alt-f10
0027 0091 0050 0049 0059 0056 0126 0;ctrl-alt-shift-f10
0027 0091 0050 0049 0126 0;f10
0027 0091 0050 0051 0059 0050 0126 0;shift-f11
0027 0091 0050 0051 0059 0051 0126 0;alt-f11
0027 0091 0050 0051 0059 0052 0126 0;alt-shift-f11
0027 0091 0050 0051 0059 0053 0126 0;ctrl-f11
0027 0091 0050 0051 0059 0054 0126 0;ctrl-shift-f11
0027 0091 0050 0051 0059 0055 0126 0;ctrl-alt-f11
0027 0091 0050 0051 0059 0056 0126 0;ctrl-alt-shift-f11
0027 0091 0050 0051 0126 0;f11
0027 0091 0050 0052 0059 0050 0126 0;shift-f12
0027 0091 0050 0052 0059 0051 0126 0;alt-f12
0027 0091 0050 0052 0059 0052 0126 0;alt-shift-f12
0027 0091 0050 0052 0059 0053 0126 0;ctrl-f12
0027 0091 0050 0052 0059 0054 0126 0;ctrl-shift-f12
0027 0091 0050 0052 0059 0055 0126 0;ctrl-alt-f12
0027 0091 0050 0052 0059 0056 0126 0;ctrl-alt-shift-f12
0027 0091 0050 0052 0126 0;f12
0027 0091 0050 0059 0050 0126 0;shift-insert
0027 0091 0050 0059 0051 0126 0;alt-insert
0027 0091 0050 0059 0052 0126 0;alt-shift-insert
0027 0091 0050 0059 0053 0126 0;ctrl-insert
0027 0091 0050 0059 0054 0126 0;ctrl-shift-insert
0027 0091 0050 0059 0055 0126 0;ctrl-alt-insert
0027 0091 0050 0059 0056 0126 0;ctrl-alt-shift-insert
0027 0091 0050 0126 0;insert
0027 0091 0051 0059 0050 0126 0;shift-delete
0027 0091 0051 0059 0051 0126 0;alt-delete
0027 0091 0051 0059 0052 0126 0;alt-shift-delete
0027 0091 0051 0059 0053 0126 0;ctrl-delete
0027 0091 0051 0059 0054 0126 0;ctrl-shift-delete
0027 0091 0051 0059 0055 0126 0;ctrl-alt-delete
0027 0091 0051 0059 0056 0126 0;ctrl-alt-shift-delete
0027 0091 0051 0126 0;delete
#0027 0091 0052 0059 0050 0126 0;shift-end
#0027 0091 0052 0059 0051 0126 0;alt-end
#0027 0091 0052 0059 0052 0126 0;alt-shift-end
#0027 0091 0052 0059 0053 0126 0;ctrl-end
#0027 0091 0052 0059 0054 0126 0;ctrl-shift-end
#0027 0091 0052 0059 0055 0126 0;ctrl-alt-end
#0027 0091 0052 0059 0056 0126 0;ctrl-alt-shift-end
0027 0091 0052 0126 0;end
0027 0091 0053 0059 0050 0126 0;shift-pageUp
0027 0091 0053 0059 0051 0126 0;alt-pageUp
0027 0091 0053 0059 0052 0126 0;alt-shift-pageUp
0027 0091 0053 0059 0053 0126 0;ctrl-pageUp
0027 0091 0053 0059 0054 0126 0;ctrl-shift-pageUp
0027 0091 0053 0059 0055 0126 0;ctrl-alt-pageUp
0027 0091 0053 0059 0056 0126 0;ctrl-alt-shift-pageUp
0027 0091 0053 0126 0;pageUp
0027 0091 0054 0059 0050 0126 0;shift-pageDown
0027 0091 0054 0059 0051 0126 0;alt-pageDown
0027 0091 0054 0059 0052 0126 0;alt-shift-pageDown
0027 0091 0054 0059 0053 0126 0;ctrl-pageDown
0027 0091 0054 0059 0054 0126 0;ctrl-shift-pageDown
0027 0091 0054 0059 0055 0126 0;ctrl-alt-pageDown
0027 0091 0054 0059 0056 0126 0;ctrl-alt-shift-pageDown
0027 0091 0054 0126 0;pageDown
0027 0091 0065 0;up
0027 0091 0066 0;down
0027 0091 0067 0;right
0027 0091 0068 0;left
0027 0091 0069 0;keypad-five
0027 0091 0090 0;shift-Horizontal-Tab

0027 0127 0;alt-delete;	Delete

"

ControlCharacters=(
	[0x00]="Enter"			# "Null character"
	[0x01]="Start-of-Header"
	[0x02]="Start-of-Text"
	[0x03]="End-of-Text"
	[0x04]="End-of-Transmission"
	[0x05]="Enquiry"
	[0x06]="Acknowledgment"
	[0x07]="Bell"
	[0x08]="Backspace"
	[0x09]="Horizontal-Tab"
	[0x0A]="Line-feed"
	[0x0B]="Vertical-Tab"
	[0x0C]="Form-feed"
	[0x0D]="Carriage-return"
	[0x0E]="Shift-Out"
	[0x0F]="Shift-In"
	[0x10]="Data-Link-Escape"
	[0x11]="XON"
	[0x12]="Device-Control-2"
	[0x13]="XOFF"
	[0x14]="Device-Control-4"
	[0x15]="Negative-Acknowledgement"
	[0x16]="Synchronous-idle"
	[0x17]="End-of-Transmission-Block"
	[0x18]="Cancel"
	[0x19]="End-of-Medium"
	[0x1A]="Substitute"
	[0x1B]="Escape"
	[0x1C]="File-Separator"
	[0x1D]="Group-Separator"
	[0x1E]="Record-Separator"
	[0x1F]="Unit-Separator"
	[0x7F]="Delete"
)

	function read1 {
		IFS='' read  -sn1 "${@}" scancode
	}
	function read2 {
		# Captues Ctrl-C 
		local -i ECode=0
		stty -echo raw
		scancode=$(dd bs=1 count=1 2>/dev/null || true )
		stty echo -raw
	}
	function ReadKey {
		local scancode 
		local scancode_f
		local d
		if read1 ${1:-}; then
			d=$(printf '%04d' "'${scancode}")
			case "${scancode}" in
				[^[:cntrl:]])
					echo "${scancode}"
					;;
				$'\e')
					local -i icnt=1
					local oscancode Match=
					scancode_f="${d}"
					while read1 -t1 && [ ${icnt} -lt 9 ]; do
						let icnt+=1
						scancode_f="${scancode_f} $(printf '%04d' "'${scancode}")"
						if  [ ${icnt} -eq 2 ] ; then
							case "${scancode}" in
								[[O]) continue;;
								[^[:cntrl:]]) Match="alt-${scancode}"; break ;;
							esac
						fi
						Match="$(echo "${SpecialKeyCodes}" | grep "^${scancode_f} 0;")"
						if [ -n "${Match:-}" ]; then
							Match="${Match#*;}"
							Match="${Match%;*}"
							break
						fi
						oscancode="${scancode}"
					done
					if [ -z "${Match}" ]; then
						case "${scancode_f}" in
							'0027') Match="Escape" ;;
							'0027 0079') Match="alt-O" ;;
							'0027 0091') Match="alt-[" ;;
						esac
					fi
					if [ -n "${Match}" ]; then
						echo "${Match}"
					else
						# print any unrecognised codes
						echo "${scancode_f} 0;"
					fi
					;;
				*)
					d=$(printf '%d' "'${scancode}")
					if [ -n "${ControlCharacters[${d}]:-}" ]; then
						echo "${ControlCharacters[${d}]}"
					else
						# print any unrecognised control characters
						printf 'Unknown %02x\n' "'${scancode}"
					fi
					;;
			esac
		fi
	}
	function HandleKey {
		local Key
		while true; do
			key="$(ReadKey )"
			case "${key}" in
				Carriage-return|Enter) 
					echo "${key}"
					break
					;;
				*)
					echo "${key}"
					;;
			esac
		done
	}
# HandlKey is a simple handler for ReadKey 
# to show how I intended to use ReadKey
# it grabs every key you press and prints out
# the Code for the key/key-combination
# It also prints out any key code it doesn't recognise 
# to make it simple to add new keys to the list.
HandleKey
when you type something you should see something like

Enter
Escape
alt-A
alt-a
ctrl-alt-shift-left
 
Old 12-19-2011, 11:14 PM   #9
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,807

Rep: Reputation: 501Reputation: 501Reputation: 501Reputation: 501Reputation: 501Reputation: 501
That's what C+ncurses is good for... (of course you can eat your breakfast with a comb, but a fork is much better.)
 
Old 12-20-2011, 09:52 PM   #10
dethrophes
LQ Newbie
 
Registered: Nov 2011
Posts: 5

Rep: Reputation: Disabled
Last version no, I think unless someone finds a bug in it.

I'd have to disagree. for my purposes c and ncurses would be overkill.
I've wanted this sort of functionality in bash for a while now, so I finally got myself to do it.
And while I was at it I wanted a decent solution.

Anyway now fixed the last of the problems and optimized for performance.
takes less than 0.005s for all keys now. most are less than 0.001s.
Also reduced the footprint.

The code should be easier to read now.



Code:
	SpecialKeyCodes2=$'
\e\ca=ctrl-alt-a
\e\cb=ctrl-alt-b
\e\cc=ctrl-alt-c
\e\cd=ctrl-alt-d
\e\ce=ctrl-alt-e
\e\cf=ctrl-alt-f
\e\a=ctrl-alt-g
\e\b=ctrl-alt-h
\e\t=ctrl-alt-i
\e\n=ctrl-alt-j
\e\v=ctrl-alt-k
\e\cl=ctrl-alt-l
\e\r=ctrl-alt-m
\e\cn=ctrl-alt-n
\e\co=ctrl-alt-o
\e\cp=ctrl-alt-p
\e\cq=ctrl-alt-q
\e\cr=ctrl-alt-r
\e\cs=ctrl-alt-s
\e\ct=ctrl-alt-t
\e\cu=ctrl-alt-u
\e\cv=ctrl-alt-v
\e\cw=ctrl-alt-w
\e\cx=ctrl-alt-x
\e\cy=ctrl-alt-y
\e\cz=ctrl-alt-z
\e\c[=ctrl-alt-[
\e\c]=ctrl-alt-]
\e\c}=ctrl-alt-}
\e\c^=ctrl-alt-^
\e\c_=ctrl-alt-_

\eO1;2F=shift-end
\eO1;2H=shift-home
\eO1;2P=shift-f1
\eO1;2Q=shift-f2
\eO1;2R=shift-f3
\eO1;2S=shift-f4
\eO1;3F=alt-end
\eO1;3H=alt-home
\eO1;3P=alt-f1
\eO1;3Q=alt-f2
\eO1;3R=alt-f3
\eO1;3S=alt-f4
\eO1;4F=alt-shift-end
\eO1;4H=alt-shift-home
\eO1;4P=alt-shift-f1
\eO1;4Q=alt-shift-f2
\eO1;4R=alt-shift-f3
\eO1;4S=alt-shift-f4
\eO1;5F=ctrl-end
\eO1;5H=ctrl-home
\eO1;5P=ctrl-f1
\eO1;5Q=ctrl-f2
\eO1;5R=ctrl-f3
\eO1;5S=ctrl-f4
\eO1;6F=ctrl-shift-end
\eO1;6H=ctrl-shift-home
\eO1;6P=ctrl-shift-f1
\eO1;6Q=ctrl-shift-f2
\eO1;6R=ctrl-shift-f3
\eO1;6S=ctrl-shift-f4
\eO1;7F=ctrl-alt-end
\eO1;7H=ctrl-alt-home
\eO1;7P=ctrl-alt-f1
\eO1;7Q=ctrl-alt-f2
\eO1;7R=ctrl-alt-f3
\eO1;7S=ctrl-alt-f4
\eO1;8F=ctrl-alt-shift-end
\eO1;8H=ctrl-alt-shift-home
\eO1;8P=ctrl-alt-shift-f1
\eO1;8Q=ctrl-alt-shift-f2
\eO1;8R=ctrl-alt-shift-f3
\eO1;8S=ctrl-alt-shift-f4
\eOF=end
\eOH=home
\eOP=f1
\eOQ=f2
\eOR=f3
\eOS=f4

\e[15;2~=shift-f5
\e[15;3~=alt-f5
\e[15;4~=alt-shift-f5
\e[15;5~=ctrl-f5
\e[15;6~=ctrl-shift-f5
\e[15;7~=ctrl-alt-f5
\e[15;8~=ctrl-alt-shift-f5
\e[15~=f5
\e[17;2~=shift-f6
\e[17;3~=alt-f6
\e[17;4~=alt-shift-f6
\e[17;5~=ctrl-f6
\e[17;6~=ctrl-shift-f6
\e[17;7~=ctrl-alt-f6
\e[17;8~=ctrl-alt-shift-f6
\e[17~=f6
\e[18;2~=shift-f7
\e[18;3~=alt-f7
\e[18;4~=alt-shift-f7
\e[18;5~=ctrl-f7
\e[18;6~=ctrl-shift-f7
\e[18;7~=ctrl-alt-f7
\e[18;8~=ctrl-alt-shift-f7
\e[18~=f7
\e[19;2~=shift-f8
\e[19;3~=alt-f8
\e[19;4~=alt-shift-f8
\e[19;5~=ctrl-f8
\e[19;6~=ctrl-shift-f8
\e[19;7~=ctrl-alt-f8
\e[19;8~=ctrl-alt-shift-f8
\e[19~=f8
\e[1;2A=shift-up
\e[1;2B=shift-down
\e[1;2C=shift-right
\e[1;2D=shift-left
\e[1;2E=shift-keypad-five
#\e[1;2~=shift-home
\e[1;3A=alt-up
\e[1;3B=alt-down
\e[1;3C=alt-right
\e[1;3D=alt-left
\e[1;3E=alt-keypad-five
#\e[1;3~=alt-home
\e[1;4A=alt-shift-up
\e[1;4B=alt-shift-down
\e[1;4C=alt-shift-right
\e[1;4D=alt-shift-left
\e[1;4E=alt-shift-keypad-five
#\e[1;4~=alt-shift-home
\e[1;5A=ctrl-up
\e[1;5B=ctrl-down
\e[1;5C=ctrl-right
\e[1;5D=ctrl-left
\e[1;5E=ctrl-keypad-five
#\e[1;5~=ctrl-home
\e[1;6A=ctrl-shift-up
\e[1;6B=ctrl-shift-down
\e[1;6C=ctrl-shift-right
\e[1;6D=ctrl-shift-left
\e[1;6E=ctrl-shift-keypad-five
#\e[1;6~=ctrl-shift-home
\e[1;7A=ctrl-alt-up
\e[1;7B=ctrl-alt-down
\e[1;7C=ctrl-alt-right
\e[1;7D=ctrl-alt-left
\e[1;7E=ctrl-alt-keypad-five
#\e[1;7~=ctrl-alt-home
\e[1;8A=ctrl-alt-shift-up
\e[1;8B=ctrl-alt-shift-down
\e[1;8C=ctrl-alt-shift-right
\e[1;8D=ctrl-alt-shift-left
\e[1;8E=ctrl-alt-shift-keypad-five
#\e[1;8~=ctrl-alt-shift-home
\e[1~=home
\e[20;2~=shift-f9
\e[20;3~=alt-f9
\e[20;4~=alt-shift-f9
\e[20;5~=ctrl-f9
\e[20;6~=ctrl-shift-f9
\e[20;7~=ctrl-alt-f9
\e[20;8~=ctrl-alt-shift-f9
\e[20~=f9
\e[21;2~=shift-f10
\e[21;3~=alt-f10
\e[21;4~=alt-shift-f10
\e[21;5~=ctrl-f10
\e[21;6~=ctrl-shift-f10
\e[21;7~=ctrl-alt-f10
\e[21;8~=ctrl-alt-shift-f10
\e[21~=f10
\e[23;2~=shift-f11
\e[23;3~=alt-f11
\e[23;4~=alt-shift-f11
\e[23;5~=ctrl-f11
\e[23;6~=ctrl-shift-f11
\e[23;7~=ctrl-alt-f11
\e[23;8~=ctrl-alt-shift-f11
\e[23~=f11
\e[24;2~=shift-f12
\e[24;3~=alt-f12
\e[24;4~=alt-shift-f12
\e[24;5~=ctrl-f12
\e[24;6~=ctrl-shift-f12
\e[24;7~=ctrl-alt-f12
\e[24;8~=ctrl-alt-shift-f12
\e[24~=f12
\e[2;2~=shift-insert
\e[2;3~=alt-insert
\e[2;4~=alt-shift-insert
\e[2;5~=ctrl-insert
\e[2;6~=ctrl-shift-insert
\e[2;7~=ctrl-alt-insert
\e[2;8~=ctrl-alt-shift-insert
\e[2~=insert
\e[3;2~=shift-delete
\e[3;3~=alt-delete
\e[3;4~=alt-shift-delete
\e[3;5~=ctrl-delete
\e[3;6~=ctrl-shift-delete
\e[3;7~=ctrl-alt-delete
\e[3;8~=ctrl-alt-shift-delete
\e[3~=delete
#\e[4;2~=shift-end
#\e[4;3~=alt-end
#\e[4;4~=alt-shift-end
#\e[4;5~=ctrl-end
#\e[4;6~=ctrl-shift-end
#\e[4;7~=ctrl-alt-end
#\e[4;8~=ctrl-alt-shift-end
\e[4~=end
\e[5;2~=shift-pageUp
\e[5;3~=alt-pageUp
\e[5;4~=alt-shift-pageUp
\e[5;5~=ctrl-pageUp
\e[5;6~=ctrl-shift-pageUp
\e[5;7~=ctrl-alt-pageUp
\e[5;8~=ctrl-alt-shift-pageUp
\e[5~=pageUp
\e[6;2~=shift-pageDown
\e[6;3~=alt-pageDown
\e[6;4~=alt-shift-pageDown
\e[6;5~=ctrl-pageDown
\e[6;6~=ctrl-shift-pageDown
\e[6;7~=ctrl-alt-pageDown
\e[6;8~=ctrl-alt-shift-pageDown
\e[6~=pageDown
\e[A=up
\e[B=down
\e[C=right
\e[D=left
\e[E=keypad-five
\e[Z=shift-Horizontal-Tab

\e\x7f=alt-delete

'

#echo "${#SpecialKeyCodes2}"



ControlCharacters=(
	[0x00]="Enter"			# "Null character"
	[0x01]="Start-of-Header"
	[0x02]="Start-of-Text"
	[0x03]="End-of-Text"
	[0x04]="End-of-Transmission"
	[0x05]="Enquiry"
	[0x06]="Acknowledgment"
	[0x07]="Bell"
	[0x08]="Backspace"
	[0x09]="Horizontal-Tab"
	[0x0A]="Line-feed"
	[0x0B]="Vertical-Tab"
	[0x0C]="Form-feed"
	[0x0D]="Carriage-return"
	[0x0E]="Shift-Out"
	[0x0F]="Shift-In"
	[0x10]="Data-Link-Escape"
	[0x11]="XON"
	[0x12]="Device-Control-2"
	[0x13]="XOFF"
	[0x14]="Device-Control-4"
	[0x15]="Negative-Acknowledgement"
	[0x16]="Synchronous-idle"
	[0x17]="End-of-Transmission-Block"
	[0x18]="Cancel"
	[0x19]="End-of-Medium"
	[0x1A]="Substitute"
	[0x1B]="Escape"
	[0x1C]="File-Separator"
	[0x1D]="Group-Separator"
	[0x1E]="Record-Separator"
	[0x1F]="Unit-Separator"
	[0x7F]="Delete"
)

	function escapeCtrlCharsString {
		local -i idx=${#1}
		local nString=""
		for (( idx=0; $idx<${#1}; idx++ )) ; do 
			case "${1:${idx}:1}" in
				[^[:cntrl:]])	nString+="${1:${idx}:1}";;
				$'\e')		nString+='\e';;
				$'\a')		nString+='\a';;
				$'\n')		nString+='\n';;
				$'\b')		nString+='\b';;
				$'\v')		nString+='\v';;
				$'\t')		nString+='\t';;
				$'\r')		nString+='\r';;
				*)		nString+="$(printf '\\x%02x' "'${1:${idx}:1}")";;
			esac
		done
		echo "${nString}"
	}
	function ReadKey {
		local scancode 

		if IFS='' read  -sN1 ${1:-} scancode; then
			case "${scancode}" in
				[^[:cntrl:]]) 
					#echo -n "$(escapeCtrlCharsString "${scancode}")="
					echo -n "${scancode}" 
					;;
				$'\e')
					while IFS='' read -srN1 -t0.0001 ; do
						scancode+="${REPLY}"
					done
					#echo -n "$(escapeCtrlCharsString "${scancode}")="
					case "${scancode}" in
							$'\e'[^[:cntrl:]]) echo -n "alt-${scancode:1}" ;;
							$'\e\n') echo -n "ctrl-alt-j" ;;
							$'\e\r') echo -n "ctrl-alt-m" ;;
							*)
								local Match="$(echo -n "${SpecialKeyCodes2}" | LC_ALL=C grep -F -m 1 -e "${scancode}=")"
								if [ -n "${Match:-}" ]; then
									Match="${Match#*=}"
									echo "${Match%;*}"
								else
									echo "$(escapeCtrlCharsString ${scancode}")="
								fi
								;;
					esac
					;;
				*)
					local h=$(printf "%x" "'${scancode}")
					#echo -n "$(escapeCtrlCharsString "${scancode}")="
					echo -n "${ControlCharacters["0x${h}"]:-\x${h}=}"
					;;
			esac
		fi
	}
	function HandleReadKey {
		local Key
		while true; do
			key="$(ReadKey )"
			echo "\"${key}\""
			case "${key}" in
				Carriage-return|Enter|q) 	break	;;
			esac
		done
	}
HandleReadKey

Last edited by dethrophes; 12-20-2011 at 09:55 PM. Reason: fixed typo
 
Old 01-07-2012, 12:06 AM   #11
dethrophes
LQ Newbie
 
Registered: Nov 2011
Posts: 5

Rep: Reputation: Disabled
Added Mouse support and Sun Function Keys

Another rewrite, as I got more comfortable with how it all works.
Added full mouse support at least as much as seems to be supported by my terminal i.e. btn 1-3 scroll up and scroll down & motion tracking.
added the codes for Sun Function keys and Meta key. i.e. Ctrl Alt Shift & Meta.




Code:
#!/bin/bash 
#set -o errexit 
#set -o errtrace 
set -o nounset 


  if [ "${S8C1T:-0}" != "1" ] ; then
    declare -gr SS3=$'\eO'      # Single Shift Select of G3 Character Set ( SS3 is 0x8f): affects next character only
    declare -gr CSI=$'\e['      # Control Sequence Introducer ( CSI is 0x9b)
  else
    declare -gr SS3=$'\x8f'     # Single Shift Select of G3 Character Set ( SS3 is 0x8f): affects next character only
    declare -gr CSI=$'\x9b'     # Control Sequence Introducer ( CSI is 0x9b)
  fi


  function  vt100_DECRST {  
    IFS=';' eval 'echo -n "${CSI}?${*?Missing Pm}l"'
  }
  function  vt100_DECSET {  
    IFS=';' eval 'echo -n "${CSI}?${*?Missing Pm}h"'
  }
  mouse_type=(
        [0]=9     ## X10 mouse reporting, for compatibility with X10's xterm, reports on button press.
        [1]=1000  ## X11 mouse reporting, reports on button press and release.
        [2]=1001  ## highlight reporting, useful for reporting mouse highlights
        [3]=1002  ## button movement reporting, reports movement when a button is presse
        [4]=1003  ## all movement reporting, reports all movements.
        [5]=1004  ## FocusIn/FocusOut can be combined with any of the mouse events since it uses a different protocol. When set, it causes xterm to send CSI I when the terminal gains focus, and CSI O when it loses focus.
        [6]=1005  ## Extended mouse mode enables UTF-8 encoding for C x and C y under all tracking modes, expanding the maximum encodable position from 223 to 2015. For positions less than 95, the resulting output is identical under both modes. Under extended mouse mode, positions greater than 95 generate "extra" bytes which will confuse applications which do not treat their input as a UTF-8 stream. Likewise, C b will be UTF-8 encoded, to reduce confusion with wheel mouse events.
    )

  function ord {
    printf -v "${1?Missing Dest Variable}" "${3:-%d}" "'${2?Missing Char}"
  }
  function ord.eascii {
    LC_CTYPE=C ord "${@}"
  }
  function AdjustMousePos {
    local -i _INDEX
    ord.eascii _INDEX "${2}"
    eval ${1}'=$(( ${_INDEX}-32))'
  }

  ###############################
  ##
  ##    READ KEY CRAP
  ##
  ##
  ###############################
  KeyModifiers=(
             [2]="S"   [3]="A"   [4]="AS"   [5]="C"   [6]="CS"  [7]="CA"    [8]="CAS"
    [9]="M" [10]="MS" [11]="MA" [12]="MAS" [13]="MC" [14]="MCS" [15]="MCA" [16]="MCAS"
    )
  KeybFntKeys=(
    [1]="home" [2]="insert" [3]="delete"  [4]="end"   [5]="pageUp" [6]="pageDown"
    [11]="f1"  [12]="f2"    [13]="f3"     [14]="f4"   [15]="f5"
    [17]="f6"  [18]="f7"    [19]="f8"     [20]="f9"   [21]="f10"
    [23]="f11" [24]="f12"   [25]="f13"    [26]="f14"  [28]="f15"
    [29]="f16" [31]="f17"   [32]="f18"    [33]="f19"  [34]="f20"
    )
  SunKeybFntKeys=(
    [214]="home"  [2]="insert" [3]="delete" [4]="end"   [216]="pageUp" [222]="pageDown"
    [224]="f1"  [225]="f2"    [226]="f3"    [227]="f4"  [228]="f5"
    [229]="f6"  [230]="f7"    [231]="f8"    [232]="f9"  [233]="f10"
    [192]="f11" [193]="f12"   [218]="keypad-five" [220]="keypad-delete"
    )
  KeybFntKeysAlt=(
    # A          B              C               D             E                   F             H         
    [0x41]="up" [0x42]="down" [0x43]="right" [0x44]="left" [0x45]="keypad-five" [0x46]="end" [0x48]="home"     
    # I               O
    [0x49]="InFocus" [0x4f]="OutOfFocus"      
    # P           Q           R           S             Z          
    [0x50]="f1" [0x51]="f2" [0x52]="f3" [0x53]="f4"  [0x5a]="S-HT" 
    )
  C0CtrlChars=(
    [0x00]="Null" [0x01]="SOH" [0x02]="STX" [0x03]="ETX" [0x04]="EOT" [0x05]="ENQ" [0x06]="ACK" 
    [0x07]="BEL"  [0x08]="BS"  [0x09]="HT"  [0x0A]="LF"  [0x0B]="VT"  [0x0C]="FF"  [0x0D]="CR"  
    [0x0E]="SO"   [0x0F]="SI"  [0x10]="DLE" [0x11]="DC1" [0x12]="DC2" [0x13]="DC3" [0x14]="DC4" 
    [0x15]="NAK"  [0x16]="SYN" [0x17]="ETB" [0x18]="CAN" [0x19]="EM"  [0x1A]="SUB" [0x1B]="ESC" 
    [0x1C]="FS"   [0x1D]="GS"  [0x1E]="RS"  [0x1F]="US"  [0x20]="SP"  [0x7F]="DEL" 
  )
  C1CtrlCharsAlt=(
    [0x01]="CA-A" [0x02]="CA-B" [0x03]="CA-C" [0x04]="CA-D"  [0x05]="CA-E" [0x06]="CA-F" [0x07]="CA-G" 
    [0x08]="CA-H" [0x09]="CA-I" [0x0a]="CA-J" [0x0b]="CA-K"  [0x0c]="CA-L" [0x0d]="CA-M" [0x0e]="CA-N"  
    [0x0f]="CA-O" [0x10]="CA-P" [0x11]="CA-Q" [0x12]="CA-R"  [0x13]="CA-S" [0x14]="CA-T" [0x15]="CA-U" 
    [0x16]="CA-V" [0x17]="CA-W" [0x18]="CA-X" [0x19]="CA-Y"  [0x1a]="CA-Z" [0x1b]="CA-[" [0x1c]="CA-]" 
    [0x1d]="CA-}" [0x1e]="CA-^" [0x1f]="CA-_" [0x20]="CA-SP" [0x7F]="A-DEL" 
  )
  MouseButtons=(
    [0x00]="MB1-P" [0x01]="MB2-P" [0x02]="MB3-P" [0x03]="MB-R"
    [0x20]="MB1-M" [0x21]="MB2-M" [0x22]="MB3-M" [0x23]="MB-M"
    [0x40]="MB4-P" [0x41]="MB5-P" 
  )
  MouseMetaButtons=(
    [0x04]="S-"    [0x08]="A-"    [0x0c]="AS-" 
    [0x10]="C-"    [0x14]="CS-"   [0x1c]="CAS-"
  )
  function GetMouseButton {
    local MouseBtn
    AdjustMousePos MouseBtn "${2}"
    MouseBtn="${MouseMetaButtons[$(( ${MouseBtn} & 0x1C))]-}${MouseButtons[$(( ${MouseBtn} & 0xe3))]}"
    eval ${1}='"${MouseBtn}"'
  }
  mouse_on="$(vt100_DECSET ${mouse_type[1]})"
  mouse_off="$(vt100_DECRST "${mouse_type[1]}" )"


  function ReadKey {
    unset UInput[@]
    local escapeSequence 
    local REPLY 

    echo -n "${mouse_on}"
    if IFS='' read  -srN1 ${1:-} escapeSequence; then
      case "${escapeSequence}" in
        [^[:cntrl:]]) 
          UInput[0]="${escapeSequence}" 
          ;;
        $'\e')
          while IFS='' read -srN1 -t0.0001 ; do
            escapeSequence+="${REPLY}"
          done
          case "${escapeSequence}" in
              $'\e'[^[:cntrl:]]) echo -n "A-${escapeSequence:1}" ;;
              ${CSI}t) 
                UInput[0]="MouseTrack"
                AdjustMousePos UInput[1] "${escapeSequence:3:1}"
                AdjustMousePos UInput[2] "${escapeSequence:4:1}"
                ;;
              ${CSI}T) 
                UInput[0]="MouseTrack"
                AdjustMousePos UInput[1] "${escapeSequence:3:1}"
                AdjustMousePos UInput[2] "${escapeSequence:4:1}"
                AdjustMousePos UInput[3] "${escapeSequence:5:1}"
                AdjustMousePos UInput[4] "${escapeSequence:6:1}"
                AdjustMousePos UInput[5] "${escapeSequence:7:1}"
                AdjustMousePos UInput[6] "${escapeSequence:8:1}"
                ;;
              ${CSI}M*)  
                GetMouseButton UInput[0] "${escapeSequence:3:1}"
                if [ -n "${UInput[0]}" ]; then  
                  AdjustMousePos UInput[1] "${escapeSequence:4:1}"
                  AdjustMousePos UInput[2] "${escapeSequence:5:1}"
                else
                  UInput[0]=$(printf 'Mouse-\\x%02x %q'  "'${escapeSequence:3:1}" "${escapeSequence:4}")
                fi
                ;;
              ${CSI}[0-9]*[ABCDEFHIOZPQRSz~])
                local CSI_Params=( ${escapeSequence//[!0-9]/ } )
                local CSI_Func="${escapeSequence:${#escapeSequence}-1}"
                case "${CSI_Func}" in
                  z) # Sun Function Keys
                    UInput[0]="${SunKeybFntKeys[${CSI_Params[0]}]-}"
                    if [ -n "${UInput[0]}" ]; then
                      [ ${#CSI_Params[@]} -le 1 ] ||  UInput[0]="${KeyModifiers[${CSI_Params[1]}]}-${UInput[0]}"
                    else
                      UInput[0]="CSI ${CSI_Params[*]} ${CSI_Func}"
                    fi
                    ;;
                  '~') # Function Keys
                    UInput[0]="${KeybFntKeys[${CSI_Params[0]}]-}"
                    if [ -n "${UInput[0]}" ]; then
                      [ ${#CSI_Params[@]} -le 1 ] ||  UInput[0]="${KeyModifiers[${CSI_Params[1]}]}-${UInput[0]}"
                    else
                      UInput[0]="CSI ${CSI_Params[*]} ${CSI_Func}"
                    fi
                    ;;
                  A|B|C|D|E|F|H|I|O|Z|P|Q|R|S)
                    ord.eascii CSI_Func "${CSI_Func}"
                    UInput[0]="${KeybFntKeysAlt[${CSI_Func}]}"
                    if [ -n "${UInput[0]}" ]; then
                      [ ${#CSI_Params[@]} -le 1 ] ||  UInput[0]="${KeyModifiers[${CSI_Params[1]}]}-${UInput[0]}"
                    else
                      UInput[0]="CSI ${CSI_Params[*]} ${CSI_Func}"
                    fi
                    ;;
                  *)
                    UInput[0]="CSI ${CSI_Params[*]} ${CSI_Func}"
                    ;;
                esac
                ;;
              ${SS3}*[ABCDEFHPQRSIO~])
                local SS3_Params=( ${escapeSequence//[!0-9]/ } )
                local SS3_Func="${escapeSequence:${#escapeSequence}-1}"
                case "${SS3_Func}" in
                  A|B|C|D|E|F|H|P|Q|R|S|~)
                    ord.eascii SS3_Func "${SS3_Func}"
                    UInput[0]="${KeybFntKeysAlt[${SS3_Func}]-}"
                    if [ -n "${UInput[0]}" ]; then
                      [ ${#SS3_Params[@]} -lt 1 ] ||  UInput[0]="${KeyModifiers[${SS3_Params[0]}]}-${UInput[0]}"
                    else
                      UInput[0]="SS3 ${SS3_Params[*]-} ${SS3_Func}"
                    fi
                    ;;
                  *)
                    UInput[0]="SS3 ${SS3_Params[*]-} ${SS3_Func}"
                    ;;
                esac
                ;;
              $'\e'[[:cntrl:]])
                ord.eascii UInput[0] "${escapeSequence:1:1}"
                UInput[0]="${C1CtrlCharsAlt[${UInput[0]}]:-}"
                [ -n "${UInput[0]:-}" ] ||  UInput[0]="$(printf "%q" "${escapeSequence}")"
                ;;
              $'\e') UInput[0]="ESC" ;;
              *)
                UInput[0]="$(printf "%q" "${escapeSequence}")"
                ;;
          esac
          ;;
        *)
          ord.eascii UInput[0] "${escapeSequence}"
          UInput[0]="${C0CtrlChars[${UInput[0]}]:-}"
          [ -n "${UInput[0]:-}" ] ||  UInput[0]="$(printf '%q' "'${escapeSequence}")"
          ;;
      esac
    fi
    echo -n "${mouse_off}"
  }
  function HandleKey {
    local -a UInput
    while true; do
      if ReadKey ; then
        case "${UInput[0]:-}" in
          CR|NULL|LF|q) 
            echo "\"${UInput[*]-}\""
            break
            ;;
          *)
            echo "\"${UInput[*]-}\""
            ;;
        esac
      fi
    done
  }
HandleKey

Last edited by dethrophes; 01-07-2012 at 12:11 AM.
 
Old 02-15-2012, 11:15 AM   #12
dethrophes
LQ Newbie
 
Registered: Nov 2011
Posts: 5

Rep: Reputation: Disabled
I moved this to http://mywiki.wooledge.org/ReadingFunctionKeysInBash
Also added a proper bash implemented vt100 parser example.
 
1 members found this post helpful.
  


Reply

Tags
bash, case, keys


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
In VIM with Eterm DEL and backspace keys gone crazy rangalo Slackware 8 12-18-2006 10:19 AM
Arrow keys not working flamingvan Solaris / OpenSolaris 5 10-03-2006 05:47 AM
Shift-arrow and Alt-arrow keys don't work in xterm Aviv Hurvitz Linux - General 2 09-30-2006 03:43 PM
VIM and the arrow keys Buto Linux - Software 1 09-16-2004 07:38 PM
Arrow keys in nethack Levitate Linux - Games 3 08-22-2004 11:44 AM


All times are GMT -5. The time now is 07:50 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration