File indexing completed on 2024-05-19 04:00:08
0001 var katescript = { 0002 "author": "Dominik Haumann <dhdev@gmx.de>, Milian Wolff <mail@milianw.de>, Gerald Senarclens de Grancy <oss@senarclens.eu>, Alex Turbov <i.zaufi@gmail.com>, Pablo Rauzy <r_NOSPAM_@uzy.me>, Henri Kaustinen <heka1@protonmail.com>", 0003 "license": "LGPL-2.1+", 0004 "revision": 12, 0005 "kate-version": "5.1", 0006 "functions": ["sort", "sortuniq", "moveLinesDown", "moveLinesUp", "natsort", "uniq", "rtrim", "ltrim", "trim", "join", "rmblank", "alignon", "unwrap", "each", "filter", "map", "duplicateLinesUp", "duplicateLinesDown", "duplicateSelection", "rewrap", "encodeURISelection", "decodeURISelection", "fsel", "bsel"], 0007 "actions": [ 0008 { "function": "sort", 0009 "name": "Sort Selected Text Alphabetically", 0010 "category": "Editing" 0011 }, 0012 { "function": "sortuniq", 0013 "name": "Remove Duplicates and Sort Selected Text Alphabetically", 0014 "category": "Editing" 0015 }, 0016 { "function": "uniq", 0017 "name": "Remove Duplicate Lines", 0018 "category": "Editing" 0019 }, 0020 { "function": "rtrim", 0021 "name": "Remove Trailing Spaces", 0022 "category": "Editing" 0023 }, 0024 { "function": "ltrim", 0025 "name": "Remove Leading Spaces", 0026 "category": "Editing" 0027 }, 0028 { "function": "trim", 0029 "name": "Remove Trailing and Leading Spaces", 0030 "category": "Editing" 0031 }, 0032 { "function": "join", 0033 "name": "Join Lines", 0034 "category": "Editing" 0035 }, 0036 { "function": "moveLinesDown", 0037 "name": "Move Lines Down", 0038 "shortcut": "Ctrl+Shift+Down", 0039 "category": "Editing" 0040 }, 0041 { "function": "moveLinesUp", 0042 "name": "Move Lines Up", 0043 "shortcut": "Ctrl+Shift+Up", 0044 "category": "Editing" 0045 }, 0046 { "function": "duplicateLinesDown", 0047 "name": "Duplicate Selected Lines Down", 0048 "category": "Editing" 0049 }, 0050 { "function": "duplicateLinesUp", 0051 "name": "Duplicate Selected Lines Up", 0052 "category": "Editing" 0053 }, 0054 { "function": "duplicateSelection", 0055 "name": "Duplicate selected text", 0056 "category": "Editing" 0057 }, 0058 { "function": "encodeURISelection", 0059 "name": "URI-encode Selected Text", 0060 "category": "Editing" 0061 }, 0062 { "function": "decodeURISelection", 0063 "name": "URI-decode Selected Text", 0064 "category": "Editing" 0065 }, 0066 { "function": "rmblank", 0067 "name": "Remove Empty Lines", 0068 "category": "Editing" 0069 } 0070 ] 0071 }; // kate-script-header, must be at the start of the file without comments, pure json 0072 0073 // required katepart js libraries 0074 require ("range.js"); 0075 0076 function sort() 0077 { 0078 each(function(lines){return lines.sort()}); 0079 } 0080 0081 function uniq() 0082 { 0083 each(function(lines) { 0084 var uniq_lines = []; 0085 var seen = new Set(); 0086 for ( var i = 0; i < lines.length; ++i ) { 0087 if (!seen.has(lines[i])) { 0088 seen.add(lines[i]); 0089 uniq_lines.push(lines[i]); 0090 } 0091 } 0092 return uniq_lines; 0093 }); 0094 } 0095 0096 function sortuniq() 0097 { 0098 each(function(lines) { 0099 var uniq_lines = []; 0100 var seen = new Set(); 0101 for ( var i = 0; i < lines.length; ++i ) { 0102 if (!seen.has(lines[i])) { 0103 seen.add(lines[i]); 0104 uniq_lines.push(lines[i]); 0105 } 0106 } 0107 return uniq_lines.sort(); 0108 }); 0109 } 0110 0111 function natsort() 0112 { 0113 each(function(lines){return lines.sort(natcompare);}); 0114 } 0115 0116 function rtrim() 0117 { 0118 map(function(l){ return l.replace(/\s+$/, ''); }); 0119 } 0120 0121 function ltrim() 0122 { 0123 map(function(l){ return l.replace(/^\s+/, ''); }); 0124 } 0125 0126 function trim() 0127 { 0128 map(function(l){ return l.replace(/^\s+|\s+$/, ''); }); 0129 } 0130 0131 function rmblank() 0132 { 0133 filter(function(l) { return l.length > 0; }); 0134 } 0135 0136 function alignon(pattern) 0137 { 0138 if (typeof pattern == "undefined") { 0139 pattern = ""; 0140 } 0141 var selection = view.selection(); 0142 if (!selection.isValid()) { 0143 selection = document.documentRange(); 0144 } 0145 view.alignOn(selection, pattern); 0146 } 0147 0148 function join(separator) 0149 { 0150 if (typeof(separator) != "string") { 0151 separator = ""; 0152 } 0153 each(function(lines){ 0154 return [lines.join(separator)]; 0155 }); 0156 } 0157 0158 // unwrap does the opposite of the script word wrap 0159 function unwrap () 0160 { 0161 var selectionRange = view.selection(); 0162 if (selectionRange.isValid()) { 0163 // unwrap all paragraphs in the selection range 0164 var currentLine = selectionRange.start.line; 0165 var count = selectionRange.end.line - selectionRange.start.line; 0166 0167 document.editBegin(); 0168 while (count >= 0) { 0169 // skip empty lines 0170 while (count >= 0 && document.firstColumn(currentLine) == -1) { 0171 --count; 0172 ++currentLine; 0173 } 0174 0175 // find block of text lines to join 0176 var anchorLine = currentLine; 0177 while (count >= 0 && document.firstColumn(currentLine) != -1) { 0178 --count; 0179 ++currentLine; 0180 } 0181 0182 if (currentLine != anchorLine) { 0183 document.joinLines(anchorLine, currentLine - 1); 0184 currentLine -= currentLine - anchorLine - 1; 0185 } 0186 } 0187 document.editEnd(); 0188 } else { 0189 // unwrap paragraph under the cursor 0190 var cursorPosition = view.cursorPosition(); 0191 if (document.firstColumn(cursorPosition.line) != -1) { 0192 var startLine = cursorPosition.line; 0193 while (startLine > 0) { 0194 if (document.firstColumn(startLine - 1) == -1) { 0195 break; 0196 } 0197 --startLine; 0198 } 0199 0200 var endLine = cursorPosition.line; 0201 var lineCount = document.lines(); 0202 while (endLine < lineCount) { 0203 if (document.firstColumn(endLine + 1) == -1) { 0204 break; 0205 } 0206 ++endLine; 0207 } 0208 0209 if (startLine != endLine) { 0210 document.editBegin(); 0211 document.joinLines(startLine, endLine); 0212 document.editEnd(); 0213 } 0214 } 0215 } 0216 } 0217 0218 /// \note Range contains a block selected by lines (\b ONLY)! 0219 /// And it is an open range! I.e. <em>[start, end)</em> (like in STL). 0220 function _getBlockForAction() 0221 { 0222 // Check if selection present in a view... 0223 var blockRange = Range(view.selection()); 0224 var cursorPosition = view.cursorPosition(); 0225 if (blockRange.isValid()) { 0226 blockRange.start.column = 0; 0227 if (blockRange.end.column != 0) 0228 blockRange.end.line++; 0229 blockRange.end.column = 0; 0230 } else { 0231 // No, it doesn't! Ok, lets select the current line only 0232 // from current position to the end 0233 blockRange = new Range(cursorPosition.line, 0, cursorPosition.line + 1, 0); 0234 } 0235 return blockRange; 0236 } 0237 0238 // Adjusts ("moves") the current selection by offset. 0239 // Positive offsets move down, negatives up. 0240 function _adjustSelection(selection, offset) 0241 { 0242 if (selection.end.line + offset < document.lines()) { 0243 selection = new Range(selection.start.line + offset, selection.start.column, 0244 selection.end.line + offset, selection.end.column); 0245 } else { 0246 selection = new Range(selection.start.line + offset, selection.start.column, 0247 selection.end.line + offset - 1, 0248 document.lineLength(selection.end.line + offset - 1)); 0249 } 0250 view.setSelection(selection); 0251 } 0252 0253 function moveLinesDown() 0254 { 0255 var selection = view.selection(); 0256 var blockRange = _getBlockForAction(); 0257 // Check is there a space to move? 0258 if (blockRange.end.line < document.lines()) { 0259 document.editBegin(); 0260 // Move a block to one line down: 0261 // 0) take one line after the block 0262 var text = document.line(blockRange.end.line); 0263 // 1) remove the line after the block 0264 document.removeLine(blockRange.end.line); 0265 // 2) insert a line before the block 0266 document.insertLine(blockRange.start.line, text); 0267 document.editEnd(); 0268 if (view.hasSelection()) 0269 _adjustSelection(selection, 1); 0270 } 0271 } 0272 0273 function moveLinesUp() 0274 { 0275 var cursor = view.cursorPosition(); 0276 var selection = view.selection(); 0277 var blockRange = _getBlockForAction(); 0278 // Check is there a space to move? 0279 if (0 < blockRange.start.line) { 0280 document.editBegin(); 0281 // Move a block to one line up: 0282 // 0) take one line before the block, 0283 var text = document.line(blockRange.start.line - 1); 0284 // 1) and insert it after the block 0285 document.insertLine(blockRange.end.line, text); 0286 // 2) remove the original line 0287 document.removeLine(blockRange.start.line - 1); 0288 view.setCursorPosition(cursor.line - 1, cursor.column); 0289 if (view.hasSelection()) 0290 _adjustSelection(selection, -1); 0291 document.editEnd(); 0292 } 0293 } 0294 0295 function duplicateLinesDown() 0296 { 0297 var selection = view.selection(); 0298 var blockRange = _getBlockForAction(); 0299 document.editBegin(); 0300 document.insertText(blockRange.start, document.text(blockRange)); 0301 _adjustSelection(selection, blockRange.end.line - blockRange.start.line); 0302 document.editEnd(); 0303 } 0304 0305 function duplicateLinesUp() 0306 { 0307 var cursor = view.cursorPosition(); 0308 var selection = view.selection(); 0309 var blockRange = _getBlockForAction(); 0310 document.editBegin(); 0311 if (blockRange.end.line == document.lines()) { 0312 var lastLine = document.lines() - 1; 0313 var lastCol = document.lineLength(document.lines() - 1); 0314 blockRange.end.line = lastLine; 0315 blockRange.end.column = lastCol; 0316 document.insertText(lastLine, lastCol, document.text(blockRange)); 0317 document.wrapLine(lastLine, lastCol); 0318 } else { 0319 document.insertText(blockRange.end, document.text(blockRange)); 0320 } 0321 view.setCursorPosition(cursor.line, cursor.column); 0322 _adjustSelection(selection, 0); 0323 document.editEnd(); 0324 } 0325 0326 0327 // Duplicate selected text at start of selection. Place cursor after selection. 0328 function duplicateSelection() 0329 { 0330 var selection = view.selectedText(); 0331 0332 if (!selection) { 0333 return 0334 } 0335 0336 var range = view.selection(); 0337 document.insertText(range.start, selection); 0338 range = view.selection(); 0339 view.setCursorPosition(range.end.line, range.end.column); 0340 } 0341 0342 function rewrap() 0343 { 0344 // initialize line span 0345 var fromLine = view.cursorPosition().line; 0346 var toLine = fromLine; 0347 var hasSelection = view.hasSelection(); 0348 0349 // if a text selection is present, use it to reformat the paragraph 0350 if (hasSelection) { 0351 var range = view.selection(); 0352 fromLine = range.start.line; 0353 toLine = range.end.line; 0354 } else { 0355 // abort, if the cursor is in an empty line 0356 if (document.firstColumn(fromLine) == -1) 0357 return; 0358 0359 // no text selection present: search for start & end of paragraph 0360 while (fromLine > 0 && 0361 document.prevNonEmptyLine(fromLine-1) == fromLine - 1) --fromLine; 0362 while (toLine < document.lines() - 1 && 0363 document.nextNonEmptyLine(toLine+1) == toLine + 1) ++toLine; 0364 } 0365 0366 // initialize wrap columns 0367 var wrapColumn = 80; 0368 var softWrapColumn = 82; 0369 var exceptionColumn = 70; 0370 0371 document.editBegin(); 0372 0373 if (fromLine < toLine) { 0374 document.joinLines(fromLine, toLine); 0375 } 0376 0377 var line = fromLine; 0378 // as long as the line is too long... 0379 while (document.lastColumn(line) > wrapColumn) { 0380 // ...search for current word boundaries... 0381 var range = document.wordRangeAt(line, wrapColumn); 0382 if (!range.isValid()) { 0383 break; 0384 } 0385 0386 // ...and wrap at a 'smart' position 0387 var wrapCursor = range.start; 0388 if (range.start.column < exceptionColumn && range.end.column <= softWrapColumn) { 0389 wrapCursor = range.end; 0390 } 0391 if (!document.wrapLine(wrapCursor)) 0392 break; 0393 ++line; 0394 } 0395 0396 document.editEnd(); 0397 } 0398 0399 function _uri_transform_selection(transformer) 0400 { 0401 var selection = view.selection(); 0402 var cursor = view.cursorPosition(); 0403 // TODO Multiline conversions are meaningless!? 0404 if (selection.isValid() && selection.onSingleLine()) { 0405 var text = document.text(selection); 0406 var coded_text = transformer(text); 0407 document.editBegin(); 0408 document.removeText(selection); 0409 document.insertText(selection.start, coded_text); 0410 document.editEnd(); 0411 var size_diff = coded_text.length - text.length; 0412 selection.end.column += size_diff; 0413 view.setSelection(selection); 0414 if (selection.start.column < cursor.column) { 0415 cursor.column += size_diff; 0416 } 0417 view.setCursorPosition(cursor); 0418 } 0419 } 0420 0421 function encodeURISelection() 0422 { 0423 _uri_transform_selection(encodeURIComponent); 0424 } 0425 0426 function decodeURISelection() 0427 { 0428 _uri_transform_selection(decodeURIComponent); 0429 } 0430 0431 function fsel(target) // forward select 0432 { 0433 startSel = view.cursorPosition(); 0434 if (typeof target == "undefined") { // by default, select til the end of the current line 0435 endSel = new Cursor(startSel.line, document.lastColumn(startSel.line) + 1); 0436 } else { // otherwise, select to the first occurrence of the given target (including it) 0437 match = view.searchText(new Range(startSel, document.documentRange().end), target); 0438 if (!match.isValid()) return false; 0439 else endSel = match.end; 0440 } 0441 view.setCursorPosition(endSel); 0442 view.setSelection(new Range(startSel, endSel)); 0443 } 0444 0445 function bsel(target) // backward select 0446 { 0447 endSel = view.cursorPosition(); 0448 if (typeof target == "undefined") { // by default, select from the beginning of the current line 0449 startSel = new Cursor(endSel.line, 0); 0450 } else { // otherwise, select from the last occurrence of the given target (including it) 0451 match = view.searchText(new Range(document.documentRange().start, endSel), target, true); 0452 if (!match.isValid()) return false; 0453 else startSel = match.start; 0454 } 0455 view.setCursorPosition(startSel); 0456 view.setSelection(new Range(startSel, endSel)); 0457 } 0458 0459 function help(cmd) 0460 { 0461 if (cmd == "sort") { 0462 return i18n("Sort the selected text or whole document."); 0463 } else if (cmd == "moveLinesDown") { 0464 return i18n("Move selected lines down."); 0465 } else if (cmd == "moveLinesUp") { 0466 return i18n("Move selected lines up."); 0467 } else if (cmd == "uniq") { 0468 return i18n("Remove duplicate lines from the selected text or whole document."); 0469 } else if (cmd == "natsort") { 0470 return i18n("Sort the selected text or whole document in natural order.<br>Here is an example to show the difference to the normal sort method:<br>sort(a10, a1, a2) => a1, a10, a2<br>natsort(a10, a1, a2) => a1, a2, a10"); 0471 } else if (cmd == "rtrim") { 0472 return i18n("Trims trailing whitespace from selection or whole document."); 0473 } else if (cmd == "ltrim") { 0474 return i18n("Trims leading whitespace from selection or whole document."); 0475 } else if (cmd == "trim") { 0476 return i18n("Trims leading and trailing whitespace from selection or whole document."); 0477 } else if (cmd == "join") { 0478 return i18n("Joins selected lines or whole document. Optionally pass a separator to put between each line:<br><code>join ', '</code> will e.g. join lines and separate them by a comma."); 0479 } else if (cmd == "rmblank") { 0480 return i18n("Removes empty lines from selection or whole document."); 0481 } else if (cmd == "alignon") { 0482 return i18n("This command aligns lines in the selected block or whole document on the column given by a regular expression given as an argument.<br><br>If you give an empty pattern it will align on the first non-blank character by default.<br>If the pattern has a capture it will indent on the captured match.<br><br><i>Examples</i>:<br>'<code>alignon -</code>' will insert spaces before the first '-' of each lines to align them all on the same column.<br>'<code>alignon :\\s+(.)</code>' will insert spaces before the first non-blank character that occurs after a colon to align them all on the same column."); 0483 } else if (cmd == "unwrap") { 0484 return "Unwraps all paragraphs in the text selection, or the paragraph under the text cursor if there is no selected text."; 0485 } else if (cmd == "each") { 0486 return i18n("Given a JavaScript function as argument, call that for the list of (selected) lines and replace them with the return value of that callback.<br>Example (join selected lines):<br><code>each 'function(lines){return lines.join(\", \");}'</code><br>To save you some typing, you can also do this to achieve the same:<br><code>each 'lines.join(\", \")'</code>"); 0487 } else if (cmd == "filter") { 0488 return i18n("Given a JavaScript function as argument, call that for the list of (selected) lines and remove those where the callback returns false.<br>Example (see also <code>rmblank</code>):<br><code>filter 'function(l){return l.length > 0;}'</code><br>To save you some typing, you can also do this to achieve the same:<br><code>filter 'line.length > 0'</code>"); 0489 } else if (cmd == "map") { 0490 return i18n("Given a JavaScript function as argument, call that for the list of (selected) lines and replace the line with the return value of the callback.<br>Example (see also <code>ltrim</code>):<br><code>map 'function(line){return line.replace(/^\\s+/, \"\");}'</code><br>To save you some typing, you can also do this to achieve the same:<br><code>map 'line.replace(/^\\s+/, \"\")'</code>"); 0491 } else if (cmd == "duplicateLinesUp") { 0492 return i18n("Duplicates the selected lines up."); 0493 } else if (cmd == "duplicateLinesDown") { 0494 return i18n("Duplicates the selected lines down."); 0495 } else if (cmd == 'duplicateSelection') { 0496 return i18n('Duplicate the selected text. Place cursor after selection.'); 0497 } else if (cmd == "encodeURISelection") { 0498 return i18n("Encode special chars in a single line selection, so the result text can be used as URI."); 0499 } else if (cmd == "decodeURISelection") { 0500 return i18n("Reverse action of URI encode."); 0501 } else if (cmd == "fsel") { 0502 return i18n("Select text forward from current cursor position to the first occurrence of the given argument after it (or the end of the current line by default)."); 0503 } else if (cmd == "bsel") { 0504 return i18n("Select text backward from current cursor position to the last occurrence of the given argument before it (or the beginning of the current line by default)."); 0505 } 0506 } 0507 0508 /// helper code below: 0509 0510 function __toFunc(func, defaultArgName) 0511 { 0512 if ( typeof(func) != "function" ) { 0513 try { 0514 func = eval("(" + func + ")"); 0515 } catch(e) {} 0516 debug(func, typeof(func)) 0517 if ( typeof(func) != "function" ) { 0518 try { 0519 // one more try to support e.g.: 0520 // map 'l+l' 0521 // or: 0522 // each 'lines.join("\n")' 0523 func = eval("(function(" + defaultArgName + "){ return " + func + ";})"); 0524 debug(func, typeof(func)) 0525 } catch(e) {} 0526 if ( typeof(func) != "function" ) { 0527 throw "parameter is not a valid JavaScript callback function: " + typeof(func); 0528 } 0529 } 0530 } 0531 return func; 0532 } 0533 0534 function each(func) 0535 { 0536 func = __toFunc(func, 'lines'); 0537 0538 var cursor = view.cursorPosition(); 0539 var selection = view.selection(); 0540 var hasSelection = selection.isValid(); 0541 if (!hasSelection) { 0542 // use whole range 0543 selection = document.documentRange(); 0544 } else { 0545 selection.start.column = 0; 0546 selection.end.column = document.lineLength(selection.end.line); 0547 } 0548 0549 var text = document.text(selection); 0550 0551 var lines = text.split("\n"); 0552 oldLineCount = lines.length; 0553 oldCurrentLineLength = document.lineLength(cursor.line); 0554 lines = func(lines); 0555 if ( typeof(lines) == "object" ) { 0556 text = lines.join("\n"); 0557 newLineCount = lines.length; 0558 } else if ( typeof(lines) == "string" ) { 0559 text = lines 0560 newLineCount = (lines.match('\n') || []).length; 0561 } else { 0562 throw "callback function for each has to return object or array of lines"; 0563 } 0564 0565 view.clearSelection(); 0566 0567 document.editBegin(); 0568 if (!hasSelection) { 0569 document.setText(text); 0570 } else { 0571 document.removeText(selection); 0572 document.insertText(selection.start, text); 0573 } 0574 document.editEnd(); 0575 if (newLineCount == oldLineCount) { 0576 if (document.lineLength(cursor.line) != oldCurrentLineLength) { 0577 cursor.column = document.lastColumn(cursor.line) + 1; 0578 } 0579 view.setCursorPosition(cursor); 0580 } 0581 } 0582 0583 function filter(func) 0584 { 0585 each(function(lines) { return lines.filter(__toFunc(func, 'line')); }); 0586 } 0587 0588 function map(func) 0589 { 0590 each(function(lines) { return lines.map(__toFunc(func, 'line')); }); 0591 } 0592 0593 /* 0594 natcompare.js -- Perform 'natural order' comparisons of strings in JavaScript. 0595 Copyright (C) 2005 by SCK-CEN (Belgian Nucleair Research Centre) 0596 Written by Kristof Coomans <kristof[dot]coomans[at]sckcen[dot]be> 0597 0598 Based on the Java version by Pierre-Luc Paour, of which this is more or less a straight conversion. 0599 Copyright (C) 2003 by Pierre-Luc Paour <natorder@paour.com> 0600 0601 The Java version was based on the C version by Martin Pool. 0602 Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au> 0603 0604 This software is provided 'as-is', without any express or implied 0605 warranty. In no event will the authors be held liable for any damages 0606 arising from the use of this software. 0607 0608 Permission is granted to anyone to use this software for any purpose, 0609 including commercial applications, and to alter it and redistribute it 0610 freely, subject to the following restrictions: 0611 0612 1. The origin of this software must not be misrepresented; you must not 0613 claim that you wrote the original software. If you use this software 0614 in a product, an acknowledgment in the product documentation would be 0615 appreciated but is not required. 0616 2. Altered source versions must be plainly marked as such, and must not be 0617 misrepresented as being the original software. 0618 3. This notice may not be removed or altered from any source distribution. 0619 */ 0620 0621 0622 function isWhitespaceChar(a) 0623 { 0624 var charCode; 0625 charCode = a.charCodeAt(0); 0626 0627 if ( charCode <= 32 ) 0628 { 0629 return true; 0630 } 0631 else 0632 { 0633 return false; 0634 } 0635 } 0636 0637 function isDigitChar(a) 0638 { 0639 var charCode; 0640 charCode = a.charCodeAt(0); 0641 0642 if ( charCode >= 48 && charCode <= 57 ) 0643 { 0644 return true; 0645 } 0646 else 0647 { 0648 return false; 0649 } 0650 } 0651 0652 function compareRight(a,b) 0653 { 0654 var bias = 0; 0655 var ia = 0; 0656 var ib = 0; 0657 0658 var ca; 0659 var cb; 0660 0661 // The longest run of digits wins. That aside, the greatest 0662 // value wins, but we can't know that it will until we've scanned 0663 // both numbers to know that they have the same magnitude, so we 0664 // remember it in BIAS. 0665 for (;; ia++, ib++) { 0666 ca = a.charAt(ia); 0667 cb = b.charAt(ib); 0668 0669 if (!isDigitChar(ca) 0670 && !isDigitChar(cb)) { 0671 return bias; 0672 } else if (!isDigitChar(ca)) { 0673 return -1; 0674 } else if (!isDigitChar(cb)) { 0675 return +1; 0676 } else if (ca < cb) { 0677 if (bias == 0) { 0678 bias = -1; 0679 } 0680 } else if (ca > cb) { 0681 if (bias == 0) 0682 bias = +1; 0683 } else if (ca == 0 && cb == 0) { 0684 return bias; 0685 } 0686 } 0687 } 0688 0689 function natcompare(a,b) { 0690 0691 var ia = 0, ib = 0; 0692 var nza = 0, nzb = 0; 0693 var ca, cb; 0694 var result; 0695 0696 while (true) 0697 { 0698 // only count the number of zeroes leading the last number compared 0699 nza = nzb = 0; 0700 0701 ca = a.charAt(ia); 0702 cb = b.charAt(ib); 0703 0704 // skip over leading spaces or zeros 0705 while ( isWhitespaceChar( ca ) || ca =='0' ) { 0706 if (ca == '0') { 0707 nza++; 0708 } else { 0709 // only count consecutive zeroes 0710 nza = 0; 0711 } 0712 0713 ca = a.charAt(++ia); 0714 } 0715 0716 while ( isWhitespaceChar( cb ) || cb == '0') { 0717 if (cb == '0') { 0718 nzb++; 0719 } else { 0720 // only count consecutive zeroes 0721 nzb = 0; 0722 } 0723 0724 cb = b.charAt(++ib); 0725 } 0726 0727 // process run of digits 0728 if (isDigitChar(ca) && isDigitChar(cb)) { 0729 if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) { 0730 return result; 0731 } 0732 } 0733 0734 if (ca == 0 && cb == 0) { 0735 // The strings compare the same. Perhaps the caller 0736 // will want to call strcmp to break the tie. 0737 return nza - nzb; 0738 } 0739 0740 if (ca < cb) { 0741 return -1; 0742 } else if (ca > cb) { 0743 return +1; 0744 } 0745 0746 ++ia; ++ib; 0747 } 0748 } 0749 0750 // kate: space-indent on; indent-width 4; replace-tabs on;