Skip to content
Snippets Groups Projects
penta-sessions.js 11.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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] :
    
    eri451's avatar
    eri451 committed
                    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);
            }
    
    eri451's avatar
    eri451 committed
    
    
    eri451's avatar
    eri451 committed
                tabs.getGroups( function ({ GroupItems }) {
                    GroupItems.groupItems.forEach( function (group, k) {
    
                        lines.push('js <<EOF');
                        lines.push('tabs.getGroups(function ({ GroupItems }) {');
                        lines.push('\tlet newGroup = GroupItems.newGroup();');
                        if (!(group.getTitle() === ""))
    
                            lines.push('\tnewGroup.setTitle(\''+group.getTitle()+'\');');
    
    eri451's avatar
    eri451 committed
                        lines.push('\tGroupItems.setActiveGroupItem(newGroup);');
    
    eri451's avatar
    eri451 committed
                        let children = group.getChildren();
                        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('\tex.tabopen(\''+loc+'\');');
                        });
                        lines.push('});');
                        lines.push('EOF');
                   });
    
    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;
            }
    
    
    eri451's avatar
    eri451 committed
            // delete inactive groups --> only vivisble tabs will remain
            tabs.getGroups( function ({ GroupItems }) {
                let activeGroup = GroupItems.getActiveGroupItem();
                let items = GroupItems.groupItems;
                for(let i in items){
                    if (items[i].id !== activeGroup.id)
                        items[i].closeAll();
                }
            });
    
    
    M Rawash's avatar
    M Rawash committed
            let curtab = gBrowser.mCurrentTab;
    
    eri451's avatar
    eri451 committed
            if(!args.bang) tabs.keepOnly(curtab); //FIXME deletes only visible tabs
    
    M Rawash's avatar
    M Rawash committed
            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: */