예제 #1
0
파일: mello.py 프로젝트: whitef0x0/gtd.py
def delete_cards(config, force, noninteractive, tags, no_tags, match, listname, attachments, has_due):
    '''Delete a set of cards specified
    '''
    _, board, _ = BoardTool.start(config)
    display = Display(config.color)
    if config.banner and not json:
        display.banner()
    cards = BoardTool.filter_cards(
        board,
        tags=tags,
        no_tags=no_tags,
        title_regex=match,
        list_regex=listname,
        has_attachments=attachments,
        has_due_date=has_due
    )
    method = 'delete' if force else 'archive'
    if noninteractive:
        if force:
            [c.delete() for c in cards]
        else:
            [c.set_closed(True) for c in cards]
    else:
        for card in cards:
            display.show_card(card)
            if prompt_for_confirmation('Delete this card?'):
                if force:
                    card.delete()
                else:
                    card.set_closed(True)
                click.secho('Card {}d!'.format(method), fg='red')
예제 #2
0
파일: gtd.py 프로젝트: robeastham/gtd.py
def delete_cards(config, force, noninteractive, tags, no_tags, match, listname, attachments, has_due):
    '''Delete a set of cards specified
    '''
    _, board = BoardTool.start(config)
    display = Display(config.color)
    if config.banner and not json:
        display.banner()
    cards = BoardTool.filter_cards(
        board,
        tags=tags,
        no_tags=no_tags,
        title_regex=match,
        list_regex=listname,
        has_attachments=attachments,
        has_due_date=has_due
    )
    method = 'delete' if force else 'archive'
    if noninteractive:
        if force:
            [c.delete() for c in cards]
        else:
            [c.set_closed(True) for c in cards]
    else:
        for card in cards:
            display.show_card(card)
            if prompt_for_confirmation('Delete this card?'):
                if force:
                    card.delete()
                else:
                    card.set_closed(True)
                click.secho('Card {}d!'.format(method), fg='red')
예제 #3
0
파일: mello.py 프로젝트: whitef0x0/gtd.py
def batch_attach(config):
    '''Extract HTTP links from card titles'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(board, title_regex=VALID_URL_REGEX)
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        if prompt_for_confirmation('Attach title?', True):
            CardTool.title_to_link(card)
예제 #4
0
파일: gtd.py 프로젝트: robeastham/gtd.py
def batch_attach(config):
    '''Extract HTTP links from card titles'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(board, title_regex=VALID_URL_REGEX)
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        if prompt_for_confirmation('Attach title?', True):
            CardTool.title_to_link(card)
예제 #5
0
def batch_tag(config, tags, no_tags, match, listname, attachments, has_due):
    '''Change tags on each card selected'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(board,
                                   tags=tags,
                                   no_tags=no_tags,
                                   title_regex=match,
                                   list_regex=listname,
                                   has_attachments=attachments,
                                   has_due_date=has_due)
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        CardTool.add_labels(card)
예제 #6
0
def batch_due(config, tags, no_tags, match, listname, attachments, has_due):
    '''Set due date for all cards selected'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(board,
                                   tags=tags,
                                   no_tags=no_tags,
                                   title_regex=match,
                                   list_regex=listname,
                                   has_attachments=attachments,
                                   has_due_date=has_due)
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        if prompt_for_confirmation('Set due date?'):
            CardTool.set_due_date(card)
