Taskwarrior Context, extended

Wie man Taskwarrior auf einem uberspace installiert, hatte ich ja schon geschrieben. Dort erwähnte ich schon, dass ich Taskwarrior nicht nur für die private Aufgabenverwaltung nutze, sondern auch dienstliche Tasks damit verwalte. Nun ist Taskwarrior allerdings so aufgebaut, dass alle Tasks einer Taskwarrior-Instanz in einer gemeinsamen Datensenke landen. In meinem Fall ist das der Taskserver, der auf dem uberspace läuft. Schaue ich nun zu Hause meine Taskliste an, sehe ich auch alle dienstlichen Tasks, im Büro auch alle privaten. Nicht sehr schön.

Um diesem Problem etwas entgegenzusteuern, hat das Taskwarrior-Team Contexts eingeführt. Dabei handelt es sich im Grunde genommen um einen permanenten Filter, der bei jedem Kommando angewendet wird. Ein Beispiel: Ich möchte einen Context mit dem Namen work, der nur Tasks anzeigt, die das Tag +work haben. Das Kommando task context define work +work erstellt ebendieses Context. In der Konfigurationsdatei wird ein solcher Context ganz einfach mit der Zeile context.work=+work hinterlegt. Um diesen Context nun zu nutzen, muss er noch per task context work aktiviert werden. Rufe ich nun task list auf, werden nur noch die Tasks aufgelistet, die mit dem Tag +work versehen sind.

Prinzipiell eine super Sache. Nach einiger Gewöhnungszeit stieß ich allerdings schnell an die Grenze, dass mir dieses Konzept etwas zu unflexibel ist. Wenn ich im Büro sitze und mal eben schnell etwas in meiner privaten Taskliste nachschauen möchte, muss ich den Context von work nach private wechseln, dann mein Kommando ausführen, um dann wieder von private zurück nach work zu wechseln. Das ist gelegentlich in Ordnung, macht man das aber häufiger, wird es schnell nervig.

Auf der Suche nach einer Lösung für dieses Komfortproblem wurde ich auf der Taskwarrior-Mailingliste in eine Richtung geschubst, die ich gar nicht auf dem Schirm hatte. Dirk Deimke schlug vor, diese Context Peeking mit Hilfe eines Shell-Scripts zu lösen. Nun bin ich mit meinen gut drei Jahren Linux-Erfahrung ja noch eher ein Linux-Kindergartenkind, daher bin ich selbst gar nicht auf diese Idee gekommen, aber wie das mit Kindergartenkindern so ist, fangen sie sofort an zu spielen, wenn man ihnen ein neues Spielzeug gibt. So habe ich es auch gemacht.

Das resultierende Shell-Script sieht nun so aus:

# Make task work with contexts like I want it to
task () {
  # get the task binary to avoid recurrence
  tb=`which task`
  # extract the selected context by matching the regex
  # context has to be the first argument and consist only
  # of alphanumeric characters
  context=`echo $1 | egrep -o "(=)[[:alnum:]]*"`
  # check whether there was a = character
  if [ -n "$context" ]
  then
    # remove the = char
    context=`echo $context | cut -c 2-`
    # check whether a context name was given
    if [ -n "$context" ]
    then
      # name given, temporarily set this context
      $tb rc.context:$context "${@:2}"
    else
      # no name given, temporarily set no context
      $tb rc.context:none "${@:2}"
    fi
  else
    # no = char, so just call task with all arguments
    $tb "${@}"
  fi
}

Was macht das Script nun? Zum einen habe ich die Möglichkeit, beim einem Aufruf von Taskwarrior einen bestimmten Context vorzugeben. Dazu nutze ich die Syntax =Context. Will ich also auf der Arbeit kurz in meine private Liste schauen, verwende ich den Aufruf task =private list.

Zusätzlich zur Wahl eines bestimmten Contexts kann ich allerdings auch das Context-Feature temporär ausschalten. Dazu verwende ich =ohne Contextnamen. Der Aufruf task = list zeigt mir somit alle Tasks, unabhängig ihres Contexts, an.

Bisher hat mir dieses simple Script schon viele gute Dienste geleistet. Und außerdem hat es mir wieder einen weiteren Teil der Linux-/Unix-Welt nähergebracht.