TWC - TaskWarrior controller - interactive command-line task and todo manager.

1. Installation

First, make sure that TaskWarrior is installed on your system. TaskWarrior is packaged for most of Linux distributions. Please refer to TaskWarrior’s documentation for details. Typically you can install Taskwarrior with one of the following commands:

$ sudo apt install taskwarrior  # Debian, Ubuntu, Termux, Windows 10 WSL
$ pacman -S task  # Archlinux
$ yum install task  # Fedora

Next you should obtain TWC with one of the methods described below. After TWC is installed it can be run by typing twc in your console.

1.1. From PyPI

TWC is distributed via PyPI. It is recommended to use a tool like pipsi to handle installations from PyPI, because it offers isolation of installed applications and an easy way to uninstall them together with their dependencies.

$ pipsi install --python python3 twc

You can also use bare PIP:

$ pip3 install --user twc

1.2. From Git

You can also manually download, build and install TWC:

$ git clone https://gitlab.com/mgoral/twc
$ cd twc
$ python3 setup.py install

setup.py accepts several options to e.g. change install destination. You can read about them by running python3 setup.py install --help.

If you only want to check TWC, you can use pipenv to install it in local virtualenv (outside of PATH). To install and run TWC this way replace setup.py command from above with:

$ pipenv install
$ pipenv run twc

2. Configuration

During startup TWC reads a configuration file that commonly contains various settings: definitions of agendas, key bindings, program options etc. Typically it is kept in user’s configuration directory: ~/.config/twc/config.py, but TWC follows ther rules of XDG Base Directory Specification:

  1. $XDG_CONFIG_HOME/twc/config.py is checked. If $XDG_CONFIG_HOME is not set, it defaults to $HOME/.config.

  2. any of $XDG_DATA_DIRS/twc/config.py is checked. $XDG_DATA_DIRS is a colon-separated list of directories to check. If it is not set, it defaults to a single directory: /etc/xdg.

Some options can be configured with specific program arguments. They are usually named the same as their config.py counterparts and they take precedence over settings from configuration file.

TWC’s configuration file is ordinary Python file. It comes with exposed variable c which should be used to configure all aspects of TWC and it contains all necessary methods to do so.

Example config.py
displayed_items = 'priority:warning:,description,[flags:comment:%a:],id:comment:,tags:info:

c.set('incsearch', False)
c.set('taskrc', '~/other_taskrc')

# visible comments
c.set_style('comment', 'fg:lightblue bold')

c.add_block(
    agenda='Next tasks',
    title='Tasks with tags',
    filter='-WAITING -BLOCKING -BLOCKED +PENDING (+tag1 or +tag2)',
    items=displayed_items,
    sort='urgency-,priority')

c.add_block(
    agenda='Next tasks',
    title='Inbox',
    filter='( status:pending tags.is: )',
    items=displayed_items)

2.1. Agendas

Agendas are built from blocks. Each block specifies methods of retrieving tasks from TaskWarrior and presenting them in TWC. These include, but are not limited to filter used to retrieve tasks, tasks' sorting method and tasks formatting.

Agendas are automatically created when blocks are defined. This is all done with c.add_block() function, which requires specifying parent agenda of block.

Apart from agenda, all parameters passed to c.add_block() must be named, i.e. given in form of name=value, like: sort='urgency', limit=5 etc.

2.2. Formatting

Block’s items and statusleft and statusright parameters are composed of lists of displayed items; they can be separated by comma, which produces space between items, or by "+" sign, which concatenates items to each other without leaving space between them.

Each item can optionally be followed by a name of style which will be applied to it and item-specific string formatting. When style of formatting are added, they must be separated and ended by a colon ":".

formatting = 'item_name:style:item_fmt:'
many_items = 'item1,item2+item3

Items are displayed only when they are present (not empty). For example if there are no tags defined for a specific task, tags item will not produce any output.

Items might contain additional characters in place of their names. TWC recognizes item name in this case. These characters are not independent however: they will also be printed only when item is present. They can be used e.g. to visually delimit some items from the others (e.g. by surrounding tags with braces).

