macros: support passing compound relative path to $FileDirPathFromParent(...)$ macro... appcode/144.938 clion/144.936 dbe/144.931
authorSergey Simonchik <sergey.simonchik@jetbrains.com>
Sun, 8 Nov 2015 22:41:24 +0000 (01:41 +0300)
committerSergey Simonchik <sergey.simonchik@jetbrains.com>
Sun, 8 Nov 2015 22:41:24 +0000 (01:41 +0300)
platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java

index eb68ae221082a13092fe19529a4205c2d5cf4e57..faee0d18ab2f1f437bbf7b6ac47c2da58ba0f26b 100644 (file)
@@ -18,9 +18,16 @@ package com.intellij.ide.macro;
 
 import com.intellij.ide.IdeBundle;
 import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
 
 public class FileDirPathFromParentMacro extends Macro {
+
+  private static final String PATH_DELIMITER = "/";
+
   @Override
   public String getName() {
     return "FileDirPathFromParent";
@@ -41,13 +48,71 @@ public class FileDirPathFromParentMacro extends Macro {
     if(args.length == 0) {
       return super.expand(dataContext, args);
     }
-    String param = args[0];
-    VirtualFile vFile = getVirtualDirOrParent(dataContext);
-    StringBuilder result = new StringBuilder();
-    while (vFile != null && !param.equalsIgnoreCase(vFile.getName())) {
-      result.insert(0, vFile.getName() + "/");
-      vFile = vFile.getParent();
+    VirtualFile dir = getVirtualDirOrParent(dataContext);
+    if (dir == null) {
+      return "";
+    }
+    String dirPath = dir.getPath();
+    String surroundedSubDir = surroundWithSlashes(FileUtil.toSystemIndependentName(args[0]));
+    String surroundedDirPath = surroundWithSlashes(dirPath);
+    if (surroundedSubDir.length() == 1) {
+      return surroundedDirPath.substring(1);
+    }
+    int ind = lastIndexOf(surroundedDirPath,
+                          surroundedSubDir,
+                          surroundedDirPath.length(),
+                          !SystemInfo.isFileSystemCaseSensitive);
+    if (ind >= 0) {
+      return surroundedDirPath.substring(ind + surroundedSubDir.length());
+    }
+    return dirPath;
+  }
+
+  private static int lastIndexOf(@NotNull CharSequence buffer, @NotNull String pattern, int maxIndex, boolean ignoreCase) {
+    int patternLength = pattern.length();
+    int end = buffer.length() - patternLength;
+    if (maxIndex > end) {
+      maxIndex = end;
+    }
+    for (int i = maxIndex; i >= 0; i--) {
+      boolean found = true;
+      for (int j = 0; j < patternLength; j++) {
+        if (ignoreCase) {
+          if (StringUtil.charsEqualIgnoreCase(pattern.charAt(j), buffer.charAt(i + j))) {
+            found = false;
+            break;
+          }
+        }
+        else {
+          if (pattern.charAt(j) != buffer.charAt(i + j)) {
+            found = false;
+            break;
+          }
+        }
+      }
+      if (found) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  @NotNull
+  private static String surroundWithSlashes(@NotNull String path) {
+    if (path.isEmpty()) {
+      return PATH_DELIMITER;
+    }
+    boolean prepend = !path.startsWith(PATH_DELIMITER);
+    boolean append = !path.endsWith(PATH_DELIMITER);
+    if (prepend && append) {
+      return PATH_DELIMITER + path + PATH_DELIMITER;
+    }
+    if (prepend) {
+      path = PATH_DELIMITER + path;
+    }
+    if (append) {
+      path += PATH_DELIMITER;
     }
-    return result.toString();
+    return path;
   }
 }