File indexing completed on 2024-12-29 03:43:58
0001 // Utility functions 0002 // distance - Like cursor, only absolute 0003 // interval - Like range, only absolute 0004 distanceFromCursor = function(cursor) { 0005 var pos = cursor.column; 0006 var a; 0007 for (a = 0; a < cursor.line; a++) { 0008 pos += document.lineLength(a) + 1; //Kate normalizes newlines to \n 0009 } 0010 return pos; 0011 } 0012 0013 intervalFromRange = function(range) { 0014 return { 0015 start: distanceFromCursor(range.start), 0016 end: distanceFromCursor(range.end) 0017 } 0018 } 0019 0020 cursorFromDistance = function(distance) { 0021 var line = 0; 0022 var positionSoFar = 0; 0023 while (positionSoFar + (document.lineLength(line) + 1) <= distance) { 0024 positionSoFar += (document.lineLength(line) + 1) 0025 line++; 0026 } 0027 return new Cursor(line, distance - positionSoFar); 0028 0029 } 0030 0031 rangeFromIntervals = function(distance1, distance2) { 0032 return new Range( cursorFromDistance(distance1), cursorFromDistance(distance2) ); 0033 } 0034 0035 // Pseudo editor interface 0036 var zen_editor = function(document, view) { 0037 this.context = document; 0038 0039 this.setContext = function(document) { 0040 this.context = document; 0041 } 0042 0043 0044 /** 0045 * Returns character indexes of selected text: object with <code>start</code> 0046 * and <code>end</code> properties. If there's no selection, should return 0047 * object with <code>start</code> and <code>end</code> properties referring 0048 * to current caret position 0049 * @return {Object} 0050 * @example 0051 * var selection = editor.getSelectionRange(); 0052 * alert(selection.start + ', ' + selection.end); 0053 */ 0054 this.getSelectionRange = function() { 0055 var returnValue 0056 if (view.hasSelection()) { 0057 returnValue = intervalFromRange(view.selection()); 0058 } 0059 else { 0060 returnValue = intervalFromRange(new Range(view.cursorPosition(), view.cursorPosition())); 0061 } 0062 return returnValue; 0063 } 0064 0065 /** 0066 * Creates selection from <code>start</code> to <code>end</code> character 0067 * indexes. If <code>end</code> is ommited, this method should place caret 0068 * and <code>start</code> index 0069 * @param {Number} start 0070 * @param {Number} [end] 0071 * @example 0072 * editor.createSelection(10, 40); 0073 * 0074 * //move caret to 15th character 0075 * editor.createSelection(15); 0076 */ 0077 this.createSelection = function(start, end) { 0078 var selection = rangeFromIntervals(start, end); 0079 view.setSelection(selection); 0080 view.setCursorPosition(cursorFromDistance(end)); 0081 } 0082 0083 /** 0084 * Returns current line's start and end indexes as object with <code>start</code> 0085 * and <code>end</code> properties 0086 * @return {Object} 0087 * @example 0088 * var range = editor.getCurrentLineRange(); 0089 * alert(range.start + ', ' + range.end); 0090 */ 0091 this.getCurrentLineRange = function() { 0092 var position = view.cursorPosition() 0093 return { 0094 start: distanceFromCursor(new Cursor(position.line, 0)), 0095 end: distanceFromCursor(new Cursor(position.line,document.lineLength(position.line))) 0096 }; 0097 } 0098 0099 /** 0100 * Returns current caret position 0101 * @return {Number|null} 0102 */ 0103 this.getCaretPos = function(){ 0104 return distanceFromCursor(view.cursorPosition()); 0105 } 0106 0107 /** 0108 * Set new caret position 0109 * @param {Number} pos Caret position 0110 */ 0111 this.setCaretPos = function(pos){ 0112 view.setCursorPosition(cursorFromDistance(pos)); 0113 } 0114 0115 /** 0116 * Returns content of current line 0117 * @return {String} 0118 */ 0119 this.getCurrentLine = function() { 0120 return document.line(view.cursorPosition().line); 0121 } 0122 0123 /** 0124 * Replace editor's content or it's part (from <code>start</code> to 0125 * <code>end</code> index). If <code>value</code> contains 0126 * <code>caret_placeholder</code>, the editor will put caret into 0127 * this position. If you skip <code>start</code> and <code>end</code> 0128 * arguments, the whole target's content will be replaced with 0129 * <code>value</code>. 0130 * 0131 * If you pass <code>start</code> argument only, 0132 * the <code>value</code> will be placed at <code>start</code> string 0133 * index of current content. 0134 * 0135 * If you pass <code>start</code> and <code>end</code> arguments, 0136 * the corresponding substring of current target's content will be 0137 * replaced with <code>value</code>. 0138 * @param {String} value Content you want to paste 0139 * @param {Number} [start] Start index of editor's content 0140 * @param {Number} [end] End index of editor's content 0141 * @param {Boolean} [no_indent] Do not auto indent <code>value</code> 0142 */ 0143 this.replaceContent = function(value, start, end, no_indent) { 0144 //handle the no indent parameter 0145 if (!no_indent) { 0146 var utils = emmet.require('utils'); 0147 value = utils.padString(value, utils.getLinePadding(this.getCurrentLine())); 0148 } 0149 0150 //emmet's tabstops - TODO: what would be the best way to support this in Kate? 0151 var tabstopData = emmet.require('tabStops').extract(value, { 0152 escape: function(ch) { 0153 return ch; 0154 } 0155 }); 0156 value = tabstopData.text; 0157 var firstTabStop = tabstopData.tabstops[0]; 0158 0159 if (typeof(end) == 'undefined') { 0160 if (typeof(start) == 'undefined') { 0161 document.setText(value); 0162 } else { 0163 document.insertText(cursorFromDistance(start), value); 0164 } 0165 } else { 0166 document.editBegin(); //group changes together in undo history 0167 var docRange = rangeFromIntervals(start, end); 0168 document.removeText(docRange); 0169 document.insertText(docRange.start, value); 0170 document.editEnd(); 0171 } 0172 if (firstTabStop) this.setCaretPos(start + firstTabStop.start); 0173 } 0174 0175 /** 0176 * Returns editor's content 0177 * @return {String} 0178 */ 0179 this.getContent = function(){ 0180 return document.text(); 0181 } 0182 0183 /** 0184 * Returns current editor's syntax mode 0185 * @return {String} 0186 */ 0187 this.getSyntax = function(){ 0188 var syntax = document.highlightingModeAt(view.cursorPosition()).toLowerCase(); 0189 if (syntax == 'haml with ruby') syntax = 'haml'; //fixes a common syntax highlighting verbosity 0190 if (syntax == 'none') 0191 syntax = 'html'; 0192 return syntax; 0193 } 0194 0195 /** 0196 * Returns current output profile name (@see emmet#setupProfile) 0197 * @return {String} 0198 */ 0199 this.getProfileName = function() { 0200 var profile = this.getSyntax(); 0201 if (profile == 'html') { 0202 var htmlProfile = emmet.require('resources').getVariable('profile'); 0203 if (!htmlProfile) { 0204 htmlProfile = this.getContent().search(/<!DOCTYPE[^>]+XHTML/i) != -1 ? 'xhtml': 'html'; 0205 } 0206 profile = htmlProfile; 0207 } 0208 return profile; 0209 } 0210 0211 /** 0212 * Ask user to enter something 0213 * @param {String} title Dialog title 0214 * @return {String} Entered data 0215 * @since 0.65 0216 */ 0217 this.prompt = function(title) { 0218 return ''; 0219 } 0220 0221 /** 0222 * Returns current selection 0223 * @return {String} 0224 * @since 0.65 0225 */ 0226 this.getSelection = function() { 0227 return view.selectedText(); 0228 } 0229 0230 /** 0231 * Returns current editor's file path 0232 * @return {String} 0233 * @since 0.65 0234 */ 0235 this.getFilePath = function() { 0236 return document.url(); //or would document.fileName() be better? 0237 } 0238 0239 }