Skip to content

Commit a53cb74

Browse files
committed
Fix creation of template files
1 parent 7df74d9 commit a53cb74

16 files changed

Lines changed: 268 additions & 102 deletions

CHANGELOG.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,26 @@
55
- Better rendering for "Go to Declaration" targets
66
- Inspection for using the same variable in the e.g. Module definition list several times
77
- Quick fix for adding usages and other messages
8-
- Rework of creating project templates and modules
98
- Update to Mathematica version 11.2
109
- Quick fix for pushing a variable inside the Module definition list
1110
- Completion for file names inside strings
1211

1312
## Version 3.0
1413

15-
- Keeping a leading * when pressing enter inside comments
14+
- Reimplementation of how Mathematica projects and modules are created.
15+
- Support Mathematica Language version on per IDEA module. This allows for checking built-in functions that are only available
16+
in a later version of Mathematica basing on the module settings in the project settings panel.
17+
- Keeping a leading * when pressing enter inside comments.
1618
- Quick Documentation lookup for own functions. This will show the usage message of a function if available.
17-
- Performance improvement through caching
19+
- Performance improvement through caching.
1820
- Support for Libraries. Libraries are basically a package folder with Mathematica source code. This code is indexed and
19-
can now be used for completion and navigation. The highlighter shows which functions come from a different file
21+
can now be used for completion and navigation. The highlighter shows which functions come from a different file.
2022
- Support for project-wide navigation and resolving of symbols. Now you can refactor, navigate and complete functions
21-
that are located in a different package file
22-
- Smart completion inside comments to insert symbols from file
23-
- Implementation of better local variable support. Especially, "With" supports now several declaration lists
23+
that are located in a different package file.
24+
- Smart completion inside comments to insert symbols from file.
25+
- Implementation of better local variable support. Especially, "With" supports now several declaration lists.
2426
- Fixing "Go to related symbol". Finds all usages of a symbol and gives file, line and a snip of the code there. You can
25-
directly navigate to any of these places
27+
directly navigate to any of these places.
2628
- Implemented "Go to Declaration" so that the user can navigate to all targets where a function is given a definition (
27-
I know that go to _declaration_ is misleading for Mathematica, but it is the easier short-cut and widely used.)
29+
I know that go to _declaration_ is misleading for Mathematica, but it is the easier short-cut and widely used).
2830
- Heavy reimplementation of the core algorithms for resolving references.

resources/META-INF/plugin.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@
7575
<extendWordSelectionHandler implementation="de.halirutan.mathematica.codeinsight.editoractions.wordselection.MathematicaFunctionSelectioner"/>
7676
<extendWordSelectionHandler implementation="de.halirutan.mathematica.codeinsight.editoractions.wordselection.MathematicaListSelectioner"/>
7777

78-
<!--&lt;!&ndash;<basicWordSelectionFilter&ndash;&gt;-->
79-
<!--&lt;!&ndash;implementation="de.halirutan.mathematica.codeinsight.editoractions.wordselection.BasicExpressionSelectionFilter"/>&ndash;&gt;-->
80-
8178
<applicationService serviceInterface="de.halirutan.mathematica.codeinsight.folding.MathematicaCodeFoldingSettingsImpl" serviceImplementation="de.halirutan.mathematica.codeinsight.folding.MathematicaCodeFoldingSettingsImpl"/>
8279
<codeFoldingOptionsProvider instance="de.halirutan.mathematica.codeinsight.folding.MathematicaFoldingOptionProvider"/>
8380
<!-- Code-style and colors-->

resources/de/halirutan/mathematica/MathematicaBundle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,4 @@ library.description=A Mathematica package directory that acts as library
6060
doc.navi.invalid=Cannot resolve symbol {0}
6161
doc.navi.navto=Navigate to definition of {0}
6262
doc.navi.builtin=Built-in symbol <b>{0}</b>
63+
module.settings.language.level=Module Language Level

resources/fileTemplates/internal/Package.m.ft

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
(* Mathematica Package *)
2-
(* Created by Mathematica Plugin for IntelliJ IDEA *)
2+
(* Created by Mathematica Plugin for IntelliJ IDEA, see http://wlplugin.halirutan.de/ *)
33

4-
(* :Title: ${NAME} *)
5-
(* :Context: ${NAME}` *)
4+
(* :Title: ${MATHEMATICA_PACKAGE_NAME} *)
5+
(* :Context: ${MATHEMATICA_CONTEXT} *)
66
(* :Author: ${USER} *)
77
(* :Date: ${YEAR}-${MONTH}-${DAY} *)
88

9-
(* :Package Version: 0.1 *)
10-
(* :Mathematica Version: *)
9+
(* :Package Version: ${MATHEMATICA_PACKAGE_VERSION} *)
10+
(* :Mathematica Version: ${MATHEMATICA_VERSION} *)
1111
(* :Copyright: (c) ${YEAR} ${USER} *)
1212
(* :Keywords: *)
1313
(* :Discussion: *)
1414

15-
BeginPackage["${NAME}`"];
15+
BeginPackage["${MATHEMATICA_CONTEXT}"];
1616
(* Exported symbols added here with SymbolName::usage *)
1717

1818
Begin["`Private`"];

resources/fileTemplates/internal/PacletInfo.m.ft

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
(* Paclet Info File *)
2-
(* Created by Mathematica Plugin for IntelliJ IDEA *)
2+
(* Created by Mathematica Plugin for IntelliJ IDEA, see http://wlplugin.halirutan.de/ *)
3+
(* :Author: ${USER} *)
4+
(* :Date: ${DATE} *)
35

46
Paclet[
5-
Name -> "${MathematicaContext}",
7+
Name -> "${MATHEMATICA_PACKAGE_NAME}",
68
Version -> "0.1",
7-
MathematicaVersion -> "${MathematicaVersion}",
9+
MathematicaVersion -> "${MATHEMATICA_VERSION}",
10+
Description -> "",
11+
Creator -> "${USER}",
812
Extensions ->
913
{
10-
{"Kernel", Root -> "Kernel", Context -> "${MathematicaContext}`"}
14+
{"Kernel", Root -> "Kernel", Context -> "${MATHEMATICA_CONTEXT}"}
1115
}
1216
]
1317

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(* Mathematica Source File *)
1+
(* Mathematica Source File *)
22
(* Created by Mathematica Plugin for IntelliJ IDEA *)
33
(* :Author: ${USER} *)
44
(* :Date: ${YEAR}-${MONTH}-${DAY} *)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
(* Mathematica Init file *)
22
(* Created by Mathematica Plugin for IntelliJ IDEA *)
3-
Get["${PROJECT_NAME}`${PROJECT_NAME}`"]
3+
Get["${MATHEMATICA_CONTEXT}${MATHEMATICA_CONTEXT}"]

src/de/halirutan/mathematica/actions/CreateMathematicaFile.java

Lines changed: 108 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,60 +25,62 @@
2525
import com.intellij.ide.actions.CreateFileFromTemplateDialog.Builder;
2626
import com.intellij.ide.fileTemplates.FileTemplate;
2727
import com.intellij.ide.fileTemplates.FileTemplateManager;
28+
import com.intellij.ide.fileTemplates.FileTemplateUtil;
29+
import com.intellij.openapi.module.Module;
30+
import com.intellij.openapi.module.ModuleUtilCore;
2831
import com.intellij.openapi.project.DumbAware;
2932
import com.intellij.openapi.project.Project;
33+
import com.intellij.openapi.projectRoots.Sdk;
34+
import com.intellij.openapi.roots.ProjectRootManager;
35+
import com.intellij.openapi.ui.InputValidator;
36+
import com.intellij.openapi.util.io.FileUtilRt;
37+
import com.intellij.openapi.util.text.StringUtil;
3038
import com.intellij.psi.PsiDirectory;
39+
import com.intellij.psi.PsiElement;
3140
import com.intellij.psi.PsiFile;
41+
import de.halirutan.mathematica.file.MathematicaFileType;
42+
import de.halirutan.mathematica.file.MathematicaTemplateProperties;
43+
import de.halirutan.mathematica.module.MathematicaLanguageLevelModuleExtension;
44+
import de.halirutan.mathematica.sdk.MathematicaLanguageLevel;
45+
import de.halirutan.mathematica.sdk.MathematicaSdkType;
3246
import de.halirutan.mathematica.util.MathematicaIcons;
3347

34-
import java.io.File;
48+
import java.util.Properties;
3549

3650
/**
3751
* Provides the creation of new Mathematica files through the IDEA <em >new...</em> action.
52+
* <p>
53+
* TODO: This should be reworked.
54+
* The global string identifier for the templates should use {@link de.halirutan.mathematica.file.MathematicaFileTemplateProvider}
55+
* instead. Furthermore, we don't use the framework of {@link CreateFileFromTemplateAction} which is ugly as shit.
56+
* Instead, the variables we set inside the file template could be live templates that are active as soon as the file
57+
* is created and we only fill it with the default values. This gives the user the ability to fix settings. Not a pressing
58+
* matter so I'll leave it for now.
3859
*
3960
* @author patrick (4/8/13)
4061
*/
4162
public class CreateMathematicaFile extends CreateFileFromTemplateAction implements DumbAware {
4263
private static final String NEW_M_FILE = "New Mathematica file";
4364

65+
private static final String PACKAGE = "Package";
66+
private static final String PLAIN = "Plain";
67+
private static final String TEST = "Test";
68+
private static final String NOTEBOOK = "Notebook";
69+
private Project myProject = null;
70+
4471
public CreateMathematicaFile() {
4572
super(NEW_M_FILE, "Creates a new .m Mathematica package file", MathematicaIcons.FILE_ICON);
4673
}
4774

48-
/**
49-
* This is stolen from here {@link http://stackoverflow.com/a/990492/1078614}
50-
*
51-
* @param s
52-
* filename with possible extension
53-
* @return filename without extension
54-
*/
55-
private static String removeExtension(String s) {
56-
57-
String separator = File.separator;
58-
String filename;
59-
60-
// Remove the path up to the filename.
61-
int lastSeparatorIndex = s.lastIndexOf(separator);
62-
if (lastSeparatorIndex == -1) {
63-
filename = s;
64-
} else {
65-
filename = s.substring(lastSeparatorIndex + 1);
66-
}
67-
68-
// Remove the extension.
69-
int extensionIndex = filename.lastIndexOf(".");
70-
if (extensionIndex == -1)
71-
return filename;
72-
73-
return filename.substring(0, extensionIndex);
74-
}
75-
7675
@Override
7776
protected void buildDialog(Project project, PsiDirectory directory, Builder builder) {
78-
builder.setTitle(NEW_M_FILE).addKind("Package", MathematicaIcons.FILE_ICON, "Package");
79-
builder.setTitle(NEW_M_FILE).addKind("Plain", MathematicaIcons.FILE_ICON, "Plain");
80-
builder.setTitle(NEW_M_FILE).addKind("Test", MathematicaIcons.FILE_ICON, "Test");
81-
builder.setTitle(NEW_M_FILE).addKind("Notebook", MathematicaIcons.FILE_ICON, "Notebook");
77+
myProject = project;
78+
final MyNameValidator nameValidator = new MyNameValidator(MathematicaFileType.DEFAULT_EXTENSIONS);
79+
builder.setTitle(NEW_M_FILE).addKind(PACKAGE, MathematicaIcons.FILE_ICON, PACKAGE);
80+
builder.setTitle(NEW_M_FILE).addKind(PLAIN, MathematicaIcons.FILE_ICON, PLAIN);
81+
builder.setTitle(NEW_M_FILE).addKind(TEST, MathematicaIcons.FILE_ICON, TEST);
82+
builder.setTitle(NEW_M_FILE).addKind(NOTEBOOK, MathematicaIcons.FILE_ICON, NOTEBOOK);
83+
builder.setValidator(nameValidator);
8284
}
8385

8486
@Override
@@ -98,9 +100,79 @@ public boolean equals(Object obj) {
98100

99101
@Override
100102
protected PsiFile createFile(String name, String templateName, PsiDirectory dir) {
101-
final FileTemplate template = FileTemplateManager.getInstance(dir.getProject()).getInternalTemplate(templateName);
102-
String fileName = removeExtension(name);
103-
return createFileFromTemplate(fileName, template, dir);
103+
MathematicaLanguageLevel version = null;
104+
final String fileWithoutExtension = StringUtil.trimExtensions(name);
105+
final Module module = ModuleUtilCore.findModuleForFile(dir.getVirtualFile(), myProject);
106+
if (module != null) {
107+
final MathematicaLanguageLevelModuleExtension languageLevelModuleExtension =
108+
MathematicaLanguageLevelModuleExtension.getInstance(module);
109+
if (languageLevelModuleExtension != null) {
110+
version = languageLevelModuleExtension.getMathematicaLanguageLevel();
111+
} else {
112+
final Sdk projectSdk = ProjectRootManager.getInstance(myProject).getProjectSdk();
113+
if (projectSdk instanceof MathematicaSdkType) {
114+
version = MathematicaLanguageLevel.createFromSdk(projectSdk);
115+
}
116+
}
117+
}
118+
if (version == null) {
119+
version = MathematicaLanguageLevel.HIGHEST;
120+
}
121+
122+
MathematicaTemplateProperties props = MathematicaTemplateProperties.create();
123+
props.setProperty(MathematicaTemplateProperties.MATHEMATICA_VERSION, version.getName());
124+
props.setProperty(MathematicaTemplateProperties.CONTEXT, fileWithoutExtension + "`");
125+
props.setProperty(MathematicaTemplateProperties.PACKAGE_NAME, fileWithoutExtension);
126+
props.setProperty(MathematicaTemplateProperties.PACKAGE_VERSION, "0.1");
127+
128+
final FileTemplateManager fileTemplateManager = FileTemplateManager.getInstance(myProject);
129+
final Properties defaultProperties = fileTemplateManager.getDefaultProperties();
130+
defaultProperties.putAll(props.getProperties());
131+
132+
final FileTemplate template = fileTemplateManager.getInternalTemplate(templateName);
133+
try {
134+
final PsiElement psiElement = FileTemplateUtil.createFromTemplate(template, name, defaultProperties, dir);
135+
if (psiElement instanceof PsiFile) {
136+
return (PsiFile) psiElement;
137+
}
138+
} catch (Exception e) {
139+
LOG.error("Error while creating new file", e);
140+
}
141+
LOG.error("Could not create file");
142+
return null;
104143
}
105144

145+
/**
146+
* Provides a simple check for file extension
147+
*/
148+
private class MyNameValidator implements InputValidator {
149+
150+
private final String[] myExtensions;
151+
152+
MyNameValidator(String[] myExtensions) {
153+
this.myExtensions = myExtensions;
154+
}
155+
156+
@Override
157+
public boolean checkInput(String inputString) {
158+
return inputString != null && hasValidFileExtension(inputString, myExtensions);
159+
}
160+
161+
private boolean hasValidFileExtension(String input, String... extensions) {
162+
if (FileUtilRt.getNameWithoutExtension(input).equals(input)) {
163+
return true;
164+
}
165+
for (String ext : extensions) {
166+
if (FileUtilRt.extensionEquals(input, ext)) return true;
167+
}
168+
return false;
169+
}
170+
171+
@Override
172+
public boolean canClose(String inputString) {
173+
return checkInput(inputString);
174+
}
175+
}
176+
177+
106178
}

src/de/halirutan/mathematica/file/MathematicaFileTemplateProvider.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,15 @@ public static PsiElement createFromTemplate(@NotNull Project project,
6666
@NotNull Properties properties) throws Exception {
6767
rootDir.refresh(false, false);
6868
PsiDirectory directory = PsiManager.getInstance(project).findDirectory(rootDir);
69+
final Properties defaultProperties = FileTemplateManager.getInstance(project).getDefaultProperties();
70+
defaultProperties.putAll(properties);
6971
if (directory != null) {
70-
return createFromTemplate(project, templateName, fileName, directory, properties);
72+
return createFromTemplate(project, templateName, fileName, directory, defaultProperties);
7173
}
7274
return null;
7375
}
7476

77+
@SuppressWarnings("UnusedReturnValue")
7578
@Nullable
7679
public static PsiElement createFromTemplate(@NotNull Project project,
7780
@NotNull VirtualFile rootDir,

src/de/halirutan/mathematica/file/MathematicaFileType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323

2424
import com.intellij.openapi.fileTypes.LanguageFileType;
2525
import de.halirutan.mathematica.Mathematica;
26-
import de.halirutan.mathematica.util.MathematicaIcons;
2726
import de.halirutan.mathematica.lang.MathematicaLanguage;
27+
import de.halirutan.mathematica.util.MathematicaIcons;
2828
import org.jetbrains.annotations.NotNull;
2929
import org.jetbrains.annotations.Nullable;
3030

@@ -37,7 +37,7 @@
3737
public class MathematicaFileType extends LanguageFileType {
3838

3939
public static final LanguageFileType INSTANCE = new MathematicaFileType();
40-
private static final String[] DEFAULT_EXTENSIONS = {"m", "mt", "nb", "mb"};
40+
public static final String[] DEFAULT_EXTENSIONS = {"m", "mt", "nb", "mb", "wl", "wlt"};
4141

4242
private MathematicaFileType() {
4343
super(MathematicaLanguage.INSTANCE);

0 commit comments

Comments
 (0)