l-pdfview.lua /size: 5953 b    last modification: 2025-02-21 11:03
1if not modules then modules = { } end modules ['l-pdfview'] = {
2    version   = 1.001,
3    comment   = "companion to mtx-context.lua",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- Todo: add options in cnf file
10
11-- Todo: figure out pdfopen/pdfclose on linux. Calling e.g. okular directly
12-- doesn't work in linux when issued from scite as it blocks the editor (no
13-- & possible or so). Unfortunately pdfopen keeps changing with not keeping
14-- downward compatibility (command line arguments and so).
15
16-- no 2>&1 any more, needs checking on windows
17
18local format, concat = string.format, table.concat
19
20local report  = logs.reporter("pdfview")
21local replace = utilities.templates.replace
22
23pdfview = pdfview or { }
24
25local opencalls  -- a table with templates that open a given pdf document
26local closecalls -- a table with templates that close a given pdf document
27local allcalls   -- a table with templates that close all open pdf documents
28local runner     -- runner function
29local expander   -- filename cleanup function
30
31if os.type == "windows" then
32
33    -- os.setenv("path",os.getenv("path") .. ";" .. "c:/data/system/pdf-xchange")
34    -- os.setenv("path",os.getenv("path") .. ";" .. "c:/data/system/sumatrapdf")
35
36    -- start is more flexible as it locates binaries in more places and doesn't lock
37
38    opencalls = {
39        ['default']     = [[pdfopen --rxi --file "%filename%"]],
40        ['acrobat']     = [[pdfopen --rxi --file "%filename%"]],
41        ['fullacrobat'] = [[pdfopen --axi --file "%filename%"]],
42        ['okular']      = [[start "test" okular.exe --unique "%filename%"]],
43        ['pdfxcview']   = [[start "test" pdfxcview.exe /A "nolock=yes=OpenParameters" "%filename%"]],
44        ['sumatra']     = [[start "test" sumatrapdf.exe -reuse-instance -bg-color 0xCCCCCC "%filename%"]],
45        ['auto']        = [[start "" "%filename%"]],
46    }
47    closecalls= {
48        ['default']     = [[pdfclose --file "%filename%"]],
49        ['acrobat']     = [[pdfclose --file "%filename%"]],
50        ['okular']      = false,
51        ['pdfxcview']   = false, -- [[pdfxcview.exe /close:discard "%filename%"]],
52        ['sumatra']     = false,
53        ['auto']        = false,
54    }
55    allcalls = {
56        ['default']     = [[pdfclose --all]],
57        ['acrobat']     = [[pdfclose --all]],
58        ['okular']      = false,
59        ['pdfxcview']   = false,
60        ['sumatra']     = false,
61        ['auto']        = false,
62    }
63
64    pdfview.method = "acrobat" -- no longer useful due to green pop up line and clashing reader/full
65 -- pdfview.method = "pdfxcview"
66    pdfview.method = "sumatra"
67
68    runner = function(template,variables)
69        local cmd = replace(template,variables)
70     -- cmd = cmd  .. " > /null"
71        report("command: %s",cmd)
72        os.execute(cmd)
73    end
74
75    expander = function(name)
76        -- We need to avoid issues with chdir to UNC paths and therefore expand
77        -- the path when we're current. (We could use one of the helpers instead)
78        if file.pathpart(name) == "" then
79            return file.collapsepath(file.join(lfs.currentdir(),name))
80        else
81            return name
82        end
83    end
84
85else
86
87    opencalls = {
88        ['default']   = [[pdfopen "%filename%"]],
89        ['okular']    = [[okular --unique "%filename%"]],
90        ['evince']    = [[evince "%filename%"]],
91        ['zathura']   = [[zathura "%filename%"]],
92        ['sumatra']   = [[wine "sumatrapdf.exe" -reuse-instance -bg-color 0xCCCCCC "%filename%"]],
93        ['pdfxcview'] = [[wine "pdfxcview.exe" /A "nolock=yes=OpenParameters" "%filename%"]],
94        ['auto']      = [[open "%filename%"]], -- linux: xdg-open
95    }
96    closecalls= {
97        ['default']   = [[pdfclose --file "%filename%"]],
98        ['okular']    = false,
99        ['evince']    = false,
100        ['zathura']   = [[killall zathura]],
101        ['sumatra']   = false,
102        ['auto']      = false,
103    }
104    allcalls = {
105        ['default']   = [[pdfclose --all]],
106        ['okular']    = false,
107        ['evince']    = false,
108        ['zathura']   = false,
109        ['sumatra']   = false,
110        ['auto']      = false,
111    }
112
113    pdfview.method = "okular"
114    pdfview.method = "sumatra" -- faster and more complete
115
116    runner = function(template,variables)
117        local cmd = replace(template,variables)
118        cmd = cmd .. " 1>/dev/null 2>/dev/null &"
119        report("command: %s",cmd)
120        os.execute(cmd)
121    end
122
123    expander = function(name)
124        return name
125    end
126
127end
128
129directives.register("pdfview.method", function(v)
130    pdfview.method = (opencalls[v] and v) or 'default'
131end)
132
133function pdfview.setmethod(method)
134    if method and opencalls[method] then
135        pdfview.method = method
136    end
137end
138
139function pdfview.methods()
140    return concat(table.sortedkeys(opencalls), " ")
141end
142
143function pdfview.status()
144    return format("pdfview methods: %s, current method: %s (directives_pdfview_method)",pdfview.methods(),tostring(pdfview.method))
145end
146
147local function fullname(name)
148    return file.addsuffix(name,"pdf")
149end
150
151function pdfview.open(...)
152    local opencall = opencalls[pdfview.method]
153    if opencall then
154        local t = { ... }
155        for i=1,#t do
156            local name = expander(fullname(t[i]))
157            if io.exists(name) then
158                runner(opencall,{ filename = name })
159            end
160        end
161    end
162end
163
164function pdfview.close(...)
165    local closecall = closecalls[pdfview.method]
166    if closecall then
167        local t = { ... }
168        for i=1,#t do
169            local name = expander(fullname(t[i]))
170            if io.exists(name) then
171                runner(closecall,{ filename = name })
172            end
173        end
174    end
175end
176
177function pdfview.closeall()
178    local allcall = allcalls[pdfview.method]
179    if allcall then
180        runner(allcall)
181    end
182end
183
184return pdfview
185