You can use any TaskWarrior’s attribute name (including UDAs).

Some examples:

items = '[priority:warning:],due:info:%Y-%m-%d:,description,id:comment:'
items = 'id+[flags::%a],description:info:,customuda:comment:'
For some types TWC returns pre-formatted strings. For example, all lists (like list of tags or annotations) will have their elements separated by a colon.

Agenda Block Items

The following items are available inside block (by calling c.add_block(items="…​")):

  • any TaskWarrior’s attribute name (including UDAs)

  • flags - list of flags/indicators of presence of certain attributes which normally might be not disired to be displayed in full (like long annotations)

Status Line Items

  • task.<attr> - any TaskWarrior’s attribute name, but they must be preceded by task. string

  • flags - list of flags/indicators of presence of certain task attributes

  • taskrc - path of currently used taskrc

  • command - name of current command, when command line is active (e.g. add, modify, annotate,…​)

  • COMMAND - same as before, but command is UPPER CASED

  • task.<attribute> - any attribute of currently highlighted task

  • agenda.pos - position of highlighted item

  • agenda.size - size of current agenda

  • agenda.ppos - percentage position of highlighted item

Items Formatting

  • all ordinary types can be formatted by using Python’s Format Specification Mini-Language

  • date/times (due, scheduled attributes) can be formatted with ordinary strftime-like formatting, for example %Y-%m-%d %H:%M.

  • flags accepts any combination of the following strings, for example %a%d:

    • %a: annotations indicator

    • %d: due indicator

    • %s: scheduled indicator

    • %t: tags indicator

2.3. Key Bindings

You can modify any key binding available in TWC with two functions: c.bind() and c.unbind(). Unbinding is particularily useful if you want to disable a default key, because TWC will unbind automatically keys when re-binding them to a different command.

TWC supports key sequences: executing commands by pressing some keys following the others (similar to e.g. Vim). For example, to jump to the first task in agenda you can double press "g". In configuration this should be set as g g (2 "g" letters separated by space).

Key prefixes are supported:

  • c- for combinations with ctrl (e.g. c-f, meaning Ctrl+f)

  • a- for combinations with alt (e.g. a-space, meaning Atl+Space)

  • s- for combinations with shift (e.g. s-tab, meaning Shift+Tab)

Due to how most terminals work, when you want to bind a command to "shift+letter", you’ll usually simply write upper-case letter, like A instead of Shift+a.

There are 2 sets of default key bindings enabled: ordinary ones (arrows used for navigation, used shortcuts are common in most of popular applications like text editors) and Vim-style (bindings familiar to Vim users).

Global Commads

activate

Performs action on currently focused item: opens task details, accepts typed command etc.

Default bindings: Enter.

cancel

Cancels current action, e.g. cancels current command. On agenda view clears prompt and selections.

Default bindings: Esc.

quit

Closes current screen (e.g. task details), eventually exitting TWC. This command is inactive when typing a command.

Default bindings: Q, q, Ctrl+c.

followurl

Searches currently selected task (either in agenda or in detailed view) for URL patterns. If any URL is found, it will be opened in a browser configured in user’s operating system. If more than one URLs are found, opens a new window which allows selecting which URLs should be opened.

Default bindings: f.

help

Displays built-in short help reference.

Default bindings: F1.

Navigation

scroll.down

Scrolls down current view, e.g. by selecting next task on agenda view or scrolling a screen on task details view.

Default bindings: Down, j.

scroll.up

Same as scroll.down, but backwards.

Default bindings: Up, k.

scroll.nextsection

Jumps to the beginning of next visual section, e.g. next block in current agenda.

Default bindings: Page Down, ].

scroll.prevsection

Jumps to the beginning of previous visual section, e.g. block in current agenda.

