rdial
¶
rdial
is a simple way to track the time you spend on tasks. It tracks the
name of a task, its start time, its duration and optionally a message… nothing
more.
It is written in Python, and requires v3.6 or later. rdial
is released
under the GPL v3.
- Git repository
- Issue tracker
- Contributors
Contents¶
Background¶
I spend an awful lot of time sitting in front of a computer, working on many disparate projects. When I need to gauge my time it would be great if I could just fire up a simple tool to see where I’ve been spending my time.
The features I need in a time tracking tool are:
Easily accessible data, in a format that can be processed simply
Ability to work off-line, because those times are considerably more common than some people seem to think
Works on all the platforms I regularly use; desktop, mobile phone, ZipIt, and more
Now rdial
is born, and I can realise those dreams!
Philosophy¶
A few interface choices in rdial may be need a little explanation. Any one of them may well be enough to deter you from using rdial at all, but that is fine as other options are out there!
Explicit new tasks¶
It is an error to try to start a task that doesn’t already exist in the database
If you wish to create a new task you must give the rdial start
--new
option when starting the task. This should — with hope — catch typos
and task name “thinkos”, and it has proven to do exactly that for me.
Switch vs “stopstart”¶
It is an error to try to start a task when another is running, or switch a task when no task is running
If you wish to start a new task you must stop the previous task. At first it seems natural to just accept that rdial start should complete the previous task, but doing so encourages users to not be aware of their current state.
Similarly, if you wish to switch to a new task then a task must be running. It might be convenient to make rdial switch just start the new task if a task is not running, but again it encourages users to be unaware of their current state.
Usage¶
rdial¶
Minimal time tracking for maximal benefit.
rdial [OPTIONS] COMMAND [ARGS]...
Options
-
--version
¶
Show the version and exit.
-
-v
,
--verbosity
<verbosity>
¶ Set verbosity level.
-
-d
,
--directory
<directory>
¶ Directory to read/write to.
-
--backup
,
--no-backup
¶
Do not write data file backups.
-
--cache
,
--no-cache
¶
Do not write cache files.
-
--config
<config>
¶ File to read configuration data from.
-
-i
,
--interactive
,
--no-interactive
¶
Support interactive message editing.
-
--colour
,
--no-colour
¶
Output colourised informational text.
Environment variables
-
RDIAL_COLOUR
Provide a default for
--colour
fsck¶
Check storage consistency.
rdial fsck [OPTIONS]
Options
-
-p
,
--progress
,
-q
,
--no-progress
¶
Display progress bar.
ledger¶
Generate ledger compatible data file.
rdial ledger [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-d
,
--duration
<duration>
¶ Filter events for specified time period.
- Options
day|week|month|year|all
-
-r
,
--rate
<rate>
¶ Hourly rate for task output.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
-
RDIAL_RATE
Provide a default for
-r
report¶
Report time tracking data.
rdial report [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
--stats
¶
Display database statistics.
-
-d
,
--duration
<duration>
¶ Filter events for specified time period.
- Options
day|week|month|year|all
-
-s
,
--sort
<sort>
¶ Field to sort by.
- Options
task|time
-
-r
,
--reverse
,
--no-reverse
¶
Reverse sort order.
-
--style
<style>
¶ Table output style.
- Options
simple|plain|grid|fancy_grid|github|pipe|orgtbl|jira|presto|psql|rst|mediawiki|moinmoin|youtrack|html|latex|latex_raw|latex_booktabs|tsv|textile
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
-
RDIAL_SORT
Provide a default for
-s
-
RDIAL_REVERSE
Provide a default for
-r
run¶
Run command with timer.
rdial run [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-n
,
--new
¶
Start a new task.
-
-t
,
--time
<time>
¶ Set start time.
-
-F
,
--file
<fname>
¶ Read closing message from file.
-
-m
,
--message
<message>
¶ Closing message.
-
-c
,
--command
<command>
¶ Command to run.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
start¶
Start task.
rdial start [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-c
,
--continue
¶
Restart previous task.
-
-n
,
--new
¶
Start a new task.
-
-t
,
--time
<time>
¶ Set start time.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
stop¶
Stop task.
rdial stop [OPTIONS]
Options
-
-F
,
--file
<fname>
¶ Read closing message from file.
-
-m
,
--message
<message>
¶ Closing message.
-
--amend
¶
Amend previous stop entry.
switch¶
Complete last task and start new one.
rdial switch [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-n
,
--new
¶
Start a new task.
-
-t
,
--time
<time>
¶ Set start time.
-
-F
,
--file
<fname>
¶ Read closing message from file.
-
-m
,
--message
<message>
¶ Closing message.
-
--amend
¶
Amend previous stop entry.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
timeclock¶
Generate ledger compatible timeclock file.
rdial timeclock [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-d
,
--duration
<duration>
¶ Filter events for specified time period.
- Options
day|week|month|year|all
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
Getting started¶
Basic usage¶
The command interface is — I hope — quite intuitive. The following is a sample session:
$ rdial start my_task
$ rdial running
Task my_task has been running for 0:12:38
$ rdial stop -m'Fixed bug #40'
Task my_task running for 0:44:00
Help on individual subcommands is available via rdial <subcommand> --help
or
in the usage document.
Current task¶
The current task name is written to the database directory in the
.current
file. You could, for example, use its contents to populate
notifiers in task bars.
As the file is created when the user executes rdial start you can also use its modification time to quickly calculate a running time for the task.
See the taskbar integration document for some guidance on using rdial in various environments.
- Manual section
1
- Manual group
user
rdial¶
Minimal time tracking for maximal benefit¶
SYNOPSIS¶
rdial [option]… <command>
DESCRIPTION¶
rdial
is a simple way to track the time you spend on tasks. It tracks
the name of a task, its start time, its duration and optionally a message…
nothing more.
OPTIONS¶
-
--version
¶
Show the version and exit.
-
-d
<directory>
,
--directory
=<directory>
¶ Database location, defaults to
${XDG_DATA_HOME:-~/.local/share}/rdial
.
-
--backup
,
--no-backup
¶
Write data file backups.
-
--cache
,
--no-cache
¶
Do not write cache files.
-
--config
<file>
¶ File to read configuration data from, defaults to
${XDG_CONFIG_HOME:-~/.config}/rdial/config
.
-
-i
,
--interactive
,
--no-interactive
¶
Support interactive message editing.
-
--colour
,
--no-colour
¶
Output colourised informational text.
-
--help
¶
Show help message and exit.
COMMANDS¶
rdial fsck¶
Check storage consistency.
rdial fsck [OPTIONS]
Options
-
-p
,
--progress
,
-q
,
--no-progress
¶
Display progress bar.
rdial start¶
Start task.
rdial start [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-c
,
--continue
¶
Restart previous task.
-
-n
,
--new
¶
Start a new task.
-
-t
,
--time
<time>
¶ Set start time.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
rdial stop¶
Stop task.
rdial stop [OPTIONS]
Options
-
-F
,
--file
<fname>
¶ Read closing message from file.
-
-m
,
--message
<message>
¶ Closing message.
-
--amend
¶
Amend previous stop entry.
rdial switch¶
Complete last task and start new one.
rdial switch [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-n
,
--new
¶
Start a new task.
-
-t
,
--time
<time>
¶ Set start time.
-
-F
,
--file
<fname>
¶ Read closing message from file.
-
-m
,
--message
<message>
¶ Closing message.
-
--amend
¶
Amend previous stop entry.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
rdial run¶
Run command with timer.
rdial run [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-n
,
--new
¶
Start a new task.
-
-t
,
--time
<time>
¶ Set start time.
-
-F
,
--file
<fname>
¶ Read closing message from file.
-
-m
,
--message
<message>
¶ Closing message.
-
-c
,
--command
<command>
¶ Command to run.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
rdial wrapper¶
Run predefined command with timer.
rdial wrapper [OPTIONS] [WRAPPER]
Options
-
-t
,
--time
<time>
¶ Set start time.
-
-F
,
--file
<fname>
¶ Read closing message from file.
-
-m
,
--message
<message>
¶ Closing message.
Arguments
-
WRAPPER
¶
Optional argument
rdial report¶
Report time tracking data.
rdial report [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
--stats
¶
Display database statistics.
-
-d
,
--duration
<duration>
¶ Filter events for specified time period.
- Options
day|week|month|year|all
-
-s
,
--sort
<sort>
¶ Field to sort by.
- Options
task|time
-
-r
,
--reverse
,
--no-reverse
¶
Reverse sort order.
-
--style
<style>
¶ Table output style.
- Options
simple|plain|grid|fancy_grid|github|pipe|orgtbl|jira|presto|psql|rst|mediawiki|moinmoin|youtrack|html|latex|latex_raw|latex_booktabs|tsv|textile
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
-
RDIAL_SORT
Provide a default for
-s
-
RDIAL_REVERSE
Provide a default for
-r
rdial ledger¶
Generate ledger compatible data file.
rdial ledger [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-d
,
--duration
<duration>
¶ Filter events for specified time period.
- Options
day|week|month|year|all
-
-r
,
--rate
<rate>
¶ Hourly rate for task output.
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
-
RDIAL_RATE
Provide a default for
-r
rdial timeclock¶
Generate ledger compatible timeclock file.
rdial timeclock [OPTIONS] [TASK]
Options
-
-x
,
--from-dir
¶
Use directory name as task name.
-
-d
,
--duration
<duration>
¶ Filter events for specified time period.
- Options
day|week|month|year|all
Arguments
-
TASK
¶
Optional argument
Environment variables
-
RDIAL_TASK
Provide a default for
TASK
BUGS¶
None known.
AUTHOR¶
Written by James Rowe
RESOURCES¶
Full documentation: https://rdial.readthedocs.io/
Issue tracker: https://github.com/JNRowe/rdial/issues/
COPYING¶
Copyright © 2011-2019 James Rowe.
rdial 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.
rdial 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 rdial. If not, see <http://www.gnu.org/licenses/>.
Configuration¶
rdial can be configured using a cascading series of files, processed in the following order:
The package’s
rdial/config
file which contains the base configurationAny
rdial/config
file that exists inXDG_CONFIG_DIRS
The user’s
rdial/config
file found inXDG_CONFIG_HOME
The
.rdialrc
found in the current directory
Note
See the XDG base directory specification for more information on
using XDG_CONFIG_DIRS
and XDG_CONFIG_HOME
.
File format¶
The configuration file is a INI
format file. Use a section labelled
rdial
for global options, and a separate section for each subcommand. Each
section consists of a series of name=value
option pairs.
An example configuration file is below:
[rdial]
colour = False
[report]
sort = time
reverse = True
The configuration files are processed using configparser
, and you can
make use of all the features it provides(such as interpolation).
rdial
section¶
backup
(default: True
)¶
If this key is set to True
then backup data files are written with a ~
suffix.
Warning
You are strongly urged to keep this set to True
, as it helps to protect
you from bugs in rdial
.
colour
(default: True
)¶
If this key is set to False
then no coloured output will be produced by
rdial
.
The key color
is also accepted.
directory
(default: $XDG_DATA_HOME/rdial
)¶
This key sets the location of your data files. Some users use this, combined with the per-directory config file, to keep per-project task databases.
interactive
(default: False
)¶
If this key is set to True
then rdial
will interactively ask the user
for for messages if they’re not supplied as arguments.
run wrappers
section¶
This section is used to configure pre-defined arguments for the rdial run subcommand. It consists of a series of string keys to use as the wrapper title, and arguments to the rdial run subcommand as values. For example:
[run wrappers]
feeds = -c 'mutt -f ~/Mail/RSS2email/' procrast
calendar = -c 'wyrd ~/.reminders/events' calendar
The above configuration entry feeds
allows us to use rdial wrapper
feeds
to open mutt
in a specific mailbox, and time our usage under the
ever popular procrast
-ination task.
Configuration via environment variables¶
rdial defaults for many options can be configured via environment variables. The design purpose for supporting these environment variables is to make it easy for users to configure per-project defaults using shell hooks.
-
RDIAL_BACKUP
¶ This controls whether rdial creates backup of data files. It must be a boolean setting that accepts
false
/true
,0
/1
orn
/y
as its value.
-
RDIAL_CACHE
¶ This controls whether rdial creates a cache for data files. It must be a boolean setting that accepts
false
/true
,0
/1
orn
/y
as its value.
-
RDIAL_COLOUR
¶ This controls whether rdial displays informational messages in colour. It must be a boolean setting that accepts
false
/true
,0
/1
orn
/y
as its value.
-
RDIAL_CONFIG
¶ The location of the configuration file. It must be a string value.
-
RDIAL_DIRECTORY
¶ The location of the rdial storage directory. It must be a string value.
-
RDIAL_INTERACTIVE
¶ This controls whether rdial asks for messages interactively if they’re not provided as arguments. It must be a boolean setting that accepts
false
/true
,0
/1
orn
/y
as its value.
-
RDIAL_PROFILE
¶ This controls whether to profile the execution of rdial. It must be a string value, and will be used as the profile’s output filename.
-
RDIAL_RATE
¶ The value for the
rdial ledger -r
hourly rate setting. It must be a numeric value.
-
RDIAL_REVERSE
¶ This controls whether rdial report inverts the sort order when displaying reports. It is a boolean setting that accepts
false
/true
,0
/1
orn
/y
as its value.
-
RDIAL_SORT
¶ This controls the sorting order for output generated by rdial report. It can either
task
ortime
to sort by task name or cumulative time respectively.
-
RDIAL_TASK
¶ This controls the default task name for rdial, and is a good way to configure a project default within a shell hook. It must be a string value.
-
XDG_CONFIG_DIRS
¶ Stacked location of directories storing configuration files, see the XDG base directory specification for more information.
-
XDG_CONFIG_HOME
¶ Path to configuration files as given by the user, if unset use the default value of
$HOME/.config
. See the XDG base directory specification for more information.
Frequently Asked Questions¶
Why must I specify --new
when creating a new task?¶
Perhaps you’re super special and never produce a typo, I’m not. The
rdial start --new
option is a fix for this common — to me — problem.
The rdial switch command is of related design. You can not use it when no task is running, and attempting to do so is probably a sign you’ve lost track of your state. I consider this to be a massive problem, and would rather not sidestep it by allowing rdial start to stop running tasks or rdial switch to work without a running task.
Where does the name rdial come from?¶
Around the beginning of 2012 I wrote a very simple shell script to track my time, and at some point I decided it should be safer and cleaner. I came up with an exceedingly clever and imaginative name for this new project, and then promptly forgot how it came about.
Since then I haven’t even managed to come up with a useful backronym for it.
How do I process rdial data files using go
?¶
If you keep receiving ErrTrailingComma
errors when reading files using
golang it is because you are processing files with empty message fields. The
default behaviour of the encoding/csv
pkg is to raise an error when it
encounters an empty final field. You can tell go
to accept empty final
fields by setting the TrailingComma
attribute on your CSV reader.
reader := csv.NewReader(file)
reader.TrailingComma = true
Integrating with taskbars¶
The following sections should give you some idea of how you can (ab)use the
<database>/.current
file in your window manager of choice.
Note
You’ll find exactly two examples right now, because these are the only two environments I use. Feel free to submit your own!
Todo
Add more fleshed out examples.
awesomewm
¶
For example, with awesomewm, you could create a simple timer based widget that shows the running task:
GLib = lgi.GLib
tasktext = wibox.widget.textbox!
tasktimer = with gears.timer timeout: 30
\connect_signal "timeout", ->
if file = io.open GLib.get_user_data_dir! .. "/rdial/.current"
tasktext\set_markup file\read!
file\close!
else
tasktext\set_markup "none"
-- fire timer for initial update
\emit_signal "timeout"
\start!
Note
The above example is compact but very naïve, and will be incorrect in the time between state changes and updates. If you’re implementing your own widget you’ll be better served by using GFileMonitor to track state changes.
You could also hook the mouse::enter
and mouse::leave
signals to create
a naughty popup showing the task time, or use awful.button to allow you to
switch tasks directly from the taskbar.
dwm
¶
With dwm you’re basically free to pump the status bar however you wish. If
you’re one of the users who likes to use a shell script to configure the bar,
then you can just cat the .current
file from within your
script.
You could also edge towards mimicking the awesomewm configuration above with the following genie snippet leveraging glib:
[indent=4]
uses
X
Posix
init
var file = GLib.Environment.get_user_data_dir() + "/rdial/.current"
var dpy = new X.Display()
var root = dpy.default_root_window()
text : string
while true
if GLib.FileUtils.test(file, GLib.FileTest.IS_REGULAR)
GLib.FileUtils.get_contents(file, out text)
else
text = "none"
dpy->change_property(root, XA_WM_NAME, XA_STRING, 8,
PropMode.Replace, (array of uchar)text,
text.length)
dpy->flush()
Posix.sleep(30)
Note
The above example is compact but very naïve, and will be incorrect in the time between state changes and updates. If you’re implementing your own status tool you’ll be better served by using GFileMonitor to track state changes.
You could also implement a simple task manager using dmenu or rofi to bind to a key, the following zsh snippet shows how to build a selector for an existing task:
tasks=(${XDG_DATA_HOME:-~/.local/share}/rdial/*~*~(:t:s/.csv/))
rofi -dmenu -p "task?" <<< ${(F)tasks}
Alternatives¶
Before diving in and spitting out this package I looked at the alternatives below. If I have missed something please drop me a mail.
It isn’t meant to be unbiased, and you should try the packages out for yourself. I keep it here mainly as a reference for myself, and maybe to help out people who are already familiar with one of the entries below.
Todo
Check for recent additions to the arena.
arbtt
¶
The “Automatic Rule-Based Time Tracker”, where automatic could equally be awesome. You run the daemon and it records yours tasks automatically. The rules to configure switching are easy to write, and depending on your needs may well catch all your task switching.
It only falls down when you need to record tasks which aren’t 100% about whacking away at the keyboard in a window, so if your time tracking needs are entirely screen based I recommend you try it out.
gtimelog
¶
gtimelog
is an interesting tool, and ticks many of the boxes for me. The
ideas are quite well thought out, and the interface is simple to use. I’m sure
it’s great for people with strictly structured working days, but that
definitely isn’t me.
As a side note, when we were playing with it at the office several of my
co-workers stumbled across various bugs that dogged its usage. Unfortunately,
the project is developed with bzr and launchpad, therefore it was simply
abandoned in favour of trying to fix it. Most moved on to org-mode
, and
some to rdial
.
hammertime
¶
hammertime is a great tool for tracking time in a simple manner, however it has a couple of drawbacks for my use case.
First, it stores data in a git
branch which means all projects need their
own git
repository. This works surprisingly well for the most part, but
makes fetching all the stored data across multiple projects quite cumbersome.
The more significant problem for me is that the implementation works by
stashing changes and switching branches, which will cause annoying rebuilds
every time you call git time
if you’re using a time based build tool like
make. However, this could fixed by using git hash-object
directly for storing updates and git cat-file
for reading data, should
anyone be interested in working on it.
I still happily recommend it to people who are simply trying to log the time spent working on small projects.
hamster-time-tracker
¶
ProjectHamster and its associated clients are a neat solution to time tracking. The gnome applet and command line interface are particularly polished. The hamster-cli in particular is extremely nice to use, and the built-in DWIM date handling provides some great shortcuts for adding missing entries.
The data backend is a simple SQLite database, and is therefore very amenable to external processing. It provides tagging on top of the fields provided by rdial, and that alone may make it more useful to you.
ktimetracker
¶
Works well, but isn’t available on most of the platforms I care about. If KDE is available everywhere you care about, I’d heartily recommend it.
org-mode
¶
org-mode includes fantastic time tracking support, and some excellent reporting
mechanisms. You can interleave your time tracking with other data, maintain
hierarchies of projects with their own time tracking data and take advantage of
all the other features org-mode
has to offer.
If I had a copy of emacs available everywhere I wanted to log time data I wouldn’t even consider using anything else. And if you use emacs then you shouldn’t either!
taskwarrior
¶
taskwarrior has some support for time tracking, and if you only need to maintain a log of the time you spend on previously defined tasks it is probably enough to get by.
I still take advantage of its functionality now, in combination with rdial
,
so that I can see when I started working toward a task in my to-do list.
timewarrior
¶
From the same stable as taskwarrior, timewarrior is an excellent solution for time tracking. It doesn’t support close messages, but it does have amazing tag support and some really useful query options.
There are import and export scripts in the extra
subdirectory, and I truly
recommend trying timewarrior out.
The only possible drawback is its speed, as with large numbers of records its startup becomes very slow. Exporting my eight year rdial database results in three second pauses on each timew run.
What is the future for rdial
?¶
Where things stand now:
$ time ./rdial.py --no-cache report --stats
65726 events in query
Duration of events 780 days, 14:04:22
First entry started at 2011-12-15 14:02:13
Last entry started at 2019-05-27 19:55:13.803240
Events exist on 2659 dates
Task “rdial” started 2019-05-27T19:55:13.803240Z
./rdial.py --no-cache report --stats 0.55s user 0.05s system 92% cpu 0.649 total
I’m clearly an extensive rdial
user, and my inbox tells me that there
are fair number of other — hopefully happy — users too. There are no plans
to stop working on it, but there are some thoughts about where it could go.
Data storage¶
The output above is fairly representative of the speed of rdial for me 1. All non-interactive commands run in well under three quarters of a second, and with the cache enabled the commands run within half a second. Performance should be better, but I find it to be within acceptable bounds.
One of the original goals of rdial
was “easily
accessible data, in a format that can be processed simply”. The CSV-backed
storage is easy to work with, and performance is acceptable. However, I’m more
than a little tempted to replace it with a sqlite-backed solution because:
sqlite
is clearly a battle tested solution.Tests show performance improvements, although the large bottlenecks are in marshalling.
The command line interface, sqlite, can export in various formats (including CSV).
It would remove the need for most of the chicanery around loading and saving of data, probably significantly improving the stability.
A small number of the reports that I generate with
rdial
are actually performed by importing the data in to asqlite
in-memory database via its CSV support, which proves the suitability already.
- Likelihood
✪✪✪✪○
- Effort
✪✪○○○
Language¶
I’m moderately happy with Python as the implementation language, although have considered switching a couple of times to improve command response times.
Over the years I’ve re-implemented rdial
to various extents when playing
with new languages:
Language |
Pros |
Cons |
---|---|---|
|
|
|
|
|
|
|
|
Note
While clearly not new languages, both Genie and C
have been considered
too. Genie
would be a good fit, but it is not clear what future it
has. C
would basically be either a huge amount of work or a simple
wrapper around existing libraries 2, neither of which I find compelling.
I’ve also considered the git approach, with a fast top-level wrapper invoking external subcommands that could be in different languages. This way we can have super fast commands where they’re really needed(rdial {start,stop,switch}), and choose a feature appropriate language for other commands(rdial report for instance). While attractive, it would make packaging far more annoying.
- Likelihood
✪✪○○○
- Effort
✪✪✪✪✪
Interfaces¶
A couple of users have expressed an interest in alternative interfaces, but I’m not very enthusiastic about working on them myself. I understand the desire, but don’t feel it is worth the effort. Added to that, if I’m not going to use them myself, I’m probably not the best person to produce them.
That said, I do use rdial
outside of the command line, but entirely by
wrapping the command line interface. This feels like a reasonable solution,
but would benefit from a faster implementation and a guaranteed output
format.
So, my intention would be:
Adding full documentation for my awesomewm integration.
Open sourcing the Android Wear swipe integrations for my watch.
A faster implementation.
Guaranteed stable output format.
- Likelihood
✪✪✪○○
- Effort
✪✪✪○○
Footnotes
Release HOWTO¶
Test¶
Tests can be run via pytest:
$ pip install -r extra/requirements-test.txt
$ pytest -v tests
When preparing a release it is important to check that rdial
works with
all supported Python versions, and that the documentation for executing them is
correct.
Prepare release¶
With the tests passing, do the following steps:
Update the version data in
rdial/_version.py
Update
NEWS.rst
with any user visible changesCommit the release notes and version changes
Create a signed tag for the release
Push the changes — including the new tag — to the GitHub repository
Create a new release on GitHub
Update PyPI¶
Create and upload the new release tarballs to PyPI using twine:
$ ./setup.py sdist bdist_wheel
$ twine upload --sign dist/rdial-${version}*
Fetch the uploaded tarballs, and check for errors.
You should also test installation from PyPI, to check the experience
rdial
’s end users will have.
Todo items for documentation¶
Todo
Check for recent additions to the arena.
(The original entry is located in /home/docs/checkouts/readthedocs.org/user_builds/rdial/checkouts/latest/doc/alternatives.rst, line 13.)
Todo
Add more fleshed out examples.
(The original entry is located in /home/docs/checkouts/readthedocs.org/user_builds/rdial/checkouts/latest/doc/taskbars.rst, line 15.)
API documentation¶
Note
The documentation in this section is aimed at people wishing to contribute to
rdial
, and can be skipped if you are simply using the tool from the
command line.
Event
¶
Note
The documentation in this section is aimed at people wishing to contribute to
rdial
, and can be skipped if you are simply using the tool from the
command line.
-
class
rdial.events.
Event
(_Event__task, start=None, delta=None, message='')[source]¶ Initialise a new
Event
object.- Parameters
-
stop
(message=None, force=False)[source]¶ Stop running event.
- Parameters
- Raises
TaskNotRunningError – Event not running
- Return type
None
-
class
rdial.events.
Events
(_Events__iterable=None, backup=True)[source]¶ Initialise a new
Events
object.- Parameters
__iterable – Objects to add to container
backup (
bool
) – Whether to create backup files
-
filter
(_Events__filt)[source]¶ Apply filter to events.
- Parameters
__filt – Function to filter with
- Return type
- Returns
Events matching given filter function
-
for_task
(_Events__task)[source]¶ Filter events for a specific task.
- Parameters
__task – Task name to filter on
- Return type
- Returns
Events marked with given task name
-
for_week
(_Events__year, _Events__week)[source]¶ Filter events for a specific ISO-8601 week.
- Parameters
__year – Year to filter events on
__week – ISO-8601 week number to filter events on
- Return type
- Returns
Events occurring in given ISO-8601 week
-
last
()[source]¶ Return current/last event.
Note
This handles the empty database case by returning
None
.
-
static
read
(_Events__directory, backup=True, write_cache=True)[source]¶ Read and parse database.
Note
Assumes a new
Events
object should be created if the directory is missing.
-
running
()[source]¶ Check if an event is running.
We return the running task, if one exists, for easy access.
-
start
(_Events__task, new=False, start='')[source]¶ Start a new event.
- Parameters
- Raises
TaskRunningError – An event is already running
- Return type
None
-
stop
(message=None, force=False)[source]¶ Stop running event.
- Parameters
- Raises
TaskNotRunningError – No task running!
- Return type
None
Examples¶
>>> event = Event('test')
>>> event.running()
'test'
>>> event.stop('complete')
>>> event.running()
False
>>> data = event.writer()
>>> data['message']
'complete'
>>> event2 = Event('test', start="2013-01-01T12:00:00Z")
>>> events = Events([event, event2])
>>> events.filter(lambda x: x.message == 'complete')
Events([Event('test', '...', '...', 'complete')])
>>> events.for_date(2013, 1)
Events([Event('test', '2013-01-01T12:00:00Z', '', '')])
>>> events.for_week(2012, 53)
Events([Event('test', '2013-01-01T12:00:00Z', '', '')])
>>> events.running()
'test'
Command line¶
Note
The documentation in this section is aimed at people wishing to contribute to
rdial
, and can be skipped if you are simply using the tool from the
command line.
Commands¶
-
rdial.cmdline.
bug_data
()¶ Produce data for rdial bug reports.
-
rdial.cmdline.
fsck
(ctx, globs, progress)¶ Check storage consistency.
- Parameters
ctx – Current command context
globs – Global options object
progress – Display progressbar
-
rdial.cmdline.
start
(globs, task, continue, new, time)¶ Start task.
- Parameters
globs – Global options object
task – Task name to operate on
continue_ – Pull task name from last running task
new – Create a new task
time – Task start time
-
rdial.cmdline.
stop
(globs, message, fname, amend)¶ Stop task.
- Parameters
globs – Global options object
message – Message to assign to event
fname – Filename to read message from
amend – Amend a previously stopped event
-
rdial.cmdline.
switch
(globs, task, new, time, amend, message, fname)¶ Complete last task and start new one.
- Parameters
globs – Global options object
task – Task name to operate on
new – Create a new task
time – Task start time
amend – Amend a previously stopped event
message – Message to assign to event
fname – Filename to read message from
-
rdial.cmdline.
run
(globs, task, new, time, message, fname, command)¶ Run command with timer.
- Parameters
globs – Global options object
task – Task name to operate on
new – Create a new task
time – Task start time
message – Message to assign to event
fname – Filename to read message from
command – Command to run
-
rdial.cmdline.
wrapper
(ctx, globs, time, message, fname, wrapper)¶ Run predefined command with timer.
- Parameters
ctx – Click context object
globs – Global options object
time – Task start time
message – Message to assign to event
fname – Filename to read message from
wrapper – Run wrapper to execute
-
rdial.cmdline.
report
(globs, task, stats, duration, sort, reverse, style)¶ Report time tracking data.
- Parameters
globs – Global options object
task – Task name to operate on
stats – Display short overview of data
duration – Time window to filter on
sort – Key to sort events on
reverse – Reverse sort order
style – Table formatting style
-
rdial.cmdline.
running
(globs)¶ Display running task, if any.
- Parameters
globs – Global options object
-
rdial.cmdline.
last
(globs)¶ Display last event, if any.
- Parameters
globs – Global options object
-
rdial.cmdline.
ledger
(globs, task, duration, rate)¶ Generate ledger compatible data file.
- Parameters
globs – Global options object
task – Task name to operate on
duration – Time window to filter on
rate – Rate to assign hours in report
-
rdial.cmdline.
timeclock
(globs, task, duration)¶ Generate ledger compatible timeclock file.
- Parameters
globs – Global options object
task – Task name to operate on
duration – Time window to filter on
Entry points¶
-
rdial.cmdline.
cli
(ctx, directory, backup, cache, config, interactive, colour)¶ Main command entry point.
- Parameters
ctx – Current command context
directory – Location to store event data
backup – Whether to create backup files
cache – Whether to create cache files
config – Location of config file
interactive – Whether to support interactive message editing
colour – Whether to colourise output
Command support¶
-
rdial.cmdline.
filter_events
(__globs, __task=None, __duration='all')[source]¶ Filter events for report processing.
- Parameters
__globs (
ROAttrDict
) – Global options object__duration (
str
) – Time window to filter on
- Returns
Events matching specified criteria
- Return type
CLI support¶
-
rdial.cmdline.
task_from_dir
(__ctx, __param, __value)[source]¶ Override task name default using name of current directory.
- Parameters
__ctx (
Context
) – Current command context__param (
Option
) – Parameter being processed__value (
bool
) – True if flag given
- Return type
None
-
rdial.cmdline.
task_option
(__fun)[source]¶ Add task selection options.
Note
This is only here to reduce duplication in command setup.
Utilities¶
Note
The documentation in this section is aimed at people wishing to contribute to
rdial
, and can be skipped if you are simply using the tool from the
command line.
Convenience functions and classes¶
-
rdial.utils.
write_current
(__fun)[source]¶ Decorator to write
.current
file on function exit.See also
-
rdial.utils.
remove_current
(__fun)[source]¶ Decorator to remove
.current
file on function exit.See also
Time handling¶
-
rdial.utils.
iso_week_to_date
(__year, __week)[source]¶ Generate date range for a given ISO-8601 week.
ISO-8601 defines a week as Monday to Sunday, with the first week of a year being the first week containing a Thursday.
Development tools¶
-
rdial.utils.
maybe_profile
()[source]¶ Profile the wrapped code block.
When
RDIAL_PROFILE
is set execute the enclosed block under bprofile. The envvar’s value should be the name of the output file to generate.When
RDIAL_PROFILE
is unset, this is just a no-op.- Return type
AbstractContextManager
[+T_co]
Examples¶
Time handling¶
>>> parse_datetime_user('40 minutes ago')
datetime.datetime(2012, 2, 15, 18, 59, 18)
Development tools¶
>>> with maybe_profile():
... time.sleep(10)
Errors¶
Note
The documentation in this section is aimed at people wishing to contribute to
rdial
, and can be skipped if you are simply using the tool from the
command line.
-
exception
rdial.events.
TaskNotExistError
[source]¶ Exception for attempting to operate on a non-existing task.
-
exception
rdial.events.
TaskNotRunningError
[source]¶ Exception for calling mutators when a task is not running.
-
exception
rdial.events.
TaskRunningError
[source]¶ Exception for starting task when a task is already running.
Examples¶
>>> events_stopped.stop()
Traceback (most recent call last):
…
TaskNotRunningError: No task running!
>>> events_running.start('rdial', new=True)
Traceback (most recent call last):
…
TaskRunningError: Running task test!