1 module dlangide.tools.d.deditorTool; 2 3 import dlangide.tools.editorTool; 4 import dlangide.tools.d.dcdinterface; 5 import dlangide.ui.dsourceedit; 6 import dlangui.widgets.editors; 7 import dlangide.ui.frame; 8 import std.stdio; 9 import std.string; 10 import std.utf; 11 import dlangui.core.logger; 12 13 import std.conv; 14 15 // TODO: async operation in background thread 16 // TODO: effective caretPositionToByteOffset/byteOffsetToCaret impl 17 18 class DEditorTool : EditorTool 19 { 20 21 22 this(IDEFrame frame) { 23 _dcd = new DCDInterface(DCD_SERVER_PORT_FOR_DLANGIDE); 24 super(frame); 25 } 26 27 override bool goToDefinition(DSourceEdit editor, TextPosition caretPosition) { 28 string[] importPaths = editor.importPaths(); 29 string content = toUTF8(editor.text); 30 auto byteOffset = caretPositionToByteOffset(content, caretPosition); 31 ResultSet output = _dcd.goToDefinition(importPaths, editor.filename, content, byteOffset); 32 33 34 switch(output.result) { 35 //TODO: Show dialog 36 case DCDResult.FAIL: 37 case DCDResult.DCD_NOT_RUNNING: 38 case DCDResult.NO_RESULT: 39 editor.setFocus(); 40 return false; 41 case DCDResult.SUCCESS: 42 auto target = to!int(output.output[1]); 43 if(output.output[0].indexOf("stdin".dup) != -1) { 44 Log.d("Declaration is in current file. Jumping to it."); 45 auto destPos = byteOffsetToCaret(content, target); 46 editor.setCaretPos(destPos.line,destPos.pos); 47 editor.setFocus(); 48 } 49 else { 50 //Must open file first to get the content for finding the correct caret position. 51 _frame.openSourceFile(to!string(output.output[0])); 52 string txt; 53 txt = toUTF8(_frame.currentEditor.text); 54 auto destPos = byteOffsetToCaret(txt, target); 55 _frame.currentEditor.setCaretPos(destPos.line,destPos.pos); 56 _frame.currentEditor.setFocus(); 57 } 58 return true; 59 default: 60 return false; 61 } 62 } 63 64 override dstring[] getCompletions(DSourceEdit editor, TextPosition caretPosition) { 65 string[] importPaths = editor.importPaths(); 66 67 string content = toUTF8(editor.text); 68 auto byteOffset = caretPositionToByteOffset(content, caretPosition); 69 ResultSet output = _dcd.getCompletions(importPaths, editor.filename, content, byteOffset); 70 switch(output.result) { 71 //TODO: Show dialog 72 case DCDResult.FAIL: 73 case DCDResult.DCD_NOT_RUNNING: 74 case DCDResult.NO_RESULT: 75 case DCDResult.SUCCESS: 76 default: 77 return output.output; 78 } 79 } 80 81 private: 82 DCDInterface _dcd; 83 84 int caretPositionToByteOffset(string content, TextPosition caretPosition) { 85 auto line = 0; 86 auto pos = 0; 87 auto bytes = 0; 88 foreach(c; content) { 89 bytes++; 90 if(c == '\n') { 91 line++; 92 } 93 if(line == caretPosition.line) { 94 if(pos == caretPosition.pos) 95 break; 96 pos++; 97 } 98 } 99 return bytes; 100 } 101 102 TextPosition byteOffsetToCaret(string content, int byteOffset) { 103 int bytes = 0; 104 int line = 0; 105 int pos = 0; 106 TextPosition textPos; 107 foreach(c; content) { 108 if(bytes == byteOffset) { 109 //We all good. 110 textPos.line = line; 111 textPos.pos = pos; 112 return textPos; 113 } 114 bytes++; 115 if(c == '\n') 116 { 117 line++; 118 pos = 0; 119 } 120 else { 121 pos++; 122 } 123 } 124 return textPos; 125 } 126 }