bmc/bmc.py

270 lines
10 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import os
import sys
from backend import commands
from backend import tools
from backend.config import Config
# TODO: Handle config
# Load EDITOR variable
EDITOR = os.environ.get("EDITOR")
def file_or_id_from_args(args):
"""
Helper function to parse provided args to check if the argument is a \
file or an identifier.
"""
return "id" if args.id else "file" if args.file else None
def parse_args():
"""
Build a parser and parse arguments of command line.
:returns: Parsed arguments from the parser.
"""
parser = argparse.ArgumentParser(
description="A bibliography management tool.")
parser.add_argument("-c", "--config", default=None,
help="path to a custom config dir.")
subparsers = parser.add_subparsers(help="sub-command help", dest='command')
subparsers.required = True # Fix for Python 3.3.5
parser_download = subparsers.add_parser('download', help="download help")
parser_download.add_argument('-m', '--manual', default=False,
action='store_true',
help="disable auto-download of bibtex")
parser_download.add_argument('-y', default=False,
help="Confirm all")
parser_download.add_argument('--tag', default='',
help="Tag")
parser_download.add_argument('--keep', default=False,
help="Do not remove the file")
parser_download.add_argument('url', nargs='+',
help="url of the file to import")
parser_download.set_defaults(func='download')
parser_import = subparsers.add_parser('import', help="import help")
parser_import.add_argument('-m', '--manual', default=False,
action='store_true',
help="disable auto-download of bibtex")
parser_import.add_argument('-y', default=False,
help="Confirm all")
parser_import.add_argument('--tag', default='', help="Tag")
parser_import.add_argument('--in-place', default=False,
dest="inplace", action='store_true',
help="Leave the imported file in place",)
parser_import.add_argument('file', nargs='+',
help="path to the file to import")
parser_import.add_argument('--skip', nargs='+',
help="path to files to skip", default=[])
parser_import.set_defaults(func='import')
parser_delete = subparsers.add_parser('delete', help="delete help")
parser_delete.add_argument('entries', metavar='entry', nargs='+',
help="a filename or an identifier")
parser_delete.add_argument('--skip', nargs='+',
help="path to files to skip", default=[])
group = parser_delete.add_mutually_exclusive_group()
group.add_argument('--id', action="store_true", default=False,
help="id based deletion")
group.add_argument('--file', action="store_true", default=False,
help="file based deletion")
parser_delete.add_argument('-f', '--force', default=False,
action='store_true',
help="delete without confirmation")
parser_delete.set_defaults(func='delete')
parser_edit = subparsers.add_parser('edit', help="edit help")
parser_edit.add_argument('entries', metavar='entry', nargs='+',
help="a filename or an identifier")
parser_edit.add_argument('--skip', nargs='+',
help="path to files to skip", default=[])
group = parser_edit.add_mutually_exclusive_group()
group.add_argument('--id', action="store_true", default=False,
help="id based deletion")
group.add_argument('--file', action="store_true", default=False,
help="file based deletion")
parser_edit.set_defaults(func='edit')
parser_list = subparsers.add_parser('list', help="list help")
parser_list.set_defaults(func='list')
parser_open = subparsers.add_parser('open', help="open help")
parser_open.add_argument('ids', metavar='id', nargs='+',
help="an identifier")
parser_open.set_defaults(func='open')
parser_export = subparsers.add_parser('export', help="export help")
parser_export.add_argument('entries', metavar='entry', nargs='+',
help="a filename or an identifier")
parser_export.add_argument('--skip', nargs='+',
help="path to files to skip", default=[])
group = parser_export.add_mutually_exclusive_group()
group.add_argument('--id', action="store_true", default=False,
help="id based deletion")
group.add_argument('--file', action="store_true", default=False,
help="file based deletion")
parser_export.set_defaults(func='export')
parser_resync = subparsers.add_parser('resync', help="resync help")
parser_resync.set_defaults(func='resync')
parser_update = subparsers.add_parser('update', help="update help")
parser_update.add_argument('entries', metavar='entry', nargs='+',
help="a filename or an identifier")
parser_update.add_argument('--skip', nargs='+',
help="path to files to skip", default=[])
group = parser_update.add_mutually_exclusive_group()
group.add_argument('--id', action="store_true", default=False,
help="id based deletion")
group.add_argument('--file', action="store_true", default=False,
help="file based deletion")
parser_update.set_defaults(func='update')
return parser.parse_args()
def main():
"""
Main function.
"""
global config
# Parse arguments
args = parse_args()
# Load the custom config if needed
if args.config is not None:
config = Config(base_config_path=args.config)
# Download command
if args.func == 'download':
skipped = []
for url in args.url:
# Try to download the URL
new_name = commands.download(url, args.manual, args.y,
args.tag)
if new_name is not None:
print("%s successfully imported as %s." % (url, new_name))
else:
tools.warning("An error occurred while downloading %s." %
(url,))
skipped.append(url)
# Output URLs with errors
if len(skipped) > 0:
tools.warning("Skipped URLs:")
for i in skipped:
tools.warning(i)
# Import command
elif args.func == 'import':
skipped = []
# Handle exclusions
files_to_process = list(set(args.file) - set(args.skip))
for filename in files_to_process:
# Try to import the file
new_name = commands.import_file(filename,
args.manual, args.y,
args.tag, not args.inplace)
if new_name is not None:
print("%s successfully imported as %s." % (filename, new_name))
else:
tools.warning("An error occurred while importing %s." %
(filename,))
skipped.append(filename)
# Output files with errors
if len(skipped) > 0:
tools.warning("Skipped files:")
for i in skipped:
tools.warning(i)
# Delete command
elif args.func == 'delete':
skipped = []
# Handle exclusions
items_to_process = list(set(args.entries) - set(args.skip))
for item in items_to_process:
# Confirm before deletion
if not args.force:
confirm = input("Are you sure you want to delete %s? [y/N] " %
(item,))
else:
confirm = 'y'
# Try to delete the item
if confirm.lower() == 'y':
file_or_id = file_or_id_from_args(args)
commands.delete(item, args.keep, file_or_id)
print("%s successfully deleted." % (item,))
else:
skipped.append(item)
# Output items with errors
if len(skipped) > 0:
tools.warning("Skipped items:")
for i in skipped:
tools.warning(i)
# Edit command
elif args.func == 'edit':
# Handle exclusions
items_to_process = list(set(args.entries) - set(args.skip))
for item in items_to_process:
file_or_id = file_or_id_from_args(args)
commands.edit(item, file_or_id)
# List command
elif args.func == 'list':
# List all available items
for id, file in commands.list_entries().items():
# And print them as "identifier: file"
print("%s: %s" % (id, file))
# Open command
elif args.func == 'open':
# Open each entry
for id in args.ids:
if not commands.open(id):
# And warn the user about missing files or errors
tools.warning("Unable to open file associated with ident %s." %
(id,))
# Export command
elif args.func == 'export':
# Handle exclusions
items_to_process = list(set(args.entries) - set(args.skip))
for item in items_to_process:
file_or_id = file_or_id_from_args(args)
print(commands.export(item, file_or_id))
# Resync command
elif args.func == 'resync':
confirm = input("Resync files and bibtex index? [y/N] ")
if confirm.lower() == 'y':
commands.resync()
# Update command
elif args.func == 'update':
# Handle exclusions
items_to_process = list(set(args.entries) - set(args.skip))
for item in items_to_process:
file_or_id = file_or_id_from_args(args)
updates = commands.update(args.entries)
# TODO \/
print("%d new versions of papers were found:" % (len(updates)))
for item in updates:
print(item)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
sys.exit()