kopia lustrzana https://github.com/c9/core
Merge pull request +13073 from c9/ide-file-tree
fix issues with file treepull/282/head
commit
7eb38be6c6
|
@ -127,10 +127,20 @@ exports.trimTrailingSpace = function(session, options) {
|
|||
var lines = doc.getAllLines();
|
||||
|
||||
var min = options && options.trimEmpty ? -1 : 0;
|
||||
var cursors = session.selection.rangeCount
|
||||
? session.selection.ranges.map(function(x) { return x.cursor; })
|
||||
: [session.selection.getCursor()];
|
||||
var ci = options && options.keepCursorPosition ? 0 : -1;
|
||||
var cursors = [], ci = -1;
|
||||
if (options && options.keepCursorPosition) {
|
||||
if (session.selection.rangeCount) {
|
||||
session.selection.rangeList.ranges.forEach(function(x, i, ranges) {
|
||||
var next = ranges[i + 1]
|
||||
if (next && next.cursor.row == x.cursor.row)
|
||||
return;
|
||||
cursors.push(x.cursor);
|
||||
});
|
||||
} else {
|
||||
cursors.push(session.selection.getCursor());
|
||||
}
|
||||
ci = 0;
|
||||
}
|
||||
var cursorRow = cursors[ci] && cursors[ci].row;
|
||||
|
||||
for (var i = 0, l=lines.length; i < l; i++) {
|
||||
|
@ -139,7 +149,7 @@ exports.trimTrailingSpace = function(session, options) {
|
|||
|
||||
if (i == cursorRow) {
|
||||
if (index < cursors[ci].column)
|
||||
index = min;
|
||||
index = cursors[ci].column;
|
||||
ci++;
|
||||
cursorRow = cursors[ci] ? cursors[ci].row : -1;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
if (typeof process !== "undefined") {
|
||||
require("amd-loader");
|
||||
require("../test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
require("../multi_select");
|
||||
var assert = require("assert");
|
||||
var EditSession = require("../edit_session").EditSession;
|
||||
var UndoManager = require("../undomanager").UndoManager;
|
||||
var whitespace = require("./whitespace");
|
||||
|
||||
// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite
|
||||
|
@ -111,8 +112,79 @@ module.exports = {
|
|||
assert.equal(indent.length, 1);
|
||||
|
||||
next();
|
||||
}
|
||||
},
|
||||
|
||||
"test trimTrailingSpace": function(next) {
|
||||
var session = new EditSession([
|
||||
"a",
|
||||
"\t b \t",
|
||||
" ",
|
||||
"\t",
|
||||
"\t\tx\t\t",
|
||||
" ",
|
||||
" "
|
||||
]);
|
||||
session.setUndoManager(new UndoManager());
|
||||
|
||||
function testOne(value, options) {
|
||||
console.log(JSON.stringify(session.getValue()))
|
||||
|
||||
whitespace.trimTrailingSpace(session, options);
|
||||
assert.equal(value, session.getValue());
|
||||
session.markUndoGroup();
|
||||
session.getUndoManager().undo();
|
||||
}
|
||||
|
||||
testOne("a\n\t b\n \n\t\n\t\tx\n \n ")
|
||||
|
||||
testOne("a\n\t b\n\n\n\t\tx\n\n", {
|
||||
trimEmpty: true
|
||||
});
|
||||
|
||||
session.selection.fromJSON([{
|
||||
start: {row:2,column:3},
|
||||
end: {row:4,column:4}
|
||||
}]);
|
||||
testOne("a\n\t b\n\n\n\t\tx\t\n\n", {
|
||||
keepCursorPosition: true,
|
||||
trimEmpty: true
|
||||
});
|
||||
|
||||
session.selection.fromJSON([{
|
||||
start: {row:2,column:3},
|
||||
end: {row:4,column:4},
|
||||
isBackwards: true
|
||||
}]);
|
||||
testOne("a\n\t b\n \n\n\t\tx\n\n", {
|
||||
keepCursorPosition: true,
|
||||
trimEmpty: true
|
||||
});
|
||||
|
||||
session.selection.$initRangeList();
|
||||
session.selection.fromJSON([{
|
||||
start: {row:2, column:3},
|
||||
end: {row:2,column:3}
|
||||
}, {
|
||||
start: {row:1, column:1},
|
||||
end: {row:1, column:1}
|
||||
}, {
|
||||
start: {row:2,column:2},
|
||||
end: {row:2,column:2}
|
||||
}, {
|
||||
start: {row:0,column:5},
|
||||
end: {row:0,column:5},
|
||||
isBackwards:false
|
||||
}, {
|
||||
start: {row:6,column:1},
|
||||
end: {row:6,column:1},
|
||||
isBackwards:false
|
||||
}]);
|
||||
testOne("a\n\t b\n \n\n\t\tx\n\n ", {
|
||||
trimEmpty: true,
|
||||
keepCursorPosition: true
|
||||
});
|
||||
next();
|
||||
},
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -49,7 +49,7 @@ var DataProvider = function(root) {
|
|||
};
|
||||
|
||||
this.open =
|
||||
this.expand = function(node, deep, silent, justLoaded) {
|
||||
this.expand = function(node, deep, silent) {
|
||||
if (typeof deep != "number")
|
||||
deep = deep ? 100 : 0;
|
||||
if (!node)
|
||||
|
@ -69,7 +69,7 @@ var DataProvider = function(root) {
|
|||
this.collapse(node, null, true);
|
||||
node.status = "loaded";
|
||||
if (!err)
|
||||
this.expand(node, null, false, true);
|
||||
this.expand(node, null, false);
|
||||
}.bind(this));
|
||||
this.setOpen(node, true);
|
||||
return;
|
||||
|
@ -95,9 +95,6 @@ var DataProvider = function(root) {
|
|||
}
|
||||
}
|
||||
|
||||
if (justLoaded)
|
||||
node.justLoaded = true;
|
||||
|
||||
this.rows = items.length;
|
||||
silent || this._signal("expand", node);
|
||||
};
|
||||
|
|
|
@ -157,11 +157,12 @@ var EditableTree = function(tree) {
|
|||
this.ace.commands.bindKeys({
|
||||
"Esc": function(ace) {
|
||||
ace.treeEditor.endRename(true);
|
||||
ace.treeEditor.tree.focus();
|
||||
},
|
||||
"Enter": function(ace) {
|
||||
ace.treeEditor.endRename();
|
||||
ace.treeEditor.tree.focus();
|
||||
},
|
||||
"ctrl-s|cmd-s": function(ace) {
|
||||
ace.treeEditor.endRename();
|
||||
},
|
||||
"Tab": function(ace) {
|
||||
ace.treeEditor.editNext(1);
|
||||
|
@ -249,17 +250,24 @@ var EditableTree = function(tree) {
|
|||
this._destroyEditor = function() {
|
||||
if (this.lastDomNode) {
|
||||
this.lastDomNode.style.color = "";
|
||||
this.lastDomNode
|
||||
this.lastDomNode;
|
||||
}
|
||||
this.ace.off("blur", this._onBlur);
|
||||
|
||||
this.tree.renderer.off("afterRender", this._onAfterRender);
|
||||
this.ace.blur();
|
||||
|
||||
this.ace.destroy();
|
||||
if (this.ace.wrapper.parentNode)
|
||||
this.ace.wrapper.parentNode.removeChild(this.ace.wrapper);
|
||||
var ace = this.ace;
|
||||
this.ace = null;
|
||||
ace.renderer.freeze();
|
||||
setTimeout(function() {
|
||||
// doing this after timeout to allow rename event focus something else
|
||||
var wasFocused = ace.isFocused();
|
||||
ace.destroy();
|
||||
if (ace.wrapper.parentNode)
|
||||
ace.wrapper.parentNode.removeChild(ace.wrapper);
|
||||
if (wasFocused)
|
||||
this.tree.focus();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
this.findNextEditPoint = function(dir, node, col, keepColumn) {
|
||||
|
@ -378,16 +386,18 @@ var EditableTree = function(tree) {
|
|||
|
||||
var val = this.ace.getValue();
|
||||
|
||||
this._destroyEditor();
|
||||
|
||||
if (!cancel && this.origVal !== val) {
|
||||
this.tree._emit("rename", {
|
||||
node: node,
|
||||
value: val,
|
||||
oldValue: this.origVal,
|
||||
column: this.column
|
||||
});
|
||||
this.tree.provider._signal("change");
|
||||
}
|
||||
|
||||
this._destroyEditor();
|
||||
};
|
||||
|
||||
}).call(EditableTree.prototype);
|
||||
|
|
|
@ -1032,7 +1032,16 @@ module.exports = function setup(fsOptions) {
|
|||
if (!exists || options.overwrite || isSamePath) {
|
||||
// Rename the file
|
||||
fs.rename(frompath, topath, function (err) {
|
||||
if (err) return callback(err);
|
||||
if (err) {
|
||||
if (err.code == 'ENOENT' && options.mkdirP != false) {
|
||||
options.mkdirP = false;
|
||||
return mkdirP(dir, {}, function(err) {
|
||||
if (err) return callback(err);
|
||||
rename(path, options, callback);
|
||||
});
|
||||
}
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// Rename metadata
|
||||
if (options.metadata !== false) {
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
"c9"
|
||||
],
|
||||
"c9plugins": {
|
||||
"c9.ide.language": "#6d5a10ac4f",
|
||||
"c9.ide.language": "#ebc064ef16",
|
||||
"c9.ide.language.css": "#be07d72209",
|
||||
"c9.ide.language.generic": "#92210f5a48",
|
||||
"c9.ide.language.html": "#22fdc74869",
|
||||
|
@ -116,7 +116,7 @@
|
|||
"c9.ide.theme.flat": "#81dadeee55",
|
||||
"c9.ide.threewaymerge": "#229382aa0b",
|
||||
"c9.ide.undo": "#b028bcb4d5",
|
||||
"c9.ide.upload": "#0bd010d3dc",
|
||||
"c9.ide.upload": "#a3da59803d",
|
||||
"c9.ide.welcome": "#5b86c44e92",
|
||||
"c9.ide.guide": "#8ab966f344"
|
||||
}
|
||||
|
|
|
@ -82,6 +82,9 @@ define(function(require, exports, module) {
|
|||
node.status = "pending";
|
||||
return;
|
||||
}
|
||||
var parentPath = e.path;
|
||||
if (!parentPath.endsWith("/"))
|
||||
parentPath += "/";
|
||||
// update cache
|
||||
if (!node) {
|
||||
if (!showHidden && isFileHidden(e.path))
|
||||
|
@ -92,97 +95,116 @@ define(function(require, exports, module) {
|
|||
orphans[e.path] = node;
|
||||
orphan = true;
|
||||
}
|
||||
node.$lastReadT = Date.now();
|
||||
|
||||
// Indicate this directory has been fully read
|
||||
model.setAttribute(node, "status", "loaded");
|
||||
|
||||
var wasOpen = startUpdate(node);
|
||||
node.children = null;
|
||||
var existing = node.map || {};
|
||||
node.map = {};
|
||||
|
||||
// Fill Parent
|
||||
var ondisk = {}, toAppend = [];
|
||||
var ondisk = Object.create(null);
|
||||
var toRemove = [];
|
||||
var toCreate = [];
|
||||
var orphanAppand = [];
|
||||
var existing = node.map || (node.map = Object.create(null));
|
||||
e.result[1].forEach(function(stat) {
|
||||
if (!stat.name || !showHidden && isFileHidden(stat.name))
|
||||
return;
|
||||
|
||||
var name = stat.name;
|
||||
var path = (e.path + "/" + name).replace("//", "/");
|
||||
var path = parentPath + name;
|
||||
|
||||
ondisk[name] = 1;
|
||||
// if (existing[name]) return;
|
||||
|
||||
if (orphans[path]) {
|
||||
toAppend.push(path);
|
||||
if (existing[name])
|
||||
delete orphans[path];
|
||||
orphanAppand.push(path);
|
||||
}
|
||||
createNode(path, stat, existing[name], true);
|
||||
|
||||
if (existing[name])
|
||||
updateNodeStat(path, stat, existing[name]);
|
||||
else
|
||||
toCreate.push(stat);
|
||||
});
|
||||
|
||||
for (var name in existing) {
|
||||
if (!ondisk[name]) {
|
||||
// onreaddir can be called before copied nodes are written to disk
|
||||
// in this case we don't want to lose "predicted" state
|
||||
if (existing[name] && existing[name].status === "predicted")
|
||||
node.map[name] = existing[name];
|
||||
else {
|
||||
delete existing[name];
|
||||
|
||||
emit("remove", {
|
||||
path: e.path + "/" + name,
|
||||
node: existing[name],
|
||||
parent: node
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Object.keys(existing).forEach(function(name) {
|
||||
// onreaddir can be called before copied nodes are written to disk
|
||||
// in this case we don't want to lose "predicted" state
|
||||
if (existing[name] && existing[name].status === "predicted")
|
||||
ondisk[name] = 1;
|
||||
if (!ondisk[name])
|
||||
toRemove.push(name);
|
||||
});
|
||||
|
||||
if (!toCreate.length && !toRemove.length && !orphanAppand.length)
|
||||
return;
|
||||
|
||||
var wasOpen = startUpdate(node);
|
||||
node.children = null;
|
||||
|
||||
// Fill Parent
|
||||
toCreate.forEach(function(stat) {
|
||||
createNode(parentPath + stat.name, stat, null, true);
|
||||
});
|
||||
|
||||
toRemove.forEach(function(name) {
|
||||
var currentNode = existing[name];
|
||||
delete existing[name];
|
||||
emit("remove", {
|
||||
path: parentPath + name,
|
||||
node: currentNode,
|
||||
parent: node
|
||||
});
|
||||
});
|
||||
|
||||
emit("readdir", { path : e.path, parent : node, orphan: orphan });
|
||||
|
||||
endUpdate(node, wasOpen);
|
||||
|
||||
toAppend.forEach(function(path) {
|
||||
orphanAppand.forEach(function(path) {
|
||||
emit("orphan-append", {path: path});
|
||||
});
|
||||
}
|
||||
fs.on("afterReaddir", onreaddir, plugin);
|
||||
|
||||
function onstat(e) {
|
||||
var stat;
|
||||
if (e.error) return;
|
||||
|
||||
if (!e.error) {
|
||||
// update cache
|
||||
var there = true;
|
||||
var node = findNode(e.path);
|
||||
var parent = findNode(dirname(e.path));
|
||||
|
||||
if (!showHidden && isFileHidden(e.path))
|
||||
return;
|
||||
// update cache
|
||||
var stat = e.result[1];
|
||||
|
||||
var there = true;
|
||||
var node = findNode(e.path);
|
||||
var parent = findNode(dirname(e.path));
|
||||
|
||||
if (!showHidden && isFileHidden(e.path))
|
||||
return;
|
||||
|
||||
if (!node) {
|
||||
if (!parent)
|
||||
return;
|
||||
there = false;
|
||||
if (!node) {
|
||||
if (!parent)
|
||||
return;
|
||||
there = false;
|
||||
}
|
||||
|
||||
if (there != !!stat) {
|
||||
if (there) {
|
||||
if (!node.link)
|
||||
deleteNode(node);
|
||||
}
|
||||
|
||||
if (there != !!e.result[1]) {
|
||||
if (there) {
|
||||
if (!node.link)
|
||||
deleteNode(node);
|
||||
}
|
||||
else {
|
||||
stat = e.result[1];
|
||||
if (typeof stat != "object")
|
||||
stat = null;
|
||||
createNode(e.path, stat);
|
||||
}
|
||||
}
|
||||
else if (there) {
|
||||
stat = e.result[1];
|
||||
else {
|
||||
if (typeof stat != "object")
|
||||
stat = null;
|
||||
createNode(e.path, stat, node);
|
||||
createNode(e.path, stat);
|
||||
}
|
||||
}
|
||||
else if (there) {
|
||||
if (typeof stat != "object")
|
||||
stat = null;
|
||||
if (!stat && node)
|
||||
return;
|
||||
if (stat && node)
|
||||
updateNodeStat(e.path, stat, node);
|
||||
else
|
||||
createNode(e.path, stat, node);
|
||||
}
|
||||
}
|
||||
fs.on("afterStat", onstat, plugin);
|
||||
fs.on("afterReadFile", function(e) {
|
||||
|
@ -295,14 +317,15 @@ define(function(require, exports, module) {
|
|||
// Validation
|
||||
var toNode = findNode(newPath);
|
||||
|
||||
deleteNode(node, true);
|
||||
if (toNode)
|
||||
deleteNode(toNode, true);
|
||||
|
||||
createNode(newPath, null, node); // Move node
|
||||
recurPathUpdate(node, oldPath, newPath);
|
||||
if (!toNode) {
|
||||
deleteNode(node, true);
|
||||
createNode(newPath, null, node); // Move node
|
||||
recurPathUpdate(node, oldPath, newPath);
|
||||
}
|
||||
|
||||
e.undo = function(){
|
||||
if (toNode)
|
||||
return;
|
||||
if (!parent) {
|
||||
var tmpParent = node;
|
||||
while (node.parent && tmpParent.parent.status == "pending")
|
||||
|
@ -318,6 +341,12 @@ define(function(require, exports, module) {
|
|||
recurPathUpdate(node, newPath, oldPath);
|
||||
};
|
||||
e.confirm = function() {
|
||||
if (toNode) {
|
||||
deleteNode(toNode, true);
|
||||
createNode(newPath, null, node); // Move node
|
||||
recurPathUpdate(node, oldPath, newPath);
|
||||
}
|
||||
|
||||
if (node.status === "predicted")
|
||||
node.status = "loaded";
|
||||
};
|
||||
|
@ -511,14 +540,8 @@ define(function(require, exports, module) {
|
|||
updateNode = orphans[path];
|
||||
delete orphans[path];
|
||||
}
|
||||
var original_stat;
|
||||
if (stat && stat.link) {
|
||||
original_stat = stat;
|
||||
stat = stat.linkStat;
|
||||
}
|
||||
|
||||
var parts = path.split("/");
|
||||
var name = parts[parts.length - 1];
|
||||
var node = model.root.map[parts[0] == "~" ? "~" : ""];
|
||||
if (!node) {
|
||||
node = orphans[parts[0]];
|
||||
|
@ -537,7 +560,7 @@ define(function(require, exports, module) {
|
|||
|
||||
var map = node.map;
|
||||
if (!map) {
|
||||
map = node.map = {};
|
||||
map = node.map = Object.create(null);
|
||||
}
|
||||
parent = node;
|
||||
node = map[p];
|
||||
|
@ -545,6 +568,11 @@ define(function(require, exports, module) {
|
|||
modified.push(parent);
|
||||
if (i !== parts.length - 1) {
|
||||
node = {label: p, path: subPath, status: "pending", isFolder: true};
|
||||
// TODO filter hidden files in getChildren instead.
|
||||
if (!showHidden && isFileHidden(p)) {
|
||||
orphans[node.path] = path;
|
||||
return;
|
||||
}
|
||||
} else if (updateNode) {
|
||||
deleteNode(updateNode, true);
|
||||
node = updateNode;
|
||||
|
@ -564,8 +592,32 @@ define(function(require, exports, module) {
|
|||
node = {label: parts[parts.length - 1], path: path};
|
||||
orphans[path] = node;
|
||||
}
|
||||
|
||||
updateNodeStat(path, stat, node);
|
||||
|
||||
node.children = null;
|
||||
|
||||
if (!updating) {
|
||||
if (!modified.length)
|
||||
modified.push(parent);
|
||||
var wasOpen = startUpdate(modified[0]);
|
||||
modified.forEach(function(n) {
|
||||
if (n != model.root)
|
||||
n.children = null;
|
||||
});
|
||||
endUpdate(modified[0], wasOpen);
|
||||
}
|
||||
model._signal("createNode", node);
|
||||
return node;
|
||||
}
|
||||
|
||||
function updateNodeStat(path, stat, node) {
|
||||
node.path = path;
|
||||
|
||||
var original_stat;
|
||||
if (stat && stat.link) {
|
||||
original_stat = stat;
|
||||
stat = stat.linkStat;
|
||||
}
|
||||
if (stat) {
|
||||
var isFolder = stat && /(directory|folder)$/.test(stat.mime);
|
||||
if (isFolder) {
|
||||
|
@ -589,25 +641,13 @@ define(function(require, exports, module) {
|
|||
delete node.isFolder;
|
||||
}
|
||||
|
||||
if (node.isFolder && !node.map)
|
||||
node.map = {};
|
||||
else if (!node.isFolder && node.map)
|
||||
if (node.isFolder && !node.map) {
|
||||
node.map = Object.create(null);
|
||||
node.children = null;
|
||||
} else if (!node.isFolder && node.map) {
|
||||
delete node.map;
|
||||
|
||||
node.children = null;
|
||||
|
||||
if (!updating) {
|
||||
if (!modified.length)
|
||||
modified.push(parent);
|
||||
var wasOpen = startUpdate(modified[0]);
|
||||
modified.forEach(function(n) {
|
||||
if (n != model.root)
|
||||
n.children = null;
|
||||
});
|
||||
endUpdate(modified[0], wasOpen);
|
||||
node.children = null;
|
||||
}
|
||||
model._signal("createNode", node);
|
||||
return node;
|
||||
}
|
||||
|
||||
function deleteNode(node, silent) {
|
||||
|
@ -670,7 +710,7 @@ define(function(require, exports, module) {
|
|||
map: {}
|
||||
};
|
||||
var root = {};
|
||||
root.map = {};
|
||||
root.map = Object.create(null);
|
||||
root.map[""] = model.projectDir;
|
||||
model.setRoot(root);
|
||||
// fs.readdir("/", function(){});
|
||||
|
@ -894,7 +934,12 @@ define(function(require, exports, module) {
|
|||
* @param {Function} progress
|
||||
* @param {Function} done
|
||||
*/
|
||||
loadNodes: loadNodes
|
||||
loadNodes: loadNodes,
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
isFileHidden: isFileHidden
|
||||
});
|
||||
|
||||
register(null, {
|
||||
|
|
|
@ -54,7 +54,7 @@ define(function(require, module, exports) {
|
|||
|
||||
var gotYesNo = false;
|
||||
plugin.once("hide", function(){
|
||||
!gotYesNo && cancel && onNo(false, true, metadata);
|
||||
!gotYesNo && cancel && onNo && onNo(false, true, metadata);
|
||||
});
|
||||
|
||||
plugin.update([
|
||||
|
@ -63,22 +63,22 @@ define(function(require, module, exports) {
|
|||
{ id: "yestoall", visible: all, onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onYes(true, metadata);
|
||||
onYes && onYes(true, metadata);
|
||||
}},
|
||||
{ id: "notoall", visible: all, onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onNo(true, false, metadata);
|
||||
onNo && onNo(true, false, metadata);
|
||||
}},
|
||||
{ id: "yes", onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onYes(false, metadata);
|
||||
onYes && onYes(false, metadata);
|
||||
}},
|
||||
{ id: "no", onclick: function(){
|
||||
gotYesNo = true;
|
||||
plugin.hide();
|
||||
onNo(false, false, metadata);
|
||||
onNo && onNo(false, false, metadata);
|
||||
}}
|
||||
]);
|
||||
}, options.queue === false);
|
||||
|
|
|
@ -3,7 +3,7 @@ define(function(require, exports, module) {
|
|||
"Panel", "c9", "util", "fs", "settings", "ui", "menus",
|
||||
"panels", "commands", "tabManager", "fs.cache", "watcher",
|
||||
"preferences", "clipboard", "dialog.alert", "dialog.fileremove",
|
||||
"dialog.fileoverwrite", "dialog.error", "layout"
|
||||
"dialog.fileoverwrite", "dialog.error", "layout", "dialog.question"
|
||||
];
|
||||
main.provides = ["tree"];
|
||||
return main;
|
||||
|
@ -24,6 +24,7 @@ define(function(require, exports, module) {
|
|||
var watcher = imports.watcher;
|
||||
var prefs = imports.preferences;
|
||||
var alert = imports["dialog.alert"].show;
|
||||
var question = imports["dialog.question"].show;
|
||||
var fsCache = imports["fs.cache"];
|
||||
var confirmRemove = imports["dialog.fileremove"].show;
|
||||
var confirmRename = imports["dialog.fileoverwrite"].show;
|
||||
|
@ -34,7 +35,7 @@ define(function(require, exports, module) {
|
|||
var TreeEditor = require("ace_tree/edit");
|
||||
var markup = require("text!./tree.xml");
|
||||
|
||||
var basename = require("path").basename;
|
||||
var join = require("path").join;
|
||||
var dirname = require("path").dirname;
|
||||
|
||||
var staticPrefix = options.staticPrefix;
|
||||
|
@ -52,7 +53,7 @@ define(function(require, exports, module) {
|
|||
});
|
||||
var emit = plugin.getEmitter();
|
||||
|
||||
var container, winFilesViewer; //UI elements
|
||||
var container, winFilesViewer; // UI elements
|
||||
var showHideScrollPos, scrollTimer;
|
||||
var tree;
|
||||
|
||||
|
@ -404,15 +405,10 @@ define(function(require, exports, module) {
|
|||
|
||||
emit("expand", { path: id });
|
||||
|
||||
if (node.justLoaded) {
|
||||
delete node.justLoaded;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only save if we are not loading the tree
|
||||
if (!refreshing || loadedSettings != -1) {
|
||||
if (!node.isRoot) {
|
||||
var refresh = !refreshing && node.status == "loaded";
|
||||
var refresh = !refreshing && node.status == "loaded" && Date.now() - node.$lastReadT > 500;
|
||||
watcher.watch(id, refresh);
|
||||
|
||||
// watch children
|
||||
|
@ -424,8 +420,10 @@ define(function(require, exports, module) {
|
|||
});
|
||||
}
|
||||
|
||||
changed = true;
|
||||
settings.save();
|
||||
if (!updateSingleDirectoryChain(true, node)) {
|
||||
changed = true;
|
||||
settings.save();
|
||||
}
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
|
@ -451,13 +449,28 @@ define(function(require, exports, module) {
|
|||
});
|
||||
}
|
||||
|
||||
changed = true;
|
||||
settings.save();
|
||||
if (!updateSingleDirectoryChain(false, node)) {
|
||||
changed = true;
|
||||
settings.save();
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
function abortNoStorage() {
|
||||
if (!c9.has(c9.STORAGE))
|
||||
return false;
|
||||
|
||||
function updateSingleDirectoryChain(isExpand, node) {
|
||||
if (!node.children || node.children.length !== 1)
|
||||
return;
|
||||
var child = node.children[0];
|
||||
if (!child || !child.isFolder || child.$depth > 0xff)
|
||||
return;
|
||||
|
||||
if (isExpand && !child.isOpen) {
|
||||
expandNode(child);
|
||||
return true;
|
||||
}
|
||||
else if (!isExpand && child.isOpen) {
|
||||
updateSingleDirectoryChain(false, child);
|
||||
delete expandedList[child.path];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Rename
|
||||
|
@ -479,34 +492,58 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
var node = e.node;
|
||||
var name = e.value;
|
||||
var name = e.value.trim();
|
||||
|
||||
// check for a path with the same name, which is not allowed to rename to:
|
||||
var path = node.path;
|
||||
var newpath = path.replace(/[^\/]+$/, name);
|
||||
var newpath = join(path, "..", name);
|
||||
|
||||
// No point in renaming when the name is the same
|
||||
if (basename(path) == name)
|
||||
if (path == newpath)
|
||||
return;
|
||||
|
||||
// Returning false from this function will cancel the rename. We do this
|
||||
// when the name to which the file is to be renamed contains invalid
|
||||
// characters
|
||||
if (/[\\\/\n\r]/.test(name)) {
|
||||
// todo is this still needed?
|
||||
|
||||
var m = /([\0\\\n\r])/.exec(name) || c9.platform == "win32" && /([\\:*?"<>|])/.exec(name);
|
||||
if (m) {
|
||||
showError(
|
||||
"Could not rename to '" + ui.htmlentities(name)
|
||||
+ "'. Names can only contain alfanumeric characters, space, . (dot)"
|
||||
+ ", - and _ (underscore). Use the terminal to rename to other names."
|
||||
"Invalid character '" + m[0] + "' in '" + name + "'"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
fs.rename(path, newpath, {}, function(err, success) { });
|
||||
// renaming to hidden file can be confusing if one doesn't know about hidden files
|
||||
if (fsCache.isFileHidden(newpath) && !settings.getBool("user/projecttree/@showhidden")) {
|
||||
settings.set("user/projecttree/@showhidden", true);
|
||||
changed = true;
|
||||
fsCache.showHidden = true;
|
||||
refresh(true, function(){});
|
||||
}
|
||||
|
||||
emit("rename", { path: newpath, oldpath: path });
|
||||
if (dirname(newpath) != dirname(path)) {
|
||||
tree.edit.ace.blur(); // TODO this shouldn't be needed when apf focus works
|
||||
question(
|
||||
"Confirm move to a new folder",
|
||||
"move '" + e.oldValue + "' to \n" +
|
||||
"'" + dirname(newpath) + "'?",
|
||||
"",
|
||||
doRename
|
||||
);
|
||||
} else {
|
||||
doRename();
|
||||
}
|
||||
|
||||
return false;
|
||||
function doRename() {
|
||||
fs.rename(path, newpath, {}, function(err, success) {
|
||||
if (err) {
|
||||
var message = err.message;
|
||||
if (err.code == "EEXIST")
|
||||
message = "File " + path + " already exists.";
|
||||
return showError(message);
|
||||
}
|
||||
if (dirname(newpath) != dirname(path))
|
||||
expandAndSelect(newpath);
|
||||
});
|
||||
emit("rename", { path: newpath, oldpath: path });
|
||||
}
|
||||
}, plugin);
|
||||
|
||||
// Context Menu
|
||||
|
@ -977,7 +1014,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
else {
|
||||
var node = fsCache.findNode(path);
|
||||
if (node) //Otherwise orphan-append will pick it up
|
||||
if (node) // Otherwise orphan-append will pick it up
|
||||
expandNode(node);
|
||||
}
|
||||
|
||||
|
@ -1045,14 +1082,14 @@ define(function(require, exports, module) {
|
|||
if (typeof node == "string")
|
||||
node = fsCache.findNode(node, "refresh");
|
||||
|
||||
if (node && !node.isFolder)
|
||||
node = node.parent;
|
||||
if (node && node.status === "loaded") {
|
||||
tree.provider.setAttribute(node, "status", "pending");
|
||||
node.children = null;
|
||||
}
|
||||
});
|
||||
|
||||
//c9.dispatchEvent("track_action", { type: "reloadtree" });
|
||||
|
||||
loadProjectTree(false, function(err) {
|
||||
var expandedNodes = Object.keys(expandedList);
|
||||
expandedList = {};
|
||||
|
@ -1067,7 +1104,7 @@ define(function(require, exports, module) {
|
|||
callback(err);
|
||||
tree.provider.on("changeScrollTop", scrollHandler);
|
||||
|
||||
emit("refreshComplete")
|
||||
emit("refreshComplete");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1100,6 +1137,7 @@ define(function(require, exports, module) {
|
|||
function expandAndSelect(path_or_node) {
|
||||
var node = findNode(path_or_node);
|
||||
expand(node, function(){
|
||||
refreshing = false;
|
||||
tree.select(node);
|
||||
scrollToSelection();
|
||||
});
|
||||
|
@ -1212,10 +1250,12 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
function select(path_or_node) {
|
||||
refreshing = false;
|
||||
tree.select(findNode(path_or_node));
|
||||
}
|
||||
|
||||
function selectList(list) {
|
||||
refreshing = false;
|
||||
tree.selection.setSelection(list.map(function(n) {
|
||||
return findNode(n);
|
||||
}));
|
||||
|
@ -1293,6 +1333,9 @@ define(function(require, exports, module) {
|
|||
|
||||
callback(err, data);
|
||||
});
|
||||
var node = fsCache.findNode(newpath, "expand");
|
||||
if (node)
|
||||
expandAndSelect(node);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -947,8 +947,10 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
function show(x, y, type) {
|
||||
if (type == "context")
|
||||
y++;
|
||||
if (type == "context") {
|
||||
x += 2;
|
||||
y += 2;
|
||||
}
|
||||
lastCoords = { x : x, y : y };
|
||||
aml.display(x, y);
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue