summaryrefslogtreecommitdiff
path: root/support/texdoc/script/texdoclib-cli.tlu
blob: 5eddc8f7f5934a899feadbdb4a7a004e87e7ee32 (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
-- texdoclib-cli.tlu: command-line interfaces for texdoc
--
-- The TeX Live Team, GPLv3, see texdoclib.tlu for details

-- dependencies
local texdoc = {
    const = require 'texdoclib-const',
    util = require 'texdoclib-util',
    config = require 'texdoclib-config',
    search = require 'texdoclib-search',
    view = require 'texdoclib-view',
}

-- shortcuts
local M = {}
local C = texdoc.const
local err_print = texdoc.util.err_print

--------------------------   parsing options   --------------------------

-- modified Alternative GetOpt
-- cf. http://lua-users.org/wiki/AlternativeGetOpt
local function getopt(arg, options)
    local tmp = nil
    local tab = {}
    local saved_arg = {table.unpack(arg)}

    for k, v in ipairs(saved_arg) do
        if string.sub(v, 1, 2) == '--' then
            table.remove(arg, 1)
            local x = string.find(v, '=', 1, true)
            if x then
                table.insert(tab, {string.sub(v, 3, x - 1), string.sub(v, x+1)})
            else
                table.insert(tab, {string.sub(v, 3), true})
            end

        elseif string.sub(v, 1, 1) == '-' then
            table.remove(arg, 1)
            local y = 2
            local l = string.len(v)
            local jopt

            while (y <= l) do
                jopt = string.sub(v, y, y)

                if string.find(options, jopt, 1, true) then
                    if y < l then
                        tmp = string.sub(v, y + 1)
                        y = l
                    else
                        table.remove(arg, 1)
                        tmp = saved_arg[k + 1]
                    end

                    -- check the existence of an argument
                    if not tmp then
                        err_print('error',
                            'Option -%s requires an argument.', jopt)
                        os.exit(C.exit_error)
                    end

                    if string.match(tmp, '^%-') then
                        table.insert(tab, {jopt, false})
                    else
                        table.insert(tab, {jopt, tmp})
                    end
                else
                    table.insert(tab, {jopt, true})
                end
                y = y + 1
            end

        else
            if tmp then tmp = nil else break end
        end
    end

    return tab
end

local function parse_options()
    local curr_arg
    local option
    local cl_config = {}

    -- actual parsing
    local optstring = ''
    for _, o in pairs(C.options) do
        if o['type'] == 'string' and o['short'] then
            optstring = optstring .. o['short']
        end
    end
    local opts = getopt(arg, optstring)

    for _, tp in ipairs(opts) do
        local k, v = tp[1], tp[2]
        if #k == 1 then
            curr_arg = '-' .. k
        else
            curr_arg = '--' .. k
        end

        for i, o in ipairs(C.options) do
            if k == o["short"] or k == o["long"] then
                k = i
                break
            end
        end

        option = C.options[k]
        if option['group'] == 'action' then
            if option['long'] == 'just-view' then
                return true, 'view', cl_config
            elseif option['long'] == 'print-completion' then
                return true, 'complete', cl_config
            else
                return true, option['long'], cl_config
            end
        elseif option['group'] then
            if option['type'] == 'boolean' then
                option['action'](cl_config, curr_arg)
            elseif option['type'] == 'string' then
                option['action'](cl_config, curr_arg, v)
            end

        -- having trouble
        else
            err_print('error', 'unknown option: ' .. curr_arg)
            err_print('error', C.error_msg)
            return false
        end
    end

    return true, action, cl_config
end

--------------------------   process execution   --------------------------

-- handling actions
local function do_action(action)
    if action == 'help' then
        texdoc.util.print_usage()
        os.exit(C.exit_ok)
    elseif action == 'version' then
        print(string.format(
            '%s %s (%s)', C.progname, C.version, C.release_date) ..
            '\n\n' .. C.copyright_msg)
        os.exit(C.exit_ok)
    elseif action == 'files' then
        print(texdoc.util.w32_path(C.fullname) .. ' ' .. C.version)
        texdoc.config.show_config_files(true)
        os.exit(C.exit_ok)
    elseif action == 'view' then
        if not arg[1] then
            err_print('error', 'Missing file operand to --just-view.')
            err_print('error', C.error_msg)
            os.exit(C.exit_usage)
        end
        texdoc.view.view_file(arg[1])
        os.exit(C.exit_ok)
    elseif action == 'complete' then
        if not arg[1] then
            err_print('error', 'Missing shell operand to --print-completion.')
            err_print('error', C.error_msg)
            os.exit(C.exit_usage)
        elseif arg[1] == 'zsh' then
            texdoc.util.print_zsh_completion()
            os.exit(C.exit_ok)
        else
            err_print('error', arg[1] .. ' is not supported currently!')
            os.exit(C.exit_error)
        end
    end
end

-- the main loop
local function do_texdoc()
    texdoc.search.init_databases()

    for _, docname in ipairs(arg) do
        -- do we have more then one argument?
        local multiarg = not not arg[2]
        -- get results
        local doclist = texdoc.search.get_doclist(docname)
        -- deliver results to the user
        texdoc.view.deliver_results(docname, doclist, multiarg)
    end
end

--------------------------   the main function   --------------------------

function M.exec()
    -- parsing command-line options
    local ok, action, cl_config = parse_options()

    if not ok then
        os.exit(C.exit_usage)
    end

    -- setup config and alias
    texdoc.config.setup_config_and_alias(cl_config)

    -- special action
    do_action(action)

    -- do we actually have arguments?
    if not arg[1] then
        err_print('error', 'No action specified.')
        err_print('error', C.error_msg)
        os.exit(C.exit_usage)
    end

    -- the main feature
    do_texdoc()

    os.exit(C.exit_ok)
end

return M

-- vim: ft=lua: