-- Example hooks.lua file, put in ~/.elinks/ as hooks.lua.
-- $Id: hooks.lua.in,v 1.26 2003/12/21 21:28:39 pasky Exp $

-- TODO: Bookmarks stuff should be completely moved to bm.lua. --pasky

-- Take care about @SOMETHING@, we're processed with autoconf!

----------------------------------------------------------------------
--  Load configuration
----------------------------------------------------------------------

dofile ("/usr/local/etc/elinks/config.lua")
home_dir = (getenv and (getenv ("HOME") or "/home/"..getenv("USER"))) or "."
dofile (elinks_home.."/config.lua")

----------------------------------------------------------------------
--  case-insensitive gsub
----------------------------------------------------------------------

-- Please note that this is not completely correct yet.
-- It will not handle pattern classes like %a properly.
-- FIXME: Handle pattern classes.

function gisub (s, pat, repl, n)
    pat = gsub (pat, '(%a)',
	        function (v) return '['..strupper(v)..strlower(v)..']' end)
    if n then
	return gsub (s, pat, repl, n)
    else
	return gsub (s, pat, repl)
    end
end


----------------------------------------------------------------------
--  goto_url_hook
----------------------------------------------------------------------

function match (prefix, url)
    return strsub (url, 1, strlen (prefix)) == prefix
end

function mod (dividend, divisor)
    while dividend >= divisor
    do dividend = dividend - divisor
    end
    return dividend
end

function hx (c)
    return strchar((c >= 10 and (c - 10) + strbyte ('A')) or c + strbyte ('0'))
end

function char2hex (c)
    return '%'..hx (strbyte (c) / 16)..hx (mod(strbyte (c), 16))
end

function escape (str)
    return gsub (str, "(%W)", char2hex)
end

-- You can write smt like "gg" to goto URL dialog and it'll go to google.com.

-- Note that this is obsoleted by the URI rewrite plugin.

dumbprefixes = {
    arc = "http://web.archive.org/web/*/%c",
    b = "http://babelfish.altavista.com/babelfish/tr",
    bz = "http://bugzilla.elinks.or.cz",
    bug = "http://bugzilla.elinks.or.cz",
    d = "http://www.dict.org",
    g  = "http://www.google.com/",
    gg = "http://www.google.com/",
    go = "http://www.google.com/",
    fm = "http://www.freshmeat.net/",
    sf = "http://www.sourceforge.net/",
    dbug = "http://bugs.debian.org/",
    dpkg = "http://packages.debian.org/",
    -- Hm, is this Debian-centric? -- Miciah
    lua = "file:///usr/share/doc/lua40-doc/manual/idx.html",
    pycur = "http://www.python.org/doc/current/",
    pydev = "http://www.python.org/dev/doc/devel/",
    pyhelp = "http://starship.python.net/crew/theller/pyhelp.cgi",
    pyvault = "http://www.vex.net/parnassus/",
    e2 = "http://www.everything2.org/",
    sd = "http://www.slashdot.org/",
    vhtml = "http://validator.w3.org/check?uri=%c",
    vcss = "http://jigsaw.w3.org/css-validator/validator?uri=%c",
}

function debian_contents (url)
	local t = {}

	url = gsub(url, '(%w+):(%w+)', function (key, val) %t[key] = val end)

	return 'http://packages.debian.org/cgi-bin/search_contents.pl?word='
	..escape(gsub(url, '%s*([^%s]+)%s*', '%1'))
	..'&searchmode='..(t.searchmode or 'searchfilesanddirs')
	..'&case='..(t.case or 'insensitive')
	..'&version='..(t.version or pipe_read('cut -d/ -f1 /etc/debian_version | tr -d \\\\n') or 'stable')
	..'&arch='..(t.arch or gsub(pipe_read('uname -m | tr -d \\\\n'), 'i%d86', 'i386') or 'i386') -- like this'll work...
end

