summaryrefslogtreecommitdiff
path: root/support/cluttex/src/texrunner/option.lua
blob: 19598610add3f4d223409aa83233a502ea94a8af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
--[[
  Copyright 2016 ARATA Mizuki

  This file is part of ClutTeX.

  ClutTeX is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  ClutTeX is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with ClutTeX.  If not, see <http://www.gnu.org/licenses/>.
]]

-- options_and_params, i = parseoption(arg, options)
-- options[i] = {short = "o", long = "option" [, param = true] [, boolean = true] [, allow_single_hyphen = false]}
-- options_and_params[j] = {"option", "value"}
-- arg[i], arg[i + 1], ..., arg[#arg] are non-options
local function parseoption(arg, options)
  local i = 1
  local option_and_params = {}
  while i <= #arg do
    if arg[i] == "--" then
      -- Stop handling options
      i = i + 1
      break
    elseif arg[i]:sub(1,2) == "--" then
      -- Long option
      local name,param = arg[i]:match("^([^=]+)=(.*)$", 3)
      name = name or arg[i]:sub(3)
      local opt = nil
      for _,o in ipairs(options) do
        if o.long then
          if o.long == name then
            if o.param then
              if param then
                -- --option=param
              else
                if o.default ~= nil then
                  param = o.default
                else
                  -- --option param
                  assert(i + 1 <= #arg, "argument missing after " .. arg[i] .. " option")
                  param = arg[i + 1]
                  i = i + 1
                end
              end
            else
              -- --option
              param = true
            end
            opt = o
            break
          elseif o.boolean and name == "no-" .. o.long then
            -- --no-option
            opt = o
            param = false
            break
          end
        end
      end
      if opt then
        table.insert(option_and_params, {opt.long, param})
      else
        -- Unknown long option
        error("unknown long option: " .. arg[i])
      end
    elseif arg[i]:sub(1,1) == "-" then
      local name,param = arg[i]:match("^([^=]+)=(.*)$", 2)
      name = name or arg[i]:sub(2)
      local opt = nil
      for _,o in ipairs(options) do
        if o.long and o.allow_single_hyphen then
          if o.long == name then
            if o.param then
              if param then
                -- -option=param
              else
                if o.default ~= nil then
                  param = o.default
                else
                  -- -option param
                  assert(i + 1 <= #arg, "argument missing after " .. arg[i] .. " option")
                  param = arg[i + 1]
                  i = i + 1
                end
              end
            else
              -- -option
              param = true
            end
            opt = o
            break
          elseif o.boolean and name == "no-" .. o.long then
            -- -no-option
            opt = o
            param = false
            break
          end
        elseif o.long and #name >= 2 and (o.long == name or (o.boolean and name == "no-" .. o.long)) then
          error("You must supply two hyphens (i.e. --" .. name .. ") for long option")
        end
      end
      if opt == nil then
        -- Short option
        name = arg[i]:sub(2,2)
        for _,o in ipairs(options) do
          if o.short then
            if o.short == name then
              if o.param then
                if #arg[i] > 2 then
                  -- -oparam
                  param = arg[i]:sub(3)
                else
                  -- -o param
                  assert(i + 1 <= #arg, "argument missing after " .. arg[i] .. " option")
                  param = arg[i + 1]
                  i = i + 1
                end
              else
                -- -o
                assert(#arg[i] == 2, "combining multiple short options like -abc is not supported")
                param = true
              end
              opt = o
              break
            end
          end
        end
      end
      if opt then
        table.insert(option_and_params, {opt.long or opt.short, param})
      else
        error("unknown short option: " .. arg[i])
      end
    else
      -- arg[i] is not an option
      break
    end
    i = i + 1
  end
  return option_and_params, i
end

return {
  parseoption = parseoption;
}