Files
ChocolateyPackages/EthanBrown.SublimeText2.WebPackages/tools/PackageCache/Emmet/editor.js
2013-04-04 08:54:25 -04:00

323 lines
7.7 KiB
JavaScript

function activeView() {
return sublime.active_window().active_view();
}
var editorProxy = emmet.exec(function(require, _) {
return {
getSelectionRange: function() {
var view = activeView();
var sel = view.sel()[0];
return {
start: sel.begin(),
end: sel.end()
};
},
createSelection: function(start, end) {
var view = activeView();
view.sel().clear();
view.sel().add(new sublime.Region(start, end || start));
view.show(view.sel());
},
getCurrentLineRange: function() {
var view = activeView();
var selection = view.sel()[0];
var line = view.line(selection);
return {
start: line.begin(),
end: line.end()
};
},
getCaretPos: function() {
var view = activeView();
var sel = view.sel();
return sel && sel[0] ? sel[0].begin() : 0;
},
setCaretPos: function(pos){
this.createSelection(pos, pos);
},
getCurrentLine: function() {
var view = activeView();
return view.substr(view.line(view.sel()[0]));
},
replaceContent: function(value, start, end, noIndent) {
if (_.isUndefined(end))
end = _.isUndefined(start) ? this.getContent().length : start;
if (_.isUndefined(start)) start = 0;
// update tabstops: make sure all caret placeholder are unique
// by default, abbreviation parser generates all unlinked (un-mirrored)
// tabstops as ${0}, so we have upgrade all caret tabstops with unique
// positions but make sure that all other tabstops are not linked accidentally
value = pyPreprocessText(value);
sublimeReplaceSubstring(start, end, value, !!noIndent);
},
getContent: function() {
var view = activeView();
return view.substr(new sublime.Region(0, view.size()));
},
getSyntax: function() {
return pyGetSyntax();
},
getProfileName: function() {
var view = activeView();
var pos = this.getCaretPos();
if (view.match_selector(pos, 'text.html')
&& sublimeGetOption('autodetect_xhtml', false)
&& require('actionUtils').isXHTML(this)) {
return 'xhtml';
}
if (view.match_selector(pos, 'string.quoted.double.block.python')
|| view.match_selector(pos, 'source.coffee string')
|| view.match_selector(pos, 'string.unquoted.heredoc')) {
// use html's default profile for:
// * Python's multiline block
// * CoffeeScript string
// * PHP heredoc
return pyDetectProfile();
}
if (view.score_selector(pos, 'source string')) {
return 'line';
}
return pyDetectProfile();
},
prompt: function(title) {
return pyEditor.prompt();
},
getSelection: function() {
var view = activeView();
return view.sel() ? view.substr(view.sel()[0]) : '';
},
getFilePath: function() {
return activeView().file_name();
}
};
});
var _completions = {};
function require(name) {
return emmet.require(name);
}
function pyPreprocessText(value) {
var base = 1000;
var zeroBase = 0;
var lastZero = null;
var range = require('range');
var ts = require('tabStops');
var tabstopOptions = {
tabstop: function(data) {
var group = parseInt(data.group, 10);
var isZero = group === 0;
if (isZero)
group = ++zeroBase;
else
group += base;
var placeholder = data.placeholder;
if (placeholder) {
// recursively update nested tabstops
placeholder = ts.processText(placeholder, tabstopOptions);
}
var result = '${' + group + (placeholder ? ':' + placeholder : '') + '}';
if (isZero) {
lastZero = range.create(data.start, result);
}
return result
},
escape: function(ch) {
if (ch == '$') {
return '\\$';
}
if (ch == '\\') {
return '\\\\';
}
return ch;
}
};
value = ts.processText(value, tabstopOptions);
if (sublimeGetOption('insert_final_tabstop', false) && !/\$\{0\}$/.test(value)) {
value += '${0}';
} else if (lastZero) {
value = require('utils').replaceSubstring(value, '${0}', lastZero);
}
return value;
}
function pyExpandAbbreviationAsYouType(abbr) {
var info = require('editorUtils').outputInfo(editorProxy);
try {
var result = emmet.expandAbbreviation(abbr, info.syntax, info.profile,
require('actionUtils').captureContext(editorProxy));
return pyPreprocessText(result);
} catch (e) {
return '';
}
}
function pyWrapAsYouType(abbr, content) {
var info = require('editorUtils').outputInfo(editorProxy);
content = require('utils').escapeText(content);
var ctx = require('actionUtils').captureContext(editorProxy);
try {
var result = require('wrapWithAbbreviation').wrap(abbr, content, info.syntax, info.profile, ctx);
return pyPreprocessText(result);
} catch(e) {
return '';
}
}
function pyCaptureWrappingRange() {
var info = require('editorUtils').outputInfo(editorProxy);
var range = editorProxy.getSelectionRange();
var startOffset = range.start;
var endOffset = range.end;
if (startOffset == endOffset) {
// no selection, find tag pair
var match = require('htmlMatcher').find(info.content, startOffset);
if (!match) {
// nothing to wrap
return null;
}
/** @type Range */
var utils = require('utils');
var narrowedSel = utils.narrowToNonSpace(info.content, match.range);
startOffset = narrowedSel.start;
endOffset = narrowedSel.end;
}
return [startOffset, endOffset];
}
function pyGetTagNameRanges(pos) {
var ranges = [];
var info = require('editorUtils').outputInfo(editorProxy);
// search for tag
try {
var tag = require('htmlMatcher').tag(info.content, pos);
if (tag) {
var open = tag.open.range;
var tagName = /^<([\w\-\:]+)/i.exec(open.substring(info.content))[1];
ranges.push([open.start + 1, open.start + 1 + tagName.length]);
if (tag.close) {
ranges.push([tag.close.range.start + 2, tag.close.range.start + 2 + tagName.length]);
}
}
} catch (e) {}
return ranges;
}
function pyGetTagRanges() {
var ranges = [];
var info = require('editorUtils').outputInfo(editorProxy);
// search for tag
try {
var tag = require('htmlMatcher').tag(info.content, editorProxy.getCaretPos());
if (tag) {
ranges.push(tag.open.range.toArray());
if (tag.close) {
ranges.push(tag.close.range.toArray());
}
}
} catch (e) {}
return ranges;
}
function pyExtractAbbreviation() {
return require('expandAbbreviation').findAbbreviation(editorProxy);
}
function pyHasSnippet(name) {
return !!emmet.require('resources').findSnippet(editorProxy.getSyntax(), name);
}
/**
* Get all available CSS completions. This method is optimized for CSS
* only since it should contain snippets only so it's not required
* to do extra parsing
*/
function pyGetCSSCompletions(dialect) {
dialect = dialect || pyGetSyntax();
if (!_completions[dialect]) {
var all = require('resources').getAllSnippets(dialect);
var css = require('cssResolver');
_completions[dialect] = _.map(all, function(v, k) {
var snippetValue = typeof v.parsedValue == 'object'
? v.parsedValue.data
: v.value;
var snippet = css.transformSnippet(snippetValue, false, dialect);
return {
k: v.nk,
label: snippet.replace(/\:\s*\$\{0\}\s*;?$/, ''),
v: css.expandToSnippet(v.nk, dialect)
};
});
}
return _completions[dialect];
}
/**
* Returns current syntax name
* @return {String}
*/
function pyGetSyntax() {
var view = activeView();
var pt = view.sel()[0].begin();
var scope = 'scope_name' in view ? view.scope_name(pt) : view.syntax_name(pt);
if (~scope.indexOf('xsl')) {
return 'xsl';
}
var syntax = 'html';
// detect CSS-like syntaxes independently,
// since it may cause collisions with some highlighters
if (/\b(less|scss|sass|css|stylus)\b/.test(scope)) {
syntax = RegExp.$1;
} else if (/\b(html|xml|haml)\b/.test(scope)) {
syntax = RegExp.$1;
}
return require('actionUtils').detectSyntax(editorProxy, syntax);
}
function pyDetectProfile(argument) {
return require('actionUtils').detectProfile(editorProxy);
}