function cvsweb (base, project, url)
	local t = {n=0}
	local file, old, new
	local replacements

	-- allow <file>:<revision>[-><revision>]
	url,replacements = gsub(url, "^(.*):(.*)->(.*)$", "%1 %2 %3")
	if replacements == 0 then url = gsub(url, "^(.*):(.*)$", "%1 %2") end

	-- split into words
	gsub(url, "([^%s]+)", function (w) tinsert(%t, w) end)
	file, old, new = t[1], t[2], t[3]

	if t[4] then error('this smartprefix takes only two to three arguments') return nil end
	if not file then error('no file given') return nil end

	if     new then return base..project.."/"..file..".diff?r1="..old.."&r2="..new.."&f=u"
	elseif old then return base.."~checkout~/"..project.."/"..file..(old ~= "latest" and "?rev="..old or "")
	else            return base..project.."/"..file
	end
end

function gmane (url)
	local group, words

	_,_,group,words = strfind(url, "([^%s]+)%s%s*(.*)$")

	if not words then return nil end

	return "http://search.gmane.org/search.php?query="..words.."&group="..group
end

-- You can write "gg:foo" or "gg foo" to goto URL dialog and it'll ask google
-- for it automagically.

-- Note that this is _mostly_ obsoleted by the URI rewrite plugin. (It can't do the
-- metas, though.)

smartprefixes = {
    arc = "http://web.archive.org/web/*/%s",
    bb = "http://babelfish.altavista.com/babelfish/tr?urltext=%s",
    bb_fr_en = "http://babelfish.altavista.com/babelfish/tr?lp=fr_en&submit=1&urltext=%s",
    bb_en_fr = "http://babelfish.altavista.com/babelfish/tr?lp=en_fr&submit=1&urltext=%s",
    bug = "http://bugzilla.elinks.or.cz/show_bug.cgi?id=%s",
    cambridge = "http://dictionary.cambridge.org/results.asp?searchword=%s",
    cliki = "http://www.cliki.net/admin/search?words=%s",
    -- If you want to add a smartprefix for another project's CVSweb,
    -- just create a lambda like this. Aren't high-level languages fun?
    cvs = function (x) return cvsweb ("http://cvsweb.elinks.or.cz/cvsweb.cgi/", "elinks", x) end,
    d = "http://www.dict.org/bin/Dict?Query=%s&Form=Dict1&Strategy=*&Database=*&submit=Submit+query",
    debcontents = debian_contents,
    dmoz = "http://search.dmoz.org/cgi-bin/search?search=%s",
    foldoc = "http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?%s",
    g  = "http://www.google.com/search?q=%s&btnG=Google+Search",
    gd = "http://www.google.com/search?q=%s&cat=gwd/Top",
    gg = "http://www.google.com/search?q=%s&btnG=Google+Search",
    -- Whose idea was it to use 'gg' for websearches? -- Miciah
    --gg = "http://groups.google.com/groups?q=%s",
    gi = "http://images.google.com/images?q=%s",
    gmane = gmane,
    gn = "http://news.google.com/news?q=%s",
    go = "http://www.google.com/search?q=%s&btnG=Google+Search",
    gwho = "http://www.googlism.com/?ism=%s&name=1",
    gwhat = "http://www.googlism.com/?ism=%s&name=2",
    gwhere = "http://www.googlism.com/?ism=%s&name=3",
    gwhen = "http://www.googlism.com/?ism=%s&name=4",
    fm = "http://www.freshmeat.net/search/?q=%s",
    savannah = "http://savannah.nongnu.org/search/?words=%s&type_of_search=soft&exact=1",
    sf = "http://sourceforge.net/search/?q=%s",
    sfp = "http://sourceforge.net/projects/%s",
    sd = "http://www.slashdot.org/search.pl?query=%s",
    sdc = "http://www.slashdot.org/search.pl?query=%s&op=comments",
    sdu = "http://www.slashdot.org/search.pl?query=%s&op=users",
    sdp = "http://www.slashdot.org/search.pl?query=%s&op=polls",
    sdj = "http://www.slashdot.org/search.pl?query=%s&op=journals",
    dbug = "http://bugs.debian.org/%s",
    dpkg = "http://packages.debian.org/%s",
    emacs = "http://www.emacswiki.org/cgi-bin/wiki.pl?search=%s",
    lyrics = "http://music.lycos.com/lyrics/results.asp?QT=L&QW=%s",
    lxr = "http://lxr.linux.no/ident?i=%s",
    onelook = "http://onelook.com/?w=%s&ls=a",
    py = "http://starship.python.net/crew/theller/pyhelp.cgi?keyword=%s&version=current",
    pydev = "http://starship.python.net/crew/theller/pyhelp.cgi?keyword=%s&version=devel",
    pyvault = "http://py.vaults.ca/apyllo.py?find=%s",
    e2 = "http://www.everything2.org/?node=%s",
    encz = "http://www.slovnik.cz/bin/ecd?ecd_il=1&ecd_vcb=%s&ecd_trn=translate&ecd_trn_dir=0&ecd_lines=15&ecd_hptxt=0",
    czen = "http://www.slovnik.cz/bin/ecd?ecd_il=1&ecd_vcb=%s&ecd_trn=translate&ecd_trn_dir=1&ecd_lines=15&ecd_hptxt=0",
    dict = "http://dictionary.reference.com/search?q=%s",
    thes = "http://thesaurus.reference.com/search?q=%s",
    a = "http://acronymfinder.com/af-query.asp?String=exact&Acronym=%s",
    imdb = "http://imdb.com/Find?%s",
    mw = "http://www.m-w.com/cgi-bin/dictionary?book=Dictionary&va=%s",
    mwt = "http://www.m-w.com/cgi-bin/thesaurus?book=Thesaurus&va=%s",
    whatis = "http://uptime.netcraft.com/up/graph/?host=%s",
    wiki = "http://www.wikipedia.org/w/wiki.phtml?search=%s",
    wn = "http://www.cogsci.princeton.edu/cgi-bin/webwn1.7.1?stage=1&word=%s",
    -- rfc by number
    rfc = "http://www.rfc-editor.org/rfc/rfc%s.txt",
    -- rfc search
    rfcs = "http://www.rfc-editor.org/cgi-bin/rfcsearch.pl?searchwords=%s&format=http&abstract=abson&keywords=keyon&num=25",
    cr   = "http://www.rfc-editor.org/cgi-bin/rfcsearch.pl?searchwords=%s&format=http&abstract=abson&keywords=keyon&num=25",
    -- Internet Draft search
    rfcid = "http://www.rfc-editor.org/cgi-bin/idsearch.pl?searchwords=%s&format=http&abstract=abson&keywords=keyon&num=25",
    id    = "http://www.rfc-editor.org/cgi-bin/idsearch.pl?searchwords=%s&format=http&abstract=abson&keywords=keyon&num=25",
    draft = "http://www.rfc-editor.org/cgi-bin/idsearch.pl?searchwords=%s&format=http&abstract=abson&keywords=keyon&num=25",
}