예제 #7
0
def batch_move(config, tags, no_tags, match, listname, attachments, has_due):
    '''Change the list of each card selected'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(board,
                                   tags=tags,
                                   no_tags=no_tags,
                                   title_regex=match,
                                   list_regex=listname,
                                   has_attachments=attachments,
                                   has_due_date=has_due)
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        if prompt_for_confirmation('Want to move this one?', True):
            CardTool.move_to_list(card)
예제 #8
0
파일: gtd.py 프로젝트: robeastham/gtd.py
def batch_tag(config, tags, no_tags, match, listname, attachments, has_due):
    '''Change tags on each card selected'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(
        board,
        tags=tags,
        no_tags=no_tags,
        title_regex=match,
        list_regex=listname,
        has_attachments=attachments,
        has_due_date=has_due
    )
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        CardTool.add_labels(card)
예제 #9
0
파일: gtd.py 프로젝트: robeastham/gtd.py
def batch_due(config, tags, no_tags, match, listname, attachments, has_due):
    '''Set due date for all cards selected'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(
        board,
        tags=tags,
        no_tags=no_tags,
        title_regex=match,
        list_regex=listname,
        has_attachments=attachments,
        has_due_date=has_due
    )
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        if prompt_for_confirmation('Set due date?'):
            CardTool.set_due_date(card)
예제 #10
0
파일: gtd.py 프로젝트: robeastham/gtd.py
def batch_move(config, tags, no_tags, match, listname, attachments, has_due):
    '''Change the list of each card selected'''
    connection, board = BoardTool.start(config)
    cards = BoardTool.filter_cards(
        board,
        tags=tags,
        no_tags=no_tags,
        title_regex=match,
        list_regex=listname,
        has_attachments=attachments,
        has_due_date=has_due
    )
    display = Display(config.color)
    if config.banner:
        display.banner()
    for card in cards:
        display.show_card(card)
        if prompt_for_confirmation('Want to move this one?', True):
            CardTool.move_to_list(card)
예제 #11
0
class CLIContext:
    '''CLIContext is a container for the commonly used objects in each gtd command.
    It is passed around as an argument injected by click after the cli() function runs.
    Any reference to "ctx" as a parameter in this file is an instance of CLIContext.

    config: todo.configuration.Configuration
    connection: todo.connection.TrelloConnection
    display: todo.display.Display
    '''
    def __init__(self, config: Configuration):
        self.config = config
        self.connection = TrelloConnection(config)
        self.display = Display(config, self.connection)
        self.board = self.connection.main_board()
        # Cached state for card_repl
        self._list_choices = build_name_lookup(
            self.connection.main_board().get_lists('open'))
        self._label_choices = build_name_lookup(
            self.connection.main_board().get_labels(limit=200))

    def card_repl(self, card: dict) -> bool:
        '''card_repl displays a command-prompt based UI for modifying a card, with tab-completion and suggestions.
        It is the logic behind "gtd review" and the "-e" flag in "gtd add"

        It makes assumptions about what a user might want to do with a card:
        - Are there attachments? Maybe you want to open them.
        - Does there appear to be a URL in the title? You might want to attach it.
        - Are there no tags? Maybe you want to add some.

        Returns:
            boolean: move forwards or backwards in the deck of cards
        '''
        on = Colors.yellow if self.config.color else ''
        off = Colors.reset if self.config.color else ''
        self.display.show_card(card)
        if self.config.prompt_for_open_attachments and card['badges'][
                'attachments']:
            if prompt_for_confirmation(f'{on}Open attachments?{off}', False):
                with DevNullRedirect():
                    for url in [
                            a['url'] for a in card.fetch_attachments()
                            if a['url']
                    ]:
                        webbrowser.open(url)
        if re.search(VALID_URL_REGEX, card['name']):
            if prompt_for_confirmation(
                    f'{on}Link in title detected, want to attach it & rename?{off}',
                    True):
                card.title_to_link()
        if self.config.prompt_for_untagged_cards and not card['labels']:
            print(f'{on}No tags on this card yet, want to add some?{off}')
            card.add_labels(self._label_choices)
        commands = {
            'archive': 'mark this card as closed',
            'attach': 'add, delete, or open attachments',
            'change-list': 'move this to a different list on the same board',
            'comment': 'add a comment to this card',
            'delete': 'permanently delete this card',
            'duedate': 'add a due date or change the due date',
            'description': 'change the description of this card (desc)',
            'help': 'display this help output (h)',
            'move': 'move to a different board and list (m)',
            'next': 'move to the next card (n)',
            'open': 'open all links on this card (o)',
            'prev': 'go back to the previous card (p)',
            'print': 're-display this card',
            'rename': 'change title of this card',
            'tag': 'add or remove tags on this card (t)',
            'unarchive': 'mark this card as open',
            'quit': 'exit program',
        }
        command_completer = FuzzyWordCompleter(commands.keys())
        while True:
            user_input = prompt('gtd.py > ', completer=command_completer)
            if user_input in ['q', 'quit']:
                raise GTDException(0)
            elif user_input in ['n', 'next']:
                return True
            elif user_input in ['p', 'prev']:
                return False
            elif user_input == 'print':
                card.fetch()
                self.display.show_card(card)
            elif user_input in ['o', 'open']:
                with DevNullRedirect():
                    for url in [
                            a['url'] for a in card.fetch_attachments()
                            if a['url'] is not None
                    ]:
                        webbrowser.open(url)
            elif user_input in ['desc', 'description']:
                card.change_description()
            elif user_input == 'delete':
                card.delete()
                print('Card deleted')
                return True
            elif user_input == 'attach':
                card.manipulate_attachments()
            elif user_input == 'archive':
                card.set_closed(True)
                print('Card archived')
                return True
            elif user_input == 'unarchive':
                card.set_closed(False)
                print('Card returned to board')
            elif user_input in ['t', 'tag']:
                card.add_labels(self._label_choices)
            elif user_input == 'rename':
                # TODO optional form 'rename New name of card'
                card.rename()
            elif user_input == 'duedate':
                card.set_due_date()
            elif user_input in ['h', 'help']:
                for cname, cdesc in commands.items():
                    print('{0:<16}| {1}{2}{3}'.format(cname, on, cdesc, off))
            elif user_input == 'change-list':
                if card.move_to_list(self._list_choices):
                    return True
            elif user_input in ['m', 'move']:
                self.move_between_boards(card)
            elif user_input == 'comment':
                # TODO Optional form 'comment Contents of a comment'
                new_comment = click.edit(text='<Comment here>',
                                         require_save=True)
                if new_comment:
                    card.comment(new_comment)
                else:
                    click.secho('Change the text & save to post the comment',
                                fg='red')
            else:
                print(
                    f'{on}{user_input}{off} is not a command, type "{on}help{off}" to view available commands'
                )

    @return_on_eof
    def move_between_boards(self, card: Card) -> None:
        boards_by_name = self.connection.boards_by_name()
        board_name = prompt('gtd.py > move > board name? ',
                            completer=FuzzyWordCompleter(
                                boards_by_name.keys()))
        board_id = boards_by_name[board_name]['id']
        lists_json = self.connection.trello.fetch_json(
            f'/boards/{board_id}/lists?cards=none&filter=open&fields=name')
        name_to_listid = {l['name']: l['id'] for l in lists_json}
        list_name = prompt(
            f'gtd.py > move > {board_name} > list name? ',
            completer=FuzzyWordCompleter(name_to_listid.keys()),
        )
        card.change_board(board_id, list_id=name_to_listid[list_name])
        click.secho(f'Changed list to {list_name} on {board_name}', fg='green')