calcurse_dmenu.sh (7086B)
1 #!/bin/sh 2 3 PROGDIR="$(cd -- "$(dirname -- "$0")" && pwd)" 4 . $PROGDIR/config.sh 5 6 [ -d "$cal_dir" ] || mkdir -p "$cal_dir" 7 [ -d "$cal_notes" ] || mkdir -p "$cal_notes" 8 [ -f "$cal_apts" ] || touch "$cal_apts" 9 [ -f "$cal_todo" ] || touch "$cal_todo" 10 [ -f "$cal_alarm" ] || touch "$cal_alarm" 11 12 t="$(mktemp)" && u="$(mktemp)" && v="$(mktemp)" && x="$(mktemp)" && y="$(mktemp)" || exit 1 13 14 cu(){ 15 rm "$u" "$t" "$v" "$x" "$y" 2>/dev/null 16 exit 0 17 } 18 19 trap cu INT 20 21 cal_msg(){ 22 msg_m="${1:-""}" 23 msg_p="${2:-""}" 24 msg_r="${3:-0}" 25 printf "%s\n" "$msg_m" | $dmenu -p "$msg_p" && return $msg_r 26 } 27 28 cal_lno_dmenu_string(){ 29 l="$(<$u sed -n "s/^.*<\([0-9]\+\)\(${rm_tag}\)*\(${n_tag}\)*\(${e_tag}\)*$/\1/p")" && \ 30 [ -n "$l" ] && \ 31 return 0 || return 1 32 } 33 34 __cal_title(){ 35 s="$S_TITLE" 36 #d="$(date +"%A, %B %d %Y")" 37 case "$typeflag" in 38 "h") s="$S_HISTORY" ;; 39 "t") s="$S_TODO" ;; 40 "a") s="$S_ALARM" ;; 41 esac 42 printf "%s" "$s" 43 } 44 45 __cal_evt_sel(){ 46 sh "$PROGDIR/entries.sh" -t "$typeflag" | \ 47 $dmenu -i -p "$(__cal_title)" || \ 48 return 1 49 #cu 50 } 51 52 cal_evt_sel(){ 53 # u = tmp file storing selected dmenu string 54 # v = tmp file storing full data line 55 # l = db line number 56 # n = note filename 57 __cal_evt_sel > $u && \ 58 cal_lno_dmenu_string && \ 59 < "$db_file" sed -n "${l}p" > $v && \ 60 n="$(<$v grep -o "$note_pattern" | tr -d ">")" && \ 61 return 0 || return 1 62 } 63 64 cal_rm_note_file(){ 65 f="${cal_notes}/${n}" 66 [ -f "$f" ] && rm "$f" 67 return 0 68 } 69 70 cal_is_todo(){ [ "$typeflag" = "t" ]; } 71 72 cal_is_alarm(){ [ "$typeflag" = "a" ]; } 73 74 cal_rm_note_ref(){ 75 cal_is_todo && s="" || s=" " 76 sed -i "${l}s/^\(.*\)${note_pattern}${s}\(.*\)$/\1\2/" "$db_file" 77 } 78 79 cal_rm_entry(){ 80 [ "$l" -gt 0 ] && sed -i "${l}d" "$db_file" 81 } 82 83 cal_note_view(){ 84 #"$term" $pager "${cal_notes}/${n}" 85 "$term" $EDITOR "${cal_notes}/${n}" 86 } 87 88 cal_entry_view(){ 89 $term sh $PROGDIR/entry_view.sh $u "$cal_notes/$n" "$typeflag" 90 } 91 92 grep_prep(){ 93 # escape special grep chars 94 b="$(<$v sed -e 's#\([][\$\*\^]\)#\\\1#g')" 95 } 96 97 flag_reset(){ 98 # Type flags 99 # c > main calendar 100 # h > historia 101 # t > todo 102 typeflag="c" 103 } 104 105 cal_note_add(){ 106 107 if cal_is_todo; then 108 sed -i " 109 ${note_lno}s/\(^\[[0-9]\+\]\)\(.*\)$/\1>${n}\2/ 110 " "$cal_note_add_file" && return 0 || return 1 111 else 112 sed -i " 113 ${note_lno}s/\(^[0-9\/]\+ \)\(@[- 0-9\>\/:@]\+\)\({.*} \)*\(|\)/\1\2\3>${n} \4/ 114 ${note_lno}s/\(^[0-9\/]\+ \)\(\[[0-9]\+\] \)\({.*} \)*/\1\2\3>${n} / 115 " "$cal_note_add_file" && return 0 || return 1 116 fi 117 } 118 119 cal_note_create(){ 120 121 # Create note 122 >$t && "$term" $EDITOR $t 123 if [ -s "$t" ] 124 then 125 # Generate note file name 126 n="$(</dev/urandom tr -dc '0-9a-f' | head -c40)" 127 # Copy temp to new note file 128 cp $t "${cal_notes}/${n}" 129 # Update apts db entry with note reference 130 cal_note_add_file="$db_file" 131 note_lno="$l" 132 if ! cal_note_add; then 133 rm -v "${cal_notes}/${n}" 134 cal_msg "removed note file, aborting cal_note_create" "cal_note_create error" 135 fi 136 fi 137 } 138 139 sort_entries(){ 140 [ -n "$1" ] && \ 141 <$v grep -E "$1" | \ 142 sed 's#^\(..\)/\(..\)/\(....\)#\3\1\2 \1/\2/\3#' | \ 143 sort | \ 144 cut -d" " -f2- >> $x && \ 145 return 0 || return 1 146 } 147 148 sort_todo(){ 149 # Sort rank then desc 150 # Move possible note for sorting, then back 151 [ -n "$1" ] && \ 152 <$v grep "$1" | \ 153 sed "s/^\(\[[0-9]\]\)\(${note_pattern}\)\( .*\)$/\1\3\2/" | \ 154 sort | \ 155 sed "s/^\(\[[0-9]\]\)\( .*\)\(${note_pattern}\)$/\1\3\2/" >> $x && \ 156 return 0 || return 1 157 } 158 sort_finalize(){ 159 >$x && \ 160 sort_entries "^[[:digit:]/]{10} \[[[:digit:]]+\] {" && \ 161 sort_entries "^[[:digit:]/]{10} @.{29}{" && \ 162 sort_entries "^[[:digit:]/]{10} @.{28}[>|]" && \ 163 sort_entries "^[[:digit:]/]{10} \[[[:digit:]]+\] [^{]" && \ 164 sort_todo "^\[[1-9]\]" && \ 165 sort_todo "^\[0\]" && \ 166 cp $x "$db_file" && \ 167 return 0 || return 1 168 } 169 170 cal_entry_edit(){ 171 # Edit entry: 172 # Parse line into calcurse_dmenu syntax 173 # Then run it into dmenu to make changes 174 # Then rm old entry 175 # Then send it into the awk processing below 176 # for new changes to be added to db file. 177 # There's more to do here than I 178 # initially thought... 179 #if entry_edit="$(<$v awk -f "$entry_edit_parser_awk" | $dmenu)"; then 180 if <$v awk -f "$entry_edit_parser_awk" | $dmenu >$t; then 181 # If edit empty, ignore 182 <$t grep -q "^[[:space:]]*$" || [ ! -s $t ] && return 0 183 # Add double colon date/description seperator if needed 184 <$t grep -q "^.*::.\+$" || sed -i 's/^/::/' $t 185 # Attemp parse of entry edit 186 if awk -vtypeflag="$typeflag" -f "$entry_add_awk" $t > $y; then 187 # If note, add it back to entry 188 if [ -n "$n" ]; then 189 cal_note_add_file="$y" 190 note_lno="1" 191 if ! cal_note_add; then 192 cal_msg "Error adding note back into edited entry. Aborting edit." 193 fi 194 fi 195 196 # Remove original entry (but keep note file) 197 cal_rm_entry 198 199 # Add freshly edited entry 200 if [ -f "$db_file" ]; then 201 cat "$db_file" "$y" > "$v" 202 sort_finalize || cal_msg "Error sorting/finalizing entry edit. Aborting edit." 203 fi 204 205 cal_msg "$(<$y awk -f "$entry_edit_parser_awk")" "Entry Edit Success" 206 else 207 cal_msg "Entry edit error, aborting edit." 208 fi 209 fi 210 } 211 212 cal_view(){ 213 214 if cal_evt_sel 215 then 216 # Remove if tagged :::r 217 if <$u grep -q "$rm_tag$" 218 then 219 cal_rm_entry 220 cal_rm_note_file 221 222 elif <$u grep -q "$n_tag$" 223 then 224 # Open note in pager 225 if [ -n "$n" ] 226 then 227 if [ -f "$cal_notes/$n" ] 228 then 229 cal_note_view 230 231 # If note empty, rm it 232 if [ ! -s "$cal_notes/$n" ] 233 then 234 cal_rm_note_file 235 cal_rm_note_ref 236 fi 237 fi 238 else 239 cal_note_create 240 fi 241 elif <$u grep -q "$e_tag$" 242 then 243 cal_entry_edit 244 else 245 cal_entry_view 246 fi 247 else 248 # Emergency exit 249 <$u grep -q "^exit$\|^quit$" && cu 250 251 # If line seperator for today/tomorrow/yesterday, do nothing 252 <$u grep "^$S_SEPERATOR$" && return 0 253 254 # If from historia, back to main list 255 [ "$typeflag" = "h" ] && flag_reset && return 0 256 257 [ "$typeflag" = "t" ] && [ ! -s $u ] && flag_reset && return 0 258 259 [ "$typeflag" = "a" ] && [ ! -s $u ] && flag_reset && return 0 260 261 # Exit if selection empty 262 <$u grep -q "^[[:space:]]*$" || [ ! -s $u ] && return 1 263 264 # launch calcurse 265 <$u grep -q "^calcurse$" && { $term calcurse; return 1; } 266 267 # Historia 268 <$u grep -q "^${h_tag}$" && typeflag="h" && return 0 269 270 # Todo 271 <$u grep -q "^${t_tag}$" && typeflag="t" && return 0 272 273 # Alarm 274 <$u grep -q "^${a_tag}$" && typeflag="a" && return 0 275 276 # Prepare for awk parse 277 278 # Add 2 colons for awk parsing 279 # This allows for quick event entries 280 # for current day. 281 # Cal entry: date(s)::description 282 # Todo entry: rank(optional)::description 283 <$u grep -q "^.*::.\+$" || sed -i 's/^/::/' $u 284 285 # Add new entry to apts file 286 # Parse new entry with awk 287 # Sort new list of entries in following order: 288 # 1 > event recurring 289 # 2 > apt recurring 290 # 3 > apt 291 # 4 > event 292 293 >$v 294 [ -f "$db_file" ] && cp "$db_file" "$v" 295 awk -vtypeflag="$typeflag" -f "$entry_add_awk" $u >> $v && \ 296 sort_finalize && \ 297 return 0 298 return 1 299 fi 300 } 301 302 # Set typeflag to Calendar to kick things off 303 flag_reset 304 305 #And so it begins 306 while 307 db_file="$cal_apts" 308 cal_is_todo && db_file="$cal_todo" 309 cal_is_alarm && db_file="$cal_alarm" 310 cal_view 311 do :; done 312 cu