diff --git a/jrnl/Entry.py b/jrnl/Entry.py index 32c76b12..e32a2c6c 100644 --- a/jrnl/Entry.py +++ b/jrnl/Entry.py @@ -6,12 +6,13 @@ import textwrap from datetime import datetime class Entry: - def __init__(self, journal, date=None, title="", body=""): + def __init__(self, journal, date=None, title="", body="", starred=False): self.journal = journal # Reference to journal mainly to access it's config self.date = date or datetime.now() self.title = title.strip() self.body = body.strip() self.tags = self.parse_tags() + self.starred = starred def parse_tags(self): fulltext = " ".join([self.title, self.body]).lower() @@ -23,6 +24,8 @@ class Entry: """Returns a string representation of the entry to be written into a journal file.""" date_str = self.date.strftime(self.journal.config['timeformat']) title = date_str + " " + self.title + if self.starred: + title += " *" body = self.body.strip() return u"{title}{sep}{body}\n".format( diff --git a/jrnl/Journal.py b/jrnl/Journal.py index ecc9a4d7..315919c0 100644 --- a/jrnl/Journal.py +++ b/jrnl/Journal.py @@ -133,12 +133,20 @@ class Journal(object): for line in journal.splitlines(): try: # try to parse line as date => new entry begins + line = line.strip() new_date = datetime.strptime(line[:date_length], self.config['timeformat']) # parsing successfull => save old entry and create new one if new_date and current_entry: entries.append(current_entry) - current_entry = Entry.Entry(self, date=new_date, title=line[date_length+1:]) + + if line.endswith("*"): + starred = True + line = line[:-1] + else: + starred = False + + current_entry = Entry.Entry(self, date=new_date, title=line[date_length+1:], starred=starred) except ValueError: # Happens when we can't parse the start of the line as an date. # In this case, just append line to our body. @@ -196,7 +204,7 @@ class Journal(object): if n: self.entries = self.entries[-n:] - def filter(self, tags=[], start_date=None, end_date=None, strict=False, short=False): + def filter(self, tags=[], start_date=None, end_date=None, starred=False, strict=False, short=False): """Removes all entries from the journal that don't match the filter. tags is a list of tags, each being a string that starts with one of the @@ -204,6 +212,8 @@ class Journal(object): start_date and end_date define a timespan by which to filter. + starred limits journal to starred entries + If strict is True, all tags must be present in an entry. If false, the entry is kept if any tag is present.""" self.search_tags = set([tag.lower() for tag in tags]) @@ -214,6 +224,7 @@ class Journal(object): result = [ entry for entry in self.entries if (not tags or tagged(entry.tags)) + and (not starred or entry.starred) and (not start_date or entry.date > start_date) and (not end_date or entry.date < end_date) ] @@ -264,7 +275,7 @@ class Journal(object): If a date is given, it will parse and use this, otherwise scan for a date in the input first.""" raw = raw.replace('\\n ', '\n').replace('\\n', '\n') - + starred = False # Split raw text into title and body title_end = len(raw) for separator in ["\n", ". ", "? ", "! "]: @@ -273,15 +284,22 @@ class Journal(object): title_end = sep_pos title = raw[:title_end+1] body = raw[title_end+1:].strip() + starred = False if not date: if title.find(":") > 0: + starred = "*" in title[:title.find(":")] date = self.parse_date(title[:title.find(":")]) - if date: # Parsed successfully, strip that from the raw text + if date or starred: # Parsed successfully, strip that from the raw text title = title[title.find(":")+1:].strip() + elif title.strip().startswith("*"): + starred = True + title = title[1:].strip() + elif title.strip().endswith("*"): + starred = True + title = title[:-1].strip() if not date: # Still nothing? Meh, just live in the moment. date = self.parse_date("now") - - entry = Entry.Entry(self, date, title, body) + entry = Entry.Entry(self, date, title, body, starred=starred) self.entries.append(entry) if sort: self.sort() diff --git a/jrnl/jrnl.py b/jrnl/jrnl.py index 7b98a42e..ec37288e 100755 --- a/jrnl/jrnl.py +++ b/jrnl/jrnl.py @@ -39,6 +39,7 @@ def parse_args(args=None): reading.add_argument('-from', dest='start_date', metavar="DATE", help='View entries after this date') reading.add_argument('-until', '-to', dest='end_date', metavar="DATE", help='View entries before this date') reading.add_argument('-and', dest='strict', action="store_true", help='Filter by tags using AND (default: OR)') + reading.add_argument('-starred', dest='starred', action="store_true", help='Show only starred entries') reading.add_argument('-n', dest='limit', default=None, metavar="N", help='Shows the last n entries matching the filter', nargs="?", type=int) reading.add_argument('-short', dest='short', action="store_true", help='Show only titles or line containing the search tags') @@ -59,10 +60,10 @@ def guess_mode(args, config): if args.decrypt is not False or args.encrypt is not False or args.export is not False or args.tags or args.delete_last: compose = False export = True - elif args.start_date or args.end_date or args.limit or args.strict or args.short: + elif any((args.start_date, args.end_date, args.limit, args.strict, args.short, args.starred)): # Any sign of displaying stuff? compose = False - elif not args.date and args.text and all(word[0] in config['tagsymbols'] for word in " ".join(args.text).split()): + elif args.text and all(word[0] in config['tagsymbols'] for word in " ".join(args.text).split()): # No date and only tags? compose = False @@ -180,7 +181,8 @@ def cli(manual_args=None): journal.filter(tags=args.text, start_date=args.start_date, end_date=args.end_date, strict=args.strict, - short=args.short) + short=args.short, + starred=args.starred) journal.limit(args.limit) # Reading mode