Opts.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #!/usr/bin/env python
  2. #
  3. # Opts.py, an options parsing library for Python. Copyright (C) 2014 by
  4. # Philemon <mmgen-py@yandex.com>.
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. import sys, getopt
  19. def usage(hd):
  20. print "USAGE: %s %s" % (hd['prog_name'], hd['usage'])
  21. sys.exit(2)
  22. def print_help(help_data):
  23. pn = help_data['prog_name']
  24. pn_len = str(len(pn)+2)
  25. print (" %-"+pn_len+"s %s") % (pn.upper()+":", help_data['desc'].strip())
  26. print (" %-"+pn_len+"s %s %s")%("USAGE:", pn, help_data['usage'].strip())
  27. sep = "\n "
  28. print " OPTIONS:"+sep+"%s" % sep.join(help_data['options'].strip().split("\n"))
  29. if "notes" in help_data:
  30. print " %s" % "\n ".join(help_data['notes'][1:-1].split("\n"))
  31. def process_opts(argv,help_data,short_opts,long_opts):
  32. long_opts = [i.replace("_","-") for i in long_opts]
  33. try: cl_opts, args = getopt.getopt(argv[1:], short_opts, long_opts)
  34. except getopt.GetoptError as err:
  35. print str(err); sys.exit(2)
  36. opts,short_opts_l = {},[]
  37. for i in short_opts:
  38. if i == ":": short_opts_l[-1] += i
  39. else: short_opts_l += i
  40. for opt, arg in cl_opts:
  41. if opt in ("-h","--help"): print_help(help_data); sys.exit()
  42. elif opt[:2] == "--" and opt[2:] in long_opts:
  43. opts[opt[2:].replace("-","_")] = True
  44. elif opt[:2] == "--" and opt[2:]+"=" in long_opts:
  45. opts[opt[2:].replace("-","_")] = arg
  46. elif opt[0] == "-" and opt[1] in short_opts_l:
  47. opts[long_opts[short_opts_l.index(opt[1:])].replace("-","_")] = True
  48. elif opt[0] == "-" and opt[1:]+":" in short_opts_l:
  49. opts[long_opts[short_opts_l.index(
  50. opt[1:]+":")][:-1].replace("-","_")] = arg
  51. else: assert False, "Invalid option"
  52. return opts,args
  53. def parse_opts(argv,help_data):
  54. lines = help_data['options'].strip().split("\n")
  55. import re
  56. pat = r"^-([a-zA-Z0-9]), --([a-zA-Z0-9-]{1,64})(=| )(.+)"
  57. rep = r"-{0}, --{1}{w}{3}"
  58. opt_data = [list(m.groups()) for m in [re.match(pat,l) for l in lines] if m]
  59. for d in opt_data:
  60. if d[2] == " ": d[2] = ""
  61. short_opts = "".join([d[0]+d[2].replace("=",":") for d in opt_data])
  62. long_opts = [d[1].replace("-","_")+d[2] for d in opt_data]
  63. help_data['options'] = "\n".join(
  64. [rep.format(w=" ", *m.groups())
  65. if m else k for m,k in [(re.match(pat,l),l) for l in lines]]
  66. )
  67. opts,args = process_opts(argv,help_data,short_opts,long_opts)
  68. return opts,args,short_opts,long_opts