Default bindings: Page Up, [.

scroll.begin

Jumps to the first task in current agenda.

Default bindings: Home, gg.

scroll.end

Jumps to the last task in current agenda.

Default bindings: End, G.

tab.next

Opens next agenda (the one to the right).

Default bindings: Tab.

tab.prev

Opens previous agenda (the one to the left).

Default bindings: Shift+Tab.

search

Starts new search of tasks in current agenda.

Default bindings: Ctrl+f, /.

search.forward

Finds next occurence of currently searched term. Defa

ult bindings: n.

search.backward

Finds previous occurence of currently searched term.

Default bindings: N.

Task Commands

task.add

Opens a command line which accepts a new task’s description and parameters. They will be directly passed to TaskWarrior, so its syntax can be used, e.g.

> Task description +tag due:someday

You can use tab- and auto-completion. Press Tab to see a list of completions available.

Default bindings: a.

task.add.subtask

Adds a new task the same way as task.add, but additionally sets a dependency to it in a currently highlighted task. Tasks added this way are considered sub-tasks and task which depend on them are their parents.

Default bindings: t.

task.modify

Opens a command line which accepts a modification command:

> -tag1 -tag2 due:

Tab- and auto-completion are available.

Default bindings: m.

task.edit

Runs task edit which edits task in a text editor. This is not the recommended method of modifying tasks, but is provided for exceptional circumstances.

Default bindings: e.

task.annotate

Opens a command line which accepts a new annotation which will be added to currently focused task.

Default bindings: A.

task.denotate

Opens a command line which accepts any of existing annotations. Typed annotation will be removed. Annotation must be typed exactly the same as it’s present inside task. Tab- and auto completion are available: they will complete full annotations.

Default bindings: D.

task.toggle

Mark focused task’s status as done if it is currently pending. Otherwise mark it as pending.

Default bindings: Alt-Space

task.delete

Delete focused task. Keep in mind that TaskWarrior doesn’t really delete tasks, but merely marks them with deleted status and removes them from most reports. You can still access them by their UUID.

Default bindings: Delete.

task.undo

Reverts the most recent action. This command uses task undo underneath.

Default bindings: u.

task.synchornize

Synchronizes tasks with a task server. Task server must be correctly configured in taskrc.

Default bindings: S.

task.select

Toggles selection for current task. You can bulk-edit multiple selected tasks, for example by adding/removing tags for all of them.

Default bindings: Space.

refresh

Refreshes the view. Useful after some modifications which by design don’t automatically refresh agenda (like sync).

Default bindings: R.

2.4. Settings

Many different settings can be changed with c.set() function. Below is alphabetical list of all available TWC settings.

agenda

Agenda to start TWC with. If it’s not set (default), first defined agenda will be used.

autocomplete

Enable commands autocompletion instead of tab completion.

Default: False.

autohelp

Shows various help texts, hints and tooltips. For example, command line will initially display additional visual feedback about current action.

Default: True.

deffilter

Default filter used for all blocks. Useful when you don’t want to repeat some

obvious filter over and over again. Default: "-DELETED -PARENT"

incsearch

Enable incremental search (search-when-typing).

Default: True

ignorecase

Disable case sensitive search.

Default: True

smartcase

Override 'ignorecase' when search string contains upper case characters. Only used when 'ignorecase' is on (that’s how it works in Vim). It results in case-sensitive search when search string contains upper case characters and case-insensitive when it contains only lower case characters.

Default: True.

statusleft
statusright

Formattings of status lines. statusleft contains elements aligned to the left and statusright - to the right. Status line is disabled when both of these settings are disabled (set to empty strings). See Formatting section for details about formatting strings.

taskrc

Path to used taskrc file.

Default: ~/.taskrc.

timeoutlen

Time in milliseconds that is waited for a mapped sequence to complete. For example, if "a b" sequence is mapped, TWC will wait for "b" after "a" was first pressed for number milliseconds equal to timeoutlen. If this time passes, it the whole key sequence is cancelled. This is similar to Vim setting with the same name.

Default: 1000.

ttimeoutlen

Time in milliseconds that is waited for a key code sequence to complete. It’s important to distinguish escape key from other keys that start with escape sequence (x1B, e.g. c-[). This s similar to Vim setting with the same name.

Default: 50.

2.5. Styles

With c.set_style() you can create new styles which can be used to change appearence of tasks and status line. Style is a mix of foregound and background colors as well as some flags describing text formatting (like bold, italics).

Table 1. Style examples
Style Description

fg:white

white foreground, color is named

bg:#000000

black background, hexadecimal notation

bg:ansiblue

ANSI color palette

bold italic underline blink reverse hidden

all supported style flags

nobold noitalic nounderline noblink noreverse nohidden

reverse flags

Predefined styles are: heading, text, comment, info, warning, error, highlight, mark, tabline, tabsel, tab, tooltip, statusline, status.1, status.2. Some of them are used for styling specific elements of program interface.

Such styles can be used e.g. to change appearence of tasks or status line.

Example style usage
c.set_style('mystyle', 'fg:#EEEEEE bg:black bold')

c.set('statusright', 'task.id:mystyle:')
c.add_block(..., items='description:mystyle:')

2.6. Configuration Reference

c.add_block(agenda, *, title, items='description', filter=None, sort=None, limit=None)

Adds a new block to a given agenda, which will be created if it doesn’t exist.

Block contains a title which is displayed above all of its tasks. Block titles are automatically styled with heading style.

Task formatting is described by items string (see Formatting section for details). By default only raw task description is displayed.

+ When given, sort parameter decides order of tasks inside block. It is compatible with TaskWarrior’s reports sorting. It iss defined by a comma-separated list of task attributes. Each of attributes can be additionally post-fixed by a "+" or "-" sign for ascending and descending order. For example:

+

sort='project+,urgency-,priority'

+ TaskWarrior’s listing breaks (e.g. project+/,description+) are not supported.

+ Maximum number of tasks displayed in block can be limited by a limit. This is applied after sorting. By default number of tasks is not limited.

+ .Example

c.add_block(
    agenda="My Agenda",
    title="All tasks",
    items='id,description',
    limit=20)
c.bind(key, command)
c.unbind(key)

These functions allow binding and unbinding keys in config.py. Keys are automatically re-bound (unbound and bound) when c.bind() is called with a previously used key and new command.

For a list and description of TWC commands see Key Bindings section.

Example
# binds a key sequence
c.bind('space t a', 'add-task')

# unbinds default undo
c.unbind('u')
c.set(setting, value)

Changes a program option named setting to the given value. See Settings section for a list and description of available settings.

Example
c.set('statusleft', 'COMMAND,task.id')
c.set('ignorecase', False)
c.set_style(name, style)

Sets a new style or changes the existing one. Styles are used to change appearence of tasks, status line and certain interface elements.

Function accepts name of a stype and style definition. See Styles section for details.

Example
c.set_style('heading', 'fg:#EEEEEE bg:black bold')

3. Program options

TWC can be invoked with additional arguments which modify its initial state and behavior. The following options are available:

-a, --agenda=AGENDA

Selects agenda which should be initially displayed when TWC starts. This option exects full agenda name and is case-sensitive. If agenda’s name contains spaces or other special characters, it can be e.g. enclosed in single or double quotes (see your shell manual for informations about escaping special characters:

twc --agenda="Next tasks"

Setting this option overrides agenda setting from configuration file.

-t, --taskrc=TASKRC

Path to taskrc which should be the source of TaskWarrior configuration used by TWC. This file should contain for example configuration of taskd (synchronization server) or UDAs. By default ~/.taskrc is used. See also taskrc(5).

Setting this option overrides taskrc setting from configuration file.

--debug

Enables additional features useful for debugging, like printing full tracebacks for exceptions.

--version

Shows TWC’s version number and then exits.

-h, --help

Displays a help message with short summary of available options and then exits.

Appendix A: Termux

TWC works on Termux, although there’s currently a bug in tzlocal - a library indirectly used by TWC to get local timezone information.

Before running TWC on Termux you have to export the following environment variable:

export TZ=$(getprop persist.sys.timezone)

Termux emulates scroll events as key presses. You can bind them for easier navigation:

c.bind('right', 'next-agenda')
c.bind('left', 'prev-agenda')

Appendix B: License

Copyright © 2019 Michał Góral.

TWC is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

TWC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with TWC. If not, see http://www.gnu.org/licenses/.