function goto_url_hook (url, current_url)
    if dumbprefixes[url] then
	if current_url then
	    return gsub(dumbprefixes[url], "%%c", current_url)
	else
            return dumbprefixes[url]
	end
    end

    if strfind(url,'%s') or strfind(url, ':') then
        local _,_,nick,val = strfind(url, "^([^%s:]+)[:%s]%s*(.-)%s*$")
        if nick and smartprefixes[nick] then
            if type(smartprefixes[nick]) == 'function' then
                return smartprefixes[nick](val)
            elseif type(smartprefixes[nick]) == 'string' then
                return format(smartprefixes[nick], escape(val))
            else
                error('smartprefix "'..nick..'" has unsupported type "'
                      ..type(smartprefixes[nick])..'".')
                return nil
            end
        end
    end

    -- Expand ~ to home directories.
    if match ("~", url) then
        if strsub(url, 2, 2) == "/" or strlen(url) == 1 then    -- ~/foo
            return home_dir..strsub(url, 2)
        else                                -- ~foo/bar
            return "/home/"..strsub(url, 2)
        end
    end

    -- Don't take localhost as directory name
    if match("localhost", url) then
	return "http://"..url
    end

    -- Unmatched.
    return url
end


-----------------------------------------------------------------------
--  follow_url_hook
---------------------------------------------------------------------

