summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorManuel Pégourié-Gonnard <mpg@elzevir.fr>2008-07-28 01:29:16 +0000
committerManuel Pégourié-Gonnard <mpg@elzevir.fr>2008-07-28 01:29:16 +0000
commit7a8b3c6f337259f7d0f69bc4af39f47a7e12b71a (patch)
tree3335f4b77f0d7a10386b06a81ec9c619b134c8c6 /Master
parent722e643edbed8411b98a9925c76c6a0fd9a2f19c (diff)
Introducing new implementation of search functions, and changing a few things in modes and the print_menu function to accomodate. Viewing currently broken.
git-svn-id: svn://tug.org/texlive/trunk@9831 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rwxr-xr-xMaster/texmf/scripts/texlive/texdoc.tlu279
1 files changed, 145 insertions, 134 deletions
diff --git a/Master/texmf/scripts/texlive/texdoc.tlu b/Master/texmf/scripts/texlive/texdoc.tlu
index 5236e3a9edc..a3f53b2840b 100755
--- a/Master/texmf/scripts/texlive/texdoc.tlu
+++ b/Master/texmf/scripts/texlive/texdoc.tlu
@@ -81,134 +81,134 @@ end
-- functions for the search options
-----------------------------------
--- full tree exploration with or without ls-R file
-
--- check which texmf roots have a ls-R file (returns an iterator for those)
--- and which don't (put them in the global no_lsr_trees) (bad)
-no_lsr_doctrees = {}
-function get_lsr_files ()
- local lsr_files = {}
- local pathlist = kpse.expand_braces('$TEXDOCS')
- for path in string.gmatch(pathlist, "[^:;]+") do
- path = string.gsub(path,'//$','')
- local tree_root
- tree_root = string.gsub(path,'doc$','')
- tree_root = string.gsub(tree_root,'^!!','')
- if lfs.isfile(tree_root .. "ls-R") then
- table.insert(lsr_files,tree_root .. "ls-R")
- else
- if not string.match(path,'^%.$') and lfs.isdir(path) then
- table.insert(no_lsr_doctrees,path)
- end
- end -- does lsRfile exist?
- end -- for path
- local i = 0
- local n = table.getn(lsr_files)
- return function ()
- i = i +1
- if i <= n then return lsr_files[i] end
+-- BEGIN kpse-like
+
+-- temporary, will be an option soon
+no_regex = true
+
+-- get global texdocs, do_recurse and must_have_lsr lists from kpse's $TEXDOCS
+function get_texdocs ()
+ local sep = (os.type == 'window') and ';' or ':'
+ -- avoid duplicates like {/english,} or {/man,} in $TEXDOCS
+ texdocs = string.gsub (kpse.expand_var ("$TEXDOCS"), "{[^{}]+,}", "")
+ -- expand the path and turn it into a lua list
+ texdocs = string.explode (kpse.expand_braces (texdocs), sep)
+ do_recurse, must_have_lsr = {}, {} -- global
+ for i, dir in ipairs (texdocs) do
+ local n
+ dir, n = string.gsub (dir, '//$', '')
+ do_recurse[i] = (n == 1)
+ texdocs[i], n = string.gsub (dir, '^!!', '')
+ must_have_lsr[i] = (n == 1)
end
end
--- protect - in patterns instead of trusting the user to do that
-function deluaficate(oldpat)
- local newpat
- -- better use long strings here, no escaping of \ needed there.
- newpat = string.gsub(oldpat,'([^\\])%-','%1%%%-')
- newpat = string.gsub(newpat,'\\','')
- return newpat
-end --deluaficate
-
--- return files in the TEXDOCS tree whose full path matches against pattern
-function pattern_search (pattern)
- docfiles = {} -- should not be local (used in recurse_tree)
- pattern = deluaficate(pattern)
- -- populate docfiles list
- for database in get_lsr_files() do
- local texmf_tree = string.gsub(database,'ls%-R$','')
- is_docline = false
- local this_dir -- changed to each individual docdir
- for line in io.lines(database) do
- if string.match(line,'^./') then
- -- a directory
- this_dir = string.gsub(line,'^./',texmf_tree)
- this_dir = string.gsub(this_dir,':$','/')
- if string.match(line,'^./doc') then
- -- the next file lines are in docdir "this_dir"
- is_docline = true
- else
- is_docline = false
- end -- docdir
- elseif string.match(line,'^%s*$') then
- -- empty line, do nothing
- -- now we have only file lines left, are they a docline?
- elseif is_docline then
- local fullpath = this_dir .. line
- if string.match(fullpath, pattern) then
- if lfs.isfile(fullpath) then -- cannot know from ls-R
- table.insert(docfiles,fullpath)
- end
- end
- end -- line starting with ./
- end -- for line
- end -- for database
- for no_lsr_dir in list(no_lsr_doctrees) do
- recurse_tree(no_lsr_dir, pattern)
+-- says if ext is 'good' according to ext_list
+function is_good_ext (ext)
+ for e in list (config.ext_list) do
+ if e == '*' then
+ return true
+ elseif (e == '') and (not ext) then
+ return true
+ elseif ext == e then
+ return true
+ end
+ end
+ return false
+end
+
+-- include a file in the lists if it should be
+function process_file (file, pathfile, code, pattern, sure_isfile)
+ local base, ext = string.match(file, '^(.*)%.(.*)$')
+ if string.find(pathfile, pattern, 1, no_regex) and is_good_ext (ext)
+ and (sure_isfile or lfs.isfile (pathfile)) then
+ if base == pattern then
+ table.insert(exact_docfiles, code..':'..pathfile)
+ else
+ table.insert(rel_docfiles, code..':'..pathfile)
+ end
end
- return docfiles
end
--- recursively explore a tree and put the file matching pattern in docfiles
-function recurse_tree (path, pattern)
+-- scan a tree
+function scan_tree (code, path, pattern, recurse)
for file in lfs.dir(path) do
- if file ~= "." and file ~= ".." then
- local f = path..'/'..file
- local attr = lfs.attributes (f)
- if attr then -- else stale symlink
- if attr.mode == "directory" then
- recurse_tree (f, pattern)
- else
- if string.match (f, pattern) then
- table.insert(docfiles,f)
- end
- end
+ if file ~= '.' and file ~= '..' then
+ local f = (path == '.') and file or path..'/'..file
+ if lfs.isdir(f) then
+ if recurse then scan_tree(code, f, pattern, recurse) end
+ else
+ process_file(file, f, code, pattern, true)
end
end
end
end
+-- finds a root with ls-R above path and return it or nil
+function lsr_root (path)
+ if not lfs.isdir (path) then return end
+ local root, shift = path, ''
+ if string.sub(root, -1) == '/' then root = string.sub(root, 1, -2) end
+ while string.find(root, '/', 1, true) do
+ if lfs.isfile(root..'/ls-R') then
+ return root, shift
+ end
+ local last_comp = string.match(root, '^.*/(.*)$')
+ -- /!\ cannot put last_comp in a regex: can contain special char
+ root = string.sub(root, 1, - (#last_comp + 2))
+ shift = last_comp..'/'..shift
+ end
+end
--- filename and mixed search modes
-
--- add a dot to ext except if it's empty
-function dotted(ext)
- if (ext == '') then
- return ext
- else
- return '.'..ext
+-- scan a ls-R file
+function scan_lsr (code, shift, pattern)
+ local isdoc = false
+ local current_dir
+ local lsr = assert(io.open('ls-R', 'r'))
+ while true do
+ local line = lsr:read('*line')
+ if line == nil then break end -- EOF
+ local dir_line = string.match (line, '^%./(.*):$')
+ if dir_line then
+ if string.find (dir_line, '^'..shift) then
+ isdoc = true
+ current_dir = dir_line
+ elseif isdoc then
+ break -- we're exiting the ./doc (or shift) dir, so it's over
+ end
+ elseif isdoc then
+ process_file (line, current_dir..'/'..line, code, pattern, false)
+ end
end
+ lsr:close()
end
--- simple search on filename using kpse
-function filename_search (filename)
- files = {}
- for ext in list(config.ext_list) do
- found = kpse.find_file(filename .. dotted(ext),
- "TeX system documentation")
- if found then table.insert(files, found) end
+-- find dirfiles according to pattern
+function populate_docfiles (pattern)
+ if not texdocs then get_texdocs() end
+ rel_docfiles, exact_docfiles = {}, {} -- global
+ local curr_dir = lfs.currentdir()
+ for code, docdir in ipairs (texdocs) do
+ root, shift = lsr_root (docdir)
+ if root and shift and do_recurse[code] then
+ assert(lfs.chdir(root))
+ scan_lsr(code, shift, pattern)
+ elseif (not must_have_lsr[code]) and lfs.isdir(docdir) then
+ assert(lfs.chdir(docdir))
+ scan_tree(code, '.', pattern, do_recurse[code])
+ end
end
- return files
+ assert(lfs.chdir(curr_dir))
end
--- do a filename search and try a full search if unsuccessfull
-function mixed_search (filename, alternative)
- results = filename_search (filename)
- if not results[1] then
- print ("texdoc info: No result with simple search, "..
- "trying full search mode.")
- results = pattern_search (alternative)
+-- END kpse-like
+
+function mixed_populate_docfiles (pattern)
+ populate_docfiles (pattern)
+ if not exact_docfiles[1] then
+ print ("texdoc info: No exact match, trying full search mode.")
+ exact_docfiles = rel_docfiles
end
- return results
end
@@ -575,22 +575,33 @@ function ext_pos (ext)
return ext_pos (ext)
end
--- print a list of files as a menu
-function print_menu (files)
- local n = #files
+-- display a table, sorted, numbered with given offset (0 by default)
+function display_table (t, offset)
+ offset = offset or 0
+ table.sort(t, file_order)
+ for i, val in ipairs (t) do
+ print (i+offset, val)
+ end
+end
+
+-- print a list of files as a menu (with an coptional complementary list)
+function print_menu (files, comp)
+ comp = comp or {}
+ local f = #files
+ local n = f + #comp
if n > 20 then
- io.write (n, " files found. Display the complete list? (y/N) ")
+ io.write (n, "results. Display them all? (y/N) ")
local ans = io.read(1)
- if not ((ans == 'y') or (ans == 'Y')) then return end
- end
- -- table.sort(results, file_order)
- for i, file in ipairs (files) do
- print (i, file)
+ if not ((ans == 'y') or (ans == 'Y')) then return end
end
+ display_table (files)
+ display_table (comp, f)
io.write ("Please enter the number of the file to view, or 0 to exit: ")
local num = io.read('*number')
- if num and files[num] then
+ if num and (num <= #files) and files[num] then
print ("Viewing file '"..files[num].."'.")
+ elseif num and comp[num-f] then
+ print ("Viewing file '"..comp[num-f].."'.")
elseif num ~= 0 then
print ("Incorrect input, skipping.")
end
@@ -667,41 +678,41 @@ end
exit_code = 0
for docname in list (arg) do
original_docname = docname
- if enable_alias and alias[docname]then
+ if enable_alias and alias[docname] then
print ("texdoc info: "..docname.." aliased to "..alias[docname])
docname = alias[docname]
end
local docfound = false
if (config.mode == 'search') then
- results = pattern_search (docname)
- if results[1] then
- print_menu (results)
+ populate_docfiles(docname)
+ if exact_docfiles[1] or rel_docfiles[1] then
+ print_menu (exact_docfiles, rel_docfiles)
else
apologize ('notfound', docname)
end
elseif (config.mode == 'list') then
- results = mixed_search (docname, original_docname)
- if results[1] then
- print_menu (results)
+ mixed_populate_docfiles (docname)
+ if exact_docfiles[1] then
+ print_menu (exact_docfiles)
else
apologize ('notfound', docname)
end
elseif (config.mode == 'view') then
- results = mixed_search (docname, original_docname)
- if results[1] then
- try_viewing (how_to_view(results[1]))
+ mixed_populate_docfiles (docname)
+ if exact_docfiles[1] then
+ try_viewing (how_to_view(exact_docfiles[1]))
else
apologize ('notfound', docname)
end
elseif (config.mode == 'mixed') then
- results = mixed_search (docname, original_docname)
- if (not results[1]) then -- no results
+ mixed_populate_docfiles (docname)
+ if (not exact_docfiles[1]) then -- no results
apologize ('notfound', docname)
- elseif (not results[2]) then -- 1 result (faster than table.maxn)
- local ok = try_viewing (how_to_view(results[1]))
+ elseif (not exact_docfiles[2]) then -- 1 result
+ local ok = try_viewing (how_to_view(exact_docfiles[1]))
if not ok then apologize ('oops') end
- else -- 2 or more results
- print_menu (results)
+ else -- 2 or more results
+ print_menu (exact_docfiles)
end
end -- if construct "case config.mode in"
end -- for docname in arg