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
|
-- view a document and/or display the list of results in texdoc
--[[
Copyright 2008, 2009 Manuel Pégourié-Gonnard
Distributed under the terms of the GNU GPL version 3 or later.
See texdoc.tlu for details.
--]]
local L = {}
load_env(L, {
'export_symbols',
'string', 'os', 'table', 'io',
'tonumber', 'ipairs', 'print',
'config',
'real_path',
'C',
'err_print', 'parse_zip',
})
----------------------------- view a document ------------------------------
-- view a document
-- see search.tlu for the structure of the argument
function view_doc(docfile)
return view_file(real_path(docfile))
end
-- get viewer and viewer_replacement before calling try_viewing
-- returns false of failure, true on success
-- viewer_replacement is either:
-- 1. the filename, quoted with "
-- 2. the filename, quoted with " followed by some rm commands
-- The second case happens when the doc was zipped. In the case, this function
-- unzips it in a tempdir so that the viewer command can use the unzipped file.
function view_file (filename)
local viewer, viewer_replacement
-- check if the file is zipped
local nozipname, zipext = parse_zip(filename)
-- determine viewer_replacement
if zipext then
local unzip_cmd = config['unzip_'..zipext]
if not unzip_cmd then
err_print("No unzip command for ."..zipext..' files, skipping '
..filename, 'error')
return false
end
local tmpdir = os.tmpdir("/tmp/texdoc.XXXXXX")
if not tmpdir then
err_print('Failed to create tempdir to unzip.', 'error')
return false
end
local basename = string.match(nozipname, '.*/(.*)$') or nozipname
local tmpfile = '"'..tmpdir..'/'..basename..'"'
if not os.execute(unzip_cmd..' "'..filename..'">'..tmpfile) then
err_print("Failed to unzip '"..filename.."'", 'error')
os.remove(tmpfile)
os.remove(tmpdir)
return false
end
viewer_replacement = ''..tmpfile..'; '
..config.rm_file..' '..tmpfile..'; '
..config.rm_dir..' '..tmpdir
filename = nozipname
else
viewer_replacement = '"'..filename..'"'
end
-- files without extension are assumed to be text
local viewext = string.match(filename,'.*%.([^/]*)$') or 'txt'
-- special case : sty files use txt viewer
if viewext == 'sty' then viewext = 'txt' end
if not config['viewer_'..viewext] then
err_print ("cannot find a viewer for file\n\t"..filename..
"\nUsing viewer_txt as a fallback. Set the 'viewer_"..viewext..
"' variable in texdoc.cnf to avoid this.", "warning")
viewext = 'txt'
if not config['viewer_'..viewext] then
err_print ("text viewer not found. This "..
"should not happen, sorry. Skipping\n\t"..filename, "error")
return false
end
end
return try_viewing(config['viewer_'..viewext], viewer_replacement)
end
-- view a file, if possible
function try_viewing (view_command, viewer_replacement)
if string.match (view_command, C.place_holder) then
view_command = string.gsub(
view_command, C.place_holder, viewer_replacement)
else
view_command = view_command..' '..viewer_replacement
end
err_print(view_command, 'debug1')
if not os.execute(view_command) then
err_print("Failed to execute '"..view_command.."'", "error")
return false
end
return true
end
----------------------------- display results ------------------------------
-- print a list of files (structure: see search.tlu) as a menu
-- if showall is false, stops as soon a non-exact match is encountered
-- (unimplemented right now, waiting for the scoring routine)
function print_menu(name, docfiles, showall)
local max_lines = tonumber(config.max_lines) or 20
if config.interact_switch and docfiles[max_lines+1] then
-- there may be too many lines, count them
local n
if showall then
n = #docfiles
else
n = 0
while docfiles[n+1] and docfiles[n+1].exact do
n = n + 1
end
end
if n > max_lines then
io.write (n, " results. Display them all? (y/N) ")
local ans = io.read('*line')
if not ((ans == 'y') or (ans == 'Y')
-- io.read had a bug wrt windows eol on some versions of texlua
or (ans == '\ry') or (ans == '\rY')) then
return
end
end
end
local i, doc
for i, doc in ipairs (docfiles) do
if (doc.exact == false) and not showall then break end
if config.machine_switch == true then
local score = doc.exact and 1 or 0
print(name, score, real_path(doc))
else
print(string.format('%2d %s', i, real_path(doc)))
end
end
if config.interact_switch then
io.write ("Please enter the number of the file to view, ",
"anything else to skip: ")
local num = tonumber(io.read('*line'))
if num and docfiles[num] then
view_doc(docfiles[num])
end
end
end
----------------------- deliver results base on mode -----------------------
function deliver_results(name, docfiles, many)
-- ensure that results were found or apologize
if not docfiles[1] then
if not config.machine_switch then
local msg = string.gsub(C.notfound_msg, C.notfound_msg_ph, name)
print(msg) -- get rid of gsub's 2nd value
end
return
end
-- shall we show all of them or only the "good" ones?
local showall = (config.mode == 'regex') or (config.mode == 'search')
if not showall and not docfiles[1].exact then
showall = true
err_print ("No exact match, trying full search mode.", "info")
end
-- view result or show menu based on mode and number of results
if (config.mode == 'view')
or config.mode == 'mixed' and (not docfiles[2]
or not docfiles[2].exact and not showall) then
view_doc(docfiles[1])
else
if many and not config.machine_switch then
print ("*** Results for: "..name.." ***")
end
print_menu(name, docfiles, showall)
end
end
-- finally export a few symbols
export_symbols(L, {
'deliver_results',
})
|