cli.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. def get_parser():
  9. p = ArgumentParser()
  10. p.add_argument("--store-dir")
  11. p.add_argument("--editor", default="sensible-editor")
  12. p.add_argument("--batch", default=False, action="store_true")
  13. p.set_defaults(func=None)
  14. subcommands = p.add_subparsers(help="Sub-commands")
  15. list_p = subcommands.add_parser("list")
  16. list_p.add_argument("folder", nargs="?", default="")
  17. list_p.set_defaults(func=main_list)
  18. add_p = subcommands.add_parser("add")
  19. add_p.add_argument("--folder", default="")
  20. add_p.add_argument("--tag", help="Comma-separated list of tags", default="")
  21. add_p.add_argument("--title", help="If omitted, auto-fetch")
  22. add_p.add_argument("--description", help="If omitted, auto-fetch")
  23. add_p.add_argument("url", nargs="?")
  24. add_p.set_defaults(func=main_add)
  25. return p
  26. def main():
  27. p = get_parser()
  28. args = p.parse_args()
  29. if args.func is None:
  30. print("Must specify a subcommand", file=sys.stderr)
  31. return 2
  32. store = marxbook.Store(args.store_dir)
  33. args.func(store, args)
  34. def main_list(store, args):
  35. for mark in store.folder(args.folder):
  36. tag = ",".join(mark["Tag"])
  37. line = [mark["Path"], tag, mark["Title"], mark["Url"]]
  38. print("\t".join(line))
  39. def edit_before_add(data: dict, args) -> dict:
  40. ser = marxbook.Serializer()
  41. fd, fpath = tempfile.mkstemp()
  42. buf = os.fdopen(fd, "w")
  43. buf.write(ser.encode(data))
  44. buf.close()
  45. proc = subprocess.Popen([args.editor, fpath])
  46. proc.communicate()
  47. with open(fpath) as buf:
  48. read_data = ser.decode(buf.read())
  49. os.unlink(fpath)
  50. data = {}
  51. for key in read_data:
  52. data[key.lower()] = read_data[key]
  53. return data
  54. def main_add(store, args):
  55. store = store.folder(args.folder)
  56. batch = args.batch
  57. if args.url is not None:
  58. urls = [args.url]
  59. else:
  60. batch = True
  61. urls = []
  62. for line in sys.stdin.readlines():
  63. urls.append(line.strip())
  64. for url in urls:
  65. data = dict(title=args.title, description=args.description, url=url)
  66. data['tag'] = [t.strip() for t in args.tag.split(",")]
  67. if args.title is None or args.description is None:
  68. _title, _description, _keys, mime, bad = marxbook.extract.network_handler(url)
  69. if not args.title:
  70. data["title"] = _title
  71. if not args.description:
  72. data["description"] = _description
  73. if not batch:
  74. data = edit_before_add(data, args)
  75. store.add(**data)
  76. print(urls)
  77. if __name__ == "__main__":
  78. ret = main()
  79. if type(ret) is int:
  80. sys.exit(ret)