Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions doc/api/editorInfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,19 @@ Returns the `rep` object.
## editorInfo.ace_isCaret(?)
## editorInfo.ace_getLineAndCharForPoint(?)
## editorInfo.ace_performDocumentApplyAttributesToCharRange(?)
## editorInfo.ace_setAttributeOnSelection(?)
## editorInfo.ace_setAttributeOnSelection(attribute, enabled)
Sets an attribute on current range.
Example: `call.editorInfo.ace_setAttributeOnSelection("turkey::balls", true); // turkey is the attribute here, balls is the value
Notes: to remove the attribute pass enabled as false
## editorInfo.ace_toggleAttributeOnSelection(?)
## editorInfo.ace_getAttributeOnSelection(attribute)
## editorInfo.ace_getAttributeOnSelection(attribute, prevChar)
Returns a boolean if an attribute exists on a selected range.
prevChar value should be true if you want to get the previous Character attribute instead of the current selection for example
if the caret is at position 0,1 (after first character) it's probable you want the attributes on the character at 0,0
The attribute should be the string name of the attribute applied to the selection IE subscript
Example usage: Apply the activeButton Class to a button if an attribute is on a highlighted/selected caret position or range.
Example: `call.editorInfo.ace_getAttributeOnSelection("subscript");` // call here is the callstack from aceEditEvent.
Example `var isItThere = documentAttributeManager.getAttributeOnSelection("turkey::balls", true);`

See the ep_subscript plugin for an example of this function in action.
Notes: Does not work on first or last character of a line. Suffers from a race condition if called with aceEditEvent.
## editorInfo.ace_performSelectionChange(?)
Expand Down
83 changes: 83 additions & 0 deletions src/static/js/AttributeManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,89 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
return [];
},

/*
Gets a given attribute on a selection
@param attributeName
@param prevChar
returns true or false if an attribute is visible in range
*/
getAttributeOnSelection: function(attributeName, prevChar){
var rep = this.rep;
if (!(rep.selStart && rep.selEnd)) return
// If we're looking for the caret attribute not the selection
// has the user already got a selection or is this purely a caret location?
var isNotSelection = (rep.selStart[0] == rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]);
if(isNotSelection){
if(prevChar){
// If it's not the start of the line
if(rep.selStart[1] !== 0){
rep.selStart[1]--;
}
}
}

var withIt = Changeset.makeAttribsString('+', [
[attributeName, 'true']
], rep.apool);
var withItRegex = new RegExp(withIt.replace(/\*/g, '\\*') + "(\\*|$)");
function hasIt(attribs)
{
return withItRegex.test(attribs);
}

return rangeHasAttrib(rep.selStart, rep.selEnd)

function rangeHasAttrib(selStart, selEnd) {
// if range is collapsed -> no attribs in range
if(selStart[1] == selEnd[1] && selStart[0] == selEnd[0]) return false

if(selStart[0] != selEnd[0]) { // -> More than one line selected
var hasAttrib = true

// from selStart to the end of the first line
hasAttrib = hasAttrib && rangeHasAttrib(selStart, [selStart[0], rep.lines.atIndex(selStart[0]).text.length])

// for all lines in between
for(var n=selStart[0]+1; n < selEnd[0]; n++) {
hasAttrib = hasAttrib && rangeHasAttrib([n, 0], [n, rep.lines.atIndex(n).text.length])
}

// for the last, potentially partial, line
hasAttrib = hasAttrib && rangeHasAttrib([selEnd[0], 0], [selEnd[0], selEnd[1]])

return hasAttrib
}

// Logic tells us we now have a range on a single line

var lineNum = selStart[0]
, start = selStart[1]
, end = selEnd[1]
, hasAttrib = true

// Iterate over attribs on this line

var opIter = Changeset.opIterator(rep.alines[lineNum])
, indexIntoLine = 0

while (opIter.hasNext()) {
var op = opIter.next();
var opStartInLine = indexIntoLine;
var opEndInLine = opStartInLine + op.chars;
if (!hasIt(op.attribs)) {
// does op overlap selection?
if (!(opEndInLine <= start || opStartInLine >= end)) {
hasAttrib = false; // since it's overlapping but hasn't got the attrib -> range hasn't got it
break;
}
}
indexIntoLine = opEndInLine;
}

return hasAttrib
}
},

/*
Gets all attributes at a position containing line number and column
@param lineNumber starting with zero
Expand Down
11 changes: 10 additions & 1 deletion src/static/js/ace2_inner.js
Original file line number Diff line number Diff line change
Expand Up @@ -2338,8 +2338,17 @@ function Ace2Inner(){
editorInfo.ace_setAttributeOnSelection = setAttributeOnSelection;


function getAttributeOnSelection(attributeName){
function getAttributeOnSelection(attributeName, prevChar){
if (!(rep.selStart && rep.selEnd)) return
var isNotSelection = (rep.selStart[0] == rep.selEnd[0] && rep.selEnd[1] === rep.selStart[1]);
if(isNotSelection){
if(prevChar){
// If it's not the start of the line
if(rep.selStart[1] !== 0){
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if line has line attribute (which makes it start with "*")? Is that ok to look the attributes there, or should you look the attributes at 2nd char on line text?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, would be interesting to try, in through it should try to put rep.selStart[1] as -1 in that instance which is not ideal :P

rep.selStart[1]--;
}
}
}

var withIt = Changeset.makeAttribsString('+', [
[attributeName, 'true']
Expand Down