1.12 ★ External Comment for COBOL etc | 外部注释用于 COBOL 等

This commit is contained in:
林万程
2022-04-06 23:08:03 +08:00
parent ac4ed47c9f
commit 879d61e34a
45 changed files with 1625 additions and 88 deletions

View File

@@ -3,47 +3,94 @@ IDEA 智能注释插件
https://plugins.jetbrains.com/plugin/18553-show-comment
English Notes:
## Notes 说明
<h2>English Notes:</h2>
<ul>
<li>Show javadoc comments at the Project view Tree structure
<li>Show javadoc comments at the end-of-line
<li>Show javadoc comments at "xx ClassNameOrSimpleName.json" and jump to field
<li>Config: settings -> Tools -> Show Comment Global/Project
<li>Config: settings -> Tools -> // Show Comment Global/Project
</ul>
Chinese Notes:
<h3>External Comment:</h3>
<ul>
<li>Reload: Tools -> 🔄 // Reload External Comment
<li>path/[any][filename.]ext.tree.tsv // file and folder tree comment 📝 📁
<li>path/[any][filename.]ext.key.tsv // line keywords to split and comment
<li>path/[any][filename.]ext.doc.tsv // line words comment
<li>In path, "doc" can replace any, and can use % like in SQL
<li>The line in key.tsv would concat lines with `|` to regexp, longer str should in front, startWith `?` to exclude
<li>Chang tsv file in find pop window would not reload!
<li>The tsv conf file must could be search in "Go to File"(Ctrl + Shift + N)
</ul>
<h2>中文说明:</h2>
<ul>
<li>在结构树显示 文档注释
<li>在行末尾显示 文档注释
<li>支持 "xx 类全名或简名.json" 文档注释与跳转到字段
<li>修改配置:设置 -> 工具 -> Show Comment Global/Project
<li>修改配置:设置 -> 工具 -> // Show Comment Global/Project
</ul>
English Change Notes:
<h3>外部注释:</h3>
<ul>
<li>重新加载:工具 -> "🔄 // Reload External Comment"
<li>path/[any][filename.]ext.tree.tsv // 文件(夹)注释 📝 📁
<li>path/[any][filename.]ext.key.tsv // 切割关键字与注释
<li>path/[any][filename.]ext.doc.tsv // 词注释
<li>key.tsv 的每一行将会用`|`连接起来形成正则表达式,较长的关键字应该放在前面,用 `?` 开头排除
<li>doc 文件夹可以替换任何一层文件夹,可以像 SQL 那样用 % 模糊匹配
<li>在搜索弹出窗中修改 tsv 文件将不会被重加载
<li>tsv 配置文件必须能被搜索(Ctrl + Shift + N)
</ul>
## Change Notes 更新说明
<h2>English Change Notes:</h2>
<ul>
<li>1.12 ★ External Comment for COBOL etc
<li>1.11 Add json key jump to field
<li>1.10 Add project-view-tree-comment for package from parent or other project
<li>1.9 Add project-view-tree-comment for "xx ClassNameOrSimpleName.json" and SPI file
<li>1.8 Add line-end-comment for "xx ClassNameOrSimpleName.json"
<li>1.8 line-end-comment for "xx ClassNameOrSimpleName.json"
<li>1.7 Add line-end-comment setting for prefix and count
<li>1.6 Add line-end-comment independent switch for call, new, ref
<li>1.5 Add line-end-comment find next loop when none
<li>1.4 Add line-end-comment find element right to left
<li>1.3 Add project-view-tree-comment
<li>1.3 project-view-tree-comment
<li>1.2 Add line-end-comment settings fro class prefix filter
<li>1.1 Add line-end-comment settings for text color
</ul>
Chinese Change Notes:
<h2>中文更新说明:</h2>
<ul>
<li>1.11 增加 json 跳转到字段
<li>1.12 ★ 外部注释用于 COBOL 等
<li>1.11 增加 json 跳转到字段
<li>1.10 增加 在父包和其他项目的包中获取 项目导航栏注释
<li>1.9 增加 "xx 类全名或简名.json" 和 SPI 项目导航栏注释
<li>1.8 增加 "xx 类全名或简名.json" 行末注释
<li>1.8 "xx 类全名或简名.json" 行末注释
<li>1.7 增加 行末注释前缀和对象数设置
<li>1.6 增加 行末调用new引用注释独立开关
<li>1.5 增加 没有注释时循环查找下一个对象
<li>1.4 增加 从右往左查找行末注释对象
<li>1.3 增加 项目导航栏注释
<li>1.3 项目导航栏注释
<li>1.2 增加 行末注释类前缀配置
<li>1.1 增加 行末文本颜色配置
</ul>
</ul>
### Demo 示例
See in IDEA with this plugin | 安装插件后用 IDEA 查看
- [Java Doc Comment Demo | Java 文档注释](src/test/java/io/github/linwancen/plugin/show/demo/java/Call.java)
- [JSON Doc Comment Demo | JSON 文档注释](src/test/java/io/github/linwancen/plugin/show/demo/json/base Pojo.json)
- [External Comment Demo For COBOL | 外部注释 Demo](src/test/java/io/github/linwancen/plugin/show/demo/ext/cobol/demo/BASE.cbl)
[COBOL Highlighting | COBOL 高亮配置](src/test/java/io/github/linwancen/plugin/show/demo/ext/cobol/COBOL_IDEA.md)

View File

