mirror of https://github.com/buggins/dlangide.git
Initial implementation of "Go to definition".
Uses DCD to get location. See issue #5
This commit is contained in:
parent
4ed1d85dab
commit
d766508c99
|
@ -0,0 +1,22 @@
|
|||
module dlangide.tools.editorTool;
|
||||
|
||||
|
||||
|
||||
import dlangui.widgets.editors;
|
||||
import dlangui.core.types;
|
||||
import dlangide.ui.frame;
|
||||
import dlangide.ui.dsourceedit;
|
||||
|
||||
public import dlangide.tools.d.editorTool;
|
||||
|
||||
class EditorTool
|
||||
{
|
||||
this(IDEFrame frame) {
|
||||
_frame = frame;
|
||||
}
|
||||
//Since files might be unsaved, we must send all the text content.
|
||||
abstract bool goToDefinition(DSourceEdit content, TextPosition caretPosition);
|
||||
|
||||
protected IDEFrame _frame;
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
module dlangide.tools.d.DCDInterface;
|
||||
|
||||
import dlangide.builders.extprocess;
|
||||
|
||||
//Interface to DCD
|
||||
//TODO: Check if server is running, start server if needed etc.
|
||||
class DCDInterface {
|
||||
ExternalProcess dcdProcess;
|
||||
this() {
|
||||
dcdProcess = new ExternalProcess();
|
||||
}
|
||||
bool execute(char[][] arguments ,ref dstring output) {
|
||||
ProtectedTextStorage stdoutTarget = new ProtectedTextStorage();
|
||||
ExternalProcess dcdProcess = new ExternalProcess();
|
||||
//TODO: Working Directory, where is that?
|
||||
dcdProcess.run("dcd-client".dup, arguments, "/usr/bin".dup, stdoutTarget);
|
||||
while(dcdProcess.poll() == ExternalProcessState.Running){ }
|
||||
output = stdoutTarget.readText();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
module dlangide.tools.d.editorTool;
|
||||
|
||||
import dlangide.tools.editorTool;
|
||||
import dlangide.tools.d.DCDInterface;
|
||||
import dlangide.ui.dsourceedit;
|
||||
import dlangui.widgets.editors;
|
||||
import dlangide.ui.frame;
|
||||
import std.stdio;
|
||||
import std.string;
|
||||
import dlangui.core.logger;
|
||||
|
||||
import std.conv;
|
||||
|
||||
class DEditorTool : EditorTool
|
||||
{
|
||||
|
||||
|
||||
this(IDEFrame frame) {
|
||||
_dcd = new DCDInterface();
|
||||
super(frame);
|
||||
}
|
||||
|
||||
override bool goToDefinition(DSourceEdit editor, TextPosition caretPosition) {
|
||||
|
||||
|
||||
auto content = editor.text();
|
||||
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
|
||||
|
||||
char[][] arguments = ["-l".dup, "-c".dup];
|
||||
arguments ~= [to!(char[])(byteOffset)];
|
||||
arguments ~= [to!(char[])(editor.projectSourceFile.filename())];
|
||||
|
||||
dstring output;
|
||||
_dcd.execute(arguments, output);
|
||||
|
||||
string[] outputLines = to!string(output).splitLines();
|
||||
Log.d("DCD:", outputLines);
|
||||
|
||||
foreach(string outputLine ; outputLines) {
|
||||
if(outputLine.indexOf("Not Found".dup) == -1) {
|
||||
auto split = outputLine.indexOf("\t");
|
||||
if(split == -1) {
|
||||
Log.d("DCD output format error.");
|
||||
break;
|
||||
}
|
||||
if(indexOf(outputLine[0 .. split],"stdin".dup) != -1) {
|
||||
Log.d("Declaration is in current file. Can jump to it.");
|
||||
auto target = to!int(outputLine[split+1 .. $]);
|
||||
auto destPos = byteOffsetToCaret(content, target);
|
||||
editor.setCaretPos(destPos.line,destPos.pos);
|
||||
}
|
||||
else {
|
||||
auto filename = outputLine[0 .. split];
|
||||
if(_frame !is null) {
|
||||
writeln("Well I'm trying");
|
||||
_frame.openSourceFile(filename);
|
||||
auto target = to!int(outputLine[split+1 .. $]);
|
||||
auto destPos = byteOffsetToCaret(_frame.currentEditor.text(), target);
|
||||
|
||||
_frame.currentEditor.setCaretPos(destPos.line,destPos.pos);
|
||||
writeln("Well I tried");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
DCDInterface _dcd;
|
||||
|
||||
int caretPositionToByteOffset(dstring content, TextPosition caretPosition) {
|
||||
auto line = 0;
|
||||
auto pos = 0;
|
||||
auto bytes = 0;
|
||||
foreach(c; content) {
|
||||
bytes++;
|
||||
if(c == '\n') {
|
||||
line++;
|
||||
}
|
||||
if(line == caretPosition.line) {
|
||||
if(pos == caretPosition.pos)
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
TextPosition byteOffsetToCaret(dstring content, int byteOffset) {
|
||||
int bytes = 0;
|
||||
int line = 0;
|
||||
int pos = 0;
|
||||
TextPosition textPos;
|
||||
foreach(c; content) {
|
||||
if(bytes == byteOffset) {
|
||||
//We all good.
|
||||
textPos.line = line;
|
||||
textPos.pos = pos;
|
||||
return textPos;
|
||||
}
|
||||
bytes++;
|
||||
if(c == '\n')
|
||||
{
|
||||
line++;
|
||||
pos = 0;
|
||||
}
|
||||
else {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
return textPos;
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@ enum IDEActions : int {
|
|||
ProjectFolderRemoveItem,
|
||||
ProjectFolderOpenItem,
|
||||
ProjectFolderRenameItem,
|
||||
GoToDefinition,
|
||||
}
|
||||
|
||||
const Action ACTION_PROJECT_FOLDER_ADD_ITEM = new Action(IDEActions.ProjectFolderAddItem, "MENU_PROJECT_FOLDER_ADD_ITEM"c);
|
||||
|
@ -85,3 +86,4 @@ const Action ACTION_HELP_ABOUT = new Action(IDEActions.HelpAbout, "MENU_HELP_ABO
|
|||
const Action ACTION_WINDOW_CLOSE_ALL_DOCUMENTS = new Action(IDEActions.WindowCloseAllDocuments, "MENU_WINDOW_CLOSE_ALL_DOCUMENTS"c);
|
||||
const Action ACTION_CREATE_NEW_WORKSPACE = new Action(IDEActions.CreateNewWorkspace, "Create new workspace"d);
|
||||
const Action ACTION_ADD_TO_CURRENT_WORKSPACE = new Action(IDEActions.AddToCurrentWorkspace, "Add to current workspace"d);
|
||||
const Action ACTION_GO_TO_DEFINITION = new Action(IDEActions.GoToDefinition, "GO_TO_DEFINITION"c, "edit-cut"c, KeyCode.KEY_G, KeyFlag.Control);
|
|
@ -86,6 +86,11 @@ class DSourceEdit : SourceEdit {
|
|||
return super.handleAction(a);
|
||||
}
|
||||
|
||||
TextPosition getCaretPosition() {
|
||||
return _caretPos;
|
||||
}
|
||||
|
||||
|
||||
/// change caret position and ensure it is visible
|
||||
void setCaretPos(int line, int column)
|
||||
{
|
||||
|
@ -245,7 +250,7 @@ class SimpleDSyntaxHighlighter : SyntaxHighlighter {
|
|||
for (;;) {
|
||||
ch = nextBracket(dir, p);
|
||||
if (!ch) // no more brackets
|
||||
return startPos;
|
||||
break;
|
||||
auto match = _bracketStack.process(ch);
|
||||
if (match == BracketMatch.FOUND)
|
||||
return p;
|
||||
|
|
|
@ -22,6 +22,7 @@ import dlangide.ui.homescreen;
|
|||
import dlangide.workspace.workspace;
|
||||
import dlangide.workspace.project;
|
||||
import dlangide.builders.builder;
|
||||
import dlangide.tools.editorTool;
|
||||
|
||||
import std.conv;
|
||||
import std.utf;
|
||||
|
@ -60,6 +61,7 @@ class IDEFrame : AppFrame {
|
|||
OutputPanel _logPanel;
|
||||
DockHost _dockHost;
|
||||
TabWidget _tabs;
|
||||
EditorTool _editorTool;
|
||||
|
||||
dstring frameWindowCaptionSuffix = "DLangIDE"d;
|
||||
|
||||
|
@ -69,6 +71,7 @@ class IDEFrame : AppFrame {
|
|||
}
|
||||
|
||||
override protected void init() {
|
||||
_editorTool = new DEditorTool(this);
|
||||
super.init();
|
||||
}
|
||||
|
||||
|
@ -378,6 +381,8 @@ class IDEFrame : AppFrame {
|
|||
tb.addControl(cbBuildConfiguration);
|
||||
tb.addButtons(ACTION_PROJECT_BUILD);
|
||||
|
||||
tb.addButtons(ACTION_GO_TO_DEFINITION);
|
||||
|
||||
tb = res.getOrAddToolbar("Edit");
|
||||
tb.addButtons(ACTION_EDIT_COPY, ACTION_EDIT_PASTE, ACTION_EDIT_CUT, ACTION_SEPARATOR,
|
||||
ACTION_EDIT_UNDO, ACTION_EDIT_REDO, ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT);
|
||||
|
@ -507,6 +512,10 @@ class IDEFrame : AppFrame {
|
|||
};
|
||||
dlg.show();
|
||||
return true;
|
||||
case IDEActions.GoToDefinition:
|
||||
Log.i("Trying to go to definition");
|
||||
_editorTool.goToDefinition(currentEditor(), currentEditor.getCaretPosition());
|
||||
return true;
|
||||
default:
|
||||
return super.handleAction(a);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ MENU_WINDOW_CLOSE_ALL_DOCUMENTS=Close All Documents
|
|||
MENU_HELP=&HELP
|
||||
MENU_HELP_VIEW_HELP=&View help
|
||||
MENU_HELP_ABOUT=&About
|
||||
GO_TO_DEFINITION=Go To Definition
|
||||
|
||||
TAB_LONG_LIST=Long list
|
||||
TAB_BUTTONS=Buttons
|
||||
|
|
Loading…
Reference in New Issue