function follow_url_hook (url)
    -- Using bookmark addon.
    if bookmark_addon then
	if bm_is_category (url) then
	    return nil
	else
	    return bm_get_bookmark_url (url) or url
	end

    -- Not using bookmark addon.
    else
	return url
    end
end


----------------------------------------------------------------------
--  pre_format_html_hook
----------------------------------------------------------------------

-- Plain strfind (no metacharacters).
function sstrfind (s, pattern)
    return strfind (s, pattern, 1, 1)
end

function highlight (url, html)
  local ret=nil

-- highlight patches
  if strfind (url, "%.patch$") then
	local tmp = tmpname ()
	writeto (tmp) write (html) writeto()
	html = pipe_read ("(code2html -l patch "..tmp.." - ) 2>/dev/null")
	remove(tmp)
	ret = 1
  end

-- Python
  if strfind (url, "%.py$") then
	local tmp = tmpname ()
	writeto (tmp) write (html) writeto()
	html = pipe_read ("(code2html -l python "..tmp.." - ) 2>/dev/null")
	remove(tmp)
	ret = 1
  end

-- Perl
  if strfind (url, "%.pl$") then
	local tmp = tmpname ()
	writeto (tmp) write (html) writeto()
	html = pipe_read ("(code2html -l perl "..tmp.." - ) 2>/dev/null")
	remove(tmp)
	ret = 1
  end

-- awk
  if strfind (url, "%.awk$") then
	local tmp = tmpname ()
	writeto (tmp) write (html) writeto()
	html = pipe_read ("(code2html -l awk "..tmp.." - ) 2>/dev/null")
	remove(tmp)
	ret = 1
  end

-- hightlight C code
    if strfind (url, "%.[ch]$") then
        local tmp = tmpname ()
        writeto (tmp) write (html) writeto ()
        html = pipe_read ("(code2html -l c "..tmp.." - ) 2>/dev/null")
        remove (tmp)
        ret = 1
    end

-- shell
    if strfind (url, "%.sh$") then
        local tmp = tmpname ()
        writeto (tmp) write (html) writeto ()
        html = pipe_read ("(code2html -l sh "..tmp.." - ) 2>/dev/null")
        remove (tmp)
        ret = 1
    end
    return ret, html
end


function pre_format_html_hook (url, html)
    local ret = nil

    -- Handle gzip'd files within reasonable size.
    -- Note that this is not needed anymore since we have a support for this
    -- in core ELinks. I still keep it here for a reference (as an example),
    -- though. If you will add something similiar using pipe_read(), feel free
    -- to remove this. --pasky
--    if strfind (url, "%.gz$") and strlen (html) < 65536 then
--        local tmp = tmpname ()
--        writeto (tmp) write (html) writeto ()
--        html = pipe_read ("(gzip -dc "..tmp.." || cat "..tmp..") 2>/dev/null")
--        remove (tmp)
--        ret = 1
--    end

    -- Highlight the source code
    if highlight_enable then
        ret, html = highlight(url, html)
    end

    -- Mangle ALT="" in IMG tags.
    if mangle_blank_alt then
	local n
	html, n = gisub (html, '(<img.-) alt=""', '%1 alt="&nbsp;"')
	ret = ret or (n > 0)
    end

    -- Fix unclosed INPUT tags.
    if 1 then
        local n
	html, n = gisub (html, '(<input[^>]-[^=]")<', '%1><')
	ret = ret or (n > 0)
    end

    -- Fix unclosed A tags.
    if 1 then
        local n
	html, n = gisub (html, '(<a[^>]-[^=]")<', '%1><')
	ret = ret or (n > 0)
    end

    -- These quick 'n dirty patterns don't maintain proper HTML.

    -- linuxtoday.com
    if sstrfind (url, "linuxtoday.com") then
        if sstrfind (url, "news_story") then
            html = gsub (html, '<TABLE CELLSPACING="0".-</TABLE>', '', 1)
            html = gsub (html, '<TR BGCOLOR="#FFF.-</TR></TABLE>', '', 1)
        else
            html = gsub (html, 'WIDTH="120">\n<TR.+</TABLE></TD>', '>', 1)
        end
        html = gsub (html, '<A HREF="http://www.internet.com.-</A>', '')
        html = gsub (html, "<IFRAME.-</IFRAME>", "")
        -- emphasis in text is lost
        return gsub (html, 'text="#002244"', 'text="#001133"', 1)

    -- dictionary.com
    elseif sstrfind (url, "dictionary.com/cgi-bin/dict.pl") then
	local t = { t = "" }
	local _, n = gsub (html, "resultItemStart %-%-%>(.-)%<%!%-%- resultItemEnd",
			   function (x) %t.t = %t.t.."<tr><td>"..x.."</td></tr>" end)
	if n == 0 then
	    -- we've already mangled this page before
	    return html
	else
	    return "<html><head><title>Dictionary.com lookup</title></head>"..
		    "<body><table border=0 cellpadding=5>"..t.t.."</table>"..
		    "</body></html>"
	end
    elseif sstrfind (url, "allmusic.com") then
        return gsub(html, "javascript:z%('(.-)'%)", "/cg/amg.dll?p=amg&sql=%1")
    end

    return ret and html