@@ -4,7 +4,7 @@ plugins {
}
group 'io.github.linwancen'
version '1.11.0.' + (new Date().format('yyyy.MM.dd_HH.mm'))
version '1.12.0.' + (new Date().format('yyyy.MM.dd_HH.mm'))
apply plugin: 'java'
@@ -37,32 +37,34 @@ patchPluginXml {
sinceBuild = '201.1'
untilBuild = ''
changeNotes = """
English Change Notes:
<h2>English Change Notes:</h2>
<ul>
<li>1.12 ★ External Comment for COBOL etc
<li>1.11 Add json key jump to field
<li>1.10 Add project-view-tree-comment for package from parent or other project
<li>1.9 Add project-view-tree-comment for "xx ClassNameOrSimpleName.json" and SPI file
<li>1.8 Add line-end-comment for "xx ClassNameOrSimpleName.json"
<li>1.8 line-end-comment for "xx ClassNameOrSimpleName.json"
<li>1.7 Add line-end-comment setting for prefix and count
<li>1.6 Add line-end-comment independent switch for call, new, ref
<li>1.5 Add line-end-comment find next loop when none
<li>1.4 Add line-end-comment find element right to left
<li>1.3 Add project-view-tree-comment
<li>1.3 project-view-tree-comment
<li>1.2 Add line-end-comment settings fro class prefix filter
<li>1.1 Add line-end-comment settings for text color
</ul>
Chinese Change Notes:
<h2>中文更新说明:</h2>
<ul>
<li>1.12 ★ 外部注释用于 COBOL 等
<li>1.11 增加 json 跳转到字段
<li>1.10 增加 在父包和其他项目的包中获取 项目导航栏注释
<li>1.9 增加 "xx 类全名或简名.json" 和 SPI 项目导航栏注释
<li>1.8 增加 "xx 类全名或简名.json" 行末注释
<li>1.8 "xx 类全名或简名.json" 行末注释
<li>1.7 增加 行末注释前缀和对象数设置
<li>1.6 增加 行末调用new引用注释独立开关
<li>1.5 增加 没有注释时循环查找下一个对象
<li>1.4 增加 从右往左查找行末注释对象
<li>1.3 增加 项目导航栏注释
<li>1.3 项目导航栏注释
<li>1.2 增加 行末注释类前缀配置
<li>1.1 增加 行末文本颜色配置
</ul>

29
settings-offline.gradle Normal file
View File

@@ -0,0 +1,29 @@
// gradle/init.d/init.gradle use allprojects {
// settings.gradle use pluginManagement {
pluginManagement {
repositories {
all { ArtifactRepository repo ->
if (repo instanceof MavenArtifactRepository) {
def url = repo.url.toString()
if (url.startsWith("https://repo1.maven.org/maven2")
|| url.startsWith("https://jcenter.bintray.com/")
|| url.startsWith("https://cache-redirector.jetbrains.com")) {
project.logger.lifecycle("remove Repository ${repo.url}.")
remove(repo)
}
}
}
mavenLocal()
maven { name "jetbrains-cache"; url "" }
maven { name "maven-cache"; url "" }
}
buildscript {
repositories {
mavenLocal()
maven { name "jetbrains-cache"; url "" }
}
}
}
rootProject.name = 'show-comment'

View File

@@ -13,7 +13,9 @@ import io.github.linwancen.plugin.show.json.JsonRef;
import io.github.linwancen.plugin.show.json.JsonUtils;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class JsonJump extends PsiReferenceContributor {

View File

@@ -14,6 +14,7 @@ import com.intellij.psi.javadoc.PsiDocComment;
import io.github.linwancen.plugin.show.doc.DocTextUtils;
import io.github.linwancen.plugin.show.line.LineDocLeftToRightUtils;
import io.github.linwancen.plugin.show.line.LineDocRightToLeftUtils;
import io.github.linwancen.plugin.show.ext.LineExtUtils;
import io.github.linwancen.plugin.show.settings.AppSettingsState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,20 +34,23 @@ public class LineEnd extends EditorLinePainter {
if (DumbService.isDumb(project)) {
return null;
}
FileViewProvider viewProvider = PsiManager.getInstance(project).findViewProvider(file);
PsiDocComment docComment = doc(project, viewProvider, lineNumber);
String comment = DocTextUtils.text(docComment);
if (comment == null) {
if (!file.exists()) {
return null;
}
String doc = doc(project, file, lineNumber);
if (doc == null) {
return null;
}
TextAttributes textAttr = file.getFileType().equals(JsonFileType.INSTANCE)
? settings.lineEndJsonTextAttr
: settings.lineEndTextAttr;
LineExtensionInfo info = new LineExtensionInfo(settings.lineEndPrefix + comment, textAttr);
LineExtensionInfo info = new LineExtensionInfo(settings.lineEndPrefix + doc, textAttr);
return Collections.singletonList(info);
}
private static @Nullable PsiDocComment doc(Project project, FileViewProvider viewProvider, int lineNumber) {
private static @Nullable String doc(@NotNull Project project,
@NotNull VirtualFile file, int lineNumber) {
FileViewProvider viewProvider = PsiManager.getInstance(project).findViewProvider(file);
if (viewProvider == null) {
return null;
}
@@ -63,9 +67,13 @@ public class LineEnd extends EditorLinePainter {
if (startOffset == endOffset) {
return null;
}
if (AppSettingsState.getInstance().findElementRightToLeft) {
return LineDocRightToLeftUtils.rightDoc(viewProvider, startOffset, endOffset);
String ext = LineExtUtils.extDoc(project, file, document, startOffset, endOffset);
if (ext != null) {
return ext;
}
return LineDocLeftToRightUtils.leftDoc(viewProvider, document, startOffset, endOffset);
PsiDocComment docComment = AppSettingsState.getInstance().findElementRightToLeft
? LineDocRightToLeftUtils.rightDoc(viewProvider, startOffset, endOffset)
: LineDocLeftToRightUtils.leftDoc(viewProvider, document, startOffset, endOffset);
return DocTextUtils.text(docComment);
}
}

View File

@@ -5,6 +5,7 @@ import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.ProjectViewNodeDecorator;
import com.intellij.ide.projectView.impl.nodes.*;
import com.intellij.ide.util.treeView.PresentableNodeDescriptor.ColoredFragment;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -15,6 +16,7 @@ import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
import io.github.linwancen.plugin.show.doc.DocTextUtils;
import io.github.linwancen.plugin.show.doc.DocUtils;
import io.github.linwancen.plugin.show.ext.TreeExtUtils;
import io.github.linwancen.plugin.show.settings.AppSettingsState;
import org.jetbrains.annotations.Nullable;
@@ -34,25 +36,43 @@ public class Tree implements ProjectViewNodeDecorator {
if (DumbService.isDumb(project)) {
return;
}
PsiDocComment docComment = nodeDoc(node, project);
if (docComment == null) {
return;
}
String commentText = DocTextUtils.text(docComment);
if (commentText == null) {
return;
}
List<ColoredFragment> coloredText = data.getColoredText();
if (coloredText.isEmpty()) {
data.addText(data.getPresentableText(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
data.addText(commentText, SimpleTextAttributes.GRAY_ATTRIBUTES);
ApplicationManager.getApplication().runReadAction(() -> {
String doc = doc(node, project);
if (doc == null) {
return;
}
List<ColoredFragment> coloredText = data.getColoredText();
if (coloredText.isEmpty()) {
data.addText(data.getPresentableText(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
data.addText(doc, SimpleTextAttributes.GRAY_ATTRIBUTES);
});
}
@Nullable
private PsiDocComment nodeDoc(ProjectViewNode<?> node, Project project) {
private String doc(ProjectViewNode<?> node, Project project) {
String extDoc = extDoc(node, project);
if (extDoc != null) {
return extDoc;
}
PsiDocComment docComment = nodeDoc(node, project);
if (docComment == null) {
return null;
}
return DocTextUtils.text(docComment);
}
@Nullable
public static String extDoc(ProjectViewNode<?> node, Project project) {
VirtualFile file = node.getVirtualFile();
if (file == null) {
return null;
}
return TreeExtUtils.extDoc(project, file);
}
@Nullable
private static PsiDocComment nodeDoc(ProjectViewNode<?> node, Project project) {
if (node instanceof PsiFileNode) {
PsiFile psiFile = ((PsiFileNode) node).getValue();
return DocUtils.fileDoc(psiFile);
@@ -97,7 +117,7 @@ public class Tree implements ProjectViewNodeDecorator {
}
@Nullable
private PsiDocComment dirDoc(PsiDirectory child) {
private static PsiDocComment dirDoc(PsiDirectory child) {
while (true) {
PsiDocComment docComment = DocUtils.dirDoc(child);
if (docComment != null) {
@@ -115,7 +135,7 @@ public class Tree implements ProjectViewNodeDecorator {
}
@Nullable
private PsiDocComment packageDoc(PsiPackage child) {
private static PsiDocComment packageDoc(PsiPackage child) {
while (true) {
PsiDocComment docComment = DocUtils.packageDoc(child);
if (docComment != null) {

View File

@@ -7,9 +7,6 @@ import com.intellij.psi.javadoc.PsiInlineDocTag;
import io.github.linwancen.plugin.show.settings.AppSettingsState;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class DocTextUtils {
private DocTextUtils() {}
@@ -20,30 +17,40 @@ public class DocTextUtils {
return null;
}
AppSettingsState appSettings = AppSettingsState.getInstance();
List<String> comments = new ArrayList<>();
int lineCount = 0;
StringBuilder sb = new StringBuilder();
PsiElement[] elements = psiDocComment.getDescriptionElements();
for (PsiElement element : elements) {
if (element instanceof PsiDocToken) {
PsiDocToken psiDocToken = (PsiDocToken) element;
comments.add(psiDocToken.getText());
} else if (element instanceof PsiInlineDocTag) {
PsiInlineDocTag psiInlineDocTag = (PsiInlineDocTag) element;
PsiElement[] children = psiInlineDocTag.getChildren();
if (children.length > 2) {
comments.add(children[2].getText());
}
if (appendElementText(sb, element)) {
lineCount++;
}
if (appSettings.lineEndCount > 0 && comments.size() >= appSettings.lineEndCount) {
if (appSettings.lineEndCount > 0
&& lineCount >= appSettings.lineEndCount
|| appSettings.lineEndLen > 0
&& sb.length() >= appSettings.lineEndLen) {
break;
}
}
if (comments.isEmpty()) {
if (sb.length() == 0) {
return null;
}
StringBuilder sb = new StringBuilder(" ");
for (String s : comments) {
sb.append(s.trim().replace("<br>", "")).append(" ");
}
sb.insert(0, " ");
return sb.toString();
}
private static boolean appendElementText(StringBuilder sb, PsiElement element) {
if (element instanceof PsiDocToken) {
PsiDocToken psiDocToken = (PsiDocToken) element;
sb.append(psiDocToken.getText().trim().replace("<br>", "")).append(" ");
return true;
}
if (element instanceof PsiInlineDocTag) {
PsiInlineDocTag psiInlineDocTag = (PsiInlineDocTag) element;
PsiElement[] children = psiInlineDocTag.getChildren();
if (children.length > 2) {
sb.append(children[2].getText().trim().replace("<br>", "")).append(" ");
}
}
return false;
}
}

View File

@@ -0,0 +1,38 @@
package io.github.linwancen.plugin.show.ext;
import io.github.linwancen.plugin.show.settings.ProjectSettingsState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
class DocMapUtils {
private DocMapUtils() {}
@Nullable
static String get(@NotNull Map<String, Map<String, List<String>>> docMap,
@NotNull ProjectSettingsState set, @NotNull String... words) {
List<String> keywordDoc = list(docMap, words);
if (keywordDoc.size() >= set.extDocColumn) {
return keywordDoc.get(set.extDocColumn - 1);
}
return null;
}
@NotNull
private static List<String> list(@NotNull Map<String, Map<String, List<String>>> docMap, @NotNull String... words) {
for (Map.Entry<String, Map<String, List<String>>> entry : docMap.entrySet()) {
Map<String, List<String>> map = entry.getValue();
for (String word : words) {
List<String> wordDoc = map.get(word);
if (wordDoc != null) {
return wordDoc;
}
}
}
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,105 @@
package io.github.linwancen.plugin.show.ext;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
import io.github.linwancen.plugin.show.settings.ProjectSettingsState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LineExtUtils {
private LineExtUtils() {}
public static String extDoc(@NotNull Project project, @NotNull VirtualFile file,
@NotNull Document document, int startOffset, int endOffset) {
Map<String, Map<String, List<String>>> keyMap = ConfCache.keyMap(project, file);
if (keyMap.isEmpty()) {
return null;
}
Pattern pattern = ConfCache.pattern(project, file, keyMap);
if (pattern == null || pattern.pattern().length() == 0) {
return null;
}
Map<String, Map<String, List<String>>> docMap = ConfCache.docMap(project, file);
if (docMap.isEmpty()) {
return null;
}
Map<String, Map<String, List<String>>> treeMap = ConfCache.treeMap(project, file);
String text = document.getText(new TextRange(startOffset, endOffset));
String[] words = pattern.split(text);
Matcher matcher = pattern.matcher(text);
return extDoc(keyMap, matcher, docMap, words, treeMap, project);
}
@Nullable
private static String extDoc(@NotNull Map<String, Map<String, List<String>>> keyMap, @NotNull Matcher matcher,
@NotNull Map<String, Map<String, List<String>>> docMap, @NotNull String[] words,
@NotNull Map<String, Map<String, List<String>>> treeMap, @NotNull Project project) {
ProjectSettingsState set = ProjectSettingsState.getInstance(project);
Pattern extReplaceToSpace = set.extReplaceToSpace;
boolean isReplaceToSpace = extReplaceToSpace.pattern().length() != 0;
boolean haveDoc = false;
StringBuilder sb = new StringBuilder();
for (String s : words) {
if (appendDoc(set, sb, docMap, treeMap, extReplaceToSpace, isReplaceToSpace, s)) {
haveDoc = true;
}
appendKeyDoc(set, sb, keyMap, matcher);
}
if (!haveDoc) {
return null;
}
return sb.toString();
}
private static boolean appendDoc(ProjectSettingsState set, StringBuilder sb,
@NotNull Map<String, Map<String, List<String>>> docMap,
@NotNull Map<String, Map<String, List<String>>> treeMap,
Pattern extReplaceToSpace, boolean isReplaceToSpace, String word) {
word = word.trim();
if (isReplaceToSpace) {
word = extReplaceToSpace.matcher(word).replaceAll(" ");
}
if (word.length() == 0) {
return false;
}
String wordDoc = DocMapUtils.get(docMap, set, word);
if (wordDoc != null) {
sb.append(wordDoc);
return true;
}
String treeDoc = DocMapUtils.get(treeMap, set, word);
if (treeDoc != null) {
sb.append(treeDoc);
return true;
}
sb.append(word);
return false;
}
private static void appendKeyDoc(@NotNull ProjectSettingsState set, @NotNull StringBuilder sb,
@NotNull Map<String, Map<String, List<String>>> keyMap,
@NotNull Matcher matcher) {
if (!matcher.find()) {
return;
}
String keyword = matcher.group();
// "" if no doc
String keyDoc = DocMapUtils.get(keyMap, set, keyword);
if (keyDoc != null) {
sb.append(" ").append(keyDoc);
}
// no one space
if (sb.length() != 1) {
sb.append(" ");
}
}
}

View File

@@ -0,0 +1,29 @@
package io.github.linwancen.plugin.show.ext;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import io.github.linwancen.plugin.show.ext.conf.ConfCache;
import io.github.linwancen.plugin.show.settings.ProjectSettingsState;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
public class TreeExtUtils {
private TreeExtUtils() {}
public static String extDoc(@NotNull Project project, @NotNull VirtualFile file) {
Map<String, Map<String, List<String>>> docMap = ConfCache.treeMap(project, file);
ProjectSettingsState set = ProjectSettingsState.getInstance(project);
String[] words = {
file.getName(),
file.getNameWithoutExtension(),
};
String extDoc = DocMapUtils.get(docMap, set, words);
if (extDoc == null) {
return null;
}
return " " + extDoc;
}
}

View File

@@ -0,0 +1,144 @@
package io.github.linwancen.plugin.show.ext.conf;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.FilenameIndex;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
/**
* call ConfFactory, ConfCacheGetUtils
*/
public class ConfCache {
private static final Pattern LINE_PATTERN = Pattern.compile("[\\r\\n]++");
static final String EXT = "tsv";
static final String KEY_MID_EXT = ".key";
static final String DOC_MID_EXT = ".doc";
static final String TREE_MID_EXT = ".tree";
private static final Map<VirtualFile, Map<String, List<String>>> KEY_CACHE = new ConcurrentHashMap<>();
private static final Map<VirtualFile, Map<String, List<String>>> DOC_CACHE = new ConcurrentHashMap<>();
private static final Map<VirtualFile, Map<String, List<String>>> TREE_CACHE = new ConcurrentHashMap<>();
private ConfCache() {}
@Nullable
public static Pattern pattern(@Nullable Project project, @NotNull VirtualFile file,
@NotNull Map<String, Map<String, List<String>>> keyMap) {
return ConfFactory.buildPattern(project, file.getPath(), keyMap);
}
@NotNull
public static Map<String, Map<String, List<String>>> keyMap(@Nullable Project project, @NotNull VirtualFile file) {
return ConfCacheGetUtils.get(file, KEY_MID_EXT, KEY_CACHE);
}
@NotNull
public static Map<String, Map<String, List<String>>> docMap(@Nullable Project project, @NotNull VirtualFile file) {
return ConfCacheGetUtils.get(file, DOC_MID_EXT, DOC_CACHE);
}
@NotNull
public static Map<String, Map<String, List<String>>> treeMap(@Nullable Project project, @NotNull VirtualFile file) {
return ConfCacheGetUtils.get(file, TREE_MID_EXT, TREE_CACHE);
}
static void remove(@NotNull VirtualFile file, String name) {
if (name != null) {
int i = name.lastIndexOf('.');
name = name.substring(0, i);
} else {
name = file.getNameWithoutExtension();
}
if (name.endsWith(KEY_MID_EXT)) {
KEY_CACHE.remove(file);
} else if (name.endsWith(DOC_MID_EXT)) {
DOC_CACHE.remove(file);
} else if (name.endsWith(TREE_MID_EXT)) {
TREE_CACHE.remove(file);
}
}
static void copy(@NotNull VirtualFile file, @NotNull VirtualFile newFile) {
String name = file.getNameWithoutExtension();
if (name.endsWith(KEY_MID_EXT)) {
copyCache(file, newFile, KEY_CACHE);
} else if (name.endsWith(DOC_MID_EXT)) {
copyCache(file, newFile, DOC_CACHE);
} else if (name.endsWith(TREE_MID_EXT)) {
copyCache(file, newFile, TREE_CACHE);
}
}
private static void copyCache(@Nullable VirtualFile file, @NotNull VirtualFile newFile,
@NotNull Map<VirtualFile, Map<String, List<String>>> cache) {
Map<String, List<String>> map = cache.get(file);
if (map != null) {
cache.put(newFile, new LinkedHashMap<>(map));
}
}
private static final NotificationGroup LOAD_ALL_LOG =
new NotificationGroup("Ext Doc Conf Load All", NotificationDisplayType.BALLOON, true);
static void loadAll(@NotNull Project project) {
ApplicationManager.getApplication().runReadAction(() ->
DumbService.getInstance(project).runReadActionInSmartMode(() -> {
Collection<VirtualFile> files = FilenameIndex.getAllFilesByExt(project, EXT);
StringBuilder sb = new StringBuilder();
KEY_CACHE.clear();
DOC_CACHE.clear();
TREE_CACHE.clear();
for (VirtualFile file : files) {
load(project, file);
sb.append(file.getPath()).append("\n");
}
if (files.isEmpty()) {
return;
}
LOAD_ALL_LOG.createNotification("Ext doc conf load all complete", files.size() + " files",
sb.toString(), NotificationType.INFORMATION).notify(project);
}));
}
static void loadFile(@Nullable Project project, @NotNull VirtualFile file) {
ApplicationManager.getApplication().runReadAction(() -> ConfCache.load(project, file));
}
private static void load(@Nullable Project project, @NotNull VirtualFile file) {
if (!ConfCache.EXT.equals(file.getExtension())) {
return;
}
Document document = FileDocumentManager.getInstance().getDocument(file);
if (document == null) {
return;
}
String text = document.getText();
String name = file.getNameWithoutExtension();
// this pattern would skip empty line
String[] lines = LINE_PATTERN.split(text);
if (name.endsWith(KEY_MID_EXT)) {
KEY_CACHE.put(file, ConfFactory.buildMap(project, file.getPath(), lines, true));
} else if (name.endsWith(DOC_MID_EXT)) {
DOC_CACHE.put(file, ConfFactory.buildMap(project, file.getPath(), lines, false));
} else if (name.endsWith(TREE_MID_EXT)) {
TREE_CACHE.put(file, ConfFactory.buildMap(project, file.getPath(), lines, false));
}
}
}

View File

@@ -0,0 +1,111 @@
package io.github.linwancen.plugin.show.ext.conf;
import com.intellij.openapi.vfs.VirtualFile;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.TreeMap;
class ConfCacheGetUtils {
private static final String SKIP_PATH = "doc";
private static final String MATCH_STR = "%";
private ConfCacheGetUtils() {}
/**
* <br>file:
* <br>a/b/c.ext
* <br>
* <br>configure file priority:
* <br>a/b/c.ext.key.tsv
* <br>a/b/x.c.ext.key.tsv
* <br>a/b/ext.key.tsv
* <br>a/b/x.ext.key.tsv
* <br>a/c.ext.key.tsv
*
* @return {@code <sortKey, T>}
*/
@NotNull
static <T> TreeMap<String, T> get(@NotNull VirtualFile file,
@NotNull String confMidExt,
@NotNull Map<VirtualFile, T> cache) {
String path = file.getPath();
String name = file.getName();
String ext = file.getExtension();
if (ext == null) {
ext = "";
}
TreeMap<String, T> map = new TreeMap<>();
int max = path.length();
int length = String.valueOf(max).length();
for (Map.Entry<VirtualFile, T> entry : cache.entrySet()) {
VirtualFile confFile = entry.getKey();
String confName = confFile.getNameWithoutExtension();
String confPath = confFile.getPath();
int level = level(path, confPath);
if (level == 0) {
continue;
}
String levelStr = StringUtils.leftPad(String.valueOf(max - level), length, '0');
if ((name + confMidExt).equals(confName)) {
map.put(levelStr + "\b" + confPath, entry.getValue());
} else if (confName.endsWith((name + confMidExt))) {
map.put(levelStr + "\t" + confPath, entry.getValue());
} else if ((ext + confMidExt).equals(confName)) {
map.put(levelStr + "\n" + confPath, entry.getValue());
} else if (confName.endsWith((ext + confMidExt))) {
map.put(levelStr + "\f" + confPath, entry.getValue());
}
}
return map;
}
private static int level(String path, String confPath) {
path = srcPath(path);
confPath = srcPath(confPath);
String[] paths = StringUtils.split(path, '/');
String[] confPaths = StringUtils.split(confPath, '/');
int length = confPaths.length;
if (length > paths.length) {
return 0;
}
for (int i = 0; i < length; i++) {
if (!match(paths[i], confPaths[i])) {
return i;
}
}
return length;
}
@NotNull
private static String srcPath(String path) {
int i = path.indexOf('!');
if (i != -1) {
return path.substring(i + 1);
}
i = path.indexOf("/resources");
if (i != -1) {
return path.substring(i + "/resources".length());
}
return path;
}
private static boolean match(String path, String confPath) {
if (confPath.equals(path) || SKIP_PATH.equals(confPath)) {
return true;
}
boolean end = false;
boolean start = false;
if (confPath.startsWith(MATCH_STR)) {
confPath = confPath.substring(1);
end = true;
}
if (confPath.endsWith(MATCH_STR)) {
confPath = confPath.substring(0, confPath.length() - 1);
start = true;
}
return end && path.endsWith(confPath) || start && path.startsWith(confPath);
}
}

View File

@@ -0,0 +1,98 @@
package io.github.linwancen.plugin.show.ext.conf;
import com.google.common.base.Splitter;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.project.Project;
import com.twelvemonkeys.util.LinkedSet;
import groovy.json.StringEscapeUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
class ConfFactory {
private static final Pattern EMPTY_PATTERN = Pattern.compile("");
private static final Map<String, Pattern> PATTERN_CACHE = new ConcurrentHashMap<>();
private static final NotificationGroup REGEXP_LOG =
new NotificationGroup("Ext Doc Keyword Regexp Compile", NotificationDisplayType.TOOL_WINDOW, true);
private static final NotificationGroup DATA_LOG =
new NotificationGroup("Ext Doc Data", NotificationDisplayType.BALLOON, true);
private ConfFactory() {}
@Nullable
static Pattern buildPattern(@Nullable Project project, @NotNull String path,
@NotNull Map<String, Map<String, List<String>>> map) {
Set<String> exclude = new LinkedSet<>();
StringBuilder sb = new StringBuilder();
for (Map<String, List<String>> keyMap : map.values()) {
// key() is escape
for (List<String> list : keyMap.values()) {
String key = list.get(0);
if (key.startsWith("?")) {
exclude.add(key.substring(1));
} else if (key.length() > 0 && !exclude.contains(key)) {
sb.append(key).append("|");
}
}
}
if (sb.length() > 0) {
sb.delete(sb.length() - 1, sb.length());
}
String regex = sb.toString();
Pattern pattern = PATTERN_CACHE.get(regex);
if (pattern != null) {
return pattern;
}
sb.insert(0, "\n");
sb.insert(0, path);
sb.insert(0, "\n");
try {
Pattern compile = Pattern.compile(regex);
PATTERN_CACHE.put(regex, compile);
REGEXP_LOG.createNotification("Ext doc keyword regexp compile success", regex.length() + " chars",
sb.toString(), NotificationType.INFORMATION).notify(project);
return compile;
} catch (Exception e) {
sb.insert(0, "\n");
sb.insert(0, e.getLocalizedMessage());
PATTERN_CACHE.put(regex, EMPTY_PATTERN);
REGEXP_LOG.createNotification("Ext doc keyword regexp compile fail", regex.length() + " chars",
sb.toString(), NotificationType.ERROR).notify(project);
return null;
}
}
public static final Pattern DEL_PATTERN = Pattern.compile("\\(\\?[^)]++\\)");
@NotNull
static Map<String, List<String>> buildMap(@Nullable Project project, @NotNull String path,
@NotNull String[] lines, boolean isKey) {
Map<String, List<String>> map = new LinkedHashMap<>();
for (String line : lines) {
List<String> words = Splitter.on('\t').splitToList(line);
if (!words.isEmpty()) {
String key = words.get(0);
if (key.length() == 0) {
continue;
}
if (isKey) {
key = StringEscapeUtils.unescapeJava(key);
String del = DEL_PATTERN.matcher(key).replaceAll("");
if (del.length() != 0) {
key = del;
}
}
map.put(key, words);
}
}
DATA_LOG.createNotification("Ext doc file load complete", map.size() + " lines",
"\n" + path, NotificationType.INFORMATION).notify(project);
return map;
}
}

View File

@@ -0,0 +1,23 @@
package io.github.linwancen.plugin.show.ext.conf;
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
/**
* call ConfCache.loadFile
*/
public class ConfFileChangeListener implements FileEditorManagerListener {
@Override
public void selectionChanged(@NotNull FileEditorManagerEvent event) {
VirtualFile file = event.getOldFile();
if (file == null) {
return;
}
if (file.exists()) {
ConfCache.loadFile(event.getManager().getProject(), file);
}
}
}

View File

@@ -0,0 +1,17 @@
package io.github.linwancen.plugin.show.ext.conf;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManagerListener;
import org.jetbrains.annotations.NotNull;
/**
* call ConfCache.loadAll
*/
public class ConfFileInitListener implements ProjectManagerListener {
@Override
public void projectOpened(@NotNull Project project) {
ConfCache.loadAll(project);
}
}

View File

@@ -0,0 +1,64 @@
package io.github.linwancen.plugin.show.ext.conf;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.events.*;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* call ConfCache.loadFile, copy, remove
*/
public class ConfFileListener implements BulkFileListener {
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
for (VFileEvent event : events) {
forEvent(event);
}
}
private static void forEvent(VFileEvent event) {
VirtualFile file = event.getFile();
if (file == null) {
return;
}
if (event instanceof VFilePropertyChangeEvent) {
VFilePropertyChangeEvent changeEvent = (VFilePropertyChangeEvent) event;
if ("name".equals(changeEvent.getPropertyName())) {
String oldName = changeEvent.getOldValue().toString();
if (oldName.endsWith(ConfCache.EXT)) {
// change cache too complicated so remove
ConfCache.remove(file, oldName);
}
}
}
if (!ConfCache.EXT.equals(file.getExtension())) {
return;
}
if (event instanceof VFileMoveEvent) {
return;
}
if (event instanceof VFileDeleteEvent) {
ConfCache.remove(file, null);
return;
}
if (event instanceof VFileCopyEvent) {
VFileCopyEvent copyEvent = (VFileCopyEvent) event;
VirtualFile newFile = copyEvent.findCreatedFile();
if (newFile == null) {
return;
}
try {
ConfCache.copy(file, newFile);
} catch (Exception ignored) {
// ignore
}
return;
}
// VFileCreateEvent
// VFileContentChangeEvent
ConfCache.loadFile(null, file);
}
}

View File

@@ -0,0 +1,20 @@
package io.github.linwancen.plugin.show.ext.conf;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* call ConfCache.loadAll
*/
public class ReloadExtDocAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
if (project == null) {
return;
}
ConfCache.loadAll(project);
}
}

View File

@@ -19,24 +19,18 @@ public class LineDocRightToLeftUtils {
// End is always white, can not -1 because @see class.name need it
PsiElement element = viewProvider.findElementAt(endOffset);
if (element == null) {
// one line end
return null;
}
AppSettingsState instance = AppSettingsState.getInstance();
PsiElement identifier;
PsiDocComment psiDocComment;
AppSettingsState setting = AppSettingsState.getInstance();
while (true) {
identifier = PsiTreeUtil.prevVisibleLeaf(element);
PsiElement identifier = PsiTreeUtil.prevVisibleLeaf(element);
if (identifier != null && identifier.getTextRange().getStartOffset() < startOffset) {
identifier = null;
}
if (identifier == null || identifier instanceof PsiIdentifier) {
if (instance.inJson && element.getLanguage().is(JsonLanguage.INSTANCE)) {
return JsonDocUtils.jsonDoc(element, startOffset, endOffset);
}
psiDocComment = LineDocUtils.elementDoc(element, identifier, startOffset, endOffset);
if (psiDocComment != null) {
return psiDocComment;
}
PsiDocComment docComment = psiDoc(setting, identifier, element, startOffset, endOffset);
if (docComment != null) {
return docComment;
}
if (identifier == null) {
return null;
@@ -44,4 +38,16 @@ public class LineDocRightToLeftUtils {
element = identifier;
}
}
public static PsiDocComment psiDoc(AppSettingsState setting,
PsiElement identifier, PsiElement element,
int startOffset, int endOffset) {
if (identifier != null && !(identifier instanceof PsiIdentifier)) {
return null;
}
if (setting.inJson && element.getLanguage().is(JsonLanguage.INSTANCE)) {
return JsonDocUtils.jsonDoc(element, startOffset, endOffset);
}
return LineDocUtils.elementDoc(element, identifier, startOffset, endOffset);
}
}

View File

@@ -22,9 +22,9 @@ public class AppSettingsState implements PersistentStateComponent<AppSettingsSta
public boolean showTreeComment = true;
public boolean showLineEndComment = true;
@SuppressWarnings("all")
@SuppressWarnings("UseJBColor")
public Color lineEndColorBright = new Color(98, 151, 85);
@SuppressWarnings("all")
@SuppressWarnings("UseJBColor")
public Color lineEndColorDark = new Color(98, 151, 85);
public final TextAttributes lineEndTextAttr = new TextAttributes(new JBColor(lineEndColorBright, lineEndColorDark),
null, null, null, Font.ITALIC);
@@ -34,6 +34,7 @@ public class AppSettingsState implements PersistentStateComponent<AppSettingsSta
public boolean findElementRightToLeft = true;
public String lineEndPrefix = " //";
public int lineEndCount = 2;
public int lineEndLen = 0;
public boolean fromCall = true;
public boolean fromNew = true;
public boolean fromRef = true;

View File

@@ -1,7 +1,6 @@
package io.github.linwancen.plugin.show.settings;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.project.Project;
@@ -9,6 +8,8 @@ import com.intellij.util.xmlb.XmlSerializerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.regex.Pattern;
@State(
name = "io.github.linwancen.plugin.comment.settings.ProjectSettingsState",
storages = @Storage("ShowCommentProject.xml")
@@ -21,9 +22,11 @@ public class ProjectSettingsState implements PersistentStateComponent<ProjectSet
public String lineEndExclude = "";
public String[] lineEndIncludeArray = {};
public String[] lineEndExcludeArray = {};
public Pattern extReplaceToSpace = Pattern.compile("");
public int extDocColumn = 2;
public static ProjectSettingsState getInstance(Project project) {
return ServiceManager.getService(project, ProjectSettingsState.class);
return project.getService(ProjectSettingsState.class);
}
@Nullable

View File

@@ -4,19 +4,45 @@
<vendor email="1498425439@qq.com" url="https://github.com/LinWanCen/show-comment">林万程</vendor>
<description><![CDATA[
English Notes:
<h2>English Notes:</h2>
<ul>
<li>Show javadoc comments at the Project view Tree structure
<li>Show javadoc comments at the end-of-line
<li>Show javadoc comments at "xx ClassNameOrSimpleName.json" and jump to field
<li>Config: settings -> Tools -> Show Comment Global/Project
<li>Config: settings -> Tools -> // Show Comment Global/Project
</ul>
Chinese Notes:
<h3>External Comment:</h3>
<ul>
<li>Reload: Tools -> 🔄 // Reload External Comment
<li>path/[any][filename.]ext.tree.tsv // file and folder tree comment 📝 📁
<li>path/[any][filename.]ext.key.tsv // line keywords to split and comment
<li>path/[any][filename.]ext.doc.tsv // line words comment
<li>In path, "doc" can replace any, and can use % like in SQL
<li>The line in key.tsv would concat lines with `|` to regexp, longer str should in front, startWith `?` to exclude
<li>Chang tsv file in find pop window would not reload!
<li>The tsv conf file must could be search in "Go to File"(Ctrl + Shift + N)
</ul>
<h2>中文说明:</h2>
<ul>
<li>在结构树显示 文档注释
<li>在行末尾显示 文档注释
<li>支持 "xx 类全名或简名.json" 文档注释与跳转到字段
<li>修改配置:设置 -> 工具 -> Show Comment Global/Project
<li>修改配置:设置 -> 工具 -> // Show Comment Global/Project
</ul>
<h3>外部注释:</h3>
<ul>
<li>重新加载:工具 -> "🔄 // Reload External Comment"
<li>path/[any][filename.]ext.tree.tsv // 文件(夹)注释 📝 📁
<li>path/[any][filename.]ext.key.tsv // 切割关键字与注释
<li>path/[any][filename.]ext.doc.tsv // 词注释
<li>key.tsv 的每一行将会用`|`连接起来形成正则表达式,较长的关键字应该放在前面,用 `?` 开头排除
<li>doc 文件夹可以替换任何一层文件夹,可以像 SQL 那样用 % 模糊匹配
<li>在搜索弹出窗中修改 tsv 文件将不会被重加载
<li>tsv 配置文件必须能被搜索(Ctrl + Shift + N)
</ul>
]]></description>
@@ -25,6 +51,21 @@ Chinese Notes:
<depends>com.intellij.modules.platform</depends>
<depends>com.intellij.modules.java</depends>
<applicationListeners>
<listener class="io.github.linwancen.plugin.show.ext.conf.ConfFileListener"
topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"/>
</applicationListeners>
<applicationListeners>
<listener class="io.github.linwancen.plugin.show.ext.conf.ConfFileChangeListener"
topic="com.intellij.openapi.fileEditor.FileEditorManagerListener"/>
</applicationListeners>
<projectListeners>
<listener class="io.github.linwancen.plugin.show.ext.conf.ConfFileInitListener"
topic="com.intellij.openapi.project.ProjectManagerListener"/>
</projectListeners>
<extensions defaultExtensionNs="com.intellij">
<editor.linePainter implementation="io.github.linwancen.plugin.show.LineEnd" />
<projectViewNodeDecorator implementation="io.github.linwancen.plugin.show.Tree"/>
@@ -32,18 +73,24 @@ Chinese Notes:
<applicationConfigurable parentId="tools"
instance="io.github.linwancen.plugin.show.settings.AppSettingsConfigurable"
id="io.github.linwancen.plugin.show.settings.AppSettingsConfigurable"
displayName="Show Comment Global"/>
displayName="// Show Comment Global"/>
<applicationService serviceImplementation="io.github.linwancen.plugin.show.settings.AppSettingsState"/>
<projectConfigurable parentId="tools"
instance="io.github.linwancen.plugin.show.settings.ProjectSettingsConfigurable"
id="io.github.linwancen.plugin.show.settings.ProjectSettingsConfigurable"
displayName="Show Comment Project"/>
displayName="// Show Comment Project"/>
<projectService serviceImplementation="io.github.linwancen.plugin.show.settings.ProjectSettingsState"/>
<psi.referenceContributor implementation="io.github.linwancen.plugin.show.JsonJump"/>
</extensions>
<actions>
<action
id="io.github.linwancen.plugin.show.ext.conf.ReLoadExtDocAction"
class="io.github.linwancen.plugin.show.ext.conf.ReloadExtDocAction"
text="🔄 // Reload External Comment">
<add-to-group group-id="ToolsMenu"/>
</action>
</actions>
</idea-plugin>

View File

@@ -0,0 +1,27 @@
COBOL 算数词汇【关键字】
ADD/SUBTRACT CORR WS-GROUP1 TO WS-GROUP2 // 数组间很少用
GIVING =>
ADD A B TO C D // C = A + B + C; D = A + B + D
ADD A B C TO D GIVING E // E = A + B + C + D
TO 是基本关键字 => 这里忽略
ADD +
SUBTRACT A B FROM C D // C = C - (A + B); D = D - (A + B)
SUBTRACT A B C FROM D GIVING E // E = D - (A + B + C)
SUBTRACT -
FROM 从
MULTIPLY A BY B C // B = A * B; C = A * C
MULTIPLY A BY B GIVING C // C = A * B
MULTIPLY *
BY by
DIVIDE A INTO B // B = B / A;
DIVIDE A BY B GIVING C REMAINDER D // C = A / B ... D
DIVIDE ÷
INTO 从
REMAINDER 余
1 COBOL 算数词汇【关键字】
2 ADD/SUBTRACT CORR WS-GROUP1 TO WS-GROUP2 // 数组间很少用
3 GIVING =>
4 ADD A B TO C D // C = A + B + C; D = A + B + D
5 ADD A B C TO D GIVING E // E = A + B + C + D
6 TO 是基本关键字 => 这里忽略
7 ADD +
8 SUBTRACT A B FROM C D // C = C - (A + B); D = D - (A + B)
9 SUBTRACT A B C FROM D GIVING E // E = D - (A + B + C)
10 SUBTRACT -
11 FROM
12 MULTIPLY A BY B C // B = A * B; C = A * C
13 MULTIPLY A BY B GIVING C // C = A * B
14 MULTIPLY *
15 BY by
16 DIVIDE A INTO B // B = B / A;
17 DIVIDE A BY B GIVING C REMAINDER D // C = A / B ... D
18 DIVIDE ÷
19 INTO
20 REMAINDER

View File

@@ -0,0 +1,6 @@
COBOL 算数符号【关键字】
COMPUTE
\+ +
\- -
\* *
\/ /
1 COBOL 算数符号【关键字】
2 COMPUTE
3 \+ +
4 \- -
5 \* *
6 \/ /

View File

@@ -0,0 +1,6 @@
COBOL 获取词汇(非必要)
DATE 系统日期
DATE YYYYMMDD 系统日期
TIME 系统时间
SYSIN 系统输入
CONSOLE 控制台
1 COBOL 获取词汇(非必要)
2 DATE 系统日期
3 DATE YYYYMMDD 系统日期
4 TIME 系统时间
5 SYSIN 系统输入
6 CONSOLE 控制台

View File

@@ -0,0 +1,3 @@
COBOL 获取【关键字】(非必要)
ACCEPT 获取
FROM 从
1 COBOL 获取【关键字】(非必要)
2 ACCEPT 获取
3 FROM

View File

@@ -0,0 +1,22 @@
COBOL 循环【关键字】(非必要)
PERFORM HELLO-WORLD THRU STRUCT
THRU ~
PERFORM A-PARA UNTIL COUNT=5
PERFORM A-PARA WITH TEST BEFORE UNTIL COUNT=5
PERFORM A-PARA WITH TEST AFTER UNTIL COUNT=5
UNTIL until
COUNT count
WITH TEST BEFORE before
WITH TEST AFTER after
PERFORM A-PARA 5 TIMES.
(?=\d++ TIMES)
PERFORM A-PARA VARYING A FROM 1 BY 1 UNTIL A=5
VARYING varying
GO TO para-1 para-2 para-3 DEPENDING ON x.
DEPENDING ON switch
1 COBOL 循环【关键字】(非必要)
2 PERFORM HELLO-WORLD THRU STRUCT
3 THRU ~
4 PERFORM A-PARA UNTIL COUNT=5
5 PERFORM A-PARA WITH TEST BEFORE UNTIL COUNT=5
6 PERFORM A-PARA WITH TEST AFTER UNTIL COUNT=5
7 UNTIL until
8 COUNT count
9 WITH TEST BEFORE before
10 WITH TEST AFTER after
11 PERFORM A-PARA 5 TIMES.
12 (?=\d++ TIMES)
13 PERFORM A-PARA VARYING A FROM 1 BY 1 UNTIL A=5
14 VARYING varying
15 GO TO para-1 para-2 para-3 DEPENDING ON x.
16 DEPENDING ON switch

View File

@@ -0,0 +1,31 @@
COBOL 字符串【关键字】(非必要)
INSPECT input-string
TALLYING output-count FOR ALL CHARACTERS
INSPECT
TALLYING
FOR ALL CHARACTERS
INSPECT input-string REPLACING ALL char1 BY char2.
REPLACING
STRING ws-string1 DELIMITED BY SPACE
ws-string2 DELIMITED BY SIZE
INTO ws-destination-string
WITH POINTER ws-count
ON OVERFLOW DISPLAY message1
NOT ON OVERFLOW DISPLAY message2
END-STRING.
STRING
DELIMITED
BY by
UNSTRING ws-string DELIMITED BY SPACE
INTO ws-str1, ws-str2
WITH POINTER ws-count
ON OVERFLOW DISPLAY message
NOT ON OVERFLOW DISPLAY message
END-UNSTRING.
1 COBOL 字符串【关键字】(非必要)
2 INSPECT input-string
3 TALLYING output-count FOR ALL CHARACTERS
4 INSPECT
5 TALLYING
6 FOR ALL CHARACTERS
7 INSPECT input-string REPLACING ALL char1 BY char2.
8 REPLACING
9 STRING ws-string1 DELIMITED BY SPACE
10 ws-string2 DELIMITED BY SIZE
11 INTO ws-destination-string
12 WITH POINTER ws-count
13 ON OVERFLOW DISPLAY message1
14 NOT ON OVERFLOW DISPLAY message2
15 END-STRING.
16 STRING
17 DELIMITED
18 BY by
19 UNSTRING ws-string DELIMITED BY SPACE
20 INTO ws-str1, ws-str2
21 WITH POINTER ws-count
22 ON OVERFLOW DISPLAY message
23 NOT ON OVERFLOW DISPLAY message
24 END-UNSTRING.

View File

@@ -0,0 +1,20 @@
COBOL-file.tsv.tree.tsv 📝 COBOL 相关文件注释
COBOL.cbl.key.tsv COBOL 必要【关键字】
COBOL-struct.cbl.doc.tsv COBOL 文件结构【关键字】
COBOL-data.cbl.key.tsv COBOL 数据部必要【关键字】
COBOL-data-layout.cbl.key.tsv COBOL 数据布局【关键字】
COBOL-data-type.cbl.key.tsv COBOL 数据类型【关键字】
COBOL-compute.cbl.key.tsv COBOL 算数符号【关键字】
COBOL-compute-word.cbl.key.tsv COBOL 算数词汇【关键字】
COBOL-accept.cbl.doc.tsv COBOL 获取词汇(非必要)
COBOL-accept.cbl.key.tsv COBOL 获取【关键字】(非必要)
COBOL-loop.cbl.key.tsv COBOL 循环【关键字】(非必要)
COBOL-string.cbl.key.tsv COBOL 字符串【关键字】(非必要)
COBOL_IDEA.md COBOL IDEA 高亮设置
COBOL_keyword1.md COBOL COBOL IDEA 高亮 普通关键字
1 COBOL-file.tsv.tree.tsv 📝 COBOL 相关文件注释
2 COBOL.cbl.key.tsv COBOL 必要【关键字】
3 COBOL-struct.cbl.doc.tsv COBOL 文件结构【关键字】
4 COBOL-data.cbl.key.tsv COBOL 数据部必要【关键字】
5 COBOL-data-layout.cbl.key.tsv COBOL 数据布局【关键字】
6 COBOL-data-type.cbl.key.tsv COBOL 数据类型【关键字】
7 COBOL-compute.cbl.key.tsv COBOL 算数符号【关键字】
8 COBOL-compute-word.cbl.key.tsv COBOL 算数词汇【关键字】
9 COBOL-accept.cbl.doc.tsv COBOL 获取词汇(非必要)
10 COBOL-accept.cbl.key.tsv COBOL 获取【关键字】(非必要)
11 COBOL-loop.cbl.key.tsv COBOL 循环【关键字】(非必要)
12 COBOL-string.cbl.key.tsv COBOL 字符串【关键字】(非必要)
13 COBOL_IDEA.md COBOL IDEA 高亮设置
14 COBOL_keyword1.md COBOL COBOL IDEA 高亮 普通关键字

View File

@@ -0,0 +1,18 @@
COBOL 文件结构【关键字】
IDENTIFICATION DIVISION 【标识部】
ENVIRONMENT DIVISION 【环境部】
SOURCE-COMPUTER (编译系统)
OBJECT-COMPUTER (执行系统)
CONFIGURATION SECTION [配置节]
INPUT-OUTPUT SECTION [输入输出节]
FILE-CONTROL (外部数据集)
DATA DIVISION 【数据部】
FILE SECTION [文件节]
WORKING-STORAGE SECTION [工作存储节]
LOCAL-STORAGE SECTION [本地存储节]
LINKAGE SECTION [连接节]
PROCEDURE DIVISION 【过程部】
1 COBOL 文件结构【关键字】
2 IDENTIFICATION DIVISION 【标识部】
3 ENVIRONMENT DIVISION 【环境部】
4 SOURCE-COMPUTER (编译系统)
5 OBJECT-COMPUTER (执行系统)
6 CONFIGURATION SECTION [配置节]
7 INPUT-OUTPUT SECTION [输入输出节]
8 FILE-CONTROL (外部数据集)
9 DATA DIVISION 【数据部】
10 FILE SECTION [文件节]
11 WORKING-STORAGE SECTION [工作存储节]
12 LOCAL-STORAGE SECTION [本地存储节]
13 LINKAGE SECTION [连接节]
14 PROCEDURE DIVISION 【过程部】

View File

@@ -0,0 +1,29 @@
COBOL 必要【关键字】
key 文件的注释前面要有制表符
长的要放在短的前面
^.{7}
\. .
\, ,
INITIALIZE 初始化
MOVE
TO =>
IF if
有些程序 THEN 没有换行所以要加这个关键字
THEN
NOT(?! '| ?=) !
AND (?!') &&
OR (?!') ||
兼容单字符字典
\=(?! ?') =
> >
< <
PERFORM call
WS-
(?<!\w)\( (
\) )
1 COBOL 必要【关键字】
2 key 文件的注释前面要有制表符
3 长的要放在短的前面
4 ^.{7}
5 \. .
6 \, ,
7 INITIALIZE 初始化
8 MOVE
9 TO =>
10 IF if
11 有些程序 THEN 没有换行所以要加这个关键字
12 THEN
13 NOT(?! '| ?=) !
14 AND (?!') &&
15 OR (?!') ||
16 兼容单字符字典
17 \=(?! ?') =
18 > >
19 < <
20 PERFORM call
21 WS-
22 (?<!\w)\( (
23 \) )

View File

@@ -0,0 +1,33 @@
# IDEA COBOL 高亮配置
- File -> Settings -> Editor -> File Types
- 文件 -> 设置 -> 编辑器 -> 文件类型
## Syntax Highlighting
Line comment: *
## Keywords
<div style="color:#0033B3">
1 blue 蓝色
</div>
[关键字1列表](COBOL_keyword1.md)
<pre style="color:#74118C">
2 Purple 紫色
END-IF
IF
THEN
</pre>
<pre style="color:#008080">
3 cyanogen 青色
INITIALIZE
</pre>
<pre style="color:#800000">
4 brown 褐色
PERFORM
</pre>

View File

@@ -0,0 +1,410 @@
SET
TO
VARYING
ACCEPT
ACCESS
ADD
ADDRESS
ADVANCING
AFTER
ALL
ALPHABET
ALPHABETIC
ALPHABETIC-LOWER
ALPHABETIC-UPPER
ALPHANUMERIC
ALPHANUMERIC-EDITED
ALSO
ALTER
ALTERNATE
AND
ANY
APPLY
ARE
AREA
AREAS
ASCENDING
ASSIGN
AT
AUTHOR
BASIS
BEFORE
BEGINNING
BINARY
BLANK
BLOCK
BOTTOM
BY
CALL
CANCEL
CBL
CD
CF
CH
CHARACTER
CHARACTERS
CLASS
CLASS-ID
CLOCK-UNITS
CLOSE
COBOL
CODE
CODE-SET
COLLATING
COLUMN
COM-REG
COMMA
COMMON
COMMUNICATION
COMP
COMP-1
COMP-2
COMP-3
COMP-4
COMP-5
COMPUTATIONAL
COMPUTATIONAL-1
COMPUTATIONAL-2
COMPUTATIONAL-3
COMPUTATIONAL-4
COMPUTATIONAL-5
COMPUTE
CONFIGURATION
CONTAINS
CONTENT
CONTINUE
CONTROL
CONTROLS
CONVERTING
COPY
CORR
CORRESPONDING
COUNT
CURRENCY
DATA
DATE-COMPILED
DATE-WRITTEN
DAY
DAY-OF-WEEK
DBCS
DE
DEBUG-CONTENTS
DEBUG-ITEM
DEBUG-LINE
DEBUG-NAME
DEBUG-SUB-1
DEBUG-SUB-2
DEBUG-SUB-3
DEBUGGING
DECIMAL-POINT
DECLARATIVES
DELETE
DELIMITED
DELIMITER
DEPENDING
DESCENDING
DESTINATION
DETAIL
DISPLAY
DISPLAY-1
DIVIDE
DIVISION
DOWN
DUPLICATES
DYNAMIC
EGCS
EGI
EJECT
ELSE
EMI
ENABLE
END
END-ADD
END-CALL
END-COMPUTE
END-DELETE
END-DIVIDE
END-EVALUATE
END-INVOKE
END-MULTIPLY
END-OF-PAGE
END-PERFORM
END-READ
END-RECEIVE
END-RETURN
END-REWRITE
END-SEARCH
END-START
END-STRING
END-SUBTRACT
END-UNSTRING
END-WRITE
ENDING
ENTER
ENTRY
ENVIRONMENT
EOP
EQUAL
ERROR
ESI
EVALUATE
EVERY
EXCEPTION
EXIT
EXTEND
EXTERNAL
FALSE
FD
FILE
FILE-CONTROL
FILLER
FINAL
FIRST
FOOTING
FOR
FROM
FUNCTION
GENERATE
GIVING
GLOBAL
GO
GOBACK
GREATER
GROUP
HEADINHIGH-VALUHIGH-VALUES
I-O
I-O-CONTROL
ID
IDENTIFICATION
IN
INDEX
INDEXED
INDICATE
INHERITS
INITIAL
INITIATE
INPUT
INPUT-OUTPUT
INSERT
INSPECT
INSTALLATION
INTO
INVALID
INVOKE
IS
JUSJUSTIFIE
KANJKE
LABEL
LAST
LEADING
LEFT
LENGTH
LESS
LIMIT
LIMITS
LINAGE
LINAGE-COUNTER
LINE
LINE-COUNTER
LINES
LINKAGE
LOCAL-STORAGE
LOCK
LOW-VALUE
LOW-VALUES
MEMORY
MERGE
MESSAGE
METACLASS
METHOD
METHOD-ID
MODE
MODULES
MORE-LABELS
MOVE
MULTIPLE
MULTIPLY
NATIVE
NATIVE_BINARY
NEGATIVE
NEXT
NO
NOT
NULL
NULLS
NUMBER
NUMERIC
NUMERIC-EDITED
OBJECT
OBJECT-COMPUTER
OCCURS
OF
OFF
OMITTED
ON
OPEN
OPTIONAL
OR
ORDER
ORGANIZATION
OTHER
OUTPUT
OVERFLOW
OVERRIDE
PACKED-DECIMAL
PADDING
PAGE
PAGE-COUNTER
PASSWORD
PF
PH
PIC
PICTURE
PLUS
POINTER
POSITION
POSITIVE
PRINTING
PROCEDURE
PROCEDURE-POINTER
PROCEDURES
PROCEED
PROCESSING
PROGRAM
PROGRAM-ID
PURGE
QUEUQUOTQUOTES
RANDOM
RD
READ
READY
RECEIVE
RECORD
RECORDING
RECORDS
RECURSIVE
REDEFINES
REEL
REFERENCE
REFERENCES
RELATIVE
RELEASE
RELOAD
REMAINDER
REMOVAL
RENAMES
REPLACE
REPLACING
REPORT
REPORTING
REPORTS
REPOSITORY
RERUN
RESERVE
RESET
RETURN
RETURN-CODE
RETURNING
REVERSED
REWIND
REWRITE
RF
RH
RIGHT
ROUNDED
RUN
SAME
SD
SEARCH
SECTION
SECURITY
SEGMENT
SEGMENT-LIMIT
SELECT
SELF
SEND
SENTENCE
SEPARATE
SEQUENCE
SEQUENTIAL
SERVICE
SET
SHIFT-IN
SHIFT-OUT
SIGN
SIZE
SKIP1
SKIP2
SKIP3
SORT
SORT-CONTROL
SORT-CORE-SIZE
SORT-FILE-SIZE
SORT-MERGE
SORT-MESSAGE
SORT-MODE-SIZE
SORT-RETURN
SOURCE
SOURCE-COMPUTER
SPACE
SPACES
SPECIAL-NAMES
STANDARD
STANDARD-1
STANDARD-2
START
STATUS
STOP
STRING
SUB-QUEUE-1
SUB-QUEUE-2
SUB-QUEUE-3
SUBTRACT
SUM
SUPER
SUPPRESS
SYMBOLIC
SYNC
SYNCHRONIZED
TABLE
TALLY
TALLYING
TAPE
TERMINAL
TERMINATE
TEST
TEXT
THAN
THROUGH
THRU
TIME
TIMES
TITLE
TO
TOP
TRACE
TRAILING
TRUE
TYPE
UNIT
UNSTRING
UNTIL
UP
UPON
USAGE
USE
USING
VALUVALUEVARYING
WHEN
WHEN-COMPILED
WITH
WORDS
WORKING-STORAGE
WRITE
WRITE-ONLY
ZERZEROEZEROS

View File

@@ -0,0 +1,10 @@
COBOL 数据布局【关键字】
REDEFINES 重定义
RENAMES 重命名
USAGE IS
COMP 二进制整数
COMP-1 单精度浮点
COMP-2 双精度浮点
COMP-3 压缩十进制
COPY
1 COBOL 数据布局【关键字】
2 REDEFINES 重定义
3 RENAMES 重命名
4 USAGE IS
5 COMP 二进制整数
6 COMP-1 单精度浮点
7 COMP-2 双精度浮点
8 COMP-3 压缩十进制
9 COPY

View File

@@ -0,0 +1,15 @@
COBOL 数据类型【关键字】
66 重命名
77 不能被细分项
88 条件名
9\( ( 数字
A\( ( 字母
X\( ( 字母数字
V\( ( 隐式小数
S\( ( 符号
P\( ( 假定小数
数据
VALUE =
1 COBOL 数据类型【关键字】
2 66 重命名
3 77 不能被细分项
4 88 条件名
5 9\( ( 数字
6 A\( ( 字母
7 X\( ( 字母数字
8 V\( ( 隐式小数
9 S\( ( 符号
10 P\( ( 假定小数
11 数据
12 VALUE =

View File

@@ -0,0 +1,5 @@
COBOL 数据部必要【关键字】
^.{7} +\d{2}
PIC
COPY
REPLACING
1 COBOL 数据部必要【关键字】
2 ^.{7} +\d{2}
3 PIC
4 COPY
5 REPLACING

View File

@@ -0,0 +1,6 @@
ACCEPT HELLO-WORLD FROM DATE
ACCEPT HELLO-WORLD FROM DATE YYYYMMDD
ACCEPT HELLO-WORLD FROM TIME
ACCEPT HELLO-WORLD FROM SYSIN
ACCEPT HELLO-WORLD FROM CONSOLE

View File

@@ -0,0 +1,9 @@
123456 INITIALIZE HELLO-WORLD
IF KEY = '1' AND KEY NOT = '2' AND (B OR NOT C) THEN
MOVE WS-HELLO-WORLD TO HELLO-WORLD
END IF
TABLE(STRUCT)
HELLO-WORLD(1:1)
PERFORM B001-A
* PERFORM STRUCT

View File

@@ -0,0 +1,10 @@
COMPUTE HELLO-WORLD = (A - B) * 100 / (C + D)
END-COMPUTE
ADD A TO B
ADD A B TO C D
SUBTRACT A FROM C
SUBTRACT A B FROM C D
MULTIPLY A BY B C
MULTIPLY A BY B GIVING C
DIVIDE A BY B GIVING C REMAINDER D

View File

@@ -0,0 +1,9 @@
PERFORM STRUCT THRU HELLO-WORLD
END-PERFORM.
PERFORM STRUCT UNTIL COUNT=5
PERFORM STRUCT WITH TEST BEFORE UNTIL COUNT=5
PERFORM STRUCT WITH TEST AFTER UNTIL COUNT=5
PERFORM STRUCT 5 TIMES
PERFORM STRUCT VARYING HELLO-WORLD FROM 1 BY 1 UNTIL HELLO-WORLD=5
GO TO STRUCT DEPENDING ON HELLO-WORLD.

View File

@@ -0,0 +1,22 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. STRUCT.
ENVIRONMENT DIVISION.
SOURCE-COMPUTER. XXX-ZOS.
OBJECT-COMPUTER. XXX-ZOS.
CONFIGURATION SECTION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
01 WS-HELLO-WORLD PIC X(9) VALUE 10 .
LOCAL-STORAGE SECTION.
01 HELLO-WORLD PIC X(9) VALUE 10 .
LINKAGE SECTION.
01 A PIC 9(9) VALUE 10 .
PROCEDURE DIVISION.

View File

@@ -0,0 +1,9 @@
KEY = '1' 字典1
KEY NOT = '2' 非 字典2
HELLO-WORLD 你好世界
B001-A 程序A
A a
B b
C c
D d
HELLO-WORLD(1:1 ( 状态1
1 KEY = '1' 字典1
2 KEY NOT = '2' 非 字典2
3 HELLO-WORLD 你好世界
4 B001-A 程序A
5 A a
6 B b
7 C c
8 D d
9 HELLO-WORLD(1:1 ( 状态1

View File

@@ -0,0 +1 @@
TABLE\( 表(
1 TABLE\( 表(

View File

@@ -0,0 +1,5 @@
ACCEPT 获取示例
BASE 基本示例
COMPUTE ➗ 计算示例
LOOP ♻ 循环示例
STRUCT 结构示例
1 ACCEPT 获取示例
2 BASE 基本示例
3 COMPUTE ➗ 计算示例
4 LOOP ♻ 循环示例
5 STRUCT 结构示例

View File

@@ -0,0 +1,4 @@
cbl.doc.tsv 自定义注释
cbl.key.tsv 自定义【关键字】
file.cbl.tree.tsv 📝 本目录 cbl 文件注释
file.tsv.tree.tsv 📝 本目录 tsv 文件注释
1 cbl.doc.tsv 自定义注释
2 cbl.key.tsv 自定义【关键字】
3 file.cbl.tree.tsv 📝 本目录 cbl 文件注释
4 file.tsv.tree.tsv 📝 本目录 tsv 文件注释

View File

@@ -0,0 +1,6 @@
folder.tsv.tree.tsv 📁 本目录文件夹注释
demo 📝 示例
%em% 前后 %s 匹配
%mo 前 %s 匹配
de% 后 %s 匹配
doc doc 匹配
1 folder.tsv.tree.tsv 📁 本目录文件夹注释
2 demo 📝 示例
3 %em% 前后 %s 匹配
4 %mo 前 %s 匹配
5 de% 后 %s 匹配
6 doc doc 匹配