Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions google_keep_tasks/cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import click
from click._compat import iteritems


def choices_prompt(text, choices, default_choice):
Expand Down Expand Up @@ -32,7 +31,7 @@ def make_formatter(self):

class GkeepGroup(click.Group):
def make_context(self, info_name, args, parent=None, **extra):
for key, value in iteritems(self.context_settings):
for key, value in self.context_settings.items():
if key not in extra:
extra[key] = value
ctx = GkeepContext(self, info_name=info_name, parent=parent, **extra)
Expand Down
101 changes: 97 additions & 4 deletions google_keep_tasks/notes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import click
import gkeepapi
import sys
import re

from gkeepapi.node import List

from google_keep_tasks.cli import GkeepGroup
from google_keep_tasks.exceptions import InvalidColor
Expand All @@ -19,6 +22,8 @@
}
COLOR_NAMES = [color.name.lower() for color in gkeepapi.node.ColorValue]

placeholder = '__placeholder__'


def get_color(color):
if not color:
Expand Down Expand Up @@ -71,6 +76,21 @@ def query_params(keep, **kwargs):
set(x.labels.all()) == set(labels) if labels is not None else None]))
return kwargs

def format_note_item(item):
return u'%s%s %s' % (
' ' if item.indented else '',
u'- [x]' if item.checked else u'- [ ]',
item.text
)

def format_note(note):
if not isinstance(note, List):
return note.text
text = ""
for item in note.items:
text += "%s | %s\n" % (item.id.ljust(30), format_note_item(item))
return text


def print_note(note):
params = COLORS.get(note.color, {})
Expand All @@ -80,15 +100,82 @@ def print_note(note):
click.echo(click.style('"' * len(note_id), **params))
if note.title:
click.echo(click.style(note.title, bold=True))
click.echo(note.text)
click.echo('-' * len(note_id))
click.echo(format_note(note))
click.echo('-' * len(note_id))
if note.labels:
click.echo()
click.echo(' '.join(click.style('[{}]'.format(label.name), underline=True, bold=True)
for label in note.labels.all()))
click.echo(click.style('"' * len(note_id), **params))
click.echo('\n')


def edit_note_checkboxes(note):
text = click.edit(format_note(note)).strip()
lines = text.split("\n")
regex = re.compile(r"([\w.]*) *\| ( *)- \[(x| )\] (.*)")

last_old_note = 'top'
current_items = []
for line in lines:
id, indent, check_mark, content = regex.match(line).groups()
found = list(filter(lambda item: item.id == id, note.items))
old_note = found[0] if len(found) > 0 else None
indented = len(indent) > 1
checked = check_mark == 'x'
current_items.append({
'id': id,
'previous': last_old_note,
'old': old_note,
'indented': indented,
'checked': checked,
'content': content
})
last_old_note = old_note

# Deletion
for item in note.items:
if item.id not in [parts['id'] for parts in current_items]:
item.delete()
print('Deleted "%s"' % item.text)

last_added = None
for parts in current_items:
previous = parts['previous'] if parts['previous'] != None else last_added

# Addition
if parts['old'] == None:
sort = int(previous.sort) - 1 if previous != None and previous != 'top' else gkeepapi.node.NewListItemPlacementValue.Top
added = note.add(parts['content'], parts['checked'], sort)
if parts['indented']:
previous.indent(added)
last_added = added
print('Added "%s"' % parts['content'])

# Modification
else:
updated = False
if parts['old'].indented and not parts['indented']:
if previous != None:
previous.dedent(parts['old'])
updated = True
if not parts['old'].indented and parts['indented']:
if previous != None:
previous.indent(parts['old'])
updated = True
if parts['old'].checked and not parts['checked']:
parts['old'].checked = False
updated = True
if not parts['old'].checked and parts['checked']:
parts['old'].checked = True
updated = True
if parts['old'].text != parts['content']:
parts['old'].text = parts['content']
updated = True
if updated:
print('Updated "%s"' % parts['content'])


def get_note_instance(keep, id=None, **kwargs):
if id:
note = keep.get(id)
Expand Down Expand Up @@ -199,7 +286,7 @@ def get_note(ctx, **kwargs):
@notes.command('edit', options_metavar='[options]')
@click.option('--title', default=None, required=False, metavar='<new title>',
help='Change the note title')
@click.option('--text', default=None, required=False, metavar='<new_note_content>',
@click.option('--text', default=None, required=False, is_flag=False, flag_value=placeholder, metavar='[new_note_content]',
help='Change the note text')
@click.option('--filter-id', default=None, required=False, metavar='<id>',
help='Filter by id note. This is the preferred way to ensure editing the correct note')
Expand Down Expand Up @@ -231,6 +318,12 @@ def edit_note(ctx, title, text, color, labels, archived, pinned, filter_id, filt
if not note:
click.echo('The note was not found', err=True)
sys.exit(2)
if text == placeholder:
if isinstance(note, List):
edit_note_checkboxes(note)
text = None
else:
text = click.edit(note.text).strip()
updated = {}
boolean_nullables = ['archived', 'pinned'] # 3 state params
for param in ['title', 'text', 'color', 'labels'] + boolean_nullables:
Expand Down Expand Up @@ -271,4 +364,4 @@ def delete_note(ctx, **kwargs):
click.echo('Note with title "{}" deleted.'.format(note.title))
else:
click.echo('The note was not found', err=True)
sys.exit(2)
sys.exit(2)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
gkeepapi>=0.10.6
click
click>=8.0.0