Skip to content
Snippets Groups Projects
penta-sessions.js 11.1 KiB
Newer Older
M Rawash's avatar
M Rawash committed
/*
M Rawash's avatar
M Rawash committed
Copyright (c) 2011-2012, M Rawash <mrawash@gmail.com>
M Rawash's avatar
M Rawash committed

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
M Rawash's avatar
M Rawash committed
*/

let sessiondir_completer = function (context) {
    context.anchored=false;
    dir = options.sessiondir;
    if (/^~?\//.test(context.filter))
        completion.file(context,true);
    else {
        completion.file(context,true,dir+context.filter);
        context.keys.text = function (f) this.path.substr(dir.length);
    }
}
M Rawash's avatar
M Rawash committed

let sessiondir_setter = function (value) {
M Rawash's avatar
M Rawash committed
    let dir = io.File(value);
    if (!dir.exists()) {
        try { dir.create(1,488) } catch(e) { return dactyl.echoerr(e.message) };
    } else if (!dir.isDirectory())
        return dactyl.echoerr(value+' is not a directory!');
    if (!/\/$/.test(value)) value+='/';
    return value
}

group.options.add(['sessiondir', 'sesdir'],
    'Default directory for saving sessions',
    'string', options.runtimepath+'/sessions/',
M Rawash's avatar
M Rawash committed
    {
        setter: sessiondir_setter,
M Rawash's avatar
M Rawash committed
    }
)

group.options.add(['sessionfile', 'sesfile'],
    'Current session file',
    'string', '',
    {
        presist: false
    }
M Rawash's avatar
M Rawash committed
)

group.options.add(['sessionoptions', 'sesop'],
    "Set what will be saved with :sessionsave",
    "stringlist", 'curdir,help,tabs',
    {
        completer: function (context) [
            ["blank", "Empty tabs"],
            ["curdir", "Current directory"],
            ["help", "Help tabs"],
            ["options", "All options and mappings"],
            ["runtime", "Current runtime path(s)"],
            ["sesdir", "Session directory as current directory"],
            ["tabs", "Normal tabs"]
        ]
    }
)

M Rawash's avatar
M Rawash committed
group.commands.add(['sessions[ave]','mkses[sion]'],
    'Save current window',
    function(args) {
        let filename = args[0] ? (/^~?\//.test(args[0]) ? args[0] :
                options.sessiondir+args[0]) : options.sessiondir+File(services.directory.get("ProfD", Ci.nsIFile)).leafName+'_'+new Date().toLocaleString().replace(/\s/g,"_")+'.penta'
M Rawash's avatar
M Rawash committed
        let file = io.File(filename);
      
        dactyl.assert(!file.exists() || args.bang, _("io.exists", file.path.quote()));

        let sesop = options.sessionoptions.toString();
        let lines = new Array('" vim: set ft=pentadactyl:\n');

        if (/sesdir/.test(sesop))
            lines.push('silent cd '+options.sessiondir);
        else if (/curdir/.test(sesop))
            lines.push('silent cd '+io.cwd.path);
        
        if (/runtime/.test(sesop))
            lines.push('set runtimepath='+options.runtimepath);

        if (/options/.test(sesop)) {
            let cmds = [cmd.serialize().map(commands.commandToString, cmd) for
                    (cmd in commands.iterator()) if (cmd.serialize)];
            cmds = array.flatten(cmds);
            lines = lines.concat(cmds);
        }
        
        if (/tabs/.test(sesop)) {
            tabs._groups.GroupItems.groupItems.forEach( function (group, k) {
                lines.push('js let newGroup = tabs._groups.GroupItems.newGroup()');
                lines.push('js newGroup.setTitle('+group.getTitle()+')');
                lines.push('js tabs._groups.GroupItems.setActiveGroupItem(newGroup)');

                group._children.forEach(function (tab, i) {
                    let loc = tab.tab.linkedBrowser.contentDocument.location.href;
                    if (/^dactyl:\/\/help\//.test(loc) && !/help/.test(sesop))
                        return;
                    if (loc == 'about:blank' && !/blank/.test(sesop))
                        return;
                    lines.push('tabopen '+loc);
                });
           });
M Rawash's avatar
M Rawash committed

        try {
M Rawash's avatar
M Rawash committed
        } catch(e) {
            dactyl.echoerr(_("io.notWriteable", file.path.quote()));
            return;
        };
        
        options.sessionfile=file.path;
        dactyl.echomsg('Saved session to '+file.path.quote());
    }, {
        argCount: '?',
    	bang: true,
        completer: sessiondir_completer
M Rawash's avatar
M Rawash committed
    }
);

M Rawash's avatar
M Rawash committed
group.commands.add(['sessiona[ppend]', 'sessionadd'],
    'Append tab(s) to a session file',
    function(args) {
        let file = io.File(/^~?\//.test(args[0]) ? args[0] : options.sessiondir+args[0]);
M Rawash's avatar
M Rawash committed
      
        if (!file.exists() || !file.isWritable() || file.isDirectory()) {
            dactyl.echoerr(_("io.notWriteable", file.path.quote()));
            return;
        }

        let data = '';
        if (args.bang) {
            tabs.visibleTabs.forEach(function (tab, i) {
                data+='\ntabopen '+tab.linkedBrowser.contentDocument.location.href;
M Rawash's avatar
M Rawash committed
            });
        } else {
            data+='\ntabopen '+gBrowser.mCurrentTab.linkedBrowser.contentDocument.location.href;
M Rawash's avatar
M Rawash committed
        }

        try {
            file.write(data,'>>');
        } catch(e) {
            dactyl.echoerr(_("io.notWriteable", file.path.quote()));
            return;
        };
        
        dactyl.echomsg('Appended tab(s) to session file '+file.path.quote());
    }, {
        argCount: '1',
    	bang: true,
        completer: sessiondir_completer
M Rawash's avatar
M Rawash committed
group.commands.add(['sessionl[oad]'],
    'Load a session file',
    function(args) {
        let file = io.File(/^~?\//.test(args[0]) ? args[0] : options.sessiondir+args[0]);
M Rawash's avatar
M Rawash committed

        if (!file.exists() || !file.isReadable() || file.isDirectory()) {
            dactyl.echoerr(_("io.notReadable", file.path.quote()));
            return;
        }

        let curtab = gBrowser.mCurrentTab;
        if(!args.bang) tabs.keepOnly(curtab);
        let sessionscript = io.source(file.path);
        sessionscript.unload();
        options.sessionfile=file.path;
        if(!args.bang) tabs.remove(curtab);
        dactyl.echomsg('Loaded session from '+file.path.quote());
    }, {
        argCount: "1",
    	bang: true,
        completer: sessiondir_completer
M Rawash's avatar
M Rawash committed
    }
);

group.mappings.add([modes.NORMAL], ['ss'],
    'Save current window',
    function() CommandExMode().open('sessionsave! ')
M Rawash's avatar
M Rawash committed
);

M Rawash's avatar
M Rawash committed
group.mappings.add([modes.NORMAL], ['sa'],
    'Append tab(s) to a session file',
    function() CommandExMode().open('sessionappend ')
M Rawash's avatar
M Rawash committed
);

M Rawash's avatar
M Rawash committed
group.mappings.add([modes.NORMAL], ['sl'],
    'Load a session file',
    function() CommandExMode().open('sessionload ')
M Rawash's avatar
M Rawash committed
);


XML.ignoreWhitespace = false;
XML.prettyPrinting = false;
var INFO =
<plugin name="penta-sessions" version="0.2"
        href="https://github.com/gwash/penta-sessions"
        summary="Pentadactyl Session Manager"
        xmlns={NS}>
    <author email="mrawash@gmail.com">M Rawash</author>
    <license href="http://www.gnu.org/licenses/gpl.html">GPL</license>
    <project name="Pentadactyl" min-version="1.0"/>
    <p>
        This plugin provides Vim-like session handeling.
    </p>
        <note>Only operates on current window</note>
    <item>
        <tags>'sesdir' 'sessiondir'</tags>
        <spec>'sessiondir' 'sesdir'</spec>
        <type>string</type>
        <default>{options.get("sessiondir").stringDefaultValue}</default>
        <description>
            <p>
                The default directory to save/load sessions from.
            </p>
        </description>
    </item>
    <item>
        <tags>'sesfile' 'sessionfile'</tags>
        <spec>'sessionfile' 'sesfile'</spec>
        <type>string</type>
        <default></default>
        <description>
            <p>
                The session file you are currently working with, this will be set 
                automatically whenever you save or load a session, but you can set it
                manually if you want.
            </p>
        </description>
    </item>
    <item>
        <tags>'sesop' 'sessionoptions'</tags>
        <spec>'sessionoptions' 'sesop'</spec>
        <type>stringlist</type>
        <default>{options.get("sessionoptions").stringDefaultValue}</default>
        <description>
            <p>
                Changes the effect of the <ex>:sessionsave</ex> command.  It is a comma
                separated list of words.  Each word enables saving and restoring
                something:
            </p>
            <dl>
            { template.map(options.get("sessionoptions").completer(), function ([k, v])
                <><dt>{k}</dt> <dd>{v}</dd></>) }
            </dl>
            <note>
                "sesdir" overrides "curdir" if added.
            </note>
        </description>
    </item>

    <item>
        <tags>ss :sessions :sessionsave :mkses :mksession</tags>
        <strut/>
        <spec>:sessions<oa>ave</oa><oa>!</oa> <oa>file</oa></spec>
        <spec>ss</spec>
        <description>
            <p>
                Saves current session to an ExCommand <oa>file</oa>, which can be 
                restored later with <ex>:sessionload <oa>file</oa></ex>.
            </p>
            <p>
                If <oa>file</oa> is just a basename or a relative path (without leading 
                directory path), it will create a session file with that name in the 
                <o>sessiondir</o>. It also takes care of creating new directories if
                specified.
                <example>
                    <ex>:sessionsave</ex> pythonref
                </example>
            </p>
            <p>
                If no <oa>file</oa> was specified it will save to a numbered file
                (based on current date) in <o>sessiondir</o>.
            </p>
            <p>
                Adding ! will overwrite the file if it exists.
                <example>
                    <ex>:sessionsave!</ex> {options.runtimepath}/sessions/gapi.penta
                </example>
            </p>
        </description>
    </item>
    <item>
        <tags>sa :sessiona :sessionappend :sessionadd</tags>
        <strut/>
        <spec>:sessiona<oa>ppend</oa><oa>!</oa> <oa>file</oa></spec>
        <spec>sa</spec>
        <description>
            <p>
                Appends current tab to an existing session <oa>file</oa>. If a ! was
                supplied it will append all tabs in current window instead.
            </p>
            <p>
                If <oa>file</oa> is a basename/relative path, it will look for it in
                <o>sessiondir</o>.
            </p>
        </description>
    </item>
    <item>
        <tags>sl :sessionl :sessionload</tags>
        <strut/>
        <spec>:sessionl<oa>oad</oa><oa>!</oa> <oa>file</oa></spec>
        <spec>sl</spec>
        <description>
            <p>
                Loads session from <oa>file</oa>, replacing all tabs in current window
                if no ! was added.
            </p>
            <p>
                If <oa>file</oa> is a basename/relative path, it will look for it in
                <o>sessiondir</o>.
M Rawash's avatar
M Rawash committed
/* vim:se sts=4 sw=4 et: */