From da7213ef242fadf4e3bd1aede9e3033059f55729 Mon Sep 17 00:00:00 2001
From: Peter Vanusanik
Date: Mon, 8 May 2023 12:08:42 +0200
Subject: [PATCH] #70
---
CHANGELOG.md | 5 +-
README.md | 19 +--
.../slt/plugin/SltDocumentationProvider.java | 24 +---
.../plugin/actions/Macroexpand1Action.java | 29 +++++
.../slt/plugin/actions/MacroexpandAction.java | 29 +++++
.../plugin/actions/MacroexpandActionBase.java | 122 ++++++++++++++++++
.../plugin/actions/MacroexpandAllAction.java | 29 +++++
.../slt/plugin/actions/MacroexpandGroup.java | 42 ++++++
.../services/lisp/LispEnvironmentService.java | 3 -
.../lisp/LispEnvironmentServiceImpl.java | 22 +---
.../SltLispEnvironmentMacroExpandCache.java | 90 -------------
.../slt/plugin/swank/SlimeListener.java | 8 ++
.../slt/plugin/swank/SwankPacket.java | 28 ++++
.../plugin/swank/requests/Macroexpand.java | 49 +++++++
.../plugin/swank/requests/Macroexpand1.java | 49 +++++++
.../plugin/swank/requests/MacroexpandAll.java | 2 +-
src/main/resources/META-INF/plugin.xml | 44 +++++--
.../resources/messages/SltBundle.properties | 7 +-
18 files changed, 444 insertions(+), 157 deletions(-)
create mode 100644 src/main/java/com/en_circle/slt/plugin/actions/Macroexpand1Action.java
create mode 100644 src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAction.java
create mode 100644 src/main/java/com/en_circle/slt/plugin/actions/MacroexpandActionBase.java
create mode 100644 src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAllAction.java
create mode 100644 src/main/java/com/en_circle/slt/plugin/actions/MacroexpandGroup.java
delete mode 100644 src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltLispEnvironmentMacroExpandCache.java
create mode 100644 src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand.java
create mode 100644 src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand1.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ddc7a5..bf32300 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 0.5.1
+## 0.5.1 230508
### Added
- Symbol inspection
@@ -6,6 +6,9 @@
- More browser options
- Evaluate top level action
+### Changes
+- Macroexpand is now action and menu, no longer automatic!
+
### Fixes
- Added symbols with no file into all search places
diff --git a/README.md b/README.md
index 7ea13a6..779aeb4 100644
--- a/README.md
+++ b/README.md
@@ -95,26 +95,21 @@ You can also open this as a project in Intellij Idea.
* [x] Breakpoints
* [x] Documentation
* [x] Hyperspec intergration
-* [x] Macro expand in documentation
- * Macro expand requires you to hover element twice for now
+* [x] Macro expand (all, 1, normal)
* [x] Find function by symbol name
* [x] Search for symbols
* [x] Back references
+* [x] Rainbow braces
* [ ] Refactoring
* [ ] List of quicklisp installed packages / ASDF packages
* [ ] List of modified top level forms that are yet to be evaluated
* [ ] Actually make an IDE, ie just plugin with dependencies as one application, not a plugin
-
-### Far futures / possible goals
-
-* [x] SDK Support
- * not a true SDK because that is only available in Intellij and not in (for instance) PyCharm, thus
-this is implemented manually.
- * [x] Download SBCL and quicklisp for user
+* [x] SDK Support
+ * not a true SDK because that is only available in Intellij and not in (for instance) PyCharm, thus
+ this is implemented manually.
+ * [x] Download SBCL and quicklisp for user
* [x] Automatic download of lisp interpret and quicklisp
-* [x] Different lisp interpreter support
-* [ ] Remote connections to interpreters
-* [ ] Rewrite everything into ABCL just for purity’s sake lol
+* [x] Different lisp interpreter support
## License
diff --git a/src/main/java/com/en_circle/slt/plugin/SltDocumentationProvider.java b/src/main/java/com/en_circle/slt/plugin/SltDocumentationProvider.java
index e8c2530..bed54ec 100644
--- a/src/main/java/com/en_circle/slt/plugin/SltDocumentationProvider.java
+++ b/src/main/java/com/en_circle/slt/plugin/SltDocumentationProvider.java
@@ -1,9 +1,7 @@
package com.en_circle.slt.plugin;
-import com.en_circle.slt.plugin.SymbolState.SymbolBinding;
import com.en_circle.slt.plugin.environment.LispFeatures;
import com.en_circle.slt.plugin.lisp.LispParserUtil;
-import com.en_circle.slt.plugin.lisp.psi.LispList;
import com.en_circle.slt.plugin.lisp.psi.LispSymbol;
import com.en_circle.slt.plugin.services.lisp.LispEnvironmentService;
import com.intellij.lang.documentation.AbstractDocumentationProvider;
@@ -68,7 +66,7 @@ public class SltDocumentationProvider extends AbstractDocumentationProvider {
String text = element.getText();
String packageName = LispParserUtil.getPackage(element);
SymbolState state = LispEnvironmentService.getInstance(element.getProject()).refreshSymbolFromServer(packageName, text);
- return asHtml(state, packageName, element);
+ return asHtml(state, element);
}
}
return null;
@@ -82,7 +80,7 @@ private PsiElement decideOnElement(PsiElement element, PsiElement originalElemen
return originalElement;
}
- private String asHtml(SymbolState state, String packageName, PsiElement element) {
+ private String asHtml(SymbolState state, PsiElement element) {
HtmlBuilder builder = new HtmlBuilder();
if (LispEnvironmentService.getInstance(element.getProject()).hasFeature(LispFeatures.DOCUMENTATION)) {
String documentation = StringUtils.replace(StringUtils.replace(escape(state.documentation), " ", " "),
@@ -91,24 +89,6 @@ private String asHtml(SymbolState state, String packageName, PsiElement element)
HtmlChunk.raw(documentation));
}
- if (LispEnvironmentService.getInstance(element.getProject()).hasFeature(LispFeatures.MACROEXPAND)) {
- LispList form = LispParserUtil.getIfHead(element);
- if (form != null && state.binding == SymbolBinding.MACRO) {
- String macroExpand = LispEnvironmentService.getInstance(element.getProject()).macroexpand(form, packageName);
- if (macroExpand != null) {
- macroExpand = StringUtils.replace(StringUtils.replace(escape(macroExpand), " ", " "),
- "\n", HtmlChunk.br().toString());
- builder.append(HtmlChunk.hr());
- builder.append(HtmlChunk.text(SltBundle.message("slt.documentation.macroexpand")));
- builder.append(HtmlChunk.br());
- builder.append(HtmlChunk.raw(macroExpand));
- } else {
- builder.append(HtmlChunk.hr());
- builder.append(HtmlChunk.text(SltBundle.message("slt.documentation.macroexpand.generating")));
- }
- }
- }
-
String doc = builder.toString();
return StringUtils.isBlank(doc) ? null : doc;
}
diff --git a/src/main/java/com/en_circle/slt/plugin/actions/Macroexpand1Action.java b/src/main/java/com/en_circle/slt/plugin/actions/Macroexpand1Action.java
new file mode 100644
index 0000000..8c500c3
--- /dev/null
+++ b/src/main/java/com/en_circle/slt/plugin/actions/Macroexpand1Action.java
@@ -0,0 +1,29 @@
+package com.en_circle.slt.plugin.actions;
+
+import com.en_circle.slt.plugin.SltBundle;
+import com.en_circle.slt.plugin.lisp.lisp.LispString;
+import com.en_circle.slt.plugin.lisp.lisp.LispUtils;
+import com.en_circle.slt.plugin.lisp.psi.LispList;
+import com.en_circle.slt.plugin.services.lisp.LispEnvironmentService;
+import com.en_circle.slt.plugin.swank.requests.Macroexpand1;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Macroexpand1Action extends MacroexpandActionBase {
+ private static final Logger log = LoggerFactory.getLogger(Macroexpand1Action.class);
+
+ @Override
+ protected void macroexpand(Project project, LispList form, String packageName, MacroexpandCallback callback) {
+ try {
+ LispEnvironmentService service = LispEnvironmentService.getInstance(project);
+ service.sendToLisp(new Macroexpand1(form.getText(), packageName, result -> {
+ callback.showMacroexpand(LispUtils.unescape(((LispString) result).getValue()));
+ }), true);
+ } catch (Exception e) {
+ log.warn(SltBundle.message("slt.error.start"), e);
+ Messages.showErrorDialog(project, e.getMessage(), SltBundle.message("slt.ui.errors.lisp.start"));
+ }
+ }
+}
diff --git a/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAction.java b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAction.java
new file mode 100644
index 0000000..a32e3c6
--- /dev/null
+++ b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAction.java
@@ -0,0 +1,29 @@
+package com.en_circle.slt.plugin.actions;
+
+import com.en_circle.slt.plugin.SltBundle;
+import com.en_circle.slt.plugin.lisp.lisp.LispString;
+import com.en_circle.slt.plugin.lisp.lisp.LispUtils;
+import com.en_circle.slt.plugin.lisp.psi.LispList;
+import com.en_circle.slt.plugin.services.lisp.LispEnvironmentService;
+import com.en_circle.slt.plugin.swank.requests.Macroexpand;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MacroexpandAction extends MacroexpandActionBase {
+ private static final Logger log = LoggerFactory.getLogger(MacroexpandAction.class);
+
+ @Override
+ protected void macroexpand(Project project, LispList form, String packageName, MacroexpandCallback callback) {
+ try {
+ LispEnvironmentService service = LispEnvironmentService.getInstance(project);
+ service.sendToLisp(new Macroexpand(form.getText(), packageName, result -> {
+ callback.showMacroexpand(LispUtils.unescape(((LispString) result).getValue()));
+ }), true);
+ } catch (Exception e) {
+ log.warn(SltBundle.message("slt.error.start"), e);
+ Messages.showErrorDialog(project, e.getMessage(), SltBundle.message("slt.ui.errors.lisp.start"));
+ }
+ }
+}
diff --git a/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandActionBase.java b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandActionBase.java
new file mode 100644
index 0000000..129d82f
--- /dev/null
+++ b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandActionBase.java
@@ -0,0 +1,122 @@
+package com.en_circle.slt.plugin.actions;
+
+import com.en_circle.slt.plugin.SltBundle;
+import com.en_circle.slt.plugin.SltCommonLispFileType;
+import com.en_circle.slt.plugin.environment.LispFeatures;
+import com.en_circle.slt.plugin.lisp.LispParserUtil;
+import com.en_circle.slt.plugin.lisp.psi.LispList;
+import com.en_circle.slt.plugin.services.lisp.LispEnvironmentService;
+import com.intellij.openapi.actionSystem.ActionUpdateThread;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.text.HtmlBuilder;
+import com.intellij.openapi.util.text.HtmlChunk;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.text.html.HTMLEditorKit;
+import java.awt.*;
+import java.util.Objects;
+
+public abstract class MacroexpandActionBase extends AnAction {
+
+ protected abstract void macroexpand(Project project, LispList form, String packageName, MacroexpandCallback callback);
+
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent event) {
+ EditorEx editor = (EditorEx) event.getData(CommonDataKeys.EDITOR);
+ LispList list = null;
+
+ if (editor != null) {
+ PsiDocumentManager psiMgr = PsiDocumentManager.getInstance(Objects.requireNonNull(editor.getProject()));
+ psiMgr.commitDocument(editor.getDocument());
+ PsiFile psiFile = psiMgr.getPsiFile(editor.getDocument());
+ if (psiFile != null) {
+ int caretOffset = editor.getExpectedCaretOffset();
+ list = findList(psiFile, caretOffset, editor.getDocument());
+ if (list != null) {
+ editor.getSelectionModel().setSelection(list.getTextOffset(), list.getTextOffset() + list.getTextLength());
+ }
+ }
+
+ if (list != null) {
+ int offset = list.getTextOffset();
+ String packageName = LispParserUtil.getPackage(psiFile, offset);
+ macroexpand(editor.getProject(), list, packageName, text -> SwingUtilities.invokeLater(() -> {
+ HtmlBuilder builder = new HtmlBuilder();
+ String macroExpand = StringUtils.replace(StringUtils.replace(StringEscapeUtils.escapeHtml(text), " ", " "),
+ "\n", HtmlChunk.br().toString());
+ builder.append(HtmlChunk.raw(macroExpand));
+
+ JEditorPane editorPane = new JEditorPane("text/html", "");
+ editorPane.setEditorKit(new HTMLEditorKit());
+ editorPane.setText(builder.toString());
+
+ JPanel textPanel = new JPanel(new BorderLayout());
+ textPanel.add(editorPane, BorderLayout.CENTER);
+
+ JBPopup popup = JBPopupFactory.getInstance()
+ .createComponentPopupBuilder(textPanel, null)
+ .setProject(editor.getProject())
+ .setTitle(SltBundle.message("slt.documentation.macroexpand"))
+ .setShowBorder(true)
+ .setMovable(true)
+ .setFocusable(true)
+ .setRequestFocus(true)
+ .createPopup();
+ popup.showInBestPositionFor(editor.getDataContext());
+ }));
+ }
+ }
+ }
+
+ protected LispList findList(PsiFile psiFile, int caretOffset, Document document) {
+ PsiElement element = psiFile.findElementAt(caretOffset);
+ if (element != null) {
+ PsiElement parent = element;
+ while (parent != null) {
+ parent = parent.getParent();
+ if (parent instanceof LispList) {
+ return (LispList) parent;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void update(@NotNull AnActionEvent event) {
+ event.getPresentation().setEnabledAndVisible(false);
+ Editor editor = event.getData(CommonDataKeys.EDITOR);
+ if (editor != null && event.getProject() != null) {
+ PsiFile file = PsiDocumentManager.getInstance(Objects.requireNonNull(editor.getProject())).getPsiFile(editor.getDocument());
+ if (file != null && SltCommonLispFileType.INSTANCE.equals(file.getFileType())) {
+ event.getPresentation().setEnabledAndVisible(LispEnvironmentService.getInstance(event.getProject())
+ .hasFeature(LispFeatures.MACROEXPAND));
+ }
+ }
+ }
+
+ @Override
+ public @NotNull ActionUpdateThread getActionUpdateThread() {
+ return ActionUpdateThread.BGT;
+ }
+
+ protected interface MacroexpandCallback {
+
+ void showMacroexpand(String text);
+
+ }
+}
diff --git a/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAllAction.java b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAllAction.java
new file mode 100644
index 0000000..c10ae54
--- /dev/null
+++ b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandAllAction.java
@@ -0,0 +1,29 @@
+package com.en_circle.slt.plugin.actions;
+
+import com.en_circle.slt.plugin.SltBundle;
+import com.en_circle.slt.plugin.lisp.lisp.LispString;
+import com.en_circle.slt.plugin.lisp.lisp.LispUtils;
+import com.en_circle.slt.plugin.lisp.psi.LispList;
+import com.en_circle.slt.plugin.services.lisp.LispEnvironmentService;
+import com.en_circle.slt.plugin.swank.requests.MacroexpandAll;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MacroexpandAllAction extends MacroexpandActionBase {
+ private static final Logger log = LoggerFactory.getLogger(MacroexpandAllAction.class);
+
+ @Override
+ protected void macroexpand(Project project, LispList form, String packageName, MacroexpandCallback callback) {
+ try {
+ LispEnvironmentService service = LispEnvironmentService.getInstance(project);
+ service.sendToLisp(new MacroexpandAll(form.getText(), packageName, result -> {
+ callback.showMacroexpand(LispUtils.unescape(((LispString) result).getValue()));
+ }), true);
+ } catch (Exception e) {
+ log.warn(SltBundle.message("slt.error.start"), e);
+ Messages.showErrorDialog(project, e.getMessage(), SltBundle.message("slt.ui.errors.lisp.start"));
+ }
+ }
+}
diff --git a/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandGroup.java b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandGroup.java
new file mode 100644
index 0000000..2f40169
--- /dev/null
+++ b/src/main/java/com/en_circle/slt/plugin/actions/MacroexpandGroup.java
@@ -0,0 +1,42 @@
+package com.en_circle.slt.plugin.actions;
+
+import com.en_circle.slt.plugin.SltBundle;
+import com.en_circle.slt.plugin.SltCommonLispFileType;
+import com.en_circle.slt.plugin.environment.LispFeatures;
+import com.en_circle.slt.plugin.services.lisp.LispEnvironmentService;
+import com.intellij.openapi.actionSystem.ActionUpdateThread;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+public class MacroexpandGroup extends DefaultActionGroup {
+
+ public MacroexpandGroup() {
+ super(() -> SltBundle.message("action.slt.actions.macroexpand.group.text"), true);
+ }
+
+ @Override
+ public void update(@NotNull AnActionEvent event) {
+ event.getPresentation().setEnabledAndVisible(false);
+ Editor editor = event.getData(CommonDataKeys.EDITOR);
+ if (editor != null && event.getProject() != null) {
+ PsiFile file = PsiDocumentManager.getInstance(Objects.requireNonNull(editor.getProject())).getPsiFile(editor.getDocument());
+ if (file != null && SltCommonLispFileType.INSTANCE.equals(file.getFileType())) {
+ event.getPresentation().setEnabledAndVisible(LispEnvironmentService.getInstance(event.getProject())
+ .hasFeature(LispFeatures.MACROEXPAND));
+ }
+ }
+ }
+
+ @Override
+ public @NotNull ActionUpdateThread getActionUpdateThread() {
+ return ActionUpdateThread.BGT;
+ }
+
+}
diff --git a/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentService.java b/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentService.java
index c9400f1..e860bec 100644
--- a/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentService.java
+++ b/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentService.java
@@ -5,7 +5,6 @@
import com.en_circle.slt.plugin.environment.SltLispEnvironment;
import com.en_circle.slt.plugin.environment.SltLispEnvironment.SltLispOutputChangedListener;
import com.en_circle.slt.plugin.lisp.lisp.LispElement;
-import com.en_circle.slt.plugin.lisp.psi.LispList;
import com.en_circle.slt.plugin.services.lisp.components.SltBreakpoint;
import com.en_circle.slt.plugin.services.lisp.components.SltLispEnvironmentSymbolCache.BatchedSymbolRefreshAction;
import com.en_circle.slt.plugin.swank.SlimeListener.DebugInterface;
@@ -55,8 +54,6 @@ static LispEnvironmentService getInstance(Project project) {
SltLispEnvironment getEnvironment();
- String macroexpand(LispList form, String packageName);
-
void updateIndentation(LispElement element);
Integer calculateOffset(PsiElement element, PsiFile file, boolean wasAfter, String text, int offset, String packageOverride);
diff --git a/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentServiceImpl.java b/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentServiceImpl.java
index d6c69a9..dfba7ec 100644
--- a/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentServiceImpl.java
+++ b/src/main/java/com/en_circle/slt/plugin/services/lisp/LispEnvironmentServiceImpl.java
@@ -8,11 +8,13 @@
import com.en_circle.slt.plugin.environment.SltLispEnvironmentConfiguration;
import com.en_circle.slt.plugin.lisp.lisp.LispContainer;
import com.en_circle.slt.plugin.lisp.lisp.LispElement;
-import com.en_circle.slt.plugin.lisp.psi.LispList;
import com.en_circle.slt.plugin.sdk.LispProjectSdk;
import com.en_circle.slt.plugin.sdk.LispSdk;
import com.en_circle.slt.plugin.sdk.SdkList;
-import com.en_circle.slt.plugin.services.lisp.components.*;
+import com.en_circle.slt.plugin.services.lisp.components.SltBreakpoint;
+import com.en_circle.slt.plugin.services.lisp.components.SltBreakpointContainer;
+import com.en_circle.slt.plugin.services.lisp.components.SltIndentationContainer;
+import com.en_circle.slt.plugin.services.lisp.components.SltLispEnvironmentSymbolCache;
import com.en_circle.slt.plugin.services.lisp.components.SltLispEnvironmentSymbolCache.BatchedSymbolRefreshAction;
import com.en_circle.slt.plugin.swank.SlimeListener;
import com.en_circle.slt.plugin.swank.SlimeListener.DebugInterface;
@@ -63,7 +65,6 @@ public class LispEnvironmentServiceImpl implements LispEnvironmentService {
private final Project project;
private final SltIndentationContainer indentationContainer;
private final SltLispEnvironmentSymbolCache symbolCache;
- private final SltLispEnvironmentMacroExpandCache macroExpandCache;
private final SltBreakpointContainer breakpointContainer;
public LispEnvironmentServiceImpl(Project project) {
@@ -71,7 +72,6 @@ public LispEnvironmentServiceImpl(Project project) {
indentationContainer = new SltIndentationContainer();
indentationContainer.init(project);
symbolCache = new SltLispEnvironmentSymbolCache(project);
- macroExpandCache = new SltLispEnvironmentMacroExpandCache();
breakpointContainer = new SltBreakpointContainer(project);
symbolCache.start();
@@ -330,23 +330,9 @@ public SltLispEnvironment getEnvironment() {
return environment;
}
- @Override
- public String macroexpand(LispList form, String packageName) {
- try {
- return macroExpandCache.macroexpand(form, packageName);
- } catch (Exception e) {
- log.error(e.getMessage());
- log.debug(e.getMessage(), e);
- }
- return null;
- }
-
@Override
public void updateIndentation(LispElement element) {
indentationContainer.update((LispContainer) element);
-
- // also clear macro cache since we get this hit on macro update
- macroExpandCache.clear();
}
@Override
diff --git a/src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltLispEnvironmentMacroExpandCache.java b/src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltLispEnvironmentMacroExpandCache.java
deleted file mode 100644
index 599affb..0000000
--- a/src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltLispEnvironmentMacroExpandCache.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.en_circle.slt.plugin.services.lisp.components;
-
-import com.en_circle.slt.plugin.lisp.lisp.LispString;
-import com.en_circle.slt.plugin.lisp.lisp.LispUtils;
-import com.en_circle.slt.plugin.lisp.psi.LispList;
-import com.en_circle.slt.plugin.services.lisp.LispEnvironmentService;
-import com.en_circle.slt.plugin.swank.requests.MacroexpandAll;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiFile;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Objects;
-
-public class SltLispEnvironmentMacroExpandCache {
-
- private final LoadingCache expandedMacros;
-
- public SltLispEnvironmentMacroExpandCache() {
- CacheLoader loader = new CacheLoader<>() {
- @Override
- public MacroExpandEntry load(@NotNull SltLispEnvironmentMacroExpandCache.MacroExpandEntry key) throws Exception {
- LispEnvironmentService.getInstance(key.project).sendToLisp(
- MacroexpandAll.macroexpand(key.form, key.packageName, result -> {
- key.evaluated = LispUtils.unescape(((LispString) result).getValue());
- }));
- return key;
- }
- };
- expandedMacros = CacheBuilder.newBuilder()
- .maximumSize(512)
- .build(loader);
- }
-
-
- public String macroexpand(LispList form, String packageName) throws Exception {
- MacroExpandEntry entry = new MacroExpandEntry();
- entry.form = form.getNode().getText();
- PsiFile file = form.getContainingFile();
- if (file != null) {
- entry.virtualFile = file.getVirtualFile();
- entry.modification = file.getModificationStamp();
- entry.packageName = packageName;
- entry.project = form.getProject();
- MacroExpandEntry cachedEntry = expandedMacros.get(entry);
- if (cachedEntry.modification < entry.modification) {
- expandedMacros.refresh(cachedEntry);
- }
- return expandedMacros.get(entry).evaluated;
- }
- return null;
- }
-
- public void clear() {
- expandedMacros.invalidateAll();
- }
-
- private static class MacroExpandEntry {
-
- public Project project;
- private String form;
- private String packageName;
- private String evaluated;
- private VirtualFile virtualFile;
- private long modification;
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- MacroExpandEntry entry = (MacroExpandEntry) o;
-
- if (!Objects.equals(form, entry.form)) return false;
- if (!Objects.equals(packageName, entry.packageName)) return false;
- return Objects.equals(virtualFile, entry.virtualFile);
- }
-
- @Override
- public int hashCode() {
- int result = form != null ? form.hashCode() : 0;
- result = 31 * result + (packageName != null ? packageName.hashCode() : 0);
- result = 31 * result + (virtualFile != null ? virtualFile.hashCode() : 0);
- return result;
- }
- }
-}
diff --git a/src/main/java/com/en_circle/slt/plugin/swank/SlimeListener.java b/src/main/java/com/en_circle/slt/plugin/swank/SlimeListener.java
index cfc4647..d624734 100644
--- a/src/main/java/com/en_circle/slt/plugin/swank/SlimeListener.java
+++ b/src/main/java/com/en_circle/slt/plugin/swank/SlimeListener.java
@@ -155,6 +155,14 @@ private void processReturn(LispContainer reply) {
macroexpandAll.processReply((LispContainer) reply.getItems().get(1));
}
+ if (request instanceof Macroexpand macroexpand) {
+ macroexpand.processReply((LispContainer) reply.getItems().get(1));
+ }
+
+ if (request instanceof Macroexpand1 macroexpand1) {
+ macroexpand1.processReply((LispContainer) reply.getItems().get(1));
+ }
+
if (request instanceof SimpleCompletion simpleCompletion) {
simpleCompletion.processReply((LispContainer) reply.getItems().get(1));
}
diff --git a/src/main/java/com/en_circle/slt/plugin/swank/SwankPacket.java b/src/main/java/com/en_circle/slt/plugin/swank/SwankPacket.java
index 52de57f..5f3cb0c 100644
--- a/src/main/java/com/en_circle/slt/plugin/swank/SwankPacket.java
+++ b/src/main/java/com/en_circle/slt/plugin/swank/SwankPacket.java
@@ -277,11 +277,39 @@ public static SwankPacket loadFile(String file, String breakpoints, String packa
return new SwankPacket(formatted);
}
+ public static SwankPacket macroexpand1(String form, String packageName, BigInteger continuation) {
+ return macroexpand1(form, "T", packageName, continuation);
+ }
+
+ public static SwankPacket macroexpand1(String form, String threadId, String packageName, BigInteger continuation) {
+ form = StringUtils.replace(form, "\\", "\\\\");
+ form = StringUtils.replace(form, "\"", "\\\"");
+ packageName = StringUtils.replace(packageName, "\\", "\\\\");
+ packageName = StringUtils.replace(packageName, "\"", "\\\"");
+ String formatted = String.format("(:emacs-rex (swank:swank-macroexpand-1 \"%s\") \":%s\" %s %s)",
+ form, packageName, threadId, continuation);
+ return new SwankPacket(formatted);
+ }
+
public static SwankPacket macroexpand(String form, String packageName, BigInteger continuation) {
return macroexpand(form, "T", packageName, continuation);
}
public static SwankPacket macroexpand(String form, String threadId, String packageName, BigInteger continuation) {
+ form = StringUtils.replace(form, "\\", "\\\\");
+ form = StringUtils.replace(form, "\"", "\\\"");
+ packageName = StringUtils.replace(packageName, "\\", "\\\\");
+ packageName = StringUtils.replace(packageName, "\"", "\\\"");
+ String formatted = String.format("(:emacs-rex (swank:swank-macroexpand \"%s\") \":%s\" %s %s)",
+ form, packageName, threadId, continuation);
+ return new SwankPacket(formatted);
+ }
+
+ public static SwankPacket macroexpandAll(String form, String packageName, BigInteger continuation) {
+ return macroexpandAll(form, "T", packageName, continuation);
+ }
+
+ public static SwankPacket macroexpandAll(String form, String threadId, String packageName, BigInteger continuation) {
form = StringUtils.replace(form, "\\", "\\\\");
form = StringUtils.replace(form, "\"", "\\\"");
packageName = StringUtils.replace(packageName, "\\", "\\\\");
diff --git a/src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand.java b/src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand.java
new file mode 100644
index 0000000..3e8db6a
--- /dev/null
+++ b/src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand.java
@@ -0,0 +1,49 @@
+package com.en_circle.slt.plugin.swank.requests;
+
+import com.en_circle.slt.plugin.lisp.lisp.LispContainer;
+import com.en_circle.slt.plugin.lisp.lisp.LispElement;
+import com.en_circle.slt.plugin.lisp.lisp.LispSymbol;
+import com.en_circle.slt.plugin.swank.SlimeRequest;
+import com.en_circle.slt.plugin.swank.SwankPacket;
+import com.intellij.openapi.project.Project;
+
+import java.math.BigInteger;
+
+public class Macroexpand extends SlimeRequest {
+
+ public static SlimeRequest macroexpand(String form, String module, Callback callback) {
+ return new Macroexpand(form, module, callback);
+ }
+
+ private final Callback callback;
+ private final String form;
+ private final String module;
+
+ public Macroexpand(String form, String module, Callback callback) {
+ this.form = form;
+ this.module = module;
+ this.callback = callback;
+ }
+
+ public void processReply(LispContainer data) {
+ if (isOk(data)) {
+ callback.onResult(data.getItems().get(1));
+ }
+ }
+
+ private boolean isOk(LispContainer data) {
+ return data.getItems().size() > 0 &&
+ data.getItems().get(0) instanceof LispSymbol &&
+ ":ok".equals(((LispSymbol) data.getItems().get(0)).getValue());
+ }
+
+ @Override
+ public SwankPacket createPacket(BigInteger requestId, Project project) {
+ return SwankPacket.macroexpand(form, module, requestId);
+ }
+
+ public interface Callback {
+ void onResult(LispElement result);
+ }
+
+}
diff --git a/src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand1.java b/src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand1.java
new file mode 100644
index 0000000..4716558
--- /dev/null
+++ b/src/main/java/com/en_circle/slt/plugin/swank/requests/Macroexpand1.java
@@ -0,0 +1,49 @@
+package com.en_circle.slt.plugin.swank.requests;
+
+import com.en_circle.slt.plugin.lisp.lisp.LispContainer;
+import com.en_circle.slt.plugin.lisp.lisp.LispElement;
+import com.en_circle.slt.plugin.lisp.lisp.LispSymbol;
+import com.en_circle.slt.plugin.swank.SlimeRequest;
+import com.en_circle.slt.plugin.swank.SwankPacket;
+import com.intellij.openapi.project.Project;
+
+import java.math.BigInteger;
+
+public class Macroexpand1 extends SlimeRequest {
+
+ public static SlimeRequest macroexpand(String form, String module, Callback callback) {
+ return new Macroexpand1(form, module, callback);
+ }
+
+ private final Callback callback;
+ private final String form;
+ private final String module;
+
+ public Macroexpand1(String form, String module, Callback callback) {
+ this.form = form;
+ this.module = module;
+ this.callback = callback;
+ }
+
+ public void processReply(LispContainer data) {
+ if (isOk(data)) {
+ callback.onResult(data.getItems().get(1));
+ }
+ }
+
+ private boolean isOk(LispContainer data) {
+ return data.getItems().size() > 0 &&
+ data.getItems().get(0) instanceof LispSymbol &&
+ ":ok".equals(((LispSymbol) data.getItems().get(0)).getValue());
+ }
+
+ @Override
+ public SwankPacket createPacket(BigInteger requestId, Project project) {
+ return SwankPacket.macroexpand1(form, module, requestId);
+ }
+
+ public interface Callback {
+ void onResult(LispElement result);
+ }
+
+}
diff --git a/src/main/java/com/en_circle/slt/plugin/swank/requests/MacroexpandAll.java b/src/main/java/com/en_circle/slt/plugin/swank/requests/MacroexpandAll.java
index 0c8563e..c7d3033 100644
--- a/src/main/java/com/en_circle/slt/plugin/swank/requests/MacroexpandAll.java
+++ b/src/main/java/com/en_circle/slt/plugin/swank/requests/MacroexpandAll.java
@@ -39,7 +39,7 @@ private boolean isOk(LispContainer data) {
@Override
public SwankPacket createPacket(BigInteger requestId, Project project) {
- return SwankPacket.macroexpand(form, module, requestId);
+ return SwankPacket.macroexpandAll(form, module, requestId);
}
public interface Callback {
diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
index d018fb7..edb5dd8 100644
--- a/src/main/resources/META-INF/plugin.xml
+++ b/src/main/resources/META-INF/plugin.xml
@@ -145,17 +145,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
@@ -209,13 +234,16 @@
0.5.0 New features:
-Hyperspec embedded in the tool window (requires internet connection to see obviously)
+0.5.1 New features:
+Symbol inspection
+Rainbow braces option
+More CLHS browser options
+Evaluate top level action
+
+0.5.1 Changes and fixes:
+Macroexpand is now action and menu, no longer automatic!
+Added symbols with no file into all search places
-0.5.0 Changes and fixes:
-Support for definitions under other expressions
-SltPlainTextSymbolCompletionContributor - to be used with git and such
-
See CHANGELOG.md for more details
]]>
diff --git a/src/main/resources/messages/SltBundle.properties b/src/main/resources/messages/SltBundle.properties
index 62c71bd..e4f22f6 100644
--- a/src/main/resources/messages/SltBundle.properties
+++ b/src/main/resources/messages/SltBundle.properties
@@ -23,9 +23,8 @@ slt.documentation.types.constant=Constant Form
slt.documentation.types.specvariable=Special Variable
slt.documentation.types.keyword=Keyword
slt.documentation.types.class=Class
-slt.documentation.macroexpand=Macro expansion:
+slt.documentation.macroexpand=Macro Expansion:
slt.documentation.types.method=Method
-slt.documentation.macroexpand.generating=Generating macro expansion, hover again to see it
# UI
slt.ui.errors.lisp.start=Failed to Start Lisp
@@ -226,6 +225,10 @@ slt.ui.statusbar.name=Current Package
slt.ui.statusbar.info=Current Package:
# Actions
+action.slt.actions.macroexpand.group.text=Macroexpand
+action.slt.actions.macroexpand.all.text=Macroexpand All
+action.slt.actions.macroexpand.one.text=Macroexpand 1
+action.slt.actions.macroexpand.normal.text=Macroexpand
action.slt.actions.eval.toplevel.text=Evaluate Top Level Expression
action.slt.actions.eval.region.text=Evaluate Selected Region
action.slt.actions.eval.previous.text=Evaluate Previous S-Expression