Dialogregie
Teil 7: Benutzerfreundliche Ein-/Ausgabe
Finale
In den vergangenen sechs Folgen der Programming Corner haben wir Ihnen die Grundlagen der Bash-Programmierung gezeigt. Damit sind Sie gut gerüstet, um vielseitige Skripte für den Alltag zu schreiben. Zusammen mit einem ansprechenden Design, wie es die drei Dialog-Programme bieten, lassen sich auch umfangreiche Eingaben verständlich abfragen. Doch Shell-Programmierung ist mehr als nur Bash-Scripting: Erst mit dem schier unerschöpflichen Werkzeugkasten der GNU-Tools wird sie zu einer leistungsfähigen und vielseitigen Programmiersprache.
Listing 1
termin-server
01 #!/bin/bash
02
03 TerminWarnung ()
04 {
05 if [ "$6" != "" ]; then
06 MailParm="-c $6"
07 fi
08
09 mail $MailParm -s "Termin am `date -d \"$2\" \"+%a, %d.%m.%Y\"`: ${4}" $1 << EOF
10 $5
11 EOF
12 }
13
14 if [ ! -r ~/.termine ]; then
15 echo "termin-server: Kann Termin-Liste nicht öffnen ($HOME/.termine)"
16 fi
17
18 IFS=$'\r'
19
20 read -a TerminListe << EOF
21 `grep -v "^#" ~/.termine | tr "\n" "$IFS"`
22 EOF
23
24 MailAdresse="${TerminListe[0]}"
25
26 IFS=$'\t'
27
28 i=1
29
30 while [ "${TerminListe[$i]}" != "" ]; do
31 set – ${TerminListe[$i]}
32
33 Vorwarnung="`date -d \"$1 $2 days ago\" +%Y%m%d`"
34 if [ "$Vorwarnung" -le "`date +%Y%m%d`" -a "$1" -ge "`date +%Y%m%d`" ]; then
35 TerminWarnung $MailAdresse $@L: *
36 fi
37
38 i=$[$i+1]
39 done
Listing 2
termin-client
001 #!/bin/bash
002 if [ -n "`which gdialog 2>/dev/null`" ]; then
003 Dialog="`which gdialog`"
004 DialogRedirect="2>~/.termine.in"
005 elif [ -n "`which kdialog 2>/dev/null`" ]; then
006 Dialog="`which kdialog`"
007 DialogRedirect="1>~/.termine.in"
008 elif [ -n "`which dialog 2>/dev/null`" ]; then
009 Dialog="`which dialog`"
010 DialogRedirect="2>~/.termine.in"
011 else
012 echo "Sie benötigen dialog, kdialog oder gdialog,"
013 echo "um dieses Programm benutzen zu können."
014 exit 1
015 fi
016
017 COLUMNS=80
018 LINES=24
019
020 AuswahlMenue ()
021 {
022 Titel="\"$1\""
023 Tasten="$2"
024 Namen="$3"
025
026 IFS=$'\t'
027 set – $Tasten
028 i=1
029 while [ "$#" -gt "0" ]; do
030 Taste[$i]="\"$1\""
031 shift
032 i=$[$i+1]
033 done
034 Elemente="$i"
035
036 IFS=$'\t'
037 set – $Namen
038 i=1
039 while [ "$#" -gt "0" ]; do
040 Name[$i]="\"$1\""
041 shift
042 i=$[$i+1]
043 done
044
045 Menu=""
046 for ((i=1; $i<$Elemente; i=$[$i+1])); do
047 Menu="${Menu}${Taste[$i]}${IFS}${Name[$i]}${IFS}"
048 done
049
050 Overhead="7"
051 if [ "$[$Elemente+$Overhead]" -lt "$LINES" ]; then
052 DisplayLines="$[$Elemente+$Overhead]"
053 else
054 DisplayLines="$LINES"
055 fi
056 DialogParms="--menu $Titel $DisplayLines $[$COLUMNS-8] $[$Elemente-1] $Menu"
057 eval $Dialog $DialogParms $DialogRedirect
058 read < ~/.termine.in
059 }
060 TextEingabe ()
061 {
062 DialogParms="--inputbox \"$1\" 8 $[$COLUMNS-8] \"$2\""
063 eval $Dialog $DialogParms $DialogRedirect
064 read < ~/.termine.in
065 if [ "$REPLY" = "" ]; then
066 REPLY="$2"
067 fi
068 }
069 JaNein ()
070 {
071 DialogParms="--yesno \"$1\" 5 $[$COLUMNS-8]"
072 eval $Dialog $DialogParms $DialogRedirect
073 }
074 Fehler ()
075 {
076 DialogParms="--msgbox \"$1\" 5 $[$COLUMNS-8]"
077 eval $Dialog $DialogParms $DialogRedirect
078 }
079 TerminBearbeiten ()
080 {
081 Nr="$1"
082
083 while true; do
084 Keys="d${IFS}v${IFS}b${IFS}t${IFS}c${IFS}l${IFS}z${IFS}"
085 Menu="Datum: `date -d ${Datum[$Nr]} +%d.%m.%Y`${IFS}Vorwarnung: ${Vorwarnzeit[$Nr]} Tage${IFS}Betreff: ${Bezeichnung[$Nr]}${IFS}Text: ${Text[$Nr]}${IFS}CCs: ${CCs[$Nr]}${IFS}Löschen${IFS}Zurück"
086
087 AuswahlMenue "Termin bearbeiten:" "$Keys" "$Menu"
088 Auswahl="$REPLY"
089
090 case $Auswahl in
091 z|"")
092 break
093 ;;
094 l)
095 JaNein "Termin löschen: Sind Sie sicher?"
096
097 if [ "$?" = "0" ]; then
098 Termine=$[$Termine-1]
099
100 for ((i=$Nr; $i < $Termine; i=$[$i+1])); do
101 Datum[$i]=${Datum[$[$i+1]]}
102 Vorwarnzeit[$i]=${Vorwarnzeit[$[$i+1]]}
103 Bezeichnung[$i]=${Bezeichnung[$[$i+1]]}
104 Text[$i]=${Text[$[$i+1]]}
105 CCs[$i]=${CCs[$[$i+1]]}
106 done
107 fi
108 break
109 ;;
110 d)
111 TextEingabe "Datum, in der Form yyyy-mm-dd:" "`date -d ${Datum[$Nr]} +%Y-%m-%d`"
112 Datum[$Nr]="`date -d $REPLY +%Y%m%d`"
113 ;;
114 v)
115 TextEingabe "Vorwarnzeit in Tagen:" "${Vorwarnzeit[$Nr]}"
116 Vorwarnzeit[$Nr]="$REPLY"
117 ;;
118 b)
119 TextEingabe "Kurze Bezeichnung des Termins:" "${Bezeichnung[$Nr]}"
120 Bezeichnung[$Nr]="$REPLY"
121 ;;
122 t)
123 TextEingabe "Ausführliche Beschreibung, Anmerkungen:" "${Text[$Nr]}"
124 Text[$Nr]="$REPLY"
125 ;;
126 c)
127 TextEingabe "Zusätzliche Empfänger der Warnung (Komma-Trennung):" "${CCs[$Nr]}"
128 CCs[$Nr]="$REPLY"
129 ;;
130 esac
131 done
132 }
133
134 ##### Hauptprogramm #####
135
136 if [ -r ~/.termine ]; then
137 IFS=$'\r'
138 read -a TerminListe << EOF
139 `grep -v "^#" ~/.termine | tr "\n" "$IFS"`
140 EOF
141
142 IFS=$'\t'
143 i=1
144 while [ "${TerminListe[$i]}" != "" ]; do
145 set – ${TerminListe[$i]}
146 Datum[$i]=$1
147 Vorwarnzeit[$i]=$2
148 Bezeichnung[$i]=$3
149 Text[$i]=$4
150 CCs[$i]=$5
151 i=$[$i+1]
152 done
153 Termine="$i"
154 else
155 MailAdresse="${LOGNAME}@localhost"
156 Termine=1
157 fi
158
159 while true; do
160 IFS=$'\t'
161 Keys="0${IFS}\$Keys${IFS}n${IFS}q${IFS}x${IFS}"
162 Menu="Adresse: ${MailAdresse}\$Menu${IFS}Neuer Termin${IFS}Speichern und Ende${IFS}Ende ohne Speichern"
163 for ((i=1; $i < $Termine; i=$[$i+1])); do
164 Keys="${Keys/\$Keys/${IFS}$i\$Keys}"
165 Menu="${Menu/\$Menu/${IFS}`date -d ${Datum[$i]} +%d.%m.%Y`: ${Bezeichnung[$i]}\$Menu}"
166 done
167 Keys="${Keys/\$Keys}"
168 Menu="${Menu/\$Menu}"
169
170 AuswahlMenue "Hauptmenü" "$Keys" "$Menu"
171 Auswahl="$REPLY"
172
173 case $Auswahl in
174 q)
175 if [ ! -e ~/.termine ]; then
176 touch ~/.termine 2>/dev/null
177 fi
178 if [ -w ~/.termine ]; then
179 echo "$MailAdresse" > ~/.termine
180 IFS=$'\t'
181 for ((i=1; $i < $Termine; i=$[$i+1])); do
182 cat >> ~/.termine << EOF
183 ${Datum[$i]}${IFS}${Vorwarnzeit[$i]}${IFS}${Bezeichnung[$i]}${IFS}${Text[$i]}${IFS}${CCs[$i]}
184 EOF
185 done
186 break
187 else
188 Fehler "Die Termine-Datei (~/.termine) lässt sich nicht schreiben."
189 fi
190 ;;
191 x|"")
192 exit 1
193 ;;
194 n)
195 Datum[$Termine]="`date +%Y%m%d`"
196 Vorwarnzeit[$Termine]="2"
197 Bezeichnung[$Termine]=""
198 Text[$Termine]=""
199 CCs[$Termine]=""
200 Termine=$[$Termine+1]
201 TerminBearbeiten $[$Termine-1]
202 ;;
203 0)
204 TextEingabe "Ihre Email-Adresse:" "$MailAdresse"
205 MailAdresse="$REPLY"
206 ;;
207 @L: *)
208 TerminBearbeiten $Auswahl
209 ;;
210 esac
211 done



