Merge with git+ssh://pasky.or.cz/srv/git/elinks.git
[elinks.git] / doc / lua-scripting.txt
blobfc0f3e83373706226757e305df79fa4f24cf2dc1
1 [[lua-scripting]]
2 Scripting ELinks with Lua
3 -------------------------
5 This file documents the Lua scripting interface of the ELinks web browser.
7 Introduction
8 ~~~~~~~~~~~~
10 What is it
11 ^^^^^^^^^^
13 Lua scripting capabilities permit users to customize the ELinks behaviour to
14 unusual degree - they allow automatic rewriting of HTML code of the received
15 documents, rewriting of the URLs entered by user etc. You can even write your
16 own bookmarks system with Lua. See also contrib/lua/ for some examples of the
17 possibilities of ELinks Lua support.
19 Please do not confuse Lua scripting with JavaScript, EcmaScript, VBScript and
20 similiar. Those are embedded in page, allowing per-document scripting related
21 to its presentation and providing some degree of interactivity etc. On the
22 contrary, the current Lua support permits scripts to be embedded to the
23 browser directly, changing the behaviour of the browser, not the document.
25 The original Lua support (in the form of Links-Lua fork of original Links) was
26 written by Peter Wang and Cliff Cunnington.  There are some rough edges
27 remaining, but is suitable for everyday use (I have been using it every day
28 for a year).
30 Where to get it
31 ^^^^^^^^^^^^^^^
33 The Lua scripting support comes with the stock ELinks distribution, no
34 additional patches and tweaks should be needed.
36 The web site of the original Links-Lua is at
37 link:http://links.sourceforge.net/links-lua/[]. Some older patches against
38 regular Links are available at
39 link:http://www.sourceforge.net/projects/links/[], but they are not being
40 maintained.
42 Lua can be found at link:http://www.lua.org/[].
44 What it runs on
45 ^^^^^^^^^^^^^^^
47 The Lua support has only been tested under Linux, although it *should*
48 work under other platforms that ELinks and Lua support (perhaps with some
49 changes to source code?).
51 Also, note that many of the scripts given here assume a Unix system.
52 Your mileage will definitely vary on other platforms.
55 Installing
56 ~~~~~~~~~~
58 Installing Lua
59 ^^^^^^^^^^^^^^
61 Before you can compile ELinks with Lua support, you must compile and install
62 Lua.  The following instructions are for a Linux system.  People on other
63 systems should try to enable `popen` support, but this is not necessary
64 (you will lose a bit of functionality though).
66 1. Download and unpack the Lua `tar.gz` or `zip` somewhere.
67 2. `cd` into the `lua` directory.
68 3. Open `config` in a text editor and uncomment the `POPEN` line.
69 4. Optionally, change the `INSTALL_ROOT line.
70 5. Run `make; make so; make sobin; make install`.  
72 On systems without shared object support, simply run `make; make install`
73 instead.
76 Installing ELinks
77 ^^^^^^^^^^^^^^^^^
79 Follow the instructions for building ELinks (it is the standard
80 `./configure; make; make install` procedure).  During the configure
81 step make sure that Lua has been detected on your system.
84 Running ELinks with Lua
85 ^^^^^^^^^^^^^^^^^^^^^^^
87 Simply start ELinks as you normally would.  To check you have Lua support
88 compiled in, open up the "Help | About" dialog box.  It should list "Lua"
89 under "Features".  If not, make sure you do not have other copies of ELinks
90 running, or start ELinks again with the "-no-connect" option on the
91 command-line.
94 Using ELinks with Lua
95 ~~~~~~~~~~~~~~~~~~~~~
97 Out of the box, ELinks with Lua will do nothing different from regular ELinks.
98 You need to write some scripts.
100 ELinks Lua additions
101 ^^^^^^^^^^^^^^^^^^^^
103 The Lua support is based on the idea of @dfn{hooks}.  A hook is a function that
104 gets called at a particular point during the execution of ELinks.  To make
105 ELinks do what you want, you can add and edit such hooks.
107 The Lua support also adds an extra dialog box, which you can open while in
108 ELinks with the comma (`,`) key.  Here you can enter Lua expressions for
109 evaluation, or override it to do something different.
111 And finally, you can bind keystrokes to Lua functions.  These keystrokes
112 won't let you do any more than is possible with the Lua Console, but
113 they're more convenient.
115 Note that this document assumes you have some knowledge of programming in Lua.
116 For that, you should refer to the Lua reference manual
117 (link:http://www.lua.org/docs.html[]). In fact, the language is relatively
118 trivial, though. You could already do wonders with simply refactoring the
119 example scripts.
121 Config file
122 ^^^^^^^^^^^
124 On startup, ELinks reads in two Lua scripts.  Firstly, a system-wide
125 configuration file called `/etc/elinks/hooks.lua`, then a file in your home
126 directory called `~/.elinks/hooks.lua`.  From these files, you can include
127 other Lua files with `dofile`, if necessary.
129 To see what kind of things you should put in here, look at
130 `contrib/lua/hooks.lua`.
132 Hooks
133 ^^^^^
135 The following hooks are available.
137 goto_url_hook (url, current_url)::
138         This hook is called when the user enters a string into the "Go to URL"
139         dialog box.  It is given the string entered, and the current URL
140         (which may be `nil`).  It should return a string, which is the URL
141         that ELinks should follow, or `nil` to cancel the operation.
143 follow_url_hook (url)::
144         This hook is passed the URL that Links is about to follow.  It should
145         return a string (the URL modified or unmodified), or `nil` to stop
146         ELinks following the URL
148 pre_format_html_hook (url, html)::
149         This hook gets called just before the final time an HTML document is
150         formatted, i.e. it only gets called once, after the entire document is
151         downloaded.  It will be passed the URL and HTML text as strings, and
152         should return the modified HTML text, or `nil` if there were no
153         modifications.
155 lua_console_hook (string)::
156         This hook is passed the string that the user entered into the "Lua
157         Console" dialog box.  It should return two values: the type of action
158         to take (`run`, `eval`, `goto-url` or `nil`), and
159         a second argument, which is the shell command to run or the Lua
160         expression to evaluate. Examples:
161          - `return "run", "someprogram"` will attempt to run the program
162            `someprogram`.
163          - `return "eval", "somefunction(1+2)"` will attempt to call the Lua
164            function `somefunction` with an argument, 3.
165          - `return "goto-url", "http://www.bogus.com"` will ask Links to visit
166            the URL "http://www.bogus.com".
167          - `return nil` will do nothing.
169 quit_hook ()::
170         This hook is run just before ELinks quits.  It is useful for cleaning
171         up things, such as temporary files you have created.
174 Functions
175 ^^^^^^^^^
177 As well as providing hooks, ELinks provides some functions in addition to the
178 standard Lua functions.
180 enable_systems_functions ()::
181 Enable some potentially dangerous functions, as well as some other
182 functions which were unfortunate enough to be lumped in the same group.
184 The functions are: `openfile`, `closefile`, `readfrom`, `writeto`, `appendto`,
185 `pipe_read`, `remove`, `rename`, `flush`, `seek`, `tmpname`, `read`, `write`
186 `execute`, `exit`, `clock`, `date`, `getenv`, `setlocale`.
188 Note: `setlocale` is a standard Lua function and will not affect
189 the current ELinks locale.
190 @end deffn
192 current_url ()::
193         Returns the URL of the current page being shown (in the ELinks session
194         that invoked the function).
196 current_link ()::
197         Returns the URL of the currently selected link, or `nil` if none is
198         selected.
200 current_title ()::
201         Returns the title of the current page, or `nil` if none.
203 current_document ()::
204         Returns the current document as a string, unformatted.
206 current_document_formatted ([width])::
207         Returns the current document, formatted for the specified screen
208         width.  If the width is not specified, then the document is formatted
209         for the current screen width (i.e. what you see on screen).  Note that
210         this function does *not* guarantee all lines will be shorter than
211         `width`, just as some lines may be wider than the screen when
212         viewing documents online.
214 pipe_read (command)::
215         Executes `command` and reads in all the data from stdout, until there
216         is no more.  This is a hack, because for some reason the standard Lua
217         function `read` seems to crash ELinks when used in pipe-reading mode.
219 execute (string)::
220         Executes shell commands `string` and returns the exit code.  Beware
221         that you must not read or write to stdin and stdout.  And unlike the
222         standard Lua function of the same name, the return value is
223         meaningless.
225 bind_key (keymap, keystroke, function)::
226         Currently, `keymap` must be the string `"main"`.  Keystroke is a
227         keystroke as you would write it in the ELinks config file
228         `~/.elinks/elinks.conf`.  The function `function` should take no
229         arguments, and should return the same values as `lua_console_hook`.
232 User protocol
233 ^^^^^^^^^^^^^
235 There is one more little thing which Links-Lua adds, which will not be
236 described in detail here.  It is the fake "user:" protocol, which can be used
237 when writing your own addons.  It allows you to generate web pages containing
238 links to "user://blahblah", which can be intercepted by the `follow_url_hook`
239 (among other things) to perform unusual actions.  For a concrete example, see
240 the bookmark addon.
243 Example recipes
244 ~~~~~~~~~~~~~~~
246 This chapter contains some example scripts that you can use.  All of them come
247 from `contrib/lua/hooks.lua`.  I really recommend you to see it directly
248 instead of copying code out of this document.  Also, not everything in there is
249 covered here.
251 If you would like to contribute scripts, that would be great!  Please send
252 them to me at mailto:tjaden@@users.sourceforge.net[].  Cliff and I plan to
253 start a script repository, provided we get some contributions.  As for script
254 ideas, you'll just have to be a little creative :-)
256 Also take a look at the `contrib/lua/` directory in the ELinks distribution.
257 Note that Peter and Cliff don't maintain the Lua support intensively anymore,
258 thus it would be probably nice to Cc me (mailto:pasky@@ucw.cz[]) if you want
259 to contribute some patch, so that I would be able to add it to the ELinks
260 distribution.
263 Go to URL on steroids
264 ^^^^^^^^^^^^^^^^^^^^^
266 There are some web sites that I visit often.  Bookmarks are okay, but they are
267 separate from the "Go to URL" dialog box, so I keep forgetting to use them.
268 Also, when I visit a search engine home page, all I really want to do is enter
269 a search term.
271 The following script allows me to type certain strings into the "Go to URL"
272 dialog box, and it will convert them to the URL I actually want to visit.  As
273 a bonus, it allows me perform some searches on sites like Google without
274 loading up the front page first.
276 -------------------------------------------------------------------------------
277 function match (prefix, url)
278     return strsub (url, 1, strlen (prefix)) == prefix
281 function strip (str)
282     return gsub (str, "^%s*(.-)%s*$", "%1")
285 function plusify (str)
286     return gsub (str, "%s", "+")
289 function goto_url_hook (url, current_url)
290     -- Google search (e.g. ,gg unix browsers).
291     if match (",gg", url) then
292         url = plusify (strip (strsub (url, 4)))
293         return "http://www.google.com/search?q="..url.."&btnG=Google+Search"
295     -- Freshmeat search.
296     elseif match (",fm", url) then
297         url = plusify (strip (strsub (url, 4)))
298         return "http://www.freshmeat.net/search/?q="..url
300     -- Appwatch search (e.g. ,aw lynx).
301     elseif match (",aw", url) then
302         url = plusify (strip (strsub (url, 4)))
303         return "http://www.appwatch.com/Linux/Users/find?q="..url
304     
305     -- Dictionary.com search (e.g. ,dict congenial).
306     elseif match (",dict", url) then
307         url = plusify (strip (strsub (url, 6)))
308         return "http://www.dictionary.com/cgi-bin/dict.pl?db=%2A&term="..url
310     -- RPM search (e.g. ,rpm links).
311     elseif match (",rpm", url) then
312         url = plusify (strip (strsub (url, 5)))
313         return "http://www.rpmfind.net/linux/rpm2html/search.php?query="
314                 ..url.."&submit=Search+..."
315         
316     -- Netcraft.com search (e.g. ,whatis www.google.com).
317     elseif match (",whatis", url) then
318         url = plusify (strip (strsub (url, 8)))
319         return "http://uptime.netcraft.com/up/graph/?host="..url
321     -- LinuxToday home page.
322     elseif match (",lt", url) then
323         return "http://linuxtoday.com/"
325     -- Weather forecast for Melbourne, Australia.
326     elseif match (",forecast", url) then
327         return "http://www.bom.gov.au/cgi-bin/wrap_fwo.pl?IDF02V00.txt"
329     -- Unmatched
330     else
331         return url
332     end
334 -------------------------------------------------------------------------------
336 (Note that this was noticably enhanced and rewritten in the ELinks standart
337 hooks.)
340 Expanding ~ (tilde)
341 ^^^^^^^^^^^^^^^^^^^
343 By adding an extra snippet of code to the previous example, we can make ELinks
344 expand pathnames such as `~/foo/bar`
345 and `~user/zappo`, like in the shell
346 and other Unix programs.
348 -------------------------------------------------------------------------------
349 -- Home directory: If you do not enable system functions, you will need
350 -- to set the following to your home directory.
352 home_dir = (getenv and getenv ("HOME")) or "/home/MYSELF"
354 function goto_url_hook (url, current_url)
355                 .
356                 .
358     -- Expand ~ to home directories.
359     elseif match ("~", url) then
360         if strsub(url, 2, 2) == "/" then    -- ~/foo
361             return home_dir..strsub(url, 2)
362         else                                -- ~foo/bar
363             return "/home/"..strsub(url, 2)
364         end
366                 .
367                 .
368 -------------------------------------------------------------------------------
371 Filtering crap
372 ^^^^^^^^^^^^^^
374 Many web pages nowadays have columns to the left and right of the text, which
375 are utterly useless.  If you happen to be viewing the page in a 80x25 screen,
376 the text you want to read ends up crammed into a tiny space in the centre.  We
377 use ELinks Lua support to manipulate the HTML before it reaches the parser.
380 linuxtoday.com
381 ++++++++++++++
383 Note: This recipe is out of date.
385 Linux Today has two problems when viewed in ELinks: the useless columns on the
386 left and the right and all the text appears in cyan.  Here is a quick recipe
387 to fix that:
389 -------------------------------------------------------------------------------
390 -- Plain strfind (no metacharacters)
391 function sstrfind (s, pattern)
392     return strfind (s, pattern, 1, 1)
395 function pre_format_html_hook (url, html)
396     -- Strip the left and right columns from Linux Today pages
397     -- and change the font colour to white.
398     if sstrfind (url, "linuxtoday.com") then
399         if sstrfind (url, "news_story") then
400             html = gsub (html, '<TABLE CELLSPACING="0".-</TABLE>', '', 1)
401             html = gsub (html, '<TR BGCOLOR="#FFF.-</TR></TABLE>', '', 1)
402         else
403             html = gsub (html, 'WIDTH="120">\n<TR.+</TABLE></TD>', '>', 1)
404         end
405         html = gsub (html, '<A HREF="http://www.internet.com.-</A>', '')
406         html = gsub (html, "<IFRAME.-</IFRAME>", "")
407         -- emphasis in text is lost
408         return gsub (html, 'text="#002244"', 'text="#001133"', 1)
409     end
411     return nil
413 -------------------------------------------------------------------------------
415 linuxgames.com
416 ++++++++++++++
418 Here is a simpler example, for link:http://www.linuxgames.com/[].
420 -------------------------------------------------------------------------------
421 function pre_format_html_hook (url, html)
422                 .
423                 .
425     elseif strfind (url, "linuxgames.com", 1, 1) then
426         return gsub (html, "<CENTER>.-</center>", "", 1)
428                 .
429                 .
430 -------------------------------------------------------------------------------
433 Reading gzipped files
434 ^^^^^^^^^^^^^^^^^^^^^
436 Note: ELinks already supports gzipped files natively.
438 Sometimes documents come gzipped in order to save space, but then you need to
439 uncompress them to read them with ELinks.  Here is a recipe to handle gzipped
440 files on a Unix system.
442 -------------------------------------------------------------------------------
443 -- This script requires system functions.
445 function pre_format_html_hook (url, html)
446                 .
447                 .
449     -- Handle gzip'd files within reasonable size.
450     if strfind (url, "%.gz$") and strlen (html) < 65536 then
451         local tmp = tmpname ()
452         writeto (tmp) write (html) writeto ()
453         html = pipe_read ("(gzip -dc "..tmp.." || cat "..tmp..") 2>/dev/null")
454         remove (tmp)
455         return html
456     end
458                 .
459                 .
460 -------------------------------------------------------------------------------
463 Printing
464 ^^^^^^^^
466 Printing a web page with ELinks usually involves quite a few steps: Save the
467 current document onto disk.  Run it through ELinks on the command-line (so it
468 fits into 80 columns) to generate a plain text version.  Remove the 80th
469 column from the text version, as it will make printers wrap down to the next
470 line.  Finally, run the processed file through `lpr', then delete it.
472 The following functions allow you to print web pages directly from ELinks,
473 using `lpr' or `enscript'.  Type `lpr()` or `enscript()` in the Lua Console to
474 run them.  (In the `hooks.lua`, I have also made it so you can just type `lpr`
475 or `enscript`.)
477 -------------------------------------------------------------------------------
478 -- This script requires system functions.
480 function catto (output)
481     writeto (output)
482     write (current_document_formatted (79))
483     writeto ()
486 -- Send the current document to `lpr'.
487 function lpr ()
488     -- You must compile Lua with `popen' support for pipes to work.
489     -- See `config' in the Lua distribution.
490     catto ("|lpr")
493 -- Send the current document to `enscript'.
494 function enscript ()
495     catto ("|enscript -fCourier8")
497 -------------------------------------------------------------------------------
500 Deferring to Netscape
501 ^^^^^^^^^^^^^^^^^^^^^
503 If you come across a brain-dead web page that is totally unreadable with
504 ELinks, you'd probably want to open it with a graphical browser.  The
505 following function opens the current document in Netscape.
507 -------------------------------------------------------------------------------
508 -- This function requires `execute', a system function.
510 -- When starting Netscape: Set to `nil' if you do not want
511 -- to open a new window for each document.
512 netscape_new_window = 1
514 -- Open current document in Netscape.
515 function netscape ()
516     local new = netscape_new_window and ",new_window" or ""
517     execute ("( netscape -remote 'openURL("..current_url ()..new..")'"
518              .." || netscape '"..current_url ().."' ) 2>/dev/null &")
520 -------------------------------------------------------------------------------
523 Alternative bookmark system
524 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
526 Many people would like to have a bookmark system with categories (note that
527 ELinks already supports that, marketing name Hiearchical bookmarks), and also
528 to be able to view them and search for them in an HTML page.  I have written
529 an alternative bookmark system (for ELinks), which some people may like better
530 than the standard bookmark system.  
534 More ideas
535 ^^^^^^^^^^
537  - The Lua interface needs to be redesigned to provide more flexible, coherent
538    and usable interface to the scripts.
540  - Cliff Cunnington had a neat idea of clipping text that you see in web pages
541    (you enter a regexp that will match the start and end of the text you want
542    to clip), and saving the text to disk, along with the URL and timestamp.
543    This would help if you find that you can't ever remember where you had seen
544    a piece of text, or if you want to keep a piece of information but don't
545    need to save the entire page.
547  - People who use download management programs could write a function to send
548    the current link to their favourite downloading program.
550  - If you wrote a small C program to put text into the X11 selection
551    clipboard, you could pass the current link or URL to that program, to make
552    it easier to paste URLs into other windows.  It might be possible to do the
553    same with GPM, or the KDE/GNOME equivalents.
555  - Send the current page to Babelfish for translation.
557  - Look for stupid JavaScript URLs and convert them to something usable.
559  - More things are possible, I'm sure.  If you have an idea that requires
560    another hook or function, contact me (Peter Wang) and I'll see what I can
561    do.