cli.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/env python3
  2. from argparse import ArgumentParser
  3. import os
  4. import subprocess
  5. import sys
  6. import tempfile
  7. import marxbook
  8. import marxbook.extract
  9. def get_parser():
  10. p = ArgumentParser()
  11. p.add_argument("--store-dir")
  12. p.add_argument("--editor", default="sensible-editor")
  13. p.add_argument("--batch", default=False, action="store_true")
  14. p.set_defaults(func=None)
  15. subcommands = p.add_subparsers(help="Sub-commands")
  16. list_p = subcommands.add_parser("list")
  17. list_p.add_argument("--format", default="{Path}\t{Tag}\t{Title}\t{Url}", dest="fmt")
  18. list_p.add_argument("folder", nargs="?", default="")
  19. list_p.set_defaults(func=main_list)
  20. add_p = subcommands.add_parser("add")
  21. add_p.add_argument("--folder", default="")
  22. add_p.add_argument("--tag", help="Comma-separated list of tags", default="")
  23. add_p.add_argument("--title", help="If omitted, auto-fetch")
  24. add_p.add_argument("--description", help="If omitted, auto-fetch")
  25. add_p.add_argument("--edit", dest="edit", action="store_true", default=None)
  26. add_p.add_argument("--no-edit", dest="edit", action="store_false", default=None)
  27. add_p.add_argument("url", nargs="?")
  28. add_p.set_defaults(func=main_add)
  29. rm_p = subcommands.add_parser("rm")
  30. rm_p.add_argument("--folder", default="")
  31. rm_p.add_argument("path")
  32. rm_p.set_defaults(func=main_rm)
  33. return p
  34. def main():
  35. p = get_parser()
  36. args = p.parse_args()
  37. if args.func is None:
  38. print("Must specify a subcommand", file=sys.stderr)
  39. return 2
  40. store = marxbook.Store(args.store_dir)
  41. args.func(store, args)
  42. def main_list(store, args):
  43. for mark in store.folder(args.folder):
  44. markdata = {"Folder": os.path.dirname(mark["Path"])}
  45. markdata.update(mark)
  46. markdata["Tag"] = ",".join(mark["Tag"])
  47. print(args.fmt.replace(r"\t", "\t").format(**markdata))
  48. class Edit:
  49. def __init__(self, args):
  50. self.args = args
  51. def edit_before_add(self, data: dict) -> dict:
  52. ser = marxbook.Serializer()
  53. fd, fpath = tempfile.mkstemp()
  54. buf = os.fdopen(fd, "w")
  55. buf.write(ser.encode(data))
  56. buf.close()
  57. proc = subprocess.Popen([self.args.editor, fpath])
  58. proc.communicate()
  59. with open(fpath) as buf:
  60. read_data = ser.decode(buf.read())
  61. os.unlink(fpath)
  62. data = {}
  63. for key in read_data:
  64. data[key.lower()] = read_data[key]
  65. return data
  66. def main_add(store, args):
  67. store = store.folder(args.folder)
  68. batch = args.batch
  69. editor = Edit(args)
  70. if args.url is not None:
  71. urls = [args.url]
  72. else:
  73. batch = True
  74. urls = []
  75. for line in sys.stdin.readlines():
  76. urls.append(line.strip())
  77. for url in urls:
  78. data = dict(title=args.title, description=args.description, url=url)
  79. data["tag"] = [t.strip() for t in args.tag.split(",")]
  80. if args.title is None or args.description is None:
  81. _title, _description, _keys, mime, bad = marxbook.extract.network_handler(
  82. url
  83. )
  84. if not args.title:
  85. data["title"] = _title
  86. if not args.description:
  87. data["description"] = _description
  88. # shall we edit?
  89. edit_needed = not batch
  90. if args.edit is not None:
  91. edit_needed = args.edit
  92. if edit_needed:
  93. data = editor.edit_before_add(data)
  94. store.add(**data)
  95. print(urls)
  96. def main_rm(store, args):
  97. store = store.folder(args.folder)
  98. dirpath, name = os.path.split(args.path)
  99. store = store.folder(dirpath)
  100. store.find(name).unlink()
  101. if __name__ == "__main__":
  102. ret = main()
  103. if type(ret) is int:
  104. sys.exit(ret)