Fix #253: Localize tag error check, fix tag exclusion

This commit is contained in:
Arun Prakash Jana 2018-03-22 19:51:07 +05:30
parent 21e32d1ed3
commit 1c5695fdbd
No known key found for this signature in database
GPG Key ID: A75979F35C080412
3 changed files with 39 additions and 13 deletions

View File

@ -365,9 +365,9 @@ PROMPT KEYS:
20. **Search** for bookmarks matching **ALL** of the tags `kernel`, `debugging`, `general kernel concepts`: 20. **Search** for bookmarks matching **ALL** of the tags `kernel`, `debugging`, `general kernel concepts`:
$ buku --stag kernel + debugging + general kernel concepts $ buku --stag kernel + debugging + general kernel concepts
21. **Search** for bookmarks matching both the tags `kernel` and `debugging`, but **excluding** bookmarks matching the tag `general kernel concepts`: 21. **Search** for bookmarks matching both the tags `kernel` and `debugging`, but **excluding** bookmarks matching the tags `general kernel concepts` and `books`:
$ buku --stag kernel + debugging - general kernel concepts $ buku --stag kernel + debugging - general kernel concepts, books
22. List **all unique tags** alphabetically: 22. List **all unique tags** alphabetically:
$ buku --stag $ buku --stag

4
buku.1
View File

@ -628,11 +628,11 @@ The last index is moved to the deleted index to keep the DB compact.
.EE .EE
.PP .PP
.IP 21. 4 .IP 21. 4
\fBSearch\fR for bookmarks matching both the tags `kernel` and `debugging`, but \fBexcluding\fR bookmarks matching the tag 'general kernel concepts': \fBSearch\fR for bookmarks matching both the tags `kernel` and `debugging`, but \fBexcluding\fR bookmarks matching the tags 'general kernel concepts' and 'books':
.PP .PP
.EX .EX
.IP .IP
.B buku --stag kernel + debugging - general kernel concepts .B buku --stag kernel + debugging - general kernel concepts, books
.IP 22. 4 .IP 22. 4
List \fBall unique tags\fR alphabetically: List \fBall unique tags\fR alphabetically:
.PP .PP

44
buku.py
View File

@ -1201,12 +1201,14 @@ class BukuDb:
List of search results, or None if no matches. List of search results, or None if no matches.
""" """
# do not allow combination of search logics tags, search_operator, excluded_tags = prep_tag_search(tags)
if ' + ' in tags and ',' in tags: if search_operator is None:
logerr("Cannot use both '+' and ',' in same search") logerr("Cannot use both '+' and ',' in same search")
return None return None
tags, search_operator, excluded_tags = prep_tag_search(tags) logdbg('tags: %s', tags)
logdbg('search_operator: %s', search_operator)
logdbg('excluded_tags: %s', excluded_tags)
if search_operator == 'AND': if search_operator == 'AND':
query = "SELECT id, url, metadata, tags, desc FROM bookmarks WHERE tags LIKE '%' || ? || '%' " query = "SELECT id, url, metadata, tags, desc FROM bookmarks WHERE tags LIKE '%' || ? || '%' "
@ -2949,6 +2951,22 @@ def prep_tag_search(tags):
a regex string of tags or None if ' - ' delimiter not in tags). a regex string of tags or None if ' - ' delimiter not in tags).
""" """
exclude_only = False
# tags may begin with `- ` if only exclusion list is provided
if tags.startswith('- '):
tags = ' ' + tags
exclude_only = True
# tags may start with `+ ` etc., tricky test case
if tags.startswith(('+ ', ', ')):
tags = tags[2:]
# tags may end with ` -` etc., tricky test case
if tags.endswith((' -', ' +', ' ,')):
tags = tags[:-2]
# tag exclusion list can be separated by comma (,), so split it first
excluded_tags = None excluded_tags = None
if ' - ' in tags: if ' - ' in tags:
tags, excluded_tags = tags.split(' - ', 1) tags, excluded_tags = tags.split(' - ', 1)
@ -2957,13 +2975,21 @@ def prep_tag_search(tags):
# join with pipe to construct regex string # join with pipe to construct regex string
excluded_tags = '|'.join(excluded_taglist) excluded_tags = '|'.join(excluded_taglist)
search_operator = 'OR' if exclude_only:
tag_delim = ',' search_operator = 'OR'
if ' + ' in tags: tags = ['']
search_operator = 'AND' else:
tag_delim = ' + ' # do not allow combination of search logics in tag inclusion list
if ' + ' in tags and ',' in tags:
return None, None, None
tags = [delim_wrap(t.strip()) for t in tags.split(tag_delim)] search_operator = 'OR'
tag_delim = ','
if ' + ' in tags:
search_operator = 'AND'
tag_delim = ' + '
tags = [delim_wrap(t.strip()) for t in tags.split(tag_delim)]
return tags, search_operator, excluded_tags return tags, search_operator, excluded_tags