Skip to content
Commits on Source (28)
......@@ -9,6 +9,8 @@ before_script:
.test: &test
stage: test
variables:
PIPENV_VERBOSITY: "-1"
script:
- tox -e $CI_JOB_NAME
......@@ -24,10 +26,7 @@ py37:
<<: *test
image: python:3.7
pylint:
<<: *test
flake8:
lint:
<<: *test
coverage:
......@@ -40,24 +39,27 @@ coverage:
- htmlcov/
allow_failure: true
twine-check:
package-check:
stage: test
before_script:
- pip3 install -rreqs/requirements-deploy.txt
- pip3 install pipenv
- pipenv install --dev --ignore-pipfile
script:
- python3 setup.py sdist bdist_wheel
- twine check dist/*
- pipenv check
- pipenv run python3 setup.py sdist bdist_wheel
- pipenv run twine check dist/*
dist:
stage: deploy
before_script:
- pip3 install -rreqs/requirements-deploy.txt
- ci/apt install -y -qq --no-install-recommends asciidoctor ruby-pygments.rb
- pipenv install --dev --ignore-pipfile
only:
- tags
- triggers
script:
- python3 setup.py sdist bdist_wheel
- twine upload dist/* -u "$PYPI_USER" -p "$PYPI_PASS"
- pipenv run twine upload dist/* -u "$PYPI_USER" -p "$PYPI_PASS"
artifacts:
name: "${CI_PROJECT_NAME}-{$CI_BUILD_REF_NAME}"
paths:
......@@ -66,7 +68,7 @@ dist:
pages:
stage: deploy
before_script:
- ci/apt install -y -qq --no-install-recommends asciidoctor
- ci/apt install -y -qq --no-install-recommends asciidoctor ruby-pygments.rb
script:
- ci/gen-pages
artifacts:
......
twc (0.5.0)
* Breaking: Rename most of commands.
This will cause non-default key bindings to stop working.
* Implemented bulk editing of tasks.
Tasks can be selected with a space and then most of ordinary commands (like
modifying, deleting, toggling, annotating, denotating) can be performed on
all selected tasks.
This adds a new command: task.select
* New command: task.edit, which opens selected tasks in $EDITOR.
* Any uncaught exceptions will be reported by shor error messages. This
fature can be disabled with --debug flag.
* Possibly long running background operations (tasks syncing) will
continuously display animations to indicate that they're still running.
* Bugfix: Fixed double delete destroying interface.
* Bugfix: Fixed incorrect sorting of children (blocking) tasks.
* Bugfix: Fixed default config error: fmt -> format.
* Bugfix: Fixed destroying the interface when 'undo' fails.
-- Michał Góral <dev@goral.net.pl> Thu, 30 May 2019 07:42:03 +0200
twc (0.4.0)
* Breaking: block.fmt becomes block.format.
......
......@@ -2,7 +2,9 @@ include README.rst
include LICENSE
include setup.py
include requirements.txt
include pyproject.toml
include Pipfile
include Pipfile.lock
graft docs
graft reqs
......
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
pytest = "*"
pytest-cov = "*"
pytest-xdist = "*"
pylint = "*"
flake8 = "*"
twine = "==1.13.0"
[packages]
twc = {path = ".",editable = true}
[requires]
This diff is collapsed.
......@@ -13,8 +13,14 @@
TWC - TaskWarrior controller - interactive command-line task and todo manager.
include::manual/install.adoc[]
include::manual/config.adoc[]
[appendix]
include::manual/termux.adoc[]
:sectnumlevels: -1
[appendix]
......
......@@ -131,13 +131,13 @@ agenda you can double press "g". In configuration this should be set as _g g_
Key prefixes are supported:
- _c-_ for combinations with ctrl (e.g. _c-f_)
- _a-_ for combinations with alt (e.g. _a-space_)
- _s-_ for combinations with shift (e.g. _s-tab_)
- _c-_ for combinations with ctrl (e.g. _c-f_, meaning kbd:[Ctrl+f])
- _a-_ for combinations with alt (e.g. _a-space_, meaning kbd:[Atl+Space])
- _s-_ for combinations with shift (e.g. _s-tab_, meaning kbd:[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 _s-a_.
"shift+letter", you'll usually simply write upper-case letter, like kbd:[A]
instead of kbd:[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
......@@ -146,56 +146,83 @@ 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_.
command etc.
+
Default bindings: kbd:[Enter].
*cancel*::
Cancels current action: closes task details, cancels current command etc.
Default bindings: _Esc_.
Cancels current action: closes task details, cancels current command etc. On
agenda view clears prompt and selections.
+
Default bindings: kbd:[Esc].
*quit*::
Exits TWC. This command is inactive when typing a command. Default bindings:
_Q_, _q_, _C-c_.
Exits TWC. This command is inactive when typing a command.
+
Default bindings: kbd:[Q], kbd:[q], kbd:[Ctrl+c].
==== Navigation
*scroll-down*::
Focuses next task in agenda. Default bindings: _Down_, _j_.
*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: kbd:[Down], kbd:[j].
*scroll-up*::
Focuses previous task in agenda. Default bindings: _Up_, _k_.
*scroll.up*::
Same as scroll.down, but backwards.
+
Default bindings: kbd:[Up], kbd:[k].
*next-block*::
Jumps to the beginning of next block in current agenda. Default bindings: _Page
Down_, _]_.
*scroll.nextsection*::
Jumps to the beginning of next visual section, e.g. next block in current
agenda.
+
Default bindings: kbd:[Page Down], kbd:[\]].
*prev-block*::
Jumps to the beginning of previous block in current agenda. Default bindings:
_Page Up_, _[_.
*scroll.prevsection*::
Jumps to the beginning of previous visual section, e.g. block in current agenda.
+
Default bindings: kbd:[Page Up], kbd:[[].
*jump-begin*::
Jumps to the first task in current agenda. Default bindings: _Home_, _gg_.
*scroll.begin*::
Jumps to the first task in current agenda.
+
Default bindings: kbd:[Home], kbd:[gg].
*jump-end*::
Jumps to the last task in current agenda. Default bindings: _End_, _G_.
*scroll.end*::
Jumps to the last task in current agenda.
+
Default bindings: kbd:[End], kbd:[G].
*next-agenda*::
Opens next agenda (the one to the right). Default bindings: _Tab_.
*tab.next*::
Opens next agenda (the one to the right).
+
Default bindings: kbd:[Tab].
*prev-agenda*::
Opens previous agenda (the one to the left). Default bindings: _S-Tab_.
*tab.prev*::
Opens previous agenda (the one to the left).
+
Default bindings: kbd:[Shift+Tab].
*search*::
Starts new search of tasks in current agenda. Default bindings: _C-f_, _/_.
Starts new search of tasks in current agenda.
+
Default bindings: kbd:[Ctrl+f], kbd:[/].
*find-next*::
Finds next occurence of currently searched term. Default bindings: _n_.
*search.forward*::
Finds next occurence of currently searched term. Defa
+
ult bindings: kbd:[n].
*find-prev*::
Finds previous occurence of currently searched term. Default bindings: _N_.
*search.backward*::
Finds previous occurence of currently searched term.
+
Default bindings: kbd:[N].
==== Task Commands
*add-task*::
*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.
+
......@@ -203,49 +230,77 @@ 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_.
You can use tab- and auto-completion. Press kbd:[Tab] to see a list of
completions available.
+
Default bindings: kbd:[a].
*modify-task*::
*task.modify*::
Opens a command line which accepts a modification command:
+
----
> -tag1 -tag2 due:
----
+
Tab- and auto-completion are available. Default bindings: _m_.
Tab- and auto-completion are available.
+
Default bindings: kbd:[m].
*task.edit*::
Runs _task sync_ which edits task in a text editor. This is not the recommended
method of modifying tasks, but is provided for exceptional circumstances.
+
Default bindings: kbd:[e].
*annotate*::
*task.annotate*::
Opens a command line which accepts a new annotation which will be added to
currently focused task. Default bindings: _A_.
currently focused task.
+
Default bindings: kbd:[A].
*denotate*::
*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_.
full annotations.
+
Default bindings: kbd:[D].
*toggle-completed*::
*task.toggle*::
Mark focused task's status as _done_ if it is currently pending. Otherwise mark
it as _pending_. Default bindings: _A-Space_
it as _pending_.
+
Default bindings: kbd:[Alt-Space]
*delete-task*::
*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_.
You can still access them by their UUID.
+
Default bindings: kbd:[Delete].
*undo*::
*task.undo*::
Reverts the most recent action. This command uses _task undo_ underneath.
Default bindings: _u_.
+
Default bindings: kbd:[u].
*synchornize*::
*task.synchornize*::
Synchronizes tasks with a task server. Task server must be correctly configured
in taskrc. Default bindings: _S_.
in taskrc.
+
Default bindings: kbd:[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: kbd:[Space].
*refresh-agenda*::
Repeats TaskWarrior queries and refreshes the view. Useful after some
modifications which by design don't automatically refresh agenda (like sync).
Default bindings: _R_.
*refresh*::
Refreshes the view. Useful after some modifications which by design don't
automatically refresh agenda (like sync).
+
Default bindings: kbd:[R].
[[settings]]
=== Settings
......@@ -258,28 +313,38 @@ 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_.
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_.
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_
Enable incremental search (search-when-typing).
+
Default: _True_
*ignorecase*::
Disable case sensitive search. Default: _True_
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_.
case-insensitive when it contains only lower case characters.
+
Default: _True_.
[[statusline]]
*statusleft*::
......@@ -302,20 +367,25 @@ that task attributes are referenced by _{task.<attribute>}_, e.g.
- {agenda.ppos} - percentage position of highlighted item
*taskrc*::
Path to used taskrc file. Default: _~/.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_.
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_.
+
Default: _50_.
[[styles]]
=== Styles
......@@ -347,8 +417,9 @@ colors as well as some flags describing text formatting (like bold, italics).
|===
NOTE: Predefined styles are: _heading, text, comment, info, warning, error,
highlight, tabline, tabsel, tab, tooltip, statusline, status.1, status.2_. Some
of them are used for styling specific elements of program interface.
highlight, mark, tabline, tabsel, tab, tooltip, statusline, status.1,
status.2_. Some of them are used for styling specific elements of program
interface.
=== Configuration Reference
......
:twdoc: https://taskwarrior.org/download/
:twc-pypi: https://pypi.org/project/twc/
:pipsi: https://github.com/mitsuhiko/pipsi
[[installation]]
== Installation
First, make sure that TaskWarrior is installed on your system. TaskWarrior is
packaged for most of Linux distributions. Please refer to TaskWarrior's
{twdoc}[documentation] for details. Typically you can install Taskwarrior with
one of the following commands:
[source, console]
----
$ 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.
=== From PyPI
TWC is distributed via {twc-pypi}[PyPI]. It is recommended to use a tool like
{pipsi}[pipsi] to handle installations from PyPI, because it offers isolation
of installed applications and an easy way to uninstall them together with their
dependencies.
[source, console]
----
$ pipsi install --python python3 twc
----
You can also use bare PIP:
[source, console]
----
$ pip3 install --user twc
----
=== From Git
You can also manually download, build and install TWC:
[source, console]
----
$ 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:
[source, console]
----
$ pipenv install
$ pipenv run twc
----
:termux: https://termux.com
:tzlocal-bug: https://github.com/regebro/tzlocal/pull/55
[[termux]]
== Termux
TWC works on {termux}[Termux], although there's currently a {tzlocal-bug}[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:
[source,sh]
----
export TZ=$(getprop persist.sys.timezone)
----
Termux emulates scroll events as key presses. You can bind them for easier
navigation:
[source,python]
----
c.bind('right', 'next-agenda')
c.bind('left', 'prev-agenda')
----
......@@ -5,6 +5,7 @@
:revnumber: @VERSION@
:man manual: TWC Manual
:man source: TWC {revnumber}
:experimental:
== NAME
......
[build-system]
requires = ["setuptools", "wheel"]
pytest==4.4.2
pytest-xdist==1.28.0
......@@ -78,6 +78,7 @@ def main():
author_email='dev@mgoral.org',
url='https://gitlab.com/mgoral/twc',
platforms=['linux'],
python_requires='>=3.5,<3.8',
setup_requires=['setuptools_scm'],
install_requires=['prompt_toolkit==2.0.9',
'tasklib==1.1.0',
......
......@@ -49,6 +49,10 @@ def parse_args():
parser.add_argument(
'-a', '--agenda',
help=tr('agenda to start application with'))
parser.add_argument(
'--debug',
action='store_true',
help=tr('enable debugging features'))
parser.add_argument(
'--version',
action='version',
......@@ -56,6 +60,17 @@ def parse_args():
return parser.parse_args()
def print_exceptions(loop, context):
exc = context['exception']
fmt = dict(etype=type(exc).__name__, msg=str(exc))
msgs = [
tr('{etype}: {msg}'.format_map(fmt)),
]
eprint(msgs)
def run():
'''Runs application'''
args = parse_args()
......@@ -86,6 +101,10 @@ def run():
use_asyncio_event_loop()
loop = asyncio.get_event_loop()
if not args.debug:
loop.set_exception_handler(print_exceptions)
loop.run_until_complete(application.run_async().to_asyncio_future())
loop.close()
......
......@@ -18,6 +18,7 @@
'''User commands'''
from prompt_toolkit.key_binding import KeyBindings
from twc.utils import cancel_all_async_tasks
from twc.conditions import (
is_normal_state,
......@@ -39,6 +40,7 @@ def global_bindings(cfg):
@cfg.command_handler('quit', kb, filter=is_normal_state)
def _(event):
'''Quit main loop'''
cancel_all_async_tasks()
event.app.exit()
return kb