Skip to content

Commit

Permalink
Adds ability to run selected in the editor Q code on configured serve…
Browse files Browse the repository at this point in the history
…r(s) (a2ndrade#42)
  • Loading branch information
YuriyYatsyk authored and a2ndrade committed Aug 12, 2019
1 parent bfc6ac0 commit a6b584f
Show file tree
Hide file tree
Showing 21 changed files with 2,806 additions and 71 deletions.
17 changes: 17 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,20 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


------------------------------------------------------------------------------

With respect to the driver for interfacing Java with kdb+ via TPC/IP (c.java):

Copyright (c) 1998-2017 Kx Systems Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

34 changes: 18 additions & 16 deletions src/main/java/com/appian/intellij/k/KCompletionContributor.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,21 +123,22 @@ private static String getText(PsiElement element) {
/**
* Different types of completions
*/
private enum CompletionContributionType {/**
* Local variable completions
*/
LOCAL {
@Override
List<ItemPresentation> getCompletions(PsiElement element) {
String input = getText(element);
return PsiTreeUtil.findChildrenOfType(PsiTreeUtil.getContextOfType(element, KLambda.class), KAssignment.class)
.stream()
.map(KAssignment::getUserId)
.filter(id -> id.getName().contains(input))
.map(id -> suppressLocationString(id.getPresentation()))
.collect(Collectors.toList());
}
},
private enum CompletionContributionType {
/**
* Local variable completions
*/
LOCAL {
@Override
List<ItemPresentation> getCompletions(PsiElement element) {
String input = getText(element);
return PsiTreeUtil.findChildrenOfType(PsiTreeUtil.getContextOfType(element, KLambda.class), KAssignment.class)
.stream()
.map(KAssignment::getUserId)
.filter(id -> id.getName().contains(input))
.map(id -> suppressLocationString(id.getPresentation()))
.collect(Collectors.toList());
}
},
/**
* Lambda parameter completions
*/
Expand Down Expand Up @@ -228,7 +229,8 @@ LookupElement createLookupElement(ItemPresentation presentation) {
* @param input an element representing user input
* @return a list of presentations for completion suggestions of this type
*/
abstract List<ItemPresentation> getCompletions(PsiElement input);}
abstract List<ItemPresentation> getCompletions(PsiElement input);
}

/**
* @param presentation a presentation
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/appian/intellij/k/KIcons.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import com.intellij.icons.AllIcons;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.LayeredIcon;
import com.intellij.ui.RowIcon;

public final class KIcons {
Expand All @@ -15,5 +16,14 @@ public final class KIcons {
public static final Icon PUBLIC_VARIABLE = new RowIcon(AllIcons.Nodes.Variable, AllIcons.Nodes.C_public);
public static final Icon PRIVATE_VARIABLE = new RowIcon(AllIcons.Nodes.Variable, AllIcons.Nodes.C_private);

public static final Icon QSERVER;

static {
LayeredIcon icon = new LayeredIcon(2);
icon.setIcon(AllIcons.Webreferences.Server, 0, 0, 0);
icon.setIcon(FILE, 1, 6, 6);
QSERVER = icon;
}

public static final Icon SYSTEM_FUNCTION = FILE;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.appian.intellij.k.actions;

import static com.intellij.execution.ui.ConsoleViewContentType.ERROR_OUTPUT;

import java.util.ArrayList;

import org.jetbrains.annotations.Nullable;

import com.appian.intellij.k.KIcons;
import com.appian.intellij.k.settings.KServerDialog;
import com.appian.intellij.k.settings.KServerSpec;
import com.appian.intellij.k.settings.KSettings;
import com.appian.intellij.k.settings.KSettingsService;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ValidationInfo;

/**
* An action that runs selected code in the editor on the specified
* server or prompts for a new server if none was provided.
* A new console named after chosen server will be open and
* re-used for subsequent commands sent to the same server.
* Q code is mirrored in the console, results and errors
* are output into the console too.
*/
public class KRunSelectionAction extends AnAction {
private final Project project;
@Nullable
private final KServerSpec spec;

KRunSelectionAction(
Project project, @Nullable String text, @Nullable KServerSpec spec) {
super(text, null, spec == null ? null : KIcons.QSERVER);
this.project = project;
this.spec = spec;
}

@Override
public void actionPerformed(AnActionEvent e) {
Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
if (editor == null) {
return;
}
String selectedText = editor.getSelectionModel().getSelectedText();
if (selectedText == null) {
return;
}

if (spec == null) {
KSettings settings = KSettingsService.getInstance().getSettings();
KServerDialog dialog = new KServerDialog(
n -> settings.getServers().stream().anyMatch(s -> s.getName().equals(n)) ? new ValidationInfo(
"Server named " + n + "' already exists") : null);

if (dialog.showAndGet()) {
ArrayList<KServerSpec> newServers = new ArrayList<>(settings.getServers());
newServers.add(dialog.getConnectionSpec());
KSettings newSettings = settings.clone();
newSettings.setServers(newServers);
KSettingsService.getInstance().setSettings(newSettings);
execute(dialog.getConnectionSpec(), selectedText);
}
} else {
execute(spec, selectedText);
}
}

private void execute(KServerSpec spec, String q) {
RunContentDescriptor contentDescriptor = KRunnerUtil.showRunContent(spec, project);
ConsoleView console = (ConsoleView)contentDescriptor.getExecutionConsole();
KServerProcessHandler processHandler = (KServerProcessHandler)contentDescriptor.getProcessHandler();
if (processHandler == null) { // can't really happen, but...
console.print("Internal error, please close the console and try again", ERROR_OUTPUT);
} else {
processHandler.execute(console, q);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.appian.intellij.k.actions;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.appian.intellij.k.settings.KSettingsService;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Editor;

/**
* An action group consisting of an action to run selected
* code on the new server or any of the servers, defined
* in settings.
*/
public class KRunSelectionActionGroup extends ActionGroup {
@NotNull
@Override
public AnAction[] getChildren(@Nullable AnActionEvent e) {
if (e == null) {
return new AnAction[0];
}

List<KRunSelectionAction> serverActions = ServiceManager.getService(KSettingsService.class)
.getSettings()
.getServers()
.stream()
.map(s -> new KRunSelectionAction(e.getProject(), s.toString(), s))
.collect(Collectors.toList());

List<AnAction> actions = new ArrayList<>();

if (!serverActions.isEmpty()) {
actions.addAll(serverActions);
actions.add(Separator.getInstance());
}

actions.add(new KRunSelectionAction(e.getProject(), "New Server...", null));
return actions.toArray(new AnAction[0]);
}

@Override
public void update(AnActionEvent event) {
// Enable/disable depending on whether user is editing
Editor editor = event.getData(CommonDataKeys.EDITOR);
if (editor == null) {
return;
}

String selectedText = Optional.ofNullable(event.getData(CommonDataKeys.EDITOR))
.map(e -> e.getSelectionModel().getSelectedText())
.orElse(null);

event.getPresentation().setEnabled(selectedText != null);

// Always make visible.
event.getPresentation().setVisible(true);
// Take this opportunity to set an icon for the menu entry.
event.getPresentation().setIcon(AllIcons.General.Run);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.appian.intellij.k.actions;

import java.util.Optional;

import com.appian.intellij.k.settings.KServerSpec;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Editor;

/**
* An action that runs selected Q code using currently
* active server or pops up a menu to choose one.
*/
public class KRunSelectionOnActiveServerAction extends AnAction {
public KRunSelectionOnActiveServerAction() {
}

@Override
public void actionPerformed(AnActionEvent e) {
Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
if (editor == null) {
return;
}
String selectedText = editor.getSelectionModel().getSelectedText();
if (selectedText == null) {
return;
}

Optional<KServerSpec> activeServer = KRunnerUtil.getSelectedServer(e.getProject());

if (activeServer.isPresent()) {
new KRunSelectionAction(getEventProject(e), null, activeServer.get()).actionPerformed(e);
return;
}

new KRunSelectionPopupAction().actionPerformed(e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.appian.intellij.k.actions;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;

/**
* An action that pops up a list of configured servers
* and runs selected Q code on the chosen server
*/
public class KRunSelectionPopupAction extends AnAction {
public KRunSelectionPopupAction() {
}

@Override
public void actionPerformed(AnActionEvent e) {
Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
if (editor == null) {
return;
}

String selectedText = editor.getSelectionModel().getSelectedText();
if (selectedText == null) {
return;
}

ListPopup popup = JBPopupFactory.getInstance()
.createActionGroupPopup("Run Selection On", new KRunSelectionActionGroup(), e.getDataContext(),
JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true);

popup.showInBestPositionFor(editor);
}
}
Loading

0 comments on commit a6b584f

Please sign in to comment.