UNPKG

4.21 kBapplication/x-shView Raw
1# readlineSync
2# https://github.com/anseki/readline-sync
3#
4# Copyright (c) 2016 anseki
5# Licensed under the MIT license.
6
7# Use perl for compatibility of sed/awk of GNU / POSIX, BSD. (and tr)
8# Hide "\n" from shell by "\fNL"
9
10decode_arg() {
11 printf '%s' "$(printf '%s' "$1" | perl -pe 's/#(\d+);/sprintf("%c", $1)/ge; s/[\r\n]/\fNL/g')"
12}
13
14# getopt(s)
15while [ $# -ge 1 ]; do
16 arg="$(printf '%s' "$1" | grep -E '^-+[^-]+$' | tr '[A-Z]' '[a-z]' | tr -d '-')"
17 case "$arg" in
18 'display') shift; options_display="$(decode_arg "$1")";;
19 'displayonly') options_displayOnly=true;;
20 'keyin') options_keyIn=true;;
21 'hideechoback') options_hideEchoBack=true;;
22 'mask') shift; options_mask="$(decode_arg "$1")";;
23 'limit') shift; options_limit="$(decode_arg "$1")";;
24 'casesensitive') options_caseSensitive=true;;
25 esac
26 shift
27done
28
29reset_tty() {
30 if [ -n "$save_tty" ]; then
31 stty --file=/dev/tty "$save_tty" 2>/dev/null || \
32 stty -F /dev/tty "$save_tty" 2>/dev/null || \
33 stty -f /dev/tty "$save_tty" || exit $?
34 fi
35}
36trap 'reset_tty' EXIT
37save_tty="$(stty --file=/dev/tty -g 2>/dev/null || stty -F /dev/tty -g 2>/dev/null || stty -f /dev/tty -g || exit $?)"
38
39[ -z "$options_display" ] && [ "$options_keyIn" = true ] && \
40 [ "$options_hideEchoBack" = true ] && [ -z "$options_mask" ] && silent=true
41[ "$options_hideEchoBack" != true ] && [ "$options_keyIn" != true ] && is_cooked=true
42
43write_tty() {
44 # if [ "$2" = true ]; then
45 # printf '%b' "$1" >/dev/tty
46 # else
47 # printf '%s' "$1" >/dev/tty
48 # fi
49 printf '%s' "$1" | perl -pe 's/\fNL/\r\n/g' >/dev/tty
50}
51
52replace_allchars() { (
53 text=''
54 for i in $(seq 1 ${#1})
55 do
56 text="$text$2"
57 done
58 printf '%s' "$text"
59) }
60
61if [ -n "$options_display" ]; then
62 write_tty "$options_display"
63fi
64if [ "$options_displayOnly" = true ]; then
65 printf "'%s'" ''
66 exit 0
67fi
68
69if [ "$is_cooked" = true ]; then
70 stty --file=/dev/tty cooked 2>/dev/null || \
71 stty -F /dev/tty cooked 2>/dev/null || \
72 stty -f /dev/tty cooked || exit $?
73else
74 stty --file=/dev/tty raw -echo 2>/dev/null || \
75 stty -F /dev/tty raw -echo 2>/dev/null || \
76 stty -f /dev/tty raw -echo || exit $?
77fi
78
79[ "$options_keyIn" = true ] && req_size=1
80
81if [ "$options_keyIn" = true ] && [ -n "$options_limit" ]; then
82 if [ "$options_caseSensitive" = true ]; then
83 limit_ptn="$options_limit"
84 else
85 # Safe list
86 # limit_ptn="$(printf '%s' "$options_limit" | sed 's/\([a-z]\)/\L\1\U\1/ig')"
87 limit_ptn="$(printf '%s' "$options_limit" | perl -pe 's/([a-z])/lc($1) . uc($1)/ige')"
88 fi
89fi
90
91while :
92do
93 if [ "$is_cooked" != true ]; then
94 # chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null)"
95 chunk="$(dd if=/dev/tty bs=1 count=1 2>/dev/null | perl -pe 's/[\r\n]/\fNL/g')"
96 else
97 IFS= read -r chunk </dev/tty || exit $?
98 chunk="$(printf '%s\fNL' "$chunk")"
99 fi
100
101 # if [ -n "$chunk" ] && [ "$(printf '%s' "$chunk" | tr '\r' '\n' | wc -l)" != "0" ]; then
102 # chunk="$(printf '%s' "$chunk" | tr '\r' '\n' | head -n 1)"
103 if [ -n "$chunk" ] && printf '%s' "$chunk" | perl -ne '/\fNL/ or exit 1'; then
104 chunk="$(printf '%s' "$chunk" | perl -pe 's/^(.*?)\fNL.*$/$1/')"
105 at_eol=true
106 fi
107
108 # other ctrl-chars
109 if [ -n "$chunk" ]; then
110 # chunk="$(printf '%s' "$chunk" | tr -d '\00-\10\13\14\16-\37\177')"
111 # for System V
112 chunk="$(printf '%s' "$chunk" | tr -d '\00\01\02\03\04\05\06\07\10\13\14\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\177')"
113 fi
114 if [ -n "$chunk" ] && [ -n "$limit_ptn" ]; then
115 chunk="$(printf '%s' "$chunk" | tr -cd "$limit_ptn")"
116 fi
117
118 if [ -n "$chunk" ]; then
119 if [ "$is_cooked" != true ]; then
120 if [ "$options_hideEchoBack" != true ]; then
121 write_tty "$chunk"
122 elif [ -n "$options_mask" ]; then
123 write_tty "$(replace_allchars "$chunk" "$options_mask")"
124 fi
125 fi
126 input="$input$chunk"
127 fi
128
129 if ( [ "$options_keyIn" != true ] && [ "$at_eol" = true ] ) || \
130 ( [ "$options_keyIn" = true ] && [ ${#input} -ge $req_size ] ); then break; fi
131done
132
133if [ "$is_cooked" != true ] && [ "$silent" != true ]; then write_tty "$(printf '%b' '\fNL')"; fi
134
135printf "'%s'" "$input"
136
137exit 0