DCD support improvements

This commit is contained in:
Vadim Lopatin 2015-02-17 16:01:12 +03:00
parent 0ae570dd26
commit 115e20ba79
8 changed files with 87 additions and 43 deletions

View File

@ -11,7 +11,7 @@
"stringImportPaths": ["views", "views/res", "views/res/i18n", "views/res/mdpi"],
"copyFiles-windows": ["lib/win32/FreeImage.dll", "lib/win32/SDL2.dll", "lib/win32/dcd-server.exe"],
"copyFiles-windows": ["lib/win32/FreeImage.dll", "lib/win32/SDL2.dll", "lib/win32/dcd-server.exe", "lib/win32/dcd-client.exe"],
"dependencies": {
"dlangui": "~master"

View File

@ -400,12 +400,13 @@ class ExternalProcess {
return _state;
}
void write(dstring data) {
void write(string data) {
if(_state == ExternalProcessState.Error || _state == ExternalProcessState.None || _state == ExternalProcessState.Stopped) {
return;
}
else {
_pipes.stdin.write(data);
Log.d("writing ", data.length, " characters to stdin");
_pipes.stdin.write("", data);
_pipes.stdin.close();
}
}

View File

@ -34,7 +34,20 @@ class DCDInterface {
//stdoutTarget = new ProtectedTextStorage();
}
protected dstring[] invokeDcd(string[] arguments, dstring content, out bool success) {
protected string dumpContext(string content, int pos) {
if (pos >= 0 && pos <= content.length) {
int start = pos;
int end = pos;
for (int i = 0; start > 0 && content[start - 1] != '\n' && i < 10; i++)
start--;
for (int i = 0; end < content.length - 1 && content[end] != '\n' && i < 10; i++)
end++;
return content[start .. pos] ~ "|" ~ content[pos .. end];
}
return "";
}
protected dstring[] invokeDcd(string[] arguments, string content, out bool success) {
success = false;
ExternalProcess dcdProcess = new ExternalProcess();
@ -48,6 +61,7 @@ class DCDInterface {
string dcd_client_dir = "/usr/bin";
}
dcdProcess.run(dcd_client_name, arguments, dcd_client_dir, stdoutTarget);
dcdProcess.write(content);
dcdProcess.wait();
@ -59,14 +73,16 @@ class DCDInterface {
return output;
}
ResultSet goToDefinition(in string[] importPaths, in dstring content, int index) {
ResultSet goToDefinition(in string[] importPaths, in string content, int index) {
ResultSet result;
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
string[] arguments = ["-l", "-c"];
arguments ~= [to!string(index)];
foreach(p; importPaths) {
arguments ~= "-I";
arguments ~= p;
arguments ~= "-I" ~ p;
}
if (_port != DCD_DEFAULT_PORT)
arguments ~= "-p" ~ to!string(_port);
@ -84,25 +100,31 @@ class DCDInterface {
debug(DCD) Log.d("DCD output:\n", output);
if(output.length > 0) {
if(output[0].indexOf("Not Found".dup) == 0) {
dstring firstLine = output[0];
if(firstLine.startsWith("Not Found") || firstLine.startsWith("Not found")) {
result.result = DCDResult.NO_RESULT;
return result;
}
}
auto split = firstLine.indexOf("\t");
if(split == -1) {
Log.d("DCD output format error.");
result.result = DCDResult.FAIL;
return result;
}
auto split = output[0].indexOf("\t");
if(split == -1) {
Log.d("DCD output format error.");
result.result = DCDResult.FAIL;
return result;
result.output ~= output[0][0 .. split];
result.output ~= output[0][split+1 .. $];
} else {
result.result = DCDResult.NO_RESULT;
//result.result = DCDResult.FAIL;
}
result.output ~= output[0][0 .. split];
result.output ~= output[0][split+1 .. $];
return result;
}
ResultSet getCompletions(in string[] importPaths, in dstring content, int index) {
ResultSet getCompletions(in string[] importPaths, in string content, int index) {
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
ResultSet result;
@ -110,8 +132,7 @@ class DCDInterface {
arguments ~= [to!string(index)];
foreach(p; importPaths) {
arguments ~= "-I";
arguments ~= p;
arguments ~= "-I" ~ p;
}
if (_port != DCD_DEFAULT_PORT)
arguments ~= "-p" ~ to!string(_port);

View File

@ -48,11 +48,8 @@ class DCDServer {
string[] srcPaths = dmdSourcePaths();
string[] arguments;
arguments ~= ("-p" ~ to!string(_port));
foreach(p; srcPaths) {
arguments ~= "-I";
arguments ~= p;
}
foreach(p; srcPaths)
arguments ~= "-I" ~ p;
if (_port != DCD_DEFAULT_PORT)
arguments ~= "-p" ~ to!string(_port);
Log.i("starting dcd-server: executable path is ", dcdServerExecutable, " args: ", arguments);
@ -73,17 +70,18 @@ class DCDServer {
_running = true;
return true;
}
/// stop DCD server
bool stop() {
if (!dcdProcess) {
Log.e("Cannot stop DCD - it's not started");
Log.e("Cannot stop DCD server - it's not started");
return false;
}
Log.i("Current DCD state: ", dcdProcess.poll());
Log.i("Killing DCD server");
debug(DCD) Log.i("Current DCD server state: ", dcdProcess.poll());
Log.i("Stopping DCD server");
ExternalProcessState state = dcdProcess.kill();
state = dcdProcess.wait();
Log.i("DCD state: ", state);
debug(DCD) Log.i("DCD server state: ", state);
destroy(dcdProcess);
dcdProcess = null;
stdoutTarget = null;

View File

@ -7,6 +7,7 @@ import dlangui.widgets.editors;
import dlangide.ui.frame;
import std.stdio;
import std.string;
import std.utf;
import dlangui.core.logger;
import std.conv;
@ -25,8 +26,9 @@ class DEditorTool : EditorTool
override bool goToDefinition(DSourceEdit editor, TextPosition caretPosition) {
string[] importPaths = editor.importPaths();
auto byteOffset = caretPositionToByteOffset(editor.text, caretPosition);
ResultSet output = _dcd.goToDefinition(importPaths, editor.text, byteOffset);
string content = toUTF8(editor.text);
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
ResultSet output = _dcd.goToDefinition(importPaths, content, byteOffset);
switch(output.result) {
@ -39,13 +41,15 @@ class DEditorTool : EditorTool
auto target = to!int(output.output[1]);
if(output.output[0].indexOf("stdin".dup) != -1) {
Log.d("Declaration is in current file. Jumping to it.");
auto destPos = byteOffsetToCaret(editor.text, target);
auto destPos = byteOffsetToCaret(content, target);
editor.setCaretPos(destPos.line,destPos.pos);
}
else {
//Must open file first to get the content for finding the correct caret position.
_frame.openSourceFile(to!string(output.output[0]));
auto destPos = byteOffsetToCaret(_frame.currentEditor.text(), target);
string txt;
txt = toUTF8(_frame.currentEditor.text);
auto destPos = byteOffsetToCaret(txt, target);
_frame.currentEditor.setCaretPos(destPos.line,destPos.pos);
}
return true;
@ -57,8 +61,9 @@ class DEditorTool : EditorTool
override dstring[] getCompletions(DSourceEdit editor, TextPosition caretPosition) {
string[] importPaths = editor.importPaths();
auto byteOffset = caretPositionToByteOffset(editor.text, caretPosition);
ResultSet output = _dcd.getCompletions(importPaths, editor.text, byteOffset);
string content = toUTF8(editor.text);
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
ResultSet output = _dcd.getCompletions(importPaths, content, byteOffset);
switch(output.result) {
//TODO: Show dialog
case DCDResult.FAIL:
@ -73,8 +78,7 @@ class DEditorTool : EditorTool
private:
DCDInterface _dcd;
// TODO: non-ascii characters support
int caretPositionToByteOffset(dstring content, TextPosition caretPosition) {
int caretPositionToByteOffset(string content, TextPosition caretPosition) {
auto line = 0;
auto pos = 0;
auto bytes = 0;
@ -92,7 +96,7 @@ private:
return bytes;
}
TextPosition byteOffsetToCaret(dstring content, int byteOffset) {
TextPosition byteOffsetToCaret(string content, int byteOffset) {
int bytes = 0;
int line = 0;
int pos = 0;

View File

@ -97,5 +97,5 @@ const Action ACTION_WINDOW_CLOSE_ALL_DOCUMENTS = new Action(IDEActions.WindowClo
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, ""c, KeyCode.KEY_G, KeyFlag.Control);
const Action ACTION_GET_COMPLETIONS = new Action(IDEActions.GetCompletionSuggestions, "SHOW_COMPLETIONS"c, ""c, KeyCode.KEY_G, KeyFlag.Control|KeyFlag.Shift);
const Action ACTION_GO_TO_DEFINITION = (new Action(IDEActions.GoToDefinition, "GO_TO_DEFINITION"c, ""c, KeyCode.KEY_G, KeyFlag.Control)).addAccelerator(KeyCode.F12, 0).disableByDefault();
const Action ACTION_GET_COMPLETIONS = (new Action(IDEActions.GetCompletionSuggestions, "SHOW_COMPLETIONS"c, ""c, KeyCode.KEY_G, KeyFlag.Control|KeyFlag.Shift)).addAccelerator(KeyCode.SPACE, KeyFlag.Control).disableByDefault();

View File

@ -32,7 +32,8 @@ class DSourceEdit : SourceEdit {
setTokenHightlightColor(TokenCategory.Comment_Documentation, 0x206000);
//setTokenHightlightColor(TokenCategory.Identifier, 0x206000); // no colors
MenuItem editPopupItem = new MenuItem(null);
editPopupItem.add(ACTION_EDIT_COPY, ACTION_EDIT_PASTE, ACTION_EDIT_CUT, ACTION_EDIT_UNDO, ACTION_EDIT_REDO, ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT, ACTION_EDIT_TOGGLE_LINE_COMMENT, ACTION_GET_COMPLETIONS);
editPopupItem.add(ACTION_EDIT_COPY, ACTION_EDIT_PASTE, ACTION_EDIT_CUT, ACTION_EDIT_UNDO, ACTION_EDIT_REDO, ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT, ACTION_EDIT_TOGGLE_LINE_COMMENT, ACTION_GET_COMPLETIONS, ACTION_GO_TO_DEFINITION);
//ACTION_GO_TO_DEFINITION, ACTION_GET_COMPLETIONS
popupMenu = editPopupItem;
showIcons = true;
showFolding = true;
@ -50,8 +51,12 @@ class DSourceEdit : SourceEdit {
return res;
}
@property bool isDSourceFile() {
return filename.endsWith(".d") || filename.endsWith(".dd") || filename.endsWith(".dh") || filename.endsWith(".ddoc");
}
void setHighlighter() {
if (filename.endsWith(".d") || filename.endsWith(".dd") || filename.endsWith(".dh") || filename.endsWith(".ddoc")) {
if (isDSourceFile) {
content.syntaxHighlighter = new SimpleDSyntaxHighlighter(filename);
} else {
content.syntaxHighlighter = null;
@ -61,7 +66,7 @@ class DSourceEdit : SourceEdit {
/// returns project import paths - if file from project is opened in current editor
string[] importPaths() {
if (_projectSourceFile)
return _projectSourceFile.project.sourcePaths;
return _projectSourceFile.project.sourcePaths ~ _projectSourceFile.project.builderSourcePaths;
return null;
}
@ -100,6 +105,21 @@ class DSourceEdit : SourceEdit {
return super.handleAction(a);
}
/// override to handle specific actions state (e.g. change enabled state for supported actions)
override bool handleActionStateRequest(const Action a) {
switch (a.id) {
case IDEActions.GoToDefinition:
case IDEActions.GetCompletionSuggestions:
if (isDSourceFile)
a.state = ACTION_STATE_ENABLED;
else
a.state = ACTION_STATE_DISABLE;
return true;
default:
return super.handleActionStateRequest(a);
}
}
void showCompletionPopup(dstring[] suggestions) {
if(suggestions.length == 0) {

View File

@ -352,7 +352,7 @@ class IDEFrame : AppFrame {
editItem.add(ACTION_EDIT_COPY, ACTION_EDIT_PASTE,
ACTION_EDIT_CUT, ACTION_EDIT_UNDO, ACTION_EDIT_REDO);
MenuItem editItemAdvanced = new MenuItem(new Action(221, "MENU_EDIT_ADVANCED"));
editItemAdvanced.add(ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT, ACTION_EDIT_TOGGLE_LINE_COMMENT, ACTION_EDIT_TOGGLE_BLOCK_COMMENT);
editItemAdvanced.add(ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT, ACTION_EDIT_TOGGLE_LINE_COMMENT, ACTION_EDIT_TOGGLE_BLOCK_COMMENT, ACTION_GO_TO_DEFINITION, ACTION_GET_COMPLETIONS);
editItem.add(editItemAdvanced);
editItem.add(ACTION_EDIT_PREFERENCES);