Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit 00fca07

Browse files
committed
Merge remote-tracking branch 'origin/master' into randy/issue-7286
2 parents acf0c47 + 8696643 commit 00fca07

29 files changed

Lines changed: 338 additions & 54 deletions

src/document/DocumentCommandHandlers.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,9 +1560,6 @@ define(function (require, exports, module) {
15601560
// Register global commands
15611561
CommandManager.register(Strings.CMD_FILE_OPEN, Commands.FILE_OPEN, handleFileOpen);
15621562
CommandManager.register(Strings.CMD_ADD_TO_WORKING_SET, Commands.FILE_ADD_TO_WORKING_SET, handleFileAddToWorkingSet);
1563-
// TODO: (issue #274) For now, hook up File > New to the "new in project" handler. Eventually
1564-
// File > New should open a new blank tab, and handleFileNewInProject should
1565-
// be called from a "+" button in the project
15661563
CommandManager.register(Strings.CMD_FILE_NEW_UNTITLED, Commands.FILE_NEW_UNTITLED, handleFileNew);
15671564
CommandManager.register(Strings.CMD_FILE_NEW, Commands.FILE_NEW, handleFileNewInProject);
15681565
CommandManager.register(Strings.CMD_FILE_NEW_FOLDER, Commands.FILE_NEW_FOLDER, handleNewFolderInProject);

src/editor/Editor.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,11 +1556,12 @@ define(function (require, exports, module) {
15561556
*/
15571557
Editor.prototype.displayErrorMessageAtCursor = function (errorMsg) {
15581558
var arrowBelow, cursorPos, cursorCoord, popoverRect,
1559-
top, left, clip, arrowLeft,
1559+
top, left, clip, arrowCenter, arrowLeft,
15601560
self = this,
15611561
$editorHolder = $("#editor-holder"),
15621562
POPOVER_MARGIN = 10,
1563-
POPOVER_ARROW_HALF_WIDTH = 10;
1563+
POPOVER_ARROW_HALF_WIDTH = 10,
1564+
POPOVER_ARROW_HALF_BASE = POPOVER_ARROW_HALF_WIDTH + 3; // 3 is border radius
15641565

15651566
function _removeListeners() {
15661567
$(self).off(".msgbox");
@@ -1639,8 +1640,14 @@ define(function (require, exports, module) {
16391640
// Popover text and arrow are positioned individually
16401641
this._$messagePopover.css({"top": top, "left": left});
16411642

1642-
// Position popover arrow exactly centered over/under cursor
1643-
arrowLeft = cursorCoord.left - left - POPOVER_ARROW_HALF_WIDTH;
1643+
// Position popover arrow centered over/under cursor...
1644+
arrowCenter = cursorCoord.left - left;
1645+
1646+
// ... but don't let it slide off text box
1647+
arrowCenter = Math.min(popoverRect.width - POPOVER_ARROW_HALF_BASE,
1648+
Math.max(arrowCenter, POPOVER_ARROW_HALF_BASE));
1649+
1650+
arrowLeft = arrowCenter - POPOVER_ARROW_HALF_WIDTH;
16441651
if (arrowBelow) {
16451652
this._$messagePopover.find(".arrowBelow").css({"margin-left": arrowLeft});
16461653
} else {

src/editor/InlineWidget.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ define(function (require, exports, module) {
9797
/**
9898
* Called once content is parented in the host editor's DOM. Useful for performing tasks like setting
9999
* focus or measuring content, which require htmlContent to be in the DOM tree.
100+
*
100101
* IMPORTANT: onAdded() MUST be overridden to call hostEditor.setInlineWidgetHeight() at least once to
101102
* set the initial height (required to animate it open). The widget will never open otherwise.
102103
*/

src/file/FileUtils.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ define(function (require, exports, module) {
3434
require("utils/Global");
3535

3636
var FileSystemError = require("filesystem/FileSystemError"),
37+
LanguageManager = require("language/LanguageManager"),
3738
PerfUtils = require("utils/PerfUtils"),
3839
Dialogs = require("widgets/Dialogs"),
3940
DefaultDialogs = require("widgets/DefaultDialogs"),
@@ -309,6 +310,40 @@ define(function (require, exports, module) {
309310
return baseName.substr(idx + 1);
310311
}
311312

313+
/**
314+
* Get the file extension (excluding ".") given a path OR a bare filename.
315+
* Returns "" for names with no extension.
316+
* If the only `.` in the file is the first character,
317+
* returns "" as this is not considered an extension.
318+
* This method considers known extensions which include `.` in them.
319+
*
320+
* @param {string} fullPath full path to a file or directory
321+
* @return {string} Returns the extension of a filename or empty string if
322+
* the argument is a directory or a filename with no extension
323+
*/
324+
function getSmartFileExtension(fullPath) {
325+
var baseName = getBaseName(fullPath),
326+
parts = baseName.split(".");
327+
328+
// get rid of file name
329+
parts.shift();
330+
if (baseName[0] === ".") {
331+
// if starts with a `.`, then still consider it as file name
332+
parts.shift();
333+
}
334+
335+
var extension = [parts.pop()], // last part is always an extension
336+
i = parts.length;
337+
while (i--) {
338+
if (LanguageManager.getLanguageForExtension(parts[i])) {
339+
extension.unshift(parts[i]);
340+
} else {
341+
break;
342+
}
343+
}
344+
return extension.join(".");
345+
}
346+
312347
/**
313348
* Computes filename as relative to the basePath. For example:
314349
* basePath: /foo/bar/, filename: /foo/bar/baz.txt
@@ -426,5 +461,6 @@ define(function (require, exports, module) {
426461
exports.getBaseName = getBaseName;
427462
exports.getRelativeFilename = getRelativeFilename;
428463
exports.getFileExtension = getFileExtension;
464+
exports.getSmartFileExtension = getSmartFileExtension;
429465
exports.compareFilenames = compareFilenames;
430466
});

src/filesystem/Directory.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ define(function (require, exports, module) {
127127
}
128128

129129
/**
130-
* Read the contents of a Directory.
130+
* Read the contents of a Directory. If this Directory is under a watch root,
131+
* the listing will exclude any items filtered out by the watch root's filter
132+
* function.
131133
*
132134
* @param {Directory} directory Directory whose contents you want to get
133135
* @param {function (?string, Array.<FileSystemEntry>=, Array.<FileSystemStats>=, Object.<string, string>=)} callback

src/filesystem/File.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ define(function (require, exports, module) {
149149

150150
// Request a consistency check if the write is not blind
151151
if (!options.blind) {
152-
options.expectedHash = this._hash;
152+
options.expectedHash = this._hash;
153153
options.expectedContents = this._contents;
154154
}
155155

src/filesystem/FileSystem.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
* to meet these requirements)
5353
*
5454
* FileSystem dispatches the following events:
55+
* (NOTE: attach to these events via `FileSystem.on()` - not `$(FileSystem).on()`)
56+
*
5557
* change - Sent whenever there is a change in the file system. The handler
5658
* is passed up to three arguments: the changed entry and, if that changed entry
5759
* is a Directory, a list of entries added to the directory and a list of entries
@@ -262,6 +264,8 @@ define(function (require, exports, module) {
262264
commandName = shouldWatch ? "watchPath" : "unwatchPath";
263265

264266
if (recursiveWatch) {
267+
// The impl can watch the entire subtree with one call on the root (we also fall into this case for
268+
// unwatch, although that never requires us to do the recursion - see similar final case below)
265269
if (entry !== watchedRoot.entry) {
266270
// Watch and unwatch calls to children of the watched root are
267271
// no-ops if the impl supports recursiveWatch
@@ -315,6 +319,8 @@ define(function (require, exports, module) {
315319
});
316320
}, callback);
317321
} else {
322+
// Unwatching never requires enumerating the subfolders (which is good, since after a
323+
// delete/rename we may be unable to do so anyway)
318324
this._enqueueWatchRequest(function (requestCb) {
319325
impl.unwatchPath(entry.fullPath, requestCb);
320326
}, callback);

src/filesystem/impls/appshell/AppshellFileSystem.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,27 @@ define(function (require, exports, module) {
3535

3636
var FILE_WATCHER_BATCH_TIMEOUT = 200; // 200ms - granularity of file watcher changes
3737

38-
var _changeCallback, // Callback to notify FileSystem of watcher changes
39-
_offlineCallback, // Callback to notify FileSystem that watchers are offline
40-
_changeTimeout, // Timeout used to batch up file watcher changes
41-
_pendingChanges = {}; // Pending file watcher changes
38+
/**
39+
* Callback to notify FileSystem of watcher changes
40+
* @type {?function(string, FileSystemStats=)}
41+
*/
42+
var _changeCallback;
43+
44+
/**
45+
* Callback to notify FileSystem if watchers stop working entirely
46+
* @type {?function()}
47+
*/
48+
var _offlineCallback;
49+
50+
/** Timeout used to batch up file watcher changes (setTimeout() return value) */
51+
var _changeTimeout;
52+
53+
/**
54+
* Pending file watcher changes - map from fullPath to flag indicating whether we need to pass stats
55+
* to _changeCallback() for this path.
56+
* @type {!Object.<string, boolean>}
57+
*/
58+
var _pendingChanges = {};
4259

4360
var _bracketsPath = FileUtils.getNativeBracketsDirectoryPath(),
4461
_modulePath = FileUtils.getNativeModuleDirectoryPath(module),
@@ -48,6 +65,7 @@ define(function (require, exports, module) {
4865

4966
var _isRunningOnWindowsXP = navigator.userAgent.indexOf("Windows NT 5.") >= 0;
5067

68+
5169
// If the connection closes, notify the FileSystem that watchers have gone offline.
5270
$(_nodeDomain.connection).on("close", function (event, promise) {
5371
if (_offlineCallback) {
@@ -105,7 +123,7 @@ define(function (require, exports, module) {
105123
if (event === "change") {
106124
// Only register change events if filename is passed
107125
if (filename) {
108-
// an existing file was created; stats are needed
126+
// an existing file was modified; stats are needed
109127
change = path + filename;
110128
_enqueueChange(change, true);
111129
}

src/htmlContent/extension-manager-dialog.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<li><a href="#registry" class="registry" data-toggle="tab"><img src="styles/images/extension-manager-registry.svg"/><br/>{{Strings.EXTENSIONS_AVAILABLE_TITLE}}</a></li>
66
<!--<li><a href="#updates" class="updates" data-toggle="tab"><img src="styles/images/extension-manager-updates.svg"/><br/>{{Strings.EXTENSIONS_UPDATES_TITLE}}</a></li>-->
77
{{/showRegistry}}
8-
<li><a href="#installed" class="installed" data-toggle="tab"><img src="styles/images/extension-manager-installed.svg"/><br/>{{Strings.EXTENSIONS_INSTALLED_TITLE}}</a><span class="notification"></span></li>
8+
<li><a href="#installed" class="installed" data-toggle="tab"><span class="notification"></span><img src="styles/images/extension-manager-installed.svg"/><br/>{{Strings.EXTENSIONS_INSTALLED_TITLE}}</a></li>
99
</ul>
1010
<div>
1111
<button class="search-clear">&times;</button>

src/language/HTMLUtils.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,8 @@ define(function (require, exports, module) {
485485
currentBlock = null,
486486
inBlock = false,
487487
outerMode = editor._codeMirror.getMode(),
488-
tokenModeName;
488+
tokenModeName,
489+
previousMode;
489490

490491
while (TokenUtils.moveNextToken(ctx, false)) {
491492
tokenModeName = CodeMirror.innerMode(outerMode, ctx.token.state).mode.name;
@@ -495,7 +496,7 @@ define(function (require, exports, module) {
495496
currentBlock.end = currentBlock.start;
496497
}
497498
// Check for end of this block
498-
if (tokenModeName !== modeName) {
499+
if (tokenModeName === previousMode) {
499500
// currentBlock.end is already set to pos of the last token by now
500501
currentBlock.text = editor.document.getRange(currentBlock.start, currentBlock.end);
501502
inBlock = false;
@@ -510,6 +511,8 @@ define(function (require, exports, module) {
510511
};
511512
blocks.push(currentBlock);
512513
inBlock = true;
514+
} else {
515+
previousMode = tokenModeName;
513516
}
514517
// else, random token: ignore
515518
}

0 commit comments

Comments
 (0)