mirror of
https://github.com/icecoder/ICEcoder.git
synced 2026-03-03 15:24:00 +01:00
Updates to JS and multiple results to handle more regex
This commit is contained in:
@@ -2794,8 +2794,8 @@ var ICEcoder = {
|
||||
// FIND & REPLACE
|
||||
// ==============
|
||||
|
||||
// Backslash escape regex chars in string
|
||||
escapeRegExp: function(string) {
|
||||
// Backslash escape regex special chars in string
|
||||
escapeRegex: function(string) {
|
||||
// $& means the whole matched string
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
},
|
||||
@@ -2829,81 +2829,43 @@ var ICEcoder = {
|
||||
|
||||
// Find & replace text according to user selections
|
||||
findReplace: function(find, selectNext, canActionChanges, findPrevious) {
|
||||
let replace, results, thisCM, avgBlockH, addPadding, rBlocks, haveMatch, blockColor, replaceQS, targetQS, filesQS;
|
||||
let replace, results, thisCM, thisSelection, rBlocks, replaceQS, targetQS, filesQS;
|
||||
|
||||
// Determine our find rExp, replace value and results display
|
||||
const rExp = new RegExp(true === parent.ICEcoder.findRegex ? find : ICEcoder.escapeRegExp(find), "gi");
|
||||
const rExp = new RegExp(true === parent.ICEcoder.findRegex ? find : ICEcoder.escapeRegex(find), "gi");
|
||||
replace = get('replace').value;
|
||||
results = get('results');
|
||||
|
||||
// Get CM pane
|
||||
thisCM = this.getThisCM();
|
||||
|
||||
// Get this selection, either as regex escaped version or regular, for comparisons
|
||||
thisSelection = true === parent.ICEcoder.findRegex ? ICEcoder.escapeRegex(thisCM.getSelection()) : thisCM.getSelection();
|
||||
|
||||
// Finding in this document only
|
||||
if (thisCM && 0 < find.length && t['this document'] === document.findAndReplace.target.value) {
|
||||
// Replacing?
|
||||
if (t['and'] === document.findAndReplace.connector.value && true === canActionChanges) {
|
||||
// Find & replace the next instance, or all?
|
||||
if (t['replace'] === document.findAndReplace.replaceAction.value && thisCM.getSelection().toLowerCase() === find.toLowerCase()) {
|
||||
if (t['replace'] === document.findAndReplace.replaceAction.value && thisSelection.toLowerCase() === find.toLowerCase()) {
|
||||
thisCM.replaceSelection(replace, "around");
|
||||
} else if (t['replace all'] === document.findAndReplace.replaceAction.value) {
|
||||
thisCM.setValue(thisCM.getValue().replace(rExp, replace));
|
||||
}
|
||||
}
|
||||
|
||||
// Set results, resultsLines and findResult back to defaults
|
||||
this.results = [];
|
||||
this.resultsLines = [];
|
||||
this.findResult = 0;
|
||||
|
||||
// Start new iterators for line & last line
|
||||
let i = 0;
|
||||
let lastLine = -1;
|
||||
|
||||
// Get lineNum and chNum from cursor
|
||||
const lineNum = thisCM.getCursor(true === selectNext ? "anchor" : "head").line + 1;
|
||||
const chNum = thisCM.getCursor(true === selectNext ? "anchor" : "head").ch;
|
||||
|
||||
// Work out the avg block is either line height or fraction of space available
|
||||
avgBlockH = !this.scrollBarVisible ? thisCM.defaultTextHeight() : parseInt(this.content.style.height, 10) / thisCM.lineCount();
|
||||
|
||||
// Need to add padding if there's no scrollbar, so current line highlighting lines up with it
|
||||
addPadding = !this.scrollBarVisible ? thisCM.heightAtLine(0) : 0;
|
||||
|
||||
// Result blocks string empty to start, ready to hold DOM elems to show in results bar
|
||||
rBlocks = "";
|
||||
|
||||
// Start looking for results
|
||||
thisCM.eachLine(function(line) {
|
||||
i++;
|
||||
haveMatch = false;
|
||||
// If we have matches for our regex for this line
|
||||
while ((match = rExp.exec(line.text)) !== null) {
|
||||
haveMatch = true;
|
||||
// Not the same as last line, add to resultsLines
|
||||
if (lastLine !== i) {
|
||||
ICEcoder.resultsLines.push(match.index);
|
||||
lastLine = i;
|
||||
}
|
||||
// If the line containing a result is less than than the cursors line or
|
||||
// if the character position of the match is less than the cursor position, increment findResult
|
||||
if (i < lineNum || (i === lineNum && match.index < chNum)) {
|
||||
ICEcoder.findResult++;
|
||||
}
|
||||
// Push the line & char position coords into results
|
||||
ICEcoder.results.push([i, match.index]);
|
||||
}
|
||||
// If the avg block height for results in results bar is above 0.5 pixels high, we can add a DOM elem
|
||||
if (0.5 <= avgBlockH) {
|
||||
// Red for current line, grey for another line, transparent if no match
|
||||
blockColor = haveMatch ? thisCM.getCursor().line + 1 == i ? "rgba(192,0,0,0.3)" : "rgba(128,128,128,0.3)" : "transparent";
|
||||
// Add the DOM elem into our rBlocks string
|
||||
rBlocks += '<div style="position: absolute; display: block; width: 12px; height:' + avgBlockH + 'px; background: ' + blockColor + '; top: ' + parseInt((avgBlockH * (i - 1)) + addPadding, 10) + 'px"></div>';
|
||||
}
|
||||
});
|
||||
rData = ICEcoder.findInCMContent(thisCM, rExp, selectNext);
|
||||
|
||||
// Set results, resultsLines and findResult plus rBlocks which shows DOM elems in results bar
|
||||
this.results = rData.results;
|
||||
this.resultsLines = rData.resultsLines;
|
||||
this.findResult = rData.findResult;
|
||||
rBlocks = rData.rBlocks;
|
||||
|
||||
// Increment findResult one more if our selection is what we want to find and we want to find next
|
||||
if (find.toLowerCase() === thisCM.getSelection().toLowerCase() && false === findPrevious) {
|
||||
ICEcoder.findResult++;
|
||||
if (find.toLowerCase() === thisSelection.toLowerCase() && false === findPrevious) {
|
||||
this.findResult++;
|
||||
}
|
||||
|
||||
if (findPrevious) {
|
||||
@@ -2940,9 +2902,11 @@ var ICEcoder = {
|
||||
this.goToLine(this.results[this.findResult][0], this.results[this.findResult][1], true);
|
||||
|
||||
// Finally, highlight our selection and focus on CM pane
|
||||
// Note when setting the end of the selection we need to deduct extra chars added (the regex escaping backslashes)
|
||||
// TODO: This idea doesn't really work if you say have "^\$x" and $x's in docs
|
||||
thisCM.setSelection(
|
||||
{"line": this.results[this.findResult][0]-1, "ch": this.results[this.findResult][1]},
|
||||
{"line": this.results[this.findResult][0]-1, "ch": this.results[this.findResult][1] + find.length}
|
||||
{"line": this.results[this.findResult][0]-1, "ch": this.results[this.findResult][1] + find.length - parseInt((ICEcoder.escapeRegex(find).length - find.length) / 2, 10)}
|
||||
);
|
||||
this.focus();
|
||||
}
|
||||
@@ -3003,6 +2967,67 @@ var ICEcoder = {
|
||||
}
|
||||
},
|
||||
|
||||
findInCMContent: function(thisCM, rExp, selectNext) {
|
||||
let avgBlockH, addPadding, rBlocks, blockColor, haveMatch;
|
||||
|
||||
// Start new iterators for line & last line
|
||||
let i = 0;
|
||||
let lastLine = -1;
|
||||
|
||||
// Set results, resultsLines and findResult to defaults
|
||||
let results = [];
|
||||
let resultsLines = [];
|
||||
let findResult = 0;
|
||||
|
||||
// Get lineNum and chNum from cursor
|
||||
const lineNum = thisCM.getCursor(true === selectNext ? "anchor" : "head").line + 1;
|
||||
const chNum = thisCM.getCursor(true === selectNext ? "anchor" : "head").ch;
|
||||
|
||||
// Work out the avg block is either line height or fraction of space available
|
||||
avgBlockH = !this.scrollBarVisible ? thisCM.defaultTextHeight() : parseInt(this.content.style.height, 10) / thisCM.lineCount();
|
||||
|
||||
// Need to add padding if there's no scrollbar, so current line highlighting lines up with it
|
||||
addPadding = !this.scrollBarVisible ? thisCM.heightAtLine(0) : 0;
|
||||
|
||||
// Result blocks string empty to start, ready to hold DOM elems to show in results bar
|
||||
rBlocks = "";
|
||||
|
||||
thisCM.eachLine(function(line) {
|
||||
i++;
|
||||
haveMatch = false;
|
||||
// If we have matches for our regex for this line
|
||||
while ((match = rExp.exec(line.text)) !== null) {
|
||||
haveMatch = true;
|
||||
// Not the same as last line, add to resultsLines
|
||||
if (lastLine !== i) {
|
||||
resultsLines.push(match.index);
|
||||
lastLine = i;
|
||||
}
|
||||
// If the line containing a result is less than than the cursors line or
|
||||
// if the character position of the match is less than the cursor position, increment findResult
|
||||
if (i < lineNum || (i === lineNum && match.index < chNum)) {
|
||||
findResult++;
|
||||
}
|
||||
// Push the line & char position coords into results
|
||||
results.push([i, match.index]);
|
||||
}
|
||||
// If the avg block height for results in results bar is above 0.5 pixels high, we can add a DOM elem
|
||||
if (0.5 <= avgBlockH) {
|
||||
// Red for current line, grey for another line, transparent if no match
|
||||
blockColor = haveMatch ? thisCM.getCursor().line + 1 == i ? "rgba(192,0,0,0.3)" : "rgba(128,128,128,0.3)" : "transparent";
|
||||
// Add the DOM elem into our rBlocks string
|
||||
rBlocks += '<div style="position: absolute; display: block; width: 12px; height:' + avgBlockH + 'px; background: ' + blockColor + '; top: ' + parseInt((avgBlockH * (i - 1)) + addPadding, 10) + 'px"></div>';
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
"results": results,
|
||||
"resultsLines": resultsLines,
|
||||
"findResult": findResult,
|
||||
"rBlocks": rBlocks
|
||||
}
|
||||
},
|
||||
|
||||
// Replace text in a file
|
||||
replaceInFile: function(fileRef, find, replace) {
|
||||
this.serverQueue(
|
||||
|
||||
@@ -48,24 +48,27 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
let foundInSelected = false;
|
||||
const userTarget = parent.document.findAndReplace.target.value;
|
||||
const findText = parent.document.findAndReplace.find.value;
|
||||
const rExp = new RegExp(true === parent.ICEcoder.findRegex ? findText : parent.ICEcoder.escapeRegex(findText), "gi");
|
||||
<?php
|
||||
$findText = str_replace("ICEcoder:", "", str_replace("'", "\'", $_GET['find']));
|
||||
// Find in open docs?
|
||||
// TODO: This doesn't actually replace if using regex, it doesn't error - tabs show a change, but nothing replaced
|
||||
if (false === isset($_GET['target'])) {
|
||||
$targetName = $t['document'];
|
||||
?>
|
||||
let startTab = parent.ICEcoder.selectedTab;
|
||||
const rExp = new RegExp(findText, "gi");
|
||||
|
||||
for (let i = 1; i <= parent.ICEcoder.openFiles.length; i++) {
|
||||
parent.ICEcoder.switchTab(i);
|
||||
const cM = parent.ICEcoder.getcMInstance();
|
||||
const content = cM.getValue();
|
||||
if (content.match(rExp)) {
|
||||
const selectNext = true;
|
||||
rData = parent.ICEcoder.findInCMContent(cM, rExp, selectNext);
|
||||
if (0 < rData.results.length) {
|
||||
resultsDisplay +=
|
||||
'<a href="javascript:gotoTab(' + i + '); goFind()">' +
|
||||
parent.ICEcoder.openFiles[i - 1] +
|
||||
'</a><br><div id="foundCount' + i + '"><?php echo $t['Found'];?> ' +
|
||||
content.match(rExp).length +
|
||||
rData.results.length +
|
||||
' <?php echo $t['times'];?></div>';
|
||||
<?php if (isset($_GET['replace'])) { ?>
|
||||
resultsDisplay +=
|
||||
@@ -79,8 +82,9 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
parent.ICEcoder.switchTab(startTab);
|
||||
}
|
||||
<?php
|
||||
// Find in files or filenames
|
||||
// Find in files or filenames
|
||||
} else {
|
||||
// filenames
|
||||
if (0 < strpos($_GET['target'], "filenames")) {
|
||||
$targetName = $t['file folder'];
|
||||
?>
|
||||
@@ -88,11 +92,18 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
for (let i = 0; i < spansArray.length; i++) {
|
||||
let foundInSelected = false;
|
||||
const targetURL = spansArray[i].id.replace(/\|/g, "/").toLowerCase();
|
||||
const targetName = targetURL.substring(targetURL.lastIndexOf("/") + 1);
|
||||
let haveMatch = false;
|
||||
while ((match = rExp.exec(targetName)) !== null) {
|
||||
console.log(match);
|
||||
haveMatch = true;
|
||||
}
|
||||
if (
|
||||
targetURL.lastIndexOf(findText.toLowerCase()) > targetURL.lastIndexOf("/")
|
||||
&& -1 < targetURL.indexOf(findText.toLowerCase()) && targetURL.indexOf('_perms')>-1) {
|
||||
// TODO: Find in filenames not working with regex, see all instances of findText and $findText below
|
||||
true === haveMatch && -1 < targetURL.indexOf('_perms')) {
|
||||
if (-1 < userTarget.indexOf("selected")) {
|
||||
for (let j = 0; j < parent.ICEcoder.selectedFiles.length; j++) {
|
||||
// TODO: This whole file needs comments - what does the below do?!
|
||||
if (
|
||||
0 === targetURL.replace(/\//g, "|").indexOf(parent.ICEcoder.selectedFiles[j].replace(/\//g, "|").replace(/_perms/g, ""))
|
||||
&& (
|
||||
@@ -110,6 +121,7 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
'\');parent.ICEcoder.goFindAfterOpenInt = setInterval(function(){goFindAfterOpen(\'<?php echo $docRoot;?>' +
|
||||
targetURL.replace(/\|/g, "/").replace(/_perms/g, "") +
|
||||
'\')}, 20);parent.ICEcoder.showHide(\'hide\', parent.document.getElementById(\'blackMask\'))">';
|
||||
// TODO: get this line working
|
||||
resultsDisplay +=
|
||||
targetURL.replace(/\|/g, "/").replace(/_perms/g, "").replace(/<?php
|
||||
echo str_replace("/", "\/",strtolower($findText)); ?>/g, "<b>" +
|
||||
@@ -118,6 +130,7 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
<?php if (false === isset($_GET['replace'])) { ?>
|
||||
resultsDisplay += '<div id="foundCount' + i +'">' + spansArray[i].innerHTML + '</div>';
|
||||
<?php ;} else { ?>
|
||||
// TODO: get this line working
|
||||
resultsDisplay +=
|
||||
'<div id="foundCount' + i + '">' + spansArray[i].innerHTML +
|
||||
', <?php echo $t['rename to'];?> ' +
|
||||
@@ -135,6 +148,7 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
}
|
||||
}
|
||||
<?php
|
||||
// files
|
||||
} else {
|
||||
$targetName = $t['file'];
|
||||
$r = 0;
|
||||
@@ -192,6 +206,7 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// TODO: consider $findText here
|
||||
$results = phpGrep($findText, $docRoot . $iceRoot, $docRoot . $iceRoot);
|
||||
echo 'resultsDisplay += "' . $results . '";';
|
||||
?>
|
||||
@@ -237,7 +252,8 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
};
|
||||
|
||||
const replaceInFileSingle = function(fileRef) {
|
||||
parent.ICEcoder.replaceInFile(fileRef, findText, '<?php if (isset($_GET['replace'])) {echo $_GET['replace'];}; ?>');
|
||||
// TODO: findText in this line
|
||||
parent.ICEcoder.replaceInFile(fileRef, true === parent.ICEcoder.findRegex ? findText : parent.ICEcoder.escapeRegex(findText), '<?php if (isset($_GET['replace'])) {echo $_GET['replace'];}; ?>');
|
||||
};
|
||||
|
||||
const replaceInFilesAll = function() {
|
||||
@@ -249,7 +265,8 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
|
||||
const renameSingle = function(arrayRef) {
|
||||
fileRef = spansArray[arrayRef].id.replace(/\|/g, "/").replace(/_perms/g, "");
|
||||
const rExp = new RegExp(findText, "gi");
|
||||
const rExp = new RegExp(true === parent.ICEcoder.findRegex ? findText : parent.ICEcoder.escapeRegex(findText), "gi");
|
||||
// TODO: get this working
|
||||
newName = spansArray[arrayRef].id.replace(/\|/g, "/").replace(/_perms/g, "").replace(rExp, "<?php if (isset($_GET['replace'])) {echo $_GET['replace'];}; ?>");
|
||||
parent.ICEcoder.renameFile(fileRef,newName);
|
||||
};
|
||||
@@ -277,7 +294,7 @@ if (true === isset($_GET['target']) && false !== strpos($_GET['target'], "filena
|
||||
parent.document.getElementById('results').style.display = 'inline-block';
|
||||
// Action the find and then focus on find input box
|
||||
setTimeout(function() {
|
||||
parent.ICEcoder.findReplace(findText, true, false, false);
|
||||
parent.ICEcoder.findReplace(true === parent.ICEcoder.findRegex ? findText : parent.ICEcoder.escapeRegex(findText), true, false, false);
|
||||
parent.document.getElementById("find").focus();
|
||||
}, 0);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user