Rename `t' to `justdoit' - justdoit - Simpler (but with not all the features) reimplementation todo.txt CLI
 (HTM) hg clone https://bitbucket.org/iamleot/justdoit
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) changeset 67517dd04e717a75c0781b31cbd3bc7995c4897a
 (DIR) parent 8d69dd7ce60a69da1cc19da11425f7f57bc670b0
 (HTM) Author: Leonardo Taccari <iamleot@gmail.com>
       Date:   Wed,  8 May 2019 19:26:59 
       
       Rename `t' to `justdoit'
       
       Diffstat:
        justdoit.sh |  318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        t.sh        |  318 ------------------------------------------------------------
        2 files changed, 318 insertions(+), 318 deletions(-)
       ---
       diff -r 8d69dd7ce60a -r 67517dd04e71 justdoit.sh
       --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
       +++ b/justdoit.sh       Wed May 08 19:26:59 2019 +0200
       @@ -0,0 +1,318 @@
       +#!/bin/sh
       +
       +#
       +# Copyright (c) 2018 Leonardo Taccari
       +# All rights reserved.
       +# 
       +# Redistribution and use in source and binary forms, with or without
       +# modification, are permitted provided that the following conditions
       +# are met:
       +# 
       +# 1. Redistributions of source code must retain the above copyright
       +#    notice, this list of conditions and the following disclaimer.
       +# 2. Redistributions in binary form must reproduce the above copyright
       +#    notice, this list of conditions and the following disclaimer in the
       +#    documentation and/or other materials provided with the distribution.
       +# 
       +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
       +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
       +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       +# POSSIBILITY OF SUCH DAMAGE.
       +#
       +
       +config_file=${T_CONFIG_FILE:=${HOME}/.config/t/t.conf}
       +
       +if [ -f "${config_file}" ]; then
       +       . "${config_file}"
       +fi
       +
       +todo_file=${T_TODO_FILE:=${HOME}/.config/t/todo.txt}
       +done_file=${T_DONE_FILE:=${HOME}/.config/t/done.txt}
       +
       +
       +#
       +# Print usage message and exit
       +#
       +usage()
       +{
       +
       +       echo "usage: t add|done|due|edit|help|list|listall"
       +
       +       exit 1
       +}
       +
       +
       +#
       +# Print help message and exit
       +#
       +help()
       +{
       +
       +       echo "usage: t add|done|edit|help|list|listall"
       +       echo
       +       echo "a|add entry"
       +       echo "Add the entry \`entry' at the end of the todo.txt file."
       +       echo
       +       echo "d|do|done item"
       +       echo "Mark an item \`item' of todo.txt file as done, moving it in done.txt"
       +       echo "and removing it from todo.txt"
       +       echo
       +       echo "due days [pattern]"
       +       echo "List all task due next number of days - and all the expired"
       +       echo "ones - that matches pattern (or all of them if no pattern is"
       +       echo "provided)"
       +       echo
       +       echo "e|ed|edit"
       +       echo "Open the todo.txt with the \${EDITOR}"
       +       echo
       +       echo "h|help"
       +       echo "Show an help message"
       +       echo
       +       echo "l|ls|list [pattern]"
       +       echo "List all todo.txt entries that matches pattern (or all of them"
       +       echo "if no pattern is provided)"
       +       echo
       +       echo "la|lsa|listall [pattern]"
       +       echo "List all done.txt and todo.txt entries that matches pattern (or"
       +       echo "all of them if no pattern is provided)"
       +       echo
       +
       +       exit 1
       +}
       +
       +
       +#
       +# Add an entry at the end of a todo.txt file
       +#
       +add()
       +{
       +       file=$1
       +       entry=$2
       +
       +       echo "${entry}" >> "${file}"
       +}
       +
       +
       +#
       +# Mark an entry item as done, adding it to the done.txt file and removing it
       +# from the todo.txt file.
       +#
       +mark_done()
       +{
       +       tfile=$1
       +       dfile=$2
       +       item=$(($3))
       +
       +       if [ ${item} -ge 1 ] && [ ${item} -le $(wc -l < "${tfile}") ]; then
       +               {
       +                       printf "x %s " "$(date +%Y-%m-%d)";
       +                       sed -n "${item}p" "${tfile}";
       +               } >> "${dfile}"
       +               sed -i.bak "${item}d" "${tfile}"
       +       fi
       +}
       +
       +
       +#
       +# List, show the contents of a todo.txt file
       +#
       +list()
       +{
       +       file=$1
       +       search=$2
       +
       +       if [ "${search}" ]; then
       +               filter() grep -F -- "${search}"
       +       else
       +               filter() cat
       +       fi
       +
       +       cat "${file}" | prettify | filter
       +}
       +
       +
       +#
       +# Prettify the output of a todo.txt
       +#
       +prettify()
       +{
       +
       +       awk '
       +       BEGIN {
       +               FS = " "
       +       }
       +
       +       function bold(s) {
       +               return sprintf("\033[1m%s\033[0m", s);
       +       }
       +
       +       function underline(s) {
       +               return sprintf("\033[4m%s\033[0m", s);
       +       }
       +
       +       #
       +       # Parse the entry and populate all optional and non-optional fields
       +       #
       +       # Every line of todo.txt file should have the following format:
       +       #
       +       #  +------------+------------+-----------------+---------------+-------------+
       +       #  | completion |  priority  | completion date | creation date | description |
       +       #  | (optional) | (optional) |   (optional)    |  (optional)   |             |
       +       #  +------------+------------+-----------------+---------------+-------------+
       +       #
       +       # where:
       +       #  - completion: just a lower-case "x" to mark that a task is done
       +       #  - priority: a upper-case letter under parethenses (e.g. "(A)")
       +       #  - completion date: date of completion of the task in the %Y-%m-%d
       +       #                     format (e.g. "2018-08-18")
       +       #  - creation date: date of creation of the task in the %Y-%m-%d
       +       #                   format (e.g. "2018-08-18")
       +       #  - description: text of the task; can contain multiple +project_tag,
       +       #                 @context_tag, special key/value tag (key:value)
       +       #
       +       {
       +               completion = ""
       +               priority = ""
       +               completion_date = ""
       +               creation_date = ""
       +               description = ""
       +
       +               i = 1
       +
       +               if ($i == "x") {
       +                       completion = "x"
       +                       i++
       +               }
       +               if (match($i, /\([A-Z]\)/)) {
       +                       priority = $i
       +                       i++
       +               }
       +               if (completion && match($i, /[0-9]+-[0-9]+-[0-9]+/)) {
       +                       completion_date = $i
       +                       i++
       +               }
       +               if (match($i, /[0-9]+-[0-9]+-[0-9]+/)) {
       +                       creation_date = $i
       +                       i++
       +               }
       +
       +               # Remove any non-description fields and possible leading spaces
       +               for (j = 1; j < i; j++) {
       +                       $j = ""
       +               }
       +               sub(/^ +/, "")
       +               description = $0
       +       }
       +
       +       {
       +               # bold all the tags
       +               gsub(/@[^ ]+/, "\033[1m&\033[0m", description)
       +
       +               if (completion) {
       +                       printf("%12s %s\n", underline(completion), description)
       +               } else {
       +                       n++
       +                       printf("%12s %s\n", underline(n), description)
       +               }
       +       }
       +       '
       +}
       +
       +
       +#
       +# Filter all due: key-values task of the next n. days and all "expired" ones.
       +#
       +due()
       +{
       +       days="$1"
       +
       +       awk -v days="${days}" '
       +       function date_to_seconds(date) {
       +               cmd = "date -d " date " +%s"
       +               cmd | getline
       +               close(cmd)
       +               return $0
       +       }
       +
       +       function seconds_to_date(seconds) {
       +               cmd = "date -r " seconds " +%Y%m%d"
       +               cmd | getline
       +               close(cmd)
       +               return $0
       +       }
       +
       +       BEGIN {
       +               n_days = int(days)
       +               n_seconds = date_to_seconds(strftime("%Y%m%d")) + \
       +                   (n_days * 60 * 60 * 24)
       +       }
       +
       +       match($0, /due:[0-9]+-[0-9]+-[0-9]+/) {
       +               # XXX: We mess up with getline in date_to_seconds()
       +               # XXX: so backup the current line.
       +               s = $0
       +
       +               # Delete "due:" and convert the date in %Y%m%d format
       +               due_date = substr(s, RSTART + 4, RLENGTH - 4)
       +               gsub(/\-/, "", due_date)
       +
       +               if (n_seconds >= date_to_seconds(due_date)) {
       +                       print s
       +               }
       +       }
       +       '
       +}
       +
       +
       +#
       +# t, a todo.sh clone in POSIX shell script
       +#
       +main()
       +{
       +       subcommand=$1
       +
       +       case $subcommand in
       +       a|add)
       +               entry=$2
       +               add "${todo_file}" "${entry}"
       +               ;;
       +       d|do|done)
       +               item=$2
       +               mark_done "${todo_file}" "${done_file}" "${item}"
       +               ;;
       +       due)
       +               days=$2
       +               search=$3
       +               list "${todo_file}" "${search}" | due "${days}"
       +               ;;
       +       e|ed|edit)
       +               ${EDITOR} "${todo_file}"
       +               ;;
       +       h|help)
       +               help
       +               ;;
       +       l|ls|list)
       +               search=$2
       +               list "${todo_file}" "${search}"
       +               ;;
       +       la|lsa|listall)
       +               search=$2
       +               list "${done_file}" "${search}"
       +               list "${todo_file}" "${search}"
       +               ;;
       +       *)
       +               usage
       +               ;;
       +       esac
       +
       +       exit 0
       +}
       +
       +main "$@"
       diff -r 8d69dd7ce60a -r 67517dd04e71 t.sh
       --- a/t.sh      Sat Sep 15 13:17:11 2018 +0200
       +++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
       @@ -1,318 +0,0 @@
       -#!/bin/sh
       -
       -#
       -# Copyright (c) 2018 Leonardo Taccari
       -# All rights reserved.
       -# 
       -# Redistribution and use in source and binary forms, with or without
       -# modification, are permitted provided that the following conditions
       -# are met:
       -# 
       -# 1. Redistributions of source code must retain the above copyright
       -#    notice, this list of conditions and the following disclaimer.
       -# 2. Redistributions in binary form must reproduce the above copyright
       -#    notice, this list of conditions and the following disclaimer in the
       -#    documentation and/or other materials provided with the distribution.
       -# 
       -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
       -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
       -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       -# POSSIBILITY OF SUCH DAMAGE.
       -#
       -
       -config_file=${T_CONFIG_FILE:=${HOME}/.config/t/t.conf}
       -
       -if [ -f "${config_file}" ]; then
       -       . "${config_file}"
       -fi
       -
       -todo_file=${T_TODO_FILE:=${HOME}/.config/t/todo.txt}
       -done_file=${T_DONE_FILE:=${HOME}/.config/t/done.txt}
       -
       -
       -#
       -# Print usage message and exit
       -#
       -usage()
       -{
       -
       -       echo "usage: t add|done|due|edit|help|list|listall"
       -
       -       exit 1
       -}
       -
       -
       -#
       -# Print help message and exit
       -#
       -help()
       -{
       -
       -       echo "usage: t add|done|edit|help|list|listall"
       -       echo
       -       echo "a|add entry"
       -       echo "Add the entry \`entry' at the end of the todo.txt file."
       -       echo
       -       echo "d|do|done item"
       -       echo "Mark an item \`item' of todo.txt file as done, moving it in done.txt"
       -       echo "and removing it from todo.txt"
       -       echo
       -       echo "due days [pattern]"
       -       echo "List all task due next number of days - and all the expired"
       -       echo "ones - that matches pattern (or all of them if no pattern is"
       -       echo "provided)"
       -       echo
       -       echo "e|ed|edit"
       -       echo "Open the todo.txt with the \${EDITOR}"
       -       echo
       -       echo "h|help"
       -       echo "Show an help message"
       -       echo
       -       echo "l|ls|list [pattern]"
       -       echo "List all todo.txt entries that matches pattern (or all of them"
       -       echo "if no pattern is provided)"
       -       echo
       -       echo "la|lsa|listall [pattern]"
       -       echo "List all done.txt and todo.txt entries that matches pattern (or"
       -       echo "all of them if no pattern is provided)"
       -       echo
       -
       -       exit 1
       -}
       -
       -
       -#
       -# Add an entry at the end of a todo.txt file
       -#
       -add()
       -{
       -       file=$1
       -       entry=$2
       -
       -       echo "${entry}" >> "${file}"
       -}
       -
       -
       -#
       -# Mark an entry item as done, adding it to the done.txt file and removing it
       -# from the todo.txt file.
       -#
       -mark_done()
       -{
       -       tfile=$1
       -       dfile=$2
       -       item=$(($3))
       -
       -       if [ ${item} -ge 1 ] && [ ${item} -le $(wc -l < "${tfile}") ]; then
       -               {
       -                       printf "x %s " "$(date +%Y-%m-%d)";
       -                       sed -n "${item}p" "${tfile}";
       -               } >> "${dfile}"
       -               sed -i.bak "${item}d" "${tfile}"
       -       fi
       -}
       -
       -
       -#
       -# List, show the contents of a todo.txt file
       -#
       -list()
       -{
       -       file=$1
       -       search=$2
       -
       -       if [ "${search}" ]; then
       -               filter() grep -F -- "${search}"
       -       else
       -               filter() cat
       -       fi
       -
       -       cat "${file}" | prettify | filter
       -}
       -
       -
       -#
       -# Prettify the output of a todo.txt
       -#
       -prettify()
       -{
       -
       -       awk '
       -       BEGIN {
       -               FS = " "
       -       }
       -
       -       function bold(s) {
       -               return sprintf("\033[1m%s\033[0m", s);
       -       }
       -
       -       function underline(s) {
       -               return sprintf("\033[4m%s\033[0m", s);
       -       }
       -
       -       #
       -       # Parse the entry and populate all optional and non-optional fields
       -       #
       -       # Every line of todo.txt file should have the following format:
       -       #
       -       #  +------------+------------+-----------------+---------------+-------------+
       -       #  | completion |  priority  | completion date | creation date | description |
       -       #  | (optional) | (optional) |   (optional)    |  (optional)   |             |
       -       #  +------------+------------+-----------------+---------------+-------------+
       -       #
       -       # where:
       -       #  - completion: just a lower-case "x" to mark that a task is done
       -       #  - priority: a upper-case letter under parethenses (e.g. "(A)")
       -       #  - completion date: date of completion of the task in the %Y-%m-%d
       -       #                     format (e.g. "2018-08-18")
       -       #  - creation date: date of creation of the task in the %Y-%m-%d
       -       #                   format (e.g. "2018-08-18")
       -       #  - description: text of the task; can contain multiple +project_tag,
       -       #                 @context_tag, special key/value tag (key:value)
       -       #
       -       {
       -               completion = ""
       -               priority = ""
       -               completion_date = ""
       -               creation_date = ""
       -               description = ""
       -
       -               i = 1
       -
       -               if ($i == "x") {
       -                       completion = "x"
       -                       i++
       -               }
       -               if (match($i, /\([A-Z]\)/)) {
       -                       priority = $i
       -                       i++
       -               }
       -               if (completion && match($i, /[0-9]+-[0-9]+-[0-9]+/)) {
       -                       completion_date = $i
       -                       i++
       -               }
       -               if (match($i, /[0-9]+-[0-9]+-[0-9]+/)) {
       -                       creation_date = $i
       -                       i++
       -               }
       -
       -               # Remove any non-description fields and possible leading spaces
       -               for (j = 1; j < i; j++) {
       -                       $j = ""
       -               }
       -               sub(/^ +/, "")
       -               description = $0
       -       }
       -
       -       {
       -               # bold all the tags
       -               gsub(/@[^ ]+/, "\033[1m&\033[0m", description)
       -
       -               if (completion) {
       -                       printf("%12s %s\n", underline(completion), description)
       -               } else {
       -                       n++
       -                       printf("%12s %s\n", underline(n), description)
       -               }
       -       }
       -       '
       -}
       -
       -
       -#
       -# Filter all due: key-values task of the next n. days and all "expired" ones.
       -#
       -due()
       -{
       -       days="$1"
       -
       -       awk -v days="${days}" '
       -       function date_to_seconds(date) {
       -               cmd = "date -d " date " +%s"
       -               cmd | getline
       -               close(cmd)
       -               return $0
       -       }
       -
       -       function seconds_to_date(seconds) {
       -               cmd = "date -r " seconds " +%Y%m%d"
       -               cmd | getline
       -               close(cmd)
       -               return $0
       -       }
       -
       -       BEGIN {
       -               n_days = int(days)
       -               n_seconds = date_to_seconds(strftime("%Y%m%d")) + \
       -                   (n_days * 60 * 60 * 24)
       -       }
       -
       -       match($0, /due:[0-9]+-[0-9]+-[0-9]+/) {
       -               # XXX: We mess up with getline in date_to_seconds()
       -               # XXX: so backup the current line.
       -               s = $0
       -
       -               # Delete "due:" and convert the date in %Y%m%d format
       -               due_date = substr(s, RSTART + 4, RLENGTH - 4)
       -               gsub(/\-/, "", due_date)
       -
       -               if (n_seconds >= date_to_seconds(due_date)) {
       -                       print s
       -               }
       -       }
       -       '
       -}
       -
       -
       -#
       -# t, a todo.sh clone in POSIX shell script
       -#
       -main()
       -{
       -       subcommand=$1
       -
       -       case $subcommand in
       -       a|add)
       -               entry=$2
       -               add "${todo_file}" "${entry}"
       -               ;;
       -       d|do|done)
       -               item=$2
       -               mark_done "${todo_file}" "${done_file}" "${item}"
       -               ;;
       -       due)
       -               days=$2
       -               search=$3
       -               list "${todo_file}" "${search}" | due "${days}"
       -               ;;
       -       e|ed|edit)
       -               ${EDITOR} "${todo_file}"
       -               ;;
       -       h|help)
       -               help
       -               ;;
       -       l|ls|list)
       -               search=$2
       -               list "${todo_file}" "${search}"
       -               ;;
       -       la|lsa|listall)
       -               search=$2
       -               list "${done_file}" "${search}"
       -               list "${todo_file}" "${search}"
       -               ;;
       -       *)
       -               usage
       -               ;;
       -       esac
       -
       -       exit 0
       -}
       -
       -main "$@"