command_line.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. ## $Id$
  2. ##
  3. ## Flexlay - A Generic 2D Game Editor
  4. ## Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
  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. # A parser for command line arguments
  19. class CommandLineOption
  20. attr_reader :short, :long, :argument, :description
  21. def initialize(short, long, argument, description)
  22. @short = short
  23. @long = long
  24. @argument = argument
  25. @description = description
  26. end
  27. end
  28. class CommandLineException < RuntimeError
  29. end
  30. class CommandLine
  31. def initialize(&block)
  32. @options = []
  33. @name = nil
  34. @usage = nil
  35. @help = []
  36. @description = nil
  37. if block then
  38. instance_eval(&block);
  39. end
  40. end
  41. def name(name)
  42. @name = name
  43. end
  44. def usage(usage)
  45. @usage = usage
  46. end
  47. def description(description)
  48. @description = description
  49. end
  50. def group(group)
  51. @help.push("\n" + group + ":")
  52. end
  53. def text(text)
  54. @help.push("\n" + text)
  55. end
  56. def option(short, long, argument, description)
  57. cmd = CommandLineOption.new(short, long, argument, description)
  58. @options.push(cmd)
  59. @help.push(cmd)
  60. end
  61. def parse(args)
  62. result = []
  63. args = args.reverse()
  64. @stop_parsing = false
  65. while not args.empty? and not @stop_parsing
  66. current = args.pop
  67. if current == "--" then
  68. while not args.empty?
  69. result.push([:rest, args.pop])
  70. end
  71. elsif current == "-" then
  72. result.push([:rest, current])
  73. elsif current[0] == ?- then
  74. if current[1] == ?- then
  75. long_option = current[2..-1]
  76. cmd = @options.find {|item| item.long == long_option }
  77. if not cmd then
  78. raise CommandLineException, "unrecoginzed option '#{current}'"
  79. else
  80. if cmd.argument then
  81. if args.empty? then
  82. raise "Error: Option '#{current}' requires argument of type '#{cmd.argument}'"
  83. else
  84. result.push([cmd.short, args.pop()])
  85. end
  86. else
  87. result.push([cmd.short, nil])
  88. end
  89. end
  90. else
  91. # short option
  92. short_options = current[1..-1]
  93. while not short_options.empty?
  94. short = short_options[0]
  95. short_options = short_options[1..-1]
  96. cmd = @options.find {|item| item.short == short}
  97. if not cmd then
  98. raise CommandLineException, "unrecoginzed option '#{current}'"
  99. else
  100. if cmd.argument then
  101. if not short_options.empty? then
  102. result.push([cmd.short, short_options])
  103. short_options = ""
  104. else
  105. if args.empty? then
  106. raise CommandLineException, "Error: Option '#{current}' requires argument of type '#{cmd.argument}'"
  107. else
  108. result.push([cmd.short, args.pop()])
  109. end
  110. end
  111. else
  112. result.push([cmd.short, nil])
  113. end
  114. end
  115. end
  116. end
  117. else
  118. # rest argument
  119. result.push([:rest, current])
  120. end
  121. end
  122. return result
  123. end
  124. def print_help()
  125. puts(@name) if @name
  126. puts("Usage: #{$0} #{@usage}") if @usage
  127. puts("")
  128. puts(@description) if @description
  129. @help.each() { |item|
  130. if item.is_a?(String)
  131. puts(item)
  132. elsif item.is_a?(CommandLineOption)
  133. puts(" %-30s %s" %
  134. [("%s%s %s" % [if item.short.is_a?(Fixnum) then
  135. if item.long then
  136. "-#{item.short.chr}, "
  137. else
  138. "-#{item.short.chr}"
  139. end
  140. else
  141. ""
  142. end,
  143. if item.long then
  144. "--#{item.long}"
  145. else
  146. ""
  147. end,
  148. if item.argument then item.argument else "" end,
  149. ]),
  150. item.description])
  151. end
  152. }
  153. end
  154. def exit()
  155. @stop_parsing = true
  156. end
  157. end
  158. # EOF #