-- Authors: Canaan Hadley-Voth
-- License: Unknown
-- Last Changed: 2005-12-20
--
-- document_menus.lua
--
-- Canaan Hadley-Voth
--
-- Navigate the filesystem by way of ion menu.
--
-- One way to implement this is to define a menu containing useful folders,
-- and use that as a starting point for binding to (see below).
--
-- 2005-12-20:
--   * Added a second possible action.  Define docmenus.exec and exec2 below.
--	Selecting an item normally (Return or right arrow) will use exec,
--	Control+Return will use exec2.
--   * Script no longer puts a temp file in the session dir.
--   * Better handling of filenames with single and double quotes.

defmenu("useful folders", {
    -- Define commonly used locations here.
    -- Or skip this defmenu and put something like the following under mainmenu...

    submenu("/", function() return docmenus.getfiletable("/") end, {noautoexpand=true}),
    submenu("~", function() return docmenus.getfiletable(os.getenv("HOME")) end, {noautoexpand=true}),
    submenu(".ion3/", function() return docmenus.getfiletable(ioncore.get_paths().userdir) end, {noautoexpand=true}),

    -- Noautoexpand makes mod_query.query_menu skip this menu's expansion, which
    -- would probably have crashed ion.  (Though using document_menus to
    -- expand filenames in a query is kind of like using wine to run firefox.
    -- mod_query.query_editfile is sufficient for that.)
})

defbindings("WMPlex", {
    kpress(META.."minus", "mod_menu.menu(_, _sub, 'useful folders')"),
})

defbindings("WScreen", {
    submap(META.."K", {
        kpress("minus", "docmenus.toggle_dotfiles()"),
    }),
})

defbindings("WMenu", {
    kpress("Control+Return", "docmenus.finish2(_)"),
})

-- This script creates menus far larger than Ion would
-- normally handle.  The default scroll behavior is going to seem
-- inadequate, and this is how you would speed it up:

--mod_menu.set({ scroll_delay=5, scroll_amount=6 })


if not docmenus then
  -- Specify something other than run-mailcap if necessary.
  docmenus={
      show_dotfiles = true,
      exec = "run-mailcap --action=edit",
      exec2 = "xterm -e vi",
  }
end

function docmenus.getfiletable(dirpath)
    local filetable = {}
    local menufile
    local safedirpath
    -- os shell is used for the menu's directory listing.
    --
    -- lscommand can be customized, to a point.
    -- Scrap the -L to keep from following symbolic links.
    -- Just don't remove -p.
    local lscommand = "ls -Lp"
    if docmenus.show_dotfiles then lscommand = lscommand.." -a" end

    if string.sub(dirpath, -1) ~= "/" then
	dirpath = dirpath.."/"
    end

    safedirpath = string.gsub(dirpath, "\\", "\\\\")
    safedirpath = string.gsub(safedirpath, "\"", "\\\"")

    local ls = assert(io.popen(lscommand.." \""..safedirpath.."\"", "r"))

    for menufile in pairs(ls:lines()) do
	if menufile == "./" then menufile = "." end

	if string.sub(menufile, 3) == "ls:" then
	    -- ls error message on broken link. skip it
	elseif menufile == "../" then
	    -- I'd prefer not to show parent directory as a folder.
	elseif string.sub(menufile, -1) == "/" then
	    table.insert(filetable, docmenus.subdir(menufile, dirpath..menufile))
    	else
	    table.insert(filetable, docmenus.file(menufile, dirpath..menufile))
    	end
    end
    ls:close()

    return filetable
end

function docmenus.file(menustr,path)
    path = string.shell_safe(path)
    path = string.gsub(path, "\\", "\\\\")
    path = string.gsub(path, "\"", "\\\"")
    return menuentry(menustr,
	"docmenus.doexec(_, \""..path.."\")"
    )
end

function docmenus.doexec(mplex, path)
    local cmd
    if docmenus.use_exec2 then
	cmd = docmenus.exec2.." "..path
    else
	cmd = docmenus.exec.." "..path
    end
    ioncore.exec_on(mplex, cmd)
    docmenus.use_exec2 = false
end

function docmenus.subdir(menustr,path)
    return submenu(menustr, function() return docmenus.getfiletable(path) end, {noautoexpand=true})
end

function docmenus.toggle_dotfiles()
    docmenus.show_dotfiles=not docmenus.show_dotfiles
end

function docmenus.finish2(wmenu)
    docmenus.use_exec2 = true
    wmenu:finish()
end
