From 49dad82abbff5d90ddbaae267eaded716aaa003a Mon Sep 17 00:00:00 2001 From: Bradley Matusiak Date: Wed, 5 Dec 2012 19:13:48 -0500 Subject: [PATCH 01/24] added debugPort for runnning nodejs apps args '-b 5858' is default --- configs/default.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configs/default.js b/configs/default.js index 21685175d96..195df6305d6 100644 --- a/configs/default.js +++ b/configs/default.js @@ -21,6 +21,7 @@ var vfsUrl = "/vfs"; var port = argv.p || process.env.PORT || 3131; var host = argv.l || process.env.IP || "localhost"; +var debugPort = argv.b || process.env.DEBUG_PORT || 5858; var config = [ { @@ -184,7 +185,8 @@ var config = [ }, { packagePath: "./cloud9.run.node-debug", - listenHint: "Important: in your scripts, use 'process.env.PORT' as port and '0.0.0.0' as host." + listenHint: "Important: in your scripts, use 'process.env.PORT' as port and '0.0.0.0' as host.", + debugPort: debugPort }, "./cloud9.run.npm", "./cloud9.run.npmnode", From ef6d771113e21f7a588e5e46d3895446c122beb7 Mon Sep 17 00:00:00 2001 From: Mostafa Eweda Date: Fri, 7 Dec 2012 13:01:09 +0200 Subject: [PATCH 02/24] Fix function loop position calc --- plugins-client/ext.jslanguage/scope_analyzer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins-client/ext.jslanguage/scope_analyzer.js b/plugins-client/ext.jslanguage/scope_analyzer.js index c17f7507906..7371c00e8cc 100644 --- a/plugins-client/ext.jslanguage/scope_analyzer.js +++ b/plugins-client/ext.jslanguage/scope_analyzer.js @@ -506,8 +506,12 @@ handler.analyze = function(value, ast, callback) { }, 'Function(x, fargs, body)', function(b, node) { if (inLoop && !inLoopAllowed) { + var pos = this.getPos(); + // treehugger doesn't store info on the position of "function" token + var line = handler.doc.getLine(pos.sl); + var sc = line.substring(0, pos.sc).lastIndexOf("function"); markers.push({ - pos: { sl: this.getPos().sl, el: this.getPos().sl, sc: this.getPos().sc, ec: this.getPos().sc + "function".length }, + pos: { sl: pos.sl, el: pos.sl, sc: sc, ec: sc + "function".length }, level: 'warning', type: 'warning', message: "Function created in a loop." From 9b1bc9d8c41e61b528f31ee33de69f6794cb17d5 Mon Sep 17 00:00:00 2001 From: Mostafa Eweda Date: Fri, 7 Dec 2012 13:02:03 +0200 Subject: [PATCH 03/24] Fix runpanel typo --- plugins-client/ext.runpanel/runpanel.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins-client/ext.runpanel/runpanel.js b/plugins-client/ext.runpanel/runpanel.js index d6ae5434e05..14e68fed85d 100644 --- a/plugins-client/ext.runpanel/runpanel.js +++ b/plugins-client/ext.runpanel/runpanel.js @@ -147,7 +147,7 @@ module.exports = ext.register("ext/runpanel/runpanel", { } }), - menus.$insertByIndex(barTools, new apf.splitbutton({ + Menus.$insertByIndex(barTools, new apf.splitbutton({ id : "btnRun", checked : "[{require('ext/settings/settings').model}::auto/configurations/@debug]", icon : "{this.checked ? 'run.png' : 'run.png'}", @@ -158,7 +158,7 @@ module.exports = ext.register("ext/runpanel/runpanel", { submenu : "mnuRunCfg" }), 100), - menus.$insertByIndex(barTools, new apf.button({ + Menus.$insertByIndex(barTools, new apf.button({ id : "btnStop", icon : "stop.png", caption : "stop", From a3b895869ee3efdf60408bdb04280094e6dbfc3a Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 29 Dec 2012 18:06:27 +0100 Subject: [PATCH 04/24] Remove sourcemint as a dependency --- README.md | 68 +++---------------- configs/default.js | 4 -- package.json | 25 +++---- .../cloud9.client-plugins/package.json | 3 +- plugins-server/cloud9.sourcemint/package.json | 18 ----- .../cloud9.sourcemint/sourcemint.js | 42 ------------ 6 files changed, 20 insertions(+), 140 deletions(-) delete mode 100644 plugins-server/cloud9.sourcemint/package.json delete mode 100644 plugins-server/cloud9.sourcemint/sourcemint.js diff --git a/README.md b/README.md index f298696509d..ab9f1a3e223 100644 --- a/README.md +++ b/README.md @@ -38,24 +38,17 @@ Requirements: * NodeJS `>= 0.6.16` * NPM `>= 1.1.16` + * libxml2-dev Install: - # Be sure you have sourcemint installed: - - npm install -g sm - - # Then: - - sm clone --dev https://github.com/ajaxorg/cloud9/tree/master cloud9 - - # or - - git clone https://github.com/ajaxorg/cloud9.git cloud9 + git clone https://github.com/ajaxorg/cloud9.git cd cloud9 - sm install - + npm install +> If installation fails with `Failed at the libxml preinstall script.` make sure you have the +> libxml2-dev package installed. +> For example, on Ubuntu you install this via: `sudo apt-get install libxml2-dev`. The above install steps create a `cloud9` directory in your current directory. Just `cd` into it and run `bin/cloud9.sh` to start: @@ -91,54 +84,11 @@ on how we added basic authentication. To update to the latest version (if this doesn't work, just make a fresh clone): git pull - sm update - -`sm update` does not currently install missing npm dependencies. To do so use: - - sm install - -## Development - -To work on a subcomponent that is copied into node_modules, you can use `sm edit`. -For instance, to work on ACE, run the following from the checkout root: - - sm edit ace - -This is somewhat equivalent to `npm link` but instead of linking to a system wide -shared package it clones the source into the node_modules/ directory. -The idea is to only "edit" when you need to make changes and when done issue -"sm save " (not yet implemented) which will pull up sourcetree to commit, -push code and switch package back to read mode (frozen). The status page - - sm status - -shows problematic and improvement oriented action steps to improve the state of -the program. These relate to git status and dependency changes that need to be -made to bring the dependencies up to date and ready to publish which leads to deployment. - -The line on the status page will have a (W) if it is setup for editing. - -To launch Sourcetree for all dirty/ahead repositories in the dependency -tree use (need to have Sourcetree command-line tools installed (`stree`)): - - sm fix - -The sourcemint package manager works alongside NPM so to link in a -(system-wide shared) NPM package use: - - rm -R node_modules/architect - npm link architect - -`sm` always works on your program sub-tree other than pulling things in -from the cache. - -To view help info for cloud9 use: - - sm help + npm update -To view usage info for `sm` use: +`npm update` does not currently install missing dependencies. To do so use: - sm -h + npm install ## Open Source Projects Used diff --git a/configs/default.js b/configs/default.js index 96f861afa2b..280005a5fff 100644 --- a/configs/default.js +++ b/configs/default.js @@ -29,10 +29,6 @@ var config = [ packagePath: "connect-architect/connect", port: port, host: host - }, { - packagePath: "./cloud9.sourcemint", - prefix: "/static/bundles", - plugins: clientExtensions }, { packagePath: "connect-architect/connect.static", prefix: "/static" diff --git a/package.json b/package.json index 00131825e1d..f38d2622931 100644 --- a/package.json +++ b/package.json @@ -3,19 +3,16 @@ "description": "Cloud9 IDE", "version": "0.7.0", "homepage" : "http://github.com/ajaxorg/cloud9", - "engines": {"node": ">= 0.6.15"}, + "engines": {"node": ">= 0.8.x"}, "author": "Ajax.org B.V. ", "help": { "web": "https://github.com/ajaxorg/cloud9/blob/master/README.md", "cli": "./scripts/help.js" }, - "pm": "sm", "dependencies": { "connect": "1.8.7", - "sourcemint-loader-js": "0.x", - "sourcemint-platform-nodejs": "0.x", "http-error": "0.0.1", "simple-template": "0.0.1", @@ -32,7 +29,15 @@ "smith": "0.1.9", "smith.io": "0.0.36", "vfs-architect": "0.0.2", - "jsDAV": "0.2.4" + "jsDAV": "0.2.4", + + "ace": "https://github.com/ajaxorg/ace/tarball/cc2a2c9e056c6d4049f8849ec3ad72974de37177", + "apf": "https://github.com/ajaxorg/apf/tarball/145f65bd24ae83f041418dd01a9c51d278045f3f", + "asyncjs": "https://github.com/ajaxorg/async.js/tarball/0b4ed5608a32c280a7690b5f52883d8d1fc0de08", + "v8debug": "https://github.com/ajaxorg/lib-v8debug/tarball/d2fac9b09724cb2e75e2807191eace9bc27d3b52", + "packager": "https://github.com/ajaxorg/packager/tarball/bee2a82c6d5e2875024bfdc83937e98092ccf04f", + "treehugger": "https://github.com/ajaxorg/treehugger/tarball/b22d7ad712f76a7e7b1070ab339d567dfbf059b1", + "runjs": "https://github.com/c9/runjs/tarball/347ad9627fb4a1d63458bc66ea40f0bf1efbf05c" }, "devDependencies": { @@ -43,16 +48,6 @@ "vfs-nodefs-adapter": "~0.3.0" }, - "mappings": { - "ace": ["npm", "https://github.com/ajaxorg/ace/tarball/cc2a2c9e056c6d4049f8849ec3ad72974de37177"], - "apf": ["npm", "https://github.com/ajaxorg/apf/tarball/145f65bd24ae83f041418dd01a9c51d278045f3f"], - "asyncjs": ["npm", "https://github.com/ajaxorg/async.js/tarball/0b4ed5608a32c280a7690b5f52883d8d1fc0de08"], - "v8debug": ["npm", "https://github.com/ajaxorg/lib-v8debug/tarball/d2fac9b09724cb2e75e2807191eace9bc27d3b52"], - "packager": ["npm", "https://github.com/ajaxorg/packager/tarball/bee2a82c6d5e2875024bfdc83937e98092ccf04f"], - "treehugger": ["npm", "https://github.com/ajaxorg/treehugger/tarball/b22d7ad712f76a7e7b1070ab339d567dfbf059b1"], - "runjs": ["npm", "https://github.com/c9/runjs/tarball/347ad9627fb4a1d63458bc66ea40f0bf1efbf05c"] - }, - "repository" : { "type" : "git", "url" : "git://github.com/ajaxorg/cloud9.git" diff --git a/plugins-server/cloud9.client-plugins/package.json b/plugins-server/cloud9.client-plugins/package.json index 14a1ab33316..8c43895ac04 100644 --- a/plugins-server/cloud9.client-plugins/package.json +++ b/plugins-server/cloud9.client-plugins/package.json @@ -11,8 +11,7 @@ "provides": ["client-plugins"], "consumes": [ "static", - "log", - "sourcemint" + "log" ] } } \ No newline at end of file diff --git a/plugins-server/cloud9.sourcemint/package.json b/plugins-server/cloud9.sourcemint/package.json deleted file mode 100644 index 152fffc78cc..00000000000 --- a/plugins-server/cloud9.sourcemint/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "cloud9.sourcemint", - "version": "0.0.1", - "main": "sourcemint.js", - "private": true, - "dependencies": { - "sourcemint-loader-js": "0.x", - "sourcemint-platform-nodejs": "0.x" - }, - - "plugin": { - "provides": ["sourcemint"], - "consumes": [ - "log", - "connect" - ] - } -} \ No newline at end of file diff --git a/plugins-server/cloud9.sourcemint/sourcemint.js b/plugins-server/cloud9.sourcemint/sourcemint.js deleted file mode 100644 index 24f2d29db92..00000000000 --- a/plugins-server/cloud9.sourcemint/sourcemint.js +++ /dev/null @@ -1,42 +0,0 @@ -var path = require("path"); -var fs = require("fs"); -var bundler = require("sourcemint-platform-nodejs/lib/bundler"); - -module.exports = function startup(options, imports, register) { - - var plugins = options.plugins || {}; - var prefix = (options.prefix || "/static/bundles"); - - var loaderStatic = imports.connect.getModule().static(path.dirname(require.resolve("sourcemint-loader-js/package.json"))); - - imports.connect.useStart(imports.connect.getModule().router(function(app) { - - // Serve the sourcemint loader file. - app.get(/^(\/loader\.[^\/]*)/, function(req, res) { - req.url = req.params[0]; - loaderStatic(req, res, function() { - res.writeHead(404); - res.end("Not found!"); - }); - }); - - // Serve client plugin bundles if available. - for (var name in plugins) { - var route = new RegExp("^" + prefix.replace(/\//g, "\\/") + "\\/" + name + "(?:\.js)?(\\/.*)?$"); - var packagePath = plugins[name] + "/package.json"; - if (path.existsSync(packagePath)) { - var descriptor = JSON.parse(fs.readFileSync(packagePath)); - if (descriptor.bundled === true) { - imports.log.log("MINT", route, plugins[name]); - app.get(route, bundler.hoist(plugins[name], { - packageIdHashSeed: "c9os" - })); - } - } - }; - })); - - register(null, { - "sourcemint": {} - }); -}; \ No newline at end of file From eeaf5e5ee0cf04a92dc6e0ccd7d358f2f78ff84e Mon Sep 17 00:00:00 2001 From: Jan Jongboom Date: Sat, 29 Dec 2012 18:27:36 +0000 Subject: [PATCH 05/24] Windows compatibility --- configs/default.js | 6 +++--- package.json | 2 +- plugins-server/cloud9.core/ide.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configs/default.js b/configs/default.js index 280005a5fff..fe3d8564dd7 100644 --- a/configs/default.js +++ b/configs/default.js @@ -5,14 +5,14 @@ var argv = require('optimist').argv; var path = require("path"); var clientExtensions = {}; -var clientDirs = fs.readdirSync(__dirname + "/../plugins-client"); +var clientDirs = fs.readdirSync(path.join(__dirname, "/../plugins-client")); for (var i = 0; i < clientDirs.length; i++) { var dir = clientDirs[i]; if (dir.indexOf("ext.") !== 0) continue; var name = dir.split(".")[1]; - clientExtensions[name] = __dirname + "/../plugins-client/" + dir; + clientExtensions[name] = path.join(__dirname, "../plugins-client/", dir); } var projectDir = (argv.w && path.resolve(process.cwd(), argv.w)) || process.cwd(); @@ -148,7 +148,7 @@ var config = [ ] }, { packagePath: "vfs-architect/local", - root: "/" + root: path.dirname(projectDir) }, { packagePath: "vfs-architect/http-adapter", mount: vfsUrl, diff --git a/package.json b/package.json index f38d2622931..4f91e8f4209 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "smith": "0.1.9", "smith.io": "0.0.36", "vfs-architect": "0.0.2", - "jsDAV": "0.2.4", + "jsDAV": "https://github.com/ajaxorg/jsDAV/tarball/209289355d69adde11dbcd0c83e6dd24a6d9184a", "ace": "https://github.com/ajaxorg/ace/tarball/cc2a2c9e056c6d4049f8849ec3ad72974de37177", "apf": "https://github.com/ajaxorg/apf/tarball/145f65bd24ae83f041418dd01a9c51d278045f3f", diff --git a/plugins-server/cloud9.core/ide.js b/plugins-server/cloud9.core/ide.js index 50b6e6f5dd7..85ea9b31bd8 100644 --- a/plugins-server/cloud9.core/ide.js +++ b/plugins-server/cloud9.core/ide.js @@ -45,7 +45,7 @@ var Ide = module.exports = function(options) { plugins: options.plugins, bundledPlugins: options.bundledPlugins || [], requirejsConfig: options.requirejsConfig, - projectName: options.projectName || this.workspaceDir.split("/").pop(), + projectName: options.projectName || Path.basename(this.workspaceDir), version: options.version, extra: options.extra, hosted: !!options.hosted, From 4855545d957340523539661a2f94d43607f2a6e4 Mon Sep 17 00:00:00 2001 From: Jan Jongboom Date: Sat, 29 Dec 2012 19:30:24 +0100 Subject: [PATCH 06/24] Add docs for installation on Windows --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ab9f1a3e223..42188e22013 100644 --- a/README.md +++ b/README.md @@ -40,16 +40,20 @@ Requirements: * NPM `>= 1.1.16` * libxml2-dev +If you're running Cloud9 on Windows you'll have to follow these steps as well: + + * Install [Grep for Windows](http://gnuwin32.sourceforge.net/downlinks/grep.php) + * Add `C:\Program Files (x86)\GnuWin32\bin` to your [PATH](http://www.computerhope.com/issues/ch000549.htm) + * Open a new instance of `cmd` with elevated rights (right click 'Run as adminstrator') + * Now follow the steps under 'Install' + * *Please note that the `npm install` fails due to a libxml error, but you can ignore that for now.* + Install: git clone https://github.com/ajaxorg/cloud9.git cd cloud9 npm install -> If installation fails with `Failed at the libxml preinstall script.` make sure you have the -> libxml2-dev package installed. -> For example, on Ubuntu you install this via: `sudo apt-get install libxml2-dev`. - The above install steps create a `cloud9` directory in your current directory. Just `cd` into it and run `bin/cloud9.sh` to start: From 2e37292cd504eb58b43698dd30d0dc76c12bff03 Mon Sep 17 00:00:00 2001 From: Jan Jongboom Date: Sat, 29 Dec 2012 18:43:08 +0000 Subject: [PATCH 07/24] Readme section for Windows --- README.md | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 42188e22013..9826c1aa4ec 100644 --- a/README.md +++ b/README.md @@ -34,20 +34,14 @@ We support the newer versions of Chrome, Firefox and Safari. ## Installation and Usage +If installing on Windows, please refer to [Installation on Windows](#installation-on-windows) + Requirements: * NodeJS `>= 0.6.16` * NPM `>= 1.1.16` * libxml2-dev -If you're running Cloud9 on Windows you'll have to follow these steps as well: - - * Install [Grep for Windows](http://gnuwin32.sourceforge.net/downlinks/grep.php) - * Add `C:\Program Files (x86)\GnuWin32\bin` to your [PATH](http://www.computerhope.com/issues/ch000549.htm) - * Open a new instance of `cmd` with elevated rights (right click 'Run as adminstrator') - * Now follow the steps under 'Install' - * *Please note that the `npm install` fails due to a libxml error, but you can ignore that for now.* - Install: git clone https://github.com/ajaxorg/cloud9.git @@ -83,6 +77,24 @@ Cloud9 is compatible with all connect authentication layers, to implement your own, please see the `plugins-server/cloud9.connect.basic-auth` plugin on how we added basic authentication. +## Installation on Windows (experimental) + +If you're running Cloud9 on Windows you'll have to follow these steps as well: + + * Install [Grep for Windows](http://gnuwin32.sourceforge.net/downlinks/grep.php) + * Add `C:\Program Files (x86)\GnuWin32\bin` to your [PATH](http://www.computerhope.com/issues/ch000549.htm) + * Open a new instance of `cmd` with elevated rights (right click 'Run as adminstrator') + * Now follow the steps under 'Install' + * *Please note that the `npm install` fails due to a libxml error, but you can ignore that for now.* + +To start Cloud9, please don't start through `bin/cloud9.sh` but rather via: + + node server.js [args] + +Please note that there will be errors displayed regarding the `find` command, +and that some features might not work. +Feel free to improve the Windows experience and open a pull request. + ## Updating To update to the latest version (if this doesn't work, just make a fresh clone): From 2be7a0c59ac67c08756ff7958b486b6152ab45b3 Mon Sep 17 00:00:00 2001 From: Jan Jongboom Date: Sat, 29 Dec 2012 18:44:25 +0000 Subject: [PATCH 08/24] Link fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9826c1aa4ec..46d0393bcb9 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ We support the newer versions of Chrome, Firefox and Safari. ## Installation and Usage -If installing on Windows, please refer to [Installation on Windows](#installation-on-windows) +If installing on Windows, please refer to [Installation on Windows](##installation-on-windows-experimental). Requirements: From 7f262dbb41ed0217ed87efde25d0edf2c7bde86c Mon Sep 17 00:00:00 2001 From: Lennart Kats Date: Tue, 15 Jan 2013 15:14:47 +0100 Subject: [PATCH 09/24] Avoid spurious cd command --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46d0393bcb9..2f8d4c3131f 100644 --- a/README.md +++ b/README.md @@ -48,10 +48,9 @@ Install: cd cloud9 npm install -The above install steps create a `cloud9` directory in your current directory. Just `cd` into it -and run `bin/cloud9.sh` to start: +The above install steps create a `cloud9` directory with a `bin/cloud9.sh` +script that can be used to start Cloud9: - cd cloud9 bin/cloud9.sh Optionally, you may specify the directory you'd like to edit: From 99e888b1a79031990ee00e9d9d31204ae8f1ba97 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 17 Jan 2013 19:22:06 +1100 Subject: [PATCH 10/24] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f298696509d..f40c49d438a 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Requirements: * NodeJS `>= 0.6.16` * NPM `>= 1.1.16` + * libxml-dev Install: From 2f178faa464531f20c27862cc4ba50227a9edfb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uli=20K=C3=B6hler?= Date: Tue, 29 Jan 2013 14:36:05 +0100 Subject: [PATCH 11/24] Improve install section in README --- README.md | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f298696509d..14305af8dbf 100644 --- a/README.md +++ b/README.md @@ -40,21 +40,18 @@ Requirements: * NPM `>= 1.1.16` Install: - - # Be sure you have sourcemint installed: - - npm install -g sm - - # Then: - - sm clone --dev https://github.com/ajaxorg/cloud9/tree/master cloud9 - - # or - - git clone https://github.com/ajaxorg/cloud9.git cloud9 - cd cloud9 - sm install - +```sh +# Be sure you have sourcemint installed: +npm install -g sm + +# Then: +sm clone --dev https://github.com/ajaxorg/cloud9/tree/master cloud9 + +# or +git clone https://github.com/ajaxorg/cloud9.git cloud9 +cd cloud9 +sm install +``` The above install steps create a `cloud9` directory in your current directory. Just `cd` into it From 504fbc0eb42da50de15567d5d4f337c03339849f Mon Sep 17 00:00:00 2001 From: ldoblies Date: Fri, 15 Feb 2013 15:36:50 +0100 Subject: [PATCH 12/24] Add quickfix framework --- .../ext.language/MarkerResolution.js | 26 + plugins-client/ext.language/language.js | 2 + plugins-client/ext.language/language.xml | 23 + plugins-client/ext.language/marker.js | 4 +- plugins-client/ext.language/quickfix.js | 450 ++++++++++++++++++ 5 files changed, 504 insertions(+), 1 deletion(-) create mode 100644 plugins-client/ext.language/MarkerResolution.js create mode 100644 plugins-client/ext.language/quickfix.js diff --git a/plugins-client/ext.language/MarkerResolution.js b/plugins-client/ext.language/MarkerResolution.js new file mode 100644 index 00000000000..8045ecc680f --- /dev/null +++ b/plugins-client/ext.language/MarkerResolution.js @@ -0,0 +1,26 @@ + +define(function(require, exports, module) { +"use strict"; + +/** +* data structure for resolutions, containing +* a label (short description, to be displayed in the list of resolutions), +* an image (to be displayed in the list of resolutions), +* a preview, +* the applied content, +* the position where the cursor should be after applying +*/ +var MarkerResolution = function(label, image, preview, appliedContent, cursorTarget){ + return { + label: label, + image: image, + preview: preview, + appliedContent: appliedContent, + cursorTarget: cursorTarget + }; +}; + + +exports.MarkerResolution = MarkerResolution; + +}); \ No newline at end of file diff --git a/plugins-client/ext.language/language.js b/plugins-client/ext.language/language.js index 51ef38f6e75..75eb1579022 100644 --- a/plugins-client/ext.language/language.js +++ b/plugins-client/ext.language/language.js @@ -17,6 +17,7 @@ var UIWorkerClient = require("ace/worker/worker_client").UIWorkerClient; var useUIWorker = window.location && /[?&]noworker=1/.test(window.location.search); var complete = require("ext/language/complete"); +var quickfix = require("ext/language/quickfix"); var marker = require("ext/language/marker"); var refactor = require("ext/language/refactor"); var outline = require("ext/language/outline"); @@ -92,6 +93,7 @@ module.exports = ext.register("ext/language/language", { outline.hook(_self, worker); keyhandler.hook(_self, worker); jumptodef.hook(_self, worker); + quickfix.hook(_self); ide.dispatchEvent("language.worker", {worker: worker}); ide.addEventListener("$event.language.worker", function(callback){ diff --git a/plugins-client/ext.language/language.xml b/plugins-client/ext.language/language.xml index b52c4876383..a6f2f43fc6e 100644 --- a/plugins-client/ext.language/language.xml +++ b/plugins-client/ext.language/language.xml @@ -124,4 +124,27 @@ + + + + + + + + + + + diff --git a/plugins-client/ext.language/marker.js b/plugins-client/ext.language/marker.js index e1bbb6313c4..fc878fb7ba2 100644 --- a/plugins-client/ext.language/marker.js +++ b/plugins-client/ext.language/marker.js @@ -83,7 +83,9 @@ module.exports = { var gutterAnno = { guttertext: anno.message, type: anno.level || "warning", - text: anno.message + text: anno.message, + pos: anno.pos, + resolutions: anno.resolutions // row will be filled in updateFloat() }; diff --git a/plugins-client/ext.language/quickfix.js b/plugins-client/ext.language/quickfix.js new file mode 100644 index 00000000000..ce7ea0e8d77 --- /dev/null +++ b/plugins-client/ext.language/quickfix.js @@ -0,0 +1,450 @@ +/** + * Cloud9 Language Foundation + * + * @copyright 2011, Ajax.org B.V. + * @license GPLv3 + */ +define(function(require, exports, module) { + +/*global barQuickfixCont sbQuickfix txtQuickfixHolder txtQuickfix txtQuickfixDoc */ + +var ide = require("core/ide"); +var dom = require("ace/lib/dom"); +var code = require("ext/code/code"); +var editors = require("ext/editors/editors"); +var lang = require("ace/lib/lang"); + +var quickfix; + +var oldCommandKey, oldOnTextInput; + +var CLASS_SELECTED = "cc_complete_option selected"; +var CLASS_UNSELECTED = "cc_complete_option"; +var SHOW_DOC_DELAY = 1500; +var SHOW_DOC_DELAY_MOUSE_OVER = 100; +var HIDE_DOC_DELAY = 1000; +var MENU_WIDTH = 400; +var MENU_SHOWN_ITEMS = 9; +var EXTRA_LINE_HEIGHT = 3; +var QFBOX_MINTIME = 500; + + +var ignoreMouseOnce = false; +var isDocShown; +var isDrawDocInvokeScheduled = false; + +var drawDocInvoke = lang.deferredCall(function() { + if (isPopupVisible() && quickfix.quickFixes[quickfix.selectedIdx].preview) { + isDocShown = true; + txtQuickfixDoc.parentNode.show(); + } + isDrawDocInvokeScheduled = false; +}); + +var undrawDocInvoke = lang.deferredCall(function() { + if (!isPopupVisible()) { + isDocShown = false; + txtQuickfixDoc.parentNode.hide(); + } +}); + +function isPopupVisible() { + return barQuickfixCont.$ext.style.display !== "none"; +} + +var commands = require("ext/commands/commands"); + +module.exports = { + + hook: function(ext) { + var _self = this; + quickfix = this; + + ide.addEventListener("tab.afterswitch", function(e) { + var page = e.nextPage; + if (!page || !page.$editor || page.$editor.path != "ext/code/code") + return; + var ace = page.$editor.amlEditor.$editor; + + if (!ace.$markerListener) + _self.initEditor(ace); + }); + + + commands.addCommand({ + name: "quickfix", + hint: "quickfix", + bindKey: {mac: "Ctrl-Shift-Q|Ctrl-Alt-Q", win: "Ctrl-Shift-Q|Ctrl-Alt-Q"}, + isAvailable : function(editor){ + return apf.activeElement.localName == "codeeditor"; + }, + exec: function(editor) { + _self.invoke(); + } + }); + + + }, + + init: function(amlNode) { + }, + + initEditor : function(editor){ + var _self = this; + + editor.on("guttermousedown", editor.$markerListener = function(e) { + _self.editor = editor; + if (e.getButton()) // !editor.isFocused() + return; + var gutterRegion = editor.renderer.$gutterLayer.getRegion(e); + if (gutterRegion != "markers") + return; + + var row = e.getDocumentPosition().row; + _self.showQuickfixBox(row, 0); + + }); + }, + + getAnnos: function(row){ + var editor = editors.currentEditor.amlEditor.$editor; + var res = []; + + editor.getSession().languageAnnos.forEach(function(anno, idx){ + if (anno.row == row){ + res.push(anno); + + /* Select the annotation in the editor */ + anno.select = function(){ + var startPos = { row: anno.pos.sl, column: anno.pos.sc }; + var endPos = { row: anno.pos.el, column: anno.pos.ec }; + editor.getSelection().setSelectionRange( + {start: startPos, end: endPos}); + }; + + /* + * Returns the screen coordinates of the start of the annotation + */ + anno.getScreenCoordinates = function(){ + return editor.renderer.textToScreenCoordinates(anno.pos.sl, + anno.pos.sc); + }; + } + }); + + res.sort(function(a,b){ return a.pos.sc - b.pos.sc; }); + + return res; + }, + + + + showQuickfixBox: function(row, column) { + var _self = this; + + // Get the annotation on this line that is containing or left of the + // position (row,column) + var annos = _self.getAnnos(row); + if (!annos.length){ + return; + } + for (var i = 0; i < annos.length - 1; i++){ + if (annos[i+1].pos.sc > column){ break; } + } + var anno = annos[i]; + if (!anno.resolutions.length){ + // TODO If some other annotation on this line has resolutions, + // quickfix that one instead + return; + } + + this.editor = editors.currentEditor; + var ace = this.editor.amlEditor.$editor; + this.selectedIdx = 0; + this.scrollIdx = 0; + this.quickfixEls = []; + //this.annos = annos; + this.quickFixes = []; + this.quickfixElement = txtQuickfix.$ext; + this.docElement = txtQuickfixDoc.$ext; + this.cursorConfig = ace.renderer.$cursorLayer.config; + this.lineHeight = this.cursorConfig.lineHeight + EXTRA_LINE_HEIGHT; + var style = dom.computedStyle(this.editor.amlEditor.$ext); + this.quickfixElement.style.fontSize = style.fontSize; + + barQuickfixCont.setAttribute('visible', true); + + + // Monkey patch + if(!oldCommandKey) { + oldCommandKey = ace.keyBinding.onCommandKey; + ace.keyBinding.onCommandKey = this.onKeyPress.bind(this); + oldOnTextInput = ace.keyBinding.onTextInput; + ace.keyBinding.onTextInput = this.onTextInput.bind(this); + } + + // Collect all quickfixes for the given annotation + _self.quickFixes = anno.resolutions; + + // Select it in the editor + anno.select(); + + this.populateQuickfixBox(this.quickFixes); + + apf.popup.setContent("quickfixBox", barQuickfixCont.$ext); + var boxLength = this.quickFixes.length || 1; + var quickfixBoxHeight = 11 + Math.min(10 * this.lineHeight, boxLength * (this.lineHeight)); + + var innerBoxLength = this.quickFixes.length || 1; + var innerQuickfixBoxHeight = Math.min(10 * this.lineHeight, innerBoxLength * (this.lineHeight)); + txtQuickfixHolder.$ext.style.height = innerQuickfixBoxHeight + "px"; + + ignoreMouseOnce = !isPopupVisible(); + + var pos = anno.getScreenCoordinates(); + apf.popup.show("quickfixBox", { + x : pos.pageX, + y : pos.pageY + _self.cursorConfig.lineHeight, + height : quickfixBoxHeight, + width : MENU_WIDTH, + animate : false, + callback : function() { + barQuickfixCont.setHeight(quickfixBoxHeight); + barQuickfixCont.$ext.style.height = quickfixBoxHeight + "px"; + sbQuickfix.$resize(); + // HACK: Need to set with non-falsy value first + _self.quickfixElement.scrollTop = 1; + _self.quickfixElement.scrollTop = 0; + } + }); + + this.popupTime = new Date().getTime(); + document.addEventListener("click", quickfix.closeQuickfixBox, false); + ace.container.addEventListener("DOMMouseScroll", quickfix.closeQuickfixBox, false); + ace.container.addEventListener("mousewheel", quickfix.closeQuickfixBox, false); + }, + + closeQuickfixBox : function(event) { + var qfBoxTime = new Date().getTime() - quickfix.popupTime; + if (!quickfix.forceClose && qfBoxTime < QFBOX_MINTIME){ + return; + } + + quickfix.forceClose = false; + + barQuickfixCont.$ext.style.display = "none"; + if (!editors.currentEditor.amlEditor) // no editor, try again later + return; + var ace = editors.currentEditor.amlEditor.$editor; + + // TODO these calls don't work. + document.removeEventListener("click", quickfix.closeQuickfixBox, false); + ace.container.removeEventListener("DOMMouseScroll", quickfix.closeQuickfixBox, false); + ace.container.removeEventListener("mousewheel", quickfix.closeQuickfixBox, false); + + if(oldCommandKey) { + ace.keyBinding.onCommandKey = oldCommandKey; + ace.keyBinding.onTextInput = oldOnTextInput; + } + oldCommandKey = oldOnTextInput = null; + undrawDocInvoke.schedule(HIDE_DOC_DELAY); + }, + + + populateQuickfixBox: function(quickFixes) { + + var _self = this; + _self.quickfixElement.innerHTML = ""; + var cursorConfig = code.amlEditor.$editor.renderer.$cursorLayer.config; + + // For each quickfix, create a list entry + quickFixes.forEach(function(qfix, qfidx){ + + var annoEl = dom.createElement("div"); + annoEl.className = qfidx === _self.selectedIdx ? CLASS_SELECTED : CLASS_UNSELECTED; + var html = ""; + + if (qfix.image) + html = ""; + + html += '' + qfix.label + ''; + + annoEl.innerHTML = html; + + annoEl.addEventListener("mouseover", function() { + if (ignoreMouseOnce) { + ignoreMouseOnce = false; + return; + } + _self.quickfixEls[_self.selectedIdx].className = CLASS_UNSELECTED; + _self.selectedIdx = qfidx; + _self.quickfixEls[_self.selectedIdx].className = CLASS_SELECTED; + _self.updateDoc(); + if (!isDrawDocInvokeScheduled) + drawDocInvoke.schedule(SHOW_DOC_DELAY_MOUSE_OVER); + }); + + + annoEl.addEventListener("click", function() { + quickfix.forceClose = true; + _self.applyQuickfix(qfix); + }); + + + annoEl.style.height = cursorConfig.lineHeight + EXTRA_LINE_HEIGHT + "px"; + annoEl.style.width = (MENU_WIDTH - 10) + "px"; + _self.quickfixElement.appendChild(annoEl); + _self.quickfixEls.push(annoEl); + }); + + _self.updateDoc(true); + + }, + + updateDoc : function(delayPopup) { + this.docElement.innerHTML = ''; + var selected = this.quickFixes[this.selectedIdx]; + + if (selected && selected.preview) { + if (isDocShown) { + txtQuickfixDoc.parentNode.show(); + } + else { + txtQuickfixDoc.parentNode.hide(); + if (!isDrawDocInvokeScheduled || delayPopup) + drawDocInvoke.schedule(SHOW_DOC_DELAY); + } + this.docElement.innerHTML += + selected.preview.replace(/\n/g, '
') + '
'; + } + else { + txtQuickfixDoc.parentNode.hide(); + } + + this.docElement.innerHTML += ''; + }, + + enable : function() { + }, + + disable : function() { + }, + + destroy : function() { + }, + + applyQuickfix : function(qfix){ + var amlEditor = editors.currentEditor.amlEditor; + var doc = amlEditor.getSession().getDocument(); + // TODO make the cursortarget default to current cursor position + var cursorTarget = { + line: 0, + column: 0 + }; + doc.setValue(qfix.appliedContent); + amlEditor.focus(); + + if (qfix.cursorTarget){ + cursorTarget = qfix.cursorTarget; + } + var selection = amlEditor.$editor.getSelection(); + selection.clearSelection(); + selection.moveCursorTo(cursorTarget.line, + cursorTarget.column, false); + }, + + onTextInput : function(text, pasted) { + this.closeQuickfixBox(); + }, + + onKeyPress : function(e, hashKey, keyCode) { + + if(e.metaKey || e.ctrlKey || e.altKey) { + this.closeQuickfixBox(); + return; + } + + var keyBinding = editors.currentEditor.amlEditor.$editor.keyBinding; + + switch(keyCode) { + case 0: break; + case 32: // Space + this.closeQuickfixBox(); + break; + case 27: // Esc + this.closeQuickfixBox(); + e.preventDefault(); + break; + case 8: // Backspace + this.closeQuickfixBox(); + e.preventDefault(); + break; + case 37: + case 39: + oldCommandKey.apply(keyBinding, arguments); + this.closeQuickfixBox(); + e.preventDefault(); + break; + case 13: // Enter + case 9: // Tab + this.applyQuickfix(this.quickFixes[this.selectedIdx]); + quickfix.forceClose = true; + this.closeQuickfixBox(); + e.stopPropagation(); + e.preventDefault(); + break; + case 40: // Down + if (this.quickfixEls.length === 1) { + this.closeQuickfixBox(); + break; + } + e.stopPropagation(); + e.preventDefault(); + this.quickfixEls[this.selectedIdx].className = CLASS_UNSELECTED; + if(this.selectedIdx < this.quickFixes.length-1) + this.selectedIdx++; + this.quickfixEls[this.selectedIdx].className = CLASS_SELECTED; + if(this.selectedIdx - this.scrollIdx > MENU_SHOWN_ITEMS) { + this.scrollIdx++; + this.quickfixEls[this.scrollIdx].scrollIntoView(true); + } + this.updateDoc(); + break; + case 38: // Up + if (this.quickfixEls.length === 1) { + this.closeQuickfixBox(); + break; + } + e.stopPropagation(); + e.preventDefault(); + if (this.selectedIdx <= 0) + return; + this.quickfixEls[this.selectedIdx].className = CLASS_UNSELECTED; + this.selectedIdx--; + this.quickfixEls[this.selectedIdx].className = CLASS_SELECTED; + if(this.selectedIdx < this.scrollIdx) { + this.scrollIdx--; + this.quickfixEls[this.scrollIdx].scrollIntoView(true); + } + this.updateDoc(); + break; + } + }, + + invoke: function(forceBox) { + var _self = this; + var editor = editors.currentEditor.amlEditor.$editor; + if (editor.inMultiSelectMode) { + _self.closeQuickfixBox(); + return; + } + _self.forceBox = forceBox; + + var pos = editor.getCursorPosition(); + + _self.showQuickfixBox(pos.row, pos.column); + } + +}; + +}); From 2ab7f2c51e3ce34e40bcf07c72a50637502c4664 Mon Sep 17 00:00:00 2001 From: Ruben Daniels Date: Tue, 19 Feb 2013 09:09:25 +0100 Subject: [PATCH 13/24] Using -e to fix installation on some platforms --- bin/cloud9.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/cloud9.sh b/bin/cloud9.sh index 633e9f79767..768557b10d3 100755 --- a/bin/cloud9.sh +++ b/bin/cloud9.sh @@ -1,6 +1,6 @@ #!/bin/sh -CMD="$(readlink $0)" +CMD="$(readlink -e $0)" CMD_DIR=`dirname "$CMD"` cd "$CMD_DIR/.." From f873beea6ad33841b78d59eff2fe3def7cfe398e Mon Sep 17 00:00:00 2001 From: ldoblies Date: Wed, 20 Feb 2013 19:14:04 +0100 Subject: [PATCH 14/24] Add js quickfix example --- plugins-client/ext.jslanguage/JSResolver.js | 51 +++++++++++++++++++++ plugins-client/ext.jslanguage/jshint.js | 5 ++ 2 files changed, 56 insertions(+) create mode 100644 plugins-client/ext.jslanguage/JSResolver.js diff --git a/plugins-client/ext.jslanguage/JSResolver.js b/plugins-client/ext.jslanguage/JSResolver.js new file mode 100644 index 00000000000..90778e608c2 --- /dev/null +++ b/plugins-client/ext.jslanguage/JSResolver.js @@ -0,0 +1,51 @@ +define(function(require, exports, module) { + "use strict"; + + var markerResolution = require('ext/language/MarkerResolution').MarkerResolution; + + var JSResolver = function(ast){ + this.addResolutions = function(markers){ + var _self = this; + markers.forEach(function(curMarker) { + curMarker.resolutions = _self.getResolutions(curMarker); + }); + }; + + this.getResolutions = function(marker){ + var type = this.getType(marker); + if (type){ + if (typeof this[type] === 'function'){ + return this[type](marker); + } + } + return []; + }; + + this.getType = function(marker){ + var msg = marker.message; + if (msg.indexOf("Missing semicolon") !== -1){ + return "missingSemicolon"; + }else if (msg.indexOf("Unnecessary semicolon") !== -1){ + return "unnecessarySemicolon"; + } + return undefined; + }; + + this.unnecessarySemicolon = function(marker){ + var label = "Remove semicolon";var image = ""; + var preview = "Remove unnecessary semicolon"; + + var appliedContent = "Not implemented"; + + return [markerResolution(label,image,preview,appliedContent)]; + }; + + this.missingSemicolon = function(marker){ + return [markerResolution("Not implemented", "", "Not implemented", "Not implemented")]; + }; + + }; + + exports.JSResolver = JSResolver; + +}); diff --git a/plugins-client/ext.jslanguage/jshint.js b/plugins-client/ext.jslanguage/jshint.js index aab074959ce..61934872baa 100644 --- a/plugins-client/ext.jslanguage/jshint.js +++ b/plugins-client/ext.jslanguage/jshint.js @@ -9,6 +9,7 @@ define(function(require, exports, module) { var baseLanguageHandler = require('ext/language/base_handler'); var lint = require("ace/mode/javascript/jshint").JSHINT; var handler = module.exports = Object.create(baseLanguageHandler); +var JSResolver = require('ext/jslanguage/JSResolver').JSResolver; var disabledJSHintWarnings = [/Missing radix parameter./, /Bad for in variable '(.+)'./, @@ -83,6 +84,10 @@ handler.analyzeSync = function(value, ast) { message: warning.reason }); }); + + var resolver = new JSResolver(ast); + resolver.addResolutions(markers); + return markers; }; From 9b09e126752fe0d6835e15db94a38d72764d5f2f Mon Sep 17 00:00:00 2001 From: ldoblies Date: Thu, 21 Feb 2013 12:50:55 +0100 Subject: [PATCH 15/24] Added application of missing/unnecessary semicolon quickfixes --- plugins-client/ext.jslanguage/JSResolver.js | 46 ++++++++++++++------- plugins-client/ext.jslanguage/jshint.js | 2 +- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/plugins-client/ext.jslanguage/JSResolver.js b/plugins-client/ext.jslanguage/JSResolver.js index 90778e608c2..b194ba83537 100644 --- a/plugins-client/ext.jslanguage/JSResolver.js +++ b/plugins-client/ext.jslanguage/JSResolver.js @@ -3,7 +3,7 @@ define(function(require, exports, module) { var markerResolution = require('ext/language/MarkerResolution').MarkerResolution; - var JSResolver = function(ast){ + var JSResolver = function(value, ast){ this.addResolutions = function(markers){ var _self = this; markers.forEach(function(curMarker) { @@ -19,29 +19,45 @@ define(function(require, exports, module) { } } return []; - }; + }; this.getType = function(marker){ var msg = marker.message; if (msg.indexOf("Missing semicolon") !== -1){ return "missingSemicolon"; - }else if (msg.indexOf("Unnecessary semicolon") !== -1){ + } else if (msg.indexOf("Unnecessary semicolon") !== -1){ return "unnecessarySemicolon"; } - return undefined; - }; - - this.unnecessarySemicolon = function(marker){ - var label = "Remove semicolon";var image = ""; - var preview = "Remove unnecessary semicolon"; - - var appliedContent = "Not implemented"; - - return [markerResolution(label,image,preview,appliedContent)]; - }; + }; this.missingSemicolon = function(marker){ - return [markerResolution("Not implemented", "", "Not implemented", "Not implemented")]; + console.log(marker.pos); + var label = "Add semicolon"; + var image = ""; + + var lines = value.split("\n"); + var before = lines[marker.pos.sl].substring(0, marker.pos.sc); + var after = lines[marker.pos.sl].substring(marker.pos.sc); + lines[marker.pos.sl] = before + "; " + after; + var preview = "Add semicolon

" + before + "; " + after + "

"; + var appliedContent = lines.join("\n"); + + return [markerResolution(label, image, preview, appliedContent)]; + }; + + this.unnecessarySemicolon = function(marker){ + console.log(marker.pos); + var label = "Remove semicolon"; + var image = ""; + + var lines = value.split("\n"); + var before = lines[marker.pos.sl].substring(0, marker.pos.sc); + var after = lines[marker.pos.sl].substring(marker.pos.sc + 1); + lines[marker.pos.sl] = before + after; + var preview = "Remove semicolon

" + before + ";" + after + "

"; + var appliedContent = lines.join("\n"); + + return [markerResolution(label, image, preview, appliedContent)]; }; }; diff --git a/plugins-client/ext.jslanguage/jshint.js b/plugins-client/ext.jslanguage/jshint.js index 61934872baa..f14dc5f7e3a 100644 --- a/plugins-client/ext.jslanguage/jshint.js +++ b/plugins-client/ext.jslanguage/jshint.js @@ -85,7 +85,7 @@ handler.analyzeSync = function(value, ast) { }); }); - var resolver = new JSResolver(ast); + var resolver = new JSResolver(value, ast); resolver.addResolutions(markers); return markers; From b3e5410a0b6b01ab281ae2ece1825e275f54d586 Mon Sep 17 00:00:00 2001 From: Mark Theunissen Date: Mon, 18 Feb 2013 11:45:36 -0600 Subject: [PATCH 16/24] Hiding the password --- server.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/server.js b/server.js index 95b22052755..22b374f7828 100755 --- a/server.js +++ b/server.js @@ -15,6 +15,17 @@ if (configName.indexOf("-") === 0) { configName = "default"; } +// If a password is given as a command line parameter, we hide it +// in the title of the process instead of displaying it in plain +// text. +var title_parts = process.argv; +title_parts.forEach(function(element, index, array) { + if (element === '--password') { + array[index+1] = 'xxxxxxxx'; + } +}); +process.title = title_parts.join(' '); + var debug = false; var packed = false; var packedName = ""; @@ -22,20 +33,20 @@ var packedName = ""; for (var p = 2; p < process.argv.length; p++) { if (process.argv[p] === "-d") { debug = true; - + // apf debug doesn't exist, or it's older than three days--rebuild it if(!path.existsSync("plugins-client/lib.apf/www/apf-packaged/apf_debug.js") || (path.existsSync("plugins-client/lib.apf/www/apf-packaged/apf_debug.js")) && ((new Date() - fs.statSync("plugins-client/lib.apf/www/apf-packaged/apf_debug.js").mtime.valueOf()) / 86400000) >= 3) { console.log("Building apfdebug for first run..."); - + var buildDebug = spawn("npm", ["run-script", "build-debug"]); - + buildDebug.stderr.setEncoding("utf8"); buildDebug.stderr.on('data', function (data) { console.error(data); }); - + buildDebug.on('exit', function (code) { if (code !== 0) { console.error('build-debug process exited with code ' + code); @@ -65,7 +76,7 @@ for (var p = 2; p < process.argv.length; p++) { " '---''(_/--' `-'\\_) Felix Lee"); var buildPackage = spawn("npm", ["run-script", "build-packed"]); - + buildPackage.stderr.setEncoding("utf8"); buildPackage.stderr.on('data', function (data) { console.error(data); From 6320b10993a8b45dc1cbf00224ba9fa5050b8082 Mon Sep 17 00:00:00 2001 From: Mark Theunissen Date: Mon, 18 Feb 2013 14:47:10 -0600 Subject: [PATCH 17/24] Make a copy of array --- server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.js b/server.js index 22b374f7828..a01c4cf1a62 100755 --- a/server.js +++ b/server.js @@ -18,7 +18,7 @@ if (configName.indexOf("-") === 0) { // If a password is given as a command line parameter, we hide it // in the title of the process instead of displaying it in plain // text. -var title_parts = process.argv; +var title_parts = process.argv.slice(); title_parts.forEach(function(element, index, array) { if (element === '--password') { array[index+1] = 'xxxxxxxx'; From 2c2b453a5d1b2768bc4ca3b41db55d6626e280f8 Mon Sep 17 00:00:00 2001 From: basdewachter Date: Mon, 25 Feb 2013 16:39:10 +0100 Subject: [PATCH 18/24] more generic way to determine path, works in MacOS --- bin/cloud9.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/cloud9.sh b/bin/cloud9.sh index 768557b10d3..717ca823455 100755 --- a/bin/cloud9.sh +++ b/bin/cloud9.sh @@ -1,7 +1,6 @@ #!/bin/sh -CMD="$(readlink -e $0)" -CMD_DIR=`dirname "$CMD"` +CMD_DIR="$( cd "$( dirname "$0" )" && pwd )" cd "$CMD_DIR/.." make update From fdf681cac6d685329eab655311a4a41d24d5c2fa Mon Sep 17 00:00:00 2001 From: ldoblies Date: Wed, 6 Mar 2013 17:06:50 +0100 Subject: [PATCH 19/24] Pass delta objects as resolution instead of whole editor contents to apply quickfixes --- plugins-client/ext.jslanguage/JSResolver.js | 39 +++++++++++++------ plugins-client/ext.jslanguage/jshint.js | 2 +- .../ext.language/MarkerResolution.js | 9 ++--- plugins-client/ext.language/quickfix.js | 27 ++++++------- 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/plugins-client/ext.jslanguage/JSResolver.js b/plugins-client/ext.jslanguage/JSResolver.js index b194ba83537..232323b9f03 100644 --- a/plugins-client/ext.jslanguage/JSResolver.js +++ b/plugins-client/ext.jslanguage/JSResolver.js @@ -2,6 +2,7 @@ define(function(require, exports, module) { "use strict"; var markerResolution = require('ext/language/MarkerResolution').MarkerResolution; + var Range = require("ace/range").Range; var JSResolver = function(value, ast){ this.addResolutions = function(markers){ @@ -34,30 +35,46 @@ define(function(require, exports, module) { console.log(marker.pos); var label = "Add semicolon"; var image = ""; + var row = marker.pos.sl; + var column = marker.pos.sc; var lines = value.split("\n"); - var before = lines[marker.pos.sl].substring(0, marker.pos.sc); - var after = lines[marker.pos.sl].substring(marker.pos.sc); - lines[marker.pos.sl] = before + "; " + after; + var before = lines[row].substring(0, column); + var after = lines[row].substring(column); var preview = "Add semicolon

" + before + "; " + after + "

"; - var appliedContent = lines.join("\n"); - return [markerResolution(label, image, preview, appliedContent)]; - }; + var insert = ";"; + if (after.length){ + insert += " "; + } + + var delta = { + action: "insertText", + range: new Range(row, column, row, column + insert.length), + text: insert + }; + + return [markerResolution(label, image, preview, [delta])]; + }; this.unnecessarySemicolon = function(marker){ console.log(marker.pos); var label = "Remove semicolon"; var image = ""; + var row = marker.pos.sl; + var column = marker.pos.sc; var lines = value.split("\n"); - var before = lines[marker.pos.sl].substring(0, marker.pos.sc); - var after = lines[marker.pos.sl].substring(marker.pos.sc + 1); - lines[marker.pos.sl] = before + after; + var before = lines[row].substring(0, column); + var after = lines[row].substring(column + 1); var preview = "Remove semicolon

" + before + ";" + after + "

"; - var appliedContent = lines.join("\n"); + + var delta = { + action: "removeText", + range: new Range(row, column, row, column + 1) + }; - return [markerResolution(label, image, preview, appliedContent)]; + return [markerResolution(label, image, preview, [delta])]; }; }; diff --git a/plugins-client/ext.jslanguage/jshint.js b/plugins-client/ext.jslanguage/jshint.js index f14dc5f7e3a..39c59f32e44 100644 --- a/plugins-client/ext.jslanguage/jshint.js +++ b/plugins-client/ext.jslanguage/jshint.js @@ -75,7 +75,7 @@ handler.analyzeSync = function(value, ast) { if(disabledJSHintWarnings[i].test(warning.reason)) return; markers.push({ - pos: { + pos: { // TODO quickfix framework needs el/ec in order to be able to select the issue in the editor sl: warning.line-1, sc: warning.character-1 }, diff --git a/plugins-client/ext.language/MarkerResolution.js b/plugins-client/ext.language/MarkerResolution.js index 8045ecc680f..92682406638 100644 --- a/plugins-client/ext.language/MarkerResolution.js +++ b/plugins-client/ext.language/MarkerResolution.js @@ -7,19 +7,18 @@ define(function(require, exports, module) { * a label (short description, to be displayed in the list of resolutions), * an image (to be displayed in the list of resolutions), * a preview, -* the applied content, +* an array of deltas (containing the changes to be applied), * the position where the cursor should be after applying */ -var MarkerResolution = function(label, image, preview, appliedContent, cursorTarget){ +var MarkerResolution = function(label, image, preview, deltas, cursorTarget){ return { label: label, image: image, preview: preview, - appliedContent: appliedContent, + deltas: deltas, cursorTarget: cursorTarget }; -}; - +}; exports.MarkerResolution = MarkerResolution; diff --git a/plugins-client/ext.language/quickfix.js b/plugins-client/ext.language/quickfix.js index ce7ea0e8d77..af53ae4274e 100644 --- a/plugins-client/ext.language/quickfix.js +++ b/plugins-client/ext.language/quickfix.js @@ -116,10 +116,15 @@ module.exports = { /* Select the annotation in the editor */ anno.select = function(){ + if (!(anno.pos.sl && anno.pos.sc && anno.pos.el && anno.pos.ec)){ + return; + } var startPos = { row: anno.pos.sl, column: anno.pos.sc }; var endPos = { row: anno.pos.el, column: anno.pos.ec }; - editor.getSelection().setSelectionRange( - {start: startPos, end: endPos}); + if (startPos.row < endPos.row || startPos.column < endPos.column){ + editor.getSelection().setSelectionRange( + {start: startPos, end: endPos}); + } }; /* @@ -336,21 +341,17 @@ module.exports = { applyQuickfix : function(qfix){ var amlEditor = editors.currentEditor.amlEditor; var doc = amlEditor.getSession().getDocument(); - // TODO make the cursortarget default to current cursor position - var cursorTarget = { - line: 0, - column: 0 - }; - doc.setValue(qfix.appliedContent); + + doc.applyDeltas(qfix.deltas); amlEditor.focus(); if (qfix.cursorTarget){ - cursorTarget = qfix.cursorTarget; - } - var selection = amlEditor.$editor.getSelection(); - selection.clearSelection(); - selection.moveCursorTo(cursorTarget.line, + var cursorTarget = qfix.cursorTarget; + var selection = amlEditor.$editor.getSelection(); + selection.clearSelection(); + selection.moveCursorTo(cursorTarget.line, cursorTarget.column, false); + } }, onTextInput : function(text, pasted) { From e18f45cb6f730166a5f1079cdc924001e732157c Mon Sep 17 00:00:00 2001 From: ldoblies Date: Fri, 8 Mar 2013 14:27:23 +0100 Subject: [PATCH 20/24] hasResolutions() getResolutions() added to language framework --- plugins-client/ext.jslanguage/jshint.js | 5 +---- plugins-client/ext.jslanguage/scope_analyzer.js | 17 +++++++++++++++++ plugins-client/ext.language/base_handler.js | 16 ++++++++++++++++ plugins-client/ext.language/worker.js | 13 ++++++++++--- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/plugins-client/ext.jslanguage/jshint.js b/plugins-client/ext.jslanguage/jshint.js index 39c59f32e44..ad1b876332c 100644 --- a/plugins-client/ext.jslanguage/jshint.js +++ b/plugins-client/ext.jslanguage/jshint.js @@ -9,7 +9,6 @@ define(function(require, exports, module) { var baseLanguageHandler = require('ext/language/base_handler'); var lint = require("ace/mode/javascript/jshint").JSHINT; var handler = module.exports = Object.create(baseLanguageHandler); -var JSResolver = require('ext/jslanguage/JSResolver').JSResolver; var disabledJSHintWarnings = [/Missing radix parameter./, /Bad for in variable '(.+)'./, @@ -85,12 +84,10 @@ handler.analyzeSync = function(value, ast) { }); }); - var resolver = new JSResolver(value, ast); - resolver.addResolutions(markers); - return markers; }; + /** * Gets an object like { foo: true } for JSHint global comments * like / * global foo: true * / diff --git a/plugins-client/ext.jslanguage/scope_analyzer.js b/plugins-client/ext.jslanguage/scope_analyzer.js index 1160fce7b66..5b9e92a9740 100644 --- a/plugins-client/ext.jslanguage/scope_analyzer.js +++ b/plugins-client/ext.jslanguage/scope_analyzer.js @@ -19,6 +19,8 @@ var completeUtil = require("ext/codecomplete/complete_util"); var handler = module.exports = Object.create(baseLanguageHandler); var outline = require("ext/jslanguage/outline"); var jshint = require("ext/jslanguage/jshint"); +var JSResolver = require('ext/jslanguage/JSResolver').JSResolver; + require("treehugger/traverse"); // add traversal functions to trees var CALLBACK_METHODS = ["forEach", "map", "reduce", "filter", "every", "some"]; @@ -260,6 +262,21 @@ handler.handlesLanguage = function(language) { return language === 'javascript'; }; +handler.getResolutions = function(value, ast, markers, callback){ + var resolver = new JSResolver(value, ast); + resolver.addResolutions(markers); + callback(markers); +}; + +handler.hasResolution = function(value, ast, marker) { + if (marker.resolutions && marker.resolutions.length){ + return true; + } + var resolver = new JSResolver(value, ast); + return resolver.getType(marker); +}; + + var scopeId = 0; var Variable = module.exports.Variable = function Variable(declaration) { diff --git a/plugins-client/ext.language/base_handler.js b/plugins-client/ext.language/base_handler.js index 93ea551f63b..972a0a79607 100644 --- a/plugins-client/ext.language/base_handler.js +++ b/plugins-client/ext.language/base_handler.js @@ -229,6 +229,22 @@ module.exports = { */ jumpToDefinition: function(doc, fullAst, pos, currentNode, callback) { callback(); + }, + + /** + * Invoked after markers were generated in analyze() + * @return marker array with attached resolutions + */ + getResolutions: function(doc, fullAst, markers, callback) { + callback(); + }, + + /** + * @return true iff the resolver for this marker could generate + * at least one resolution for it + */ + hasResolution: function(doc, fullAst, marker, callback) { + callback(); } }; diff --git a/plugins-client/ext.language/worker.js b/plugins-client/ext.language/worker.js index 3b11d67ff84..9247847f3cb 100644 --- a/plugins-client/ext.language/worker.js +++ b/plugins-client/ext.language/worker.js @@ -418,8 +418,15 @@ function asyncParForEach(array, fn, callback) { asyncForEach(_self.handlers, function(handler, next) { if (handler.handlesLanguage(part.language)) { handler.analyze(part.value, ast, function(result) { - if (result) - partMarkers = partMarkers.concat(result); + if (result){ + handler.getResolutions(part.value, ast, result, function(result2){ + if (result2){ + partMarkers = partMarkers.concat(result2); + }else{ + partMarkers = partMarkers.concat(result); + } + }); + } next(); }); } @@ -455,7 +462,7 @@ function asyncParForEach(array, fn, callback) { callback(); }); }; - + this.checkForMarker = function(pos) { var astPos = {line: pos.row, col: pos.column}; for (var i = 0; i < this.currentMarkers.length; i++) { From e973be0bb7a54dc524faffac8e6b46bf64608e0a Mon Sep 17 00:00:00 2001 From: mahnerak Date: Sun, 7 Apr 2013 23:44:07 +0400 Subject: [PATCH 21/24] status.c9.io protocol fix https://status.c9.io/ is not working, because there's no valid SSL certificate. Changing to http://status.c9.io/ --- plugins-server/cloud9.core/view/ide.tmpl.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins-server/cloud9.core/view/ide.tmpl.html b/plugins-server/cloud9.core/view/ide.tmpl.html index a71ab4fc8c8..250ec7ee8f8 100644 --- a/plugins-server/cloud9.core/view/ide.tmpl.html +++ b/plugins-server/cloud9.core/view/ide.tmpl.html @@ -44,7 +44,7 @@ var footer = document.createElement("div"); footer.className = "footer"; // yes this is bad - footer.innerHTML = 'Documentation | Server Status | Support'; + footer.innerHTML = 'Documentation | Server Status | Support'; var content = document.createElement("div"); content.className = "loading-progress"; From 7bc4cffb0085bca249a12dc85f3e665dd8093947 Mon Sep 17 00:00:00 2001 From: Bradley Matusiak Date: Wed, 10 Apr 2013 18:26:04 -0400 Subject: [PATCH 22/24] apf fix for depreciated feature --- plugins-client/lib.apf/www/apf-packaged/apf_release.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins-client/lib.apf/www/apf-packaged/apf_release.js b/plugins-client/lib.apf/www/apf-packaged/apf_release.js index 114943531d4..dfc94d378e2 100644 --- a/plugins-client/lib.apf/www/apf-packaged/apf_release.js +++ b/plugins-client/lib.apf/www/apf-packaged/apf_release.js @@ -40158,7 +40158,7 @@ apf.runWebkit = function(){ var bytes = Array.prototype.map.call(string, function(c) { return c.charCodeAt(0) & 0xff; }); - this.send(new Uint8Array(bytes).buffer); + this.send(new Uint8Array(bytes)); }; } } From db917c825b28e87563e83ba13998aa8834e5604b Mon Sep 17 00:00:00 2001 From: Bradley Matusiak Date: Thu, 11 Apr 2013 16:49:39 -0400 Subject: [PATCH 23/24] x-file-size can be sent as undefined text --- plugins-server/cloud9.fs/fs/file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins-server/cloud9.fs/fs/file.js b/plugins-server/cloud9.fs/fs/file.js index b16b90adb35..5e71ac06941 100644 --- a/plugins-server/cloud9.fs/fs/file.js +++ b/plugins-server/cloud9.fs/fs/file.js @@ -29,7 +29,7 @@ require("util").inherits(jsDAV_FS_File, jsDAV_FS_Node); var path = this.path; // is it a chunked upload? var size = handler.httpRequest.headers["x-file-size"]; - if (size) { + if (size && size !== "undefined") { var parts = Util.splitPath(this.path); if (!handler.httpRequest.headers["x-file-name"]) handler.httpRequest.headers["x-file-name"] = parts[1]; From 96b6af0deb42ddb50747027d7d96725525f1444a Mon Sep 17 00:00:00 2001 From: Mostafa Eweda Date: Mon, 29 Apr 2013 20:57:09 +0200 Subject: [PATCH 24/24] Stick back to node 0.6.x and fix the broken vfs-local + get rid of runjs --- configs/default.js | 2 +- package.json | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/configs/default.js b/configs/default.js index 9265f972aad..f3f38a0b6b1 100644 --- a/configs/default.js +++ b/configs/default.js @@ -149,7 +149,7 @@ var config = [ ] }, { packagePath: "vfs-architect/local", - root: path.dirname(projectDir) + root: "/" }, { packagePath: "vfs-architect/http-adapter", mount: vfsUrl, diff --git a/package.json b/package.json index 4f91e8f4209..6925263c0de 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "Cloud9 IDE", "version": "0.7.0", "homepage" : "http://github.com/ajaxorg/cloud9", - "engines": {"node": ">= 0.8.x"}, + "engines": {"node": ">= 0.6.15"}, "author": "Ajax.org B.V. ", "help": { "web": "https://github.com/ajaxorg/cloud9/blob/master/README.md", @@ -36,8 +36,7 @@ "asyncjs": "https://github.com/ajaxorg/async.js/tarball/0b4ed5608a32c280a7690b5f52883d8d1fc0de08", "v8debug": "https://github.com/ajaxorg/lib-v8debug/tarball/d2fac9b09724cb2e75e2807191eace9bc27d3b52", "packager": "https://github.com/ajaxorg/packager/tarball/bee2a82c6d5e2875024bfdc83937e98092ccf04f", - "treehugger": "https://github.com/ajaxorg/treehugger/tarball/b22d7ad712f76a7e7b1070ab339d567dfbf059b1", - "runjs": "https://github.com/c9/runjs/tarball/347ad9627fb4a1d63458bc66ea40f0bf1efbf05c" + "treehugger": "https://github.com/ajaxorg/treehugger/tarball/b22d7ad712f76a7e7b1070ab339d567dfbf059b1" }, "devDependencies": {