naggie / dstask

Git powered terminal-based todo/note manager -- markdown note page per task. Single binary!
https://calbryant.uk/blog/dstask-a-taskwarrior-alternative/
MIT License
803 stars 47 forks source link

Feature Request: Hooks #39

Open cgardner opened 4 years ago

cgardner commented 4 years ago

I use taskwarrior's hooks for integrating in other applications (time tracking with ledger mostly) and it would be awesome to have a similar capability with dstask.

naggie commented 4 years ago

Hooks are not currently planned but perhaps they'd be a valuable feature, allowing plugging in to other things instead of implementing everything to reduce bloat.

How does your ledger integration work with taskwarrior?

cgardner commented 4 years ago

It's pretty simple, It just updates a file with templated value. https://www.ledger-cli.org/3.0/doc/ledger3.html#Time-Keeping

So when I start a task, It'll just update my file with something like i 2020/07/27 16:40:00 PROJECT:ProjectName When I stop a task, it does exactly the same thing, except the first character is "o"

Dieterbe commented 3 years ago

an alternative to consider, is shell scripts/aliases/functions that wrap dstask calls and execute other logic around them.

i'm thinking something like

function task {
    if [ "$1" == "start" ]; then
        echo "i $(date +'%F %T') PROJECT:ProjectName" >> somefile
        exec dstask "$@"
    fi                 
    if [ "$1" == "stop" ]; then
        echo "o $(date +'%F %T') PROJECT:ProjectName" >> somefile
        exec dstask "$@"
    fi
}

pro:

  1. not bound by a hooks system, "anything's possible".
  2. easy to debug and familiar syntax if you know basic shell scripting

con:

  1. perhaps more ugly
  2. not sure how to get certain values that dtask itself might infer based on environment variables, configuration, etc
  3. if values need to be parsed out of the commandline, that will get ugly too

to solve con 2/3, we could also, perhaps pass a special flag to dstask that makes it print all values (inferred context, time spent on tasks, etc), which can then be used in the script. Just as with a hooks system, you can typically use variables that automatically get expanded by dstask.

To be clear, I don't have a strong opinion on either approach. I'm merely mentioning an alternative. I guess they also don't have to be mutually exclusive. I think a hooks system is nice, if it's easy to understand and debug. (e.g. a --dry-run mode that allows you to freely invoke dstask commands to confirm that the hooks work without actually modifying your task database. with the script approach this can easily be done by uncommenting the calls to dstask)

cgardner commented 3 years ago

I've started going down this route with pretty much all of my tools.

Here's an example of the dstask function that I've been working on with a stub for start that can be used as a workaround

function dstask() {
  local action="$1"
  shift
  # if action is a number, switch with the next argument
  case $action in
    "jira")
      # Send task to Jira
      JIRA_PROJECT="JIRAPROJ"

      local stories=()
      echo "Creating stories for $@ in $JIRA_PROJECT"
      for id in ${@}; do
        local summary=$(command dstask $id | jq -r '.[0].summary | tostring')
        local notes=$(command dstask $id | jq -r '.[0].notes | tostring')

        local story=$(jira create -p $JIRA_PROJECT -i 'Story' --noedit \
          --override reporter=$(whoami) --override summary="${summary}" \
          --override description="${notes}" | awk '{ print $3 }')
        stories+=($story)
      done
      command dstask $@ done
      echo $stories

      ;;
    "shortcut")
      # Shortcut so I don't have to remember the template numbers
      command dstask add "${2}" template:65
      ;;
    "export" | "ex")
      # Export notes to MS Word
      local id="${1}"

      local summary=$(command dstask $id | jq -r '.[0].summary | tostring')
      local notes=$(command dstask $id |jq -r '.[0].notes | tostring')

      echo "${notes}" | pandoc --defaults \
        $HOME/.config/pandoc/defaults.yaml --filter pandoc-plantuml -o \
        $HOME/Downloads/$summary.docx

      echo "\"$HOME/Downloads/$summary.docx\""
      ;;
    "start") 
      # Do something before
      command dstask start $@
      # Do something after
      ;;
    *)
      command dstask $@
      ;;
  esac
}
cgardner commented 3 years ago

I wonder how well the git-hooks could be used as a workaround. Specifically some custom pre and post commit script examples.

Dieterbe commented 3 years ago

i think we need to start collecting more use cases of what people actually want to achieve. the use case of time tracking seems like a great example and demonstrates why a hook system native in dstask would be better than using git-hooks. Git would see "a commit is happening", but dstask knows "a commit happens because task X from project Y with tags abc was just started", and dstask could make all that information available (say, as environment variables) to the hooked-in code. Git hooks would have to figure this out themselves by processing the commit (similarly, shell code extensions like i suggested would have a hard time figuring this out as well)