end


----------------------------------------------------------------------
--  Miscellaneous functions, accessed with the Lua Console.
----------------------------------------------------------------------

-- Reload this file (hooks.lua) from within Links.
function reload ()
    dofile (hooks_file)
end

-- Helper function.
function catto (output)
    local doc = current_document_formatted (79)
    if doc then writeto (output) write (doc) writeto () end
end

-- Email the current document, using Mutt (http://www.mutt.org).
-- This only works when called from lua_console_hook, below.
function mutt ()
    local tmp = tmpname ()
    writeto (tmp) write (current_document ()) writeto ()
    tinsert (tmp_files, tmp)
    return "run", "mutt -a "..tmp
end

-- Table of expressions which are recognised by our lua_console_hook.
console_hook_functions = {
    reload	= "reload ()",
    mutt	= mutt,
}

function lua_console_hook (expr)
    local x = console_hook_functions[expr]
    if type (x) == "function" then
	return x ()
    else
	return "eval", x or expr
    end
end


----------------------------------------------------------------------
--  quit_hook
----------------------------------------------------------------------

-- We need to delete the temporary files that we create.
if not tmp_files then
    tmp_files = {}
end

function quit_hook ()
    if bookmark_addon then
	bm_save_bookmarks ()
    end

    if tmp_files and remove then
        tmp_files.n = nil
        for i,v in tmp_files do remove (v) end
    end
end


----------------------------------------------------------------------
--  Examples of keybinding
----------------------------------------------------------------------

-- Bind Ctrl-H to a "Home" page.

--    bind_key ("main", "Ctrl-H",
--	      function () return "goto_url", "http://www.google.com/" end)

-- Bind Alt-p to print.

--    bind_key ("main", "Alt-p", lpr)

-- Bind Alt-m to toggle ALT="" mangling.

    bind_key ("main", "Alt-m",
	      function () mangle_blank_alt = not mangle_blank_alt end)


----------------------------------------------------------------------
--  Bookmark addon
----------------------------------------------------------------------

if bookmark_addon then

    dofile (elinks_home.."/bm.lua")

    -- Add/change any bookmark options here.

    -- Be careful not to load bookmarks if this script is being
    -- reloaded while in ELinks, or we will lose unsaved changes.
    if not bm_bookmarks or getn (bm_bookmarks) == 0 then
	bm_load_bookmarks ()
    end

    -- My bookmark key bindings.
--    bind_key ('main', 'a', bm_add_bookmark)
--    bind_key ('main', 's', bm_view_bookmarks)
--    bind_key ('main', 'Alt-e', bm_edit_bookmark)
--    bind_key ('main', 'Alt-d', bm_delete_bookmark)
--    bind_key ('main', 'Alt-k', bm_move_bookmark_up)
--    bind_key ('main', 'Alt-j', bm_move_bookmark_down)

end


-- vim: shiftwidth=4 softtabstop=4
