Commit 4f9df324 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge pull request #57 from mruwek/aliases

parents 6689308e bb9de101
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from six import u
from test.TopydoTestCase import TopydoTest
from topydo.Commands import get_subcommand
from topydo.commands.AddCommand import AddCommand
from topydo.commands.DeleteCommand import DeleteCommand
from topydo.commands.ListCommand import ListCommand
from topydo.commands.ListProjectCommand import ListProjectCommand
from topydo.lib.Config import config
class GetSubcommandTest(TopydoTest):
def test_normal_cmd(self):
args = ["add"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, AddCommand))
def test_cmd_help(self):
args = ["help", "add"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, AddCommand))
self.assertEqual(final_args, ["help"])
def test_alias(self):
config("test/data/aliases.conf")
args = ["foo"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, DeleteCommand))
self.assertEqual(final_args, ["-f", "test"])
def test_default_cmd01(self):
args = ["bar"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, ListCommand))
self.assertEqual(final_args, ["bar"])
def test_default_cmd02(self):
args = []
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, ListCommand))
self.assertEqual(final_args, [])
def test_alias_default_cmd01(self):
config("test/data/aliases.conf", {('topydo', 'default_command'): 'foo'})
args = ["bar"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, DeleteCommand))
self.assertEqual(final_args, ["-f", "test", "bar"])
def test_alias_default_cmd02(self):
config("test/data/aliases.conf", {('topydo', 'default_command'): 'foo'})
args = []
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, DeleteCommand))
self.assertEqual(final_args, ["-f", "test"])
def test_wrong_alias(self):
config("test/data/aliases.conf")
args = ["baz"]
real_cmd, final_args = get_subcommand(args)
self.assertEqual(real_cmd, None)
if __name__ == '__main__':
unittest.main()
[aliases]
foo = rm -f test
baz = FooBar
...@@ -46,3 +46,14 @@ append_parent_contexts = 0 ...@@ -46,3 +46,14 @@ append_parent_contexts = 0
; context_color = magenta ; context_color = magenta
; metadata_color = green ; metadata_color = green
; link_color = light-cyan ; link_color = light-cyan
[aliases]
;showall = ls -x
;lsproj = lsprj
;listprj = lsprj
;listproj = lsprj
;listproject = lsprj
;listprojects = lsprj
;listcon = lscon
;listcontext = lscon
;listcontexts = lscon
...@@ -35,15 +35,7 @@ _SUBCOMMAND_MAP = { ...@@ -35,15 +35,7 @@ _SUBCOMMAND_MAP = {
'exit': 'ExitCommand', # used for the prompt 'exit': 'ExitCommand', # used for the prompt
'ls': 'ListCommand', 'ls': 'ListCommand',
'lscon': 'ListContextCommand', 'lscon': 'ListContextCommand',
'listcon': 'ListContextCommand',
'listcontext': 'ListContextCommand',
'listcontexts': 'ListContextCommand',
'lsprj': 'ListProjectCommand', 'lsprj': 'ListProjectCommand',
'lsproj': 'ListProjectCommand',
'listprj': 'ListProjectCommand',
'listproj': 'ListProjectCommand',
'listproject': 'ListProjectCommand',
'listprojects': 'ListProjectCommand',
'postpone': 'PostponeCommand', 'postpone': 'PostponeCommand',
'pri': 'PriorityCommand', 'pri': 'PriorityCommand',
'quit': 'ExitCommand', 'quit': 'ExitCommand',
...@@ -53,7 +45,6 @@ _SUBCOMMAND_MAP = { ...@@ -53,7 +45,6 @@ _SUBCOMMAND_MAP = {
'tag': 'TagCommand', 'tag': 'TagCommand',
} }
def get_subcommand(p_args): def get_subcommand(p_args):
""" """
Retrieves the to-be executed Command and returns a tuple (Command, args). Retrieves the to-be executed Command and returns a tuple (Command, args).
...@@ -80,13 +71,31 @@ def get_subcommand(p_args): ...@@ -80,13 +71,31 @@ def get_subcommand(p_args):
__import__(modulename, globals(), locals(), [classname], 0) __import__(modulename, globals(), locals(), [classname], 0)
return getattr(sys.modules[modulename], classname) return getattr(sys.modules[modulename], classname)
def resolve_alias(p_alias, p_args):
"""
Resolves a subcommand alias and returns a tuple (Command, args).
If alias resolves to non-existent command, main help message is
returned.
"""
real_subcommand, alias_args = alias_map[p_alias]
try:
result = import_subcommand(real_subcommand)
args = alias_args + p_args
return (result, args)
except KeyError:
return get_subcommand(['help'])
result = None result = None
args = p_args args = p_args
alias_map = config().aliases()
try: try:
subcommand = p_args[0] subcommand = p_args[0]
if subcommand in _SUBCOMMAND_MAP: if subcommand in alias_map:
result, args = resolve_alias(subcommand, args[1:])
elif subcommand in _SUBCOMMAND_MAP:
result = import_subcommand(subcommand) result = import_subcommand(subcommand)
args = args[1:] args = args[1:]
elif subcommand == 'help': elif subcommand == 'help':
...@@ -101,12 +110,16 @@ def get_subcommand(p_args): ...@@ -101,12 +110,16 @@ def get_subcommand(p_args):
pass pass
else: else:
p_command = config().default_command() p_command = config().default_command()
if p_command in _SUBCOMMAND_MAP: if p_command in alias_map:
result, args = resolve_alias(p_command, args)
elif p_command in _SUBCOMMAND_MAP:
result = import_subcommand(p_command) result = import_subcommand(p_command)
# leave args unchanged # leave args unchanged
except IndexError: except IndexError:
p_command = config().default_command() p_command = config().default_command()
if p_command in _SUBCOMMAND_MAP: if p_command in alias_map:
result, args = resolve_alias(p_command, args)
elif p_command in _SUBCOMMAND_MAP:
result = import_subcommand(p_command) result = import_subcommand(p_command)
return (result, args) return (result, args)
...@@ -30,7 +30,9 @@ from topydo.lib.RelativeDate import relative_date_to_date ...@@ -30,7 +30,9 @@ from topydo.lib.RelativeDate import relative_date_to_date
def _subcommands(p_word_before_cursor): def _subcommands(p_word_before_cursor):
""" Generator for subcommand name completion. """ """ Generator for subcommand name completion. """
subcommands = [sc for sc in sorted(_SUBCOMMAND_MAP.keys()) if sc_map = config().aliases()
sc_map.update(_SUBCOMMAND_MAP)
subcommands = [sc for sc in sorted(sc_map.keys()) if
sc.startswith(p_word_before_cursor)] sc.startswith(p_word_before_cursor)]
for command in subcommands: for command in subcommands:
yield Completion(command, -len(p_word_before_cursor)) yield Completion(command, -len(p_word_before_cursor))
......
...@@ -42,6 +42,7 @@ class _Config: ...@@ -42,6 +42,7 @@ class _Config:
""" """
self.sections = [ self.sections = [
'add', 'add',
'aliases',
'colorscheme', 'colorscheme',
'dep', 'dep',
'ls', 'ls',
...@@ -94,6 +95,17 @@ class _Config: ...@@ -94,6 +95,17 @@ class _Config:
'link_color': 'cyan', 'link_color': 'cyan',
'priority_colors': 'A:cyan,B:yellow,C:blue', 'priority_colors': 'A:cyan,B:yellow,C:blue',
}, },
'aliases': {
'lsproj': 'lsprj',
'listprj': 'lsprj',
'listproj': 'lsprj',
'listproject': 'lsprj',
'listprojects': 'lsprj',
'listcon': 'lscon',
'listcontext': 'lscon',
'listcontexts': 'lscon',
},
} }
self.config = {} self.config = {}
...@@ -279,6 +291,22 @@ class _Config: ...@@ -279,6 +291,22 @@ class _Config:
except ValueError: except ValueError:
return self.defaults['add']['auto_creation_date'] == '1' return self.defaults['add']['auto_creation_date'] == '1'
def aliases(self):
"""
Returns dict with aliases names as keys and pairs of actual
subcommand and alias args as values.
"""
aliases = self.cp.items('aliases')
alias_dict = dict()
for alias, meaning in aliases:
meaning = meaning.split()
real_subcommand = meaning[0]
alias_args = meaning[1:]
alias_dict[alias] = (real_subcommand, alias_args)
return alias_dict
def config(p_path=None, p_overrides=None): def config(p_path=None, p_overrides=None):
""" """
Retrieve the config instance. Retrieve the config instance.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment