Permalink
Browse files

New implementation of Brackets plugin

  • Loading branch information...
1 parent 40f4c89 commit a0d348a48986d9105fc9c83ea0822329cd583775 @sergeche sergeche committed Apr 29, 2014
Showing with 371 additions and 1,308 deletions.
  1. +9 −5 brackets-fs.js
  2. +194 −158 editor.js
  3. +0 −121 file.js
  4. +3 −3 keymap.json
  5. +158 −159 main.js
  6. +1 −1 package.json
  7. +6 −0 requirejs-config.json
  8. +0 −861 snippets.json
View
@@ -1,10 +1,14 @@
-define(['./path', 'filesystem/FileSystem', 'emmet/plugin/file'], function(path, fs, emmetFile) {
+define(function(require, exports, module) {
+ var path = require('./path');
+ var emmetFile = require('emmet/plugin/file');
+ var FileSystem = brackets.getModule('filesystem/FileSystem');
+
emmetFile({
_exists: function(file) {
},
read: function(file, size, callback) {
- var fd = fs.getFileForPath(file);
+ var fd = FileSystem.getFileForPath(file);
if (!fd) {
return callback('File "' + path + '" does not exists.');
}
@@ -22,7 +26,7 @@ define(['./path', 'filesystem/FileSystem', 'emmet/plugin/file'], function(path,
while (dirname && dirname !== path.dirname(dirname)) {
dirname = path.dirname(dirname);
f = path.join(dirname, fileName);
- if (fs.getFileForPath(f)) {
+ if (FileSystem.getFileForPath(f)) {
return f;
}
}
@@ -31,7 +35,7 @@ define(['./path', 'filesystem/FileSystem', 'emmet/plugin/file'], function(path,
},
createPath: function(parent, fileName, callback) {
- fs.getFileForPath(parent).exists(function(err, exists) {
+ FileSystem.getFileForPath(parent).exists(function(err, exists) {
if (exists) {
parent = path.dirname(parent);
}
@@ -41,7 +45,7 @@ define(['./path', 'filesystem/FileSystem', 'emmet/plugin/file'], function(path,
},
save: function(file, content) {
- fs.getFileForPath(file).write(content, {encoding: 'ascii'});
+ FileSystem.getFileForPath(file).write(content, {encoding: 'ascii'});
}
});
View
@@ -1,160 +1,196 @@
-define(['./emmet'], function(emmet) {
- var require = emmet.require;
- var _ = require('_');
+/**
+ * Emmet Editor interface implementation for Brackets.
+ * Interface is optimized for multiple cursor usage: authors
+ * should run acttion multiple times and update `selectionIndex`
+ * property on each iteration.
+ */
+define(function(require, exports, module) {
+ var emmet = require('emmet/emmet');
+ var utils = require('emmet/utils/common');
+ var editorUtils = require('emmet/utils/editor');
+ var actionUtils = require('emmet/utils/action');
+ var tabStops = require('emmet/assets/tabStops');
- var modeMap = {
- "text/html": "html",
- "htmlmixed": "html",
- "text/x-brackets-html": "html",
- "application/xml": "xml",
- "text/xsl": "xsl",
- "text/css": "css",
- "text/x-less": "less",
- "text/x-scss": "scss",
- "text/x-sass": "sass",
- "php": "html"
- };
-
- return {
- context: null,
- filePath: null,
- setupContext: function (context, filePath) {
- this.context = context;
- this.filePath = filePath;
- var indentation = "\t";
- if (!context.getOption("indentWithTabs")) {
- indentation = require("utils").repeatString(" ", context.getOption("indentUnit"));
- }
-
- require("resources").setVariable("indentation", indentation);
- },
-
- getSelectionRange: function () {
- var caretPos = this.getCaretPos();
- return {
- start: caretPos,
- end: caretPos + this.getSelection().length
- };
- },
-
- createSelection: function (start, end) {
- if (start == end) {
- this.context.setCursor(this.context.posFromIndex(start));
- } else {
- this.context.setSelection(this.context.posFromIndex(start), this.context.posFromIndex(end));
- }
- },
-
- getCurrentLineRange: function () {
- var caret = this.context.getCursor(true);
- return {
- start: this.context.indexFromPos({line: caret.line, ch: 0}),
- end: this.context.indexFromPos({line: caret.line, ch: this.context.getLine(caret.line).length})
- };
- },
-
- getCaretPos: function () {
- return this.context.indexFromPos(this.context.getCursor(true));
- },
-
- setCaretPos: function (pos) {
- this.createSelection(pos, pos);
- },
-
- getCurrentLine: function () {
- return this.context.getLine(this.context.getCursor(true).line) || "";
- },
-
- replaceContent: function (value, start, end, noIndent) {
- if (_.isUndefined(end))
- end = _.isUndefined(start) ? value.length : start;
- if (_.isUndefined(start)) start = 0;
- var utils = require("utils");
-
- // indent new value
- if (!noIndent) {
- value = utils.padString(value, utils.getLinePaddingFromPosition(this.getContent(), start));
- }
-
- // find new caret position
- var tabstopData = require("tabStops").extract(value, {
- escape: function (ch) {
- return ch;
- }
- });
- value = tabstopData.text;
- var firstTabStop = tabstopData.tabstops[0];
-
- if (firstTabStop) {
- firstTabStop.start += start;
- firstTabStop.end += start;
- } else {
- firstTabStop = {
- start: value.length + start,
- end: value.length + start
- };
- }
-
- // do a compound change to record all changes into single undo event
- var that = this;
- var op = this.context.operation || this.context.compoundChange;
- op.call(this.context, function() {
- that.context.replaceRange(value, that.context.posFromIndex(start), that.context.posFromIndex(end));
- that.createSelection(firstTabStop.start, firstTabStop.end);
- });
- },
-
- getContent: function () {
- return this.context.getValue();
- },
-
- getCMSyntax: function() {
- var syntax = this.context.getOption("mode");
- return syntax in modeMap ? modeMap[syntax] : syntax;
- },
-
- getSyntax: function () {
- var syntax = this.getCMSyntax();
- return require('actionUtils').detectSyntax(this, syntax);
- },
-
- /**
- * Returns current output profile name (@see emmet#setupProfile)
- * @return {String}
- */
- getProfileName: function () {
- if (this.context.getOption("profile"))
- return this.context.getOption("profile");
-
- return require('actionUtils').detectProfile(this);
- },
-
- /**
- * Ask user to enter something
- * @param {String} title Dialog title
- * @return {String} Entered data
- * @since 0.65
- */
- prompt: function (title) {
- return prompt(title);
- },
-
- /**
- * Returns current selection
- * @return {String}
- * @since 0.65
- */
- getSelection: function () {
- return this.context.getSelection() || "";
- },
-
- /**
- * Returns current editor"s file path
- * @return {String}
- * @since 0.65
- */
- getFilePath: function () {
- return this.filePath;
- }
- };
+ var Editor = brackets.getModule('editor/Editor').Editor;
+
+ /**
+ * Normalizes text before it goes to editor: replaces indentation
+ * and newlines with ones used in editor
+ * @param {String} text Text to normalize
+ * @param {Editor} editor Brackets editor instance
+ * @return {String}
+ */
+ function normalize(text, editor) {
+ var indentation = '\t';
+ if (!Editor.getUseTabChar()) {
+ indentation = '';
+ var units = Editor.getSpaceUnits();
+ while (units--) {
+ indentation += ' ';
+ }
+ }
+
+ return editorUtils.normalize(text, {
+ indentation: indentation,
+ newline: '\n'
+ });
+ }
+
+ return {
+ editor: null,
+ selectionIndex: 0,
+ modeMap: {
+ 'text/html': 'html',
+ 'application/xml': 'xml',
+ 'text/xsl': 'xsl',
+ 'text/css': 'css',
+ 'text/x-less': 'less',
+ 'text/x-scss': 'scss',
+ 'text/x-sass': 'sass'
+ },
+
+ setup: function(editor, selIndex) {
+ this.editor = editor;
+ this.selectionIndex = selIndex || 0;
+ },
+
+ _convertRange: function(sel) {
+ return {
+ start: this.editor.indexFromPos(sel.start),
+ end: this.editor.indexFromPos(sel.end)
+ };
+ },
+
+ _currentLineRange: function() {
+ var sel = this.editor.getSelections()[this.selectionIndex];
+ return this.editor.convertToLineSelections([sel])[0].selectionForEdit;
+ },
+
+ _posFromIndex: function(index) {
+ // XXX: shouldn’t use private editor._codeMirror here,
+ // Brackets must provide `posFromIndex()` method alias
+ return this.editor._codeMirror.posFromIndex(index);
+ },
+
+ /**
+ * Returns list of selections for current CodeMirror instance.
+ * @return {Array}
+ */
+ selectionList: function() {
+ return this.editor.getSelections().map(this._convertRange, this);
+ },
+
+ getCaretPos: function() {
+ return this.getSelectionRange().start;
+ },
+
+ setCaretPos: function(pos) {
+ this.createSelection(pos);
+ },
+
+ /**
+ * Returns current selection range (for current selection index)
+ * @return {Object}
+ */
+ getSelectionRange: function() {
+ return this.selectionList()[this.selectionIndex];
+ },
+
+ createSelection: function(start, end) {
+ end = end || start;
+
+ var sels = this.editor.getSelections();
+ sels[this.selectionIndex] = {
+ start: this._posFromIndex(start),
+ end: this._posFromIndex(end)
+ };
+ this.editor.setSelections(sels);
+ },
+
+ /**
+ * Returns current selection
+ * @return {String}
+ */
+ getSelection: function() {
+ var sel = this.editor.getSelections()[this.selectionIndex];
+ return this.editor.document.getRange(sel.start, sel.end);
+ },
+
+ getCurrentLineRange: function() {
+ return this._convertRange(this._currentLineRange());
+ },
+
+ getCurrentLine: function() {
+ var lineRange = this._currentLineRange();
+ return this.editor.document.getRange(lineRange.start, lineRange.end);
+ },
+
+ getContent: function() {
+ return this.editor.document.getText();
+ },
+
+ replaceContent: function(value, start, end, noIndent) {
+ if (typeof end == 'undefined') {
+ end = (typeof start == 'undefined') ? this.getContent().length : start;
+ }
+ if (typeof start == 'undefined') {
+ start = 0;
+ }
+
+ // indent new value
+ if (!noIndent) {
+ value = utils.padString(value, utils.getLinePaddingFromPosition(this.getContent(), start));
+ }
+
+ // find new caret position
+ var tabstopData = tabStops.extract(value, {
+ escape: function(ch) {
+ return ch;
+ }
+ });
+ value = tabstopData.text;
+
+ var firstTabStop = tabstopData.tabstops[0] || {start: value.length, end: value.length};
+ firstTabStop.start += start;
+ firstTabStop.end += start;
+
+ this.editor.document.replaceRange(value, this._posFromIndex(start), this._posFromIndex(end));
+ this.createSelection(firstTabStop.start, firstTabStop.end);
+ },
+
+ getSyntax: function() {
+ var sel = this.editor.getSelections()[this.selectionIndex];
+ var mode = this.editor.getModeForRange(sel.start, sel.end).name;
+ return this.modeMap[mode] || mode;
+ },
+
+ /**
+ * Returns current output profile name (@see emmet#setupProfile)
+ * @return {String}
+ */
+ getProfileName: function() {
+ return actionUtils.detectProfile(this);
+ },
+
+ /**
+ * Ask user to enter something
+ * @param {String} title Dialog title
+ * @return {String} Entered data
+ */
+ prompt: function(title) {
+ return prompt(title);
+ },
+
+ /**
+ * Returns current editor's file path
+ * @return {String}
+ */
+ getFilePath: function() {
+ if (this.editor.document.isUntitled()) {
+ return null;
+ }
+
+ return this.editor.document.file.fullPath;
+ }
+ };
});
Oops, something went wrong.

0 comments on commit a0d348a

Please sign in to comment.