├── LICENSE ├── Makefile ├── NEWS ├── README.pod ├── alt_getopt ├── alt_getopt.lua ├── fake └── tests ├── test.out └── test.sh /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Aleksey Cheusov 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ################################################## 2 | 3 | VERSION= 0.8.0 4 | PROJECTNAME= lua-alt-getopt 5 | BIRTHDATE= 2009-01-10 6 | 7 | LUA_LMODULES= alt_getopt.lua 8 | 9 | MKC_REQD= 0.20.0 10 | 11 | ################################################## 12 | .PHONY: test 13 | test: 14 | @echo 'running tests...'; \ 15 | ln -f -s ${.CURDIR}/alt_getopt.lua ${.CURDIR}/tests; \ 16 | export OBJDIR=${.OBJDIR}; \ 17 | if cd ${.CURDIR}/tests && ./test.sh; \ 18 | then echo ' succeeded'; \ 19 | else echo ' failed'; false; \ 20 | fi 21 | 22 | .include 23 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | ====================================================================== 2 | Version 0.8.0, by Peter Melnichenko, Fri, 06 Jan 2017 13:49:49 +0300 3 | 4 | FIX: alt_getopt no longer uses 'module()'. 5 | 6 | alt_getopt now supports Lua 5.3. 7 | 8 | ====================================================================== 9 | Version 0.7.0, by Aleksey Cheusov, Sun, 18 Oct 2009 14:17:28 +0300 10 | 11 | FIX: POSIX getopt("xo:") accepts './app -xoVVV' and './app -xo VVV' 12 | treating them as './app -x -o VVV'. 13 | Now Lua alt_getopt does the same. 14 | 15 | Additional regression tests/examples 16 | 17 | error() function is not used for exiting anymore. 18 | os.exit() is used instead. 19 | 20 | ====================================================================== 21 | Version 0.6.0, by Aleksey Cheusov, Sun, 26 Apr 2009 19:52:38 +0300 22 | 23 | FIXED: global variable 'optind'. Now it is local. 24 | Minor improvements and code clean-ups. 25 | Thanks to Leo P. for all this. 26 | 27 | ====================================================================== 28 | Version 0.5.0, by Aleksey Cheusov 29 | 30 | First publicly available release 31 | -------------------------------------------------------------------------------- /README.pod: -------------------------------------------------------------------------------- 1 | =head3 Description 2 | 3 | lua_altgetopt is a MIT-licenced module for Lua programming language 4 | for processing application's arguments the same way 5 | POSIX getopt(3) and BSD/Solaris getopt_long(3) functions do. 6 | 7 | =head3 Features 8 | 9 | Main features and goals: 10 | 11 | =over 6 12 | 13 | =item * 14 | 15 | Compatibility with POSIX, that is, SUS "Utility Syntax Guidelines" 16 | guidelines 3-12 17 | L. 18 | 19 | =item * 20 | 21 | Support for long options, e.g. compatibility with getopt_long(3) C function 22 | present in *BSD and Solaris operating systems. 23 | 24 | =item * 25 | 26 | Unlike GNU getopt(3) and getopt_long(3) lua_altgetopt does not permute the contents 27 | of argv as it scans. This means lua_altgetopt strictly conforms to POSIX rules 28 | of options parsing. GNU getopt(3) and getopt_long(3) are buggy! 29 | 30 | =item * 31 | 32 | Strict error checking, i.e., checks for an incorrect use of options. 33 | 34 | =item * 35 | 36 | Two ways of options handling are provided. 37 | See alt_getopt.get_ordered_opts and alt_getopt.get_opts functions. 38 | 39 | =item * 40 | 41 | This module is written in plain Lua. 42 | 43 | =item * 44 | 45 | No extra dependencies. 46 | 47 | =item * 48 | 49 | No hooks, no functional tricks ;-) 50 | 51 | =back 52 | 53 | =head3 Installation: 54 | 55 | install mk-configure on your system, then run the following commands. 56 | 57 | # mkcmake all 58 | # mkcmake test 59 | # mkcmake install 60 | 61 | =head3 Bug reports 62 | 63 | Please report bugs here 64 | L 65 | 66 | =head3 Author 67 | 68 | Aleksey Cheusov 69 | -------------------------------------------------------------------------------- /alt_getopt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local alt_getopt = require "alt_getopt" 4 | 5 | local long_opts = { 6 | verbose = "v", 7 | help = "h", 8 | fake = 0, 9 | len = 1, 10 | output = "o", 11 | set_value = "S", 12 | ["set-output"] = "o" 13 | } 14 | 15 | local opts 16 | local optarg 17 | local optind 18 | opts,optind,optarg = alt_getopt.get_ordered_opts (arg, "hVvo:n:S:", long_opts) 19 | for i,v in ipairs (opts) do 20 | if optarg [i] then 21 | io.write ("option `" .. v .. "': " .. optarg [i] .. "\n") 22 | else 23 | io.write ("option `" .. v .. "'\n") 24 | end 25 | end 26 | 27 | optarg,optind = alt_getopt.get_opts (arg, "hVvo:n:S:", long_opts) 28 | local fin_options = {} 29 | for k,v in pairs (optarg) do 30 | table.insert (fin_options, "fin-option `" .. k .. "': " .. v .. "\n") 31 | end 32 | table.sort (fin_options) 33 | io.write (table.concat (fin_options)) 34 | 35 | for i = optind,#arg do 36 | io.write (string.format ("ARGV [%s] = %s\n", i, arg [i])) 37 | end 38 | -------------------------------------------------------------------------------- /alt_getopt.lua: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2009 Aleksey Cheusov 2 | -- 3 | -- Permission is hereby granted, free of charge, to any person obtaining 4 | -- a copy of this software and associated documentation files (the 5 | -- "Software"), to deal in the Software without restriction, including 6 | -- without limitation the rights to use, copy, modify, merge, publish, 7 | -- distribute, sublicense, and/or sell copies of the Software, and to 8 | -- permit persons to whom the Software is furnished to do so, subject to 9 | -- the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be 12 | -- included in all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | -- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | -- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | -- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | local type, pairs, ipairs, io, os = type, pairs, ipairs, io, os 23 | 24 | alt_getopt = {} 25 | 26 | local function convert_short2long (opts) 27 | local ret = {} 28 | 29 | for short_opt, accept_arg in opts:gmatch("(%w)(:?)") do 30 | ret[short_opt]=#accept_arg 31 | end 32 | 33 | return ret 34 | end 35 | 36 | local function exit_with_error (msg, exit_status) 37 | io.stderr:write (msg) 38 | os.exit (exit_status) 39 | end 40 | 41 | local function err_unknown_opt (opt) 42 | exit_with_error ("Unknown option `-" .. 43 | (#opt > 1 and "-" or "") .. opt .. "'\n", 1) 44 | end 45 | 46 | local function canonize (options, opt) 47 | if not options [opt] then 48 | err_unknown_opt (opt) 49 | end 50 | 51 | while type (options [opt]) == "string" do 52 | opt = options [opt] 53 | 54 | if not options [opt] then 55 | err_unknown_opt (opt) 56 | end 57 | end 58 | 59 | return opt 60 | end 61 | 62 | function alt_getopt.get_ordered_opts (arg, sh_opts, long_opts) 63 | local i = 1 64 | local count = 1 65 | local opts = {} 66 | local optarg = {} 67 | 68 | local options = convert_short2long (sh_opts) 69 | for k,v in pairs (long_opts) do 70 | options [k] = v 71 | end 72 | 73 | while i <= #arg do 74 | local a = arg [i] 75 | 76 | if a == "--" then 77 | i = i + 1 78 | break 79 | 80 | elseif a == "-" then 81 | break 82 | 83 | elseif a:sub (1, 2) == "--" then 84 | local pos = a:find ("=", 1, true) 85 | 86 | if pos then 87 | local opt = a:sub (3, pos-1) 88 | 89 | opt = canonize (options, opt) 90 | 91 | if options [opt] == 0 then 92 | exit_with_error ("Bad usage of option `" .. a .. "'\n", 1) 93 | end 94 | 95 | optarg [count] = a:sub (pos+1) 96 | opts [count] = opt 97 | else 98 | local opt = a:sub (3) 99 | 100 | opt = canonize (options, opt) 101 | 102 | if options [opt] == 0 then 103 | opts [count] = opt 104 | else 105 | if i == #arg then 106 | exit_with_error ("Missed value for option `" .. a .. "'\n", 1) 107 | end 108 | 109 | optarg [count] = arg [i+1] 110 | opts [count] = opt 111 | i = i + 1 112 | end 113 | end 114 | count = count + 1 115 | 116 | elseif a:sub (1, 1) == "-" then 117 | 118 | for j=2,a:len () do 119 | local opt = canonize (options, a:sub (j, j)) 120 | 121 | if options [opt] == 0 then 122 | opts [count] = opt 123 | count = count + 1 124 | elseif a:len () == j then 125 | if i == #arg then 126 | exit_with_error ("Missed value for option `-" .. opt .. "'\n", 1) 127 | end 128 | 129 | optarg [count] = arg [i+1] 130 | opts [count] = opt 131 | i = i + 1 132 | count = count + 1 133 | break 134 | else 135 | optarg [count] = a:sub (j+1) 136 | opts [count] = opt 137 | count = count + 1 138 | break 139 | end 140 | end 141 | else 142 | break 143 | end 144 | 145 | i = i + 1 146 | end 147 | 148 | return opts,i,optarg 149 | end 150 | 151 | function alt_getopt.get_opts (arg, sh_opts, long_opts) 152 | local ret = {} 153 | 154 | local opts,optind,optarg = alt_getopt.get_ordered_opts (arg, sh_opts, long_opts) 155 | for i,v in ipairs (opts) do 156 | if optarg [i] then 157 | ret [v] = optarg [i] 158 | else 159 | ret [v] = 1 160 | end 161 | end 162 | 163 | return ret,optind 164 | end 165 | 166 | return alt_getopt 167 | -------------------------------------------------------------------------------- /fake: -------------------------------------------------------------------------------- 1 | abba 2 | -------------------------------------------------------------------------------- /tests/test.out: -------------------------------------------------------------------------------- 1 | ================================================================= 2 | ======= args: ../alt_getopt -h - 3 | option `h' 4 | fin-option `h': 1 5 | ARGV [2] = - 6 | ================================================================= 7 | ======= args: ../alt_getopt --help 8 | option `h' 9 | fin-option `h': 1 10 | ================================================================= 11 | ======= args: ../alt_getopt -h --help -v --verbose -V -o 123 -o234 12 | option `h' 13 | option `h' 14 | option `v' 15 | option `v' 16 | option `V' 17 | option `o': 123 18 | option `o': 234 19 | fin-option `V': 1 20 | fin-option `h': 1 21 | fin-option `o': 234 22 | fin-option `v': 1 23 | ================================================================= 24 | ======= args: ../alt_getopt --output 123 --output 234 -n 999 -n9999 --len 5 --fake /dev/null 25 | option `o': 123 26 | option `o': 234 27 | option `n': 999 28 | option `n': 9999 29 | option `len': 5 30 | option `fake' 31 | fin-option `fake': 1 32 | fin-option `len': 5 33 | fin-option `n': 9999 34 | fin-option `o': 234 35 | ARGV [11] = /dev/null 36 | ================================================================= 37 | ======= args: ../alt_getopt -hVv -- -1 -2 -3 38 | option `h' 39 | option `V' 40 | option `v' 41 | fin-option `V': 1 42 | fin-option `h': 1 43 | fin-option `v': 1 44 | ARGV [3] = -1 45 | ARGV [4] = -2 46 | ARGV [5] = -3 47 | ================================================================= 48 | ======= args: ../alt_getopt --fake -v -- -1 -2 -3 49 | option `fake' 50 | option `v' 51 | fin-option `fake': 1 52 | fin-option `v': 1 53 | ARGV [4] = -1 54 | ARGV [5] = -2 55 | ARGV [6] = -3 56 | ================================================================= 57 | ======= args: ../alt_getopt - -1 -2 -3 58 | ARGV [1] = - 59 | ARGV [2] = -1 60 | ARGV [3] = -2 61 | ARGV [4] = -3 62 | ================================================================= 63 | ======= args: ../alt_getopt --fake -v - -1 -2 -3 64 | option `fake' 65 | option `v' 66 | fin-option `fake': 1 67 | fin-option `v': 1 68 | ARGV [3] = - 69 | ARGV [4] = -1 70 | ARGV [5] = -2 71 | ARGV [6] = -3 72 | ================================================================= 73 | ======= args: ../alt_getopt -1 -2 -3 74 | Unknown option `-1' 75 | ================================================================= 76 | ======= args: ../alt_getopt -hvV 77 | option `h' 78 | option `v' 79 | option `V' 80 | fin-option `V': 1 81 | fin-option `h': 1 82 | fin-option `v': 1 83 | ================================================================= 84 | ======= args: ../alt_getopt -ho 123 85 | option `h' 86 | option `o': 123 87 | fin-option `h': 1 88 | fin-option `o': 123 89 | ================================================================= 90 | ======= args: ../alt_getopt -hoV 123 91 | option `h' 92 | option `o': V 93 | fin-option `h': 1 94 | fin-option `o': V 95 | ARGV [2] = 123 96 | ================================================================= 97 | ======= args: ../alt_getopt --unknown 98 | Unknown option `--unknown' 99 | ================================================================= 100 | ======= args: ../alt_getopt --output=file.out -nNNN --len=LENGTH 101 | option `o': file.out 102 | option `n': NNN 103 | option `len': LENGTH 104 | fin-option `len': LENGTH 105 | fin-option `n': NNN 106 | fin-option `o': file.out 107 | ================================================================= 108 | ======= args: ../alt_getopt --output --file-- 109 | option `o': --file-- 110 | fin-option `o': --file-- 111 | ================================================================= 112 | ======= args: ../alt_getopt --output 113 | Missed value for option `--output' 114 | ================================================================= 115 | ======= args: ../alt_getopt -ho 116 | Missed value for option `-o' 117 | ================================================================= 118 | ======= args: ../alt_getopt --help -o 119 | Missed value for option `-o' 120 | ================================================================= 121 | ======= args: ../alt_getopt --help=value 122 | Bad usage of option `--help=value' 123 | ================================================================= 124 | ======= args: ../alt_getopt -ofile1 --set_value 111 --output file2 --set-output=file3 125 | option `o': file1 126 | option `S': 111 127 | option `o': file2 128 | option `o': file3 129 | fin-option `S': 111 130 | fin-option `o': file3 131 | -------------------------------------------------------------------------------- /tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | runtest (){ 4 | printf '=================================================================\n' 5 | printf '======= args: %s\n' "$*" 6 | "$@" 2>&1 | awk '/stack traceback:/, /\[C\]: [?]/ {next} {print}' 7 | } 8 | 9 | do_test_getopt (){ 10 | runtest ../alt_getopt -h - 11 | runtest ../alt_getopt --help 12 | runtest ../alt_getopt -h --help -v --verbose -V -o 123 -o234 13 | runtest ../alt_getopt --output 123 --output 234 -n 999 -n9999 --len 5 --fake /dev/null 14 | runtest ../alt_getopt -hVv -- -1 -2 -3 15 | runtest ../alt_getopt --fake -v -- -1 -2 -3 16 | runtest ../alt_getopt - -1 -2 -3 17 | runtest ../alt_getopt --fake -v - -1 -2 -3 18 | runtest ../alt_getopt -1 -2 -3 19 | runtest ../alt_getopt -hvV 20 | runtest ../alt_getopt -ho 123 21 | runtest ../alt_getopt -hoV 123 22 | runtest ../alt_getopt --unknown 23 | runtest ../alt_getopt --output='file.out' -nNNN --len=LENGTH 24 | runtest ../alt_getopt --output --file-- 25 | 26 | runtest ../alt_getopt --output 27 | runtest ../alt_getopt -ho 28 | runtest ../alt_getopt --help -o 29 | runtest ../alt_getopt --help=value 30 | runtest ../alt_getopt -ofile1 --set_value 111 --output file2 \ 31 | --set-output=file3 32 | 33 | true 34 | } 35 | 36 | do_test (){ 37 | do_test_getopt 38 | } 39 | 40 | OBJDIR=${OBJDIR:=.} 41 | 42 | do_test > $OBJDIR/_test.res 2>&1 43 | 44 | if ! diff -u test.out $OBJDIR/_test.res; then 45 | echo "rewrite fails" 1>&2 46 | exit 1 47 | fi 48 | 49 | --------------------------------------------------------------------------------