From 6a13649c54b6086095c13cb0a09812924f6d2c91 Mon Sep 17 00:00:00 2001 From: lew Date: Wed, 1 Apr 2026 23:00:00 +0100 Subject: [PATCH] feat: stop subcommand, and disables empty lines from counting as an alarm element --- nag | 64 ++++++++++++++++++++++++++++++++++++++++++++++++--- test/nag.bats | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 3 deletions(-) diff --git a/nag b/nag index 1b9ee4c..617b8a4 100755 --- a/nag +++ b/nag @@ -419,8 +419,8 @@ _read_alarms() { local _line while IFS= read -r _line || [[ -n "${_line}" ]] do - _ALARMS+=("${_line}") - done < "${NAG_PATH}" + [[ -n "${_line}" ]] && _ALARMS+=("${_line}") + done < "${NAG_PATH}" || true fi } @@ -540,7 +540,7 @@ _format_time() { _date_prefix="Tomorrow" elif (( _days_away <= 6 )) then - _date_prefix="$(date -d "@${_timestamp}" "+%A")" + _date_prefix="This $(date -d "@${_timestamp}" "+%A")" elif (( _days_away <= 13 )) then _date_prefix="Next $(date -d "@${_timestamp}" "+%A")" @@ -714,6 +714,12 @@ list() { _read_alarms + if (( ${#_ALARMS[@]} == 0 )) + then + printf "Nothing to nag about.\\n" + return 0 + fi + # Sort alarms by timestamp (field 2). local -a _sorted IFS=$'\n' _sorted=($(printf "%s\n" "${_ALARMS[@]}" | sort -t$'\t' -k2 -n)) @@ -743,6 +749,58 @@ list() { done } +# stop ######################################################################## + +describe "stop" < + +Description: + Stop an alarm by ID. +HEREDOC +stop() { + local _target_id="${1:-}" + [[ -n "${_target_id}" ]] || _exit_1 printf "Usage: %s stop \\n" "${_ME}" + + _acquire_lock + _read_alarms + + local -a _new_alarms=() + local _found=0 + local _line + + for _line in "${_ALARMS[@]:-}" + do + [[ -n "${_line}" ]] || continue + local _id + _id="$(_get_alarm_field "${_line}" 1)" + if [[ "${_id}" == "${_target_id}" ]] + then + _found=1 + else + _new_alarms+=("${_line}") + fi + done + + if [[ "${_found}" -eq 0 ]] + then + _release_lock + _exit_1 printf "No alarm with ID %s.\\n" "${_target_id}" + fi + + if [[ "${#_new_alarms[@]}" -eq 0 ]] + then + _ALARMS=() + : > "${NAG_PATH}" + else + _ALARMS=("${_new_alarms[@]}") + _write_alarms + fi + _release_lock + + printf "Stopped alarm %s.\\n" "${_target_id}" +} + # at ########################################################################## describe "at" <" ]] +} + +@test "stop removes an alarm by ID" { + run_nag at "tomorrow 3pm" "take a break" + run_nag stop 1 + [ "${status}" -eq 0 ] + [[ "${output}" =~ "Stopped alarm 1" ]] + run_nag + [[ "${output}" =~ "Nothing to nag about" ]] +} + +@test "stop removes only the targeted alarm" { + run_nag at "tomorrow 3pm" "first" + run_nag at "tomorrow 4pm" "second" + run_nag at "tomorrow 5pm" "third" + run_nag stop 2 + [ "${status}" -eq 0 ] + run_nag + [[ "${output}" =~ "first" ]] + [[ ! "${output}" =~ "second" ]] + [[ "${output}" =~ "third" ]] +} + +@test "stop with nonexistent ID fails" { + run_nag stop 99 + [ "${status}" -eq 1 ] +} + +@test "stop without ID fails" { + run_nag stop + [ "${status}" -eq 1 ] +} + @test "list sorts alarms by time" { run_nag at "tomorrow 3pm" "take a break" run_nag at "tomorrow 9am" "standup"