summaryrefslogtreecommitdiff
path: root/Master/texmf/scripts/texdoc/config.tlu
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf/scripts/texdoc/config.tlu')
-rw-r--r--Master/texmf/scripts/texdoc/config.tlu486
1 files changed, 486 insertions, 0 deletions
diff --git a/Master/texmf/scripts/texdoc/config.tlu b/Master/texmf/scripts/texdoc/config.tlu
new file mode 100644
index 00000000000..1098d39b7ea
--- /dev/null
+++ b/Master/texmf/scripts/texdoc/config.tlu
@@ -0,0 +1,486 @@
+-- configuration handling for 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', 'table', 'os', 'kpse', 'lfs', 'io',
+ 'arg',
+ 'ipairs', 'pairs', 'tonumber', 'tostring', 'setmetatable', 'next', 'print',
+ 'assert', 'error',
+ 'C',
+ 'err_print', 'win32_hook',
+ 'config', 'alias'
+})
+
+----------------------- hide config and alias tables -----------------------
+
+function set_read_only(table, name)
+ assert(next(table) == nil,
+ 'Internal error: '..name..' should be empty at this point.')
+ local ro = 'Internal error: attempt to update read-only table '
+ local real = {}
+ setmetatable(table, {
+ __index = real,
+ __newindex = function () error(ro..name..'.') end,
+ })
+ return function(k, v) real[k] = v end
+end
+
+real_set_config = set_read_only(config, 'config')
+real_set_alias = set_read_only(alias, 'alias')
+
+---------------------------- general functions -----------------------------
+
+-- set a config parameter, but don't overwrite it if already set
+-- three special types: *_list (list), *_switch (boolean), *_level (number)
+function set_config_element (key, value, context)
+ local is_known = false -- is key a valid option?
+ local option
+ for _, option in ipairs(C.known_options) do
+ if string.match(key, '^'..option..'$') then is_known = true break end
+ end
+ -- warn and exit if key is not a known option
+ if not is_known then config_warn(key, nil, context, true) return end
+ -- exit if key is already set (/!\ must test for nil, not false)
+ if not (config[key] == nil) then return nil end
+ -- detect the type of the key
+ if string.match(key, '_list$') then
+ -- coma-separated list
+ local values = string.explode(value, ',')
+ local inverse = {}
+ for i, j in ipairs(values) do -- sanitize values...
+ j = string.gsub(j, '%s*$', '')
+ j = string.gsub(j, '^%s*', '')
+ values[i] = j
+ inverse[j] = i -- ... and build inverse mapping on the way
+ end
+ real_set_config(key, values)
+ real_set_config(key..'_inv', inverse)
+ real_set_config(key..'_max', #values)
+ elseif string.find (key, '_switch$') then
+ -- boolean
+ if value == 'true' then
+ real_set_config(key, true)
+ elseif value == 'false' then
+ real_set_config(key, false)
+ else
+ config_warn (key, value, context)
+ end
+ elseif string.find (key, '_level$') then
+ -- integer
+ local val = tonumber (value)
+ if val then
+ real_set_config(key, val)
+ else
+ config_warn (key, value, context)
+ end
+ else -- string
+ real_set_config(key, value)
+ end
+ -- special case: if we just set verbosity_level, print version info now
+ if key == 'verbosity_level' then
+ err_print(arg[0]..' version '..C.version, 'debug1')
+ end
+ -- now tell what we have just done, for debugging
+ err_print('Setting "'..key..'='..value..'" '
+ ..context_to_string(context)..'.', 'debug2')
+end
+
+-- a helper function for warning messages in the above
+function config_warn (key, value, context, unknown)
+ local begin = unknown
+ and 'Unknown option "'..key..'"'
+ or 'Illegal value "'..tostring(value)..'" for option "'..key..'"'
+ local ending = '. Skipping.'
+ err_print (begin..' '..context_to_string(context)..ending, 'warning')
+end
+
+-- interpreting 'context' for the previous functions
+function context_to_string(context)
+ if not context then return '(no context)' end
+ if context.src == 'cl' then
+ return 'from command line option "'..context.name..'"'
+ elseif context.src == 'env' then
+ return 'from environment variable "'..context.name..'"'
+ elseif context.src == 'file' then
+ return 'in file "'..context.file..'" on line '..context.line
+ elseif context.src == 'def' then
+ return 'from built-in defaults'
+ else
+ return 'from unkown source (should not happen, please report)'
+ end
+end
+
+-- set a whole list, also whithout overwriting
+function set_config_list (conf, context)
+ for key, value in pairs(conf) do
+ set_config_element (key, value, context)
+ end
+end
+
+-- set an alias (w/o overwriting)
+function set_alias (key, value)
+ if alias[key] == nil then
+ real_set_alias(key, value)
+ end
+end
+
+------------------------ options from command line -------------------------
+
+-- set config from the command line
+-- Please make sure to update C.usage_msg accordingly
+-- and set a default value in setup_config_from_defaults() if relevant.
+function setup_config_from_cl ()
+ local curr_arg
+ local function set_config_elt(key, val)
+ set_config_element(key, val, {src='cl', name=curr_arg})
+ end
+ while arg[1] and string.match(arg[1],'^%-') do
+ curr_arg = table.remove(arg,1)
+ -- special options
+ if (curr_arg == '-h') or (curr_arg == '--help') then
+ print (C.usage_msg)
+ os.exit(0)
+ elseif (curr_arg == '-V') or (curr_arg == '--version') then
+ print (C.progname .. ' ' .. C.version )
+ os.exit(0)
+ elseif (curr_arg == '-f') or (curr_arg == '--files') then
+ print (C.progname .. ' ' .. C.version )
+ setup_config_from_files ()
+ show_config_files (print, true)
+ os.exit(0)
+ -- options related to mode
+ elseif (curr_arg == '-w') or (curr_arg == '--view') then
+ set_config_elt('mode', 'view')
+ elseif (curr_arg == '-m') or (curr_arg == '--mixed') then
+ set_config_elt('mode', 'mixed')
+ elseif (curr_arg == '-l') or (curr_arg == '--list') then
+ set_config_elt('mode', 'list')
+ elseif (curr_arg == '-s') or (curr_arg == '--search') then
+ set_config_elt ('mode', 'search')
+ elseif (curr_arg == '-r') or (curr_arg == '--regex') then
+ set_config_elt ('mode', 'regex')
+ -- interaction
+ elseif (curr_arg == '-I') or (curr_arg == '--nointeract') then
+ set_config_elt('interact_switch', 'false')
+ elseif (curr_arg == '-i') or (curr_arg == '--interact') then
+ set_config_elt('interact_switch', 'true')
+ -- output format
+ elseif (curr_arg == '-M') or (curr_arg == '--machine') then
+ set_config_elt('machine_switch', 'true')
+ -- alias
+ elseif (curr_arg == '-A') or (curr_arg == '--noalias') then
+ set_config_elt('alias_switch', 'false')
+ elseif (curr_arg == '-a') or (curr_arg == '--alias') then
+ set_config_elt('alias_switch', 'true')
+ -- verbosity
+ elseif (curr_arg == '-d') or (curr_arg == '--debug') then
+ set_config_elt('verbosity_level', C.err_max)
+ elseif string.match(curr_arg, '^%-v') then
+ local value = string.gsub(curr_arg, '^%-v=?', '')
+ set_config_elt('verbosity_level', value)
+ elseif string.match(curr_arg, '^%-%-verbosity') then
+ local value = string.gsub(curr_arg, '^%-%-verbosity=?', '')
+ set_config_elt('verbosity_level', value)
+ -- extensions list
+ elseif string.match(curr_arg, '^%-e') then
+ local value = string.gsub(curr_arg, '^%-e=?', '')
+ set_config_elt('ext_list', value)
+ elseif string.match(curr_arg, '^%-%-extensions') then
+ local value = string.gsub(curr_arg, '^%-%-extensions=?', '')
+ set_config_elt('ext_list', value)
+ -- problem
+ else
+ err_print ("unknown option: "..curr_arg, "error")
+ print (C.error_msg)
+ os.exit(2)
+ end
+ end
+end
+
+------------------------- config from environment --------------------------
+
+-- set config from environment if available
+function setup_config_from_env ()
+ local function set_config_elt_from_vars(key, vars)
+ for _, var in ipairs(vars) do
+ local value = os.getenv(var)
+ if value then
+ set_config_element(key, value, {src='env', name=var})
+ end
+ end
+ end
+ set_config_elt_from_vars('viewer_pdf',
+ {"PDFVIEWER_texdoc", "TEXDOCVIEW_pdf", "TEXDOC_VIEWER_PDF", "PDFVIEWER"})
+ set_config_elt_from_vars('viewer_ps',
+ {"PSVIEWER_texdoc", "TEXDOCVIEW_ps", "TEXDOC_VIEWER_PS", "PSVIEWER"})
+ set_config_elt_from_vars('viewer_dvi',
+ {"DVIVIEWER_texdoc", "TEXDOCVIEW_dvi", "TEXDOC_VIEWER_DVI", "DVIVIEWER"})
+ set_config_elt_from_vars('viewer_html',
+ {"BROWSER_texdoc", "TEXDOCVIEW_html", "TEXDOC_VIEWER_HTML", "BROWSER"})
+ set_config_elt_from_vars('viewer_txt',
+ {"PAGER_texdoc", "TEXDOCVIEW_txt", "TEXDOC_VIEWER_TXT", "PAGER"})
+end
+
+---------------------- options and aliases from files ----------------------
+
+-- set config+aliases from a particular config file assumed to exist
+function read_config_file(configfile)
+ local cnf = assert(io.open(configfile, 'r'))
+ local lineno = 0
+ while true do
+ local key, val
+ local line=cnf:read('*line')
+ lineno = lineno + 1
+ if line == nil then break end -- EOF
+ line = string.gsub(line, '%s*#.*$', '') -- comments begin with #
+ line = string.gsub(line, '%s*$', '') -- remove trailing spaces
+ line = string.gsub(line, '^%s*', '') -- remove leading spaces
+ key, val = string.match(line, '^([%a%d_]+)%s*=%s*(.+)')
+ if key and val then
+ set_config_element(key, val, {
+ src='file', file=configfile, line=lineno})
+ else
+ key, val = string.match(line, '^alias%s+([%a%d_-]+)%s*=%s*(.+)')
+ if key and val then
+ set_alias(key, val)
+ else
+ if (not string.match (line, '^%s*$')) then
+ err_print ('syntax error in '..configfile..
+ ' at line '..lineno..'.', 'warning')
+ end
+ end
+ end
+ end
+ cnf:close()
+end
+
+-- return a table with config file and if they exist
+function get_config_files ()
+ local platform = string.match (kpse.var_value ('SELFAUTOLOC'), '.*/(.*)$')
+ local TEXMFHOME = kpse.var_value ('TEXMFHOME')
+ local TEXMFLOCAL = kpse.var_value ('TEXMFLOCAL')
+ local TEXMFMAIN = kpse.var_value ('TEXMFMAIN')
+ return {
+ TEXMFHOME .. '/texdoc/texdoc-'..platform..'.cnf',
+ TEXMFHOME .. '/texdoc/texdoc.cnf',
+ TEXMFHOME .. '/texdoc/texdoc-dist.cnf',
+ TEXMFLOCAL .. '/texdoc/texdoc-'..platform..'.cnf',
+ TEXMFLOCAL .. '/texdoc/texdoc.cnf',
+ TEXMFMAIN .. '/texdoc/texdoc.cnf'
+ }
+end
+
+-- the config_files table is shared by the next two functions
+do
+local config_files = {}
+
+-- set config/aliases from all config files
+function setup_config_from_files ()
+ for i, file in ipairs (get_config_files ()) do
+ local found = lfs.isfile(file)
+ config_files[i] = {
+ path = file,
+ status = found and (config.lastfile_switch
+ and 'disabled' or 'active') or 'absent',
+ }
+ if config_files[i].status == 'active' then
+ read_config_file (file)
+ end
+ end
+end
+
+-- now a special information function (see -f,--file option)
+function show_config_files (print_fun, prefix)
+ print_fun("Configuration files are:")
+ for i, file in ipairs (config_files) do
+ local home = prefix and
+ ((i==2) and "(*) " or " ") -- home conffile is the 2nd
+ or ''
+ print_fun (home..file.status..'\t'..win32_hook(file.path))
+ end
+ if prefix then
+ print("(*) This is the recommended configuration file "
+ .. "for your personal preferences.")
+ end
+end
+
+end -- scope of config_files
+
+---------------------- options from built-in defaults ----------------------
+
+-- for default viewer on general Unix, we have a list; the following two
+-- functions are used to check in the path which program is available
+
+-- check if "name" is the name of a file in the path
+-- Warning: to be used only on Unix! (separators, and PATH irrelevant on win32)
+function is_in_path(name)
+ local path_list = string.explode(os.getenv("PATH"), ':')
+ for _, path in ipairs(path_list) do
+ if lfs.isfile(path..'/'..name) then return true end
+ end
+ return false
+end
+
+-- return the first element of "list" whose name is found in path, or nil
+function first_in_path(cmds)
+ for _, cmd in ipairs(cmds) do
+ if is_in_path(cmd[1]) then return cmd[2] end
+ end
+ return nil
+end
+
+-- set some fall-back default values if no previous value is set
+function setup_config_from_defaults()
+ local function set_config_ls(ls) set_config_list(ls, {src='def'}) end
+ local function set_config_elt(key, val)
+ set_config_element(key, val, {src='def'})
+ end
+ if (os.type == "windows") then
+ set_config_ls {
+ -- Use 'start' to get file associations.
+ -- We need to quote the filenames, but the first quoted argument
+ -- is considered as the title by start, so we provide a dummy title.
+ -- Also, since the command line parser removes quotes if there
+ -- is no space inside, the dummy title must contain spaces.
+ viewer_dvi = 'start "texdoc dvi viewer"',
+ viewer_html = 'start "texdoc html viewer"',
+ viewer_pdf = 'start "texdoc pdf viewer"',
+ viewer_ps = 'start "texdoc ps viewer"',
+ -- 'more' is always available.
+ -- However, we can't assume texdoc is called from a cmd.exe window
+ -- (it can be run from the start->run menu), hence we make sure
+ -- to open a new window if needed.
+ viewer_txt = 'start cmd /k more',
+ }
+ elseif (os.name == 'macosx') then
+ set_config_ls {
+ viewer_dvi = 'open',
+ viewer_html = 'open',
+ viewer_pdf = 'open',
+ viewer_ps = 'open',
+ viewer_txt = 'less',
+ }
+ else -- generic Unix
+ set_config_ls {
+ viewer_dvi = first_in_path {
+ {'evince', '(evince %s) &'},
+ {'okular', '(okular %s) &'},
+ {'kdvi', '(kdvi %s) &'},
+ {'xgdvi', '(xgdvi %s) &'},
+ {'spawg', '(spawg %s) &'},
+ {'spawx11', '(spawx11 %s) &'},
+ {'tkdvi', '(tkdvi %s) &'},
+ {'dvilx', '(dvilx %s) &'},
+ {'advi', '(advi %s) &'},
+ {'xdvik-ja', '(xdvik-ja %s) &'},
+ {'xdvi', '(xdvi %s) &'},
+ {'gnome-open', '(gnome-open %s) &'}, -- gnome
+ {'kde-open', '(kde-open %s) &'}, -- kde 4
+ {'kfmclient', '(kfmclient exec %s) &'}, -- older kde
+ {'exo-open', '(exo-open %s) &'}, -- xfce
+ {'xdg-open', '(xdg-open %s) &'}, -- freedesktop.org
+ {'see', '(see %s) &'}
+ },
+ viewer_html = first_in_path {
+ {'firefox', '(firefox %s) &'},
+ {'seamonkey', '(seamonkey %s) &'},
+ {'mozilla', '(mozilla %s) &'},
+ {'konqueror', '(konqueror %s) &'},
+ {'epiphany', '(epiphany %s) &'},
+ {'opera', '(opera %s) &'},
+ {'w3m', 'w3m'},
+ {'links', 'links'},
+ {'lynx', 'lynx'},
+ {'gnome-open', '(gnome-open %s) &'}, -- gnome
+ {'kde-open', '(kde-open %s) &'}, -- kde 4
+ {'kfmclient', '(kfmclient exec %s) &'}, -- older kde
+ {'exo-open', '(exo-open %s) &'}, -- xfce
+ {'xdg-open', '(xdg-open %s) &'}, -- freedesktop.org
+ {'see', 'see'}
+ },
+ viewer_pdf = first_in_path {
+ {'evince', '(evince %s) &'},
+ {'okular', '(okular %s) &'},
+ {'kpdf', '(kpdf %s) &'},
+ {'xpdf', '(xpdf %s) &'},
+ {'acroread', '(xpdf %s) &'},
+ {'gnome-open', '(gnome-open %s) &'}, -- gnome
+ {'kde-open', '(kde-open %s) &'}, -- kde 4
+ {'kfmclient', '(kfmclient exec %s) &'}, -- older kde
+ {'exo-open', '(exo-open %s) &'}, -- xfce
+ {'xdg-open', '(xdg-open %s) &'}, -- freedesktop.org
+ {'see', '(see %s) &'}
+ },
+ viewer_ps = first_in_path {
+ {'evince', '(evince %s) &'},
+ {'okular', '(okular %s) &'},
+ {'kghostview', '(kghostview %s) &'},
+ {'gv', '(gv %s) &'},
+ {'gnome-open', '(gnome-open %s) &'}, -- gnome
+ {'kde-open', '(kde-open %s) &'}, -- kde 4
+ {'kfmclient', '(kfmclient exec %s) &'}, -- older kde
+ {'exo-open', '(exo-open %s) &'}, -- xfce
+ {'xdg-open', '(xdg-open %s) &'}, -- freedesktop.org
+ {'see', '(see %s) &'}
+ },
+ viewer_txt = first_in_path {
+ {'most', 'most'},
+ {'less', 'less'},
+ {'more', 'more'}
+ }
+ }
+ end
+ -- then various, platform independant, stuff
+ set_config_ls {
+ mode = 'view',
+ interact_switch = 'true',
+ machine_switch = 'false',
+ verbosity_level = '2',
+ ext_list = 'pdf, html, txt, man1.pdf, man5.pdf, ps, dvi, ',
+ }
+ -- must be set after mode!
+ set_config_elt ('alias_switch', alias_from_mode(config.mode))
+ -- zip-related options
+ if C.support_zipped then
+ set_config_ls {
+ zipext_list = 'gz, bz2',
+ unzip_gz = 'gzip -d -c',
+ unzip_bz2 = 'bzip -d -c',
+ rm_file = 'rm -f',
+ rm_dir = 'rmdir'
+ }
+ end
+end
+
+-- the default value of config.alias_switch depends on the mode as follows
+function alias_from_mode (mode) -- /!\ returns a string!
+ if (mode == 'view') or (mode == 'mixed') or (mode == 'list') then
+ return 'true'
+ else
+ return 'false'
+ end
+end
+
+-------------------------- set all configuration ---------------------------
+
+-- populate the config and alias arrays
+function setup_config_and_alias()
+ -- setup config from all sources
+ setup_config_from_cl()
+ setup_config_from_env()
+ setup_config_from_files()
+ setup_config_from_defaults()
+ -- we were waiting for config.verbosity_level to be know to do this
+ show_config_files(function(s) err_print(s, 'debug1') end)
+end
+
+-- finally export a few symbols
+export_symbols(L, {
+ 'setup_config_and_alias',
+})