aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKris De Volder2012-05-01 16:20:51 (EDT)
committerGrant Gayed2012-05-09 14:09:40 (EDT)
commit56e9bc64bb5f4b267672f7dee43872509cb5421d (patch)
tree9840c5e2d67d670a207a2e2b7fee0bc6f8557f62
parentb997ef7cf98fa8615ac4560daf834bb4b59fbba6 (diff)
downloadorg.eclipse.orion.client-56e9bc64bb5f4b267672f7dee43872509cb5421d.zip
org.eclipse.orion.client-56e9bc64bb5f4b267672f7dee43872509cb5421d.tar.gz
org.eclipse.orion.client-56e9bc64bb5f4b267672f7dee43872509cb5421d.tar.bz2
initial console release
-rw-r--r--bundles/org.eclipse.orion.client.console/.project23
-rw-r--r--bundles/org.eclipse.orion.client.console/.settings/org.eclipse.pde.core.prefs4
-rw-r--r--bundles/org.eclipse.orion.client.console/META-INF/MANIFEST.MF8
-rw-r--r--bundles/org.eclipse.orion.client.console/about.html29
-rw-r--r--bundles/org.eclipse.orion.client.console/build.properties23
-rw-r--r--bundles/org.eclipse.orion.client.console/bundle.properties2
-rw-r--r--bundles/org.eclipse.orion.client.console/plugin.xml30
m---------bundles/org.eclipse.orion.client.console/submodules/gcli0
-rw-r--r--bundles/org.eclipse.orion.client.console/web/console/current-directory.js130
-rw-r--r--bundles/org.eclipse.orion.client.console/web/console/directory-type.js291
-rw-r--r--bundles/org.eclipse.orion.client.console/web/console/gcliConsolePlugin.html31
-rw-r--r--bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.css414
-rw-r--r--bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.html43
-rw-r--r--bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.js284
14 files changed, 1312 insertions, 0 deletions
diff --git a/bundles/org.eclipse.orion.client.console/.project b/bundles/org.eclipse.orion.client.console/.project
new file mode 100644
index 0000000..bf39786
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.orion.client.console</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.orion.client.console/.settings/org.eclipse.pde.core.prefs b/bundles/org.eclipse.orion.client.console/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..30e026c
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,4 @@
+#Tue Jan 18 14:23:15 CET 2011
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/bundles/org.eclipse.orion.client.console/META-INF/MANIFEST.MF b/bundles/org.eclipse.orion.client.console/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a73c911
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/META-INF/MANIFEST.MF
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.orion.client.console;singleton:=true
+Bundle-Version: 0.0.1.qualifier
+Bundle-ActivationPolicy: lazy
+Bundle-Vendor: %Bundle-Vendor
+Bundle-Localization: bundle
diff --git a/bundles/org.eclipse.orion.client.console/about.html b/bundles/org.eclipse.orion.client.console/about.html
new file mode 100644
index 0000000..8657dfd
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/about.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>April 26, 2011</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+<a href="http://www.eclipse.org/legal/epl-v10.html">Eclipse Public License Version 1.0</a>
+(&quot;EPL&quot;), and the <a href="http://www.eclipse.org/org/documents/edl-v10.html">
+Eclipse Distribution License Version 1.0</a> (&quot;EDL&quot;).
+For purposes of the EPL and EDL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/bundles/org.eclipse.orion.client.console/build.properties b/bundles/org.eclipse.orion.client.console/build.properties
new file mode 100644
index 0000000..b5c1d01
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/build.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2011 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials are made
+# available under the terms of the Eclipse Public License v1.0
+# (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+# License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+#
+# Contributors: IBM Corporation - initial API and implementation
+###############################################################################
+
+bin.includes = META-INF/,\
+ web/,\
+ bundle.properties,\
+ about.html,\
+ submodules/gcli/lib/,\
+ plugin.xml
+src.includes = web/,\
+ about.html,\
+ bundle.properties,\
+ submodules/gcli/lib/gcli/
+bin.excludes = submodules/gcli/lib/demo/,\
+ submodules/gcli/lib/gclitest/,\
+ submodules/gcli/lib/test/
diff --git a/bundles/org.eclipse.orion.client.console/bundle.properties b/bundles/org.eclipse.orion.client.console/bundle.properties
new file mode 100644
index 0000000..77f2a02
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/bundle.properties
@@ -0,0 +1,2 @@
+Bundle-Vendor = Eclipse.org - Orion
+Bundle-Name = Orion Commmand Line UI (Incubation)
diff --git a/bundles/org.eclipse.orion.client.console/plugin.xml b/bundles/org.eclipse.orion.client.console/plugin.xml
new file mode 100644
index 0000000..1bc6396
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/plugin.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.eclipse.equinox.http.registry.httpcontexts">
+ <httpcontext
+ id="org.eclipse.orion.server.configurator.httpcontext.console">
+ <resource-mapping
+ path="/web/console">
+ </resource-mapping>
+ </httpcontext>
+ <httpcontext
+ id="org.eclipse.orion.server.configurator.httpcontext.console.gcli">
+ <resource-mapping
+ path="/submodules/gcli">
+ </resource-mapping>
+ </httpcontext>
+ </extension>
+ <extension
+ point="org.eclipse.equinox.http.registry.resources">
+ <resource
+ alias="/console"
+ httpcontextId="org.eclipse.orion.server.configurator.httpcontext.console">
+ </resource>
+ <resource
+ alias="/console/gcli"
+ httpcontextId="org.eclipse.orion.server.configurator.httpcontext.console.gcli">
+ </resource>
+ </extension>
+</plugin>
diff --git a/bundles/org.eclipse.orion.client.console/submodules/gcli b/bundles/org.eclipse.orion.client.console/submodules/gcli
new file mode 160000
+Subproject 52e9d9602f5046a0b9c1399297d653febf16657
diff --git a/bundles/org.eclipse.orion.client.console/web/console/current-directory.js b/bundles/org.eclipse.orion.client.console/web/console/current-directory.js
new file mode 100644
index 0000000..1980688
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/web/console/current-directory.js
@@ -0,0 +1,130 @@
+/*global require define setTimeout */
+/**
+ * This module provides utility methods to retrieve information about directorie. It also keeps
+ * track of the 'current' directory state by using the 'dojo.hash()' function to store and retrieve
+ * the current directory location from the page URL.
+ */
+define(['dojo', 'orion/bootstrap', 'orion/fileClient'], function (dojo, mBootstrap, mFileClient) {
+
+ var fileClient;
+ var exports = {};
+
+ //The current path. I.e. the working dir relative to which we will execute commands on the server.
+ var currentTreeNode = null;
+
+ function withWorkspace(k) {
+ fileClient.loadWorkspace('').then(k);
+ }
+ exports.withWorkspace = withWorkspace;
+
+ /**
+ * Make sure that there is a currentTreeNode and call given callback on the tree node
+ * as soon as its available.
+ */
+ function withCurrentTreeNode(doit) {
+ if (currentTreeNode===null) {
+ var location = dojo.hash() || "";
+ fileClient.loadWorkspace(location).then(function (node) {
+ currentTreeNode = node;
+ doit(node);
+ });
+ } else {
+ //Wrapped in a setTimeout to ensure it always executed as later scheduled event.
+ //otherwise the execution order will be different depending on whether currentTreeNode==null
+ setTimeout(function () {
+ doit(currentTreeNode);
+ });
+ }
+ }
+ exports.withCurrentTreeNode = withCurrentTreeNode;
+
+ /**
+ * Returns true if string is a string that ends with the string suffix.
+ */
+ function endsWith(string, suffix) {
+ if (typeof(string)==='string' && typeof(suffix)==='string') {
+ var loc = string.lastIndexOf(suffix);
+ return (loc + suffix.length) === string.length;
+ }
+ return false;
+ }
+
+ /**
+ * Get the location of a given node's parent node. May return null if the node is a workspace node
+ * so it doesn't have a parent.
+ * <p>
+ * Warning: a valid parent location is the empty String '' which indicates the 'root' location.
+ * To check whether a valid parent was returned use 'if (loc!==null)' rather than 'if (loc)'.
+ * The empty String will count as 'false' in if tests!
+ */
+ function getParentLocation(node) {
+ if (node.Parents && node.Parents.length>0) {
+ return node.Parents[0].Location;
+ } else {
+ //TODO: Hack allert! Should not be using URL hackery to determine parent location
+ // but it seems sometimes we don't have a choice because the Parent's attribute is missing.
+ // Should investigate precisely how breadcrumbs does this.
+ var location = node.Location;
+ var parentLocation = null;
+ if (endsWith(location,'/')) {
+ location = location.slice(0, location.length-1);
+ }
+ if (location) {
+ var lastSlash = location.lastIndexOf('/');
+ if (lastSlash>=0) {
+ parentLocation = location.slice(0, lastSlash+1);
+ if (parentLocation==='/file/') {
+ parentLocation = '';
+ } else if (parentLocation==='/workspace/') {
+ parentLocation = null;
+ }
+ }
+ }
+ return parentLocation;
+ }
+ }
+ exports.getParentLocation = getParentLocation;
+
+ function setCurrentTreeNode(node) {
+ currentTreeNode = node;
+ if (currentTreeNode && currentTreeNode.Location) {
+ dojo.hash(currentTreeNode.Location);
+ }
+ }
+ exports.setCurrentTreeNode = setCurrentTreeNode;
+
+ /**
+ * Calls the callback function 'k' with the children of a given node.
+ * If the children are available the callback function is called immediately otherwise
+ * the children will be retrieved and the callback function called whenever the children
+ * become available.
+ */
+ function withChildren(node, k) {
+ if (node.Children) {
+ k(node.Children);
+ } else if (node.ChildrenLocation) {
+ fileClient.fetchChildren(node.ChildrenLocation).then(function (children) {
+ node.Children = children; // cache for later.
+ k(children);
+ });
+ }
+ }
+ exports.withChildren = withChildren;
+
+ function withCurrentChildren(k) {
+ withCurrentTreeNode(function (node) {
+ withChildren(node, k);
+ });
+ }
+ exports.withCurrentChildren = withCurrentChildren;
+
+ dojo.ready(function() {
+ mBootstrap.startup().then(function(core) {
+ var serviceRegistry = core.serviceRegistry;
+ fileClient = new mFileClient.FileClient(serviceRegistry);
+ });
+ });
+
+ return exports;
+
+}); \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.console/web/console/directory-type.js b/bundles/org.eclipse.orion.client.console/web/console/directory-type.js
new file mode 100644
index 0000000..92ecc99
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/web/console/directory-type.js
@@ -0,0 +1,291 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 VMWare and others.
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+ *
+ * Contributors:
+ * Kris De Volder (VMWare) - initial API and implementation
+ *******************************************************************************/
+/*global define require setTimeout*/
+define(['gcli/types', 'gcli/types/basic', 'gcli/ui/field', 'gcli/argument', 'gcli/util', 'dojo', 'gcli/cli',
+'gcli/ui/menu', 'console/current-directory'], function() {
+
+ var dojo = require('dojo');
+ var registerType = require('gcli/types').registerType;
+ var StringType = require('gcli/types/basic').StringType;
+ var Conversion = require('gcli/types').Conversion;
+ var Status = require('gcli/types').Status;
+ var Field = require('gcli/ui/field').Field;
+ var Argument = require('gcli/argument').Argument;
+ var addField = require('gcli/ui/field').addField;
+ var dom = require('gcli/util').dom;
+ var createEvent = require('gcli/util').createEvent;
+// var Assignment = require('gcli/cli').Assignment;
+ var Menu = require('gcli/ui/menu').Menu;
+ var withCurrentChildren = require('console/current-directory').withCurrentChildren;
+
+ var cache = {};
+
+ /**
+ * Returns true if string is a string that starts with the given prefix.
+ */
+ function startsWith(string, prefix) {
+ if (typeof(string)==='string' && typeof(prefix)==='string') {
+ return string.indexOf(prefix)===0;
+ }
+ return false;
+ }
+
+ function withValidDirs(k) {
+ withCurrentChildren(function (nodes) {
+ var names = ['..'];
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes[i];
+ if (node.Directory) {
+ names.push(node.Name);
+ }
+ }
+ k(names);
+ });
+ }
+
+ function computeCompletions(text, validDirs) {
+ var completions = [];
+ for (var i = 0; i < validDirs.length; i++) {
+ var candidate = validDirs[i];
+ if (startsWith(candidate, text)) {
+ completions.push({
+ name: candidate,
+ description: candidate,
+ value: candidate
+ });
+ }
+ }
+ return completions;
+ }
+
+ /**
+ * Gets list of completions, may return null if the list can't be computed
+ * synchronously.
+ */
+ function getCompletions(text) {
+ if (cache.completions && cache.text===text) {
+ return cache.completions;
+ }
+ if (cache.validDirs) {
+ //Do a quick computation from the list of dirs
+ cache.completions = computeCompletions(text, cache.validDirs);
+ cache.text = text;
+ return cache.completions;
+ }
+ //Values will be cached in future... but we have no completions at this time.
+ //We couldn't get the list just from cached values...
+ //try to prefetch cache for future use.
+ withValidDirs(function (validDirs) {
+ cache.validDirs = validDirs;
+ });
+ return null;
+ }
+
+ /**
+ * Gets list of completions passing the result to callback function k.
+ * Will asynchronously fetch needed data if required.
+ */
+ function withCompletions(text, k) {
+ var completions = getCompletions(text);
+ if (completions) {
+ k(completions);
+ } else {
+ withValidDirs(function (validDirs) {
+ cache.validDirs = validDirs;
+ k(getCompletions(text));
+ });
+ }
+ }
+
+ function find(array, pred) {
+ for (var i = 0; i < array.length; i++) {
+ if (pred(array[i])) {
+ return array[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * called to create a Conversion with a known list of predictions.
+ */
+ function createConversion(str, arg, completions) {
+ var exactMatch = find(completions, function(el) {
+ return el.name === str;
+ });
+ var message;
+ var status = Status.COMPLETE; //Default in case we forgte to set it.
+ if (exactMatch) {
+ status = Status.COMPLETE;
+ } else if (completions!==null && completions.length>0) {
+ status = Status.INCOMPLETE;
+ } else {
+ status = Status.ERROR;
+ message = "'"+str+"'"+" is not a valid directory";
+ }
+ return new Conversion(
+ //value,
+ str,
+ //arg,
+ arg,
+ //status,
+ status,
+ //message,
+ message,
+ //predictions
+ completions
+ );
+ }
+
+ function DirectoryType(typeSpec) {
+ if (Object.keys(typeSpec).length > 0) {
+ throw new Error('DirectoryType can not be customized');
+ }
+ }
+
+ DirectoryType.prototype = Object.create(StringType.prototype);
+ DirectoryType.prototype.name = 'directory';
+
+ DirectoryType.prototype.parse = function (arg) {
+ var str = arg.text || "";
+ //var prefix = arg.prefix || "";
+ var completions = getCompletions(str);
+ if (completions!==null) {
+ return createConversion(str, arg, completions);
+ } else {
+ //The completions aren't available yet. We should try to return a Conversion that
+ //still allows user to edit, but without predictions.
+ //Also we add a 'then' method allowing access to the actual conversion via a callback.
+ var deferredConversion = new Conversion(
+ //value,
+ str,
+ //arg,
+ arg,
+ //status,
+ Status.INCOMPLETE,
+ //message,
+ undefined,
+ //predictions
+ completions
+ );
+ deferredConversion.then = function(callback) {
+ withCompletions(str, function (completions) {
+ callback(createConversion(str, arg, completions));
+ });
+ };
+ return deferredConversion;
+ }
+ };
+ registerType(DirectoryType);
+
+ /**
+ * A field that allows editing of directories. Basically, this is a
+ * String field with a menu attached to show the predictions.
+ */
+ function DirectoryField(type, options) {
+ Field.call(this, type, options);
+
+ this.onInputChange = this.onInputChange.bind(this);
+ this.arg = new Argument();
+
+ this.element = dom.createElement(this.document, 'div');
+
+ this.input = dom.createElement(this.document, 'input');
+ this.input.type = 'text';
+ this.input.addEventListener('keyup', this.onInputChange, false);
+ this.input.classList.add('gcli-field');
+ this.input.classList.add('gcli-field-directory');
+ this.element.appendChild(this.input);
+
+ this.menu = new Menu({ document: this.document, field: true });
+ this.element.appendChild(this.menu.element);
+
+ this.input.addEventListener('keyup', this.onInputChange, false);
+ this.fieldChanged = createEvent('DirectoryField.fieldChanged');
+
+ // i.e. Register this.onItemClick as the default action for a menu click
+ this.menu.onItemClick = this.onItemClick.bind(this);
+ }
+
+ DirectoryField.prototype = Object.create(Field.prototype);
+
+ DirectoryField.prototype.destroy = function() {
+ Field.prototype.destroy.call(this);
+ this.input.removeEventListener('keyup', this.onInputChange, false);
+ this.menu.destroy();
+ delete this.element;
+ delete this.input;
+ delete this.menu;
+ delete this.document;
+ delete this.onInputChange;
+ };
+
+ DirectoryField.prototype.setConversion = function(conversion) {
+ this.arg = conversion.arg;
+ this.input.value = conversion.arg.text;
+ this.setMessage(conversion.message);
+
+ var items = [];
+ var predictions = conversion.getPredictions();
+ predictions.forEach(function(item) {
+ // Commands can be hidden
+ if (!item.hidden) {
+ items.push({
+ name: item.name,
+ complete: item.name,
+ description: ''//item.description || ''
+ });
+ }
+ }, this);
+ this.menu.show(items);
+
+ if (conversion.then) { // We only got a 'provisional' conversion. When caches are filled we'll get
+ // a callback and should try again.
+ var that = this;
+ conversion.then(function () {
+ if (that.element) { //if there's no UI yet => ignore.
+ that.setConversion(that.getConversion());
+ }
+ });
+ }
+ };
+
+ DirectoryField.prototype.onItemClick = function(ev) {
+ this.item = ev.currentTarget.item;
+ this.arg = this.arg.beget(this.item.complete, { normalize: true });
+ var conversion = this.type.parse(this.arg);
+ this.fieldChanged({ conversion: conversion });
+ this.setMessage(conversion.message);
+ };
+
+ DirectoryField.prototype.getConversion = function() {
+ // This tweaks the prefix/suffix of the argument to fit
+ this.arg = this.arg.beget(this.input.value, { prefixSpace: true });
+ return this.type.parse(this.arg);
+ };
+
+ DirectoryField.claim = function(type) {
+ return type instanceof DirectoryType ? (Field.MATCH+1) : Field.NO_MATCH;
+ };
+
+ addField(DirectoryField);
+
+ dojo.subscribe("/dojo/hashchange", function (newHash) {
+ cache = {};
+ });
+
+ //Not exporting anything. This module just contributes stuff to gcli by calling gcli API.
+ return {};
+});
+
+
+
diff --git a/bundles/org.eclipse.orion.client.console/web/console/gcliConsolePlugin.html b/bundles/org.eclipse.orion.client.console/web/console/gcliConsolePlugin.html
new file mode 100644
index 0000000..6389368
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/web/console/gcliConsolePlugin.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <script type="text/javascript" src="../orion/plugin.js"></script>
+ <script>
+ /*global window*/
+ function qualifyURL(url){
+ var a = document.createElement('a');
+ a.href = url; // set string url
+ return a.href;
+ }
+
+ window.onload = function() {
+ var serviceImpl = { /* All data is in properties */ };
+
+ var provider = new eclipse.PluginProvider();
+
+ provider.registerServiceProvider("orion.page.link", serviceImpl, {
+ name: "Console",
+ id: "orion.gcli",
+ uriTemplate: "{OrionHome}/console/orion-gcli-console.html"
+ });
+ provider.connect();
+ };
+ </script>
+</head>
+<body>
+<h1>Plugin</h1>
+</body>
+</html>
diff --git a/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.css b/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.css
new file mode 100644
index 0000000..d0e78e0
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.css
@@ -0,0 +1,414 @@
+@import "../org.dojotoolkit/dojo/resources/dojo.css";
+
+@import "../org.dojotoolkit/dijit/themes/nihilo/nihilo.css";
+
+@import "../org.dojotoolkit/dijit/themes/nihilo/Tree.css";
+
+@import
+ "../org.dojotoolkit/dijit/themes/nihilo/layout/BorderContainer.css";
+
+@import "../org.dojotoolkit/dijit/themes/nihilo/form/Common.css";
+
+@import "../org.dojotoolkit/dijit/themes/nihilo/form/Button.css";
+
+@import "../css/ide.css";
+
+@import "../css/breadcrumbs.css";
+
+@import "../css/commands.css";
+
+@import "../org.dojotoolkit/dojox/grid/resources/Grid.css";
+
+@import "../org.dojotoolkit/dojox/grid/resources/nihiloGrid.css";
+
+html,body {
+ height: 100%;
+}
+
+h1 {
+ position: relative;
+ margin-top: 18px;
+}
+
+select {
+ font-size: 1em;
+ border: 1px #999 solid;
+ color: #666;
+}
+
+button {
+ background: white;
+ color: #666;
+ border: solid 1px #999;
+ border-radius: 2px;
+ font-size: 0.9em;
+}
+
+#pluginUrlEntry {
+ background: white;
+ color: #666;
+ border: solid 1px #999;
+ border-radius: 2px;
+ font-size: 0.9em;
+ padding: 1px;
+}
+
+.statusPane {
+ font-weight: bold;
+}
+
+.categories {
+ background: #EDEDED;
+}
+
+#content-title {
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #666;
+ margin: 0;
+ padding-bottom: 14px;
+ padding-top: 13px;
+ margin-right: 16px;
+ text-align: right;
+}
+
+#categories>ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+#navbar {
+ margin: 0;
+ padding: 0;
+}
+
+.navbar-item {
+ border-bottom: 1px solid transparent;
+ border-top: 1px solid transparent;
+ color: #666;
+ display: block;
+ font-size: 90%;
+ outline: none;
+ padding: 7px 0;
+ text-align: right;
+ padding-right: 20px;
+ cursor:pointer;
+}
+
+ul,menu,dir {
+ display: block;
+ list-style-type: disc;
+}
+
+.navbar-item-selected {
+ background: #e3e3e3;
+ color: black;
+}
+
+.settings {
+ min-width:1000px;
+ max-width:1300px;
+ padding-left: 20px;
+ padding-right: 40px;
+}
+
+.pluginwrapper {
+ padding-bottom: 40px;
+ padding-top: 24px;
+ border-bottom: 1px dotted #BFBFBF;
+}
+
+.pluginTitle {
+ float: left;
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #666;
+ margin: 0;
+}
+
+.oldLink {
+ float: left;
+ color: #666;
+ margin: 2px;
+ padding-left: 5px;
+}
+
+.sectionProgress {
+ float: left; font-size : 1.2em; font-weight : bold; color : #666;
+ margin-left: 2px;
+ text-decoration: blink;
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #666;
+}
+
+.pluginSubTitle {
+ font-size: 1.1em;
+ font-weight: normal;
+ color: #666;
+ padding: 5px;
+}
+
+.additions {
+ float: right;
+ background: #666;
+ font-size: .9em;
+ color: white;
+ padding: 4px;
+ border-radius: 2px;
+}
+
+.additions-light {
+ float: right;
+ font-size: .9em;
+ color: white;
+ padding: 4px;
+ border-radius: 2px;
+}
+
+.settings h1 {
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #666;
+ margin: 0;
+ padding-bottom: 14px;
+ padding-top: 13px;
+ border-bottom: 1px dotted #BFBFBF;
+}
+
+.settings section {
+ color: #666;
+ border-bottom: 1px dotted #BFBFBF;
+ display: -webkit-box;
+ display: -moz-box;
+ margin-top: 17px;
+ padding-bottom: 20px;
+ width: 100%;
+ margin-right: 16px;
+}
+
+.settings section>h3 {
+ margin: 0;
+ vertical-align: middle;
+ width: 130px;
+ padding-right: 10px;
+}
+
+.settings section>div {
+ margin: 0;
+ vertical-align: middle;
+}
+
+.settings section>div>div {
+ margin: 10px 0;
+}
+
+.settings section>div>div>label>span {
+ min-width: 145px;
+ display: inline-block;
+ min-width: 100px;
+}
+
+.displaytable>section {
+ display: table-row;
+}
+
+.web-content-select-label {
+ min-width: 145px;
+}
+
+.web-content-select-label>span:only-of-type {
+ display: inline-block;
+ min-width: 100px;
+}
+
+input[type="checkbox"] {
+ margin: 3px 3px 3px 4px;
+ margin-left: 0;
+ margin-right: 0;
+ position: relative;
+ top: 1px;
+}
+
+.addPluginClosed {
+ float: right;
+ width: 10px;
+ height: 10px;
+ background: #FEFF66;
+ background: #666;
+ padding: 4px;
+ color: white;
+ font-size: 8pt;
+ border-radius: 4px;
+ top: 10px;
+}
+
+.interactionOpen {
+ border-bottom: 1px dotted #BFBFBF;
+ height: 30px;
+ padding-bottom: 5px;
+ padding-top: 5px;
+ margin-right: 16px;
+ -webkit-padding-start: 5px;
+ -webkit-padding-end: 4px;
+ -webkit-transition: padding 500ms, height 400ms, opacity 800ms;
+ -moz-padding-start: 4px;
+ -moz-padding-end: 3px;
+ -moz-transition: padding 500ms, height 400ms, opacity 800ms;
+ -ms-padding-start: 4px;
+ -ms-padding-end: 3px;
+ -ms-transition: padding 500ms, height 400ms, opacity 800ms;
+}
+
+.interactionClosed {
+ height: 0;
+ opacity: 0;
+ margin-right: 16px;
+ -webkit-padding-start: 4px;
+ -webkit-padding-end: 3px;
+ -webkit-transition: padding 300ms, height 700ms, opacity 200ms;
+ -moz-padding-start: 4px;
+ -moz-padding-end: 3px;
+ -moz-transition: padding 300ms, height 700ms, opacity 200ms;
+ -ms-padding-start: 4px;
+ -ms-padding-end: 3px;
+ -ms-transition: padding 500ms, height 400ms, opacity 800ms;
+}
+
+#plugin-settings .displaytable>section {
+ display: block;
+ width: 100%;
+}
+
+div.page section:last-child {
+ border-bottom: none;
+}
+
+#plugin-settings .displaytable>section>* {
+ display: block;
+}
+
+#plugin-settings-list {
+ min-height: 0;
+ overflow-y: hidden;
+ width: 100%;
+}
+
+.plugin-list-item {
+ padding-top: 20px;
+ margin-bottom: 20px;
+ width: 100%;
+}
+
+list,grid {
+ display: block;
+ outline: none;
+ overflow: auto;
+ position: relative;
+}
+
+.plugin-icon {
+ float: left;
+ position: relative;
+ height: 48px;
+ vertical-align: text-top;
+ width: 48px;
+ padding-right: 15px;
+}
+
+.stretch {
+ float: left;
+ position: relative;
+ white-space:normal;
+ max-width:600px;
+}
+
+list>*,grid>* {
+ display: block;
+ outline: none;
+ overflow: auto;
+ position: relative;
+ line-height: 20px;
+ white-space: pre;
+}
+
+.plugin-title {
+ font-size: 16px;
+ font-weight: 500;
+ padding-right: 20px;
+}
+
+#plugin-settings .displaytable {
+ display: block;
+}
+
+.plugin-settings-content {
+ border-bottom: 0px solid #eee;
+ margin-top: 3px;
+ width: 100%;
+}
+
+.plugin-settings {
+ overflow-x: hidden;
+}
+
+.plugin-version {
+ font-size: 13px;
+ font-weight: 400;
+ padding-right: 10px;
+}
+
+.plugin-description {
+ font-size: 13px;
+ white-space: normal;
+ padding-right: 10px;
+ min-width:100px;
+ max-width:200px;
+}
+
+.plugin-delete {
+ float: right;
+ position: relative;
+ background: white;
+ color: #666;
+ border: solid 1px #999;
+ border-radius: 2px;
+ font-size: 0.9em;
+}
+
+.plugin-action-area {
+ float: right;
+ position: relative;
+ background: white;
+ color: #666;
+ font-size: 0.9em;
+}
+
+.plugin-links-view {
+ padding-right: 15px;
+}
+
+.plugin-links {
+ padding-right: 13px;
+}
+#gcli-row-complete {
+ position: absolute;
+ top: 2px;
+ left: 0;
+ width: 100%;
+ height: 20px;
+ font-family: "Courier New", "Lucida Console", monospace;
+ font-size: 13px;
+ z-index: -1000;
+}
+#gcli-input {
+ width: 100%;
+ padding-left: 1em;
+ font-family: "Courier New","Lucida Console",monospace;
+ font-size: 13px;
+ background: transparent;
+}
+#gcli-display {
+ overflow: hidden;
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.html b/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.html
new file mode 100644
index 0000000..b91aa3d
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>Console</title>
+
+ <link rel="stylesheet" type="text/css" href="orion-gcli-console.css" />
+ <script type="text/javascript" src="../requirejs/require.js"></script>
+ <script type="text/javascript">
+
+ require({ baseUrl: '..',
+ packages: [{ name: 'dojo', location: 'org.dojotoolkit/dojo', main: 'lib/main-browser', lib: '.' },
+ { name: 'dijit', location: 'org.dojotoolkit/dijit', main: 'lib/main',lib: '.' },
+ { name: 'dojox', location: 'org.dojotoolkit/dojox', main: 'lib/main', lib: '.' } ],
+ paths: { text: 'requirejs/text', i18n: 'requirejs/i18n', domReady: 'requirejs/domReady' },
+ packagePaths: {
+ "console/gcli/lib": [
+ { name: "gcli", main: "index", lib: "." }
+// { name: "test", main: "index", lib: "." },
+// { name: "gclitest", main: "index", lib: "." },
+// { name: "demo", main: "index", lib: "." }
+ ]
+ }
+ });
+ require(["console/orion-gcli-console"]);
+ </script>
+ <body style="visibility:hidden" class="nihilo">
+ <div id="orion.console" class="orionPage" dojoType="dijit.layout.BorderContainer" design="headline" gutters="false">
+ <div class="banner" id="banner" dojoType="dijit.layout.ContentPane" region="top">
+ </div>
+ <div id="centerPane" dojoType="dijit.layout.BorderContainer" region="center" gutters="false" design="headline" liveSplitters="false" splitter="false">
+ <div class="toolbar" id="pageToolbar" dojoType="dijit.layout.ContentPane" splitter="false" region="top">
+ </div>
+ <div id="gcli-display" dojoType="dijit.layout.ContentPane" region="center"></div>
+ <div id="glci-input-area" dojoType="dijit.layout.ContentPane" region="bottom">
+ <input id="gcli-input"/>
+ <div id="gcli-row-complete"></div>
+ </div>
+ </div>
+ <div class="footer" id="footer" dojoType="dijit.layout.ContentPane" region="bottom" splitter="false">
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.js b/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.js
new file mode 100644
index 0000000..7f8b858
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.console/web/console/orion-gcli-console.js
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+ *
+ * Contributors:
+ * Contributors: IBM Corporation - initial API and implementation
+ * (copied: see explorer-table.js)
+ * Kris De Volder (VMWare) - Copied from explorer-table.js and modified to
+ * implement console page.
+ *******************************************************************************/
+/*global define require dojo dijit orion window widgets localStorage*/
+/*jslint browser:true devel:true*/
+
+define(['dojo', 'orion/bootstrap', 'orion/status', 'orion/commands', 'orion/globalCommands',
+ 'orion/searchClient', 'orion/fileClient', 'gcli/index', 'console/directory-type',
+ 'console/current-directory', 'orion/es5shim'],
+function(dojo, mBootstrap, mStatus, mCommands, mGlobalCommands, mSearchClient, mFileClient, gcli ) {
+
+ var withWorkspace = require('console/current-directory').withWorkspace;
+ var withCurrentTreeNode = require('console/current-directory').withCurrentTreeNode;
+ var withChildren = require('console/current-directory').withChildren;
+ var setCurrentTreeNode = require('console/current-directory').setCurrentTreeNode;
+ var getParentLocation = require('console/current-directory').getParentLocation;
+
+ var statusService;
+
+ ////////////////// implementation of the ls command ////////////////////////////////////////////////////////////
+
+ function editURL(node) {
+ //TODO: We should do this the right way. Orion probably has some
+ // service registration points to determine 'edit' actions based on the resource type.
+ // The only (bad) reason for this hacky implementation is that I do not yet know how to do
+ // it correctly.
+ return "/edit/edit.html#"+node.Location;
+ }
+
+ /**
+ * Helper function to format a single child node in a directory.
+ */
+ function formatLsChild(node, result) {
+ result = result || [];
+ if (node.Name) {
+ if (node.Directory) {
+ result.push(node.Name);
+ result.push('/');
+ } else {
+ result.push('<a href="');
+ result.push(editURL(node));
+ result.push('">');
+ result.push(node.Name); //TODO: html escape sequences?
+ result.push('</a>');
+ }
+ result.push('<br>');
+ }
+ return result;
+ }
+
+ /**
+ * Helper function to format the result of ls. Accepts a current file or workspace node and
+ * formats its children.
+ * <p>
+ * Optionally accepts an array 'result' to which the resulting Strings should be pushed.
+ * <p>
+ * To avoid massive String copying the result is returned as an array of
+ * Strings rather than one massive String. Caller should join('') the returned result.
+ */
+ function formatLs(node, result, k) {
+ result = result || [];
+ withChildren(node, function (children) {
+ for (var i = 0; i < children.length; i++) {
+ formatLsChild(children[i], result);
+ }
+ k(result);
+ });
+ }
+
+ /**
+ * Execution function for the ls gcli command
+ */
+ function lsExec(args, context) {
+ var result = context.createPromise();
+ setCurrentTreeNode(null); // Flushes current node cache.
+ withCurrentTreeNode(function (node) {
+ formatLs(node, [], function (buffer) {
+ result.resolve(buffer.join(''));
+ });
+ });
+ return result;
+ }
+
+ ////////// implementaton of the 'cd' command ///////////////////////////////////////////////////
+
+ function cdExec(args, context) {
+ var targetDirName = args.directory;
+ var result = context.createPromise();
+ withCurrentTreeNode(function (node) {
+ if (targetDirName==='..') {
+ var newLocation = getParentLocation(node);
+ if (newLocation!==null) {
+ dojo.hash(newLocation);
+ setCurrentTreeNode(null);
+ result.resolve('Changed to parent directory');
+ } else {
+ result.resolve('ERROR: Can not determine parent');
+ }
+ } else {
+ withChildren(node, function (children) {
+ var found = false;
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if (child.Name===targetDirName) {
+ if (child.Directory) {
+ found = true;
+ setCurrentTreeNode(child);
+ result.resolve('Working directory changed successfully');
+ } else {
+ result.resolve('ERROR: '+targetDirName+' is not a directory');
+ }
+ }
+ }
+ if (!found) {
+ result.resolve('ERROR: '+targetDirName+' not found.');
+ }
+ });
+ }
+ });
+ return result;
+ }
+
+ //////// implementation of the 'pwd' command ///////////////////////////////////////////
+
+ function pwdExec(args, context) {
+ //TODO: this implementation doesn't print the full path, only the name of the current
+ // directory node.
+ var result = context.createPromise();
+ withCurrentTreeNode(function (node) {
+ var buffer = formatLsChild(node);
+ result.resolve(buffer.join(''));
+ });
+ return result;
+ }
+
+ /**
+ * Add generally useful commands related to file/dir navigation.
+ * These commands are directly contributed to gcli, not via the 'orion.console.command'
+ * extension point.
+ */
+ function initGenericCommands() {
+ gcli.addCommand({
+ name: 'ls',
+ description: 'Show a list of files at the current directory',
+ exec: lsExec,
+ returnType: 'string'
+ });
+ gcli.addCommand({
+ name: 'cd',
+ description: 'Change current directory',
+ exec: cdExec,
+ returnType: 'string',
+ params: [
+ {
+ name: 'directory',
+ type: 'directory',
+ description: 'directory'
+ }
+ ]
+ });
+
+ gcli.addCommand({
+ name: 'pwd',
+ description: 'Print current directory',
+ exec: pwdExec,
+ returnType: 'string'
+ });
+ }
+
+ function render(text) {
+// var node = dojo.create("pre", {className: 'console-command-output'});
+// // setting textContent we don't need to worry about escaping stuff.
+// node.textContent = text;
+// return node;
+ var obj = JSON.parse(text);
+ for (var key in obj) {
+ var node = dojo.create(key, obj[key]);
+ // node.textContent = 'asdf';
+ return node;
+ }
+ }
+
+ /**
+ * This function creates a JSON object that contains bits of context information an
+ * external command may need access to to execute.
+ */
+ function createPluginContext(gcliContext, k) {
+ withWorkspace(function (wsNode) {
+ withCurrentTreeNode(function (pwdNode) {
+ return k({
+ location: pwdNode.Location,
+ workspaceLocation: wsNode.Location
+ });
+ });
+ });
+ }
+
+ /**
+ * Creates a gcli exec function wrapping a 'run' function contributed by
+ * a 'orion.console.command' service implementation.
+ */
+ function contributedExecFunc(service) {
+ if (typeof(service.run)==='function') {
+ //TODO: we may support different styles of exec functions based on
+ // properties set in the service. For now we just have the one
+ // type that executes asynchronously and renders the result as 'pre' text.
+ return function (args, context) {
+ var promise = context.createPromise();
+ createPluginContext(context, function (jsonContext) {
+ service.run(args, jsonContext).then(function (result) {
+ promise.resolve(render(result));
+ });
+ });
+ return promise;
+ };
+ }
+ return undefined;
+ //returns undefined if we can't create an exec function (typically because the
+ //service doesn't provide one and is just a parent node in the command hierarchy).
+ }
+
+ /**
+ * Wrap command implementations contributed via 'orion.console.command' extension
+ * point, and register them with gcli.
+ */
+ function initContributedCommands(serviceRegistry) {
+ var allReferences = serviceRegistry.getServiceReferences("orion.console.command");
+ for (var i = 0; i < allReferences.length; ++i) {
+ var ref = allReferences[i];
+ var service = serviceRegistry.getService(ref);
+ if (service) {
+ gcli.addCommand({
+ name: ref.getProperty("name"),
+ description: ref.getProperty("description"),
+ manual: ref.getProperty("manual"),
+ params: ref.getProperty("params"),
+ exec: contributedExecFunc(service)
+ });
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ function initCommands(serviceRegistry) {
+ initGenericCommands();
+ initContributedCommands(serviceRegistry);
+ }
+
+ //TODO: Do we really need to wait for both dojo.ready and mBootstrap.startup?
+ // Maybe one of them already implies the other?
+ dojo.ready(function() {
+ mBootstrap.startup().then(function(core) {
+
+ var serviceRegistry = core.serviceRegistry;
+ var preferences = core.preferences;
+
+ document.body.style.visibility = "visible";
+ dojo.parser.parse();
+
+ // Register services
+ statusService = new mStatus.StatusReportingService(serviceRegistry, "statusPane", "notifications");
+ var commandService = new mCommands.CommandService({serviceRegistry: serviceRegistry});
+ var searcher = new mSearchClient.Searcher({serviceRegistry: serviceRegistry, commandService: commandService, fileService: mFileClient});
+ mGlobalCommands.generateBanner("banner", serviceRegistry, commandService, preferences, searcher);
+
+ statusService.setMessage("Loading...");
+
+ initCommands(serviceRegistry);
+ gcli.createView();
+ });
+ });
+}); \ No newline at end of file