Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 379312

Summary: plug-ins cannot contribute new types to Shell page
Product: [ECD] Orion Reporter: Grant Gayed <grant_gayed>
Component: ClientAssignee: Grant Gayed <grant_gayed>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: john.arthorne, simon_kaegi
Version: 0.5   
Target Milestone: 3.0 M1   
Hardware: PC   
OS: Windows 7   
Whiteboard:

Description Grant Gayed CLA 2012-05-11 16:37:26 EDT
The code is in place in the console page to enable this, but its test case of moving the implemented 'directory' type out to an external plug-in failed.  The type's generated completion predictions seemingly arrived too late for GCLI as a result of having to do a round trip across the plug-in boundary.  I think the underlying issue here is that GCLI needs to be able to accept completion suggestions at more arbitrary times than is currently supported.
Comment 1 Grant Gayed CLA 2012-07-17 13:55:04 EDT
This is logged at mozilla: https://bugzilla.mozilla.org/show_bug.cgi?id=685526 .
Comment 3 Grant Gayed CLA 2013-04-12 10:38:30 EDT
Example usage:

/* first, here's a custom type */

/*
 * The current need to provide one of these status values in the result
 * object may go away since the Shell page should be able to compute the
 * status based on the presence/absence of a value in the result, and by
 * comparing the typed string with the prediction strings.  But for now
 * one of these status values must be provided in the result.
 */
var CompletionStatus = {
    /**
     * @name orion.shell.CompletionStatus.MATCH
     * the current text matches a valid argument value
     */
    MATCH: 0,
    /**
     * @name orion.shell.CompletionStatus.PARTIAL
     * the current text matches a subset of the initial characters of a valid
     * argument value (ie.- a value in the midst of being typed)
     */
    PARTIAL: 1,
    /**
     * @name orion.shell.CompletionStatus.ERROR
     * the current text does not match a subset of the initial characters of any valid values
     */
    ERROR: 2
};
var labTypeProperties = { 
    name: "lab"
};
var labTypeImpl = {
    parse: function(arg, typeSpec, context) {
        /*
         * Compute all potential prediction objects here, can be done asynchronously
         * if needed (eg.- if need to wait on an XHR).
         */
        var ottawaValue = {name: 'Ottawa', address: 'Kanata, actually'};
        var rtpValue = {name: 'RTP', address: 'Raleigh'};
        if (typeSpec.showClimateToo) {
            ottawaValue.climate = "colder";
            rtpValue.climate = "warmer";
        }
        var potentialPredictions = [
            {
                name: 'Ottawa', /* the string to be typed */
                value: ottawaValue /* the corresponding model object */
            },
            {
                name: 'RTP', /* the string to be typed */
                value: rtpValue /* the corresponding model object */
            }
        ];

        var value; /* undefined until a valid value is fully typed */
        var status; /* one of the CompletionStatus values above */
        var predictions = []; /* an [] of {name: typedString, value: object} */

        for (var i = 0; i < potentialPredictions.length; i++) {
            if (potentialPredictions[i].name.indexOf(arg.text) === 0) {
                predictions.push(potentialPredictions[i]);
                if (potentialPredictions[i].name === arg.text) {
                    value = potentialPredictions[i].value;
                }
            }
        }

        status = CompletionStatus.ERROR;
        if (predictions.length > 0) {
            status = value ? CompletionStatus.MATCH : CompletionStatus.PARTIAL;
        }
        var result = {
            value: value,
            message: (status === CompletionStatus.ERROR ? ("'" + arg.text + "' is not valid") : undefined),
            status: status,
            predictions: predictions
        };

        /*
         * If all of the above can be computed synchronously then just return result directly.
         * If the above cannot be done synchronously (eg.- waiting on an XHR) then
         * return a promise as demonstrated below and resolve it when the result becomes ready.
         */
        var promise = new orion.Deferred();
        setTimeout(
            function() {
                promise.resolve(result); /* result has become ready some time later */
            }
        );	
        return promise;
    }
};

/* here's a command that uses the custom type */

var printLabProperties = { 
    name: "printLab",
    description: "Print a lab location",
    parameters: [{
        name: "lab",
        type: {name: "lab", showClimateToo: true},
        description: "The name of the lab to print info for"
    }],
    returnType: "string"
};
var printLabImpl = {
    callback: function(args) {
        var result = "Lab name: " + args.lab.name + "\nLocation: " + args.lab.address;
        if (args.lab.climate) {
            result += "\nClimate: " + args.lab.climate;
        }
        return result;
    }
};

var provider = new orion.PluginProvider();
provider.registerServiceProvider("orion.shell.type", labTypeImpl, labTypeProperties);
provider.registerServiceProvider("orion.shell.command", printLabImpl, printLabProperties);
provider.connect();