/
Holixus
/
node-getopt
Обзор
Документация
Войти
/
Holixus
/
node-getopt
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
lib/getopt.toffee
232 строки
6 KB
Vladimir Antonov
Fix of multi-lines option value parsing
10 фев 2016, 17:08
10 фев 2016, 17:08
1e3ccaf
Код
Авторство
О чём код?
class ParsedOption constructor: (@argv, @options) -> empty: -> if @argv.length return false for own k, v of @options return false return true class Getopt @HAS_ARGUMENT = true @NO_ARGUMENT = false @MULTI_SUPPORTED = true @SINGLE_ONLY = false @VERSION = '0.2.3' # public constructor: (@options) -> @short_options = {} @long_options = {} @long_names = [] @events = {} @event_names = [] @errorFunc = (e) -> console.info(e.message) process.exit(1) if process.argv[1] @help = "Usage: node #{process.argv[1].match(/(?:.*[\/\\])?(.*)$/)[1]}\n\n[[OPTIONS]]\n" else @help = "[[OPTIONS]]" for option in @options [short_name, definition, comment] = option comment ?= '' definition ?= '' short_name ?= '' definition =~ /^([\w\-]*)/ long_name = \1 has_argument = definition.indexOf('=') != -1 multi_supported = definition.indexOf('+') != -1 optional = /\[=.*?\]/.test(definition) long_name = long_name.trim() short_name = short_name.trim() if optional && short_name throw new Error('optional argument can only work with long option'); unless long_name long_name = short_name name = long_name if long_name == '' throw new Error("empty option found. the last option name is #{@long_names.slice(-1)}"); unless @long_options[long_name]? @long_names.push long_name @long_options[long_name] = {name, short_name, long_name, has_argument, multi_supported, comment, optional, definition} else throw new Error("option #{long_name} redefined."); if short_name != '' if short_name.length != 1 throw new Error 'short option must be single characters' @short_options[short_name] = @long_options[long_name] @ # Events on: (name, cb) -> @events[name] = cb @event_names.push name @ emit: (name, cb) -> if @events[name] @events[name].call @, @parsedOption.argv, @parsedOption.options else throw new Error("Getopt trigger '#{name}' is not found") trigger_events_: -> {options} = @parsedOption for name in @event_names if options[name]? @emit(name) @ # Command line parser save_option_: (options, option, argv) -> if option.has_argument if argv.length == 0 throw new Error("option #{option.long_name} need argument") value = argv.shift() else value = true names = [option.name] # Have't decided replace - to _ or not or both existed # opt.options['option-with-hyphen'] # vs opt.options.option_with_hyphen # if option.name.indexOf('-') != -1 # names.push option.name.replace(/\-/g, '_') for name in names if option.multi_supported options[name] ?= [] options[name].push value else options[name] = value @ parse: (argv) -> try # clone argv argv = argv[0..] rt_options = {} rt_argv = [] while (arg = argv.shift())? if arg =~ /^-(\w[\w\-]*)/ # short option short_names = \1 for short_name, i in short_names option = @short_options[short_name] unless option throw new Error("invalid option #{short_name}") if option.has_argument if i < arg.length - 2 argv.unshift arg.slice(i+2) @save_option_(rt_options, option, argv) break else @save_option_(rt_options, option, argv) else if arg =~ /^--(\w[\w\-]*)((?:=[^]*)?)$/ # long option long_name = \1 value = \2 option = @long_options[long_name] unless option throw new Error("invalid option #{long_name}") if value != '' value = value[1..] argv.unshift(value) else if option.optional argv.unshift('') @save_option_(rt_options, option, argv) else if arg == '--' rt_argv = rt_argv.concat(argv) break else rt_argv.push arg catch e @errorFunc(e) @parsedOption = new ParsedOption(rt_argv, rt_options) @trigger_events_() @parsedOption parse_system: -> @parse(process.argv.slice(2)) parseSystem: -> @parse_system() # Help Controller setHelp: (@help) -> @ getHelp: -> ws = [] options = [] for long_name in @long_names option = @long_options[long_name] {short_name, long_name, comment, definition} = option if (short_name && short_name == long_name) # only has short name opt = "-#{short_name}" else if short_name # both has short name and long name opt = "-#{short_name}, --#{definition}" else # only has long name opt = " --#{definition}" ws[0] = Math.max(ws[0] >> 0, opt.length) options.push [opt, comment] strs = for option in options [opt, comment] = option while opt.length < ws[0] opt += ' ' " #{opt} #{comment}" @help.replace('[[OPTIONS]]', strs.join("\n")) showHelp: -> console.info @getHelp() @ bindHelp: (help) -> if help @setHelp help @on 'help', -> @showHelp() process.exit(0) @ getVersion: -> Getopt.VERSION error: (@errorFunc) -> @ @getVersion: -> @VERSION # For oneline creator @create: (options) -> new Getopt(options) module.exports = Getopt # vim: sw=2 ts=2 sts=2 expandtab :