Support positional arguments as search keywords
1. All search options are now boolean 2. -s is the default search option
This commit is contained in:
parent
ab49a7242a
commit
bb8e683f93
22
README.md
22
README.md
@ -132,6 +132,9 @@ usage: buku [OPTIONS] [KEYWORD [KEYWORD ...]]
|
|||||||
|
|
||||||
Powerful command-line bookmark manager. Your mini web!
|
Powerful command-line bookmark manager. Your mini web!
|
||||||
|
|
||||||
|
POSITIONAL ARGUMENTS:
|
||||||
|
KEYWORD search keywords
|
||||||
|
|
||||||
GENERAL OPTIONS:
|
GENERAL OPTIONS:
|
||||||
-a, --add URL [tag, ...]
|
-a, --add URL [tag, ...]
|
||||||
bookmark URL with comma-separated tags
|
bookmark URL with comma-separated tags
|
||||||
@ -168,17 +171,16 @@ EDIT OPTIONS:
|
|||||||
N=0: mutable (default), N=1: immutable
|
N=0: mutable (default), N=1: immutable
|
||||||
|
|
||||||
SEARCH OPTIONS:
|
SEARCH OPTIONS:
|
||||||
-s, --sany keyword [...]
|
-s, --sany find records with ANY search keyword
|
||||||
find records with ANY search keyword
|
this is the default search option
|
||||||
-S, --sall keyword [...]
|
-S, --sall find records with ALL search keywords
|
||||||
find records with ALL search keywords
|
|
||||||
special keywords -
|
special keywords -
|
||||||
"blank": entries with empty title/tag
|
"blank": entries with empty title/tag
|
||||||
"immutable": entries with locked title
|
"immutable": entries with locked title
|
||||||
--deep match substrings ('pen' matches 'opens')
|
--deep match substrings ('pen' matches 'opens')
|
||||||
--sreg expression run a regex search
|
--sreg run a regex search
|
||||||
--stag [...] search bookmarks by a tag
|
--stag search bookmarks by a tag
|
||||||
list all tags, if no arguments
|
list all tags, if no search keywords
|
||||||
|
|
||||||
ENCRYPTION OPTIONS:
|
ENCRYPTION OPTIONS:
|
||||||
-l, --lock [N] encrypt DB file with N (> 0, default 8)
|
-l, --lock [N] encrypt DB file with N (> 0, default 8)
|
||||||
@ -198,7 +200,7 @@ POWER TOYS:
|
|||||||
accepts indices and ranges
|
accepts indices and ranges
|
||||||
show all bookmarks, if no arguments
|
show all bookmarks, if no arguments
|
||||||
-f, --format N limit fields in -p or Json search output
|
-f, --format N limit fields in -p or Json search output
|
||||||
1: URL, 2: URL and tag, 3: title
|
N=1: URL, N=2: URL and tag, N=3: title
|
||||||
-r, --replace oldtag [newtag ...]
|
-r, --replace oldtag [newtag ...]
|
||||||
replace oldtag with newtag everywhere
|
replace oldtag with newtag everywhere
|
||||||
delete oldtag, if no newtag
|
delete oldtag, if no newtag
|
||||||
@ -213,7 +215,7 @@ POWER TOYS:
|
|||||||
--expand N/URL expand a tny.im shortened url
|
--expand N/URL expand a tny.im shortened url
|
||||||
--tacit reduce verbosity
|
--tacit reduce verbosity
|
||||||
--threads N max network connections in full refresh
|
--threads N max network connections in full refresh
|
||||||
default 4, min 1, max 10
|
default N=4, min N=1, max N=10
|
||||||
--upstream check latest upstream version available
|
--upstream check latest upstream version available
|
||||||
-z, --debug show debug information and verbose logs
|
-z, --debug show debug information and verbose logs
|
||||||
|
|
||||||
@ -247,7 +249,7 @@ SYMBOLS:
|
|||||||
- **Search** works in mysterious ways:
|
- **Search** works in mysterious ways:
|
||||||
- Case-insensitive.
|
- Case-insensitive.
|
||||||
- Matches words in URL, title and tags.
|
- Matches words in URL, title and tags.
|
||||||
- --sany : match any of the keywords in URL, title or tags.
|
- --sany : match any of the keywords in URL, title or tags. Default search option.
|
||||||
- --sall : match all the keywords in URL, title or tags.
|
- --sall : match all the keywords in URL, title or tags.
|
||||||
- --deep : match **substrings** (`match` matches `rematched`) in URL, title and tags.
|
- --deep : match **substrings** (`match` matches `rematched`) in URL, title and tags.
|
||||||
- --sreg : match a regular expression (ignores --deep).
|
- --sreg : match a regular expression (ignores --deep).
|
||||||
|
4
buku.1
4
buku.1
@ -60,7 +60,7 @@ Bookmarks with immutable titles are listed with bold '(L)' after the URL.
|
|||||||
\fBSearch\fR works in mysterious ways:
|
\fBSearch\fR works in mysterious ways:
|
||||||
- Case-insensitive.
|
- Case-insensitive.
|
||||||
- Matches words in URL, title and tags.
|
- Matches words in URL, title and tags.
|
||||||
- --sany : match any of the keywords in URL, title or tags.
|
- --sany : match any of the keywords in URL, title or tags. Default search option.
|
||||||
- --sall : match all the keywords in URL, title or tags.
|
- --sall : match all the keywords in URL, title or tags.
|
||||||
- --deep : match \fBsubstrings\fR (`match` matches `rematched`) in URL, title and tags.
|
- --deep : match \fBsubstrings\fR (`match` matches `rematched`) in URL, title and tags.
|
||||||
- --sreg : match a regular expression (ignores --deep).
|
- --sreg : match a regular expression (ignores --deep).
|
||||||
@ -110,6 +110,8 @@ Set the title of a bookmark immutable during updates. Works with --add, --update
|
|||||||
.TP
|
.TP
|
||||||
.BI \-s " " \--sany " keyword [...]"
|
.BI \-s " " \--sany " keyword [...]"
|
||||||
Search bookmarks with ANY of the keyword(s) in URL, title or tags and show the results. Prompts to enter result number to open in browser. Note that the sequential result index is not the DB index. The DB index is shown in bold within '[]' after the URL.
|
Search bookmarks with ANY of the keyword(s) in URL, title or tags and show the results. Prompts to enter result number to open in browser. Note that the sequential result index is not the DB index. The DB index is shown in bold within '[]' after the URL.
|
||||||
|
.br
|
||||||
|
This is the default search option for positional arguments if no other search option is specified.
|
||||||
.TP
|
.TP
|
||||||
.BI \-S " " \--sall " keyword [...]"
|
.BI \-S " " \--sall " keyword [...]"
|
||||||
Search bookmarks with ALL keywords in URL, title or tags and show the results. Behaviour same as --sany.
|
Search bookmarks with ALL keywords in URL, title or tags and show the results. Behaviour same as --sany.
|
||||||
|
67
buku.py
67
buku.py
@ -887,6 +887,9 @@ class BukuDb:
|
|||||||
:return: search results, or None, if no matches
|
:return: search results, or None, if no matches
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
if not keywords:
|
||||||
|
return None
|
||||||
|
|
||||||
qry = 'SELECT id, url, metadata, tags, desc FROM bookmarks WHERE'
|
qry = 'SELECT id, url, metadata, tags, desc FROM bookmarks WHERE'
|
||||||
# Deep query string
|
# Deep query string
|
||||||
q1 = "(tags LIKE ('%' || ? || '%') OR URL LIKE ('%' || ? || '%') OR \
|
q1 = "(tags LIKE ('%' || ? || '%') OR URL LIKE ('%' || ? || '%') OR \
|
||||||
@ -941,11 +944,7 @@ class BukuDb:
|
|||||||
logerr(e)
|
logerr(e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
results = self.cur.fetchall()
|
return self.cur.fetchall()
|
||||||
if len(results) == 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
def search_by_tag(self, tag):
|
def search_by_tag(self, tag):
|
||||||
'''Search and list bookmarks with a tag
|
'''Search and list bookmarks with a tag
|
||||||
@ -960,11 +959,7 @@ class BukuDb:
|
|||||||
logdbg('query: "%s", args: %s', query, tag)
|
logdbg('query: "%s", args: %s', query, tag)
|
||||||
|
|
||||||
self.cur.execute(query, (tag,))
|
self.cur.execute(query, (tag,))
|
||||||
results = self.cur.fetchall()
|
return self.cur.fetchall()
|
||||||
if len(results) == 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
def compactdb(self, index, delay_commit=False):
|
def compactdb(self, index, delay_commit=False):
|
||||||
'''When an entry at index is deleted, move the
|
'''When an entry at index is deleted, move the
|
||||||
@ -2207,13 +2202,18 @@ def main():
|
|||||||
|
|
||||||
# Setup custom argument parser
|
# Setup custom argument parser
|
||||||
argparser = ExtendedArgumentParser(
|
argparser = ExtendedArgumentParser(
|
||||||
description='Powerful command-line bookmark manager. Your mini web!',
|
description='''Powerful command-line bookmark manager. Your mini web!
|
||||||
|
|
||||||
|
POSITIONAL ARGUMENTS:
|
||||||
|
KEYWORD search keywords''',
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
usage='''buku [OPTIONS] [KEYWORD [KEYWORD ...]]''',
|
usage='''buku [OPTIONS] [KEYWORD [KEYWORD ...]]''',
|
||||||
add_help=False
|
add_help=False
|
||||||
)
|
)
|
||||||
HIDE = argparse.SUPPRESS
|
HIDE = argparse.SUPPRESS
|
||||||
|
|
||||||
|
argparser.add_argument('keywords', nargs='*', metavar='KEYWORD', help=HIDE)
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
# GENERAL OPTIONS GROUP
|
# GENERAL OPTIONS GROUP
|
||||||
# ---------------------
|
# ---------------------
|
||||||
@ -2277,23 +2277,22 @@ def main():
|
|||||||
|
|
||||||
search_grp = argparser.add_argument_group(
|
search_grp = argparser.add_argument_group(
|
||||||
title='SEARCH OPTIONS',
|
title='SEARCH OPTIONS',
|
||||||
description=''' -s, --sany keyword [...]
|
description=''' -s, --sany find records with ANY search keyword
|
||||||
find records with ANY search keyword
|
this is the default search option
|
||||||
-S, --sall keyword [...]
|
-S, --sall find records with ALL search keywords
|
||||||
find records with ALL search keywords
|
|
||||||
special keywords -
|
special keywords -
|
||||||
"blank": entries with empty title/tag
|
"blank": entries with empty title/tag
|
||||||
"immutable": entries with locked title
|
"immutable": entries with locked title
|
||||||
--deep match substrings ('pen' matches 'opens')
|
--deep match substrings ('pen' matches 'opens')
|
||||||
--sreg expression run a regex search
|
--sreg run a regex search
|
||||||
--stag [...] search bookmarks by a tag
|
--stag search bookmarks by a tag
|
||||||
list all tags, if no arguments''')
|
list all tags, if no search keywords''')
|
||||||
addarg = search_grp.add_argument
|
addarg = search_grp.add_argument
|
||||||
addarg('-s', '--sany', nargs='+', help=HIDE)
|
addarg('-s', '--sany', action='store_true', help=HIDE)
|
||||||
addarg('-S', '--sall', nargs='+', help=HIDE)
|
addarg('-S', '--sall', action='store_true', help=HIDE)
|
||||||
addarg('--sreg', nargs=1, help=HIDE)
|
addarg('--sreg', action='store_true', help=HIDE)
|
||||||
addarg('--deep', action='store_true', help=HIDE)
|
addarg('--deep', action='store_true', help=HIDE)
|
||||||
addarg('--stag', nargs='*', help=HIDE)
|
addarg('--stag', action='store_true', help=HIDE)
|
||||||
|
|
||||||
# ------------------------
|
# ------------------------
|
||||||
# ENCRYPTION OPTIONS GROUP
|
# ENCRYPTION OPTIONS GROUP
|
||||||
@ -2326,7 +2325,7 @@ def main():
|
|||||||
accepts indices and ranges
|
accepts indices and ranges
|
||||||
show all bookmarks, if no arguments
|
show all bookmarks, if no arguments
|
||||||
-f, --format N limit fields in -p or Json search output
|
-f, --format N limit fields in -p or Json search output
|
||||||
1: URL, 2: URL and tag, 3: title
|
N=1: URL, N=2: URL and tag, N=3: title
|
||||||
-r, --replace oldtag [newtag ...]
|
-r, --replace oldtag [newtag ...]
|
||||||
replace oldtag with newtag everywhere
|
replace oldtag with newtag everywhere
|
||||||
delete oldtag, if no newtag
|
delete oldtag, if no newtag
|
||||||
@ -2341,7 +2340,7 @@ def main():
|
|||||||
--expand N/URL expand a tny.im shortened url
|
--expand N/URL expand a tny.im shortened url
|
||||||
--tacit reduce verbosity
|
--tacit reduce verbosity
|
||||||
--threads N max network connections in full refresh
|
--threads N max network connections in full refresh
|
||||||
default 4, min 1, max 10
|
default N=4, min N=1, max N=10
|
||||||
--upstream check latest upstream version available
|
--upstream check latest upstream version available
|
||||||
-z, --debug show debug information and verbose logs''')
|
-z, --debug show debug information and verbose logs''')
|
||||||
addarg = power_grp.add_argument
|
addarg = power_grp.add_argument
|
||||||
@ -2455,22 +2454,24 @@ def main():
|
|||||||
search_opted = True
|
search_opted = True
|
||||||
update_search_results = False
|
update_search_results = False
|
||||||
|
|
||||||
if args.sany is not None:
|
if args.sany:
|
||||||
# Search URLs, titles, tags for any keyword
|
# Search URLs, titles, tags for any keyword
|
||||||
search_results = bdb.searchdb(args.sany, False, args.deep)
|
search_results = bdb.searchdb(args.keywords, False, args.deep)
|
||||||
elif args.sall is not None:
|
elif args.sall:
|
||||||
# Search URLs, titles, tags with all keywords
|
# Search URLs, titles, tags with all keywords
|
||||||
search_results = bdb.searchdb(args.sall, True, args.deep)
|
search_results = bdb.searchdb(args.keywords, True, args.deep)
|
||||||
elif args.sreg is not None:
|
elif args.sreg:
|
||||||
# Run a regular expression search
|
# Run a regular expression search
|
||||||
search_results = bdb.searchdb(args.sreg, regex=True)
|
search_results = bdb.searchdb(args.keywords, regex=True)
|
||||||
elif args.stag is not None:
|
elif args.stag:
|
||||||
# Search bookmarks by tag
|
# Search bookmarks by tag
|
||||||
if len(args.stag):
|
if args.keywords:
|
||||||
search_results = bdb.search_by_tag(' '.join(args.stag))
|
search_results = bdb.search_by_tag(' '.join(args.keywords))
|
||||||
else:
|
else:
|
||||||
# Use sub prompt to list all tags
|
# Use sub prompt to list all tags
|
||||||
prompt(bdb, None, args.noprompt, subprompt=True)
|
prompt(bdb, None, args.noprompt, subprompt=True)
|
||||||
|
elif args.keywords:
|
||||||
|
search_results = bdb.searchdb(args.keywords, False, args.deep)
|
||||||
else:
|
else:
|
||||||
search_opted = False
|
search_opted = False
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user