Delete a range OR list of indices
This commit is contained in:
parent
336bb2a371
commit
2abeffe4c5
38
README.md
38
README.md
@ -130,7 +130,9 @@ Please substitute `$version` with the appropriate package version.
|
||||
refresh all titles, if no arguments
|
||||
refresh title of bookmark at N, if only
|
||||
N is specified without any edit options
|
||||
-d, --delete [N] delete bookmark at DB index N
|
||||
-d, --delete [...] delete bookmarks. Valid inputs: either
|
||||
a hyphenated single range (100-200),
|
||||
OR space-separated indices (100 15 200)
|
||||
delete all bookmarks, if no arguments
|
||||
-h, --help show this information and exit
|
||||
|
||||
@ -198,6 +200,9 @@ Please substitute `$version` with the appropriate package version.
|
||||
- If --title, --tag or --comment is passed without argument, clear the corresponding field from DB.
|
||||
- If --url is passed (and --title is omitted), update the title from web using the URL.
|
||||
- If index number is passed without any other options (--url, --title, --tag and --comment), read the URL from DB and update title from web.
|
||||
- **Delete** operation:
|
||||
- When a record is deleted, the last record is moved to the index.
|
||||
- Delete doesn't work with range and indices provided together as arguments. It's an intentional decision to avoid extra sorting, in-range checks and to keep the auto-DB compaction functionality intact.
|
||||
- **Search** works in mysterious ways:
|
||||
- Case-insensitive.
|
||||
- Substrings match (`match` matches `rematched`) for URL, title and tags.
|
||||
@ -206,7 +211,6 @@ Please substitute `$version` with the appropriate package version.
|
||||
- --st : search bookmarks by tag, or show all tags alphabetically.
|
||||
- You can search bookmarks by tag (see [examples](#examples)).
|
||||
- Search results are indexed serially. This index is different from actual database index of a bookmark record which is shown in bold within `[]` after the URL.
|
||||
- Auto DB compaction: when a record is deleted, the last record is moved to the index.
|
||||
- **Encryption** is optional and manual. AES256 algorithm is used. If you choose to use encryption, the database file should be unlocked (-k) before using buku and locked (-l) afterwards. Between these 2 operations, the database file lies unencrypted on the disk, and NOT in memory. Also, note that the database file is *unencrypted on creation*.
|
||||
|
||||
# Examples
|
||||
@ -260,48 +264,52 @@ The last index is moved to the deleted index to keep the DB compact.
|
||||
11. **Delete all** bookmarks:
|
||||
|
||||
$ buku -d
|
||||
12. **Search** bookmarks for **ANY** of the keywords `kernel` and `debugging` in URL, title or tags:
|
||||
12. **Delete** a **range or list** of bookmarks:
|
||||
|
||||
$ buku -d 100-200 // delete bookmarks from index 100 to 200
|
||||
$ buku 100 15 200 // delete bookmarks at indices 100, 15 and 200
|
||||
13. **Search** bookmarks for **ANY** of the keywords `kernel` and `debugging` in URL, title or tags:
|
||||
|
||||
$ buku -s kernel debugging
|
||||
13. **Search** bookmarks with **ALL** the keywords `kernel` and `debugging` in URL, title or tags:
|
||||
14. **Search** bookmarks with **ALL** the keywords `kernel` and `debugging` in URL, title or tags:
|
||||
|
||||
$ buku -S kernel debugging
|
||||
|
||||
14. **Search** bookmarks with **tag** `general kernel concepts`:
|
||||
15. **Search** bookmarks with **tag** `general kernel concepts`:
|
||||
|
||||
$ buku --st general kernel concepts
|
||||
Note the commas (,) before and after the tag. Comma is the tag delimiter in DB.
|
||||
15. List **all unique tags** alphabetically:
|
||||
16. List **all unique tags** alphabetically:
|
||||
|
||||
$ buku --st
|
||||
16. **Encrypt or decrypt** DB with **custom number of iterations** (15) to generate key:
|
||||
17. **Encrypt or decrypt** DB with **custom number of iterations** (15) to generate key:
|
||||
|
||||
$ buku -l 15
|
||||
$ buku -k 15
|
||||
The same number of iterations must be used for one lock & unlock instance. Default is 8.
|
||||
17. **Show details** of bookmark at index 15012014:
|
||||
18. **Show details** of bookmark at index 15012014:
|
||||
|
||||
$ buku -p 15012014
|
||||
18. **Show all** bookmarks with real index from database:
|
||||
19. **Show all** bookmarks with real index from database:
|
||||
|
||||
$ buku -p
|
||||
$ buku -p | more
|
||||
19. **Replace tag** 'old tag' with 'new tag':
|
||||
20. **Replace tag** 'old tag' with 'new tag':
|
||||
|
||||
$ buku -r 'old tag' new tag
|
||||
20. **Delete tag** 'old tag' from DB:
|
||||
21. **Delete tag** 'old tag' from DB:
|
||||
|
||||
$ buku -r 'old tag'
|
||||
21. **Append tags** 'tag 1', 'tag 2' to existing tags of bookmark at index 15012014:
|
||||
22. **Append tags** 'tag 1', 'tag 2' to existing tags of bookmark at index 15012014:
|
||||
|
||||
$ buku -u 15012014 --tag + tag 1, tag 2
|
||||
22. **Open URL** at index 15012014 in browser:
|
||||
23. **Open URL** at index 15012014 in browser:
|
||||
|
||||
$ buku -o 15012014
|
||||
23. To list bookmarks with no title or tags for **bookkeeping**:
|
||||
24. To list bookmarks with no title or tags for **bookkeeping**:
|
||||
|
||||
$ buku -S blank
|
||||
24. More **help**:
|
||||
25. More **help**:
|
||||
|
||||
$ buku
|
||||
$ man buku
|
||||
|
51
buku
51
buku
@ -664,13 +664,23 @@ class BukuDb:
|
||||
self.conn.commit()
|
||||
print('Index %d moved to %d' % (row[0], index))
|
||||
|
||||
def delete_bookmark(self, index):
|
||||
def delete_bookmark(self, index, low=0, high=0, is_range=False):
|
||||
"""Delete a single record or remove the table if index is None
|
||||
|
||||
Params: index to delete
|
||||
"""
|
||||
|
||||
if index == 0: # Remove the table
|
||||
if is_range:
|
||||
try:
|
||||
self.cur.execute('DELETE from bookmarks where id BETWEEN ? AND ?', (low, high))
|
||||
self.conn.commit()
|
||||
print('Bookmarks from index %s to %s deleted' % (low, high))
|
||||
except IndexError:
|
||||
print('Index out of bound')
|
||||
|
||||
for index in range(low, high):
|
||||
self.compactdb(index)
|
||||
elif index == 0: # Remove the table
|
||||
resp = input('ALL bookmarks will be removed. Enter \x1b[1my\x1b[21m to confirm: ')
|
||||
if resp != 'y':
|
||||
print('No bookmarks deleted')
|
||||
@ -1459,12 +1469,14 @@ if __name__ == '__main__':
|
||||
refresh all titles, if no arguments
|
||||
refresh title of bookmark at N, if only
|
||||
N is specified without any edit options
|
||||
-d, --delete [N] delete bookmark at DB index N
|
||||
-d, --delete [...] delete bookmarks. Valid inputs: either
|
||||
a hyphenated single range (100-200),
|
||||
OR space-separated indices (100 15 200)
|
||||
delete all bookmarks, if no arguments
|
||||
-h, --help show this information and exit''')
|
||||
general_group.add_argument('-a', '--add', nargs='+', dest='addurl', metavar=('URL', 'tags'), help=argparse.SUPPRESS)
|
||||
general_group.add_argument('-u', '--update', nargs='*', dest='update', action=CustomUpdateAction, metavar=('N', 'URL tags'), help=argparse.SUPPRESS)
|
||||
general_group.add_argument('-d', '--delete', nargs='?', dest='delete', type=int, const=0, metavar='N', help=argparse.SUPPRESS)
|
||||
general_group.add_argument('-d', '--delete', nargs='*', dest='delete', metavar='N', help=argparse.SUPPRESS)
|
||||
general_group.add_argument('-h', '--help', dest='help', action='store_true', help=argparse.SUPPRESS)
|
||||
|
||||
# Edit options
|
||||
@ -1634,10 +1646,33 @@ if __name__ == '__main__':
|
||||
|
||||
# Delete record(s)
|
||||
if args.delete is not None:
|
||||
if args.delete < 0:
|
||||
printmsg('Index must be >= 0', 'ERROR')
|
||||
bdb.close_quit(1)
|
||||
bdb.delete_bookmark(args.delete)
|
||||
if len(args.delete) == 0:
|
||||
bdb.delete_bookmark(0)
|
||||
elif len(args.delete) == 1 and '-' in args.delete[0]:
|
||||
vals = str(args.delete[0]).split('-')
|
||||
if len(vals) == 2 and is_int(vals[0]) and is_int(vals[1]):
|
||||
if int(vals[0]) == int(vals[1]):
|
||||
bdb.delete_bookmark(int(vals[0]))
|
||||
elif int(vals[0]) < int(vals[1]):
|
||||
bdb.delete_bookmark(0, int(vals[0]), int(vals[1]), True)
|
||||
else:
|
||||
bdb.delete_bookmark(0, int(vals[1]), int(vals[0]), True)
|
||||
else:
|
||||
printmsg('Incorrect range', 'ERROR')
|
||||
bdb.close_quit(1)
|
||||
else:
|
||||
ids = []
|
||||
for idx in args.delete:
|
||||
if idx not in ids:
|
||||
ids += (idx,)
|
||||
|
||||
ids.sort(key=lambda x: int(x), reverse=True)
|
||||
for idx in ids:
|
||||
if is_int(idx):
|
||||
bdb.delete_bookmark(int(idx))
|
||||
else:
|
||||
printmsg('Incorrect index %s' % idx, 'ERROR')
|
||||
bdb.close_quit(1)
|
||||
|
||||
# Search URLs, titles, tags for any keyword
|
||||
if args.sany is not None:
|
||||
|
44
buku.1
44
buku.1
@ -24,6 +24,10 @@ URLs are unique in DB. The same URL cannot be added twice. You can update tags a
|
||||
\fITags\fR:
|
||||
- Comma (',') is the tag delimiter in DB. Any tag cannot have comma(s) in it. Tags are filtered (for unique tags) and sorted.
|
||||
.PP
|
||||
\fIDelete\fR operation:
|
||||
- When a record is deleted, the last record is moved to the index.
|
||||
- Delete doesn't work with range and indices provided together as arguments. It's an intentional decision to avoid extra sorting, in-range checks and to keep the auto-DB compaction functionality intact.
|
||||
.PP
|
||||
\fIUpdate\fR operation:
|
||||
- If --title, --tag or --comment is passed without argument, clear the corresponding field from DB.
|
||||
- If --url is passed (and --title is omitted), update the title from web using the URL.
|
||||
@ -38,8 +42,6 @@ URLs are unique in DB. The same URL cannot be added twice. You can update tags a
|
||||
- You can search bookmarks by tag (see examples below).
|
||||
- Search results are indexed serially. This index is different from actual database index of a bookmark record which is shown in bold within '[]' after the URL.
|
||||
.PP
|
||||
Auto DB compaction: when a record is deleted, the last record is moved to the index.
|
||||
.PP
|
||||
\fIEncryption\fR is optional and manual. AES256 algorithm is used. If you choose to use encryption, the database file should be unlocked (-k) before using buku and locked (-l) afterwards. Between these 2 operations, the database file lies unencrypted on the disk, and NOT in memory. Also, note that the database file is \fBunencrypted on creation\fR.
|
||||
.SH GENERAL OPTIONS
|
||||
.TP
|
||||
@ -55,12 +57,8 @@ in DB. If
|
||||
.I N
|
||||
and other options are omitted, all titles are refreshed from the web. Works with update modifiers for the fields url, title, tag and comment. If only N is passed without any edit options, title is fetched and updated (if not empty).
|
||||
.TP
|
||||
.BI \-d " " \--delete " [N]"
|
||||
Delete bookmark at index
|
||||
.I N
|
||||
in DB (from -p output). The last record is moved to the removed index. If
|
||||
.I N
|
||||
is omitted, all records are deleted from the DB.
|
||||
.BI \-d " " \--delete " [...]"
|
||||
Delete bookmarks. You can either provide a single hyphenated range (e.g. 100-200) or a space-separated list of indices (e.g. 5 6 23 4 110 45). Note that range and list don't work together.
|
||||
.TP
|
||||
.BI \-h " " \--help
|
||||
Show program help and exit.
|
||||
@ -272,20 +270,28 @@ The last index is moved to the deleted index to keep the DB compact.
|
||||
.B buku -d
|
||||
.PP
|
||||
.IP 12. 4
|
||||
\fBDelete\fR a \fBrange or list\fR of bookmarks:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B $ buku -d 100-200 // delete bookmarks from index 100 to 200
|
||||
.B $ buku 100 15 200 // delete bookmarks at indices 100, 15 and 200
|
||||
.PP
|
||||
.IP 13. 4
|
||||
\fBSearch\fR bookmarks for \fBANY\fR of the keywords 'kernel' and 'debugging' in URL, title or tags:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku -s kernel debugging
|
||||
.PP
|
||||
.IP 13. 4
|
||||
.IP 14. 4
|
||||
\fBSearch\fR bookmarks with \fBALL\fR the keywords 'kernel' and 'debugging' in URL, title or tags:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku -S kernel debugging
|
||||
.PP
|
||||
.IP 14. 4
|
||||
.IP 15. 4
|
||||
\fBSearch\fR bookmarks with \fBtag\fR 'general kernel concepts':
|
||||
.PP
|
||||
.EX
|
||||
@ -296,14 +302,14 @@ The last index is moved to the deleted index to keep the DB compact.
|
||||
.IP "" 4
|
||||
Note the commas (,) before and after the tag. Comma is the tag delimiter in DB.
|
||||
.PP
|
||||
.IP 15. 4
|
||||
.IP 16. 4
|
||||
List \fBall unique tags\fR alphabetically:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku --st
|
||||
.PP
|
||||
.IP 16. 4
|
||||
.IP 17. 4
|
||||
\fBEncrypt or decrypt\fR DB with \fBcustom number of iterations\fR (15) to generate key:
|
||||
.PP
|
||||
.EX
|
||||
@ -316,14 +322,14 @@ List \fBall unique tags\fR alphabetically:
|
||||
.IP "" 4
|
||||
The same number of iterations must be used for one lock & unlock instance. Default is 8.
|
||||
.PP
|
||||
.IP 17. 4
|
||||
.IP 18. 4
|
||||
\fBShow details\fR of bookmark at index 15012014:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku -p 15012014
|
||||
.PP
|
||||
.IP 18. 4
|
||||
.IP 19. 4
|
||||
\fBShow all\fR bookmarks with real index from database:
|
||||
.PP
|
||||
.EX
|
||||
@ -331,35 +337,35 @@ The same number of iterations must be used for one lock & unlock instance. Defau
|
||||
.B buku -p
|
||||
.B buku -p | more
|
||||
.PP
|
||||
.IP 19. 4
|
||||
.IP 20. 4
|
||||
\fBReplace tag\fR 'old tag' with 'new tag':
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku -r 'old tag' new tag
|
||||
.PP
|
||||
.IP 20. 4
|
||||
.IP 21. 4
|
||||
\fBDelete tag\fR 'old tag' from DB:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku -r 'old tag'
|
||||
.PP
|
||||
.IP 21. 4
|
||||
.IP 22. 4
|
||||
\fBAppend tags\fR 'tag 1', 'tag 2' to existing tags of bookmark at index 15012014:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku -u 15012014 --tag + tag 1, tag 2
|
||||
.PP
|
||||
.IP 22. 4
|
||||
.IP 23. 4
|
||||
\fBOpen URL\fR at index 15012014 in browser:
|
||||
.PP
|
||||
.EX
|
||||
.IP
|
||||
.B buku -o 15012014
|
||||
.PP
|
||||
.IP 23. 4
|
||||
.IP 24. 4
|
||||
To list bookmarks with no title or tags for \fBbookkeeping\fR:
|
||||
.PP
|
||||
.EX
|
||||
|
Loading…
Reference in New Issue
Block a user